Changeset c595308


Ignore:
Timestamp:
2008-02-11T21:20:35Z (16 years ago)
Author:
Sven Moritz Hallberg <sm@…>
Branches:
master
Children:
8bd697c
Parents:
d6fdf44
Message:
  • use a recursive otr_mutex
  • implement 'otr forget fingerprint' and 'otr forget context' commands
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • irc.c

    rd6fdf44 rc595308  
    131131
    132132        irc->otr_us = otrl_userstate_create();
    133         irc->otr_mutex = g_mutex_new();
     133        g_static_rec_mutex_init(&irc->otr_mutex);
    134134       
    135135        return( irc );
     
    284284       
    285285        otrl_userstate_free(irc->otr_us);
    286         g_mutex_free(irc->otr_mutex);
     286        g_static_rec_mutex_free(&irc->otr_mutex);
    287287       
    288288        g_free(irc);
  • irc.h

    rd6fdf44 rc595308  
    9999       
    100100        OtrlUserState otr_us;
    101         GMutex *otr_mutex;      /* for locking otr during keygen */
     101        GStaticRecMutex otr_mutex;      /* for locking otr during keygen */
    102102} irc_t;
    103103
  • otr.c

    rd6fdf44 rc595308  
    5454void cmd_otr_info(irc_t *irc, char **args);
    5555void cmd_otr_keygen(irc_t *irc, char **args);
    56 /* void cmd_otr_forget(irc_t *irc, char **args); */
     56void cmd_otr_forget(irc_t *irc, char **args);
    5757
    5858const command_t otr_commands[] = {
     
    6363        { "info",        0, &cmd_otr_info,       0 },
    6464        { "keygen",      1, &cmd_otr_keygen,     0 },
    65         /*
    66         { "forget",      1, &cmd_otr_forget,     0 },
    67         */
     65        { "forget",      2, &cmd_otr_forget,     0 },
    6866        { NULL }
    6967};
     
    7472/* start background thread to generate a (new) key for a given account */
    7573void otr_keygen(irc_t *irc, const char *handle, const char *protocol);
     74
    7675/* keygen thread main func */
    7776gpointer otr_keygen_thread_func(gpointer data);
     77
    7878/* mainloop handler for when keygen thread finishes */
    7979gboolean keygen_finish_handler(gpointer data, gint fd, b_input_condition cond);
     80
    8081/* data to be passed to otr_keygen_thread_func */
    8182struct kgdata {
     
    8990};
    9091
    91 /* yes/no handlers for "generate key now?" */
     92/* some yes/no handlers */
    9293void yes_keygen(gpointer w, void *data);
    93 void no_keygen(gpointer w, void *data);
     94void yes_forget_fingerprint(gpointer w, void *data);
     95void yes_forget_context(gpointer w, void *data);
    9496
    9597/* helper to make sure accountname and protocol match the incoming "opdata" */
     
    124126/* show the list of fingerprints associated with a given context */
    125127void show_fingerprints(irc_t *irc, ConnContext *ctx);
     128
     129/* find a fingerprint by prefix (given as any number of hex strings) */
     130Fingerprint *match_fingerprint(irc_t *irc, ConnContext *ctx, const char **args);
    126131
    127132/* to log out accounts during keygen */
     
    259264        char *colormsg;
    260265       
    261     if(!g_mutex_trylock(ic->irc->otr_mutex)) {
     266    if(!g_static_rec_mutex_trylock(&ic->irc->otr_mutex)) {
    262267                irc_usermsg(ic->irc, "otr keygen in progress - msg from %s dropped",
    263268                        peernick(ic->irc, handle, ic->acc->prpl->name));
     
    273278        if(ignore_msg) {
    274279                /* this was an internal OTR protocol message */
    275                 g_mutex_unlock(ic->irc->otr_mutex);
     280                g_static_rec_mutex_unlock(&ic->irc->otr_mutex);
    276281                return NULL;
    277282        } else if(!newmsg) {
    278283                /* this was a non-OTR message */
    279                 g_mutex_unlock(ic->irc->otr_mutex);
     284                g_static_rec_mutex_unlock(&ic->irc->otr_mutex);
    280285                return g_strdup(msg);
    281286        } else {
     
    296301                }
    297302                otrl_message_free(newmsg);
    298                 g_mutex_unlock(ic->irc->otr_mutex);
     303                g_static_rec_mutex_unlock(&ic->irc->otr_mutex);
    299304                return colormsg;
    300305        }
     
    307312        ConnContext *ctx = NULL;
    308313       
    309     if(!g_mutex_trylock(ic->irc->otr_mutex)) {
     314    if(!g_static_rec_mutex_trylock(&ic->irc->otr_mutex)) {
    310315                irc_usermsg(ic->irc, "otr keygen in progress - msg to %s not sent",
    311316                        peernick(ic->irc, handle, ic->acc->prpl->name));
     
    317322                msg, NULL, &otrmsg, NULL, NULL);
    318323        if(st) {
    319                 g_mutex_unlock(ic->irc->otr_mutex);
     324                g_static_rec_mutex_unlock(&ic->irc->otr_mutex);
    320325                return st;
    321326        }
     
    328333                if(!ctx) {
    329334                        otrl_message_free(otrmsg);
    330                         g_mutex_unlock(ic->irc->otr_mutex);
     335                        g_static_rec_mutex_unlock(&ic->irc->otr_mutex);
    331336                        return 1;
    332337                }
     
    339344        }
    340345       
    341         g_mutex_unlock(ic->irc->otr_mutex);
     346        g_static_rec_mutex_unlock(&ic->irc->otr_mutex);
    342347        return st;
    343348}
     
    359364       
    360365        if(!cmd->command) {
    361                 irc_usermsg(irc, "%s %s: unknown subcommand, see \x02help otr\x02",
     366                irc_usermsg(irc, "%s: unknown subcommand \"%s\", see \x02help otr\x02",
    362367                        args[0], args[1]);
    363368                return;
     
    392397        s = g_strdup_printf("oops, no otr privkey for %s/%s - generate one now?",
    393398                accountname, protocol);
    394         query_add(ic->irc, ic, s, yes_keygen, no_keygen, ic->acc);
     399        query_add(ic->irc, ic, s, yes_keygen, NULL, ic->acc);
    395400}
    396401
     
    476481                check_imc(opdata, context->accountname, context->protocol);
    477482        user_t *u;
     483        const char *trust;
    478484
    479485        log_message(LOGLVL_DEBUG, "op_gone_secure '%s' '%s' '%s'", context->accountname, context->protocol, context->username);
     
    486492                return;
    487493        }
    488         if(context->active_fingerprint->trust[0])
     494       
     495        trust = context->active_fingerprint->trust;
     496        if(trust && trust[0])
    489497                u->encrypted = 2;
    490498        else
     
    579587        otrl_message_disconnect(irc->otr_us, &global.otr_ops,
    580588                u->ic, u->ic->acc->user, u->ic->acc->prpl->name, u->handle);
     589       
     590        /* for some reason, libotr (3.1.0) doesn't do this itself: */
     591        if(u->encrypted) {
     592                ConnContext *ctx;
     593                ctx = otrl_context_find(irc->otr_us, u->handle, u->ic->acc->user,
     594                        u->ic->acc->prpl->name, 0, NULL, NULL, NULL);
     595                if(ctx)
     596                        op_gone_insecure(u->ic, ctx);
     597                else /* huh? */
     598                        u->encrypted = 0;
     599        }
    581600}
    582601
     
    719738                        *(protocol++) = '\0';
    720739                        myhandle = strchr(protocol, '/');
    721                         if(!myhandle) {
    722                                 /* TODO: try to find a unique account for this context */
    723                         }
    724740                }
    725741                if(protocol && myhandle) {
     
    728744                        ctx = otrl_context_find(irc->otr_us, handle, myhandle, protocol, 0, NULL, NULL, NULL);
    729745                        if(!ctx) {
    730                                 irc_usermsg(irc, "no such context (%s %s %s)", handle, protocol, myhandle);
     746                                irc_usermsg(irc, "no such context");
    731747                                g_free(arg);
    732748                                return;
     
    778794        if(otrl_privkey_find(irc->otr_us, a->user, a->prpl->name)) {
    779795                char *s = g_strdup_printf("account %d already has a key, replace it?", n);
    780                 query_add(irc, a->ic, s, yes_keygen, no_keygen, a);
     796                query_add(irc, a->ic, s, yes_keygen, NULL, a);
    781797        } else {
    782798                otr_keygen(irc, a->user, a->prpl->name);
     799        }
     800}
     801
     802void yes_forget_fingerprint(gpointer w, void *data)
     803{
     804        struct im_connection *ic = (struct im_connection *)w;
     805        Fingerprint *fp = (Fingerprint *)data;
     806       
     807        if(fp == fp->context->active_fingerprint) {
     808                irc_usermsg(ic->irc, "that fingerprint is active, terminate otr connection first");
     809                return;
     810        }
     811               
     812        otrl_context_forget_fingerprint(fp, 0);
     813}
     814
     815void yes_forget_context(gpointer w, void *data)
     816{
     817        struct im_connection *ic = (struct im_connection *)w;
     818        ConnContext *ctx = (ConnContext *)data;
     819       
     820        if(ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
     821                irc_usermsg(ic->irc, "active otr connection with %s, terminate it first",
     822                        peernick(ic->irc, ctx->username, ctx->protocol));
     823                return;
     824        }
     825               
     826        if(ctx->msgstate == OTRL_MSGSTATE_FINISHED)
     827                otrl_context_force_plaintext(ctx);
     828        otrl_context_forget(ctx);
     829}
     830
     831void cmd_otr_forget(irc_t *irc, char **args)
     832{
     833        if(!strcmp(args[1], "fingerprint"))
     834        {
     835                user_t *u;
     836                ConnContext *ctx;
     837                Fingerprint *fp;
     838                char human[54];
     839                char *s;
     840               
     841                if(!args[3]) {
     842                        irc_usermsg(irc, "otr %s %s: not enough arguments (2 req.)", args[0], args[1]);
     843                        return;
     844                }
     845               
     846                u = user_find(irc, args[2]);
     847                if(!u || !u->ic) {
     848                        irc_usermsg(irc, "%s: unknown user", args[2]);
     849                        return;
     850                }
     851               
     852                ctx = otrl_context_find(irc->otr_us, u->handle, u->ic->acc->user,
     853                        u->ic->acc->prpl->name, 0, NULL, NULL, NULL);
     854                if(!ctx) {
     855                        irc_usermsg(irc, "no otr context with %s", args[2]);
     856                        return;
     857                }
     858               
     859                fp = match_fingerprint(irc, ctx, ((const char **)args)+3);
     860                if(!fp) {
     861                        /* match_fingerprint does error messages */
     862                        return;
     863                }
     864               
     865                if(fp == ctx->active_fingerprint) {
     866                        irc_usermsg(irc, "that fingerprint is active, terminate otr connection first");
     867                        return;
     868                }
     869               
     870                otrl_privkey_hash_to_human(human, fp->fingerprint);
     871                s = g_strdup_printf("about to forget fingerprint %s, are you sure?", human);
     872                query_add(irc, u->ic, s, yes_forget_fingerprint, NULL, fp);
     873        }
     874       
     875        else if(!strcmp(args[1], "context"))
     876        {
     877                user_t *u;
     878                ConnContext *ctx;
     879                char *s;
     880               
     881                u = user_find(irc, args[2]);
     882                if(!u || !u->ic) {
     883                        irc_usermsg(irc, "%s: unknown user", args[2]);
     884                        return;
     885                }
     886               
     887                ctx = otrl_context_find(irc->otr_us, u->handle, u->ic->acc->user,
     888                        u->ic->acc->prpl->name, 0, NULL, NULL, NULL);
     889                if(!ctx) {
     890                        irc_usermsg(irc, "no otr context with %s", args[2]);
     891                        return;
     892                }
     893               
     894                if(ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
     895                        irc_usermsg(irc, "active otr connection with %s, terminate it first", args[2]);
     896                        return;
     897                }
     898               
     899                s = g_strdup_printf("about to forget otr data about %s, are you sure?", args[2]);
     900                query_add(irc, u->ic, s, yes_forget_context, NULL, ctx);
     901        }
     902       
     903        else if(!strcmp(args[1], "key"))
     904        {
     905                irc_usermsg(irc, "n/a: TODO");
     906        }
     907       
     908        else
     909        {
     910                irc_usermsg(irc, "otr %s: unknown subcommand \"%s\", see \x02help otr forget\x02",
     911                        args[0], args[1]);
    783912        }
    784913}
     
    9561085        int trusted = u->encrypted > 1;
    9571086        char flags[7];
    958         int nflags;
     1087        int nflags=0;
    9591088        char *p = flags;
    9601089        char *from;
     
    10361165}
    10371166
     1167Fingerprint *match_fingerprint(irc_t *irc, ConnContext *ctx, const char **args)
     1168{
     1169        Fingerprint *fp, *fp2;
     1170        char human[45];
     1171        char prefix[45], *p;
     1172        int n;
     1173        int i,j;
     1174       
     1175        /* assemble the args into a prefix in standard "human" form */
     1176        n=0;
     1177        p=prefix;
     1178        for(i=0; args[i]; i++) {
     1179                for(j=0; args[i][j]; j++) {
     1180                        char c = toupper(args[i][j]);
     1181                       
     1182                        if(n>=40) {
     1183                                irc_usermsg(irc, "too many fingerprint digits given, expected at most 40");
     1184                                return NULL;
     1185                        }
     1186                       
     1187                        if( (c>='A' && c<='F') || (c>='0' && c<='9') ) {
     1188                                *(p++) = c;
     1189                        } else {
     1190                                irc_usermsg(irc, "invalid hex digit '%c' in block %d", args[i][j], i+1);
     1191                                return NULL;
     1192                        }
     1193                       
     1194                        n++;
     1195                        if(n%8 == 0)
     1196                                *(p++) = ' ';
     1197                }
     1198        }
     1199        *p = '\0';
     1200        log_message(LOGLVL_DEBUG, "match_fingerprint '%s'", prefix);
     1201        log_message(LOGLVL_DEBUG, "n=%d strlen(prefix)=%d", n, strlen(prefix));
     1202       
     1203        /* find first fingerprint with the given prefix */
     1204        n = strlen(prefix);
     1205        for(fp=&ctx->fingerprint_root; fp; fp=fp->next) {
     1206                if(!fp->fingerprint)
     1207                        continue;
     1208                otrl_privkey_hash_to_human(human, fp->fingerprint);
     1209                if(!strncmp(prefix, human, n))
     1210                        break;
     1211        }
     1212        if(!fp) {
     1213                irc_usermsg(irc, "%s: no match", prefix);
     1214                return NULL;
     1215        }
     1216       
     1217        /* make sure the match, if any, is unique */
     1218        for(fp2=fp->next; fp2; fp2=fp2->next) {
     1219                if(!fp2->fingerprint)
     1220                        continue;
     1221                otrl_privkey_hash_to_human(human, fp2->fingerprint);
     1222                if(!strncmp(prefix, human, n))
     1223                        break;
     1224        }
     1225        if(fp2) {
     1226                irc_usermsg(irc, "%s: multiple matches", prefix);
     1227                return NULL;
     1228        }
     1229       
     1230        return fp;
     1231}
     1232
    10381233void show_general_otr_info(irc_t *irc)
    10391234{
     
    10801275               
    10811276                if(ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) {
    1082                         otrl_privkey_hash_to_human(human, ctx->active_fingerprint->fingerprint);
    10831277                        irc_usermsg(irc, "  \x02%s\x02", userstring);
    1084                         irc_usermsg(irc, "    %s", human);
    10851278                } else {
    10861279                        irc_usermsg(irc, "  %s", userstring);
     
    11241317        }
    11251318
    1126     irc_usermsg(irc, "  known fingerprints: (bold=active)");   
     1319    irc_usermsg(irc, "  fingerprints: (bold=active)"); 
    11271320        show_fingerprints(irc, ctx);
    11281321}
     
    11591352                return;
    11601353        }
    1161         kg->done = FALSE;
     1354        kg->done = 0;
    11621355
    11631356        /* Poll for completion of the thread periodically. I would have preferred
     
    11951388       
    11961389        /* lock OTR subsystem and do the work */
    1197         g_mutex_lock(kg->irc->otr_mutex);
     1390        g_static_rec_mutex_lock(&kg->irc->otr_mutex);
    11981391        kg->result = otrl_privkey_generate(kg->irc->otr_us, kg->keyfile, kg->handle,
    11991392                kg->protocol);
    1200         g_mutex_unlock(kg->irc->otr_mutex);
     1393        g_static_rec_mutex_unlock(&kg->irc->otr_mutex);
    12011394        /* OTR enabled again */
    12021395       
    12031396        /* notify mainloop */
    12041397        g_mutex_lock(kg->mutex);
    1205         kg->done = TRUE;
     1398        kg->done = 1;
    12061399        g_mutex_unlock(kg->mutex);
    12071400       
     
    12391432}
    12401433
    1241 void no_keygen(gpointer w, void *data)
    1242 {
    1243         account_t *acc = (account_t *)data;
    1244        
    1245         irc_usermsg(acc->irc, "keygen cancelled for %s/%s",
    1246                 acc->user, acc->prpl->name);
    1247 }
    1248 
    12491434
    12501435#else /* WITH_OTR undefined */
  • root_commands.c

    rd6fdf44 rc595308  
    8686                return;
    8787       
    88         if(!g_mutex_trylock(irc->otr_mutex)) {
     88        if(!g_static_rec_mutex_trylock(&irc->otr_mutex)) {
    8989                irc_usermsg(irc, "keygen in progress, bitlbee comatose - please wait");
    9090                return;
     
    9797                        {
    9898                                irc_usermsg( irc, "Not enough parameters given (need %d)", commands[i].required_parameters );
    99                                 g_mutex_unlock(irc->otr_mutex);
     99                                g_static_rec_mutex_unlock(&irc->otr_mutex);
    100100                                return;
    101101                        }
    102102                        commands[i].execute( irc, cmd );
    103                         g_mutex_unlock(irc->otr_mutex);
     103                        g_static_rec_mutex_unlock(&irc->otr_mutex);
    104104                        return;
    105105                }
    106106       
    107107        irc_usermsg( irc, "Unknown command: %s. Please use \x02help commands\x02 to get a list of available commands.", cmd[0] );
    108         g_mutex_unlock(irc->otr_mutex);
     108        g_static_rec_mutex_unlock(&irc->otr_mutex);
    109109}
    110110
Note: See TracChangeset for help on using the changeset viewer.