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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 168 - (hide annotations) (download)
Thu Aug 22 05:18:26 2002 UTC (10 years, 9 months ago) by weaselp
File MIME type: text/plain
File size: 12098 byte(s)
List known mixmasters in remailer-conf replies. How do I get a list of
the pgp keyring so I can also list type I remailers? Do we need to list
type I remailers?
1 rabbi 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     Encrypt message for Mixmaster chain
9 weaselp 168 $Id: chain2.c,v 1.3 2002/08/22 05:18:26 weaselp Exp $ */
10 rabbi 1
11    
12     #include "mix3.h"
13     #include <string.h>
14     #include <stdlib.h>
15     #include <time.h>
16     #include <ctype.h>
17     #include <assert.h>
18    
19     #ifdef USE_RSA
20    
21     #define N(X) (isdigit(X) ? (X)-'0' : 0)
22    
23 weaselp 168 int prepare_type2list(BUFFER *out)
24 rabbi 101 {
25     FILE *list;
26     char line[LINELEN], name[LINELEN], addr[LINELEN], keyid[LINELEN],
27     version[LINELEN], flags[LINELEN];
28    
29     list = mix_openfile(TYPE2LIST, "r");
30     if (list == NULL) {
31     list = mix_openfile(PUBRING, "r");
32     if (list == NULL)
33     return (-1);
34     }
35     while (fgets(line, sizeof(line), list) != NULL) {
36     if (strleft(line, begin_key)) {
37     while (fgets(line, sizeof(line), list) != NULL &&
38     !strleft(line, end_key)) ;
39     } else if (strlen(line) > 36 && line[0] != '#') {
40     if (sscanf(line, "%127s %127s %127s %127s %127s", name,
41     addr, keyid, version, flags) < 4)
42     continue;
43 weaselp 168 buf_appends(out, line);
44 rabbi 101 }
45     }
46     fclose(list);
47     return (0);
48     }
49    
50 rabbi 1 int mix2_rlist(REMAILER remailer[])
51     {
52     FILE *list;
53     int n, i, listed = 0;
54    
55     char line[LINELEN], name[LINELEN], addr[LINELEN], keyid[LINELEN],
56     version[LINELEN], flags[LINELEN];
57    
58     list = mix_openfile(TYPE2LIST, "r");
59     if (list == NULL) {
60     list = mix_openfile(PUBRING, "r");
61     if (list == NULL)
62     return (-1);
63     }
64     for (n = 1; fgets(line, sizeof(line), list) != NULL && n < MAXREM;)
65     if (strleft(line, begin_key)) {
66     while (fgets(line, sizeof(line), list) != NULL &&
67     !strleft(line, end_key)) ;
68     } else if (strlen(line) > 36 && line[0] != '#') {
69     flags[0] = '\0';
70     if (sscanf(line, "%127s %127s %127s %127s %127s", name,
71     addr, keyid, version, flags) < 4)
72     continue;
73     strncpy(remailer[n].name, name, sizeof(remailer[n].name));
74     remailer[n].name[sizeof(remailer[n].name) - 1] = '\0';
75     strncpy(remailer[n].addr, addr, sizeof(remailer[n].addr));
76     remailer[n].addr[sizeof(remailer[n].addr) - 1] = '\0';
77     remailer[n].flags.mix = 1;
78     remailer[n].flags.cpunk = 0;
79     remailer[n].flags.nym = 0;
80     remailer[n].flags.newnym = 0;
81     id_decode(keyid, remailer[n].keyid);
82     remailer[n].version = N(version[0]);
83     remailer[n].flags.compress = strfind(flags, "C");
84     remailer[n].flags.post = strfind(flags, "N");
85     remailer[n].flags.middle = strfind(flags, "M");
86     remailer[n].info[0].reliability = 0;
87     remailer[n].info[0].latency = 0;
88     remailer[n].info[0].history[0] = '\0';
89     n++;
90     }
91     fclose(list);
92     list = mix_openfile(TYPE2REL, "r");
93     if (list != NULL) {
94     while (fgets(line, sizeof(line), list) != NULL &&
95     !strleft(line, "--------------------------------------------")) ;
96     while (fgets(line, sizeof(line), list) != NULL &&
97     !strleft(line, "</PRE>"))
98     if (strlen(line) >= 44 && strlen(line) <= 46)
99     for (i = 1; i < n; i++)
100     if (strleft(line, remailer[i].name) &&
101     line[strlen(remailer[i].name)] == ' ') {
102     strncpy(remailer[i].info[0].history, line + 15, 12);
103     remailer[i].info[0].history[12] = '\0';
104     remailer[i].info[0].reliability = 10000 * N(line[37])
105     + 1000 * N(line[38]) + 100 * N(line[39])
106     + 10 * N(line[41]) + N(line[42]);
107     remailer[i].info[0].latency = 36000 * N(line[28])
108     + 3600 * N(line[29]) + 600 * N(line[31])
109     + 60 * N(line[32]) + 10 * N(line[34])
110     + N(line[35]);
111     listed++;
112     }
113     fclose(list);
114     }
115     if (listed < 4) /* we have no valid reliability info */
116     for (i = 1; i < n; i++)
117     remailer[i].info[0].reliability = 10000;
118     return (n);
119     }
120    
121     static int send_packet(int numcopies, BUFFER *packet, int chain[],
122     int chainlen, int packetnum, int numpackets,
123     BUFFER *mid, REMAILER remailer[], int maxrem,
124     BUFFER *feedback)
125     {
126     BUFFER *pid, *out, *header, *other, *encrypted, *key, *body;
127     BUFFER *iv, *ivarray, *temp;
128     BUFFER *pubkey;
129     char addr[LINELEN];
130     int thischain[20];
131     int hop;
132     int c, i;
133     int timestamp = 0;
134     int israndom = 0;
135     int err = 1;
136    
137     body = buf_new();
138     pid = buf_new();
139     out = buf_new();
140     header = buf_new();
141     other = buf_new();
142     key = buf_new();
143     encrypted = buf_new();
144     iv = buf_new();
145     ivarray = buf_new();
146     temp = buf_new();
147    
148     buf_setrnd(pid, 16);
149    
150     for (c = 0; c < numcopies; c++) {
151     buf_set(body, packet);
152    
153     for (hop = 0; hop < chainlen; hop++)
154     thischain[hop] = chain[hop];
155    
156     israndom = chain_rand(remailer, maxrem, thischain, chainlen, 0);
157     if (israndom == -1) {
158     err = -1;
159     clienterr(feedback, "No reliable remailers!");
160     }
161     if ((numcopies > 1 || numpackets > 1) && !israndom && (chainlen != 1)) {
162     clienterr(feedback,
163     "Multi-packet message without random remailers!");
164     err = -1;
165     goto end;
166     }
167     for (hop = 0; hop < chainlen; hop++) {
168     switch (remailer[thischain[hop]].version) {
169     case 2:
170     case 3: /* not implemented yet; fall back to version 2 */
171     /* create header chart to be encrypted with the session key */
172     if (numcopies > 1 && hop == 0)
173     buf_set(encrypted, pid); /* same ID only at final hop */
174     else
175     buf_setrnd(encrypted, 16);
176     buf_setrnd(key, 24); /* key for encrypting the body */
177     buf_cat(encrypted, key);
178     buf_setrnd(iv, 8); /* IV for encrypting the body */
179    
180     if (hop > 0) {
181     /* IVs for header chart encryption */
182     buf_setrnd(ivarray, 18 * 8);
183     buf_cat(ivarray, iv); /* 19th IV equals the body IV */
184    
185     buf_appendc(encrypted, 0);
186     buf_cat(encrypted, ivarray);
187     memset(addr, 0, 80);
188     strcpy(addr, remailer[thischain[hop - 1]].addr);
189     buf_append(encrypted, addr, 80);
190     } else {
191     if (numpackets == 1)
192     buf_appendc(encrypted, 1);
193     else {
194     buf_appendc(encrypted, 2);
195     buf_appendc(encrypted, (byte) packetnum);
196     buf_appendc(encrypted, (byte) numpackets);
197     }
198     buf_cat(encrypted, mid);
199     buf_cat(encrypted, iv); /* body encryption IV */
200     }
201    
202     /* timestamp */
203     buf_appends(encrypted, "0000");
204     buf_appendc(encrypted, '\0'); /* timestamp magic */
205     timestamp = time(NULL) / SECONDSPERDAY - rnd_number(4);
206     buf_appendi_lo(encrypted, timestamp);
207    
208     /* message digest for this header */
209     digest_md5(encrypted, temp);
210     buf_cat(encrypted, temp);
211     buf_pad(encrypted, 328);
212    
213     /* encrypt message body */
214     buf_crypt(body, key, iv, ENCRYPT);
215    
216     if (hop > 0) {
217     /* encrypt the other header charts */
218     buf_clear(other);
219     for (i = 0; i < 19; i++) {
220     buf_clear(iv);
221     buf_clear(temp);
222     buf_append(iv, ivarray->data + 8 * i, 8);
223     buf_append(temp, header->data + 512 * i, 512);
224     buf_crypt(temp, key, iv, ENCRYPT);
225     buf_cat(other, temp);
226     }
227     } else
228     buf_setrnd(other, 19 * 512); /* fill with random data */
229    
230     /* create session key and IV to encrypt the header ... */
231     buf_setrnd(key, 24);
232     buf_setrnd(iv, 8);
233     buf_crypt(encrypted, key, iv, ENCRYPT);
234     pubkey = buf_new();
235     err = db_getpubkey(remailer[thischain[hop]].keyid, pubkey);
236     if (err == -1)
237     goto end;
238     err = pk_encrypt(key, pubkey); /* ... and encrypt the
239     session key */
240     buf_free(pubkey);
241     if (err == -1 || key->length != 128) {
242     clienterr(feedback, "Encryption failed!");
243     err = -1;
244     goto end;
245     }
246     /* now build the new header */
247     buf_clear(header);
248     buf_append(header, remailer[thischain[hop]].keyid, 16);
249     buf_appendc(header, 128);
250     buf_cat(header, key);
251     buf_cat(header, iv);
252     buf_cat(header, encrypted);
253     buf_pad(header, 512);
254     buf_cat(header, other);
255     break;
256     default:
257     err = -1;
258     goto end;
259     }
260     }
261    
262     /* build the message */
263     buf_sets(out, remailer[thischain[chainlen - 1]].addr);
264     buf_nl(out);
265     buf_cat(out, header);
266     buf_cat(out, body);
267     assert(header->length == 10240 && body->length == 10240);
268     mix_pool(out, INTERMEDIATE, -1);
269    
270     if (feedback) {
271     for (hop = chainlen - 1; hop >= 0; hop--) {
272     buf_appends(feedback, remailer[thischain[hop]].name);
273     if (hop > 0)
274     buf_appendc(feedback, ',');
275     }
276     buf_nl(feedback);
277     }
278     }
279     end:
280     buf_free(pid);
281     buf_free(body);
282     buf_free(out);
283     buf_free(header);
284     buf_free(temp);
285     buf_free(other);
286     buf_free(key);
287     buf_free(encrypted);
288     buf_free(iv);
289     buf_free(ivarray);
290     return (err);
291     }
292    
293     int mix2_encrypt(int type, BUFFER *message, char *chainstr, int numcopies,
294     BUFFER *feedback)
295     {
296     /* returns 0 on success, -1 on error. feedback contains the selected
297     remailer chain or an error message */
298    
299     REMAILER remailer[MAXREM];
300     int maxrem;
301     BUFFER *line, *field, *content, *header, *msgdest, *msgheader, *body,
302     *temp, *mid;
303     byte numdest = 0, numhdr = 0;
304     char hdrline[LINELEN];
305     BUFFER *packet;
306     int chain[20];
307     int chainlen;
308     int i;
309     int err = 0;
310    
311     mix_init(NULL);
312     packet = buf_new();
313     line = buf_new();
314     field = buf_new();
315     content = buf_new();
316     msgheader = buf_new();
317     msgdest = buf_new();
318     body = buf_new();
319     temp = buf_new();
320     mid = buf_new();
321     header = buf_new();
322     if (feedback)
323     buf_reset(feedback);
324    
325     if (numcopies == 0)
326     numcopies = NUMCOPIES;
327     if (numcopies > 10)
328     numcopies = 10;
329    
330     maxrem = mix2_rlist(remailer);
331     if (maxrem < 1) {
332     clienterr(feedback, "No remailer list!");
333     err = -1;
334     goto end;
335     }
336     chainlen = chain_select(chain, chainstr, maxrem, remailer, 0, line);
337     if (chainlen < 1) {
338     if (line->length)
339     clienterr(feedback, line->data);
340     else
341     clienterr(feedback, "Invalid remailer chain!");
342     err = -1;
343     goto end;
344     }
345     if (chain[0] == 0)
346     chain[0] = chain_randfinal(type, remailer, maxrem, 0);
347    
348     if (chain[0] == -1) {
349     clienterr(feedback, "No reliable remailers!");
350     err = -1;
351     goto end;
352     }
353     switch (remailer[chain[0]].version) {
354     case 2:
355     if (type == MSG_NULL) {
356     memset(hdrline, 0, 80);
357     strcpy(hdrline, "null:");
358     buf_append(msgdest, hdrline, 80);
359     numdest++;
360     } else
361     while (buf_getheader(message, field, content) == 0) {
362     if (bufieq(field, "to")) {
363     memset(hdrline, 0, 80);
364     strncpy(hdrline, content->data, 80);
365     buf_append(msgdest, hdrline, 80);
366     numdest++;
367     } else if (type == MSG_POST && bufieq(field, "newsgroups")) {
368     memset(hdrline, 0, 80);
369     strcpy(hdrline, "post: ");
370     strcatn(hdrline, content->data, 80);
371     buf_append(msgdest, hdrline, 80);
372     numdest++;
373     } else {
374     buf_clear(header);
375     buf_appendheader(header, field, content);
376     hdr_encode(header, 80);
377     while (buf_getline(header, line) == 0) {
378     /* paste in encoded header entry */
379     memset(hdrline, 0, 80);
380     strncpy(hdrline, line->data, 80);
381     buf_append(msgheader, hdrline, 80);
382     numhdr++;
383     }
384     }
385     }
386     buf_appendc(body, numdest);
387     buf_cat(body, msgdest);
388     buf_appendc(body, numhdr);
389     buf_cat(body, msgheader);
390    
391     if (type != MSG_NULL) {
392     buf_rest(temp, message);
393     if (temp->length > 10236 && remailer[chain[0]].flags.compress)
394     buf_compress(temp);
395     buf_cat(body, temp);
396     buf_reset(temp);
397     }
398     buf_setrnd(mid, 16); /* message ID */
399     for (i = 0; i <= body->length / 10236; i++) {
400     long length;
401    
402     length = body->length - i * 10236;
403     if (length > 10236)
404     length = 10236;
405     buf_clear(packet);
406     buf_appendl_lo(packet, length);
407     buf_append(packet, body->data + i * 10236, length);
408     buf_pad(packet, 10240);
409     if (send_packet(numcopies, packet, chain, chainlen,
410     i + 1, body->length / 10236 + 1,
411     mid, remailer, maxrem, feedback) == -1)
412     err = -1;
413     }
414     break;
415     case 3:
416     NOT_IMPLEMENTED;
417     break;
418     default:
419     clienterr(feedback, "Unknown remailer version!");
420     err = -1;
421     }
422    
423     end:
424     buf_free(packet);
425     buf_free(line);
426     buf_free(field);
427     buf_free(content);
428     buf_free(header);
429     buf_free(msgheader);
430     buf_free(msgdest);
431     buf_free(body);
432     buf_free(temp);
433     buf_free(mid);
434     return (err);
435     }
436    
437     #else
438    
439     int mix2_rlist(REMAILER remailer[])
440     {
441     return (0);
442     }
443    
444     int mix2_encrypt(int type, BUFFER *message, char *chainstr, int numcopies,
445     BUFFER *feedback)
446     {
447     return (-1);
448     }
449     #endif

  ViewVC Help
Powered by ViewVC 1.1.5