main.c (22681B)
1 /* Mixmaster version 3.0 -- (C) 1999 - 2006 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 Command-line based frontend 9 $Id: main.c 937 2006-06-24 15:52:20Z colin $ */ 10 11 12 #include "mix3.h" 13 #include "pgp.h" 14 #include <stdio.h> 15 #include <string.h> 16 #include <ctype.h> 17 #include <stdlib.h> 18 #ifdef POSIX 19 #include <unistd.h> 20 #else /* end of POSIX */ 21 #include <io.h> 22 #endif /* else if not POSIX */ 23 #include <assert.h> 24 25 static char *largopt(char *p, char *opt, char *name, int *error); 26 static void noarg(char *name, char p); 27 static int check_get_pass(int force, int never_ask_for_passphrase); 28 29 /** main *****************************************************************/ 30 31 /* Returns: 32 0 successful operation 33 1 command line error 34 2 client error condition */ 35 36 #ifdef WIN32SERVICE 37 int mix_main(int argc, char *argv[]) 38 #else 39 int main(int argc, char *argv[]) 40 #endif /* WIN32SERVICE */ 41 { 42 int error = 0, deflt = 1, help = 0, readmail = 0, send = -1, sendpool = 0, 43 header = 1, maint = 0, keygen = 0, verbose = 0, sign = 0, encrypt = 0, 44 redirect_mail = 0, about=0, version=0; 45 int daemon = 0, type_list = 0, nodetach = 0; 46 int update_stats = 0, update_pingerlist = 0; 47 int never_ask_for_passphrase = 0; 48 49 #ifdef USE_SOCK 50 int pop3 = 0; 51 52 #endif /* USE_SOCK */ 53 char *filename = NULL; 54 int i; 55 int ret = 0; 56 char *p, *q; 57 char chain[1024] = ""; 58 char nym[LINELEN] = ""; 59 BUFFER *nymopt, *pseudonym, *attachments, *statssrc; 60 int numcopies = 0; /* default value set in mix.cfg */ 61 BUFFER *msg, *chainlist, *field, *content; 62 FILE *f; 63 char pingpath[PATHMAX]; 64 65 /* Check if parse_yearmonthday works */ 66 assert(parse_yearmonthday("2003-04-01") == 1049155200); 67 68 mix_init(NULL); 69 70 msg = buf_new(); 71 chainlist = buf_new(); 72 nymopt = buf_new(); 73 pseudonym = buf_new(); 74 attachments = buf_new(); 75 field = buf_new(); 76 content = buf_new(); 77 statssrc = buf_new(); 78 79 #ifdef USE_NCURSES 80 if (argc == 1) { 81 if (isatty(fileno(stdin))) 82 menu_main(); 83 else 84 menu_folder(0, NULL); 85 goto clientpool; 86 } 87 #endif /* USE_NCURSES */ 88 if (argc > 1 && strleft(argv[1], "-f")) { 89 menu_folder(strlen(argv[1]) > 2 ? argv[1][2] : 0, argc < 3 ? NULL : argv[2]); 90 goto clientpool; 91 } 92 for (i = 1; i < argc; i++) { 93 p = argv[i]; 94 if (p[0] == '-' && p[1] != '\0') { 95 if (p[1] == '-') { 96 p += 2; 97 if (strieq(p, "help")) 98 help = 1, deflt = 0; 99 else if (streq(p, "version")) 100 version = 1, deflt = 0; 101 else if (streq(p, "about")) 102 about = 1, deflt = 0; 103 else if (streq(p, "verbose")) 104 verbose = 1; 105 else if (streq(p, "type-list")) 106 type_list = 1; 107 else if (streq(p, "dummy")) 108 send = MSG_NULL, deflt = 0; 109 else if (streq(p, "remailer")) 110 maint = 1, deflt = 0; 111 else if (streq(p, "generate-key")) 112 keygen = 2, deflt = 0; 113 else if (streq(p, "update-keys")) 114 keygen = 1, deflt = 0; 115 else if (streq(p, "send")) 116 sendpool = 1, deflt = 0; 117 else if (streq(p, "read-mail")) 118 readmail = 1, deflt = 0; 119 else if (streq(p, "redirect")) 120 redirect_mail = 1, deflt = 0; 121 else if (streq(p, "store-mail")) 122 readmail = 2, deflt = 0; 123 #ifdef USE_SOCK 124 else if (streq(p, "pop-mail")) 125 pop3 = 1, deflt = 0; 126 #endif /* USE_SOCK */ 127 else if (streq(p, "daemon")) 128 daemon = 1, deflt = 0; 129 else if (streq(p, "no-detach")) 130 nodetach = 1; 131 else if (streq(p, "post")) 132 send = MSG_POST; 133 else if (streq(p, "mail")) 134 send = MSG_MAIL; 135 else if (streq(p, "sign")) 136 sign = 1; 137 else if (streq(p, "encrypt")) 138 encrypt = 1; 139 else if (streq(p, "no-ask-passphrase")) 140 never_ask_for_passphrase = 1; 141 else if (streq(p, "update-pinger-list")) 142 update_pingerlist = 1; 143 else if (streq(p, "update-stats")) { 144 buf_clear(statssrc); 145 f = mix_openfile(STATSSRC, "r"); 146 if (f != NULL) { 147 buf_read(statssrc, f); 148 fclose(f); 149 } 150 if (statssrc->length > 0) { 151 update_stats = 1; 152 } else { 153 deflt = 0; 154 fprintf(stderr, "%s: No current stats source --%s\n", argv[0], p); 155 } 156 } else if (strleft(p, "update-stats") && p[strlen("update-stats")] == '=') { 157 buf_clear(statssrc); 158 buf_appendf(statssrc, "%s", (p + strlen("update-stats") + 1)); 159 if (statssrc->length > 0) { 160 update_stats = 1; 161 } else { 162 fprintf(stderr, "%s: No stats source specified --%s\n", argv[0], p); 163 } 164 } else if ((q = largopt(p, "to", argv[0], &error)) != NULL) { 165 header = 0; 166 buf_appendf(msg, "To: %s\n", q); 167 } else if ((q = largopt(p, "post-to", argv[0], &error)) != NULL) { 168 send = MSG_POST, header = 0; 169 buf_appendf(msg, "Newsgroups: %s\n", q); 170 } else if ((q = largopt(p, "subject", argv[0], &error)) != NULL) { 171 buf_appendf(msg, "Subject: %s\n", q); 172 } else if ((q = largopt(p, "header", argv[0], &error)) != NULL) { 173 buf_appendf(msg, "%s\n", q); 174 } else if ((q = largopt(p, "chain", argv[0], &error)) != NULL) { 175 buf_appendf(msg, "Chain: %s\n", q); 176 } 177 #ifdef USE_PGP 178 else if ((q = largopt(p, "reply-chain", argv[0], &error)) != NULL) { 179 buf_appendf(msg, "Reply-Chain: %s\n", q); 180 } else if ((q = largopt(p, "latency", argv[0], &error)) != NULL) { 181 buf_appendf(msg, "Latency: %s\n", q); 182 } else if ((q = largopt(p, "attachment", argv[0], &error)) != NULL) { 183 buf_appendf(attachments, "%s\n", q); 184 #ifdef NYMSUPPORT 185 } else if ((q = largopt(p, "nym-config", argv[0], &error)) != NULL) { 186 deflt = 0; 187 strncpy(nym, q, sizeof(nym)); 188 if (i > argc && strileft(argv[i + 1], "name=")) 189 buf_sets(pseudonym, argv[++i] + 5); 190 else if (i > argc && strileft(argv[i + 1], "opt=")) 191 buf_appends(nymopt, argv[++i] + 5); 192 } else if ((q = largopt(p, "nym", argv[0], &error)) != NULL) { 193 buf_appendf(msg, "Nym: %s\n", q); 194 #endif /* NYMSUPPORT */ 195 } 196 #endif /* USE_PGP */ 197 else if ((q = largopt(p, "copies", argv[0], &error)) != NULL) { 198 sscanf(q, "%d", &numcopies); 199 } else if ((q = largopt(p, "config", argv[0], &error)) != NULL) { 200 strncpy(MIXCONF, q, PATHMAX); 201 MIXCONF[PATHMAX-1] = 0; 202 mix_config(); /* configuration file changed - reread it */ 203 } else if (error == 0 && mix_configline(p) == 0) { 204 fprintf(stderr, "%s: Invalid option %s\n", argv[0], argv[i]); 205 error = 1; 206 } 207 } else { 208 while (*++p) { 209 switch (*p) { 210 case 'd': 211 send = MSG_NULL, deflt = 0; 212 break; 213 case 'R': 214 readmail = 1, deflt = 0; 215 break; 216 case 'I': 217 readmail = 2, deflt = 0; 218 break; 219 case 'S': 220 sendpool = 1, deflt = 0; 221 break; 222 case 'M': 223 maint = 1, deflt = 0; 224 break; 225 #ifdef USE_SOCK 226 case 'P': 227 pop3 = 1, deflt = 0; 228 break; 229 #endif /* USE_SOCK */ 230 case 'D': 231 daemon = 1, deflt = 0; 232 break; 233 case 'G': 234 keygen = 2, deflt = 0; 235 break; 236 case 'K': 237 keygen = 1, deflt = 0; 238 break; 239 case 'L': /* backwards compatibility */ 240 break; 241 case 'v': 242 verbose = 1; 243 break; 244 case 'h': 245 help = 1, deflt = 0; 246 break; 247 case 'T': 248 type_list = 1; 249 break; 250 case 'V': 251 version = 1, deflt = 0; 252 break; 253 case 't': 254 if (*(p + 1) == 'o') 255 p++; 256 header = 0; 257 if (i < argc - 1) 258 buf_appendf(msg, "To: %s\n", argv[++i]); 259 else { 260 fprintf(stderr, "%s: Missing argument for option -to\n", argv[0]); 261 error = 1; 262 } 263 break; 264 case 's': 265 if (i < argc - 1) 266 buf_appendf(msg, "Subject: %s\n", argv[++i]); 267 else { 268 noarg(argv[0], *p); 269 error = 1; 270 } 271 break; 272 case 'l': 273 if (i < argc - 1) 274 buf_appendf(msg, "Chain: %s\n", argv[++i]); 275 else { 276 noarg(argv[0], *p); 277 error = 1; 278 } 279 break; 280 case 'r': 281 if (i < argc - 1) 282 buf_appendf(msg, "Reply-Chain: %s\n", argv[++i]); 283 else { 284 noarg(argv[0], *p); 285 error = 1; 286 } 287 break; 288 #ifdef USE_PGP 289 case 'n': 290 if (i < argc - 1) 291 buf_appendf(msg, "Nym: %s\n", argv[++i]); 292 else { 293 noarg(argv[0], *p); 294 error = 1; 295 } 296 break; 297 #endif /* USE_PGP */ 298 case 'c': 299 if (i < argc - 1) 300 sscanf(argv[++i], "%d", &numcopies); 301 else { 302 noarg(argv[0], *p); 303 error = 1; 304 } 305 break; 306 case 'p': 307 send = MSG_POST; 308 break; 309 case 'g': 310 if (i < argc - 1) { 311 send = MSG_POST, header = 0; 312 buf_appendf(msg, "Newsgroups: %s\n", argv[++i]); 313 } else { 314 noarg(argv[0], *p); 315 error = 1; 316 } 317 break; 318 case 'a': 319 if (i < argc - 1) 320 buf_appendf(attachments, "%s\n", argv[++i]); 321 else { 322 noarg(argv[0], *p); 323 error = 1; 324 } 325 break; 326 case 'm': 327 send = MSG_MAIL; 328 break; 329 default: 330 fprintf(stderr, "%s: Invalid option -%c\n", argv[0], *p); 331 error = 1; 332 break; 333 } 334 } 335 } 336 } else { 337 if (strchr(argv[i], '@')) { 338 header = 0; 339 buf_appendf(msg, "To: %s\n", argv[i]); 340 } else { 341 if (filename == NULL) 342 filename = argv[i]; 343 else { 344 fprintf(stderr, "%s: Error in command line: %s\n", argv[0], argv[i]); 345 error = 1; 346 } 347 } 348 } 349 } 350 351 if (error) { 352 ret = 1; 353 goto end; 354 } 355 356 if (type_list) { 357 BUFFER *type2list; 358 type2list = buf_new(); 359 if (prepare_type2list(type2list) < 0) { 360 fprintf(stderr, "Cannot print type2.list.\n"); 361 ret = 2; 362 } else { 363 printf("%s", type2list->data); 364 }; 365 buf_free(type2list); 366 goto end; 367 } 368 369 if (version) { 370 printf("Mixmaster %s\n", VERSION); 371 ret = 0; 372 goto end; 373 } 374 375 if (update_pingerlist) { 376 mixfile(pingpath, ALLPINGERSFILE); 377 if (verbose) printf ("downloading %s...\n", ALLPINGERSURL); 378 if (url_download(ALLPINGERSURL, pingpath) < 0) { 379 printf(" Download failed... Try again later.\n"); 380 errlog(ERRORMSG, "All Pingers File Download failed.\n"); 381 } else { 382 if (verbose) printf(" Done.\n"); 383 errlog(LOG, "All Pingers File Downloaded OK.\n"); 384 } 385 ret = 0; 386 goto end; 387 } 388 389 if (update_stats) { 390 ret = download_stats(statssrc->data); 391 if (ret == -3) { 392 fprintf(stderr, "Stats source does not include all required files.\n"); 393 } else if (ret == -2) { 394 fprintf(stderr, "Could not open stats source file for writing\n"); 395 } else if (ret == -1) { 396 fprintf(stderr, "Stats source download failed.\n"); 397 } 398 ret = 0; 399 goto end; 400 } 401 402 #ifdef USE_NCURSES 403 /* If we get here then it's possible we still want to use the NCURSES interface */ 404 if (deflt && (send == -1) && isatty(fileno(stdin))) { 405 menu_main(); 406 goto clientpool; 407 } 408 #endif /* USE_NCURSES */ 409 410 if (help ||about ||(isatty(fileno(stdin)) && isatty(fileno(stdout)))) 411 fprintf(stderr, "Mixmaster %s\n", VERSION); 412 if (help ||about) 413 printf("\n\n"); 414 if (about) { 415 printf("Many people have contributed to the source code for Mixmaster.\n"); 416 printf("These contributors include:\n\n"); 417 printf("Lance Cottrell\n"); 418 printf("Janis Jagars\n"); 419 printf("Ulf Moeller\n"); 420 printf("Peter Palfrader\n"); 421 printf("Len Sassaman\n"); 422 printf("\nand others. For full information on copyright and license issues,\n"); 423 printf("read the bundled file COPYRIGHT.\n\n"); 424 ret = 0; 425 goto end; 426 } 427 428 if (help) { 429 printf("Usage: %s [options] [user@host] [filename]\n\n", argv[0]); 430 printf("Options:\n\ 431 \n\ 432 -h, --help summary of command line options\n\ 433 -V, --version print version information\n\ 434 --about print authorship information\n\ 435 -T, --type-list list available remailers\n\ 436 -t, --to=user@host the recipient's address(es)\n\ 437 -g, --post-to=newsgroup newsgroup(s) to post to\n\ 438 -p, --post input is a Usenet article\n\ 439 -m, --mail input is a mail message\n\ 440 -s, --subject=subject message subject\n\ 441 --header='header line' arbitrary message headers\n\ 442 -a, --attachment=file attach a file\n" 443 #ifdef USE_PGP 444 #ifdef NYMSUPPORT 445 "-n, --nym=yournym use pseudonym to send the message\n" 446 #endif /* NYMSUPPORT */ 447 " --encrypt encrypt the message using the PGP format\n\ 448 --sign sign the message using the PGP format\n" 449 #endif /* USE_PGP */ 450 "-l, --chain=mix1,mix2,mix3,... specify a remailer chain\n\ 451 -c, --copies=num send num copies to increase reliability\n\ 452 -d, --dummy generate a dummy message\n\ 453 -S, --send send the message(s) in the pool\n" 454 #ifdef USE_PGP 455 #ifdef NYMSUPPORT 456 " --nym-config=yournym generate a new pseudonym\n\ 457 --latency=hours reply chain latency\n\ 458 --reply-chain=rem1,rem2,... reply chain for the pseudonym\n" 459 #endif /* NYMSUPPORT */ 460 #endif /* USE_PGP */ 461 "-v, --verbose output informational messages\n\ 462 -f [file] read a mail folder\n\ 463 --update-pinger-list Download an updated all pingers list file\n\ 464 --update-stats[=source] Download updated stats\n" 465 466 #ifndef USE_NCURSES 467 "\n-fr, -ff, -fg [file] send reply/followup/group reply to a message\n" 468 #endif /* USE_NCURSES */ 469 "\nThe input file is expected to contain mail headers if no address is\n\ 470 specified in the command line.\n\ 471 \n\ 472 Remailer:\n\ 473 \n\ 474 -R, --read-mail read remailer message from stdin\n\ 475 -I, --store-mail read remailer msg from stdin, do not decrypt\n\ 476 -M, --remailer process the remailer pool\n\ 477 -D, --daemon remailer as background process\n\ 478 --no-detach do not detach from terminal as daemon\n" 479 #ifdef USE_SOCK 480 "-S, --send force sending messages from the pool\n" 481 #endif /* USE_SOCK */ 482 "-P, --pop-mail force getting messages from POP3 servers\n\ 483 -G, --generate-key generate a new remailer key\n\ 484 -K, --update-keys generate remailer keys if necessary\n\ 485 --config=file use alternate configuration file\n" 486 #ifdef WIN32SERVICE 487 "\n\ 488 WinNT service:\n\ 489 \n\ 490 --install-svc install the service\n\ 491 --remove-svc remove the service\n\ 492 --run-svc run as a service\n" 493 #endif /* WIN32SERVICE */ 494 ); 495 496 ret = 0; 497 goto end; 498 } 499 500 if (deflt && send == -1) 501 send = MSG_MAIL; 502 if (nym[0] != 0) 503 send = -1; 504 if ((send == MSG_MAIL || send == MSG_POST) && filename == NULL && 505 header == 1 && isatty(fileno(stdin))) { 506 /* we don't get here if USE_NCURSES is set */ 507 printf("Run `%s -h' to view a summary of the command line options.\n\nEnter the message, complete with headers.\n", 508 argv[0]); 509 #ifdef UNIX 510 printf("When done, press ^D.\n\n"); 511 #else 512 printf("When done, press ^Z.\n\n"); 513 #endif /* else not UNIX */ 514 } 515 if (header == 0) 516 buf_nl(msg); 517 518 /* timeskew check */ 519 if (REMAIL == 1) 520 mix_check_timeskew(); 521 522 if (readmail || redirect_mail || send == MSG_MAIL || send == MSG_POST) { 523 if (filename == NULL || streq(filename, "-")) 524 f = stdin; 525 else { 526 f = fopen(filename, "r"); 527 if (f == NULL) 528 fprintf(stderr, "Can't open %s.\n", filename); 529 } 530 531 if (f && buf_read(msg, f) != -1) { 532 if (readmail == 1) { 533 check_get_pass(1, never_ask_for_passphrase); 534 mix_decrypt(msg); 535 } else if (readmail == 2) 536 pool_add(msg, "inf"); 537 if (send == MSG_MAIL || send == MSG_POST || redirect_mail) { 538 BUFFER *sendmsg; 539 int numdest = 0; 540 541 sendmsg = buf_new(); 542 543 while (buf_getheader(msg, field, content) == 0) { 544 if (bufieq(field, "nym")) { 545 strncpy(nym, content->data, sizeof(nym)); 546 } else if (bufieq(field, "chain")) 547 if (strchr(content->data, ';')) { 548 i = strchr(content->data, ';') - (char *)content->data; 549 strncpy(chain, content->data, i); 550 if (strstr(content->data + i, "copies=") != NULL) { 551 sscanf(strstr(content->data + i, "copies=") + 552 sizeof("copies=") - 1, "%d", &numcopies); 553 } 554 } else 555 strncpy(chain, content->data, sizeof(chain)); 556 else { /* line goes into message */ 557 if (((redirect_mail || send == MSG_MAIL) && bufieq(field, "to")) 558 || (send == MSG_POST && bufieq(field, "newsgroups"))) 559 numdest++; 560 if (bufieq(field, "from") && !redirect_mail) 561 fprintf(stderr, "Warning: The message has a From: line.\n"); 562 buf_appendheader(sendmsg, field, content); 563 } 564 } 565 buf_nl(sendmsg); 566 buf_rest(sendmsg, msg); 567 568 while (buf_getline(attachments, field) != -1) 569 if (attachfile(sendmsg, field) == -1) { 570 errlog(ERRORMSG, "Can't attach %b!\n", field); 571 ret = 2; 572 goto end; 573 } 574 575 #ifdef USE_PGP 576 if (nym[0] != 0 && strchr(nym, '@') == NULL) 577 strcatn(nym, "@", sizeof(nym)); 578 if (sign || encrypt) { 579 BUFFER *pass; 580 581 pass = buf_new(); 582 user_pass(pass); 583 if (pgp_mailenc((encrypt ? PGP_ENCRYPT : 0) | 584 (nym[0] != 0 && sign ? PGP_SIGN : 0) | 585 PGP_TEXT | PGP_REMAIL, sendmsg, nym, 586 pass, NULL, NYMSECRING) != 0) { 587 fprintf(stderr, "Encryption failed: missing key!"); 588 ret = 2; 589 goto end; 590 } 591 buf_free(pass); 592 } 593 if (nym[0] != 0) { 594 #ifdef NYMSUPPORT 595 if (nym_encrypt(sendmsg, nym, send) == 0) 596 send = MSG_MAIL; 597 else 598 #endif /* NYMSUPPORT */ 599 fprintf(stderr, "Nym error, sending message anonymously.\n"); 600 } 601 #endif /* USE_PGP */ 602 if (numdest == 0) { 603 fprintf(stderr, "No destination address given!\n"); 604 ret = 2; 605 } else if (numcopies < 0 || numcopies > 10) { 606 fprintf(stderr, "Invalid number of copies!\n"); 607 ret = 2; 608 } else { 609 if ( ( redirect_mail ? 610 redirect_message(sendmsg, chain, numcopies, chainlist) : 611 mix_encrypt(send, sendmsg, chain, numcopies, chainlist) 612 ) == -1) { 613 ret = 2; 614 if (chainlist->length) 615 fprintf(stderr, "%s\n", chainlist->data); 616 else 617 fprintf(stderr, "Failed!\n"); 618 } else if (verbose) { 619 fprintf(stderr, "Chain: "); 620 buf_write(chainlist, stderr); 621 } 622 } 623 624 buf_free(sendmsg); 625 } 626 if (filename != NULL) 627 fclose(f); 628 } else 629 ret = 2; 630 } 631 if (send == MSG_NULL) { 632 if (msg->length) { 633 while (buf_getheader(msg, field, content) == 0) { 634 if (bufieq(field, "chain")) 635 strncpy(chain, content->data, sizeof(chain)); 636 } 637 } 638 if (mix_encrypt(MSG_NULL, NULL, chain, numcopies, chainlist) == -1) { 639 ret = 2; 640 if (chainlist->length) 641 printf("%s\n", chainlist->data); 642 else 643 fprintf(stderr, "Failed!\n"); 644 } else if (verbose) { 645 printf("Chain: "); 646 buf_write(chainlist, stdout); 647 } 648 } 649 #ifdef USE_PGP 650 #ifdef NYMSUPPORT 651 if (nym[0] != 0) { 652 char nymserver[LINELEN] = "*"; 653 BUFFER *chains; 654 655 chains = buf_new(); 656 if (numcopies < 1 || numcopies > 10) 657 numcopies = 1; 658 while (buf_getheader(msg, field, content) != -1) { 659 if (bufieq(field, "chain")) 660 strncpy(chain, content->data, sizeof(chain)); 661 else if (bufieq(field, "reply-chain")) 662 buf_appendf(chains, "Chain: %b\n", content); 663 else if (field->length) 664 buf_appendheader(chains, field, content); 665 else 666 buf_nl(chains); 667 } 668 if (strrchr(nym, '@')) { 669 strncpy(nymserver, strrchr(nym, '@'), sizeof(nymserver)); 670 *strrchr(nym, '@') = '\0'; 671 } 672 if (nym_config(NYM_CREATE, nym, nymserver, pseudonym, 673 chain, numcopies, chains, nymopt) < 0) { 674 ret = 2; 675 fprintf(stderr, "Failed!\n"); 676 } 677 user_delpass(); 678 buf_free(chains); 679 } 680 #endif /* NYMSUPPORT */ 681 #endif /* USE_PGP */ 682 683 if (keygen) { 684 check_get_pass(0, never_ask_for_passphrase); 685 keymgt(keygen); 686 } 687 if (sendpool) 688 mix_send(); 689 #ifdef USE_SOCK 690 if (pop3) 691 pop3get(); 692 #endif /* USE_SOCK */ 693 if (maint) { 694 check_get_pass(1, never_ask_for_passphrase); 695 mix_regular(0); 696 } 697 698 clientpool: 699 if ((REMAIL == 0) && (CLIENTAUTOFLUSH == 1)) { 700 SENDPOOLTIME = 0; 701 RATE = 100; 702 mix_send(); 703 }; 704 705 end: 706 buf_free(field); 707 buf_free(content); 708 buf_free(chainlist); 709 buf_free(msg); 710 buf_free(nymopt); 711 buf_free(pseudonym); 712 buf_free(attachments); 713 buf_free(statssrc); 714 715 if (daemon) { 716 check_get_pass(1, never_ask_for_passphrase); 717 #ifdef UNIX 718 if (! nodetach) { 719 int pid; 720 721 fprintf(stderr, "Detaching.\n"); 722 /* Detach as suggested by the Unix Programming FAQ */ 723 pid = fork(); 724 if (pid > 0) 725 exit(0); 726 if (setsid() < 0) { 727 /* This should never happen. */ 728 fprintf(stderr, "setsid() failed.\n"); 729 exit(1); 730 }; 731 pid = fork(); 732 if (pid > 0) 733 exit(0); 734 }; 735 if (chdir(MIXDIR) < 0) { 736 if (chdir("/") < 0) { 737 fprintf(stderr, "Cannot chdir to mixdir or /.\n"); 738 exit(1); 739 }; 740 }; 741 if (write_pidfile(PIDFILE)) { 742 fprintf(stderr, "Aborting.\n"); 743 exit(1); 744 } 745 if (! nodetach) { 746 freopen ("/dev/null", "r", stdin); 747 freopen ("/dev/null", "w", stdout); 748 freopen ("/dev/null", "w", stderr); 749 } 750 #endif /* UNIX */ 751 mix_daemon(); 752 #ifdef UNIX 753 /* ifdef this one too, so that we do not need to export it from windows dll */ 754 clear_pidfile(PIDFILE); 755 #endif /* UNIX */ 756 } 757 mix_exit(); 758 return (ret); 759 } 760 761 static char *largopt(char *p, char *opt, char *name, int *error) 762 { 763 if (streq(p, opt)) { 764 fprintf(stderr, "%s: Missing argument for option --%s\n", name, p); 765 *error = 1; 766 } else if (strleft(p, opt) && p[strlen(opt)] == '=') { 767 return (p + strlen(opt) + 1); 768 } 769 return (NULL); 770 } 771 772 static void noarg(char *name, char p) 773 { 774 fprintf(stderr, "%s: Missing argument for option -%c\n", name, p); 775 } 776 777 static int check_get_pass(int force, int never_ask_for_passphrase) 778 /* get a passphrase and check against keys 779 * if force != 0 passphrase must match with some key */ 780 { 781 BUFFER *pass, *pass2, *key; 782 int n = 0; 783 784 if (PASSPHRASE[0] == '\0' && isatty(fileno(stdin)) && ! never_ask_for_passphrase) { 785 pass = buf_new(); 786 pass2 = buf_new(); 787 key = buf_new(); 788 buf_sets(pass, PASSPHRASE); 789 while ( 790 #ifdef USE_PGP 791 pgpdb_getkey(PK_DECRYPT, PGP_ES_RSA, NULL, NULL, NULL, NULL, NULL, 792 NULL, NULL, NULL, pass) < 0 && 793 pgpdb_getkey(PK_DECRYPT, PGP_E_ELG, NULL, NULL, NULL, NULL, NULL, 794 NULL, NULL, NULL, pass) < 0 && 795 #endif /* USE_PGP */ 796 getv2seckey(NULL, key) < 0) 797 { 798 user_delpass(); 799 if (n) 800 fprintf(stderr, "re-"); 801 user_pass(pass); 802 strncpy(PASSPHRASE, pass->data, LINELEN); 803 PASSPHRASE[LINELEN-1] = 0; 804 if (!force) { 805 if (n && buf_eq(pass, pass2)) 806 break; 807 buf_set(pass2, pass); 808 } 809 n=1; 810 } 811 user_delpass(); 812 buf_free(pass); 813 buf_free(pass2); 814 buf_free(key); 815 816 strncpy(ENTEREDPASSPHRASE, PASSPHRASE, LINELEN); 817 ENTEREDPASSPHRASE[LINELEN-1] = 0; 818 } 819 return 1; 820 }