#include #include #include #include "proto.h" #include "privkey.h" #include "message.h" #define ALICE "alice" #define BOB "bob" #define PROTO "prpl-oscar" static OtrlPolicy ALICEPOLICY = OTRL_POLICY_DEFAULT &~ OTRL_POLICY_ALLOW_V1; static OtrlPolicy BOBPOLICY = OTRL_POLICY_DEFAULT; void receiving(const char *from, const char *to, const char *msg); typedef struct s_node { struct s_node *next; char *from, *to, *msg; } MsgNode; static MsgNode *noderoot = NULL; static MsgNode **nodeend = &noderoot; void otrl_sm_init(void) {} void otrl_sm_state_new(OtrlSMState *smst) {} void otrl_sm_state_init(OtrlSMState *smst) {} void otrl_sm_state_free(OtrlSMState *smst) {} gcry_error_t otrl_sm_step1(OtrlSMAliceState *astate, const unsigned char* secret, int secretlen, unsigned char** output, int* outputlen) {return gcry_error(GPG_ERR_NO_ERROR);} gcry_error_t otrl_sm_step2a(OtrlSMBobState *bstate, const unsigned char* input, const int inputlen, int received_question) {return gcry_error(GPG_ERR_NO_ERROR);} gcry_error_t otrl_sm_step2b(OtrlSMBobState *bstate, const unsigned char* secret, int secretlen, unsigned char **output, int* outputlen) {return gcry_error(GPG_ERR_NO_ERROR);} gcry_error_t otrl_sm_step3(OtrlSMAliceState *astate, const unsigned char* input, const int inputlen, unsigned char **output, int* outputlen) {return gcry_error(GPG_ERR_NO_ERROR);} gcry_error_t otrl_sm_step4(OtrlSMBobState *bstate, const unsigned char* input, const int inputlen, unsigned char **output, int* outputlen) {return gcry_error(GPG_ERR_NO_ERROR);} gcry_error_t otrl_sm_step5(OtrlSMAliceState *astate, const unsigned char* input, const int inputlen) {return gcry_error(GPG_ERR_NO_ERROR);} static void dispatch(void) { while(noderoot) { MsgNode *node = noderoot; receiving(node->from, node->to, node->msg); free(node->from); free(node->to); free(node->msg); noderoot = node->next; free(node); if (noderoot == NULL) nodeend = &noderoot; } } static void inject(const char *from, const char *to, const char *msg) { MsgNode *node = malloc(sizeof(*node)); node->from = strdup(from); node->to = strdup(to); node->msg = strdup(msg); node->next = NULL; *nodeend = node; nodeend = &(node->next); printf("[%s->%s: %s]\n\n", from, to, msg); } static OtrlPolicy op_policy(void *opdata, ConnContext *context) { if (!strcmp(context->accountname, ALICE)) return ALICEPOLICY; if (!strcmp(context->accountname, BOB)) return BOBPOLICY; return OTRL_POLICY_DEFAULT; } static void op_inject(void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message) { inject(accountname, recipient, message); } static void op_notify(void *opdata, OtrlNotifyLevel level, const char *accountname, const char *protocol, const char *username, const char *title, const char *primary, const char *secondary) { } static int op_display_otr_message(void *opdata, const char *accountname, const char *protocol, const char *username, const char *msg) { return -1; } static void op_gone_secure(void *opdata, ConnContext *context) { printf("SECURE (%d): %s / %s\n\n", context->protocol_version, context->accountname, context->username); } static void op_gone_insecure(void *opdata, ConnContext *context) { printf("INSECURE: %s / %s\n\n", context->accountname, context->username); } static void op_still_secure(void *opdata, ConnContext *context, int is_reply) { printf("REFRESH (%d/%d): %s / %s\n\n", is_reply, context->protocol_version, context->accountname, context->username); } static OtrlMessageAppOps ops = { op_policy, NULL, NULL, op_inject, op_notify, op_display_otr_message, NULL, NULL, NULL, NULL, NULL, op_gone_secure, op_gone_insecure, op_still_secure, NULL }; static OtrlUserState us; void receiving(const char *from, const char *to, const char *msg) { int ignore; char *newmsg; OtrlTLV *tlvs; ignore = otrl_message_receiving(us, &ops, NULL, to, PROTO, from, msg, &newmsg, &tlvs, NULL, NULL); if (!ignore) { printf("%s> %s\n\n", from, newmsg ? newmsg : msg); } otrl_message_free(newmsg); otrl_tlv_free(tlvs); } static void sending(const char *from, const char *to, const char *msg) { gcry_error_t err; OtrlTLV *tlvs = NULL; char *newmsg; err = otrl_message_sending(us, &ops, NULL, from, PROTO, to, msg, tlvs, &newmsg, NULL, NULL, NULL); if (!err) { inject(from, to, newmsg ? newmsg : msg); } otrl_message_free(newmsg); otrl_tlv_free(tlvs); } static void test(int vers, int both) { printf("\n\n*** Testing version %d, %s ***\n\n", vers, both ? "simultaneous start" : "Alice start"); otrl_context_forget_all(us); if (vers == 1) ALICEPOLICY = OTRL_POLICY_ALLOW_V1; else if (vers == 2) ALICEPOLICY = OTRL_POLICY_ALLOW_V2; else ALICEPOLICY = OTRL_POLICY_DEFAULT; sending(ALICE, BOB, "?OTR?"); if (both) { sending(BOB, ALICE, "?OTR?"); } dispatch(); sending(ALICE, BOB, "Hi there"); dispatch(); } void test_unreadable(void) { ConnContext *bobcontext; printf("\n\n*** Testing Bob receiving unreadable messages from " "Alice ***\n\n"); bobcontext = otrl_context_find(us, ALICE, BOB, PROTO, 0, 0, NULL, NULL, NULL); otrl_context_force_plaintext(bobcontext); sending(ALICE, BOB, "unreadable text"); dispatch(); } void test_crash1(void) { ConnContext *alicecontext, *bobcontext; printf("\n\n*** Testing old double gcry_cipher_release case ***\n\n"); otrl_context_forget_all(us); ALICEPOLICY = OTRL_POLICY_DEFAULT; sending(ALICE, BOB, "?OTR?"); dispatch(); alicecontext = otrl_context_find(us, BOB, ALICE, PROTO, 0, 0, NULL, NULL, NULL); bobcontext = otrl_context_find(us, ALICE, BOB, PROTO, 0, 0, NULL, NULL, NULL); sending(ALICE, BOB, "Hi!"); dispatch(); sending(BOB, ALICE, "There!"); dispatch(); sending(ALICE, BOB, "You!"); dispatch(); otrl_context_force_plaintext(bobcontext); sending(BOB, ALICE, "?OTR?"); dispatch(); sending(ALICE, BOB, "now."); dispatch(); printf("%d %p %p\n", alicecontext->our_keyid, alicecontext->their_y, alicecontext->their_old_y); printf("%p %p %p %p\n", alicecontext->sesskeys[0][0].sendenc, alicecontext->sesskeys[0][1].sendenc, alicecontext->sesskeys[1][0].sendenc, alicecontext->sesskeys[1][1].sendenc); sending(BOB, ALICE, "then."); dispatch(); } void test_refresh(int vers) { ConnContext *alicecontext, *bobcontext; printf("\n\n*** Testing refresh ***\n\n"); otrl_context_forget_all(us); if (vers == 1) ALICEPOLICY = OTRL_POLICY_ALLOW_V1; else if (vers == 2) ALICEPOLICY = OTRL_POLICY_ALLOW_V2; else ALICEPOLICY = OTRL_POLICY_DEFAULT; sending(ALICE, BOB, "?OTR?"); dispatch(); alicecontext = otrl_context_find(us, BOB, ALICE, PROTO, 0, 0, NULL, NULL, NULL); bobcontext = otrl_context_find(us, ALICE, BOB, PROTO, 0, 0, NULL, NULL, NULL); printf("%p %p\n", alicecontext, bobcontext); sending(ALICE, BOB, "Hi!"); dispatch(); sending(BOB, ALICE, "There!"); dispatch(); sending(ALICE, BOB, "You!"); dispatch(); sending(ALICE, BOB, "Guys!"); dispatch(); sending(BOB, ALICE, "?OTR?"); dispatch(); sending(ALICE, BOB, "Refreshed!"); dispatch(); sending(BOB, ALICE, "Also refreshed!"); dispatch(); } int main(int argc, char **argv) { OTRL_INIT; us = otrl_userstate_create(); otrl_privkey_read(us, "/home/iang/.gaim/otr.private_key"); otrl_instag_read(us, "inst.txt"); test(1,0); test(2,0); test(3,0); test(1,1); test(2,1); test_unreadable(); test_crash1(); test_refresh(3); test_refresh(2); test_refresh(1); otrl_userstate_free(us); return 0; }