/[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 1 - (show annotations) (download)
Wed Oct 31 08:19:51 2001 UTC (11 years, 7 months ago) by rabbi
File MIME type: text/plain
File size: 9771 byte(s)
Initial revision
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.1 2001/10/31 08:19:53 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 char idstr[33], line[LINELEN];
87 int ret = 1;
88 long now, old = 0;
89 LOCK *i = NULL;
90
91 now = time(NULL);
92 id_encode(id->data, idstr);
93
94 if ((f = mix_openfile(IDLOG, "r+")) != NULL)
95 fscanf(f, "%*s %ld", &old);
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, "w")) != NULL) {
104 fprintf(f, "new %ld\n%s %ld\n", now, idstr, now);
105 fclose(f);
106 errlog(NOTICE, "Creating %s\n", IDLOG);
107 } else {
108 errlog(ERRORMSG, "Can't create %s\n", IDLOG);
109 }
110 return (1);
111 }
112 }
113
114 if (now - old < 5 * SECONDSPERDAY) /* never reject messages less than */
115 old = now - 5 * SECONDSPERDAY; /* 5 days old (== minimum IDEXP) */
116
117 if (timestamp > 0 && timestamp <= old) {
118 errlog(LOG, "Ignoring old message.\n");
119 ret = 0;
120 goto end;
121 }
122 i = lockfile(IDLOG);
123 while (fgets(line, sizeof(line), f) != NULL) {
124 if (strleft(line, idstr)) {
125 errlog(LOG, "Ignoring redundant message.\n");
126 ret = 0;
127 goto end;
128 }
129 }
130 fprintf(f, "%s %ld\n", idstr, now);
131 end:
132 if (i)
133 unlockfile(i);
134 fclose(f);
135 return (ret);
136 }
137
138 int mix2_decrypt(BUFFER *m)
139 /* 0: ok -1: error -2: old message */
140 {
141 int err = 0;
142 int i;
143 BUFFER *privkey;
144 BUFFER *keyid;
145 BUFFER *dec, *deskey;
146 BUFFER *packetid, *mid, *digest, *addr, *temp, *iv, *ivvec;
147 int type, packet = 0, numpackets = 0, timestamp = 0;
148 BUFFER *body;
149 BUFFER *header, *out;
150
151 privkey = buf_new();
152 keyid = buf_new();
153 dec = buf_new();
154 deskey = buf_new();
155 packetid = buf_new();
156 mid = buf_new();
157 digest = buf_new();
158 addr = buf_new();
159 temp = buf_new();
160 iv = buf_new();
161 ivvec = buf_new();
162 body = buf_new();
163 header = buf_new();
164 out = buf_new();
165
166 buf_get(m, keyid, 16);
167 err = db_getseckey(keyid->data, privkey);
168 if (err == -1)
169 goto end;
170 buf_get(m, deskey, buf_getc(m));
171 err = pk_decrypt(deskey, privkey);
172 if (err == -1 || deskey->length != 24) {
173 err = -1;
174 errlog(NOTICE, "Cannot decrypt message.\n");
175 goto end;
176 }
177 buf_get(m, iv, 8);
178 buf_get(m, dec, 328);
179 buf_crypt(dec, deskey, iv, DECRYPT);
180 buf_get(dec, packetid, 16);
181 buf_get(dec, deskey, 24);
182 type = buf_getc(dec);
183 switch (type) {
184 case 0:
185 buf_get(dec, ivvec, 152);
186 buf_get(dec, addr, 80);
187 break;
188 case 1:
189 buf_get(dec, mid, 16);
190 buf_get(dec, iv, 8);
191 break;
192 case 2:
193 packet = buf_getc(dec);
194 numpackets = buf_getc(dec);
195 buf_get(dec, mid, 16);
196 buf_get(dec, iv, 8);
197 break;
198 default:
199 errlog(WARNING, "Unknown message type.\n");
200 err = -1;
201 goto end;
202 }
203 if (dec->data[dec->ptr] == '0' && dec->data[dec->ptr + 1] == '0' &&
204 dec->data[dec->ptr + 2] == '0' && dec->data[dec->ptr + 3] == '0' &&
205 dec->data[dec->ptr + 4] == '\0') {
206 dec->ptr += 5;
207 timestamp = buf_geti_lo(dec);
208 }
209 buf_get(dec, digest, 16);
210
211 dec->length = dec->ptr - 16; /* ignore digest */
212 dec->ptr = dec->length;
213
214 if (!isdigest_md5(dec, digest)) {
215 errlog(NOTICE, "Message digest does not match.\n");
216 err = -1;
217 goto end;
218 }
219 if (!isnewid(packetid, timestamp * SECONDSPERDAY)) {
220 err = -2;
221 goto end;
222 }
223 buf_append(body, m->data + 20 * 512, 10240);
224
225 switch (type) {
226 case 0:
227 buf_chop(addr);
228 buf_cat(out, addr);
229 buf_nl(out);
230 for (i = 0; i < 19; i++) {
231 buf_reset(header);
232 buf_append(header, m->data + (i + 1) * 512, 512);
233 buf_reset(iv);
234 buf_append(iv, ivvec->data + i * 8, 8);
235 buf_crypt(header, deskey, iv, DECRYPT);
236 buf_cat(out, header);
237 }
238 buf_reset(header);
239 buf_pad(header, 512);
240 buf_cat(out, header);
241 buf_reset(iv);
242 buf_append(iv, ivvec->data + 144, 8);
243 buf_crypt(body, deskey, iv, DECRYPT);
244 buf_cat(out, body);
245 mix_pool(out, INTERMEDIATE, -1);
246 break;
247 case 1:
248 buf_crypt(body, deskey, iv, DECRYPT);
249 err = v2body_setlen(body);
250 if (err == -1)
251 goto end;
252 assert(body->ptr == 4);
253 v2body(body);
254 break;
255 case 2:
256 buf_crypt(body, deskey, iv, DECRYPT);
257 v2partial(body, mid, packet, numpackets);
258 break;
259 }
260 end:
261 buf_free(privkey);
262 buf_free(keyid);
263 buf_free(dec);
264 buf_free(deskey);
265 buf_free(packetid);
266 buf_free(mid);
267 buf_free(digest);
268 buf_free(addr);
269 buf_free(temp);
270 buf_free(iv);
271 buf_free(ivvec);
272 buf_free(body);
273 buf_free(header);
274 buf_free(out);
275
276 return (err);
277 }
278
279 int v2body_setlen(BUFFER *body)
280 {
281 long length;
282
283 length = buf_getl_lo(body);
284 if (length < 0 || length > body->length)
285 return (-1);
286 body->length = length + 4;
287 return (0);
288 }
289
290 int v2body(BUFFER *body)
291 {
292 int i, n;
293 BUFFER *to, *newsgroups;
294 BUFFER *temp, *out;
295 BUFFER *line;
296 int type = MSG_MAIL;
297 int subject = 0;
298
299 line = buf_new();
300 to = buf_new();
301 newsgroups = buf_new();
302 temp = buf_new();
303 out = buf_new();
304
305 n = buf_getc(body);
306 for (i = 0; i < n; i++) {
307 buf_get(body, line, 80);
308 buf_chop(line);
309 if (bufileft(line, "null:"))
310 goto end;
311 if (bufileft(line, "post:")) {
312 type = MSG_POST;
313 if (line->length > 5) {
314 int j = 5;
315
316 while (j < line->length && isspace(line->data[j]))
317 j++;
318 if (newsgroups->length > 0)
319 buf_appends(newsgroups, ",");
320 buf_append(newsgroups, line->data + j, line->length - j);
321 }
322 } else {
323 if (to->length > 0)
324 buf_appends(to, ",");
325 buf_cat(to, line);
326 }
327 }
328 if (to->length > 0) {
329 buf_appends(out, "To: ");
330 buf_cat(out, to);
331 buf_nl(out);
332 }
333 if (newsgroups->length > 0) {
334 buf_appends(out, "Newsgroups: ");
335 buf_cat(out, newsgroups);
336 buf_nl(out);
337 }
338 n = buf_getc(body);
339 for (i = 0; i < n; i++) {
340 buf_get(body, line, 80);
341 buf_chop(line);
342 if (bufileft(line, "Subject:"))
343 subject = 1;
344 buf_cat(out, line);
345 buf_nl(out);
346 }
347
348 buf_rest(temp, body);
349 buf_uncompress(temp);
350 buf_set(body, temp);
351 buf_reset(temp);
352
353 if (buf_lookahead(body, line) == 0 && isline(line, HASHMARK)) {
354 buf_getline(body, line);
355 while (buf_getline(body, line) == 0) {
356 if (bufileft(line, "subject:"))
357 subject = 1;
358 buf_cat(out, line);
359 buf_nl(out);
360 }
361 }
362 if (type == MSG_POST && !subject)
363 buf_appends(out, "Subject: (no subject)\n");
364
365 buf_nl(out);
366 buf_rest(out, body);
367 buf_reset(body);
368 mix_pool(out, type, -1);
369
370 end:
371 buf_free(line);
372 buf_free(to);
373 buf_free(newsgroups);
374 buf_free(temp);
375 buf_free(out);
376 return (0);
377 }
378
379 int v2_merge(BUFFER *mid)
380 {
381 char fname[PATHMAX], line[LINELEN];
382 BUFFER *temp, *msg;
383 FILE *l, *f;
384 int i, numpackets;
385 struct stat sb;
386 long d;
387 int n;
388 int err = -1;
389
390 temp = buf_new();
391 msg = buf_new();
392 pool_packetfile(fname, mid, 0);
393 l = fopen(fname, "a+");
394 if (l != NULL)
395 lock(l);
396
397 pool_packetfile(fname, mid, 1);
398 f = fopen(fname, "rb");
399 if (f == NULL)
400 goto end;
401 fscanf(f, "%32s %ld %d %d\n", line, &d, &i, &numpackets);
402 fclose(f);
403
404 /* do we have all packets? */
405 for (i = 1; i <= numpackets; i++) {
406 pool_packetfile(fname, mid, i);
407 if (stat(fname, &sb) != 0)
408 goto end;
409 }
410 errlog(LOG, "Reassembling multipart message.\n");
411 for (i = 1; i <= numpackets; i++) {
412 pool_packetfile(fname, mid, i);
413 f = fopen(fname, "rb");
414 if (f == NULL)
415 goto end;
416 fscanf(f, "%32s %ld %d %d\n", line, &d, &n, &n);
417 buf_clear(temp);
418 buf_read(temp, f);
419 v2body_setlen(temp);
420 buf_append(msg, temp->data + 4, temp->length - 4);
421 fclose(f);
422 unlink(fname);
423 }
424 err = v2body(msg);
425
426 end:
427 if (l != NULL)
428 fclose(l);
429 pool_packetfile(fname, mid, 0);
430 unlink(fname);
431 buf_free(temp);
432 buf_free(msg);
433 return (err);
434 }
435
436 int v2partial(BUFFER *m, BUFFER *mid, int packet, int numpackets)
437 {
438 char fname[PATHMAX], idstr[33];
439 FILE *f;
440 int err = 1;
441
442 pool_packetfile(fname, mid, packet);
443 f = fopen(fname, "wb");
444 if (f == NULL) {
445 err = -1;
446 goto end;
447 }
448 id_encode(mid->data, idstr);
449 fprintf(f, "%s %ld %d %d\n", idstr, (long) time(NULL), packet,
450 numpackets);
451 buf_write(m, f);
452 buf_reset(m);
453 fclose(f);
454 v2_merge(mid);
455 end:
456 return (err);
457 }
458
459 #else
460
461 int mix2_decrypt(BUFFER *m)
462 {
463 return (-1);
464 }
465 #endif

  ViewVC Help
Powered by ViewVC 1.1.5