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

Contents of /branches/mixmaster_2_9_STABLE/Mix/Src/rem2.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.5