URI: 
       tchain.c - mixmaster - mixmaster 3.0 patched for libressl
  HTML git clone git://parazyd.org/mixmaster.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
       ---
       tchain.c (11809B)
       ---
            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    Prepare messages for remailer chain
            9    $Id: chain.c 934 2006-06-24 13:40:39Z rabbi $ */
           10 
           11 
           12 #include "mix3.h"
           13 #include <string.h>
           14 #include <ctype.h>
           15 #include <assert.h>
           16 #include <stdlib.h>
           17 
           18 void clienterr(BUFFER *msgbuf, char *err)
           19 {
           20   if (msgbuf) {
           21     buf_sets(msgbuf, "Error: ");
           22     buf_appends(msgbuf, err);
           23   } else
           24     errlog(ERRORMSG, "%s\n", err);
           25 }
           26 
           27 void parse_badchains(int badchains[MAXREM][MAXREM], char *file, char *startindicator, REMAILER *remailer, int maxrem) {
           28   int i,j;
           29   FILE *list;
           30   char line[LINELEN];
           31 
           32   if (!badchains)
           33     return;
           34 
           35   for (i = 0; i < maxrem; i++ )
           36     for (j = 0; j < maxrem; j++ )
           37       badchains[i][j] = 0;
           38   list = mix_openfile(TYPE2REL, "r");
           39   if (list != NULL) {
           40     while (fgets(line, sizeof(line), list) != NULL &&
           41       !strleft(line, startindicator)) ;
           42     while (fgets(line, sizeof(line), list) != NULL &&
           43       strleft(line, "(")) {
           44       char *left, *right, *tmp;
           45       int lefti, righti;
           46 
           47       left = line + 1;
           48       while (*left == ' ')
           49         left ++;
           50 
           51       tmp = left + 1;
           52       while (*tmp != ' ' && *tmp != '\0' && *tmp != ')')
           53         tmp ++;
           54       if (*tmp == '\0' || *tmp == ')')
           55         /* parsing this line failed */
           56         continue;
           57       *tmp = '\0';
           58 
           59       right = tmp+1;
           60       while (*right == ' ')
           61         right ++;
           62       tmp = right + 1;
           63       while (*tmp != ' ' && *tmp != '\0' && *tmp != ')')
           64         tmp ++;
           65       if (*tmp == '\0')
           66         /* parsing this line failed */
           67         continue;
           68       *tmp = '\0';
           69 
           70       lefti = -1;
           71       righti = -1;
           72       for (i = 1; i < maxrem; i++) {
           73         if (strcmp(remailer[i].name, left) == 0)
           74           lefti = i;
           75         if (strcmp(remailer[i].name, right) == 0)
           76           righti = i;
           77       }
           78       if (strcmp(left, "*") == 0)
           79         lefti = 0;
           80       if (strcmp(right, "*") == 0)
           81         righti = 0;
           82 
           83       if (lefti == -1 || righti == -1)
           84         /* we don't know about one or both remailers */
           85         continue;
           86       badchains[lefti][righti] = 1;
           87     }
           88     fclose(list);
           89     /* If some broken chain includes all remailers (*) mark it broken for
           90      * every single remailer - this simplifies handling in other places */
           91     for (i=1; i < maxrem; i++ ) {
           92       if (badchains[0][i])
           93         for (j=1; j < maxrem; j++ )
           94           badchains[j][i] = 1;
           95       if (badchains[i][0])
           96         for (j=1; j < maxrem; j++ )
           97           badchains[i][j] = 1;
           98     }
           99   }
          100 }
          101 
          102 
          103 int chain_select(int hop[], char *chainstr, int maxrem, REMAILER *remailer,
          104                  int type, BUFFER *feedback)
          105 {
          106   int len = 0;
          107   int i, j, k;
          108   BUFFER *chain, *selected, *addr;
          109   chain = buf_new();
          110   selected = buf_new();
          111   addr = buf_new();
          112 
          113   if (chainstr == NULL || chainstr[0] == '\0')
          114     buf_sets(chain, CHAIN);
          115   else
          116     buf_sets(chain, chainstr);
          117 
          118   /* put the chain backwards: final hop is in hop[0] */
          119 
          120   for (i = chain->length; i >= 0; i--)
          121     if (i == 0 || chain->data[i - 1] == ','
          122         || chain->data[i - 1] == ';' || chain->data[i - 1] == ':') {
          123       for (j = i; isspace(chain->data[j]);)        /* ignore whitespace */
          124         j++;
          125       if (chain->data[j] == '\0')
          126         break;
          127 
          128       if (chain->data[j] == '*')
          129         k = 0;
          130 #if 0
          131       else if (isdigit(chain->data[j]))
          132         k = atoi(chain->data + j);
          133 #endif /* 0 */
          134       else {
          135         buf_sets(selected, chain->data + j);
          136         rfc822_addr(selected, addr);
          137         buf_clear(selected);
          138         buf_getline(addr, selected);
          139         if (!selected->length)
          140           buf_sets(selected, chain->data + j);
          141 
          142         for (k = 0; k < maxrem; k++)
          143           if (((remailer[k].flags.mix && type == 0) ||
          144                (remailer[k].flags.cpunk && type == 1) ||
          145                (remailer[k].flags.newnym && type == 2)) &&
          146               (streq(remailer[k].name, selected->data) ||
          147                strieq(remailer[k].addr, selected->data) ||
          148                (selected->data[0] == '@' && strifind(remailer[k].addr,
          149                                             selected->data))))
          150             break;
          151       }
          152       if (k < 0 || k >= maxrem) {
          153         if (feedback != NULL) {
          154                 buf_appendf(feedback, "No such remailer: %b", selected);
          155                 buf_nl(feedback);
          156         }
          157 #if 0
          158         k = 0;
          159 #else /* end of 0 */
          160         len = -1;
          161         goto end;
          162 #endif /* else not 0 */
          163       }
          164       hop[len++] = k;
          165       if (len >= 20) {          /* array passed in is has length 20 */
          166         if (feedback != NULL) {
          167                 buf_appends(feedback, "Chain too long.\n");
          168         }
          169         break;
          170       }
          171       if (i > 0)
          172         chain->data[i - 1] = '\0';
          173     }
          174 end:
          175   buf_free(chain);
          176   buf_free(selected);
          177   buf_free(addr);
          178   return len;
          179 }
          180 
          181 int chain_randfinal(int type, REMAILER *remailer, int badchains[MAXREM][MAXREM], int maxrem, int rtype, int chain[], int chainlen, int ignore_constraints_if_necessary)
          182 {
          183   int randavail;
          184   int i;
          185   int t;
          186   int select[MAXREM];
          187   int secondtolasthop = (chainlen <= 1 ? -1 : chain[1]);
          188   int constraints_ignored = 0;
          189 
          190   t = rtype;
          191   if (rtype == 2)
          192     t = 1;
          193 
          194 start:
          195   randavail = 0;
          196   /* select a random final hop */
          197   for (i = 1; i < maxrem; i++) {
          198     select[i] = 
          199        ((remailer[i].flags.mix && rtype == 0) ||             /* remailer supports type */
          200          (remailer[i].flags.pgp && remailer[i].flags.ek && rtype == 1) ||
          201          (remailer[i].flags.newnym && rtype == 2)) &&
          202         (remailer[i].info[t].reliability >= 100 * RELFINAL || constraints_ignored ) && /* remailer has sufficient reliability */
          203         (remailer[i].info[t].latency <= MAXLAT || constraints_ignored ) &&             /* remailer has low enough latency */
          204         (remailer[i].info[t].latency >= MINLAT || constraints_ignored ) &&             /* remailer has high enough latency */
          205         (type == MSG_NULL || !remailer[i].flags.middle) &&   /* remailer is not middleman */
          206         !remailer[i].flags.star_ex &&                        /* remailer is not excluded from random selection */
          207         (remailer[i].flags.post || type != MSG_POST) &&      /* remailer supports post when this is a post */
          208         ((secondtolasthop == -1) || !badchains[secondtolasthop][i]);
          209                                      /* we only have hop or the previous one can send to this (may be random) */
          210     randavail += select[i];
          211   }
          212 
          213   for (i = 1; i <= DISTANCE; i++)
          214     if (i < chainlen && select[chain[i]] && chain[i]) {
          215       select[chain[i]] = 0;
          216       randavail--;
          217     }
          218 
          219   assert(randavail >= 0);
          220   if (randavail == 0) {
          221     if (ignore_constraints_if_necessary && !constraints_ignored) {
          222       errlog(WARNING, "No reliable remailers. Ignoring for randhop\n");
          223       constraints_ignored = 1;
          224       goto start;
          225     };
          226     i = -1;
          227   } else {
          228     do
          229       i = rnd_number(maxrem - 1) + 1;
          230     while (!select[i]);
          231   }
          232   return (i);
          233 }
          234 
          235 int chain_rand(REMAILER *remailer, int badchains[MAXREM][MAXREM], int maxrem,
          236                int thischain[], int chainlen, int t, int ignore_constraints_if_necessary)
          237      /* set random chain. returns 0 if not random, 1 if random, -1 on error */
          238 /* t... 0 for mixmaster Type II
          239  *      1 for cypherpunk Type I
          240  */
          241 {
          242   int hop;
          243   int err = 0;
          244   int constraints_ignored = 0;
          245 
          246   assert(t == 0 || t == 1);
          247 
          248 start:
          249   for (hop = 0; hop < chainlen; hop++)
          250     if (thischain[hop] == 0) {
          251       int select[MAXREM];
          252       int randavail = 0;
          253       int i;
          254 
          255       err = 1;
          256       if (hop > 0)
          257         assert(thischain[hop-1]); /* we already should have chosen a remailer after this one */
          258       for (i = 1; i < maxrem; i++) {
          259         select[i] = ((remailer[i].flags.mix && t == 0) ||        /* remailer supports type */
          260                      (remailer[i].flags.pgp && remailer[i].flags.ek && t == 1)) &&
          261           (remailer[i].info[t].reliability >= 100 * MINREL || constraints_ignored ) &&  /* remailer has sufficient reliability */
          262           (remailer[i].info[t].latency <= MAXLAT || constraints_ignored ) &&            /* remailer has low enough latency */
          263           (remailer[i].info[t].latency >= MINLAT || constraints_ignored ) &&            /* remailer has high enough latency */
          264           !remailer[i].flags.star_ex &&                          /* remailer is not excluded from random selection */
          265           !badchains[i][0] && !badchains[i][thischain[hop-1]] && /* remailer can send to the next one */
          266           (hop == chainlen-1 || !badchains[thischain[hop+1]][i]);
          267                                    /* we are at the first hop or the previous one can send to this (may be random) */
          268         randavail += select[i];
          269       }
          270 
          271       for (i = hop - DISTANCE; i <= hop + DISTANCE; i++)
          272         if (i >= 0 && i < chainlen && select[thischain[i]] && thischain[i]) {
          273           select[thischain[i]] = 0;
          274           randavail--;
          275         }
          276 
          277 
          278       assert(randavail >= 0);
          279       if (randavail < 1) {
          280         if (ignore_constraints_if_necessary && !constraints_ignored) {
          281           errlog(WARNING, "No reliable remailers. Ignoring for randhop\n");
          282           constraints_ignored = 1;
          283           goto start;
          284         };
          285         err = -1;
          286         goto end;
          287       }
          288       do
          289         thischain[hop] = rnd_number(maxrem - 1) + 1;
          290       while (!select[thischain[hop]]);
          291     }
          292 end:
          293   return (err);
          294 }
          295 
          296 int mix_encrypt(int type, BUFFER *message, char *chainstr, int numcopies,
          297                 BUFFER *chainlist)
          298 {
          299   return (mix2_encrypt(type, message, chainstr, numcopies, 0, chainlist));
          300 }
          301 
          302 /* float chain_reliablity(char *chain, int chaintype,
          303                           char *reliability_string);
          304  *
          305  * Compute reliablity of a chain.
          306  *
          307  * We get the reliablity of the chain by multiplying the reliablity of
          308  * every remailer in the chain. The return value is the reliablity of
          309  * the chain, or a negative number if the reliablity can not be
          310  * calculated. There are two reasons why may not be able to calculated
          311  * the reliablity: A remailer in the chain is selected randomly, or we
          312  * don't have statistics about one of the remailers in the chain.
          313  * remailer_type indicates the remailer type:
          314  * 0 = Mixmaster, 1 = Cypherpunk
          315  *
          316  * If reliability_string is non-NULL, the reliability is also returned
          317  * as a string in this variable. The size of the string must be at
          318  * least 9 characters!
          319  *
          320  * This function has been added by Gerd Beuster. (gb@uni-koblenz.de)
          321  *--------------------------------------------------------------------*/
          322 
          323 float chain_reliability(char *chain, int chaintype,
          324                         char *reliability_string){
          325 
          326   float acc_reliability = 1; /* Accumulated reliablity */
          327   char *name_start, *name_end; /* temporary pointers used
          328                                  in string scanning */
          329   char remailer_name[20]; /* The length of the array is taken from mix3.h. */
          330   int error = 0;
          331   int maxrem;
          332   int i;
          333   int previous = -1;
          334   REMAILER remailer[MAXREM];
          335   int badchains[MAXREM][MAXREM];
          336 
          337   /* chaintype 0=mix 1=ek 2=newnym */
          338   assert((chaintype == 0) || (chaintype == 1));
          339   maxrem = (chaintype == 0 ? mix2_rlist(remailer, badchains) : t1_rlist(remailer, badchains));
          340 
          341   /* Dissect chain */
          342   name_start = chain;
          343   name_end = chain;
          344   while(*name_end != '\0'){ /* While string not scanned completely */
          345     do /* Get next remailer */
          346       name_end+=sizeof(char);
          347     while( (*name_end != ',') && (*name_end != '\0'));
          348     strncpy(remailer_name, name_start,
          349             (name_end - name_start) / sizeof(char) + 1*sizeof(char));
          350     remailer_name[name_end-name_start]='\0';
          351     /* Lookup reliablity for remailer remailer_name */
          352     for(i=0;
          353         (i < maxrem) && (strcmp(remailer[i].name, remailer_name) != 0);
          354         i++);
          355     if(!strcmp(remailer[i].name, remailer_name)) { /* Found it! */
          356       acc_reliability *=
          357         ((float) remailer[i].info[chaintype].reliability) / 10000;
          358       if (previous != -1) {
          359         if (badchains[previous][i] || badchains[0][i])
          360           acc_reliability = 0;
          361       }
          362       previous = i;
          363     } else
          364       error = 1; /* Did not find this remailer. We can't calculate
          365                     the reliablity for the whole chain. */
          366     name_start = name_end+sizeof(char);
          367   }
          368 
          369   if(error || (name_start==name_end))
          370     acc_reliability = -1;
          371 
          372   /* Convert reliability into string, if appropriate */
          373   if(reliability_string){
          374     if(acc_reliability < 0)
          375       sprintf(reliability_string, "  n/a  ");
          376     else{
          377       sprintf(reliability_string, "%6.2f", acc_reliability*100);
          378       *(reliability_string+6*sizeof(char)) = '%';
          379     }
          380   }
          381 
          382   return acc_reliability;
          383 }
          384