Changeset 5a71d9c for otr.c


Ignore:
Timestamp:
2008-02-09T17:58:13Z (16 years ago)
Author:
Sven Moritz Hallberg <sm@…>
Branches:
master
Children:
f55cfe9
Parents:
a13855a
Message:
  • add support for setting ops/voice according to OTR msgstate
  • add 'otr trust' user command
  • support non-otr messages during keygen
  • run otr messages through strip_html
  • interpret <b> and <i> tags in html messages
  • record max message size in prpl
  • add 'encrypted' flag to user_t
  • cosmetics
File:
1 edited

Legend:

Unmodified
Added
Removed
  • otr.c

    ra13855a r5a71d9c  
    3535void op_gone_secure(void *opdata, ConnContext *context);
    3636
    37 void op_gone_secure(void *opdata, ConnContext *context);
    38 
    3937void op_gone_insecure(void *opdata, ConnContext *context);
    4038
     
    5351void cmd_otr_abort(irc_t *irc, char **args); /* TODO: does this cmd even make sense? */
    5452void cmd_otr_request(irc_t *irc, char **args); /* TODO: do we even need this? */
    55 void cmd_otr_auth(irc_t *irc, char **args);
     53void cmd_otr_smp(irc_t *irc, char **args);
     54void cmd_otr_trust(irc_t *irc, char **args);
    5655/* TODO: void cmd_otr_affirm(irc_t *irc, char **args); */
    5756void cmd_otr_fprints(irc_t *irc, char **args);
     
    6261        { "abort",    1, &cmd_otr_abort,    0 },
    6362        { "request",  1, &cmd_otr_request,  0 },
    64         { "auth",     2, &cmd_otr_auth,     0 },
     63        { "smp",      2, &cmd_otr_smp,      0 },
     64        { "trust",    6, &cmd_otr_trust,    0 },
    6565        { "fprints",  0, &cmd_otr_fprints,  0 },
    6666        { "info",     1, &cmd_otr_info,     0 },
     
    9797        const char *protocol);
    9898
    99 /* determine the nick for a given handle/protocol pair */
     99/* determine the nick for a given handle/protocol pair
     100   returns "handle/protocol" if not found */
    100101const char *peernick(irc_t *irc, const char *handle, const char *protocol);
     102
     103/* determine the user_t for a given handle/protocol pair
     104   returns NULL if not found */
     105user_t *peeruser(irc_t *irc, const char *handle, const char *protocol);
    101106
    102107/* handle SMP TLVs from a received message */
    103108void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs);
     109
     110/* update op/voice flag of given user according to encryption state and settings
     111   returns 0 if neither op_buddies nor voice_buddies is set to "encrypted",
     112   i.e. msgstate should be announced seperately */
     113int otr_update_modeflags(irc_t *irc, user_t *u);
    104114
    105115/* show the list of fingerprints associated with a given context */
     
    239249       
    240250    if(!g_mutex_trylock(ic->irc->otr_mutex)) {
    241         /* TODO: queue msgs received during keygen for later */
    242                 irc_usermsg(ic->irc, "msg from %s during keygen - dropped",
     251        user_t *u = user_findhandle(ic, handle);
     252       
     253        /* fallback for non-otr clients */
     254        if(u && !u->encrypted) {
     255                return g_strdup(msg);
     256        }
     257       
     258        /* TODO: queue msgs received during keygen for later? */
     259                irc_usermsg(ic->irc, "otr msg from %s during keygen - dropped",
    243260                        peernick(ic->irc, handle, ic->acc->prpl->name));
    244261                return NULL;
     
    283300int otr_send_message(struct im_connection *ic, const char *handle, const char *msg, int flags)
    284301{       
    285     int st;
    286     char *otrmsg = NULL;
    287     ConnContext *ctx = NULL;
    288    
     302        int st;
     303        char *otrmsg = NULL;
     304        ConnContext *ctx = NULL;
     305       
    289306    if(!g_mutex_trylock(ic->irc->otr_mutex)) {
    290         irc_usermsg(ic->irc, "msg to %s during keygen - not sent",
    291                 peernick(ic->irc, handle, ic->acc->prpl->name));
    292         return 1;
     307                user_t *u = user_findhandle(ic, handle);
     308       
     309                /* Fallback for non-otr clients.
     310                   Yes, we must be very sure this doesn't send stuff in the clear where it
     311                   shouldn't... */
     312                if(u && !u->encrypted) {
     313                        return ic->acc->prpl->buddy_msg(ic, (char *)handle, (char *)msg, flags);
     314                }
     315               
     316                /* otherwise refuse to send */
     317                irc_usermsg(ic->irc, "otr msg to %s not sent during keygen",
     318                        peernick(ic->irc, handle, ic->acc->prpl->name));
     319                return 1;
    293320    }
    294321   
     
    414441
    415442int op_display_otr_message(void *opdata, const char *accountname,
    416         const char *protocol, const char *username, const char *msg)
     443        const char *protocol, const char *username, const char *message)
    417444{
    418445        struct im_connection *ic = check_imc(opdata, accountname, protocol);
    419 
    420         log_message(LOGLVL_DEBUG, "op_display_otr_message '%s' '%s' '%s' '%s'", accountname, protocol, username, msg);
    421 
    422         irc_usermsg(ic->irc, "%s", msg);
    423 
     446        char *msg = g_strdup(message);
     447
     448        log_message(LOGLVL_DEBUG, "op_display_otr_message '%s' '%s' '%s' '%s'", accountname, protocol, username, message);
     449
     450        strip_html(msg);
     451        irc_usermsg(ic->irc, "otr: %s", msg);
     452
     453        g_free(msg);
    424454        return 0;
    425455}
     
    452482        struct im_connection *ic =
    453483                check_imc(opdata, context->accountname, context->protocol);
     484        user_t *u;
    454485
    455486        log_message(LOGLVL_DEBUG, "op_gone_secure '%s' '%s' '%s'", context->accountname, context->protocol, context->username);
    456487
    457         irc_usermsg(ic->irc, "conversation with %s is now off the record",
    458                 peernick(ic->irc, context->username, context->protocol));
     488        u = peeruser(ic->irc, context->username, context->protocol);
     489        if(!u) {
     490                log_message(LOGLVL_ERROR,
     491                        "BUG: otr.c: op_gone_secure: user_t for %s/%s not found!",
     492                        context->username, context->protocol);
     493                return;
     494        }
     495        if(context->active_fingerprint->trust[0])
     496                u->encrypted = 2;
     497        else
     498                u->encrypted = 1;
     499        if(!otr_update_modeflags(ic->irc, u))
     500                irc_usermsg(ic->irc, "conversation with %s is now off the record", u->nick);
    459501}
    460502
     
    463505        struct im_connection *ic =
    464506                check_imc(opdata, context->accountname, context->protocol);
     507        user_t *u;
    465508
    466509        log_message(LOGLVL_DEBUG, "op_gone_insecure '%s' '%s' '%s'", context->accountname, context->protocol, context->username);
    467510
    468         irc_usermsg(ic->irc, "conversation with %s is now in the clear",
    469                 peernick(ic->irc, context->username, context->protocol));
     511        u = peeruser(ic->irc, context->username, context->protocol);
     512        if(!u) {
     513                log_message(LOGLVL_ERROR,
     514                        "BUG: otr.c: op_gone_insecure: user_t for %s/%s not found!",
     515                        context->username, context->protocol);
     516                return;
     517        }
     518        u->encrypted = 0;
     519        if(!otr_update_modeflags(ic->irc, u))
     520                irc_usermsg(ic->irc, "conversation with %s is now in the clear", u->nick);
    470521}
    471522
     
    474525        struct im_connection *ic =
    475526                check_imc(opdata, context->accountname, context->protocol);
     527        user_t *u;
    476528
    477529        log_message(LOGLVL_DEBUG, "op_still_secure '%s' '%s' '%s' is_reply=%d",
    478530                context->accountname, context->protocol, context->username, is_reply);
    479531
    480         irc_usermsg(ic->irc, "otr connection with %s has been refreshed",
    481                 peernick(ic->irc, context->username, context->protocol));
     532        u = peeruser(ic->irc, context->username, context->protocol);
     533        if(!u) {
     534                log_message(LOGLVL_ERROR,
     535                        "BUG: otr.c: op_still_secure: user_t for %s/%s not found!",
     536                        context->username, context->protocol);
     537                return;
     538        }
     539        if(context->active_fingerprint->trust[0])
     540                u->encrypted = 2;
     541        else
     542                u->encrypted = 1;
     543        if(!otr_update_modeflags(ic->irc, u))
     544                irc_usermsg(ic->irc, "otr connection with %s has been refreshed", u->nick);
    482545}
    483546
    484547void op_log_message(void *opdata, const char *message)
    485548{
    486         log_message(LOGLVL_INFO, "%s", message);
     549        char *msg = g_strdup(message);
     550       
     551        strip_html(msg);
     552        log_message(LOGLVL_INFO, "otr: %s", msg);
     553        g_free(msg);
    487554}
    488555
    489556int op_max_message_size(void *opdata, ConnContext *context)
    490557{
    491         /* TODO: make max_message_size a property of the prpl.
    492                  the values here are taken from the libotr UPGRADING file */
    493         if(!strcmp(context->protocol, "msn"))
    494                 return 1409;
    495         if(!strcmp(context->protocol, "yahoo"))
    496                 return 832;
    497         if(!strcmp(context->protocol, "oscar"))
    498                 return 2343;
     558        struct im_connection *ic =
     559                check_imc(opdata, context->accountname, context->protocol);
     560
     561        return ic->acc->prpl->mms;
    499562}
    500563
     
    542605}
    543606
    544 void cmd_otr_auth(irc_t *irc, char **args)
     607void cmd_otr_smp(irc_t *irc, char **args)
    545608{
    546609        user_t *u;
     
    589652}
    590653
     654int hexval(char a)
     655{
     656        int x=tolower(a);
     657       
     658        if(x>='a' && x<='f')
     659                x = x - 'a' + 10;
     660        else if(x>='0' && x<='9')
     661                x = x - '0';
     662        else
     663                return -1;
     664       
     665        return x;
     666}
     667
     668void cmd_otr_trust(irc_t *irc, char **args)
     669{
     670        user_t *u;
     671        ConnContext *ctx;
     672        unsigned char raw[20];
     673        Fingerprint *fp;
     674        int i,j;
     675       
     676        u = user_find(irc, args[1]);
     677        if(!u || !u->ic) {
     678                irc_usermsg(irc, "%s: unknown user", args[1]);
     679                return;
     680        }
     681       
     682        ctx = otrl_context_find(irc->otr_us, u->handle,
     683                u->ic->acc->user, u->ic->acc->prpl->name, 0, NULL, NULL, NULL);
     684        if(!ctx) {
     685                irc_usermsg(irc, "%s: no otr context with user", args[1]);
     686                return;
     687        }
     688       
     689        /* convert given fingerprint to raw representation */
     690        for(i=0; i<5; i++) {
     691                for(j=0; j<4; j++) {
     692                        char *p = args[2+i]+(2*j);
     693                        char *q = p+1;
     694                        int x, y;
     695                       
     696                        if(!*p || !*q) {
     697                                irc_usermsg(irc, "failed: truncated fingerprint block %d", i+1);
     698                                return;
     699                        }
     700                       
     701                        x = hexval(*p);
     702                        y = hexval(*q);
     703                        if(x<0) {
     704                                irc_usermsg(irc, "failed: %d. hex digit of block %d out of range", 2*j+1, i+1);
     705                                return;
     706                        }
     707                        if(y<0) {
     708                                irc_usermsg(irc, "failed: %d. hex digit of block %d out of range", 2*j+2, i+1);
     709                                return;
     710                        }
     711
     712                        raw[i*4+j] = x*16 + y;
     713                }
     714        }
     715        fp = otrl_context_find_fingerprint(ctx, raw, 0, NULL);
     716        if(!fp) {
     717                irc_usermsg(irc, "failed: no such fingerprint for %s", args[1]);
     718        } else {
     719                char *trust = args[7] ? args[7] : "affirmed";
     720                otrl_context_set_trust(fp, trust);
     721                irc_usermsg(irc, "fingerprint match, trust set to \"%s\"", trust);
     722                if(u->encrypted)
     723                        u->encrypted = 2;
     724                otr_update_modeflags(irc, u);
     725        }
     726}
     727
    591728void cmd_otr_fprints(irc_t *irc, char **args)
    592729{
     
    649786                u->ic->acc->user, u->ic->acc->prpl->name, 0, NULL, NULL, NULL);
    650787        if(!ctx) {
    651                 irc_usermsg(irc, "no otr info on %s", args[1]);
     788                irc_usermsg(irc, "no otr context with %s", args[1]);
    652789                return;
    653790        }
     
    672809        irc_usermsg(irc, "  otr offer status: %s", offer_status);
    673810        irc_usermsg(irc, "  connection state: %s", message_state);
    674         irc_usermsg(irc, "  protocol version: %d", ctx->protocol_version);
    675         fp = ctx->active_fingerprint;
    676         if(!fp) {
    677                 irc_usermsg(irc, "  active f'print:   none");
    678         } else {
    679                 otrl_privkey_hash_to_human(human, fp->fingerprint);
    680                 if(!fp->trust || fp->trust[0] == '\0') {
    681                         trust="untrusted";
     811       
     812        if(ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
     813                irc_usermsg(irc, "  protocol version: %d", ctx->protocol_version);
     814                fp = ctx->active_fingerprint;
     815                if(!fp) {
     816                        irc_usermsg(irc, "  active f'print:   none?");
    682817                } else {
    683                         trust=fp->trust;
    684                 }
    685                 irc_usermsg(irc, "  active f'print:   %s (%s)", human, trust);
     818                        otrl_privkey_hash_to_human(human, fp->fingerprint);
     819                        if(!fp->trust || fp->trust[0] == '\0') {
     820                                trust="untrusted";
     821                        } else {
     822                                trust=fp->trust;
     823                        }
     824                        irc_usermsg(irc, "  active f'print:   %s (%s)", human, trust);
     825                }
    686826        }
    687827}
     
    809949}
    810950
    811 const char *peernick(irc_t *irc, const char *handle, const char *protocol)
     951user_t *peeruser(irc_t *irc, const char *handle, const char *protocol)
    812952{
    813953        user_t *u;
    814         static char fallback[512];
    815        
    816         g_snprintf(fallback, 511, "%s/%s", handle, protocol);
     954       
    817955        for(u=irc->users; u; u=u->next) {
    818956                struct prpl *prpl;
     
    822960                if(strcmp(prpl->name, protocol) == 0
    823961                        && prpl->handle_cmp(u->handle, handle) == 0) {
    824                         return u->nick;
    825                 }
    826         }
    827        
    828         return fallback;
     962                        return u;
     963                }
     964        }
     965       
     966        return NULL;
     967}
     968
     969const char *peernick(irc_t *irc, const char *handle, const char *protocol)
     970{
     971        static char fallback[512];
     972       
     973        user_t *u = peeruser(irc, handle, protocol);
     974        if(u) {
     975                return u->nick;
     976        } else {
     977                g_snprintf(fallback, 511, "%s/%s", handle, protocol);
     978                return fallback;
     979        }
     980}
     981
     982int otr_update_modeflags(irc_t *irc, user_t *u)
     983{
     984        char *vo = set_getstr(&irc->set, "voice_buddies");
     985        char *oo = set_getstr(&irc->set, "op_buddies");
     986        char eflag=0, tflag=0;
     987        int e = u->encrypted;
     988        int t = (u->encrypted > 1);
     989       
     990        if(!strcmp(vo, "encrypted"))
     991                eflag='v';
     992        else if(!strcmp(oo, "encrypted"))
     993                eflag='o';
     994        if(!strcmp(vo, "trusted"))
     995                tflag='v';
     996        else if(!strcmp(oo, "trusted"))
     997                tflag='o';
     998       
     999        if(!eflag)
     1000                return 0;
     1001       
     1002        if(tflag) {
     1003                irc_write( irc, ":%s!%s@%s MODE %s %c%c%c%c %s %s", irc->mynick, irc->mynick, irc->myhost,
     1004                        irc->channel, e?'+':'-', eflag, t?'+':'-', tflag, u->nick, u->nick );
     1005        } else {
     1006                irc_write( irc, ":%s!%s@%s MODE %s %c%c %s", irc->mynick, irc->mynick, irc->myhost,
     1007                        irc->channel, e?'+':'-', eflag, u->nick );
     1008        }
     1009               
     1010        return 1;
    8291011}
    8301012
     
    9661148        account_t *acc = (account_t *)data;
    9671149       
    968         /* TODO: remember that we didn't want a key? */
    9691150        irc_usermsg(acc->irc, "proceeding without key, otr inoperable on %s/%s",
    9701151                acc->user, acc->prpl->name);
     1152        /* TODO:
     1153        irc_usermsg(acc->irc, "setting otr policy for %s/%s to \"never\"",
     1154                acc->user, acc->prpl->name);
     1155        set_setstr(acc->set, "otr_policy", "never");
     1156        */
    9711157}
    9721158
Note: See TracChangeset for help on using the changeset viewer.