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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11 - (show annotations) (download)
Tue Nov 6 23:41:58 2001 UTC (11 years, 6 months ago) by rabbi
Original Path: trunk/Mix/Src/rem.c
File MIME type: text/plain
File size: 12129 byte(s)
First round of changes adding support for Mixmaster as a service under
Windows NT.
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 remailer messages
9 $Id: rem.c,v 1.3 2001/11/06 23:41:58 rabbi Exp $ */
10
11
12 #include "mix3.h"
13 #include <stdlib.h>
14 #include <string.h>
15 #include <time.h>
16 #include <ctype.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #ifdef POSIX
20 #include <unistd.h>
21 #else
22 #include <io.h>
23 #endif
24 #ifndef _MSC
25 #include <dirent.h>
26 #endif
27 #include <assert.h>
28
29 int blockrequest(BUFFER *message);
30
31 #define REQUESTHELP 100
32 #define REQUESTSTATS 101
33 #define REQUESTKEY 200
34 #define REQUESTCONF 201
35 #define REQUESTOPKEY 202
36 #define BLOCKREQUEST 666
37 #define DISABLED 99
38
39 #define CPUNKMSG 1
40 #define MIXMSG 2
41
42 int mix_decrypt(BUFFER *message)
43 {
44 int type = 0;
45 BUFFER *field, *content;
46 BUFFER *to, *subject, *replyto, *reply;
47 FILE *f;
48 BUFFER *block;
49 int err = 0;
50
51 mix_init(NULL);
52 field = buf_new();
53 content = buf_new();
54 to = buf_new();
55 replyto = buf_new();
56 reply = buf_new();
57 block = buf_new();
58 subject = buf_new();
59 buf_sets(subject, "Subject: Re: your mail");
60
61 buf_rewind(message);
62
63 f = mix_openfile(SOURCEBLOCK, "r");
64 if (f != NULL) {
65 buf_read(block, f);
66 fclose(f);
67 }
68 for (;;) {
69 err = buf_getheader(message, field, content);
70 if (err == 1) {
71 /* "::" marks for additional header lines */
72 while (buf_lookahead(message, field) == 1)
73 buf_getheader(message, field, content);
74 if (isline(field, HDRMARK))
75 continue;
76 else
77 goto hdrend;
78 }
79 if (err == -1)
80 goto hdrend;
81
82 if ((bufieq(field, "from") || bufieq(field, "sender") || bufieq(field,"received")) &&
83 doblock(content, block, 1) != 0)
84 goto end;
85
86 if (bufieq(field, "to"))
87 buf_cat(to, content);
88 else if (bufieq(field, "from") && replyto->length == 0)
89 /* reply to From address if no Reply-To header present */
90 buf_set(replyto, content);
91 else if (bufieq(field, "reply-to"))
92 buf_set(replyto, content);
93 else if (MIX && bufieq(field, "remailer-type") &&
94 bufileft(content, "mixmaster"))
95 type = MIXMSG;
96 else if (bufieq(field, "subject")) {
97 if (bufieq(content, "help") || bufieq(content, "remailer-help"))
98 type = REQUESTHELP;
99 else if (bufieq(content, "remailer-stats"))
100 type = REQUESTSTATS;
101 else if (bufieq(content, "remailer-key"))
102 type = REQUESTKEY;
103 else if (bufieq(content, "remailer-adminkey"))
104 type = REQUESTOPKEY;
105 else if (bufieq(content, "remailer-conf"))
106 type = REQUESTCONF;
107 else if (bufileft(content, "destination-block"))
108 type = BLOCKREQUEST;
109 else {
110 buf_sets(subject, "Subject: ");
111 if (!bufileft(content, "re:"))
112 buf_appends(subject, "Re: ");
113 buf_cat(subject, content);
114 }
115 } else if (bufieq(field, "test-to") || bufieq(field, "encrypted") ||
116 bufieq(field, "anon-to") ||
117 bufieq(field, "request-remailing-to") ||
118 bufieq(field, "remail-to") || bufieq(field, "anon-post-to") ||
119 bufieq(field, "post-to") || bufieq(field, "anon-send-to") ||
120 bufieq(field, "send-to") || bufieq(field, "remix-to"))
121 type = CPUNKMSG;
122 }
123 hdrend:
124 if (type > 0 && REMAIL == 0)
125 type = DISABLED;
126 switch (type) {
127 case REQUESTHELP:
128 if (sendinfofile(HELPFILE, NULL, replyto, NULL) == -1)
129 errlog(WARNING, "No help file available.\n");
130 break;
131 case REQUESTKEY:
132 err = key(reply);
133 if (err == 0)
134 err = sendmail(reply, REMAILERNAME, replyto);
135 break;
136 case REQUESTOPKEY:
137 err = adminkey(reply);
138 if (err == 0)
139 err = sendmail(reply, REMAILERNAME, replyto);
140 break;
141 case REQUESTSTATS:
142 err = stats(reply);
143 if (err == 0)
144 err = sendmail(reply, REMAILERNAME, replyto);
145 break;
146 case REQUESTCONF:
147 err = conf(reply);
148 if (err == 0)
149 err = sendmail(reply, REMAILERNAME, replyto);
150 break;
151 case CPUNKMSG:
152 err = t1_decrypt(message);
153 if (err != 0) {
154 errlog(LOG, "Invalid type 1 message from %b\n", replyto);
155 sendinfofile(USAGEFILE, USAGELOG, replyto, NULL);
156 logmail(err == -2 ? MAILUSAGE : MAILERROR, message);
157 }
158 break;
159 case MIXMSG:
160 err = t2_decrypt(message);
161 if (err == -1) {
162 errlog(LOG, "Invalid type 2 message from %b\n", replyto);
163 sendinfofile(USAGEFILE, USAGELOG, replyto, NULL);
164 logmail(MAILERROR, message);
165 }
166 break;
167 case BLOCKREQUEST:
168 blockrequest(message);
169 logmail(MAILBLOCK, message);
170 break;
171 case DISABLED:
172 errlog(ERRORMSG, "Remailer is disabled.\n");
173 buf_sets(reply, "Subject: remailer error\n\nThe remailer is disabled.\n");
174 sendmail(reply, REMAILERNAME, replyto);
175 logmail(MAILERROR, message);
176 break;
177 default:
178 if (strifind
179 (replyto->data, "mailer-daemon")) {
180 errlog(LOG, "Bounce mail from %b\n", replyto);
181 logmail(MAILBOUNCE, message);
182 } else if (bufifind(to, REMAILERADDR) && blockrequest(message))
183 logmail(MAILBLOCK, message);
184 else if (!AUTOREPLY)
185 logmail(MAILBOX, message);
186 else if (bufifind(to, REMAILERADDR)) {
187 errlog(LOG, "Non-remailer message from %b\n", replyto);
188 sendinfofile(USAGEFILE, USAGELOG, replyto, NULL);
189 logmail(MAILUSAGE, message);
190 } else if (bufifind(to, COMPLAINTS)) {
191 errlog(WARNING, "Abuse complaint from %b\n", replyto);
192 sendinfofile(ABUSEFILE, NULL, replyto, subject);
193 logmail(MAILABUSE, message);
194 } else if (ANONADDR[0] && bufifind(to, ANONADDR)) {
195 errlog(LOG, "Reply to anonymous message from %b\n", replyto);
196 sendinfofile(REPLYFILE, NULL, replyto, subject);
197 logmail(MAILANON, message);
198 } else {
199 errlog(DEBUGINFO, "Mail from %b\n", replyto);
200 logmail(MAILBOX, message);
201 }
202 err = 1;
203 }
204 end:
205 buf_free(field);
206 buf_free(content);
207 buf_free(to);
208 buf_free(replyto);
209 buf_free(reply);
210 buf_free(block);
211 buf_free(subject);
212 return (err);
213 }
214
215 int t2_decrypt(BUFFER *in)
216 {
217 int err = 0;
218 BUFFER *msg;
219
220 msg = buf_new();
221 do {
222 err = mix_dearmor(in, msg);
223 if (err != -1) {
224 if (v3_magic(msg->data))
225 err = mix3_decrypt(msg);
226 else
227 err = mix2_decrypt(msg);
228 }
229 }
230 while (in->ptr + 1000 < in->length); /* accept several packets in one message */
231
232 buf_free(msg);
233 return (err);
234 }
235
236 int mix_pool(BUFFER *msg, int type, long latent)
237 {
238 char path[PATHMAX], pathtmp[PATHMAX];
239 FILE *f;
240 int err = -1;
241
242 f = pool_new(latent > 0 ? "lat" : "msg", pathtmp, path);
243 if (f != NULL) {
244 if (latent > 0)
245 fprintf(f, "%d %ld\n", type, latent + time(NULL));
246 else
247 fprintf(f, "%d 0\n", type);
248 err = buf_write(msg, f);
249 fclose(f);
250 }
251 if (err == 0) {
252 rename(pathtmp, path);
253 errlog(DEBUGINFO, "Added message to pool.\n");
254 }
255 return (err);
256 }
257
258 int pool_packetfile(char *fname, BUFFER *mid, int packetnum)
259 /* create a filename */
260 {
261 #ifdef SHORTNAMES
262 sprintf(fname, "%s%cp%02x%02x%02x%01x.%02x", POOLDIR, DIRSEP,
263 mid->data[0], mid->data[1], mid->data[2], mid->data[3] & 15,
264 packetnum);
265 #else
266 sprintf(fname, "%s%cp%02x%02x%02x%02x%02x%02x%01x", POOLDIR, DIRSEP,
267 packetnum, mid->data[0], mid->data[1], mid->data[2], mid->data[3],
268 mid->data[4], mid->data[5] & 15);
269 #endif
270 return (0);
271 }
272
273 void pool_packetexp(void)
274 {
275 DIR *d;
276 struct dirent *e;
277 struct stat sb;
278
279 d = opendir(POOLDIR);
280 if (d != NULL)
281 for (;;) {
282 e = readdir(d);
283 if (e == NULL)
284 break;
285 if (e->d_name[0] == 'p') {
286 if (stat(e->d_name, &sb) == 0 &&
287 time(NULL) - sb.st_mtime > PACKETEXP) {
288 errlog(NOTICE, "Expiring partial message %s.\n",
289 e->d_name);
290 unlink(e->d_name);
291 }
292 }
293 }
294 closedir(d);
295 }
296
297 void logmail(char *mailbox, BUFFER *message)
298 {
299 time_t t;
300 struct tm *tc;
301 char line[LINELEN];
302
303 /* mailbox is "|program", "user@host", "stdout" or "filename" */
304 buf_rewind(message);
305 if (mailbox[0] == '\0') /* default action */
306 mailbox = MAILBOX;
307 if (strieq(mailbox, "stdout"))
308 buf_write(message, stdout);
309 else if (mailbox[0] == '|') {
310 FILE *p;
311
312 errlog(DEBUGINFO, "Piping message to %s.", mailbox + 1);
313 p = openpipe(mailbox + 1);
314 if (p != NULL) {
315 buf_write(message, p);
316 closepipe(p);
317 }
318 } else if (strchr(mailbox, '@')) {
319 BUFFER *field, *content;
320
321 field = buf_new();
322 content = buf_new();
323 while (buf_getheader(message, field, content) == 0)
324 if (bufieq(field, "x-loop") && bufifind(content, REMAILERADDR)) {
325 errlog(WARNING, "Loop detected! Message not sent to %s.\n", mailbox);
326 goto isloop;
327 }
328 buf_sets(content, mailbox);
329 sendmail(message, NULL, content);
330 isloop:
331 buf_free(field);
332 buf_free(content);
333 } else {
334 FILE *mbox;
335
336 mbox = mix_openfile(mailbox, "a");
337 if (mbox == NULL) {
338 errlog(ERRORMSG, "Can't write to mail folder %s\n", mailbox);
339 return;
340 }
341 lock(mbox);
342 if (!bufileft(message, "From ")) {
343 t = time(NULL);
344 tc = localtime(&t);
345 strftime(line, LINELEN, "From Mixmaster %a %b %d %H:%M:%S %Y\n", tc);
346 fprintf(mbox, line);
347 }
348 buf_write(message, mbox);
349 fprintf(mbox, "\n");
350 unlock(mbox);
351 fclose(mbox);
352 }
353 }
354
355 int blockrequest(BUFFER *message)
356 {
357 int request = 0, domain;
358 BUFFER *from, *line, *field, *content, *addr;
359 FILE *f;
360 char *destblklst = (char *)malloc( strlen(DESTBLOCK)+1 );
361 char *destblk;
362
363 from = buf_new();
364 line = buf_new();
365 field = buf_new();
366 content = buf_new();
367 addr = buf_new();
368
369 buf_rewind(message);
370 while (buf_getheader(message, field, content) == 0)
371 if (bufieq(field, "from"))
372 buf_set(from, content);
373 else if (bufieq(field, "subject"))
374 buf_cat(message, content);
375 while (buf_getline(message, line) != -1)
376 if (bufifind(line, "destination-block")) {
377 buf_clear(addr);
378 request = 1;
379 if (buffind(line, "@")) {
380 int c = 0;
381
382 while (!strileft(line->data + line->ptr, "block"))
383 line->ptr++;
384 while (c != ' ')
385 c = tolower(buf_getc(line));
386 while (c == ' ')
387 c = buf_getc(line);
388 do {
389 buf_appendc(addr, c);
390 c = buf_getc(line);
391 } while (c > ' ');
392 } else
393 buf_set(addr, from);
394 if (bufieq(addr, REMAILERADDR)) {
395 errlog(LOG, "Ignoring blocking request for %b from %b.\n", addr, from);
396 return (2);
397 }
398 if (buf_ieq(addr, from))
399 errlog(NOTICE, "Blocking request for %b\n", addr);
400 else
401 errlog(NOTICE, "Blocking request for %b from %b\n", addr, from);
402 if (AUTOBLOCK) {
403 domain = 0;
404 if (addr->data[0] == '@') {
405 domain = 1;
406 buf_sets(line, "postmaster");
407 buf_cat(line, addr);
408 buf_move(addr, line);
409 }
410 buf_clear(line);
411 rfc822_addr(addr, line);
412 if (strchr(line->data, '@') && strchr(strchr(line->data, '@'), '.')) {
413 strcpy( destblklst, DESTBLOCK );
414 destblk = strtok( destblklst, " " );
415 f = mix_openfile( destblk, "a" );
416 free( destblklst );
417 if (f != NULL) {
418 lock(f);
419 sendinfofile(BLOCKFILE, NULL, line, NULL);
420 if (line->length) {
421 if (domain)
422 fprintf(f, "%s", line->data + sizeof("postmaster") - 1);
423 else
424 fprintf(f, "%s", line->data);
425 } else
426 errlog(NOTICE, "%b already blocked.\n", addr);
427 unlock(f);
428 fclose(f);
429 } else
430 errlog(ERRORMSG, "Can't write to %s.\n", DESTBLOCK);
431 } else
432 errlog(WARNING, "Invalid address not added to %s: %b\n", DESTBLOCK,
433 addr);
434 }
435 }
436 return (request);
437 }
438
439
440 int idexp(void)
441 {
442 FILE *f;
443 BUFFER *b;
444 long now, then;
445 char line[LINELEN];
446 LOCK *i;
447
448 if (IDEXP == 0)
449 return (0);
450
451 b = buf_new();
452 f = mix_openfile(IDLOG, "r");
453 if (f == NULL)
454 return (-1);
455 i = lockfile(IDLOG);
456 now = time(NULL);
457 fgets(line, sizeof(line), f); /* replace first line */
458 while (fgets(line, sizeof(line), f) != NULL) {
459 sscanf(line, "%*s %ld", &then);
460 if (now - then < IDEXP)
461 buf_appends(b, line);
462 }
463 fclose(f);
464 f = mix_openfile(IDLOG, "w");
465 if (f != NULL) {
466 fprintf(f, "expired %ld\n", now - IDEXP);
467 buf_write(b, f);
468 fclose(f);
469 }
470 unlockfile(i);
471 return (0);
472 }

  ViewVC Help
Powered by ViewVC 1.1.5