Revision control

Copy as Markdown

Other Tools

/*
* Off-the-Record Messaging Toolkit
* Copyright (C) 2004-2012 Ian Goldberg, Rob Smits, Chris Alexander,
* Nikita Borisov
* <otr@cypherpunks.ca>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* system headers */
#include <stdio.h>
#include <stdlib.h>
/* libotr headers */
#include "proto.h"
/* toolkit headers */
#include "readotr.h"
#include "parse.h"
static void parse(const char *msg)
{
OtrlMessageType mtype = otrl_proto_message_type(msg);
CommitMsg cmsg;
KeyMsg kmsg;
RevealSigMsg rmsg;
SignatureMsg smsg;
KeyExchMsg keyexch;
DataMsg datamsg;
switch(mtype) {
case OTRL_MSGTYPE_QUERY:
printf("OTR Query:\n\t%s\n\n", msg);
break;
case OTRL_MSGTYPE_DH_COMMIT:
cmsg = parse_commit(msg);
if (!cmsg) {
printf("Invalid D-H Commit Message\n\n");
break;
}
printf("D-H Commit Message:\n");
dump_data(stdout, "\tVersion", &(cmsg->version), 1);
if (cmsg->version == 3) {
dump_int(stdout, "\tSender instance", cmsg->sender_instance);
dump_int(stdout, "\tReceiver instance",
cmsg->receiver_instance);
}
dump_data(stdout, "\tEncrypted Key", cmsg->enckey,
cmsg->enckeylen);
dump_data(stdout, "\tHashed Key", cmsg->hashkey,
cmsg->hashkeylen);
printf("\n");
free_commit(cmsg);
break;
case OTRL_MSGTYPE_DH_KEY:
kmsg = parse_key(msg);
if (!kmsg) {
printf("Invalid D-H Key Message\n\n");
break;
}
printf("D-H Key Message:\n");
dump_data(stdout, "\tVersion", &(kmsg->version), 1);
if (kmsg->version == 3) {
dump_int(stdout, "\tSender instance", kmsg->sender_instance);
dump_int(stdout, "\tReceiver instance",
kmsg->receiver_instance);
}
dump_mpi(stdout, "\tD-H Key", kmsg->y);
printf("\n");
free_key(kmsg);
break;
case OTRL_MSGTYPE_REVEALSIG:
rmsg = parse_revealsig(msg);
if (!rmsg) {
printf("Invalid Reveal Signature Message\n\n");
break;
}
printf("Reveal Signature Message:\n");
dump_data(stdout, "\tVersion", &(rmsg->version), 1);
if (rmsg->version == 3) {
dump_int(stdout, "\tSender instance", rmsg->sender_instance);
dump_int(stdout, "\tReceiver instance",
rmsg->receiver_instance);
}
dump_data(stdout, "\tKey", rmsg->key, rmsg->keylen);
dump_data(stdout, "\tEncrypted Signature",
rmsg->encsig, rmsg->encsiglen);
dump_data(stdout, "\tMAC", rmsg->mac, 20);
printf("\n");
free_revealsig(rmsg);
break;
case OTRL_MSGTYPE_SIGNATURE:
smsg = parse_signature(msg);
if (!smsg) {
printf("Invalid Signature Message\n\n");
break;
}
printf("Signature Message:\n");
dump_data(stdout, "\tVersion", &(smsg->version), 1);
if (smsg->version == 3) {
dump_int(stdout, "\tSender instance", smsg->sender_instance);
dump_int(stdout, "\tReceiver instance",
smsg->receiver_instance);
}
dump_data(stdout, "\tEncrypted Signature",
smsg->encsig, smsg->encsiglen);
dump_data(stdout, "\tMAC", smsg->mac, 20);
printf("\n");
free_signature(smsg);
break;
case OTRL_MSGTYPE_V1_KEYEXCH:
keyexch = parse_keyexch(msg);
if (!keyexch) {
printf("Invalid Key Exchange Message\n\n");
break;
}
printf("Key Exchange Message:\n");
dump_int(stdout, "\tReply", keyexch->reply);
dump_mpi(stdout, "\tDSA p", keyexch->p);
dump_mpi(stdout, "\tDSA q", keyexch->q);
dump_mpi(stdout, "\tDSA g", keyexch->g);
dump_mpi(stdout, "\tDSA e", keyexch->e);
dump_int(stdout, "\tKeyID", keyexch->keyid);
dump_mpi(stdout, "\tDH y", keyexch->y);
dump_mpi(stdout, "\tSIG r", keyexch->r);
dump_mpi(stdout, "\tSIG s", keyexch->s);
printf("\n");
free_keyexch(keyexch);
break;
case OTRL_MSGTYPE_DATA:
datamsg = parse_datamsg(msg);
if (!datamsg) {
printf("Invalid Data Message\n\n");
break;
}
printf("Data Message:\n");
dump_data(stdout, "\tVersion", &(datamsg->version), 1);
if (datamsg->flags >= 0) {
dump_int(stdout, "\tFlags", datamsg->flags);
}
if (datamsg->version == 3) {
dump_int(stdout, "\tSender instance", datamsg->sender_instance);
dump_int(stdout, "\tReceiver instance",
datamsg->receiver_instance);
}
dump_int(stdout, "\tSender keyid", datamsg->sender_keyid);
dump_int(stdout, "\tRcpt keyid", datamsg->rcpt_keyid);
dump_mpi(stdout, "\tDH y", datamsg->y);
dump_data(stdout, "\tCounter", datamsg->ctr, 8);
dump_data(stdout, "\tEncrypted message", datamsg->encmsg,
datamsg->encmsglen);
dump_data(stdout, "\tMAC", datamsg->mac, 20);
if (datamsg->mackeyslen > 0) {
size_t len = datamsg->mackeyslen;
unsigned char *mks = datamsg->mackeys;
unsigned int i = 0;
printf("\tRevealed MAC keys:\n");
while(len > 19) {
char title[20];
sprintf(title, "\t\tKey %u", ++i);
dump_data(stdout, title, mks, 20);
mks += 20; len -= 20;
}
}
printf("\n");
free_datamsg(datamsg);
break;
case OTRL_MSGTYPE_ERROR:
printf("OTR Error:\n\t%s\n\n", msg);
break;
case OTRL_MSGTYPE_TAGGEDPLAINTEXT:
printf("Tagged plaintext message:\n\t%s\n\n", msg);
break;
case OTRL_MSGTYPE_NOTOTR:
printf("Not an OTR message:\n\t%s\n\n", msg);
break;
case OTRL_MSGTYPE_UNKNOWN:
printf("Unrecognized OTR message:\n\t%s\n\n", msg);
break;
}
fflush(stdout);
}
static void usage(const char *progname)
{
fprintf(stderr, "Usage: %s\n"
"Read Off-the-Record (OTR) Key Exchange and/or Data messages from stdin\n"
"and display their contents in a more readable format.\n", progname);
exit(1);
}
int main(int argc, char **argv)
{
char *otrmsg = NULL;
if (argc != 1) {
usage(argv[0]);
}
while ((otrmsg = readotr(stdin)) != NULL) {
parse(otrmsg);
free(otrmsg);
}
return 0;
}