Changeset dc9797f


Ignore:
Timestamp:
2008-02-16T13:24:44Z (16 years ago)
Author:
Sven Moritz Hallberg <sm@…>
Branches:
master
Children:
3064ea4
Parents:
27db433
Message:

keep track of which keys are queued for generation

Files:
4 edited

Legend:

Unmodified
Added
Removed
  • irc.c

    r27db433 rdc9797f  
    134134        conf_loaddefaults( irc );
    135135
    136         irc->otr_us = otrl_userstate_create();
    137         irc->otr_keygen = 0;
    138         irc->otr_to = NULL;
    139         irc->otr_from = NULL;
    140         irc->otr_ntodo = 0;
     136        irc->otr = otr_new();
    141137       
    142138        return( irc );
     
    290286        }
    291287       
    292         otrl_userstate_free(irc->otr_us);
    293         if(irc->otr_keygen) {
    294                 kill(irc->otr_keygen, SIGTERM);
    295                 waitpid(irc->otr_keygen, NULL, 0);
    296                 /* TODO: remove stale keygen tempfiles */
    297         }
     288        otr_free(irc->otr);
    298289       
    299290        g_free(irc);
  • irc.h

    r27db433 rdc9797f  
    9898        gint ping_source_id;
    9999       
    100         OtrlUserState otr_us;
    101         pid_t otr_keygen;    /* pid of keygen slave */
    102         FILE *otr_to;        /* pipe to keygen slave */
    103         FILE *otr_from;      /* pipe from keygen slave */
    104         int otr_ntodo;       /* number of keys left to generate */
     100        otr_t *otr;            /* OTR state and book keeping */
    105101} irc_t;
    106102
  • otr.c

    r27db433 rdc9797f  
    4545#include <sys/wait.h>
    4646#include <unistd.h>
     47#include <assert.h>
    4748
    4849
     
    103104
    104105/** misc. helpers/subroutines: **/
     106
     107/* check whether we are already generating a key for a given account */
     108int keygen_in_progress(irc_t *irc, const char *handle, const char *protocol);
    105109
    106110/* start background process to generate a (new) key for a given account */
     
    191195}
    192196
     197otr_t *otr_new(void)
     198{
     199        otr_t *otr = g_new0(otr_t, 1);
     200
     201        otr->us = otrl_userstate_create();
     202       
     203        return otr;
     204}
     205
     206void otr_free(otr_t *otr)
     207{
     208        otrl_userstate_free(otr->us);
     209        if(otr->keygen) {
     210                kill(otr->keygen, SIGTERM);
     211                waitpid(otr->keygen, NULL, 0);
     212                /* TODO: remove stale keygen tempfiles */
     213        }
     214        if(otr->to)
     215                fclose(otr->to);
     216        if(otr->from)
     217                fclose(otr->from);
     218        while(otr->todo) {
     219                kg_t *p = otr->todo;
     220                otr->todo = p->next;
     221                g_free(p);
     222        }
     223        g_free(otr);
     224}
     225
    193226void otr_load(irc_t *irc)
    194227{
     
    201234
    202235        g_snprintf(s, 511, "%s%s.otr_keys", global.conf->configdir, irc->nick);
    203         e = otrl_privkey_read(irc->otr_us, s);
     236        e = otrl_privkey_read(irc->otr->us, s);
    204237        if(e && e!=enoent) {
    205238                irc_usermsg(irc, "otr load: %s: %s", s, gcry_strerror(e));
    206239        }
    207240        g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, irc->nick);
    208         e = otrl_privkey_read_fingerprints(irc->otr_us, s, NULL, NULL);
     241        e = otrl_privkey_read_fingerprints(irc->otr->us, s, NULL, NULL);
    209242        if(e && e!=enoent) {
    210243                irc_usermsg(irc, "otr load: %s: %s", s, gcry_strerror(e));
     
    225258
    226259        g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, irc->nick);
    227         e = otrl_privkey_write_fingerprints(irc->otr_us, s);
     260        e = otrl_privkey_write_fingerprints(irc->otr->us, s);
    228261        if(e) {
    229262                irc_usermsg(irc, "otr save: %s: %s", s, gcry_strerror(e));
     
    263296        OtrlPrivKey *k;
    264297       
    265         k = otrl_privkey_find(irc->otr_us, a->user, a->prpl->name);
     298        k = otrl_privkey_find(irc->otr->us, a->user, a->prpl->name);
    266299        if(k) {
    267                 irc_usermsg(irc, "otr: %s/%s ready",
    268                         a->user, a->prpl->name);
     300                irc_usermsg(irc, "otr: %s/%s ready", a->user, a->prpl->name);
     301        } if(keygen_in_progress(irc, a->user, a->prpl->name)) {
     302                irc_usermsg(irc, "otr: keygen for %s/%s in progress", a->user, a->prpl->name);
    269303        } else {
    270304                otr_keygen(irc, a->user, a->prpl->name);
     
    279313        char *colormsg;
    280314       
    281         ignore_msg = otrl_message_receiving(ic->irc->otr_us, &global.otr_ops, ic,
     315        ignore_msg = otrl_message_receiving(ic->irc->otr->us, &global.otr_ops, ic,
    282316                ic->acc->user, ic->acc->prpl->name, handle, msg, &newmsg,
    283317                &tlvs, NULL, NULL);
     
    293327        } else {
    294328                /* OTR has processed this message */
    295                 ConnContext *context = otrl_context_find(ic->irc->otr_us, handle,
     329                ConnContext *context = otrl_context_find(ic->irc->otr->us, handle,
    296330                        ic->acc->user, ic->acc->prpl->name, 0, NULL, NULL, NULL);
    297331                if(context && context->msgstate == OTRL_MSGSTATE_ENCRYPTED &&
     
    319353        ConnContext *ctx = NULL;
    320354       
    321         st = otrl_message_sending(ic->irc->otr_us, &global.otr_ops, ic,
     355        st = otrl_message_sending(ic->irc->otr->us, &global.otr_ops, ic,
    322356                ic->acc->user, ic->acc->prpl->name, handle,
    323357                msg, NULL, &otrmsg, NULL, NULL);
     
    326360        }
    327361
    328         ctx = otrl_context_find(ic->irc->otr_us,
     362        ctx = otrl_context_find(ic->irc->otr->us,
    329363                        handle, ic->acc->user, ic->acc->prpl->name,
    330364                        1, NULL, NULL, NULL);
     
    384418        struct im_connection *ic = check_imc(opdata, context->accountname, context->protocol);
    385419        const char *p;
     420       
     421        log_message(LOGLVL_DEBUG, "op_policy '%s' '%s'", context->accountname, context->protocol);
     422       
     423        /* policy override during keygen: if we're missing the key for context but are currently
     424           generating it, then that's as much as we can do. => temporarily return NEVER. */
     425        if(keygen_in_progress(ic->irc, context->accountname, context->protocol) &&
     426           !otrl_privkey_find(ic->irc->otr->us, context->accountname, context->protocol))
     427                return OTRL_POLICY_NEVER;
    386428
    387429        p = set_getstr(&ic->irc->set, "otr_policy");
     
    402444{
    403445        struct im_connection *ic = check_imc(opdata, accountname, protocol);
    404         char *s;
    405446       
    406447        log_message(LOGLVL_DEBUG, "op_create_privkey '%s' '%s'", accountname, protocol);
    407448
    408         s = g_strdup_printf("oops, no otr privkey for %s - generate one now?",
    409                 accountname);
    410         query_add(ic->irc, ic, s, yes_keygen, NULL, ic->acc);
     449        /* will fail silently if keygen already in progress */
     450        otr_keygen(ic->irc, accountname, protocol);
    411451}
    412452
     
    596636        }
    597637       
    598         otrl_message_disconnect(irc->otr_us, &global.otr_ops,
     638        otrl_message_disconnect(irc->otr->us, &global.otr_ops,
    599639                u->ic, u->ic->acc->user, u->ic->acc->prpl->name, u->handle);
    600640       
     
    602642        if(u->encrypted) {
    603643                ConnContext *ctx;
    604                 ctx = otrl_context_find(irc->otr_us, u->handle, u->ic->acc->user,
     644                ctx = otrl_context_find(irc->otr->us, u->handle, u->ic->acc->user,
    605645                        u->ic->acc->prpl->name, 0, NULL, NULL, NULL);
    606646                if(ctx)
     
    643683        }
    644684       
    645         ctx = otrl_context_find(irc->otr_us, u->handle,
     685        ctx = otrl_context_find(irc->otr->us, u->handle,
    646686                u->ic->acc->user, u->ic->acc->prpl->name, 1, NULL, NULL, NULL);
    647687        if(!ctx) {
     
    654694                        "SMP already in phase %d, sending abort before reinitiating",
    655695                        ctx->smstate->nextExpected+1);
    656                 otrl_message_abort_smp(irc->otr_us, &global.otr_ops, u->ic, ctx);
     696                otrl_message_abort_smp(irc->otr->us, &global.otr_ops, u->ic, ctx);
    657697                otrl_sm_state_free(ctx->smstate);
    658698        }
     
    662702        if(ctx->smstate->secret == NULL) {
    663703                irc_usermsg(irc, "smp: initiating with %s...", u->nick);
    664                 otrl_message_initiate_smp(irc->otr_us, &global.otr_ops,
     704                otrl_message_initiate_smp(irc->otr->us, &global.otr_ops,
    665705                        u->ic, ctx, (unsigned char *)args[2], strlen(args[2]));
    666706                /* smp is now in EXPECT2 */
     
    669709                   received the SMP1, so let's issue a response */
    670710                irc_usermsg(irc, "smp: responding to %s...", u->nick);
    671                 otrl_message_respond_smp(irc->otr_us, &global.otr_ops,
     711                otrl_message_respond_smp(irc->otr->us, &global.otr_ops,
    672712                        u->ic, ctx, (unsigned char *)args[2], strlen(args[2]));
    673713                /* smp is now in EXPECT3 */
     
    689729        }
    690730       
    691         ctx = otrl_context_find(irc->otr_us, u->handle,
     731        ctx = otrl_context_find(irc->otr->us, u->handle,
    692732                u->ic->acc->user, u->ic->acc->prpl->name, 0, NULL, NULL, NULL);
    693733        if(!ctx) {
     
    753793                        *(myhandle++) = '\0';
    754794                        handle = arg;
    755                         ctx = otrl_context_find(irc->otr_us, handle, myhandle, protocol, 0, NULL, NULL, NULL);
     795                        ctx = otrl_context_find(irc->otr->us, handle, myhandle, protocol, 0, NULL, NULL, NULL);
    756796                        if(!ctx) {
    757797                                irc_usermsg(irc, "no such context");
     
    766806                                return;
    767807                        }
    768                         ctx = otrl_context_find(irc->otr_us, u->handle, u->ic->acc->user,
     808                        ctx = otrl_context_find(irc->otr->us, u->handle, u->ic->acc->user,
    769809                                u->ic->acc->prpl->name, 0, NULL, NULL, NULL);
    770810                        if(!ctx) {
     
    803843        }
    804844       
    805         if(otrl_privkey_find(irc->otr_us, a->user, a->prpl->name)) {
     845        if(keygen_in_progress(irc, a->user, a->prpl->name)) {
     846                irc_usermsg(irc, "keygen for account %d already in progress", n);
     847                return;
     848        }
     849       
     850        if(otrl_privkey_find(irc->otr->us, a->user, a->prpl->name)) {
    806851                char *s = g_strdup_printf("account %d already has a key, replace it?", n);
    807852                query_add(irc, NULL, s, yes_keygen, NULL, a);
     
    871916                }
    872917               
    873                 ctx = otrl_context_find(irc->otr_us, u->handle, u->ic->acc->user,
     918                ctx = otrl_context_find(irc->otr->us, u->handle, u->ic->acc->user,
    874919                        u->ic->acc->prpl->name, 0, NULL, NULL, NULL);
    875920                if(!ctx) {
     
    907952                }
    908953               
    909                 ctx = otrl_context_find(irc->otr_us, u->handle, u->ic->acc->user,
     954                ctx = otrl_context_find(irc->otr->us, u->handle, u->ic->acc->user,
    910955                        u->ic->acc->prpl->name, 0, NULL, NULL, NULL);
    911956                if(!ctx) {
     
    9581003{
    9591004        irc_t *irc = ic->irc;
    960         OtrlUserState us = irc->otr_us;
     1005        OtrlUserState us = irc->otr->us;
    9611006        OtrlMessageAppOps *ops = &global.otr_ops;
    9621007        OtrlTLV *tlv = NULL;
     
    13071352        /* find first key which matches the given prefix */
    13081353        n = strlen(prefix);
    1309         for(k=irc->otr_us->privkey_root; k; k=k->next) {
    1310                 p = otrl_privkey_fingerprint(irc->otr_us, human, k->accountname, k->protocol);
     1354        for(k=irc->otr->us->privkey_root; k; k=k->next) {
     1355                p = otrl_privkey_fingerprint(irc->otr->us, human, k->accountname, k->protocol);
    13111356                if(!p) /* gah! :-P */
    13121357                        continue;
     
    13211366        /* make sure the match, if any, is unique */
    13221367        for(k2=k->next; k2; k2=k2->next) {
    1323                 p = otrl_privkey_fingerprint(irc->otr_us, human, k2->accountname, k2->protocol);
     1368                p = otrl_privkey_fingerprint(irc->otr->us, human, k2->accountname, k2->protocol);
    13241369                if(!p) /* gah! :-P */
    13251370                        continue;
     
    13431388        /* list all privkeys */
    13441389        irc_usermsg(irc, "\x1fprivate keys:\x1f");
    1345         for(key=irc->otr_us->privkey_root; key; key=key->next) {
     1390        for(key=irc->otr->us->privkey_root; key; key=key->next) {
    13461391                const char *hash;
    13471392               
     
    13581403                   account/protocol, but libotr currently doesn't provide a direct routine
    13591404                   for hashing a given 'OtrlPrivKey'... */
    1360                 hash = otrl_privkey_fingerprint(irc->otr_us, human, key->accountname, key->protocol);
     1405                hash = otrl_privkey_fingerprint(irc->otr->us, human, key->accountname, key->protocol);
    13611406                if(hash) /* should always succeed */
    13621407                        irc_usermsg(irc, "    %s", human);
     
    13661411        irc_usermsg(irc, "%s", "");
    13671412        irc_usermsg(irc, "\x1f" "connection contexts:\x1f (bold=currently encrypted)");
    1368         for(ctx=irc->otr_us->context_root; ctx; ctx=ctx->next) {\
     1413        for(ctx=irc->otr->us->context_root; ctx; ctx=ctx->next) {\
    13691414                user_t *u;
    13701415                char *userstring;
     
    14251470}
    14261471
     1472int keygen_in_progress(irc_t *irc, const char *handle, const char *protocol)
     1473{
     1474        kg_t *kg;
     1475       
     1476        log_message(LOGLVL_DEBUG, "keygen_in_progress '%s' '%s'", handle, protocol);
     1477       
     1478        if(!irc->otr->sent_accountname || !irc->otr->sent_protocol)
     1479                return 0;
     1480
     1481        /* are we currently working on this key? */
     1482        if(!strcmp(handle, irc->otr->sent_accountname) &&
     1483           !strcmp(protocol, irc->otr->sent_protocol))
     1484                return 1;
     1485       
     1486        /* do we have it queued for later? */
     1487        for(kg=irc->otr->todo; kg; kg=kg->next) {
     1488                if(!strcmp(handle, kg->accountname) &&
     1489                   !strcmp(protocol, kg->protocol))
     1490                        return 1;
     1491        }
     1492       
     1493        return 0;
     1494}
     1495
    14271496void otr_keygen(irc_t *irc, const char *handle, const char *protocol)
    14281497{
     1498        /* do nothing if a key for the requested account is already being generated */
     1499        if(keygen_in_progress(irc, handle, protocol))
     1500                return;
     1501       
    14291502        irc_usermsg(irc, "generating new private key for %s/%s...", handle, protocol);
    14301503
    14311504        /* see if we already have a keygen child running. if not, start one and put a
    14321505           handler on its output. */
    1433         if(!irc->otr_keygen || waitpid(irc->otr_keygen, NULL, WNOHANG)) {
     1506        if(!irc->otr->keygen || waitpid(irc->otr->keygen, NULL, WNOHANG)) {
    14341507                pid_t p;
    14351508                int to[2], from[2];
     
    14571530                        /* child process */
    14581531                        signal(SIGTERM, exit);
    1459                         keygen_child_main(irc->otr_us, to[0], from[1]);
     1532                        keygen_child_main(irc->otr->us, to[0], from[1]);
    14601533                        exit(0);
    14611534                }
    14621535               
    1463                 irc->otr_keygen = p;
    1464                 irc->otr_to = tof;
    1465                 irc->otr_from = fromf;
    1466                 irc->otr_ntodo = 0;
     1536                irc->otr->keygen = p;
     1537                irc->otr->to = tof;
     1538                irc->otr->from = fromf;
     1539                irc->otr->sent_accountname = NULL;
     1540                irc->otr->sent_protocol = NULL;
     1541                irc->otr->todo = NULL;
    14671542                b_input_add(from[0], GAIM_INPUT_READ, keygen_finish_handler, irc);
    14681543        }
    14691544       
    1470         /* send accountname and protocol for the new key to our keygen slave */
    1471         fprintf(irc->otr_to, "%s\n%s\n", handle, protocol);
    1472         fflush(irc->otr_to);
    1473         irc->otr_ntodo++;
     1545        /* is the keygen slave currently working? */
     1546        if(irc->otr->sent_accountname) {
     1547                /* enqueue our job for later transmission */
     1548                log_message(LOGLVL_DEBUG, "enqueueing keygen for %s/%s", handle, protocol);
     1549                kg_t **kg = &irc->otr->todo;
     1550                while(*kg)
     1551                        kg=&((*kg)->next);
     1552                *kg = g_new0(kg_t, 1);
     1553                (*kg)->accountname = handle;
     1554                (*kg)->protocol = protocol;
     1555        } else {
     1556                /* send our job over and remember it */
     1557                log_message(LOGLVL_DEBUG, "slave: generate for %s/%s!", handle, protocol);
     1558                fprintf(irc->otr->to, "%s\n%s\n", handle, protocol);
     1559                fflush(irc->otr->to);
     1560                irc->otr->sent_accountname = handle;
     1561                irc->otr->sent_protocol = protocol;
     1562        }
    14741563}
    14751564
     
    15151604        log_message(LOGLVL_DEBUG, "keygen_finish_handler cond=%d", cond);
    15161605
    1517         myfgets(filename, 512, irc->otr_from);
    1518         myfgets(msg, 512, irc->otr_from);
     1606        myfgets(filename, 512, irc->otr->from);
     1607        myfgets(msg, 512, irc->otr->from);
    15191608       
    15201609        log_message(LOGLVL_DEBUG, "filename='%s'", filename);
     
    15281617                unlink(filename);
    15291618                rename(tmp,kf);
    1530                 otrl_privkey_read(irc->otr_us, kf);
     1619                otrl_privkey_read(irc->otr->us, kf);
    15311620                g_free(kf);
    15321621                g_free(tmp);
    15331622        }
    1534                
    1535         irc->otr_ntodo--;
    1536         if(irc->otr_ntodo < 1) {
    1537                 /* okay, we think the slave is idle now, so kill him */
     1623       
     1624        /* forget this job */
     1625        irc->otr->sent_accountname = NULL;
     1626        irc->otr->sent_protocol = NULL;
     1627       
     1628        /* see if there are any more in the queue */
     1629        if(irc->otr->todo) {
     1630                kg_t *p = irc->otr->todo;
     1631                /* send the next one over */
     1632                log_message(LOGLVL_DEBUG, "slave: keygen for %s/%s!", p->accountname, p->protocol);
     1633                fprintf(irc->otr->to, "%s\n%s\n", p->accountname, p->protocol);
     1634                fflush(irc->otr->to);
     1635                irc->otr->sent_accountname = p->accountname;
     1636                irc->otr->sent_protocol = p->protocol;
     1637                irc->otr->todo = p->next;
     1638                g_free(p);
     1639                return TRUE;   /* keep watching */
     1640        } else {
     1641                /* okay, the slave is idle now, so kill him */
    15381642                log_message(LOGLVL_DEBUG, "all keys done. die, slave!");
    1539                 fclose(irc->otr_from);
    1540                 fclose(irc->otr_to);
    1541                 kill(irc->otr_keygen, SIGTERM);
    1542                 waitpid(irc->otr_keygen, NULL, 0);
    1543                 irc->otr_keygen = 0;
     1643                fclose(irc->otr->from);
     1644                fclose(irc->otr->to);
     1645                kill(irc->otr->keygen, SIGTERM);
     1646                waitpid(irc->otr->keygen, NULL, 0);
     1647                irc->otr->keygen = 0;
    15441648                return FALSE;  /* unregister ourselves */
    1545         } else {
    1546                 return TRUE;   /* slave still working, keep watching */
    15471649        }
    15481650}
     
    15811683        account_t *acc = (account_t *)data;
    15821684       
    1583         otr_keygen(acc->irc, acc->user, acc->prpl->name);
     1685        if(keygen_in_progress(acc->irc, acc->user, acc->prpl->name)) {
     1686                irc_usermsg(acc->irc, "keygen for %s/%s already in progress",
     1687                        acc->user, acc->prpl->name);
     1688        } else {
     1689                otr_keygen(acc->irc, acc->user, acc->prpl->name);
     1690        }
    15841691}
    15851692
  • otr.h

    r27db433 rdc9797f  
    4949#include <libotr/privkey.h>
    5050
     51/* representing a keygen job */
     52typedef struct kg {
     53        const char *accountname;
     54        const char *protocol;
     55       
     56        struct kg *next;
     57} kg_t;
     58
     59/* struct to encapsulate our book keeping stuff */
     60typedef struct otr {
     61        OtrlUserState us;
     62        pid_t keygen;    /* pid of keygen slave (0 if none) */
     63        FILE *to;        /* pipe to keygen slave */
     64        FILE *from;      /* pipe from keygen slave */
     65       
     66        /* active keygen job (NULL if none) */
     67        const char *sent_accountname;
     68        const char *sent_protocol;
     69       
     70        /* keygen jobs waiting to be sent to slave */
     71        kg_t *todo;
     72} otr_t;
     73
    5174/* called from main() */
    5275void otr_init(void);
     76
     77/* called from irc_new()/irc_free() */
     78otr_t *otr_new();
     79void otr_free(otr_t *otr);
    5380
    5481/* called by storage_* functions */
     
    7198#else
    7299
    73 typedef void *OtrlUserState;
     100typedef void otr_t;
    74101typedef void *OtrlMessageAppOps;
    75102
    76 #define otrl_userstate_create() (NULL)
    77 #define otrl_userstate_free(us) {}
    78 
    79103#define otr_init() {}
     104#define otr_new() (NULL)
     105#define otr_free(otr) {}
    80106#define otr_load(irc) {}
    81107#define otr_save(irc) {}
Note: See TracChangeset for help on using the changeset viewer.