Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • otr.c

    r858ea01 rfaa75c0e  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2008 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    88  OTR support (cf. http://www.cypherpunks.ca/otr/)
    99 
    10   2008, Sven Moritz Hallberg <pesco@khjk.org>
    11   (c) and funded by stonedcoder.org
     10  (c) 2008-2010 Sven Moritz Hallberg <pesco@khjk.org>
     11  (c) 2008 funded by stonedcoder.org
    1212   
    1313  files used to store OTR data:
     
    8787void cmd_otr_disconnect(irc_t *irc, char **args);
    8888void cmd_otr_smp(irc_t *irc, char **args);
     89void cmd_otr_smpq(irc_t *irc, char **args);
    8990void cmd_otr_trust(irc_t *irc, char **args);
    9091void cmd_otr_info(irc_t *irc, char **args);
     
    9697        { "disconnect",  1, &cmd_otr_disconnect, 0 },
    9798        { "smp",         2, &cmd_otr_smp,        0 },
     99        { "smpq",        3, &cmd_otr_smpq,       0 },
    98100        { "trust",       6, &cmd_otr_trust,      0 },
    99101        { "info",        0, &cmd_otr_info,       0 },
     
    154156/* handle SMP TLVs from a received message */
    155157void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs);
     158
     159/* combined handler for the 'otr smp' and 'otr smpq' commands */
     160void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question,
     161                const char *secret);
    156162
    157163/* update op/voice flag of given user according to encryption state and settings
     
    732738void cmd_otr_smp(irc_t *irc, char **args)
    733739{
    734         irc_user_t *u;
    735         ConnContext *ctx;
    736        
    737         u = irc_user_by_name(irc, args[1]);
    738         if(!u || !u->bu || !u->bu->ic) {
    739                 irc_usermsg(irc, "%s: unknown user", args[1]);
    740                 return;
    741         }
    742         if(!(u->bu->flags & BEE_USER_ONLINE)) {
    743                 irc_usermsg(irc, "%s is offline", args[1]);
    744                 return;
    745         }
    746        
    747         ctx = otrl_context_find(irc->otr->us, u->bu->handle,
    748                 u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, 1, NULL, NULL, NULL);
    749         if(!ctx) {
    750                 /* huh? out of memory or what? */
    751                 return;
    752         }
    753 
    754         if(ctx->smstate->nextExpected != OTRL_SMP_EXPECT1) {
    755                 log_message(LOGLVL_INFO,
    756                         "SMP already in phase %d, sending abort before reinitiating",
    757                         ctx->smstate->nextExpected+1);
    758                 otrl_message_abort_smp(irc->otr->us, &otr_ops, u->bu->ic, ctx);
    759                 otrl_sm_state_free(ctx->smstate);
    760         }
    761        
    762         /* warning: the following assumes that smstates are cleared whenever an SMP
    763            is completed or aborted! */
    764         if(ctx->smstate->secret == NULL) {
    765                 irc_usermsg(irc, "smp: initiating with %s...", u->nick);
    766                 otrl_message_initiate_smp(irc->otr->us, &otr_ops,
    767                         u->bu->ic, ctx, (unsigned char *)args[2], strlen(args[2]));
    768                 /* smp is now in EXPECT2 */
    769         } else {
    770                 /* if we're still in EXPECT1 but smstate is initialized, we must have
    771                    received the SMP1, so let's issue a response */
    772                 irc_usermsg(irc, "smp: responding to %s...", u->nick);
    773                 otrl_message_respond_smp(irc->otr->us, &otr_ops,
    774                         u->bu->ic, ctx, (unsigned char *)args[2], strlen(args[2]));
    775                 /* smp is now in EXPECT3 */
    776         }
     740        otr_smp_or_smpq(irc, args[1], NULL, args[2]);   /* no question */
     741}
     742
     743void cmd_otr_smpq(irc_t *irc, char **args)
     744{
     745        otr_smp_or_smpq(irc, args[1], args[2], args[3]);
    777746}
    778747
     
    10981067        if(!context) {
    10991068                /* huh? out of memory or what? */
     1069                irc_usermsg(irc, "smp: failed to get otr context for %s", u->nick);
     1070                otrl_message_abort_smp(us, ops, u->bu->ic, context);
     1071                otrl_sm_state_free(context->smstate);
    11001072                return;
    11011073        }
    11021074        nextMsg = context->smstate->nextExpected;
    11031075
     1076        if (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) {
     1077                irc_usermsg(irc, "smp %s: opponent violated protocol, aborting",
     1078                        u->nick);
     1079                otrl_message_abort_smp(us, ops, u->bu->ic, context);
     1080                otrl_sm_state_free(context->smstate);
     1081                return;
     1082        }
     1083
     1084        tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q);
     1085        if (tlv) {
     1086                if (nextMsg != OTRL_SMP_EXPECT1) {
     1087                        irc_usermsg(irc, "smp %s: spurious SMP1Q received, aborting", u->nick);
     1088                        otrl_message_abort_smp(us, ops, u->bu->ic, context);
     1089                        otrl_sm_state_free(context->smstate);
     1090                } else {
     1091                        char *question = g_strndup((char *)tlv->data, tlv->len);
     1092                        irc_usermsg(irc, "smp: initiated by %s with question: \x02\"%s\"\x02", u->nick,
     1093                                question);
     1094                        irc_usermsg(irc, "smp: respond with \x02otr smp %s <answer>\x02",
     1095                                u->nick);
     1096                        g_free(question);
     1097                        /* smp stays in EXPECT1 until user responds */
     1098                }
     1099        }
    11041100        tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1);
    11051101        if (tlv) {
     
    11341130                } else {
    11351131                        /* SMP3 received, otrl_message_receiving will have sent SMP4 and set fp trust */
    1136                         const char *trust = context->active_fingerprint->trust;
    1137                         if(!trust || trust[0]=='\0') {
    1138                                 irc_usermsg(irc, "smp %s: secrets did not match, fingerprint not trusted",
     1132                        /* as noted above, fp trust SHOULD have been set by libotr.
     1133                         * however at least version 3.2.0 seems to forget it when
     1134                         * responding to an smp session that was initiated with SMP1Q
     1135                         * (question and answer); other cases appear to work fine.
     1136                         * as a workaround, we explicitly set it below.
     1137                         */
     1138                        if(context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED) {
     1139                                otrl_context_set_trust(context->active_fingerprint, "smp");
     1140                                irc_usermsg(irc, "smp %s: secrets proved equal, fingerprint trusted",
    11391141                                        u->nick);
    11401142                        } else {
    1141                                 irc_usermsg(irc, "smp %s: secrets proved equal, fingerprint trusted",
     1143                                otrl_context_set_trust(context->active_fingerprint, "");
     1144                                irc_usermsg(irc, "smp %s: secrets did not match, fingerprint not trusted",
    11421145                                        u->nick);
    11431146                        }
     
    11541157                } else {
    11551158                        /* SMP4 received, otrl_message_receiving will have set fp trust */
    1156                         const char *trust = context->active_fingerprint->trust;
    1157                         if(!trust || trust[0]=='\0') {
    1158                                 irc_usermsg(irc, "smp %s: secrets did not match, fingerprint not trusted",
     1159                        if(context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED) {
     1160                                irc_usermsg(irc, "smp %s: secrets proved equal, fingerprint trusted",
    11591161                                        u->nick);
    11601162                        } else {
    1161                                 irc_usermsg(irc, "smp %s: secrets proved equal, fingerprint trusted",
     1163                                irc_usermsg(irc, "smp %s: secrets did not match, fingerprint not trusted",
    11621164                                        u->nick);
    11631165                        }
     
    11711173                otrl_sm_state_free(context->smstate);
    11721174                /* smp is in back in EXPECT1 */
     1175        }
     1176}
     1177
     1178/* combined handler for the 'otr smp' and 'otr smpq' commands */
     1179void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question,
     1180                const char *secret)
     1181{
     1182        irc_user_t *u;
     1183        ConnContext *ctx;
     1184
     1185        u = irc_user_by_name(irc, nick);
     1186        if(!u || !u->bu || !u->bu->ic) {
     1187                irc_usermsg(irc, "%s: unknown user", nick);
     1188                return;
     1189        }
     1190        if(!(u->bu->flags & BEE_USER_ONLINE)) {
     1191                irc_usermsg(irc, "%s is offline", nick);
     1192                return;
     1193        }
     1194       
     1195        ctx = otrl_context_find(irc->otr->us, u->bu->handle,
     1196                u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, 0, NULL, NULL, NULL);
     1197        if(!ctx || ctx->msgstate != OTRL_MSGSTATE_ENCRYPTED) {
     1198                irc_usermsg(irc, "smp: otr inactive with %s, try \x02otr connect"
     1199                                " %s\x02", nick, nick);
     1200                return;
     1201        }
     1202
     1203        if(ctx->smstate->nextExpected != OTRL_SMP_EXPECT1) {
     1204                log_message(LOGLVL_INFO,
     1205                        "SMP already in phase %d, sending abort before reinitiating",
     1206                        ctx->smstate->nextExpected+1);
     1207                otrl_message_abort_smp(irc->otr->us, &otr_ops, u->bu->ic, ctx);
     1208                otrl_sm_state_free(ctx->smstate);
     1209        }
     1210
     1211        if(question) {
     1212                /* this was 'otr smpq', just initiate */
     1213                irc_usermsg(irc, "smp: initiating with %s...", u->nick);
     1214                otrl_message_initiate_smp_q(irc->otr->us, &otr_ops, u->bu->ic, ctx,
     1215                        question, (unsigned char *)secret, strlen(secret));
     1216                /* smp is now in EXPECT2 */
     1217        } else {
     1218                /* this was 'otr smp', initiate or reply */
     1219                /* warning: the following assumes that smstates are cleared whenever an SMP
     1220                   is completed or aborted! */
     1221                if(ctx->smstate->secret == NULL) {
     1222                        irc_usermsg(irc, "smp: initiating with %s...", u->nick);
     1223                        otrl_message_initiate_smp(irc->otr->us, &otr_ops,
     1224                                u->bu->ic, ctx, (unsigned char *)secret, strlen(secret));
     1225                        /* smp is now in EXPECT2 */
     1226                } else {
     1227                        /* if we're still in EXPECT1 but smstate is initialized, we must have
     1228                           received the SMP1, so let's issue a response */
     1229                        irc_usermsg(irc, "smp: responding to %s...", u->nick);
     1230                        otrl_message_respond_smp(irc->otr->us, &otr_ops,
     1231                                u->bu->ic, ctx, (unsigned char *)secret, strlen(secret));
     1232                        /* smp is now in EXPECT3 */
     1233                }
    11731234        }
    11741235}
Note: See TracChangeset for help on using the changeset viewer.