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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 375 - (show annotations) (download)
Fri Oct 18 00:45:12 2002 UTC (10 years, 7 months ago) by rabbi
File MIME type: text/plain
File size: 30125 byte(s)
Fixed some comments.
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 Mixmaster initialization, configuration
9 $Id: mix.c,v 1.37 2002/10/18 00:45:12 rabbi Exp $ */
10
11
12 #include "mix3.h"
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <stdarg.h>
17 #include <ctype.h>
18 #include <time.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #ifdef POSIX
22 #include <signal.h>
23 #include <unistd.h>
24 #include <pwd.h>
25 #include <sys/utsname.h>
26 #else /* end of POSIX */
27 #include <io.h>
28 #include <direct.h>
29 #endif /* else if not POSIX */
30 #ifdef WIN32
31 #include <windows.h>
32 #endif /* WIN32 */
33 #include <assert.h>
34 #include "menu.h"
35
36 int buf_vappendf(BUFFER *b, char *fmt, va_list args);
37
38 /** filenames ************************************************************/
39 char MIXCONF[PATHMAX] = DEFAULT_MIXCONF;
40 char DISCLAIMFILE[PATHMAX];
41 char FROMDSCLFILE[PATHMAX];
42 char MSGFOOTERFILE[PATHMAX];
43 char POP3CONF[PATHMAX];
44 char HELPFILE[PATHMAX];
45 char ABUSEFILE[PATHMAX];
46 char REPLYFILE[PATHMAX];
47 char USAGEFILE[PATHMAX];
48 char USAGELOG[PATHMAX];
49 char BLOCKFILE[PATHMAX];
50 char ADMKEYFILE[PATHMAX];
51 char KEYFILE[PATHMAX];
52 char PGPKEY[PATHMAX];
53 char DSAPARAMS[PATHMAX];
54 char DHPARAMS[PATHMAX];
55 char MIXRAND[PATHMAX];
56 char SECRING[PATHMAX];
57 char PUBRING[PATHMAX];
58 char IDLOG[PATHMAX];
59 char STATS[PATHMAX];
60 char DESTBLOCK[PATHMAX];
61 char DESTALLOW[PATHMAX];
62 char SOURCEBLOCK[PATHMAX];
63 char HDRFILTER[PATHMAX];
64 char REGULAR[PATHMAX];
65 char POOL[PATHMAX];
66 char TYPE1LIST[PATHMAX];
67 char TYPE2REL[PATHMAX];
68 char TYPE2LIST[PATHMAX];
69 char PIDFILE[PATHMAX];
70
71 char PGPREMPUBRING[PATHMAX];
72 char PGPREMPUBASC[PATHMAX];
73 char PGPREMSECRING[PATHMAX];
74 char NYMSECRING[PATHMAX];
75 char NYMDB[PATHMAX];
76
77
78 /** config ***************************************************************/
79
80 char MIXDIR[PATHMAX];
81 char POOLDIR[PATHMAX];
82
83 /* programs */
84 char SENDMAIL[LINELEN];
85 char SENDANONMAIL[LINELEN];
86 char NEWS[LINELEN];
87 char TYPE1[LINELEN];
88
89 /* addresses */
90 char MAILtoNEWS[LINELEN];
91 char REMAILERNAME[LINELEN];
92 char ANONNAME[LINELEN];
93 char REMAILERADDR[LINELEN];
94 char ANONADDR[LINELEN];
95 char COMPLAINTS[LINELEN];
96 int AUTOREPLY;
97 char SMTPRELAY[LINELEN];
98 char SMTPUSERNAME[LINELEN];
99 char SMTPPASSWORD[LINELEN];
100
101 #ifdef USE_SOCK
102 char HELONAME[LINELEN];
103 char ENVFROM[LINELEN];
104 int POP3DEL;
105 int POP3SIZELIMIT;
106 long POP3TIME;
107
108 #endif /* USE_SOCK */
109
110 char SHORTNAME[LINELEN];
111
112 /* remailer configuration */
113 int REMAIL;
114 int MIX;
115 int PGP;
116 int UNENCRYPTED;
117 int REMIX;
118 int REPGP;
119
120 int POOLSIZE;
121 int RATE;
122 int INDUMMYP;
123 int OUTDUMMYP;
124 int INDUMMYMAXP;
125 int OUTDUMMYMAXP;
126 int MIDDLEMAN;
127 int AUTOBLOCK;
128 char FORWARDTO[LINELEN];
129 int SIZELIMIT; /* maximal size of remailed messages */
130 int INFLATEMAX; /* maximal size of Inflate: padding */
131 int MAXRANDHOPS;
132 int BINFILTER; /* filter binary attachments? */
133 int LISTSUPPORTED; /* list supported remailers in remailer-conf reply? */
134 long PACKETEXP; /* Expiration time for old packets */
135 long IDEXP; /* 0 = no ID log !! */
136 long SENDPOOLTIME; /* frequency for sending pool messages */
137 long MAILINTIME; /* frequency for processing MAILIN mail */
138
139 long KEYLIFETIME;
140 long KEYOVERLAPPERIOD;
141 long KEYGRACEPERIOD;
142
143 char ERRLOG[LINELEN];
144 char ADDRESS[LINELEN];
145 char NAME[LINELEN];
146
147 char ORGANIZATION[LINELEN];
148 char MID[LINELEN];
149
150 /* client config */
151 int NUMCOPIES;
152 char CHAIN[LINELEN];
153 int VERBOSE;
154 int DISTANCE;
155 int MINREL;
156 int RELFINAL;
157 long MAXLAT;
158 char PGPPUBRING[PATHMAX];
159 char PGPSECRING[PATHMAX];
160 char PASSPHRASE[LINELEN];
161 char MAILIN[PATHMAX];
162 char MAILBOX[PATHMAX];
163 char MAILABUSE[PATHMAX];
164 char MAILBLOCK[PATHMAX];
165 char MAILUSAGE[PATHMAX];
166 char MAILANON[PATHMAX];
167 char MAILERROR[PATHMAX];
168 char MAILBOUNCE[PATHMAX];
169
170 char ENTEREDPASSPHRASE[LINELEN] = "";
171
172 static int rereadconfig = 0;
173 static int terminatedaemon = 0;
174
175 #if defined(S_IFDIR) && !defined(S_ISDIR)
176 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
177 #endif /* defined(S_IFDIR) && !defined(S_ISDIR) */
178
179 static int mixdir(char *d, int create)
180 {
181 int err;
182 struct stat buf;
183
184 if (d != MIXDIR)
185 strncpy(MIXDIR, d, PATHMAX);
186 if (MIXDIR[strlen(MIXDIR) - 1] == DIRSEP)
187 MIXDIR[strlen(MIXDIR) - 1] = '\0';
188 err = stat(MIXDIR, &buf);
189 if (err == -1) {
190 if (create) {
191 #ifndef POSIX
192 err = mkdir(MIXDIR);
193 #else /* end of not POSIX */
194 err = mkdir(MIXDIR, S_IRWXU);
195 #endif /* else if POSIX */
196 if (err == 0)
197 errlog(NOTICE, "Creating directory %s.\n", MIXDIR);
198 } else
199 err = 1;
200 } else if (!S_ISDIR(buf.st_mode))
201 err = -1;
202 if (err == 0)
203 strcatn(MIXDIR, DIRSEPSTR, PATHMAX);
204 return (err);
205 }
206
207 void whoami(char *addr, char *defaultname)
208 {
209 char *p = NULL;
210
211 #if defined(HAVE_GETDOMAINNAME) || (defined(HAVE_GETHOSTNAME) && ! defined(HAVE_UNAME))
212 char line[LINELEN];
213
214 #endif /* defined(HAVE_GETDOMAINNAME) || [...] */
215 #ifdef HAVE_UNAME
216 struct utsname uts;
217
218 #endif /* HAVE_UNAME */
219 #ifdef POSIX
220 p = getlogin();
221 #endif /* POSIX */
222 if (p == NULL)
223 strcpy(addr, defaultname);
224 else
225 strncpy(addr, p, LINELEN);
226
227 strcatn(addr, "@", LINELEN);
228 #ifdef HAVE_UNAME
229 if (uname(&uts) != -1)
230 strcatn(addr, uts.nodename, LINELEN);
231 #elif defined(HAVE_GETHOSTNAME) /* end of HAVE_UNAME */
232 if (gethostname(line, LINELEN) == 0)
233 strcatn(addr, line, LINELEN);
234 #endif /* defined(HAVE_GETHOSTNAME) */
235 if (addr[strlen(addr) - 1] == '@')
236 strcatn(addr, SHORTNAME, LINELEN);
237
238 if (strchr(strchr(addr, '@'), '.') == NULL) {
239 #ifdef HAVE_GETDOMAINNAME
240 if (getdomainname(line, LINELEN) == 0 && !streq(line, "(none)")) {
241 strcatn(addr, ".", LINELEN);
242 strcatn(addr, line, LINELEN);
243 }
244 #endif /* HAVE_GETDOMAINNAME */
245 }
246 }
247
248 #define read_conf(t) readconfline(line, #t, sizeof(#t)-1, t)
249
250 static int readconfline(char *line, char *name, int namelen, char *var)
251 {
252 if (strncmp(line, name, namelen) == 0 &&
253 (isspace(line[namelen]) || line[namelen] == '=')) {
254 line += namelen;
255 if (*line == '=')
256 line++;
257 while (isspace(*line))
258 line++;
259 if (line[0] == '\n' || line[0] == '\0') /* leave default */
260 return (1);
261 strncpy(var, line, LINELEN);
262 if (var[strlen(var) - 1] == '\n')
263 var[strlen(var) - 1] = '\0';
264 return (1);
265 } else
266 return (0);
267 }
268
269 #define read_conf_i(t) readiconfline(line, #t, sizeof(#t)-1, &t)
270
271 static int readiconfline(char *line, char *name, int namelen, int *var)
272 {
273 if (strncmp(line, name, namelen) == 0 &&
274 (isspace(line[namelen]) || line[namelen] == '=')) {
275 line += namelen;
276 if (*line == '=')
277 line++;
278 while (isspace(*line))
279 line++;
280 if (line[0] == '\n' || line[0] == '\0') /* leave default */
281 return (1);
282 switch (tolower(line[0])) {
283 case 'n':
284 *var = 0;
285 break;
286 case 'y':
287 *var = 1;
288 break;
289 case 'x':
290 *var = 2;
291 break;
292 default:
293 sscanf(line, "%d", var);
294 }
295 return (1);
296 } else
297 return (0);
298 }
299
300 #define read_conf_t(t) readtconfline(line, #t, sizeof(#t)-1, &t)
301
302 static int readtconfline(char *line, char *name, int namelen, long *var)
303 {
304 char *linenext;
305 int mod = 0;
306 long l = 0;
307 long n;
308
309 if (strncmp(line, name, namelen) == 0 &&
310 (isspace(line[namelen]) || line[namelen] == '=')) {
311 line += namelen;
312 if (*line == '=')
313 line++;
314 for (;; line++) {
315 n = strtol(line, &linenext, 10);
316 if (linenext == line)
317 break;
318 line = linenext;
319 mod = 1;
320 assert(line != NULL);
321 while (isspace(*line))
322 line++;
323 switch (tolower(*line)) {
324 case 'y': /* years */
325 l += 365 * 24 * 60 * 60 * n;
326 break;
327 case 'b': /* months */
328 l += 30 * 24 * 60 * 60 * n;
329 break;
330 case 'w': /* weeks */
331 l += 7 * 24 * 60 * 60 * n;
332 break;
333 case 'd': /* days */
334 l += 24 * 60 * 60 * n;
335 break;
336 case 's': /* seconds */
337 l += n;
338 break;
339 case 'm': /* minutes */
340 l += 60 * n;
341 break;
342 case 'h': /* hours - default */
343 default:
344 l += 60 * 60 * n;
345 break;
346 }
347 }
348 if (mod)
349 *var = l;
350 return (1);
351 } else
352 return (0);
353 }
354
355 static void mix_setdefaults()
356 {
357 #define strnncpy(a,b) strncpy(a, b, sizeof(a)); a[sizeof(a)-1] = '\0'
358
359 strnncpy(DISCLAIMFILE , DEFAULT_DISCLAIMFILE);
360 strnncpy(FROMDSCLFILE , DEFAULT_FROMDSCLFILE);
361 strnncpy(MSGFOOTERFILE, DEFAULT_MSGFOOTERFILE);
362 strnncpy(POP3CONF , DEFAULT_POP3CONF);
363 strnncpy(HELPFILE , DEFAULT_HELPFILE);
364 strnncpy(ABUSEFILE , DEFAULT_ABUSEFILE);
365 strnncpy(REPLYFILE , DEFAULT_REPLYFILE);
366 strnncpy(USAGEFILE , DEFAULT_USAGEFILE);
367 strnncpy(USAGELOG , DEFAULT_USAGELOG);
368 strnncpy(BLOCKFILE , DEFAULT_BLOCKFILE);
369 strnncpy(ADMKEYFILE , DEFAULT_ADMKEYFILE);
370 strnncpy(KEYFILE , DEFAULT_KEYFILE);
371 strnncpy(PGPKEY , DEFAULT_PGPKEY);
372 strnncpy(DSAPARAMS , DEFAULT_DSAPARAMS);
373 strnncpy(DHPARAMS , DEFAULT_DHPARAMS);
374 strnncpy(MIXRAND , DEFAULT_MIXRAND);
375 strnncpy(SECRING , DEFAULT_SECRING);
376 strnncpy(PUBRING , DEFAULT_PUBRING);
377 strnncpy(IDLOG , DEFAULT_IDLOG);
378 strnncpy(STATS , DEFAULT_STATS);
379 strnncpy(DESTBLOCK , DEFAULT_DESTBLOCK);
380 strnncpy(DESTALLOW , DEFAULT_DESTALLOW);
381 strnncpy(SOURCEBLOCK , DEFAULT_SOURCEBLOCK);
382 strnncpy(HDRFILTER , DEFAULT_HDRFILTER);
383 strnncpy(REGULAR , DEFAULT_REGULAR);
384 strnncpy(POOL , DEFAULT_POOL);
385 strnncpy(TYPE1LIST , DEFAULT_TYPE1LIST);
386 strnncpy(TYPE2REL , DEFAULT_TYPE2REL);
387 strnncpy(TYPE2LIST , DEFAULT_TYPE2LIST);
388 strnncpy(PIDFILE , DEFAULT_PIDFILE);
389
390 strnncpy(PGPREMPUBRING, DEFAULT_PGPREMPUBRING);
391 strnncpy(PGPREMPUBASC , DEFAULT_PGPREMPUBASC);
392 strnncpy(PGPREMSECRING, DEFAULT_PGPREMSECRING);
393 strnncpy(NYMSECRING , DEFAULT_NYMSECRING);
394 strnncpy(NYMDB , DEFAULT_NYMDB);
395
396
397 strnncpy(MIXDIR , "");
398 strnncpy(POOLDIR , "");
399
400 /* programs */
401 #ifdef WIN32
402 strnncpy(SENDMAIL , "outfile");
403 #else /* end of WIN32 */
404 strnncpy(SENDMAIL , "/usr/lib/sendmail -t");
405 #endif /* else if not WIN32 */
406 strnncpy(SENDANONMAIL , "");
407 strnncpy(NEWS , "");
408 strnncpy(TYPE1 , "");
409
410 /* addresses */
411 strnncpy(MAILtoNEWS , "mail2news@anon.lcs.mit.edu");
412 strnncpy(REMAILERNAME , "Anonymous Remailer");
413 strnncpy(ANONNAME , "Anonymous");
414 strnncpy(REMAILERADDR , "");
415 strnncpy(ANONADDR , "");
416 strnncpy(COMPLAINTS , "");
417 strnncpy(SMTPRELAY , "");
418 AUTOREPLY = 0;
419
420 #ifdef USE_SOCK
421 strnncpy(HELONAME , "");
422 strnncpy(ENVFROM , "");
423 POP3DEL = 0;
424 POP3SIZELIMIT = 0;
425 POP3TIME = 60 * 60;
426
427 #endif /* USE_SOCK */
428
429 strnncpy(SHORTNAME , "");
430
431 /* configuration */
432 REMAIL = 0;
433 MIX = 1;
434 PGP = 1;
435 UNENCRYPTED = 0;
436 REMIX = 1;
437 REPGP = 1;
438
439 POOLSIZE = 0;
440 RATE = 100;
441 INDUMMYP = 3; /* add dummy messages with probability p for each message added to the pool */
442 OUTDUMMYP = 10; /* add dummy messages with probability p each time we send from the pool */
443 INDUMMYMAXP = 84; /* for both of the above: while (rnd < p) { senddummy(); } */
444 OUTDUMMYMAXP = 96; /* set max INDUMMYP and OUTDUMMYP such that 24 and 5.25 dummy messages will */
445 MIDDLEMAN = 0; /* be generated on average. More than this is insane. */
446 AUTOBLOCK = 1;
447 strnncpy(FORWARDTO, "*");
448 SIZELIMIT = 0; /* maximal size of remailed messages */
449 INFLATEMAX = 50; /* maximal size of Inflate: padding */
450 MAXRANDHOPS = 20;
451 BINFILTER = 0; /* filter binary attachments? */
452 LISTSUPPORTED = 1; /* list supported remailers in remailer-conf reply? */
453 PACKETEXP = 7 * SECONDSPERDAY; /* Expiration time for old packets */
454 IDEXP = 7 * SECONDSPERDAY; /* 0 = no ID log !! */
455 SENDPOOLTIME = 60 * 60; /* frequency for sending pool messages */
456 MAILINTIME = 5 * 60; /* frequency for processing MAILIN mail */
457
458 KEYLIFETIME = 13 * 30 * 24 * 60 * 60; /* validity period for keys. */
459 KEYOVERLAPPERIOD = 1 * 30 * 24 * 60 * 60; /* when keys have this amount of time */
460 /* left before expiration, create */
461 /* new ones when ./mix -K is run.*/
462 KEYGRACEPERIOD = 7 * 24 * 60 * 60; /* accept mail to the old key for this */
463 /* amount of time after it has expired. */
464
465
466 strnncpy(ERRLOG , "");
467 strnncpy(ADDRESS , "");
468 strnncpy(NAME , "");
469
470 strnncpy(ORGANIZATION, "Anonymous Posting Service");
471 strnncpy(MID , "y");
472
473 /* client config */
474 NUMCOPIES = 1;
475 strnncpy(CHAIN, "*,*,*,*");
476 VERBOSE = 2;
477 DISTANCE = 2;
478 MINREL = 98;
479 RELFINAL = 99;
480 MAXLAT = 36 * 60 * 60;
481 strnncpy(PGPPUBRING, "");
482 strnncpy(PGPSECRING, "");
483 #ifdef COMPILEDPASS
484 strnncpy(PASSPHRASE, COMPILEDPASS);
485 #else /* end of COMPILEDPASS */
486 strnncpy(PASSPHRASE, "");
487 #endif /* else if not COMPILEDPASS */
488 strnncpy(MAILIN , "");
489 strnncpy(MAILBOX , "mbox");
490 strnncpy(MAILABUSE , "");
491 strnncpy(MAILBLOCK , "");
492 #ifdef WIN32
493 strnncpy(MAILUSAGE , "nul:");
494 strnncpy(MAILANON , "nul:");
495 strnncpy(MAILERROR , "nul:");
496 #else /* end of WIN32 */
497 strnncpy(MAILUSAGE , "/dev/null");
498 strnncpy(MAILANON , "/dev/null");
499 strnncpy(MAILERROR , "/dev/null");
500 #endif /* else if not WIN32 */
501 strnncpy(MAILBOUNCE, "");
502 }
503
504 int mix_configline(char *line)
505 {
506 return (read_conf(ADDRESS) || read_conf(NAME) ||
507 read_conf(SHORTNAME) || read_conf(REMAILERADDR) ||
508 read_conf(ANONADDR) || read_conf(REMAILERNAME) ||
509 read_conf(ANONNAME) || read_conf(COMPLAINTS) ||
510 read_conf_i(AUTOREPLY) || read_conf(SMTPRELAY) ||
511 read_conf(SMTPUSERNAME) || read_conf(SMTPPASSWORD) ||
512 #ifdef USE_SOCK
513 read_conf(HELONAME) || read_conf(ENVFROM) ||
514 #endif /* USE_SOCK */
515 read_conf(SENDMAIL) || read_conf(SENDANONMAIL) ||
516 read_conf_i(REMAIL) || read_conf_i(MIX) ||
517 read_conf_i(PGP) || read_conf_i(UNENCRYPTED) ||
518 read_conf_i(REMIX) || read_conf(NEWS) ||
519 read_conf_i(REPGP) ||
520 read_conf(MAILtoNEWS) || read_conf(ERRLOG) ||
521 read_conf(ORGANIZATION) || read_conf(MID) ||
522 read_conf(TYPE1) || read_conf_i(POOLSIZE) ||
523 read_conf_i(RATE) || read_conf_i(MIDDLEMAN) ||
524 read_conf_i(INDUMMYP) ||
525 read_conf_i(OUTDUMMYP) ||
526 read_conf_i(AUTOBLOCK) || read_conf(FORWARDTO) ||
527 read_conf_i(SIZELIMIT) || read_conf_i(INFLATEMAX) ||
528 read_conf_i(MAXRANDHOPS) || read_conf_i(BINFILTER) ||
529 read_conf_i(LISTSUPPORTED) ||
530 read_conf_t(PACKETEXP) || read_conf_t(IDEXP) ||
531 read_conf_t(SENDPOOLTIME) || read_conf_i(NUMCOPIES) ||
532 read_conf_t(MAILINTIME) ||
533 read_conf(CHAIN) || read_conf_i(VERBOSE) ||
534 read_conf_i(DISTANCE) || read_conf_i(MINREL) ||
535 read_conf_i(RELFINAL) || read_conf_t(MAXLAT) ||
536 read_conf(PGPPUBRING) || read_conf(PGPSECRING) ||
537 read_conf(PASSPHRASE) || read_conf_t(KEYLIFETIME) ||
538 read_conf_t(KEYGRACEPERIOD) || read_conf_t(KEYOVERLAPPERIOD) ||
539 #ifdef USE_SOCK
540 read_conf_i(POP3DEL) || read_conf_i(POP3SIZELIMIT) ||
541 read_conf_t(POP3TIME) ||
542 #endif /* USE_SOCK */
543 read_conf(MAILBOX) || read_conf(MAILABUSE) ||
544 read_conf(MAILBLOCK) || read_conf(MAILUSAGE) ||
545 read_conf(MAILANON) || read_conf(MAILERROR) ||
546 read_conf(MAILBOUNCE) || read_conf(MAILIN) ||
547
548 read_conf(DISCLAIMFILE) || read_conf(FROMDSCLFILE) ||
549 read_conf(MSGFOOTERFILE) ||
550 read_conf(POP3CONF) || read_conf(HELPFILE) ||
551 read_conf(ABUSEFILE) || read_conf(REPLYFILE) ||
552 read_conf(USAGEFILE) || read_conf(USAGELOG) ||
553 read_conf(BLOCKFILE) || read_conf(ADMKEYFILE) ||
554 read_conf(KEYFILE) || read_conf(PGPKEY) ||
555 read_conf(DSAPARAMS) || read_conf(DHPARAMS) ||
556 read_conf(MIXRAND) || read_conf(SECRING) ||
557 read_conf(PUBRING) || read_conf(IDLOG) ||
558 read_conf(STATS) || read_conf(DESTBLOCK) ||
559 read_conf(DESTALLOW) || read_conf(SOURCEBLOCK) ||
560 read_conf(HDRFILTER) || read_conf(REGULAR) ||
561 read_conf(POOL) || read_conf(TYPE1LIST) ||
562 read_conf(TYPE2REL) || read_conf(TYPE2LIST) ||
563 read_conf(PGPREMPUBRING) || read_conf(PGPREMPUBASC) ||
564 read_conf(PGPREMSECRING) || read_conf(NYMSECRING) ||
565 read_conf(NYMDB) || read_conf(PIDFILE) );
566 }
567
568 int mix_config(void)
569 {
570 char *d;
571 FILE *f;
572 char line[PATHMAX];
573 int err = -1;
574 #ifdef POSIX
575 struct passwd *pw;
576 #endif /* POSIX */
577 struct stat buf;
578 #ifdef HAVE_UNAME
579 struct utsname uts;
580 #endif /* HAVE_UNAME */
581 #ifdef WIN32
582 HKEY regsw, reg, regpgp;
583 DWORD type, len;
584 int rkey = 0;
585 #endif /* WIN32 */
586
587 mix_setdefaults();
588
589 #ifdef POSIX
590 pw = getpwuid(getuid());
591 #endif /* POSIX */
592
593 #ifdef WIN32
594 RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, &regsw);
595 len=sizeof(line);
596 if (err == -1 &&
597 RegOpenKeyEx(regsw, "Mixmaster", 0, KEY_QUERY_VALUE, &reg) == 0) {
598 if (RegQueryValueEx(reg, "MixDir", 0, &type, line, &len) == 0)
599 err = mixdir(line, 1);
600 RegCloseKey(reg);
601 }
602 #endif /* WIN32 */
603
604 if (err == -1 && (d = getenv("MIXPATH")) != NULL)
605 err = mixdir(d, 1);
606
607 #ifdef SPOOL
608 if (err == -1 && strlen(SPOOL) > 0)
609 err = mixdir(SPOOL, 0);
610 #endif /* SPOOL */
611
612 #ifdef POSIX
613 if (err == -1 && pw != NULL) {
614 strncpy(line, pw->pw_dir, PATHMAX);
615 line[PATHMAX-1] = '\0';
616 if (line[strlen(line) - 1] != DIRSEP)
617 strcatn(line, DIRSEPSTR, PATHMAX);
618 strcatn(line, HOMEMIXDIR, PATHMAX);
619 err = mixdir(line, 1);
620 }
621 #endif /* POSIX */
622
623 if (err == -1) {
624 getcwd(MIXDIR, PATHMAX);
625 mixdir(MIXDIR, 0);
626 }
627
628 #ifdef GLOBALMIXCONF
629 f = mix_openfile(GLOBALMIXCONF, "r");
630 if (f != NULL) {
631 while (fgets(line, LINELEN, f) != NULL)
632 if (line[0] > ' ' && line[0] != '#')
633 mix_configline(line);
634 fclose(f);
635 }
636 #endif /* GLOBALMIXCONF */
637 f = mix_openfile(MIXCONF, "r");
638 if (f != NULL) {
639 while (fgets(line, LINELEN, f) != NULL)
640 if (line[0] > ' ' && line[0] != '#')
641 mix_configline(line);
642 fclose(f);
643 }
644
645 mixfile(POOLDIR, POOL); /* set POOLDIR after reading POOL from cfg file */
646 if (POOLDIR[strlen(POOLDIR) - 1] == DIRSEP)
647 POOLDIR[strlen(POOLDIR) - 1] = '\0';
648 if (stat(POOLDIR, &buf) != 0)
649 if
650 #ifndef POSIX
651 (mkdir(POOLDIR) != 0)
652 #else /* end of not POSIX */
653 (mkdir(POOLDIR, S_IRWXU) == -1)
654 #endif /* else if POSIX */
655 strncpy(POOLDIR, MIXDIR, PATHMAX);
656
657 if (IDEXP > 0 && IDEXP < 5 * SECONDSPERDAY)
658 IDEXP = 5 * SECONDSPERDAY;
659 if (MAXRANDHOPS > 20)
660 MAXRANDHOPS = 20;
661 if (INDUMMYP > INDUMMYMAXP)
662 INDUMMYP = INDUMMYMAXP;
663 if (OUTDUMMYP > OUTDUMMYMAXP)
664 OUTDUMMYP = OUTDUMMYMAXP;
665
666 if (strchr(SHORTNAME, '.'))
667 *strchr(SHORTNAME, '.') = '\0';
668 if (strchr(SHORTNAME, ' '))
669 *strchr(SHORTNAME, ' ') = '\0';
670 #ifdef HAVE_UNAME
671 if (SHORTNAME[0] == '\0' && uname(&uts) != -1)
672 strncpy(SHORTNAME, uts.nodename, LINELEN);
673 #elif defined(HAVE_GETHOSTNAME) /* end of HAVE_UNAME */
674 if (SHORTNAME[0] == '\0')
675 gethostname(SHORTNAME, LINELEN);
676 #endif /* defined(HAVE_GETHOSTNAME) */
677 if (SHORTNAME[0] == '\0')
678 strcpy(SHORTNAME, "unknown");
679
680 if (ADDRESS[0] == '\0')
681 whoami(ADDRESS, "user");
682
683 #ifdef HAVE_GECOS
684 if (NAME[0] == '\0' && pw != NULL)
685 strcatn(NAME, pw->pw_gecos, sizeof(NAME));
686 #endif /* HAVE_GECOS */
687
688 if (REMAILERADDR[0] == '\0')
689 strncpy(REMAILERADDR, ADDRESS, LINELEN);
690
691 if (COMPLAINTS[0] == '\0')
692 strncpy(COMPLAINTS, REMAILERADDR, LINELEN);
693
694 if (strchr(REMAILERNAME, '@') == NULL) {
695 strcatn(REMAILERNAME, " <", LINELEN);
696 strcatn(REMAILERNAME, REMAILERADDR, LINELEN);
697 strcatn(REMAILERNAME, ">", LINELEN);
698 }
699 if (strchr(ANONNAME, '@') == NULL && ANONADDR[0] != '\0') {
700 strcatn(ANONNAME, " <", LINELEN);
701 strcatn(ANONNAME, ANONADDR, LINELEN);
702 strcatn(ANONNAME, ">", LINELEN);
703 }
704 if (strchr(ANONNAME, '@') == NULL) {
705 strcatn(ANONNAME, " <", LINELEN);
706 strcatn(ANONNAME, REMAILERADDR, LINELEN);
707 strcatn(ANONNAME, ">", LINELEN);
708 }
709 #ifndef USE_PGP
710 if (TYPE1[0] == '\0')
711 PGP = 0;
712 #endif /* not USE_PGP */
713 #ifndef USE_RSA
714 MIX = 0;
715 #endif /* not USE_RSA */
716
717 #ifdef WIN32
718 if (RegOpenKeyEx(regsw, "PGP", 0, KEY_ALL_ACCESS, &regpgp) == 0)
719 rkey++;
720 if (rkey && RegOpenKeyEx(regpgp, "PGPlib", 0, KEY_QUERY_VALUE, &reg) == 0)
721 rkey++;
722 if (PGPPUBRING[0] == '\0' && rkey == 2) {
723 len = PATHMAX;
724 RegQueryValueEx(reg, "PubRing", 0, &type, PGPPUBRING, &len);
725 }
726 if (PGPSECRING[0] == '\0' && rkey == 2) {
727 len = PATHMAX;
728 RegQueryValueEx(reg, "SecRing", 0, &type, PGPSECRING, &len);
729 }
730 if (rkey == 2)
731 RegCloseKey(reg);
732 if (rkey)
733 RegCloseKey(regpgp);
734 RegCloseKey(regsw);
735 #endif /* WIN32 */
736
737 if (PGPPUBRING[0] == '\0') {
738 char *d;
739
740 if ((d = getenv("HOME")) != NULL) {
741 strcpy(PGPPUBRING, d);
742 strcatn(PGPPUBRING, "/.pgp/", PATHMAX);
743 }
744 strcatn(PGPPUBRING, "pubring.pkr", PATHMAX);
745 if (stat(PGPPUBRING, &buf) == -1)
746 strcpy(strrchr(PGPPUBRING, '.'), ".pgp");
747 }
748 if (PGPSECRING[0] == '\0') {
749 char *d;
750
751 if ((d = getenv("HOME")) != NULL) {
752 strcpy(PGPSECRING, d);
753 strcatn(PGPSECRING, "/.pgp/", PATHMAX);
754 }
755 strcatn(PGPSECRING, "secring.skr", PATHMAX);
756 if (stat(PGPSECRING, &buf) == -1)
757 strcpy(strrchr(PGPSECRING, '.'), ".pgp");
758 }
759 if (streq(NEWS, "mail-to-news"))
760 strncpy(NEWS, MAILtoNEWS, sizeof(NEWS));
761
762 if (f == NULL) {
763 #ifndef GLOBALMIXCONF
764 /* Only write the config file in non systemwide installation */
765 f = mix_openfile(MIXCONF, "w");
766 if (f == NULL)
767 errlog(WARNING, "Can't open %s%s!\n", MIXDIR, MIXCONF);
768 else {
769 fprintf(f, "# mix.cfg - mixmaster configuration file\n");
770 fprintf(f, "NAME %s\n", NAME);
771 fprintf(f, "ADDRESS %s\n", ADDRESS);
772 fprintf(f, "\n# edit to set up a remailer:\n");
773 fprintf(f, "REMAIL n\n");
774 fprintf(f, "SHORTNAME %s\n", SHORTNAME);
775 fprintf(f, "REMAILERADDR %s\n", REMAILERADDR);
776 fprintf(f, "COMPLAINTS %s\n", COMPLAINTS);
777 fclose(f);
778 }
779 #endif /* not GLOBALMIXCONF */
780 REMAIL = 0;
781 }
782
783 if (ENTEREDPASSPHRASE[0] != '\0') {
784 strncpy(PASSPHRASE, ENTEREDPASSPHRASE, LINELEN);
785 PASSPHRASE[LINELEN-1] = 0;
786 };
787
788 return (0);
789 }
790
791 /** Library initialization: ******************************************/
792
793 static int initialized = 0;
794
795 int mix_init(char *mixdir)
796 {
797 if (!initialized) {
798 if (mixdir)
799 strncpy(MIXDIR, mixdir, LINELEN);
800 mix_config();
801 #if defined(USE_SOCK) && defined(WIN32)
802 sock_init();
803 #endif /* defined(USE_SOCK) && defined(WIN32) */
804 /* atexit (mix_exit); */
805 initialized = 1;
806 }
807
808 if (rnd_init() == -1)
809 rnd_seed();
810 return(0);
811 }
812
813 void mix_exit(void)
814 {
815 if (!initialized)
816 return;
817 rnd_final();
818 #if defined(USE_SOCK) && defined(WIN32)
819 sock_exit();
820 #endif /* defined(USE_SOCK) && defined(WIN32) */
821 initialized=0;
822 }
823
824 int mix_regular(int force)
825 {
826 FILE *f;
827 long now, tpool = 0, tpop3 = 0, tdaily = 0, tmailin = 0;
828 int ret = 0;
829
830 mix_init(NULL);
831 now = time(NULL);
832
833 f = mix_openfile(REGULAR, "r+");
834 if (f != NULL) {
835 lock(f);
836 fscanf(f, "%ld %ld %ld %ld", &tpool, &tpop3, &tdaily, &tmailin);
837 if (now - tpool >= SENDPOOLTIME)
838 force |= FORCE_POOL | FORCE_MAILIN;
839 #ifdef USE_SOCK
840 if (now - tpop3 >= POP3TIME)
841 force |= FORCE_POP3 | FORCE_MAILIN;
842 #endif /* USE_SOCK */
843 if (now - tdaily >= SECONDSPERDAY)
844 force |= FORCE_DAILY;
845 if (now - tmailin >= MAILINTIME)
846 force |= FORCE_MAILIN;
847 if (force & FORCE_POOL)
848 tpool = now;
849 if (force & FORCE_POP3)
850 tpop3 = now;
851 if (force & FORCE_DAILY)
852 tdaily = now;
853 if (force & FORCE_MAILIN)
854 tmailin = now;
855 rewind(f);
856 fprintf(f, "%ld %ld %ld %ld\n", tpool, tpop3, tdaily, tmailin);
857 unlock(f);
858 fclose(f);
859 } else {
860 force = FORCE_POOL | FORCE_POP3 | FORCE_DAILY | FORCE_MAILIN;
861 f = mix_openfile(REGULAR, "w+");
862 if (f != NULL) {
863 lock(f);
864 fprintf(f, "%ld %ld %ld %ld\n", now, now, now, now);
865 unlock(f);
866 fclose(f);
867 } else
868 errlog(ERRORMSG, "Can't create %s!\n", REGULAR);
869 }
870
871 if (force & FORCE_DAILY)
872 mix_daily(), ret = 1;
873 #ifdef USE_SOCK
874 if (force & FORCE_POP3)
875 pop3get();
876 #endif /* USE_SOCK */
877 if (force & FORCE_MAILIN)
878 ret = process_mailin();
879 if (force & FORCE_POOL)
880 ret = pool_send();
881
882 return (ret);
883 }
884
885 int mix_daily(void)
886 {
887 idexp();
888 pool_packetexp();
889 stats(NULL);
890 keymgt(0);
891 return (0);
892 }
893
894 /** Handle signals SIGHUP, SIGINT, and SIGTERM
895 This signal handler gets called if the daemon
896 process receives one of SIGHUP, SIGINT, or SIGTERM.
897 It then sets either rereadconfig of terminatedaemon
898 to true depending on the signal received.
899
900 @author PP
901 @return nothing
902 */
903 #ifdef POSIX
904 void sighandler(int signal) {
905 if (signal == SIGHUP)
906 rereadconfig = 1;
907 else if (signal == SIGINT || signal == SIGTERM)
908 terminatedaemon = 1;
909 };
910 #endif /* POSIX */
911
912 /** Set the signal handler for SIGHUP, SIGINT and SIGTERM
913 This function registers signal handlers so that
914 we can react on signals send by the user in daemon
915 mode. SIGHUP will instruct mixmaster to reload its
916 configuration while SIGINT and SIGTERM will instruct
917 it to shut down. Mixmaster will finish the current
918 pool run before it terminates.
919
920 @param restart Whether or not system calls should be
921 restarted. Usually we want this, the
922 only excetion is the sleep() in the
923 daemon mail loop.
924 @author PP
925 @return -1 if calling sigaction failed, 0 on
926 no error
927 */
928 int setsignalhandler(int restart)
929 {
930 #ifdef POSIX
931 struct sigaction hdl;
932 int err = 0;
933
934 memset(&hdl, 0, sizeof(hdl));
935 hdl.sa_handler = sighandler;
936 hdl.sa_flags = restart ? SA_RESTART : 0;
937
938 if (sigaction(SIGHUP, &hdl, NULL))
939 err = -1;
940 if (sigaction(SIGINT, &hdl, NULL))
941 err = -1;
942 if (sigaction(SIGTERM, &hdl, NULL))
943 err = -1;
944 return (err);
945 #else /* POSIX */
946 return(0);
947 #endif /* POSIX */
948 }
949
950 #ifdef WIN32
951 /* Try to detect if we are the service or not...
952 seems there is no easy reliable way */
953 int is_nt_service(void)
954 {
955 static int issvc = -1;
956 #ifdef WIN32SERVICE
957 STARTUPINFO StartupInfo;
958 OSVERSIONINFO VersionInfo;
959 DWORD dwsize;
960
961 if (issvc != -1) /* do it only once */
962 return issvc;
963
964 VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
965 if (GetVersionEx(&VersionInfo))
966 if (VersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
967 return issvc = 0; /* not NT - not the service */
968
969 GetStartupInfo(&StartupInfo);
970 if (StartupInfo.lpDesktop[0] == 0)
971 return issvc = 1; /* have no desktop - we are the service probably */
972 #endif /* WIN32SERVICE */
973
974 return issvc = 0; /* assume not the service */
975 } /* is_nt_service */
976
977 HANDLE hMustTerminate = NULL;
978 void set_nt_exit_event(HANDLE h_svc_exit_event)
979 {
980 hMustTerminate = h_svc_exit_event;
981 } /* set_nt_exit_event */
982
983 #endif /* WIN32 */
984
985 int mix_daemon(void)
986 {
987 long t, slept;
988 t = SENDPOOLTIME;
989 if (MAILINTIME < t && (MAILIN != NULL && MAILIN[0] != '\0'))
990 t = MAILINTIME;
991 #ifdef USE_SOCK
992 if (POP3TIME < t)
993 t = POP3TIME;
994 #endif /* USE_SOCK */
995 if (t < 5)
996 t = 5; /* Some kind of safety for broken systems */
997 slept = t;
998
999 setsignalhandler(1); /* set signal handlers and restart any interrupted system calls */
1000 for(;;) {
1001 if (terminatedaemon)
1002 break;
1003 if (rereadconfig) {
1004 rereadconfig = 0;
1005 mix_config();
1006 t = SENDPOOLTIME;
1007 if (MAILINTIME < t && (MAILIN != NULL && MAILIN[0] != '\0'))
1008 t = MAILINTIME;
1009 #ifdef USE_SOCK
1010 if (POP3TIME < t)
1011 t = POP3TIME;
1012 if (t < 5)
1013 t = 5; /* Some kind of safety for broken systems */
1014 #endif /* USE_SOCK */
1015 }
1016 if (slept >= t) {
1017 mix_regular(0);
1018 slept = 0;
1019 }
1020
1021 #ifdef WIN32SERVICE
1022 if (hMustTerminate) {
1023 if (WaitForSingleObject(hMustTerminate, t * 1000) == WAIT_OBJECT_0) {
1024 CloseHandle(hMustTerminate);
1025 terminatedaemon = 1;
1026 }
1027 }
1028 #endif /* WIN32SERVICE */
1029
1030 if (!terminatedaemon && !rereadconfig) {
1031 setsignalhandler(0); /* set signal handlers; don't restart system calls */
1032 #ifdef WIN32
1033 Sleep(t * 1000); /* how to get the real number of seconds slept? */
1034 slept = t;
1035 #else /* end of WIN32 */
1036 slept += (t - slept) - sleep(t - slept);
1037 #endif /* else if not WIN32 */
1038 setsignalhandler(1); /* set signal handlers and restart any interrupted system calls */
1039 }
1040 }
1041 return (0);
1042 }
1043
1044 /** error ***************************************************************/
1045
1046 void errlog(int type, char *fmt,...)
1047 {
1048 va_list args;
1049 BUFFER *msg;
1050 FILE *e = NULL;
1051 time_t t;
1052 struct tm *tc;
1053 char line[LINELEN];
1054 int p;
1055 char err[6][8] =
1056 {"", "Error", "Warning", "Notice", "Info", "Info"};
1057
1058 if ((VERBOSE == 0 && type != ERRORMSG) || (type == LOG && VERBOSE < 2)
1059 || (type == DEBUGINFO && VERBOSE < 3))
1060 return;
1061
1062 t = time(NULL);
1063 tc = localtime(&t);
1064 strftime(line, LINELEN, "[%Y-%m-%d %H:%M:%S] ", tc);
1065
1066 msg = buf_new();
1067 buf_appends(msg, line);
1068 p = msg->length;
1069 buf_appendf(msg, "%s: ", err[type]);
1070 va_start(args, fmt);
1071 buf_vappendf(msg, fmt, args);
1072 va_end(args);
1073
1074 if (streq(ERRLOG, "stdout"))
1075 e = stdout;
1076 else if (streq(ERRLOG, "stderr"))
1077 e = stderr;
1078
1079 if (e == NULL && (ERRLOG[0] == '\0' ||
1080 (e = mix_openfile(ERRLOG, "a")) == NULL))
1081 mix_status("%s", msg->data + p);
1082 else {
1083 buf_write(msg, e);
1084 if (e != stderr && e != stdout) {
1085 fclose(e);
1086 /* duplicate the error message on screen */
1087 mix_status("%s", msg->data + p);
1088 }
1089 }
1090 buf_free(msg);
1091 }
1092
1093 static char statusline[BUFSIZE] = "";
1094
1095 void mix_status(char *fmt,...)
1096 {
1097 va_list args;
1098
1099 if (fmt != NULL) {
1100 va_start(args, fmt);
1101 #ifdef _MSC
1102 _vsnprintf(statusline, sizeof(statusline) - 1, fmt, args);
1103 #else /* end of _MSC */
1104 vsnprintf(statusline, sizeof(statusline) - 1, fmt, args);
1105 #endif /* else if not _MSC */
1106 va_end(args);
1107 }
1108 #ifdef USE_NCURSES
1109 if (menu_initialized) {
1110 cl(LINES - 2, 10);
1111 printw("%s", statusline);
1112 refresh();
1113 } else
1114 #endif /* USE_NCURSES */
1115 {
1116 fprintf(stderr, "%s", statusline);
1117 }
1118 }
1119
1120 void mix_genericerror(void)
1121 {
1122 if (streq(statusline, "") || strfind(statusline, "...") ||
1123 strifind(statusline, "generating"))
1124 mix_status("Failed!");
1125 else
1126 mix_status(NULL);
1127 }

  ViewVC Help
Powered by ViewVC 1.1.5