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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 82 - (show annotations) (download)
Tue Jul 9 08:02:02 2002 UTC (10 years, 10 months ago) by rabbi
File MIME type: text/plain
File size: 10154 byte(s)
The format of id.log is now binary. Mixmaster still performs a linear
search on it for duplicate checking, but this should improve performance
on slower systems over having the entries stored in a text file.

We had considered using a hash table, but id.log entries only matter up to
7 days anyway, so there isn't too much more to be gained. Perhaps if we
had Mixmaster on cell phones... ;)

Thanks to Disastry for this patch.
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 Process Mixmaster remailer messages
9 $Id: rem2.c,v 1.2 2002/07/09 08:02:02 rabbi Exp $ */
10
11
12 #include "mix3.h"
13 #include <string.h>
14 #include <time.h>
15 #include <ctype.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #ifdef POSIX
19 #include <unistd.h>
20 #else
21 #include <io.h>
22 #endif
23 #ifndef _MSC
24 #include <dirent.h>
25 #endif
26 #include <assert.h>
27
28 int mix_dearmor(BUFFER *in, BUFFER *out)
29 {
30 BUFFER *line, *md;
31 int tempbuf = 0;
32 int err = 0;
33
34 line = buf_new();
35 md = buf_new();
36
37 if (in == out) {
38 tempbuf = 1;
39 out = buf_new();
40 }
41 do {
42 err = buf_getline(in, line);
43 if (err == -1)
44 goto end;
45 }
46 while (!bufeq(line, begin_remailer));
47
48 do {
49 /* skip lines before message digest */
50 if (buf_getline(in, md) == -1)
51 break;
52 } while (strlen(md->data) != 24);
53
54 decode(in, out);
55
56 err = buf_getline(in, line);
57 if (err != 0 || !bufeq(line, end_remailer))
58 err = -1;
59 else {
60 digest_md5(out, line);
61 encode(line, 0);
62 if (!buf_eq(md, line))
63 err = -1;
64 if (out->length != 20480)
65 err = -1;
66 }
67
68 end:
69 if (err == -1)
70 errlog(NOTICE, "Malformatted message.\n");
71
72 if (tempbuf) {
73 buf_move(in, out);
74 buf_free(out);
75 }
76 buf_free(line);
77 buf_free(md);
78 return (err);
79 }
80
81 #ifdef USE_RSA
82
83 static int isnewid(BUFFER *id, long timestamp)
84 {
85 FILE *f;
86 int ret = 1;
87 long now, old = 0;
88 LOCK *i = NULL;
89 idlog_t idbuf;
90
91 now = time(NULL);
92
93 if ((f = mix_openfile(IDLOG, "rb+")) != NULL) {
94 fread(&idbuf,1,sizeof(idlog_t),f);
95 old = idbuf.time;
96 } else {
97 if (IDEXP == 0) {
98 if (timestamp > 0 && timestamp <= now - 7 * SECONDSPERDAY) {
99 errlog(LOG, "Ignoring old message.\n");
100 return (0);
101 }
102 } else {
103 if ((f = mix_openfile(IDLOG, "wb")) != NULL) {
104 memset(idbuf.id,0,sizeof(idbuf.id));
105 idbuf.time = now;
106 fwrite(&idbuf,1,sizeof(idlog_t),f);
107 memcpy(idbuf.id,id->data,sizeof(idbuf.id));
108 idbuf.time = now;
109 fwrite(&idbuf,1,sizeof(idlog_t),f);
110 fclose(f);
111 errlog(NOTICE, "Creating %s\n", IDLOG);
112 } else {
113 errlog(ERRORMSG, "Can't create %s\n", IDLOG);
114 }
115 return (1);
116 }
117 }
118
119 if (now - old < 5 * SECONDSPERDAY) /* never reject messages less than */
120 old = now - 5 * SECONDSPERDAY; /* 5 days old (== minimum IDEXP) */
121
122 if (timestamp > 0 && timestamp <= old) {
123 errlog(LOG, "Ignoring old message.\n");
124 ret = 0;
125 goto end;
126 }
127 i = lockfile(IDLOG);
128 while (fread(&idbuf, 1, sizeof(idlog_t), f) == sizeof(idlog_t)) {
129 if (!memcmp(idbuf.id, id->data, sizeof(idbuf.id))) {
130 errlog(LOG, "Ignoring redundant message.\n");
131 ret = 0;
132 goto end;
133 }
134 }
135 if (ftell(f)%sizeof(idlog_t)) fseek(f,0-(ftell(f)%sizeof(idlog_t)),SEEK_CUR); /* make sure that we're on sizeof(idlog_t) byte boundary */
136 memcpy(idbuf.id,id->data,sizeof(idbuf.id));
137 idbuf.time = now;
138 fwrite(&idbuf,1,sizeof(idlog_t),f);
139 end:
140 if (i)
141 unlockfile(i);
142 fclose(f);
143 return (ret);
144 }
145
146 int mix2_decrypt(BUFFER *m)
147 /* 0: ok -1: error -2: old message */
148 {
149 int err = 0;
150 int i;
151 BUFFER *privkey;
152 BUFFER *keyid;
153 BUFFER *dec, *deskey;
154 BUFFER *packetid, *mid, *digest, *addr, *temp, *iv, *ivvec;
155 int type, packet = 0, numpackets = 0, timestamp = 0;
156 BUFFER *body;
157 BUFFER *header, *out;
158
159 privkey = buf_new();
160 keyid = buf_new();
161 dec = buf_new();
162 deskey = buf_new();
163 packetid = buf_new();
164 mid = buf_new();
165 digest = buf_new();
166 addr = buf_new();
167 temp = buf_new();
168 iv = buf_new();
169 ivvec = buf_new();
170 body = buf_new();
171 header = buf_new();
172 out = buf_new();
173
174 buf_get(m, keyid, 16);
175 err = db_getseckey(keyid->data, privkey);
176 if (err == -1)
177 goto end;
178 buf_get(m, deskey, buf_getc(m));
179 err = pk_decrypt(deskey, privkey);
180 if (err == -1 || deskey->length != 24) {
181 err = -1;
182 errlog(NOTICE, "Cannot decrypt message.\n");
183 goto end;
184 }
185 buf_get(m, iv, 8);
186 buf_get(m, dec, 328);
187 buf_crypt(dec, deskey, iv, DECRYPT);
188 buf_get(dec, packetid, 16);
189 buf_get(dec, deskey, 24);
190 type = buf_getc(dec);
191 switch (type) {
192 case 0:
193 buf_get(dec, ivvec, 152);
194 buf_get(dec, addr, 80);
195 break;
196 case 1:
197 buf_get(dec, mid, 16);
198 buf_get(dec, iv, 8);
199 break;
200 case 2:
201 packet = buf_getc(dec);
202 numpackets = buf_getc(dec);
203 buf_get(dec, mid, 16);
204 buf_get(dec, iv, 8);
205 break;
206 default:
207 errlog(WARNING, "Unknown message type.\n");
208 err = -1;
209 goto end;
210 }
211 if (dec->data[dec->ptr] == '0' && dec->data[dec->ptr + 1] == '0' &&
212 dec->data[dec->ptr + 2] == '0' && dec->data[dec->ptr + 3] == '0' &&
213 dec->data[dec->ptr + 4] == '\0') {
214 dec->ptr += 5;
215 timestamp = buf_geti_lo(dec);
216 }
217 buf_get(dec, digest, 16);
218
219 dec->length = dec->ptr - 16; /* ignore digest */
220 dec->ptr = dec->length;
221
222 if (!isdigest_md5(dec, digest)) {
223 errlog(NOTICE, "Message digest does not match.\n");
224 err = -1;
225 goto end;
226 }
227 if (!isnewid(packetid, timestamp * SECONDSPERDAY)) {
228 err = -2;
229 goto end;
230 }
231 buf_append(body, m->data + 20 * 512, 10240);
232
233 switch (type) {
234 case 0:
235 buf_chop(addr);
236 buf_cat(out, addr);
237 buf_nl(out);
238 for (i = 0; i < 19; i++) {
239 buf_reset(header);
240 buf_append(header, m->data + (i + 1) * 512, 512);
241 buf_reset(iv);
242 buf_append(iv, ivvec->data + i * 8, 8);
243 buf_crypt(header, deskey, iv, DECRYPT);
244 buf_cat(out, header);
245 }
246 buf_reset(header);
247 buf_pad(header, 512);
248 buf_cat(out, header);
249 buf_reset(iv);
250 buf_append(iv, ivvec->data + 144, 8);
251 buf_crypt(body, deskey, iv, DECRYPT);
252 buf_cat(out, body);
253 mix_pool(out, INTERMEDIATE, -1);
254 break;
255 case 1:
256 buf_crypt(body, deskey, iv, DECRYPT);
257 err = v2body_setlen(body);
258 if (err == -1)
259 goto end;
260 assert(body->ptr == 4);
261 v2body(body);
262 break;
263 case 2:
264 buf_crypt(body, deskey, iv, DECRYPT);
265 v2partial(body, mid, packet, numpackets);
266 break;
267 }
268 end:
269 buf_free(privkey);
270 buf_free(keyid);
271 buf_free(dec);
272 buf_free(deskey);
273 buf_free(packetid);
274 buf_free(mid);
275 buf_free(digest);
276 buf_free(addr);
277 buf_free(temp);
278 buf_free(iv);
279 buf_free(ivvec);
280 buf_free(body);
281 buf_free(header);
282 buf_free(out);
283
284 return (err);
285 }
286
287 int v2body_setlen(BUFFER *body)
288 {
289 long length;
290
291 length = buf_getl_lo(body);
292 if (length < 0 || length > body->length)
293 return (-1);
294 body->length = length + 4;
295 return (0);
296 }
297
298 int v2body(BUFFER *body)
299 {
300 int i, n;
301 BUFFER *to, *newsgroups;
302 BUFFER *temp, *out;
303 BUFFER *line;
304 int type = MSG_MAIL;
305 int subject = 0;
306
307 line = buf_new();
308 to = buf_new();
309 newsgroups = buf_new();
310 temp = buf_new();
311 out = buf_new();
312
313 n = buf_getc(body);
314 for (i = 0; i < n; i++) {
315 buf_get(body, line, 80);
316 buf_chop(line);
317 if (bufileft(line, "null:"))
318 goto end;
319 if (bufileft(line, "post:")) {
320 type = MSG_POST;
321 if (line->length > 5) {
322 int j = 5;
323
324 while (j < line->length && isspace(line->data[j]))
325 j++;
326 if (newsgroups->length > 0)
327 buf_appends(newsgroups, ",");
328 buf_append(newsgroups, line->data + j, line->length - j);
329 }
330 } else {
331 if (to->length > 0)
332 buf_appends(to, ",");
333 buf_cat(to, line);
334 }
335 }
336 if (to->length > 0) {
337 buf_appends(out, "To: ");
338 buf_cat(out, to);
339 buf_nl(out);
340 }
341 if (newsgroups->length > 0) {
342 buf_appends(out, "Newsgroups: ");
343 buf_cat(out, newsgroups);
344 buf_nl(out);
345 }
346 n = buf_getc(body);
347 for (i = 0; i < n; i++) {
348 buf_get(body, line, 80);
349 buf_chop(line);
350 if (bufileft(line, "Subject:"))
351 subject = 1;
352 buf_cat(out, line);
353 buf_nl(out);
354 }
355
356 buf_rest(temp, body);
357 buf_uncompress(temp);
358 buf_set(body, temp);
359 buf_reset(temp);
360
361 if (buf_lookahead(body, line) == 0 && isline(line, HASHMARK)) {
362 buf_getline(body, line);
363 while (buf_getline(body, line) == 0) {
364 if (bufileft(line, "subject:"))
365 subject = 1;
366 buf_cat(out, line);
367 buf_nl(out);
368 }
369 }
370 if (type == MSG_POST && !subject)
371 buf_appends(out, "Subject: (no subject)\n");
372
373 buf_nl(out);
374 buf_rest(out, body);
375 buf_reset(body);
376 mix_pool(out, type, -1);
377
378 end:
379 buf_free(line);
380 buf_free(to);
381 buf_free(newsgroups);
382 buf_free(temp);
383 buf_free(out);
384 return (0);
385 }
386
387 int v2_merge(BUFFER *mid)
388 {
389 char fname[PATHMAX], line[LINELEN];
390 BUFFER *temp, *msg;
391 FILE *l, *f;
392 int i, numpackets;
393 struct stat sb;
394 long d;
395 int n;
396 int err = -1;
397
398 temp = buf_new();
399 msg = buf_new();
400 pool_packetfile(fname, mid, 0);
401 l = fopen(fname, "a+");
402 if (l != NULL)
403 lock(l);
404
405 pool_packetfile(fname, mid, 1);
406 f = fopen(fname, "rb");
407 if (f == NULL)
408 goto end;
409 fscanf(f, "%32s %ld %d %d\n", line, &d, &i, &numpackets);
410 fclose(f);
411
412 /* do we have all packets? */
413 for (i = 1; i <= numpackets; i++) {
414 pool_packetfile(fname, mid, i);
415 if (stat(fname, &sb) != 0)
416 goto end;
417 }
418 errlog(LOG, "Reassembling multipart message.\n");
419 for (i = 1; i <= numpackets; i++) {
420 pool_packetfile(fname, mid, i);
421 f = fopen(fname, "rb");
422 if (f == NULL)
423 goto end;
424 fscanf(f, "%32s %ld %d %d\n", line, &d, &n, &n);
425 buf_clear(temp);
426 buf_read(temp, f);
427 v2body_setlen(temp);
428 buf_append(msg, temp->data + 4, temp->length - 4);
429 fclose(f);
430 unlink(fname);
431 }
432 err = v2body(msg);
433
434 end:
435 if (l != NULL)
436 fclose(l);
437 pool_packetfile(fname, mid, 0);
438 unlink(fname);
439 buf_free(temp);
440 buf_free(msg);
441 return (err);
442 }
443
444 int v2partial(BUFFER *m, BUFFER *mid, int packet, int numpackets)
445 {
446 char fname[PATHMAX], idstr[33];
447 FILE *f;
448 int err = 1;
449
450 pool_packetfile(fname, mid, packet);
451 f = fopen(fname, "wb");
452 if (f == NULL) {
453 err = -1;
454 goto end;
455 }
456 id_encode(mid->data, idstr);
457 fprintf(f, "%s %ld %d %d\n", idstr, (long) time(NULL), packet,
458 numpackets);
459 buf_write(m, f);
460 buf_reset(m);
461 fclose(f);
462 v2_merge(mid);
463 end:
464 return (err);
465 }
466
467 #else
468
469 int mix2_decrypt(BUFFER *m)
470 {
471 return (-1);
472 }
473 #endif

  ViewVC Help
Powered by ViewVC 1.1.5