/[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 916 - (show annotations) (download)
Sat Aug 13 10:55:14 2005 UTC (7 years, 10 months ago) by rabbi
File MIME type: text/plain
File size: 11768 byte(s)
Added new config directive MINLAT. Remailers will not be chosen in the path for dummy messages or random hops unless their latency is greater than or equal to the MINLAT value. (Default: 5 minutes.)

This is a precautionary measure against broken remailers. It does not affect currently operating remailers at this time.

Suggested by Zax. (Closes #1241903).
1 /* Mixmaster version 3.0 -- (C) 1999 - 2004 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$ */
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

Properties

Name Value
svn:keywords Id

  ViewVC Help
Powered by ViewVC 1.1.5