URI: 
       tnym.c - mixmaster - mixmaster 3.0 patched for libressl
  HTML git clone git://parazyd.org/mixmaster.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
       ---
       tnym.c (15627B)
       ---
            1 /* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
            2 
            3    Mixmaster may be redistributed and modified under certain conditions.
            4    This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
            5    ANY KIND, either express or implied. See the file COPYRIGHT for
            6    details.
            7 
            8    Create nym server messages
            9    $Id: nym.c 934 2006-06-24 13:40:39Z rabbi $ */
           10 
           11 
           12 #ifdef NYMSUPPORT
           13 
           14 #include "mix3.h"
           15 #include "pgp.h"
           16 #include <string.h>
           17 #include <time.h>
           18 #include <assert.h>
           19 
           20 int nym_config(int mode, char *nym, char *nymserver, BUFFER *pseudonym,
           21                char *sendchain, int sendnumcopies, BUFFER *chains,
           22                BUFFER *options)
           23 {
           24 #ifndef USE_PGP
           25   return (-1);
           26 #else /* end of not USE_PGP */
           27   REMAILER remailer[MAXREM];
           28   int badchains[MAXREM][MAXREM];
           29   KEYRING *r;
           30   int maxrem;
           31   int chain[20];
           32   char rchain[CHAINMAX];
           33   BUFFER *userid, *msg, *req, *k, *line, *ek, *eklist, *key, *pubkey, *out,
           34       *oldchains;
           35   int latency;
           36   int err = -1;
           37   int status;
           38   int desttype = MSG_MAIL;
           39   int rblock = 0;
           40   BUFFER *nymlist, *userpass, *config;
           41   LOCK *nymlock;
           42 
           43   userid = buf_new();
           44   msg = buf_new();
           45   req = buf_new();
           46   k = buf_new();
           47   line = buf_new();
           48   ek = buf_new();
           49   eklist = buf_new();
           50   key = buf_new();
           51   pubkey = buf_new();
           52   out = buf_new();
           53   config = buf_new();
           54   nymlist = buf_new();
           55   userpass = buf_new();
           56   oldchains = buf_new();
           57 
           58   for (;;) {
           59     user_pass(userpass);
           60     if (user_confirmpass(userpass))
           61       break;
           62     user_delpass();
           63   }
           64 
           65   if (nymserver) {
           66     maxrem = t1_rlist(remailer, badchains);
           67     if (maxrem < 1)
           68       return (-1);
           69     if (chain_select(chain, nymserver, maxrem, remailer, 2, NULL) != 1)
           70       return (-1);
           71     if (chain[0] == 0)
           72       chain[0] = chain_randfinal(MSG_MAIL, remailer, badchains, maxrem, 2, NULL, -1);
           73     if (chain[0] == -1)
           74       return (-1);
           75     assert(strchr(nym, '@') == NULL && strchr(remailer[chain[0]].addr, '@'));
           76     strcatn(nym, strchr(remailer[chain[0]].addr, '@'), LINELEN);
           77     buf_appends(config, remailer[chain[0]].addr);
           78   } else
           79     assert(strchr(nym, '@') != NULL);
           80 
           81   status = nymlist_getnym(nym, config->length ? NULL : config, eklist, NULL,
           82                           NULL, oldchains);
           83   if (mode == NYM_CREATE && status == NYM_OK)
           84     mode = NYM_MODIFY;
           85 
           86   buf_appendc(userid, '<');
           87   buf_appends(userid, nym);
           88   buf_appendc(userid, '>');
           89 
           90   buf_sets(req, "Config:\nFrom: ");
           91   buf_append(req, nym, strchr(nym, '@') - nym);
           92   buf_appends(req, "\nNym-Commands:");
           93   if (mode == NYM_CREATE)
           94     buf_appends(req, " create?");
           95   if (mode == NYM_DELETE)
           96     buf_appends(req, " delete");
           97   else {
           98     if (options && options->length > 0) {
           99       if (!bufleft(options, " "))
          100         buf_appendc(req, ' ');
          101       buf_cat(req, options);
          102     }
          103     if (pseudonym && pseudonym->length > 0) {
          104       buf_appends(req, " name=\"");
          105       buf_cat(req, pseudonym);
          106       buf_appendc(req, '\"');
          107     }
          108   }
          109   buf_nl(req);
          110   if (mode == NYM_CREATE) {
          111     buf_appends(req, "Public-Key:\n");
          112 
          113   getkey:
          114     r = pgpdb_open(NYMSECRING, userpass, 0, PGP_TYPE_PRIVATE);
          115     if (r == NULL) {
          116       err = -3;
          117       goto end;
          118     }
          119     if (r->filetype == -1)
          120       r->filetype = 0;
          121 
          122     while (pgpdb_getnext(r, key, NULL, userid) != -1)
          123       if (pgp_makepubkey(key, NULL, pubkey, userpass, 0) == 0)
          124         err = 0;
          125     pgpdb_close(r);
          126     if (err != 0) {
          127       if (err == -2)
          128         goto end;
          129       err = -2;
          130       if (pseudonym && pseudonym->length) {
          131         buf_set(userid, pseudonym);
          132         buf_appendc(userid, ' ');
          133       } else
          134         buf_clear(userid);
          135       buf_appendf(userid, "<%s>", nym);
          136       pgp_keygen(PGP_ES_RSA, 0, userid, userpass, NULL, NYMSECRING, 2);
          137       goto getkey;
          138     }
          139     pgp_armor(pubkey, PGP_ARMOR_NYMKEY);
          140     buf_cat(req, pubkey);
          141   }
          142   if (mode != NYM_DELETE) {
          143     if (nymlist_read(nymlist) == -1) {
          144       user_delpass();
          145       err = -1;
          146       goto end;
          147     }
          148     if (chains)
          149       for (;;) {
          150         err = buf_getheader(chains, k, line);
          151         if (err == -1 && rblock == 0)
          152           break;
          153         if (err != 0 && rblock == 1) {
          154           buf_setrnd(ek, 16);
          155           if (t1_encrypt(desttype, msg, rchain, latency, ek, NULL) != 0) {
          156             err = -2;
          157             goto end;
          158           }
          159           encode(ek, 0);
          160           buf_cat(eklist, ek);
          161           buf_nl(eklist);
          162           buf_appends(req, "Reply-Block:\n");
          163           buf_cat(req, msg);
          164           buf_clear(msg);
          165           rblock = 0;
          166           continue;
          167         }
          168         if (bufieq(k, "Chain"))
          169           strncpy(rchain, line->data, sizeof(rchain));
          170         else if (bufieq(k, "Latency"))
          171           sscanf(line->data, "%d", &latency);
          172         else if (bufieq(k, "Null"))
          173           desttype = MSG_NULL, rblock = 1;
          174         else {
          175           buf_appendheader(msg, k, line);
          176           if (bufieq(k, "To"))
          177             desttype = MSG_MAIL, rblock = 1;
          178           if (bufieq(k, "Newsgroups"))
          179             desttype = MSG_POST, rblock = 1;
          180         }
          181       }
          182   }
          183   nymlock = lockfile(NYMDB);
          184   if (nymlist_read(nymlist) == 0) {
          185     nymlist_del(nymlist, nym);
          186     nymlist_append(nymlist, nym, config, options, pseudonym,
          187                    chains ? chains : oldchains, eklist,
          188                    mode == NYM_DELETE ? NYM_DELETED :
          189                    (status == -1 ? NYM_WAITING : status));
          190     nymlist_write(nymlist);
          191   } else
          192     err = -1;
          193   unlockfile(nymlock);
          194 
          195 #ifdef DEBUG
          196   buf_write(req, stderr);
          197 #endif /* DEBUG */
          198   buf_clear(line);
          199   buf_appendc(line, '<');
          200   buf_cat(line, config);
          201   buf_appendc(line, '>');
          202 
          203   err = pgp_encrypt(PGP_ENCRYPT | PGP_SIGN | PGP_TEXT | PGP_REMAIL,
          204                     req, line, userid, userpass, NULL, NYMSECRING);
          205   if (err != 0)
          206     goto end;
          207 #ifdef DEBUG
          208   buf_write(req, stderr);
          209 #endif /* DEBUG */
          210   buf_sets(out, "To: ");
          211   buf_cat(out, config);
          212   buf_nl(out);
          213   buf_nl(out);
          214   buf_cat(out, req);
          215 
          216   err = mix_encrypt(desttype, out, sendchain, sendnumcopies, line);
          217   if (err)
          218     mix_status("%s\n", line->data);
          219 
          220 end:
          221   if (strchr(nym, '@')) *strchr(nym, '@') = '\0';
          222   buf_free(userid);
          223   buf_free(msg);
          224   buf_free(req);
          225   buf_free(k);
          226   buf_free(line);
          227   buf_free(ek);
          228   buf_free(eklist);
          229   buf_free(key);
          230   buf_free(pubkey);
          231   buf_free(out);
          232   buf_free(nymlist);
          233   buf_free(userpass);
          234   buf_free(oldchains);
          235   buf_free(config);
          236   return (err);
          237 #endif /* else if USE_PGP */
          238 }
          239 
          240 int nym_encrypt(BUFFER *msg, char *nym, int type)
          241 {
          242 #ifndef USE_PGP
          243   return (-1);
          244 #else /* end of not USE_PGP */
          245   BUFFER *out, *userpass, *sig, *config;
          246   int err = -1;
          247 
          248   out = buf_new();
          249   userpass = buf_new();
          250   sig = buf_new();
          251   config = buf_new();
          252 
          253   if (nymlist_getnym(nym, config, NULL, NULL, NULL, NULL) == NYM_OK) {
          254     buf_appends(out, "From: ");
          255     buf_append(out, nym, strchr(nym, '@') - nym);
          256     buf_nl(out);
          257     if (type == MSG_POST) {
          258       buf_appends(out, "To: ");
          259       buf_appends(out, MAILtoNEWS);
          260       buf_nl(out);
          261     }
          262     buf_cat(out, msg);
          263     mail_encode(out, 0);
          264     buf_appendc(sig, '<');
          265     buf_appends(sig, nym);
          266     buf_appendc(sig, '>');
          267 #ifdef DEBUG
          268     buf_write(out, stderr);
          269 #endif /* DEBUG */
          270     user_pass(userpass);
          271     err = pgp_encrypt(PGP_ENCRYPT | PGP_SIGN | PGP_TEXT | PGP_REMAIL,
          272                       out, config, sig, userpass, NULL, NYMSECRING);
          273     if (err == 0) {
          274       buf_clear(msg);
          275       buf_appends(msg, "To: send");
          276       buf_appends(msg, strchr(nym, '@'));
          277       buf_nl(msg);
          278       buf_nl(msg);
          279       buf_cat(msg, out);
          280     }
          281   }
          282   buf_free(out);
          283   buf_free(config);
          284   buf_free(userpass);
          285   buf_free(sig);
          286   return (err);
          287 #endif /* else if USE_PGP */
          288 }
          289 
          290 int nym_decrypt(BUFFER *msg, char *thisnym, BUFFER *log)
          291 {
          292 #ifndef USE_PGP
          293   return (-1);
          294 #else /* end of not USE_PGP */
          295   BUFFER *pgpmsg, *out, *line;
          296   BUFFER *nymlist, *userpass;
          297   BUFFER *decr, *sig, *mid;
          298   BUFFER *name, *rblocks, *eklist, *config;
          299   int decrypted = 0;
          300   int err = 1;
          301   long ptr;
          302   char nym[LINELEN];
          303   BUFFER *ek, *opt;
          304   int status;
          305   LOCK *nymlock;
          306   time_t t;
          307   struct tm *tc;
          308   char timeline[LINELEN];
          309 
          310   pgpmsg = buf_new();
          311   out = buf_new();
          312   line = buf_new();
          313   nymlist = buf_new();
          314   userpass = buf_new();
          315   config = buf_new();
          316   ek = buf_new();
          317   decr = buf_new();
          318   sig = buf_new();
          319   mid = buf_new();
          320   opt = buf_new();
          321   name = buf_new();
          322   rblocks = buf_new();
          323   eklist = buf_new();
          324 
          325   if (thisnym)
          326     thisnym[0] = '\0';
          327   while ((ptr = msg->ptr, err = buf_getline(msg, line)) != -1) {
          328     if (bufleft(line, begin_pgpmsg)) {
          329       err = -1;
          330       msg->ptr = ptr;
          331       pgp_dearmor(msg, pgpmsg);
          332       if (pgp_isconventional(pgpmsg)) {
          333         user_pass(userpass);
          334         nymlock = lockfile(NYMDB);
          335         if (nymlist_read(nymlist) == -1)
          336           user_delpass();
          337         while (nymlist_get(nymlist, nym, config, eklist, opt, name,
          338                            rblocks, &status) >= 0) {
          339           while (buf_getline(eklist, ek) == 0) {
          340             decode(ek, ek);
          341             if (t1_getreply(pgpmsg, ek, 20) == 0) {
          342               buf_clear(out);
          343               err = pgp_decrypt(pgpmsg, userpass, sig, NULL,
          344                                 NYMSECRING);
          345               buf_sets(out, "From nymserver ");
          346               if (strchr(sig->data, '[') && strchr(sig->data, ']'))
          347                 buf_append(out, strchr(sig->data, '[') + 1,
          348                            strchr(sig->data, ']') -
          349                            strchr(sig->data, '[') - 1);
          350               else {
          351                 t = time(NULL);
          352                 tc = localtime(&t);
          353                 strftime(timeline, LINELEN, "%a %b %d %H:%M:%S %Y", tc);
          354                 buf_appends(out, timeline);
          355               }
          356               buf_nl(out);
          357               if (err == PGP_SIGOK &&
          358                   bufifind(sig, config->data)) {
          359                 buf_appends(out, "Nym: ");
          360                 if (status == NYM_WAITING)
          361                   buf_appends(out, "confirm ");
          362                 buf_appends(out, nym);
          363                 buf_nl(out);
          364                 if (thisnym && status == NYM_OK)
          365                   strncpy(thisnym, nym, LINELEN);
          366               } else
          367                 buf_appends(out, "Warning: Signature verification failed!\n");
          368               buf_cat(out, pgpmsg);
          369               decrypted = 2;
          370               if (log) {
          371                 digest_md5(out, mid);
          372                 encode(mid, 0);
          373                 if (buffind(log, mid->data)) {
          374                   decrypted = -1;
          375                   unlockfile(nymlock);
          376                   goto end;
          377                 } else {
          378                   buf_cat(log, mid);
          379                   buf_nl(log);
          380                 }
          381               }
          382               if (status == NYM_WAITING) {
          383                 nymlist_del(nymlist, nym);
          384                 nymlist_append(nymlist, nym, config, opt,
          385                                name, rblocks, eklist, NYM_OK);
          386               }
          387               break;
          388             }
          389           }
          390         }
          391         nymlist_write(nymlist);
          392         unlockfile(nymlock);
          393       }
          394       if (decrypted == 0) {
          395         user_pass(userpass);
          396         err = pgp_decrypt(pgpmsg, userpass, sig, PGPPUBRING, PGPSECRING);
          397         if (err == PGP_ERR)
          398           err = pgp_decrypt(pgpmsg, userpass, sig, PGPPUBRING,
          399                             NYMSECRING);
          400 #if 0
          401         if (err == PGP_PASS || err == PGP_ERR)
          402           user_delpass();
          403 #endif /* 0 */
          404         if (err != PGP_ERR && err != PGP_PASS && err != PGP_NOMSG &&
          405             err != PGP_NODATA) {
          406           buf_appends(out, info_beginpgp);
          407           if (err == PGP_SIGOK)
          408             buf_appendf(out, " (SIGNED)\n%s%b", info_pgpsig, sig);
          409           buf_nl(out);
          410           buf_cat(out, pgpmsg);
          411           buf_appends(out, info_endpgp);
          412           buf_nl(out);
          413           decrypted = 1;
          414         }
          415       }
          416       if (decrypted == 0) {
          417         buf_cat(out, line);
          418         buf_nl(out);
          419       }
          420     } else {
          421       if (bufileft(line, info_beginpgp))
          422           buf_appendc(out, ' '); /* escape info line in text */
          423       buf_cat(out, line);
          424       buf_nl(out);
          425     }
          426   }
          427 
          428   if (decrypted)
          429     buf_move(msg, out);
          430   else
          431     buf_rewind(msg);
          432   if (decrypted == 2)
          433     nym_decrypt(msg, thisnym, NULL);
          434 end:
          435   buf_free(pgpmsg);
          436   buf_free(out);
          437   buf_free(line);
          438   buf_free(decr);
          439   buf_free(sig);
          440   buf_free(mid);
          441   buf_free(opt);
          442   buf_free(name);
          443   buf_free(config);
          444   buf_free(rblocks);
          445   buf_free(eklist);
          446   buf_free(nymlist);
          447   buf_free(userpass);
          448   buf_free(ek);
          449   return (decrypted);
          450 #endif /* else if USE_PGP */
          451 }
          452 
          453 int nymlist_read(BUFFER *list)
          454 {
          455 #ifdef USE_PGP
          456   BUFFER *key;
          457 
          458 #endif /* USE_PGP */
          459   FILE *f;
          460   int err = 0;
          461 
          462   buf_clear(list);
          463   f = mix_openfile(NYMDB, "rb");
          464   if (f != NULL) {
          465     buf_read(list, f);
          466     fclose(f);
          467 #ifdef USE_PGP
          468     key = buf_new();
          469     user_pass(key);
          470     if (key->length)
          471       if (pgp_decrypt(list, key, NULL, NULL, NULL) < 0) {
          472         buf_clear(list);
          473         err = -1;
          474       }
          475     buf_free(key);
          476 #endif /* USE_PGP */
          477   }
          478   return (err);
          479 }
          480 
          481 int nymlist_write(BUFFER *list)
          482 {
          483 #ifdef USE_PGP
          484   BUFFER *key;
          485 
          486 #endif /* USE_PGP */
          487   FILE *f;
          488 
          489   if (list->length == 0)
          490     return (-1);
          491 
          492 #ifdef USE_PGP
          493   key = buf_new();
          494   user_pass(key);
          495   if (key->length)
          496     pgp_encrypt(PGP_NCONVENTIONAL | PGP_NOARMOR, list, key, NULL, NULL, NULL,
          497                 NULL);
          498   buf_free(key);
          499 #endif /* USE_PGP */
          500   f = mix_openfile(NYMDB, "wb");
          501   if (f == NULL)
          502     return (-1);
          503   else {
          504     buf_write(list, f);
          505     fclose(f);
          506   }
          507   return (0);
          508 }
          509 
          510 int nymlist_get(BUFFER *list, char *nym, BUFFER *config, BUFFER *ek,
          511                 BUFFER *opt, BUFFER *name, BUFFER *chains, int *status)
          512 {
          513   BUFFER *line;
          514   int err = -1;
          515 
          516   line = buf_new();
          517   if (ek)
          518     buf_clear(ek);
          519   if (opt)
          520     buf_clear(opt);
          521   if (name)
          522     buf_clear(name);
          523   if (chains)
          524     buf_clear(chains);
          525   if (config)
          526     buf_clear(config);
          527 
          528   for (;;) {
          529     if (buf_getline(list, line) == -1)
          530       goto end;
          531     if (bufleft(line, "nym="))
          532       break;
          533   }
          534   strncpy(nym, line->data + 4, LINELEN);
          535 
          536   for (;;) {
          537     if (buf_getline(list, line) == -1)
          538       break;
          539     if (opt && bufleft(line, "opt="))
          540       line->ptr = 4, buf_rest(opt, line);
          541     if (name && bufleft(line, "name="))
          542       line->ptr = 5, buf_rest(name, line);
          543     if (config && bufleft(line, "config="))
          544       line->ptr = 7, buf_rest(config, line);
          545     if (bufeq(line, "ek=")) {
          546       while (buf_getline(list, line) == 0 && !bufeq(line, "end ek"))
          547         if (ek) {
          548           buf_cat(ek, line);
          549           buf_nl(ek);
          550         }
          551     }
          552     if (bufeq(line, "chains=")) {
          553       while (buf_getline(list, line) == 0 && !bufeq(line, "end chains"))
          554         if (chains) {
          555           buf_cat(chains, line);
          556           buf_nl(chains);
          557         }
          558     }
          559     if (status && bufleft(line, "status="))
          560       *status = line->data[7] - '0';
          561     if (bufeq(line, "end")) {
          562       err = 0;
          563       break;
          564     }
          565   }
          566 end:
          567   buf_free(line);
          568   return (err);
          569 }
          570 
          571 int nymlist_append(BUFFER *list, char *nym, BUFFER *config, BUFFER *opt,
          572                    BUFFER *name, BUFFER *rblocks, BUFFER *eklist, int status)
          573 {
          574   buf_appends(list, "nym=");
          575   buf_appends(list, nym);
          576   buf_nl(list);
          577   buf_appends(list, "config=");
          578   buf_cat(list, config);
          579   buf_nl(list);
          580   buf_appends(list, "status=");
          581   buf_appendc(list, (byte) (status + '0'));
          582   buf_nl(list);
          583   if (name) {
          584     buf_appends(list, "name=");
          585     buf_cat(list, name);
          586     buf_nl(list);
          587   }
          588   buf_appends(list, "opt=");
          589   buf_cat(list, opt);
          590   buf_nl(list);
          591   buf_appends(list, "chains=\n");
          592   buf_cat(list, rblocks);
          593   buf_appends(list, "end chains\n");
          594   buf_appends(list, "ek=\n");
          595   buf_cat(list, eklist);
          596   buf_appends(list, "end ek\n");
          597   buf_appends(list, "end\n");
          598   return (0);
          599 }
          600 
          601 int nymlist_del(BUFFER *list, char *nym)
          602 {
          603   BUFFER *new;
          604   char thisnym[LINELEN];
          605   BUFFER *config, *ek, *name, *rblocks, *opt;
          606   int thisstatus;
          607 
          608   new = buf_new();
          609   config = buf_new();
          610   ek = buf_new();
          611   name = buf_new();
          612   rblocks = buf_new();
          613   opt = buf_new();
          614 
          615   buf_rewind(list);
          616   while (nymlist_get(list, thisnym, config, ek, opt, name, rblocks,
          617                      &thisstatus) >= 0)
          618     if (!streq(nym, thisnym))
          619       nymlist_append(new, thisnym, config, opt, name, rblocks, ek,
          620                      thisstatus);
          621 
          622   buf_move(list, new);
          623   buf_free(new);
          624   buf_free(name);
          625   buf_free(opt);
          626   buf_free(rblocks);
          627   buf_free(config);
          628   buf_free(ek);
          629   return (0);
          630 }
          631 
          632 int nymlist_getnym(char *nym, BUFFER *config, BUFFER *ek, BUFFER *opt,
          633                    BUFFER *name, BUFFER *rblocks)
          634      /* "nym@nymserver.domain" or "nym@" */
          635 {
          636   BUFFER *nymlist, *userpass;
          637   char n[LINELEN];
          638   int err = -1;
          639   int status;
          640 
          641   nymlist = buf_new();
          642   userpass = buf_new();
          643 
          644   user_pass(userpass);
          645   if (nymlist_read(nymlist) != -1) {
          646     while (nymlist_get(nymlist, n, config, ek, opt, name, rblocks,
          647                        &status) >= 0)
          648       if (streq(nym, n) || (nym[strlen(nym) - 1] == '@' && strleft(n, nym))) {
          649         err = status;
          650         strncpy(nym, n, LINELEN);
          651         break;
          652       }
          653   }
          654   buf_free(userpass);
          655   buf_free(nymlist);
          656   return (err);
          657 }
          658 
          659 int nymlist_getstatus(char *nym)
          660 {
          661   int status;
          662 
          663   if ((status = nymlist_getnym(nym, NULL, NULL, NULL, NULL, NULL)) == 0)
          664     return (status);
          665   else
          666     return (-1);
          667 }
          668 
          669 #endif /* NYMSUPPORT */