URI: 
       tchain1.c - mixmaster - mixmaster 3.0 patched for libressl
  HTML git clone git://parazyd.org/mixmaster.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
       ---
       tchain1.c (8551B)
       ---
            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    Encrypt message for Cypherpunk remailer chain
            9    $Id: chain1.c 934 2006-06-24 13:40:39Z rabbi $ */
           10 
           11 
           12 #include "mix3.h"
           13 #include "pgp.h"
           14 #include <string.h>
           15 #include <ctype.h>
           16 
           17 #define N(X) (isdigit(X) ? (X)-'0' : 0)
           18 
           19 int t1_rlist(REMAILER remailer[], int badchains[MAXREM][MAXREM])
           20 {
           21   FILE *list, *excl;
           22   int i, listed = 0;
           23   int n = 0;
           24   char line[2 * LINELEN], l2[LINELEN], name[LINELEN], *flags;
           25   BUFFER *starex;
           26 
           27   starex = buf_new();
           28   excl = mix_openfile(STAREX, "r");
           29   if (excl != NULL) {
           30     buf_read(starex, excl);
           31     fclose(excl);
           32   }
           33 
           34   list = mix_openfile(TYPE1LIST, "r");
           35   if (list == NULL) {
           36     buf_free(starex);
           37     return (-1);
           38   }
           39 
           40   while (fgets(line, sizeof(line), list) != NULL && n < MAXREM) {
           41     if (strleft(line, "$remailer") &&
           42         strchr(line, '<') && strchr(line, '>') &&
           43         strchr(line, '{') && strchr(line, '{') + 4 < strchr(line, '}')) {
           44       if (line[strlen(line) - 1] == '\n')
           45         line[strlen(line) - 1] = '\0';
           46       if (line[strlen(line) - 1] == '\r')
           47         line[strlen(line) - 1] = '\0';
           48       while (line[strlen(line) - 1] == ' ')
           49         line[strlen(line) - 1] = '\0';
           50       if (line[strlen(line) - 1] != ';'
           51           && fgets(l2, sizeof(l2), list) != NULL)
           52         strcatn(line, l2, LINELEN);
           53       flags = strchr(line, '>');
           54       strncpy(name, strchr(line, '{') + 2,
           55               strchr(line, '}') - strchr(line, '{') - 3);
           56       name[strchr(line, '}') - strchr(line, '{') - 3] = '\0';
           57       name[20] = '\0';
           58 
           59       for (i = 1; i <= n; i++)
           60         if (streq(name, remailer[i].name))
           61           break;
           62       if (i > n) {
           63         /* not in mix list */
           64         n++;
           65         strcpy(remailer[i].name, name);
           66         strncpy(remailer[i].addr, strchr(line, '<') + 1,
           67                 strchr(line, '>') - strchr(line, '<'));
           68         remailer[i].addr[strchr(line, '>') - strchr(line, '<') - 1]
           69           = '\0';
           70         remailer[i].flags.mix = 0;
           71         remailer[i].flags.post = strifind(flags, " post");
           72       }
           73       remailer[i].flags.cpunk = strfind(flags, " cpunk");
           74       remailer[i].flags.pgp = strfind(flags, " pgp");
           75       remailer[i].flags.pgponly = strfind(flags, " pgponly");
           76       remailer[i].flags.latent = strfind(flags, " latent");
           77       remailer[i].flags.middle = strfind(flags, " middle");
           78       remailer[i].flags.ek = strfind(flags, " ek");
           79       remailer[i].flags.esub = strfind(flags, " esub");
           80       remailer[i].flags.newnym = strfind(flags, " newnym");
           81       remailer[i].flags.nym = strfind(flags, " nym");
           82       remailer[i].info[1].reliability = 0;
           83       remailer[i].info[1].latency = 0;
           84       remailer[i].info[1].history[0] = '\0';
           85       remailer[i].flags.star_ex = bufifind(starex, name);
           86    }
           87     if (strleft(line,
           88                 "-----------------------------------------------------------------------"))
           89       break;
           90   }
           91   n++;                                /* ?? */
           92   while (fgets(line, sizeof(line), list) != NULL) {
           93     if (strlen(line) >= 72 && strlen(line) <= 73)
           94       for (i = 1; i < n; i++)
           95         if (strleft(line, remailer[i].name) &&
           96             line[strlen(remailer[i].name)] == ' ') {
           97           strncpy(remailer[i].info[1].history, line + 42, 12);
           98           remailer[i].info[1].history[12] = '\0';
           99           remailer[i].info[1].reliability = 10000 * N(line[64])
          100             + 1000 * N(line[65]) + 100 * N(line[66])
          101             + 10 * N(line[68]) + N(line[69]);
          102           remailer[i].info[1].latency = 36000 * N(line[55])
          103             + 3600 * N(line[56]) + 600 * N(line[58])
          104             + 60 * N(line[59]) + 10 * N(line[61])
          105             + N(line[62]);
          106           listed++;
          107         }
          108   }
          109   fclose(list);
          110   parse_badchains(badchains, TYPE1LIST, "Broken type-I remailer chains", remailer, n);
          111   if (listed < 4)                /* we have no valid reliability info */
          112     for (i = 1; i < n; i++)
          113       remailer[i].info[1].reliability = 10000;
          114 
          115 #ifdef USE_PGP
          116   pgp_rlist(remailer, n);
          117 #endif /* USE_PGP */
          118   buf_free(starex);
          119   return (n);
          120 }
          121 
          122 int t1_ek(BUFFER *key, BUFFER *seed, int num)
          123 {
          124   buf_reset(key);
          125   buf_appendc(key, (byte) num);
          126   buf_cat(key, seed);
          127   digest_md5(key, key);
          128   encode(key, 0);
          129 #ifdef DEBUG
          130   fprintf(stderr, "passphrase=%s (%2X%2X%2X%2X %d)\n", key->data,
          131           seed->data[0], seed->data[1], seed->data[2], seed->data[3], num);
          132 #endif /* DEBUG */
          133   return (0);
          134 }
          135 
          136 int t1_encrypt(int type, BUFFER *message, char *chainstr, int latency,
          137                BUFFER *ek, BUFFER *feedback)
          138 {
          139   BUFFER *b, *rem, *dest, *line, *field, *content;
          140   REMAILER remailer[MAXREM];
          141   int badchains[MAXREM][MAXREM];
          142   int maxrem, chainlen = 0;
          143   int chain[20];
          144   int hop;
          145   int hashmark = 0;
          146   int err = 0;
          147 
          148   b = buf_new();
          149   rem = buf_new();
          150   dest = buf_new();
          151   line = buf_new();
          152   field = buf_new();
          153   content = buf_new();
          154 
          155   maxrem = t1_rlist(remailer, badchains);
          156   if (maxrem < 1) {
          157     clienterr(feedback, "No remailer list!");
          158     err = -1;
          159     goto end;
          160   }
          161   chainlen = chain_select(chain, chainstr, maxrem, remailer, 1, line);
          162   if (chainlen < 1) {
          163     if (line->length)
          164       clienterr(feedback, line->data);
          165     else
          166       clienterr(feedback, "Invalid remailer chain!");
          167     err = -1;
          168     goto end;
          169   }
          170   if (chain[0] == 0)
          171     chain[0] = chain_randfinal(type, remailer, badchains, maxrem, 1, chain, chainlen, 0);
          172 
          173   if (chain[0] == -1) {
          174     clienterr(feedback, "Invalid remailer chain!");
          175     err = -1;
          176     goto end;
          177   }
          178   if (chain_rand(remailer, badchains, maxrem, chain, chainlen, 1, 0) == -1) {
          179     clienterr(feedback, "No reliable remailers!");
          180     err = -1;
          181     goto end;
          182   }
          183   while (buf_getheader(message, field, content) == 0) {
          184     hdr_encode(content, 0);
          185     if (type == MSG_POST && bufieq(field, "newsgroups") &&
          186         remailer[chain[0]].flags.post) {
          187       buf_appendf(dest, "Anon-Post-To: %b\n", content);
          188     } else if (type == MSG_MAIL && bufieq(field, "to")) {
          189       buf_appendf(dest, "Anon-To: %b\n", content);
          190     } else {
          191       /* paste header */
          192       if (type == MSG_POST && bufieq(field, "newsgroups"))
          193         buf_appendf(dest, "Anon-To: %s\n", MAILtoNEWS);
          194       if (hashmark == 0) {
          195         buf_appends(b, "##\n");
          196         hashmark = 1;
          197       }
          198       buf_appendheader(b, field, content);
          199     }
          200   }
          201   buf_nl(b);
          202   buf_rest(b, message);
          203   buf_move(message, b);
          204 
          205   if (type != MSG_NULL && dest->length == 0) {
          206     clienterr(feedback, "No destination address!");
          207     err = -1;
          208     goto end;
          209   }
          210   if (type == MSG_NULL) {
          211     buf_sets(dest, "Null:\n");
          212   }
          213   for (hop = 0; hop < chainlen; hop++) {
          214     if (hop == 0) {
          215       buf_sets(b, "::\n");
          216       buf_cat(b, dest);
          217     } else {
          218       buf_sets(b, "::\nAnon-To: ");
          219       buf_appends(b, remailer[chain[hop - 1]].addr);
          220       buf_nl(b);
          221     }
          222     if (remailer[chain[hop]].flags.latent && latency > 0)
          223       buf_appendf(b, "Latent-Time: +%d:00r\n", latency);
          224     if (ek && remailer[chain[hop]].flags.ek) {
          225       t1_ek(line, ek, hop);
          226       buf_appendf(b, "Encrypt-Key: %b\n", line);
          227     }
          228     buf_nl(b);
          229     buf_cat(b, message);
          230 #ifdef USE_PGP
          231     if (remailer[chain[hop]].flags.pgp) {
          232       buf_clear(message);
          233       buf_clear(rem);
          234       buf_setf(rem, "<%s>", remailer[chain[hop]].addr);
          235       err = pgp_encrypt(PGP_ENCRYPT | PGP_REMAIL | PGP_TEXT, b, rem,
          236                         NULL, NULL, NULL, NULL);
          237       if (err < 0) {
          238         buf_setf(line, "No PGP key for remailer %s!\n",
          239                  remailer[chain[hop]].name);
          240         clienterr(feedback, line->data);
          241         goto end;
          242       }
          243       buf_appends(message, "::\nEncrypted: PGP\n\n");
          244       buf_cat(message, b);
          245     } else
          246 #endif /* USE_PGP */
          247     {
          248       if (remailer[chain[hop]].flags.pgponly) {
          249         buf_setf(line, "PGP encryption needed for remailer %s!\n",
          250                  remailer[chain[hop]].name);
          251         clienterr(feedback, line->data);
          252         goto end;
          253       }
          254       buf_move(message, b);
          255     }
          256     if (ek && remailer[chain[hop]].flags.ek)
          257       buf_appends(message, "\n**\n");
          258   }
          259   buf_clear(b);
          260   if (chainlen == 0) {
          261     buf_appends(b, "::\n");
          262     buf_cat(b, dest);
          263   } else {
          264     buf_appendf(b, "%s: %s\n", ek ? "::\nAnon-To" : "To",
          265                 remailer[chain[chainlen - 1]].addr);
          266   }
          267   buf_nl(b);
          268   buf_cat(b, message);
          269   buf_move(message, b);
          270 end:
          271   buf_free(b);
          272   buf_free(rem);
          273   buf_free(dest);
          274   buf_free(line);
          275   buf_free(field);
          276   buf_free(content);
          277   return (err);
          278 }
          279 
          280 #ifdef USE_PGP
          281 int t1_getreply(BUFFER *msg, BUFFER *ek, int len)
          282 {
          283   BUFFER *key, *decrypt;
          284   int err = -1;
          285   int hop = 0;
          286 
          287   key = buf_new();
          288   decrypt = buf_new();
          289 
          290   do {
          291     t1_ek(key, ek, hop);
          292     buf_set(decrypt, msg);
          293     if (pgp_decrypt(decrypt, key, NULL, NULL, NULL) == 0
          294         && decrypt->data != NULL)
          295       err = 0, buf_move(msg, decrypt);
          296   }
          297   while (hop++ < len);
          298   return (err);
          299 }
          300 
          301 #endif /* USE_PGP */