/[pkg-mixmaster]/trunk/Mix/Src/chain.c
ViewVC logotype

Contents of /trunk/Mix/Src/chain.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 592 - (show annotations) (download)
Mon Sep 29 01:06:54 2003 UTC (9 years, 7 months ago) by weaselp
File MIME type: text/plain
File size: 11590 byte(s)
Ignore 'No reliable remailers' problems when randhopping messages in middleman
mode.  That is better than dropping them.
1 /* Mixmaster version 3 -- (C) 1999 Anonymizer Inc.
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,v 1.16 2003/09/29 01:06:54 weaselp Exp $ */
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] <= ' ' || 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 small enough latency */
204 (type == MSG_NULL || !remailer[i].flags.middle) && /* remailer is not middleman */
205 !remailer[i].flags.star_ex && /* remailer is not excluded from random selection */
206 (remailer[i].flags.post || type != MSG_POST) && /* remailer supports post when this is a post */
207 ((secondtolasthop == -1) || !badchains[secondtolasthop][i]);
208 /* we only have hop or the previous one can send to this (may be random) */
209 randavail += select[i];
210 }
211
212 for (i = 1; i <= DISTANCE; i++)
213 if (i < chainlen && select[chain[i]] && chain[i]) {
214 select[chain[i]] = 0;
215 randavail--;
216 }
217
218 assert(randavail >= 0);
219 if (randavail == 0) {
220 if (ignore_constraints_if_necessary && !constraints_ignored) {
221 errlog(WARNING, "No reliable remailers. Ignoring for randhop\n");
222 constraints_ignored = 1;
223 goto start;
224 };
225 i = -1;
226 } else {
227 do
228 i = rnd_number(maxrem - 1) + 1;
229 while (!select[i]);
230 }
231 return (i);
232 }
233
234 int chain_rand(REMAILER *remailer, int badchains[MAXREM][MAXREM], int maxrem,
235 int thischain[], int chainlen, int t, int ignore_constraints_if_necessary)
236 /* set random chain. returns 0 if not random, 1 if random, -1 on error */
237 /* t... 0 for mixmaster Type II
238 * 1 for cypherpunk Type I
239 */
240 {
241 int hop;
242 int err = 0;
243 int constraints_ignored = 0;
244
245 assert(t == 0 || t == 1);
246
247 start:
248 for (hop = 0; hop < chainlen; hop++)
249 if (thischain[hop] == 0) {
250 int select[MAXREM];
251 int randavail = 0;
252 int i;
253
254 err = 1;
255 if (hop > 0)
256 assert(thischain[hop-1]); /* we already should have chosen a remailer after this one */
257 for (i = 1; i < maxrem; i++) {
258 select[i] = ((remailer[i].flags.mix && t == 0) || /* remailer supports type */
259 (remailer[i].flags.pgp && remailer[i].flags.ek && t == 1)) &&
260 (remailer[i].info[t].reliability >= 100 * MINREL || constraints_ignored ) && /* remailer has sufficient reliability */
261 (remailer[i].info[t].latency <= MAXLAT || constraints_ignored ) && /* remailer has small enough latency */
262 !remailer[i].flags.star_ex && /* remailer is not excluded from random selection */
263 !badchains[i][0] && !badchains[i][thischain[hop-1]] && /* remailer can send to the next one */
264 (hop == chainlen-1 || !badchains[thischain[hop+1]][i]);
265 /* we are at the first hop or the previous one can send to this (may be random) */
266 randavail += select[i];
267 }
268
269 for (i = hop - DISTANCE; i <= hop + DISTANCE; i++)
270 if (i >= 0 && i < chainlen && select[thischain[i]] && thischain[i]) {
271 select[thischain[i]] = 0;
272 randavail--;
273 }
274
275
276 assert(randavail >= 0);
277 if (randavail < 1) {
278 if (ignore_constraints_if_necessary && !constraints_ignored) {
279 errlog(WARNING, "No reliable remailers. Ignoring for randhop\n");
280 constraints_ignored = 1;
281 goto start;
282 };
283 err = -1;
284 goto end;
285 }
286 do
287 thischain[hop] = rnd_number(maxrem - 1) + 1;
288 while (!select[thischain[hop]]);
289 }
290 end:
291 return (err);
292 }
293
294 int mix_encrypt(int type, BUFFER *message, char *chainstr, int numcopies,
295 BUFFER *chainlist)
296 {
297 return (mix2_encrypt(type, message, chainstr, numcopies, 0, chainlist));
298 }
299
300 /* float chain_reliablity(char *chain, int chaintype,
301 char *reliability_string);
302 *
303 * Compute reliablity of a chain.
304 *
305 * We get the reliablity of the chain by multiplying the reliablity of
306 * every remailer in the chain. The return value is the reliablity of
307 * the chain, or a negative number if the reliablity can not be
308 * calculated. There are two reasons why may not be able to calculated
309 * the reliablity: A remailer in the chain is selected randomly, or we
310 * don't have statistics about one of the remailers in the chain.
311 * remailer_type indicates the remailer type:
312 * 0 = Mixmaster, 1 = Cypherpunk
313 *
314 * If reliability_string is non-NULL, the reliability is also returned
315 * as a string in this variable. The size of the string must be at
316 * least 9 characters!
317 *
318 * This function has been added by Gerd Beuster. (gb@uni-koblenz.de)
319 *--------------------------------------------------------------------*/
320
321 float chain_reliability(char *chain, int chaintype,
322 char *reliability_string){
323
324 float acc_reliability = 1; /* Accumulated reliablity */
325 char *name_start, *name_end; /* temporary pointers used
326 in string scanning */
327 char remailer_name[20]; /* The length of the array is taken from mix3.h. */
328 int error = 0;
329 int maxrem;
330 int i;
331 int previous = -1;
332 REMAILER remailer[MAXREM];
333 int badchains[MAXREM][MAXREM];
334
335 /* chaintype 0=mix 1=ek 2=newnym */
336 assert((chaintype == 0) || (chaintype == 1));
337 maxrem = (chaintype == 0 ? mix2_rlist(remailer, badchains) : t1_rlist(remailer, badchains));
338
339 /* Dissect chain */
340 name_start = chain;
341 name_end = chain;
342 while(*name_end != '\0'){ /* While string not scanned completely */
343 do /* Get next remailer */
344 name_end+=sizeof(char);
345 while( (*name_end != ',') && (*name_end != '\0'));
346 strncpy(remailer_name, name_start,
347 (name_end - name_start) / sizeof(char) + 1*sizeof(char));
348 remailer_name[name_end-name_start]='\0';
349 /* Lookup reliablity for remailer remailer_name */
350 for(i=0;
351 (i < maxrem) && (strcmp(remailer[i].name, remailer_name) != 0);
352 i++);
353 if(!strcmp(remailer[i].name, remailer_name)) { /* Found it! */
354 acc_reliability *=
355 ((float) remailer[i].info[chaintype].reliability) / 10000;
356 if (previous != -1) {
357 if (badchains[previous][i] || badchains[0][i])
358 acc_reliability = 0;
359 }
360 previous = i;
361 } else
362 error = 1; /* Did not find this remailer. We can't calculate
363 the reliablity for the whole chain. */
364 name_start = name_end+sizeof(char);
365 }
366
367 if(error || (name_start==name_end))
368 acc_reliability = -1;
369
370 /* Convert reliability into string, if appropriate */
371 if(reliability_string){
372 if(acc_reliability < 0)
373 sprintf(reliability_string, " n/a ");
374 else{
375 sprintf(reliability_string, "%6.2f", acc_reliability*100);
376 *(reliability_string+6*sizeof(char)) = '%';
377 }
378 }
379
380 return acc_reliability;
381 }
382

  ViewVC Help
Powered by ViewVC 1.1.5