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

Contents of /trunk/Mix/Src/rem1.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: 12067 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 Cypherpunk remailer messages
9 $Id: rem1.c,v 1.1 2001/10/31 08:19:53 rabbi Exp $ */
10
11
12 #include "mix3.h"
13 #include <ctype.h>
14 #include <time.h>
15 #include <string.h>
16
17 static int t1msg(BUFFER *in, int hdr);
18
19 int isline(BUFFER *line, char *text)
20 {
21 int i;
22
23 if (!bufileft(line, text))
24 return (0);
25
26 for (i = strlen(text); i < line->length; i++)
27 if (!isspace(line->data[i]))
28 return(0);
29 return(1);
30 }
31
32 int t1_decrypt(BUFFER *in)
33 {
34 int ret;
35
36 buf_rewind(in);
37 if (TYPE1[0] == '\0')
38 ret = t1msg(in, 1);
39 else {
40 FILE *f;
41
42 f = openpipe(TYPE1);
43 if (f == NULL)
44 return -1;
45 buf_write(in, f);
46 ret = closepipe(f);
47 }
48 if (ret == 0)
49 stats_log(1);
50 return (ret);
51 }
52
53 #ifdef USE_IDEA
54 void t1_esub(BUFFER *esub, BUFFER *subject)
55 {
56 BUFFER *iv, *out;
57 char hex[33];
58
59 iv = buf_new();
60 out = buf_new();
61
62 buf_appendrnd(iv, 8);
63 id_encode(iv->data, hex);
64 buf_append(out, hex, 16);
65
66 digest_md5(esub, esub);
67 digest_md5(subject, subject);
68 buf_ideacrypt(subject, esub, iv, ENCRYPT);
69 id_encode(subject->data, hex);
70 buf_appends(out, hex);
71 buf_move(subject, out);
72 buf_free(iv);
73 buf_free(out);
74 }
75 #endif
76
77 #define N(X) (isdigit(X) ? (X)-'0' : 0)
78
79 static int readnum(BUFFER *b, int f)
80 {
81 int num = 0;
82
83 if (b->length > 0)
84 sscanf(b->data, "%d", &num);
85 num *= f;
86 if (strchr(b->data, 'r'))
87 num = rnd_number(num) + 1;
88 return (num);
89 }
90
91 static int t1msg(BUFFER *in, int hdr)
92 /* hdr = 1: mail header, hdr = 2: pasted header, hdr = 0: ignore */
93 {
94 BUFFER *field, *content, *line;
95 BUFFER *cutmarks, *to, *newsgroups, *ek, *ekdes, *ekcast, *esub, *subject;
96 BUFFER *temp, *header, *out;
97 BUFFER *test, *testto, *remixto;
98 int err = 0;
99 int encrypted = 0;
100 int type = -1;
101 int latent = 0;
102 int remix = 0;
103 int inflate = 0;
104
105 field = buf_new();
106 content = buf_new();
107 line = buf_new();
108 to = buf_new();
109 remixto = buf_new();
110 cutmarks = buf_new();
111 newsgroups = buf_new();
112 ek = buf_new();
113 ekdes = buf_new();
114 ekcast = buf_new();
115 esub = buf_new();
116 subject = buf_new();
117 temp = buf_new();
118 header = buf_new();
119 out = buf_new();
120 test = buf_new();
121 testto = buf_new();
122
123 if (REMIX == 1)
124 remix = 2;
125 if (!UNENCRYPTED)
126 encrypted = -1;
127
128 header:
129 while (buf_getheader(in, field, content) == 0) {
130 if (header->length == 0 && bufieq(content, ":")) /* HDRMARK */
131 hdr = 2;
132
133 if (bufieq(field, "test-to"))
134 buf_set(testto, content);
135 else if (PGP && bufieq(field, "encrypted"))
136 encrypted = 1;
137 else if (bufieq(field, "remix-to")) {
138 remix = 1;
139 buf_set(remixto, content);
140 if (type == -1)
141 type = MSG_MAIL;
142 } else if (bufieq(field, "anon-to") ||
143 bufieq(field, "request-remailing-to") ||
144 bufieq(field, "remail-to") ||
145 bufieq(field, "anon-send-to")) {
146 if (bufieq(field, "remail-to"))
147 remix = 0;
148 if (to->length > 0)
149 buf_appendc(to, ',');
150 buf_cat(to, content);
151 if (type == -1)
152 type = MSG_MAIL;
153 } else if (bufieq(field, "anon-post-to") || bufieq(field, "post-to")) {
154 if (newsgroups->length > 0)
155 buf_appendc(newsgroups, ',');
156 buf_cat(newsgroups, content);
157 type = MSG_POST;
158 } else if (bufieq(field, "cutmarks"))
159 buf_set(cutmarks, content);
160 else if (bufieq(field, "latent-time")) {
161 byte *q;
162 int l;
163
164 q = content->data;
165 l = strlen(q);
166 latent = 0;
167 if (q[0] == '+')
168 q++;
169 if (l >= 5 && q[2] == ':')
170 latent = 600 * N(q[0]) + 60 * N(q[1]) + 10 * N(q[3]) + N(q[4]);
171 else if (l >= 4 && q[1] == ':')
172 latent = 60 * N(q[0]) + 10 * N(q[2]) + N(q[3]);
173 else if (l >= 3 && q[0] == ':')
174 latent = 10 * N(q[1]) + N(q[2]);
175 if (!bufleft(content, "+")) {
176 time_t now;
177
178 time(&now);
179 latent -= localtime(&now)->tm_hour * 60;
180 if (latent < 0)
181 latent += 24 * 60;
182 }
183 if (q[l - 1] == 'r')
184 latent = rnd_number(latent);
185 } else if (bufieq(field, "null"))
186 type = MSG_NULL;
187 else if (bufieq(field, "encrypt-key") || bufieq(field, "encrypt-idea"))
188 buf_set(ek, content);
189 else if (bufieq(field, "encrypt-des") || bufieq(field, "encrypt-3des"))
190 buf_set(ekdes, content);
191 else if (bufieq(field, "encrypt-cast") || bufieq(field, "encrypt-cast5"))
192 buf_set(ekcast, content);
193 else if (bufieq(field, "encrypt-subject"))
194 buf_set(esub, content);
195 else if (bufieq(field, "inflate")) {
196 inflate = readnum(content, 1024);
197 if (inflate > INFLATEMAX * 1024)
198 inflate = INFLATEMAX * 1024;
199 } else if (bufieq(field, "rand-hop")) {
200 int randhops, i;
201 randhops = readnum(content, 1);
202 if (randhops > MAXRANDHOPS)
203 randhops = MAXRANDHOPS;
204 buf_clear(temp);
205 if (remixto->length)
206 buf_move(temp, remixto);
207 for (i = 0; i < randhops; i++) {
208 if (remixto->length > 0)
209 buf_appendc(remixto, ',');
210 buf_appendc(remixto, '*');
211 }
212 if (temp->length) {
213 buf_appendc(remixto, ',');
214 buf_cat(remixto, temp);
215 }
216 }
217 #if USE_NSUB
218 else if (bufieq(field, "subject"))
219 buf_set(subject, content);
220 #endif
221 }
222
223 if (cutmarks->length > 0) {
224 BUFFER *cut;
225
226 cut = buf_new();
227 buf_clear(temp);
228
229 while ((err = buf_getline(in, line)) != -1 && !buf_eq(line, cutmarks)) {
230 buf_cat(temp, line);
231 buf_nl(temp);
232 }
233 while (err != -1) {
234 err = buf_getline(in, line);
235 if (err == -1 || buf_eq(line, cutmarks)) {
236 t1msg(cut, 0);
237 buf_clear(cut);
238 } else {
239 buf_cat(cut, line);
240 buf_nl(cut);
241 }
242 }
243 buf_move(in, temp);
244 buf_clear(cutmarks);
245 }
246 if (encrypted == 1) {
247 #ifdef USE_PGP
248 err = pgp_dearmor(in, temp);
249 if (err == 0) {
250 BUFFER *pass;
251
252 pass = buf_new();
253 buf_sets(pass, PASSPHRASE);
254 err = pgp_decrypt(temp, pass, NULL, NULL, NULL);
255 buf_free(pass);
256 }
257 if (err != -1 && temp->length == 0) {
258 errlog(ERRORMSG, "Empty PGP message.\n");
259 err = -1;
260 goto end;
261 }
262 if (err != -1) {
263 buf_rest(temp, in); /* dangerous, but required for reply blocks */
264 buf_move(in, temp);
265 encrypted = 0;
266 hdr = 0;
267 goto header;
268 }
269 #endif
270 if (testto->length == 0)
271 errlog(ERRORMSG, "Can't decrypt PGP message.\n");
272 buf_appends(test, "Can't decrypt PGP message.\n");
273 }
274 while ((err = buf_lookahead(in, line)) == 1)
275 buf_getline(in, line);
276 #if 0
277 if (err == -1)
278 goto end;
279 #endif
280
281 if (isline(line, HDRMARK) && (hdr == 0 || hdr == 1)) {
282 buf_getline(in, NULL);
283 hdr = 2;
284 goto header;
285 } else if (isline(line, HASHMARK)) {
286 buf_getline(in, NULL);
287 for (;;) {
288 if (buf_lookahead(in, line) == 0 && bufileft(line, "subject:")) {
289 buf_getheader(in, field, content);
290 buf_set(subject, content);
291 }
292 if (buf_getline(in, line) != 0)
293 break;
294 buf_cat(header, line);
295 buf_nl(header);
296 }
297 }
298 if (encrypted == -1) {
299 if (testto->length == 0)
300 errlog(LOG, "Unencrypted message detected.\n");
301 buf_appends(test, "Unencrypted message detected.\n");
302 err = -2;
303 goto end;
304 }
305 if (type == MSG_POST && subject->length == 0)
306 buf_sets(subject, "(no subject)");
307
308 if (to->length > 0)
309 buf_appendf(out, "To: %b\n", to);
310 else if (remixto->length > 0)
311 buf_appendf(out, "To: %b\n", remixto);
312 if (newsgroups->length > 0)
313 buf_appendf(out, "Newsgroups: %b\n", newsgroups);
314 if (subject->length > 0) {
315 #ifdef USE_IDEA
316 if (esub->length > 0)
317 t1_esub(esub, subject);
318 #endif
319 buf_appendf(out, "Subject: %b\n", subject);
320 }
321 buf_cat(out, header);
322 buf_nl(out);
323
324 #if 0
325 inflate -= in->length;
326 #endif
327 if (inflate > 0) {
328 buf_setrnd(temp, inflate * 3 / 4);
329 encode(temp, 64);
330 buf_appends(in, "\n-----BEGIN GARBAGE-----\n");
331 buf_cat(in, temp);
332 buf_appends(in, "-----END GARBAGE-----\n");
333 }
334
335 if (!(ek->length || ekdes->length || ekcast->length))
336 buf_rest(out, in);
337 else {
338 err = 0;
339 buf_clear(temp);
340 while (buf_getline(in, line) != -1) {
341 if (isline(line, EKMARK)) {
342 buf_cat(out, temp);
343 buf_clear(temp);
344 buf_rest(temp, in);
345 break;
346 }
347 else {
348 buf_cat(temp, line);
349 buf_nl(temp);
350 }
351 }
352 #ifdef USE_PGP
353 if (ekcast->length) {
354 err = pgp_encrypt(PGP_CONVCAST | PGP_TEXT, temp, ekcast, NULL, NULL,
355 NULL, NULL);
356 buf_clear(ekcast);
357 }
358 if (ekdes->length) {
359 err = pgp_encrypt(PGP_CONV3DES | PGP_TEXT, temp, ekdes, NULL, NULL,
360 NULL, NULL);
361 buf_clear(ekdes);
362 }
363 if (ek->length) {
364 err = pgp_encrypt(PGP_CONVENTIONAL | PGP_TEXT, temp, ek, NULL, NULL,
365 NULL, NULL);
366 buf_clear(ek);
367 }
368 buf_appends(out, EKMARK);
369 buf_nl(out);
370 buf_cat(out, temp);
371 #else
372 err = -1;
373 #endif
374 }
375
376 if (type == -1) {
377 buf_appends(test, "No destination.\n");
378 err = -1;
379 }
380
381 end:
382 if (testto->length) {
383 BUFFER *report;
384 int i;
385
386 report = buf_new();
387 buf_sets(report,
388 "Subject: remailer test report\n\nThis is an automated response to the test message you sent to ");
389 buf_appends(report, SHORTNAME);
390 buf_appends(report, ".\nYour test message results follow:\n\n");
391 buf_appends(report, remailer_type);
392 buf_appends(report, VERSION);
393 buf_appends(report, "\n\n");
394 if (err == 0) {
395 err = filtermsg(out);
396 if (err == -1)
397 buf_appends(report, "This remailer cannot deliver the message.\n\n");
398 else {
399 buf_appends(report, "Valid ");
400 buf_appends(report, type == MSG_POST ? "Usenet" : "mail");
401 buf_appends(report, " message.\n");
402 if (remixto->length) {
403 if (remix && MIX)
404 buf_appends(report, "Delivery via Mixmaster: ");
405 else if (remix)
406 buf_appends(report, "Error! Can't remix: ");
407 else
408 buf_appends(report, "Delivery via Cypherpunk remailer: ");
409 buf_cat(report, remixto);
410 buf_nl(report);
411 }
412 else if (type == MSG_POST && strchr(NEWS, '@') && !strchr(NEWS, ' ')) {
413 buf_appendf(report, "News gateway: %s\n", NEWS);
414 }
415 buf_appends(report,
416 "\n=========================================================================\nThe first 20 lines of the message follow:\n");
417 if (err != 1)
418 buf_appendf(report, "From: %s\n", ANONNAME);
419 if (type == MSG_POST && ORGANIZATION[0] != '\0')
420 buf_appendf(report, "Organization: %s\n", ORGANIZATION);
421 }
422 for (i = 0; i < 20 && buf_getline(out, test) != -1; i++)
423 buf_cat(report, test), buf_nl(report);
424 } else {
425 buf_appends(report, "The remailer message is invalid.\n\n");
426 if (test->length) {
427 buf_appends(report, "The following error occurred: ");
428 buf_cat(report, test);
429 buf_nl(report);
430 }
431 }
432 buf_appends(report,
433 "=========================================================================\nThe first 20 lines of your message to the remailer follow:\n");
434 buf_rewind(in);
435 for (i = 0; i < 20 && buf_getline(in, test) != -1; i++)
436 buf_cat(report, test), buf_nl(report);
437
438 sendmail(report, REMAILERNAME, testto);
439 err = 0;
440 buf_free(report);
441 } else if (err == 0 && type != MSG_NULL) {
442 err = 1;
443 if (bufieq(to, REMAILERADDR)) /* don't remix to ourselves */
444 remix = 0;
445 if (remix && remixto->length == 0)
446 buf_set(remixto, to);
447 if (remix)
448 err = mix_encrypt(type, out, remixto->data, 1, line);
449 if (err != 0) {
450 if (remix == 1)
451 errlog(NOTICE, "Can't remix -- %b\n", line);
452 else {
453 if (remixto->length)
454 err = t1_encrypt(type, out, remixto->data, 0, 0, line);
455 if (err != 0)
456 err = mix_pool(out, type, latent * 60);
457 }
458 }
459 }
460
461 buf_free(field);
462 buf_free(content);
463 buf_free(line);
464 buf_free(to);
465 buf_free(remixto);
466 buf_free(newsgroups);
467 buf_free(subject);
468 buf_free(ek);
469 buf_free(ekcast);
470 buf_free(ekdes);
471 buf_free(esub);
472 buf_free(cutmarks);
473 buf_free(temp);
474 buf_free(out);
475 buf_free(header);
476 buf_free(test);
477 buf_free(testto);
478 return (err);
479 }

  ViewVC Help
Powered by ViewVC 1.1.5