1 /* $OpenBSD: smtpd.c,v 1.234 2014/07/10 15:54:55 eric Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org> 5 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> 6 * Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/types.h> 22 #include <sys/queue.h> 23 #include <sys/tree.h> 24 #include <sys/socket.h> 25 #include <sys/wait.h> 26 #include <sys/stat.h> 27 #include <sys/uio.h> 28 #include <sys/mman.h> 29 30 #include <bsd_auth.h> 31 #include <dirent.h> 32 #include <err.h> 33 #include <errno.h> 34 #include <event.h> 35 #include <fcntl.h> 36 #include <imsg.h> 37 #include <inttypes.h> 38 #include <login_cap.h> 39 #include <paths.h> 40 #include <pwd.h> 41 #include <signal.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <time.h> 46 #include <unistd.h> 47 #include <util.h> 48 49 #include <openssl/ssl.h> 50 #include <openssl/evp.h> 51 52 #include "smtpd.h" 53 #include "log.h" 54 #include "ssl.h" 55 56 static void parent_imsg(struct mproc *, struct imsg *); 57 static void usage(void); 58 static void parent_shutdown(int); 59 static void parent_send_config(int, short, void *); 60 static void parent_send_config_lka(void); 61 static void parent_send_config_pony(void); 62 static void parent_send_config_ca(void); 63 static void parent_sig_handler(int, short, void *); 64 static void forkmda(struct mproc *, uint64_t, struct deliver *); 65 static int parent_forward_open(char *, char *, uid_t, gid_t); 66 static void fork_peers(void); 67 static struct child *child_add(pid_t, int, const char *); 68 69 static void offline_scan(int, short, void *); 70 static int offline_add(char *); 71 static void offline_done(void); 72 static int offline_enqueue(char *); 73 74 static void purge_task(void); 75 static int parent_auth_user(const char *, const char *); 76 static void load_pki_tree(void); 77 static void load_pki_keys(void); 78 79 enum child_type { 80 CHILD_DAEMON, 81 CHILD_MDA, 82 CHILD_ENQUEUE_OFFLINE, 83 }; 84 85 struct child { 86 pid_t pid; 87 enum child_type type; 88 const char *title; 89 int mda_out; 90 uint64_t mda_id; 91 char *path; 92 char *cause; 93 }; 94 95 struct offline { 96 TAILQ_ENTRY(offline) entry; 97 char *path; 98 }; 99 100 #define OFFLINE_READMAX 20 101 #define OFFLINE_QUEUEMAX 5 102 static size_t offline_running = 0; 103 TAILQ_HEAD(, offline) offline_q; 104 105 static struct event config_ev; 106 static struct event offline_ev; 107 static struct timeval offline_timeout; 108 109 static pid_t purge_pid = -1; 110 111 extern char **environ; 112 void (*imsg_callback)(struct mproc *, struct imsg *); 113 114 enum smtp_proc_type smtpd_process; 115 116 struct smtpd *env = NULL; 117 118 struct mproc *p_control = NULL; 119 struct mproc *p_lka = NULL; 120 struct mproc *p_parent = NULL; 121 struct mproc *p_queue = NULL; 122 struct mproc *p_scheduler = NULL; 123 struct mproc *p_pony = NULL; 124 struct mproc *p_ca = NULL; 125 126 const char *backend_queue = "fs"; 127 const char *backend_scheduler = "ramqueue"; 128 const char *backend_stat = "ram"; 129 130 int profiling = 0; 131 int verbose = 0; 132 int debug = 0; 133 int foreground = 0; 134 int control_socket = -1; 135 136 struct tree children; 137 138 static void 139 parent_imsg(struct mproc *p, struct imsg *imsg) 140 { 141 struct forward_req *fwreq; 142 struct deliver deliver; 143 struct child *c; 144 struct msg m; 145 const void *data; 146 const char *username, *password, *cause; 147 uint64_t reqid; 148 size_t sz; 149 void *i; 150 int fd, n, v, ret; 151 152 if (p->proc == PROC_LKA) { 153 switch (imsg->hdr.type) { 154 case IMSG_LKA_OPEN_FORWARD: 155 fwreq = imsg->data; 156 fd = parent_forward_open(fwreq->user, fwreq->directory, 157 fwreq->uid, fwreq->gid); 158 fwreq->status = 0; 159 if (fd == -1 && errno != ENOENT) { 160 if (errno == EAGAIN) 161 fwreq->status = -1; 162 } 163 else 164 fwreq->status = 1; 165 m_compose(p, IMSG_LKA_OPEN_FORWARD, 0, 0, fd, 166 fwreq, sizeof *fwreq); 167 return; 168 169 case IMSG_LKA_AUTHENTICATE: 170 /* 171 * If we reached here, it means we want root to lookup 172 * system user. 173 */ 174 m_msg(&m, imsg); 175 m_get_id(&m, &reqid); 176 m_get_string(&m, &username); 177 m_get_string(&m, &password); 178 m_end(&m); 179 180 ret = parent_auth_user(username, password); 181 182 m_create(p, IMSG_LKA_AUTHENTICATE, 0, 0, -1); 183 m_add_id(p, reqid); 184 m_add_int(p, ret); 185 m_close(p); 186 return; 187 } 188 } 189 190 if (p->proc == PROC_PONY) { 191 switch (imsg->hdr.type) { 192 case IMSG_MDA_FORK: 193 m_msg(&m, imsg); 194 m_get_id(&m, &reqid); 195 m_get_data(&m, &data, &sz); 196 m_end(&m); 197 if (sz != sizeof(deliver)) 198 fatalx("expected deliver"); 199 memmove(&deliver, data, sz); 200 forkmda(p, reqid, &deliver); 201 return; 202 203 case IMSG_MDA_KILL: 204 m_msg(&m, imsg); 205 m_get_id(&m, &reqid); 206 m_get_string(&m, &cause); 207 m_end(&m); 208 209 i = NULL; 210 while ((n = tree_iter(&children, &i, NULL, (void**)&c))) 211 if (c->type == CHILD_MDA && 212 c->mda_id == reqid && 213 c->cause == NULL) 214 break; 215 if (!n) { 216 log_debug("debug: smtpd: " 217 "kill request: proc not found"); 218 return; 219 } 220 221 c->cause = xstrdup(cause, "parent_imsg"); 222 log_debug("debug: smtpd: kill requested for %u: %s", 223 c->pid, c->cause); 224 kill(c->pid, SIGTERM); 225 return; 226 } 227 } 228 229 if (p->proc == PROC_CONTROL) { 230 switch (imsg->hdr.type) { 231 case IMSG_CTL_VERBOSE: 232 m_msg(&m, imsg); 233 m_get_int(&m, &v); 234 m_end(&m); 235 log_verbose(v); 236 return; 237 238 case IMSG_CTL_PROFILE: 239 m_msg(&m, imsg); 240 m_get_int(&m, &v); 241 m_end(&m); 242 profiling = v; 243 return; 244 245 case IMSG_CTL_SHUTDOWN: 246 parent_shutdown(0); 247 return; 248 } 249 } 250 251 errx(1, "parent_imsg: unexpected %s imsg from %s", 252 imsg_to_str(imsg->hdr.type), proc_title(p->proc)); 253 } 254 255 static void 256 usage(void) 257 { 258 extern char *__progname; 259 260 fprintf(stderr, "usage: %s [-dhnv] [-D macro=value] " 261 "[-f file] [-P system] [-T trace]\n", __progname); 262 exit(1); 263 } 264 265 static void 266 parent_shutdown(int ret) 267 { 268 void *iter; 269 struct child *child; 270 pid_t pid; 271 272 iter = NULL; 273 while (tree_iter(&children, &iter, NULL, (void**)&child)) 274 if (child->type == CHILD_DAEMON) 275 kill(child->pid, SIGTERM); 276 277 do { 278 pid = waitpid(WAIT_MYPGRP, NULL, 0); 279 } while (pid != -1 || (pid == -1 && errno == EINTR)); 280 281 unlink(SMTPD_SOCKET); 282 283 log_warnx("warn: parent terminating"); 284 exit(ret); 285 } 286 287 static void 288 parent_send_config(int fd, short event, void *p) 289 { 290 parent_send_config_lka(); 291 parent_send_config_pony(); 292 parent_send_config_ca(); 293 purge_config(PURGE_PKI); 294 } 295 296 static void 297 parent_send_config_pony(void) 298 { 299 log_debug("debug: parent_send_config: configuring pony process"); 300 m_compose(p_pony, IMSG_CONF_START, 0, 0, -1, NULL, 0); 301 m_compose(p_pony, IMSG_CONF_END, 0, 0, -1, NULL, 0); 302 } 303 304 void 305 parent_send_config_lka() 306 { 307 log_debug("debug: parent_send_config_ruleset: reloading"); 308 m_compose(p_lka, IMSG_CONF_START, 0, 0, -1, NULL, 0); 309 m_compose(p_lka, IMSG_CONF_END, 0, 0, -1, NULL, 0); 310 } 311 312 static void 313 parent_send_config_ca(void) 314 { 315 log_debug("debug: parent_send_config: configuring ca process"); 316 m_compose(p_ca, IMSG_CONF_START, 0, 0, -1, NULL, 0); 317 m_compose(p_ca, IMSG_CONF_END, 0, 0, -1, NULL, 0); 318 } 319 320 static void 321 parent_sig_handler(int sig, short event, void *p) 322 { 323 struct child *child; 324 int die = 0, status, fail; 325 pid_t pid; 326 char *cause; 327 328 switch (sig) { 329 case SIGTERM: 330 case SIGINT: 331 die = 1; 332 /* FALLTHROUGH */ 333 case SIGCHLD: 334 do { 335 pid = waitpid(-1, &status, WNOHANG); 336 if (pid <= 0) 337 continue; 338 339 fail = 0; 340 if (WIFSIGNALED(status)) { 341 fail = 1; 342 asprintf(&cause, "terminated; signal %d", 343 WTERMSIG(status)); 344 } else if (WIFEXITED(status)) { 345 if (WEXITSTATUS(status) != 0) { 346 fail = 1; 347 asprintf(&cause, "exited abnormally"); 348 } else 349 asprintf(&cause, "exited okay"); 350 } else 351 fatalx("smtpd: unexpected cause of SIGCHLD"); 352 353 if (pid == purge_pid) 354 purge_pid = -1; 355 356 child = tree_pop(&children, pid); 357 if (child == NULL) 358 goto skip; 359 360 switch (child->type) { 361 case CHILD_DAEMON: 362 die = 1; 363 if (fail) 364 log_warnx("warn: lost child: %s %s", 365 child->title, cause); 366 break; 367 368 case CHILD_MDA: 369 if (WIFSIGNALED(status) && 370 WTERMSIG(status) == SIGALRM) { 371 free(cause); 372 asprintf(&cause, "terminated; timeout"); 373 } 374 else if (child->cause && 375 WIFSIGNALED(status) && 376 WTERMSIG(status) == SIGTERM) { 377 free(cause); 378 cause = child->cause; 379 child->cause = NULL; 380 } 381 if (child->cause) 382 free(child->cause); 383 log_debug("debug: smtpd: mda process done " 384 "for session %016"PRIx64 ": %s", 385 child->mda_id, cause); 386 m_create(p_pony, IMSG_MDA_DONE, 0, 0, 387 child->mda_out); 388 m_add_id(p_pony, child->mda_id); 389 m_add_string(p_pony, cause); 390 m_close(p_pony); 391 /* free(cause); */ 392 break; 393 394 case CHILD_ENQUEUE_OFFLINE: 395 if (fail) 396 log_warnx("warn: smtpd: " 397 "couldn't enqueue offline " 398 "message %s; smtpctl %s", 399 child->path, cause); 400 else 401 unlink(child->path); 402 free(child->path); 403 offline_done(); 404 break; 405 406 default: 407 fatalx("smtpd: unexpected child type"); 408 } 409 free(child); 410 skip: 411 free(cause); 412 } while (pid > 0 || (pid == -1 && errno == EINTR)); 413 414 if (die) 415 parent_shutdown(1); 416 break; 417 default: 418 fatalx("smtpd: unexpected signal"); 419 } 420 } 421 422 int 423 main(int argc, char *argv[]) 424 { 425 int c, i; 426 int opts, flags; 427 const char *conffile = CONF_FILE; 428 struct smtpd smtpd; 429 struct event ev_sigint; 430 struct event ev_sigterm; 431 struct event ev_sigchld; 432 struct event ev_sighup; 433 struct timeval tv; 434 435 env = &smtpd; 436 437 flags = 0; 438 opts = 0; 439 debug = 0; 440 verbose = 0; 441 442 log_init(1); 443 444 TAILQ_INIT(&offline_q); 445 446 while ((c = getopt(argc, argv, "B:dD:hnP:f:T:v")) != -1) { 447 switch (c) { 448 case 'B': 449 if (strstr(optarg, "queue=") == optarg) 450 backend_queue = strchr(optarg, '=') + 1; 451 else if (strstr(optarg, "scheduler=") == optarg) 452 backend_scheduler = strchr(optarg, '=') + 1; 453 else if (strstr(optarg, "stat=") == optarg) 454 backend_stat = strchr(optarg, '=') + 1; 455 else 456 log_warnx("warn: " 457 "invalid backend specifier %s", 458 optarg); 459 break; 460 case 'd': 461 foreground = 1; 462 break; 463 case 'D': 464 if (cmdline_symset(optarg) < 0) 465 log_warnx("warn: " 466 "could not parse macro definition %s", 467 optarg); 468 break; 469 case 'h': 470 log_info("version: OpenSMTPD " SMTPD_VERSION); 471 usage(); 472 break; 473 case 'n': 474 debug = 2; 475 opts |= SMTPD_OPT_NOACTION; 476 break; 477 case 'f': 478 conffile = optarg; 479 break; 480 case 'T': 481 if (!strcmp(optarg, "imsg")) 482 verbose |= TRACE_IMSG; 483 else if (!strcmp(optarg, "io")) 484 verbose |= TRACE_IO; 485 else if (!strcmp(optarg, "smtp")) 486 verbose |= TRACE_SMTP; 487 else if (!strcmp(optarg, "mfa") || 488 !strcmp(optarg, "filter") || 489 !strcmp(optarg, "filters")) 490 verbose |= TRACE_FILTERS; 491 else if (!strcmp(optarg, "mta") || 492 !strcmp(optarg, "transfer")) 493 verbose |= TRACE_MTA; 494 else if (!strcmp(optarg, "bounce") || 495 !strcmp(optarg, "bounces")) 496 verbose |= TRACE_BOUNCE; 497 else if (!strcmp(optarg, "scheduler")) 498 verbose |= TRACE_SCHEDULER; 499 else if (!strcmp(optarg, "lookup")) 500 verbose |= TRACE_LOOKUP; 501 else if (!strcmp(optarg, "stat") || 502 !strcmp(optarg, "stats")) 503 verbose |= TRACE_STAT; 504 else if (!strcmp(optarg, "rules")) 505 verbose |= TRACE_RULES; 506 else if (!strcmp(optarg, "mproc")) 507 verbose |= TRACE_MPROC; 508 else if (!strcmp(optarg, "expand")) 509 verbose |= TRACE_EXPAND; 510 else if (!strcmp(optarg, "table") || 511 !strcmp(optarg, "tables")) 512 verbose |= TRACE_TABLES; 513 else if (!strcmp(optarg, "queue")) 514 verbose |= TRACE_QUEUE; 515 else if (!strcmp(optarg, "all")) 516 verbose |= ~TRACE_DEBUG; 517 else if (!strcmp(optarg, "profstat")) 518 profiling |= PROFILE_TOSTAT; 519 else if (!strcmp(optarg, "profile-imsg")) 520 profiling |= PROFILE_IMSG; 521 else if (!strcmp(optarg, "profile-queue")) 522 profiling |= PROFILE_QUEUE; 523 else if (!strcmp(optarg, "profile-buffers")) 524 profiling |= PROFILE_BUFFERS; 525 else 526 log_warnx("warn: unknown trace flag \"%s\"", 527 optarg); 528 break; 529 case 'P': 530 if (!strcmp(optarg, "smtp")) 531 flags |= SMTPD_SMTP_PAUSED; 532 else if (!strcmp(optarg, "mta")) 533 flags |= SMTPD_MTA_PAUSED; 534 else if (!strcmp(optarg, "mda")) 535 flags |= SMTPD_MDA_PAUSED; 536 break; 537 case 'v': 538 verbose |= TRACE_DEBUG; 539 break; 540 default: 541 usage(); 542 } 543 } 544 545 argv += optind; 546 argc -= optind; 547 548 if (argc || *argv) 549 usage(); 550 551 ssl_init(); 552 553 if (parse_config(&smtpd, conffile, opts)) 554 exit(1); 555 556 if (strlcpy(env->sc_conffile, conffile, SMTPD_MAXPATHLEN) 557 >= SMTPD_MAXPATHLEN) 558 errx(1, "config file exceeds SMTPD_MAXPATHLEN"); 559 560 if (env->sc_opts & SMTPD_OPT_NOACTION) { 561 load_pki_tree(); 562 load_pki_keys(); 563 fprintf(stderr, "configuration OK\n"); 564 exit(0); 565 } 566 567 env->sc_flags |= flags; 568 569 /* check for root privileges */ 570 if (geteuid()) 571 errx(1, "need root privileges"); 572 573 /* the control socket ensures that only one smtpd instance is running */ 574 control_socket = control_create_socket(); 575 576 if (!queue_init(backend_queue, 1)) 577 errx(1, "could not initialize queue backend"); 578 579 env->sc_stat = stat_backend_lookup(backend_stat); 580 if (env->sc_stat == NULL) 581 errx(1, "could not find stat backend \"%s\"", backend_stat); 582 583 if (env->sc_queue_flags & QUEUE_ENCRYPTION) { 584 if (env->sc_queue_key == NULL) { 585 char *password; 586 587 password = getpass("queue key: "); 588 if (password == NULL) 589 err(1, "getpass"); 590 591 env->sc_queue_key = strdup(password); 592 memset(password, 0, strlen(password)); 593 if (env->sc_queue_key == NULL) 594 err(1, "strdup"); 595 } 596 else { 597 char *buf; 598 char *lbuf; 599 size_t len; 600 601 if (strcasecmp(env->sc_queue_key, "stdin") == 0) { 602 lbuf = NULL; 603 buf = fgetln(stdin, &len); 604 if (buf[len - 1] == '\n') { 605 lbuf = calloc(len, 1); 606 if (lbuf == NULL) 607 err(1, "calloc"); 608 memcpy(lbuf, buf, len-1); 609 } 610 else { 611 lbuf = calloc(len+1, 1); 612 if (lbuf == NULL) 613 err(1, "calloc"); 614 memcpy(lbuf, buf, len); 615 } 616 env->sc_queue_key = lbuf; 617 } 618 } 619 } 620 621 if (env->sc_queue_flags & QUEUE_COMPRESSION) 622 env->sc_comp = compress_backend_lookup("gzip"); 623 624 log_init(foreground); 625 log_verbose(verbose); 626 627 load_pki_tree(); 628 629 log_info("info: %s %s starting", SMTPD_NAME, SMTPD_VERSION); 630 631 if (! foreground) 632 if (daemon(0, 0) == -1) 633 err(1, "failed to daemonize"); 634 635 for (i = 0; i < MAX_BOUNCE_WARN; i++) { 636 if (env->sc_bounce_warn[i] == 0) 637 break; 638 log_debug("debug: bounce warning after %s", 639 duration_to_text(env->sc_bounce_warn[i])); 640 } 641 642 log_debug("debug: using \"%s\" queue backend", backend_queue); 643 log_debug("debug: using \"%s\" scheduler backend", backend_scheduler); 644 log_debug("debug: using \"%s\" stat backend", backend_stat); 645 log_info("info: startup%s", (verbose & TRACE_DEBUG)?" [debug mode]":""); 646 647 if (env->sc_hostname[0] == '\0') 648 errx(1, "machine does not have a hostname set"); 649 env->sc_uptime = time(NULL); 650 651 fork_peers(); 652 653 config_process(PROC_PARENT); 654 655 imsg_callback = parent_imsg; 656 event_init(); 657 658 signal_set(&ev_sigint, SIGINT, parent_sig_handler, NULL); 659 signal_set(&ev_sigterm, SIGTERM, parent_sig_handler, NULL); 660 signal_set(&ev_sigchld, SIGCHLD, parent_sig_handler, NULL); 661 signal_set(&ev_sighup, SIGHUP, parent_sig_handler, NULL); 662 signal_add(&ev_sigint, NULL); 663 signal_add(&ev_sigterm, NULL); 664 signal_add(&ev_sigchld, NULL); 665 signal_add(&ev_sighup, NULL); 666 signal(SIGPIPE, SIG_IGN); 667 668 config_peer(PROC_CONTROL); 669 config_peer(PROC_LKA); 670 config_peer(PROC_QUEUE); 671 config_peer(PROC_CA); 672 config_peer(PROC_PONY); 673 config_done(); 674 675 evtimer_set(&config_ev, parent_send_config, NULL); 676 memset(&tv, 0, sizeof(tv)); 677 evtimer_add(&config_ev, &tv); 678 679 /* defer offline scanning for a second */ 680 evtimer_set(&offline_ev, offline_scan, NULL); 681 offline_timeout.tv_sec = 1; 682 offline_timeout.tv_usec = 0; 683 evtimer_add(&offline_ev, &offline_timeout); 684 685 if (pidfile(NULL) < 0) 686 err(1, "pidfile"); 687 688 purge_task(); 689 690 if (event_dispatch() < 0) 691 fatal("smtpd: event_dispatch"); 692 693 return (0); 694 } 695 696 static void 697 load_pki_tree(void) 698 { 699 struct pki *pki; 700 const char *k; 701 void *iter_dict; 702 703 log_debug("debug: init ssl-tree"); 704 iter_dict = NULL; 705 while (dict_iter(env->sc_pki_dict, &iter_dict, &k, (void **)&pki)) { 706 log_debug("info: loading pki information for %s", k); 707 if (pki->pki_cert_file == NULL) 708 fatalx("load_pki_tree: missing certificate file"); 709 if (pki->pki_key_file == NULL) 710 fatalx("load_pki_tree: missing key file"); 711 712 if (! ssl_load_certificate(pki, pki->pki_cert_file)) 713 fatalx("load_pki_tree: failed to load certificate file"); 714 715 if (pki->pki_ca_file) 716 if (! ssl_load_cafile(pki, pki->pki_ca_file)) 717 fatalx("load_pki_tree: failed to load CA file"); 718 if (pki->pki_dhparams_file) 719 if (! ssl_load_dhparams(pki, pki->pki_dhparams_file)) 720 fatalx("load_pki_tree: failed to load dhparams file"); 721 } 722 } 723 724 void 725 load_pki_keys(void) 726 { 727 struct pki *pki; 728 const char *k; 729 void *iter_dict; 730 731 log_debug("debug: init ssl-tree"); 732 iter_dict = NULL; 733 while (dict_iter(env->sc_pki_dict, &iter_dict, &k, (void **)&pki)) { 734 log_debug("info: loading pki keys for %s", k); 735 736 if (! ssl_load_keyfile(pki, pki->pki_key_file, k)) 737 fatalx("load_pki_keys: failed to load key file"); 738 } 739 } 740 741 static void 742 fork_peers(void) 743 { 744 tree_init(&children); 745 746 init_pipes(); 747 748 child_add(queue(), CHILD_DAEMON, proc_title(PROC_QUEUE)); 749 child_add(control(), CHILD_DAEMON, proc_title(PROC_CONTROL)); 750 child_add(lka(), CHILD_DAEMON, proc_title(PROC_LKA)); 751 child_add(scheduler(), CHILD_DAEMON, proc_title(PROC_SCHEDULER)); 752 child_add(pony(), CHILD_DAEMON, proc_title(PROC_PONY)); 753 child_add(ca(), CHILD_DAEMON, proc_title(PROC_CA)); 754 post_fork(PROC_PARENT); 755 } 756 757 void 758 post_fork(int proc) 759 { 760 if (proc != PROC_QUEUE && env->sc_queue_key) 761 explicit_bzero(env->sc_queue_key, strlen(env->sc_queue_key)); 762 763 if (proc != PROC_CONTROL) { 764 close(control_socket); 765 control_socket = -1; 766 } 767 768 if (proc == PROC_CA) { 769 load_pki_keys(); 770 } 771 } 772 773 int 774 fork_proc_backend(const char *key, const char *conf, const char *procname) 775 { 776 pid_t pid; 777 int sp[2]; 778 char path[SMTPD_MAXPATHLEN]; 779 char name[SMTPD_MAXPATHLEN]; 780 char *arg; 781 782 if (strlcpy(name, conf, sizeof(name)) >= sizeof(name)) { 783 log_warnx("warn: %s-proc: conf too long", key); 784 return (0); 785 } 786 787 arg = strchr(name, ':'); 788 if (arg) 789 *arg++ = '\0'; 790 791 if (snprintf(path, sizeof(path), PATH_LIBEXEC "/%s-%s", key, name) >= 792 (ssize_t)sizeof(path)) { 793 log_warn("warn: %s-proc: exec path too long", key); 794 return (-1); 795 } 796 797 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) == -1) { 798 log_warn("warn: %s-proc: socketpair", key); 799 return (-1); 800 } 801 802 if ((pid = fork()) == -1) { 803 log_warn("warn: %s-proc: fork", key); 804 close(sp[0]); 805 close(sp[1]); 806 return (-1); 807 } 808 809 if (pid == 0) { 810 /* child process */ 811 dup2(sp[0], STDIN_FILENO); 812 if (closefrom(STDERR_FILENO + 1) < 0) 813 exit(1); 814 815 if (procname == NULL) 816 procname = name; 817 818 execl(path, procname, arg, NULL); 819 err(1, "execl: %s", path); 820 } 821 822 /* parent process */ 823 close(sp[0]); 824 825 return (sp[1]); 826 } 827 828 struct child * 829 child_add(pid_t pid, int type, const char *title) 830 { 831 struct child *child; 832 833 if ((child = calloc(1, sizeof(*child))) == NULL) 834 fatal("smtpd: child_add: calloc"); 835 836 child->pid = pid; 837 child->type = type; 838 child->title = title; 839 840 tree_xset(&children, pid, child); 841 842 return (child); 843 } 844 845 static void 846 purge_task(void) 847 { 848 struct passwd *pw; 849 DIR *d; 850 int n; 851 uid_t uid; 852 gid_t gid; 853 854 n = 0; 855 if ((d = opendir(PATH_SPOOL PATH_PURGE))) { 856 while (readdir(d) != NULL) 857 n++; 858 closedir(d); 859 } else 860 log_warn("warn: purge_task: opendir"); 861 862 if (n > 2) { 863 switch (purge_pid = fork()) { 864 case -1: 865 log_warn("warn: purge_task: fork"); 866 break; 867 case 0: 868 if ((pw = getpwnam(SMTPD_USER)) == NULL) 869 fatalx("unknown user " SMTPD_USER); 870 if (chroot(PATH_SPOOL PATH_PURGE) == -1) 871 fatal("smtpd: chroot"); 872 if (chdir("/") == -1) 873 fatal("smtpd: chdir"); 874 uid = pw->pw_uid; 875 gid = pw->pw_gid; 876 if (setgroups(1, &gid) || 877 setresgid(gid, gid, gid) || 878 setresuid(uid, uid, uid)) 879 fatal("smtpd: cannot drop privileges"); 880 rmtree("/", 1); 881 _exit(0); 882 break; 883 default: 884 break; 885 } 886 } 887 } 888 889 static void 890 forkmda(struct mproc *p, uint64_t id, struct deliver *deliver) 891 { 892 char ebuf[128], sfn[32]; 893 struct delivery_backend *db; 894 struct child *child; 895 pid_t pid; 896 int allout, pipefd[2]; 897 mode_t omode; 898 899 log_debug("debug: smtpd: forking mda for session %016"PRIx64 900 ": \"%s\" as %s", id, deliver->to, deliver->user); 901 902 db = delivery_backend_lookup(deliver->mode); 903 if (db == NULL) { 904 (void)snprintf(ebuf, sizeof ebuf, "could not find delivery backend"); 905 m_create(p_pony, IMSG_MDA_DONE, 0, 0, -1); 906 m_add_id(p_pony, id); 907 m_add_string(p_pony, ebuf); 908 m_close(p_pony); 909 return; 910 } 911 912 if (deliver->userinfo.uid == 0 && ! db->allow_root) { 913 (void)snprintf(ebuf, sizeof ebuf, "not allowed to deliver to: %s", 914 deliver->user); 915 m_create(p_pony, IMSG_MDA_DONE, 0, 0, -1); 916 m_add_id(p_pony, id); 917 m_add_string(p_pony, ebuf); 918 m_close(p_pony); 919 return; 920 } 921 922 if (pipe(pipefd) < 0) { 923 (void)snprintf(ebuf, sizeof ebuf, "pipe: %s", strerror(errno)); 924 m_create(p_pony, IMSG_MDA_DONE, 0, 0, -1); 925 m_add_id(p_pony, id); 926 m_add_string(p_pony, ebuf); 927 m_close(p_pony); 928 return; 929 } 930 931 /* prepare file which captures stdout and stderr */ 932 (void)strlcpy(sfn, "/tmp/smtpd.out.XXXXXXXXXXX", sizeof(sfn)); 933 omode = umask(7077); 934 allout = mkstemp(sfn); 935 umask(omode); 936 if (allout < 0) { 937 (void)snprintf(ebuf, sizeof ebuf, "mkstemp: %s", strerror(errno)); 938 m_create(p_pony, IMSG_MDA_DONE, 0, 0, -1); 939 m_add_id(p_pony, id); 940 m_add_string(p_pony, ebuf); 941 m_close(p_pony); 942 close(pipefd[0]); 943 close(pipefd[1]); 944 return; 945 } 946 unlink(sfn); 947 948 pid = fork(); 949 if (pid < 0) { 950 (void)snprintf(ebuf, sizeof ebuf, "fork: %s", strerror(errno)); 951 m_create(p_pony, IMSG_MDA_DONE, 0, 0, -1); 952 m_add_id(p_pony, id); 953 m_add_string(p_pony, ebuf); 954 m_close(p_pony); 955 close(pipefd[0]); 956 close(pipefd[1]); 957 close(allout); 958 return; 959 } 960 961 /* parent passes the child fd over to mda */ 962 if (pid > 0) { 963 child = child_add(pid, CHILD_MDA, NULL); 964 child->mda_out = allout; 965 child->mda_id = id; 966 close(pipefd[0]); 967 m_create(p, IMSG_MDA_FORK, 0, 0, pipefd[1]); 968 m_add_id(p, id); 969 m_close(p); 970 return; 971 } 972 973 if (chdir(deliver->userinfo.directory) < 0 && chdir("/") < 0) 974 err(1, "chdir"); 975 if (setgroups(1, &deliver->userinfo.gid) || 976 setresgid(deliver->userinfo.gid, deliver->userinfo.gid, deliver->userinfo.gid) || 977 setresuid(deliver->userinfo.uid, deliver->userinfo.uid, deliver->userinfo.uid)) 978 err(1, "forkmda: cannot drop privileges"); 979 if (dup2(pipefd[0], STDIN_FILENO) < 0 || 980 dup2(allout, STDOUT_FILENO) < 0 || 981 dup2(allout, STDERR_FILENO) < 0) 982 err(1, "forkmda: dup2"); 983 if (closefrom(STDERR_FILENO + 1) < 0) 984 err(1, "closefrom"); 985 if (setsid() < 0) 986 err(1, "setsid"); 987 if (signal(SIGPIPE, SIG_DFL) == SIG_ERR || 988 signal(SIGINT, SIG_DFL) == SIG_ERR || 989 signal(SIGTERM, SIG_DFL) == SIG_ERR || 990 signal(SIGCHLD, SIG_DFL) == SIG_ERR || 991 signal(SIGHUP, SIG_DFL) == SIG_ERR) 992 err(1, "signal"); 993 994 /* avoid hangs by setting 5m timeout */ 995 alarm(300); 996 997 db->open(deliver); 998 } 999 1000 static void 1001 offline_scan(int fd, short ev, void *arg) 1002 { 1003 DIR *dir = arg; 1004 struct dirent *d; 1005 int n = 0; 1006 1007 if (dir == NULL) { 1008 log_debug("debug: smtpd: scanning offline queue..."); 1009 if ((dir = opendir(PATH_SPOOL PATH_OFFLINE)) == NULL) 1010 errx(1, "smtpd: opendir"); 1011 } 1012 1013 while ((d = readdir(dir)) != NULL) { 1014 if (d->d_type != DT_REG) 1015 continue; 1016 1017 if (offline_add(d->d_name)) { 1018 log_warnx("warn: smtpd: " 1019 "could not add offline message %s", d->d_name); 1020 continue; 1021 } 1022 1023 if ((n++) == OFFLINE_READMAX) { 1024 evtimer_set(&offline_ev, offline_scan, dir); 1025 offline_timeout.tv_sec = 0; 1026 offline_timeout.tv_usec = 100000; 1027 evtimer_add(&offline_ev, &offline_timeout); 1028 return; 1029 } 1030 } 1031 1032 log_debug("debug: smtpd: offline scanning done"); 1033 closedir(dir); 1034 } 1035 1036 static int 1037 offline_enqueue(char *name) 1038 { 1039 char t[SMTPD_MAXPATHLEN], *path; 1040 struct stat sb; 1041 pid_t pid; 1042 struct child *child; 1043 struct passwd *pw; 1044 1045 if (!bsnprintf(t, sizeof t, "%s/%s", PATH_SPOOL PATH_OFFLINE, name)) { 1046 log_warnx("warn: smtpd: path name too long"); 1047 return (-1); 1048 } 1049 1050 if ((path = strdup(t)) == NULL) { 1051 log_warn("warn: smtpd: strdup"); 1052 return (-1); 1053 } 1054 1055 log_debug("debug: smtpd: enqueueing offline message %s", path); 1056 1057 if ((pid = fork()) == -1) { 1058 log_warn("warn: smtpd: fork"); 1059 free(path); 1060 return (-1); 1061 } 1062 1063 if (pid == 0) { 1064 char *envp[2], *p, *tmp; 1065 FILE *fp; 1066 size_t len; 1067 arglist args; 1068 1069 memset(&args, 0, sizeof(args)); 1070 1071 if (lstat(path, &sb) == -1) { 1072 log_warn("warn: smtpd: lstat: %s", path); 1073 _exit(1); 1074 } 1075 1076 if (chflags(path, 0) == -1) { 1077 log_warn("warn: smtpd: chflags: %s", path); 1078 _exit(1); 1079 } 1080 1081 pw = getpwuid(sb.st_uid); 1082 if (pw == NULL) { 1083 log_warnx("warn: smtpd: getpwuid for uid %d failed", 1084 sb.st_uid); 1085 _exit(1); 1086 } 1087 1088 if (! S_ISREG(sb.st_mode)) { 1089 log_warnx("warn: smtpd: file %s (uid %d) not regular", 1090 path, sb.st_uid); 1091 _exit(1); 1092 } 1093 1094 if (setgroups(1, &pw->pw_gid) || 1095 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 1096 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) || 1097 closefrom(STDERR_FILENO + 1) == -1) 1098 _exit(1); 1099 1100 if ((fp = fopen(path, "r")) == NULL) 1101 _exit(1); 1102 1103 if (chdir(pw->pw_dir) == -1 && chdir("/") == -1) 1104 _exit(1); 1105 1106 if (setsid() == -1 || 1107 signal(SIGPIPE, SIG_DFL) == SIG_ERR || 1108 dup2(fileno(fp), STDIN_FILENO) == -1) 1109 _exit(1); 1110 1111 if ((p = fgetln(fp, &len)) == NULL) 1112 _exit(1); 1113 1114 if (p[len - 1] != '\n') 1115 _exit(1); 1116 p[len - 1] = '\0'; 1117 1118 addargs(&args, "%s", "sendmail"); 1119 1120 while ((tmp = strsep(&p, "|")) != NULL) 1121 addargs(&args, "%s", tmp); 1122 1123 if (lseek(fileno(fp), len, SEEK_SET) == -1) 1124 _exit(1); 1125 1126 envp[0] = "PATH=" _PATH_DEFPATH; 1127 envp[1] = (char *)NULL; 1128 environ = envp; 1129 1130 execvp(PATH_SMTPCTL, args.list); 1131 _exit(1); 1132 } 1133 1134 offline_running++; 1135 child = child_add(pid, CHILD_ENQUEUE_OFFLINE, NULL); 1136 child->path = path; 1137 1138 return (0); 1139 } 1140 1141 static int 1142 offline_add(char *path) 1143 { 1144 struct offline *q; 1145 1146 if (offline_running < OFFLINE_QUEUEMAX) 1147 /* skip queue */ 1148 return offline_enqueue(path); 1149 1150 q = malloc(sizeof(*q) + strlen(path) + 1); 1151 if (q == NULL) 1152 return (-1); 1153 q->path = (char *)q + sizeof(*q); 1154 memmove(q->path, path, strlen(path) + 1); 1155 TAILQ_INSERT_TAIL(&offline_q, q, entry); 1156 1157 return (0); 1158 } 1159 1160 static void 1161 offline_done(void) 1162 { 1163 struct offline *q; 1164 1165 offline_running--; 1166 1167 while (offline_running < OFFLINE_QUEUEMAX) { 1168 if ((q = TAILQ_FIRST(&offline_q)) == NULL) 1169 break; /* all done */ 1170 TAILQ_REMOVE(&offline_q, q, entry); 1171 offline_enqueue(q->path); 1172 free(q); 1173 } 1174 } 1175 1176 static int 1177 parent_forward_open(char *username, char *directory, uid_t uid, gid_t gid) 1178 { 1179 char pathname[SMTPD_MAXPATHLEN]; 1180 int fd; 1181 struct stat sb; 1182 1183 if (! bsnprintf(pathname, sizeof (pathname), "%s/.forward", 1184 directory)) 1185 fatal("smtpd: parent_forward_open: snprintf"); 1186 1187 if (stat(directory, &sb) < 0) { 1188 log_warn("warn: smtpd: parent_forward_open: %s", directory); 1189 return -1; 1190 } 1191 if (sb.st_mode & S_ISVTX) { 1192 log_warnx("warn: smtpd: parent_forward_open: %s is sticky", 1193 directory); 1194 errno = EAGAIN; 1195 return -1; 1196 } 1197 1198 do { 1199 fd = open(pathname, O_RDONLY); 1200 } while (fd == -1 && errno == EINTR); 1201 if (fd == -1) { 1202 if (errno == ENOENT) 1203 return -1; 1204 if (errno == EMFILE || errno == ENFILE || errno == EIO) { 1205 errno = EAGAIN; 1206 return -1; 1207 } 1208 log_warn("warn: smtpd: parent_forward_open: %s", pathname); 1209 return -1; 1210 } 1211 1212 if (! secure_file(fd, pathname, directory, uid, 1)) { 1213 log_warnx("warn: smtpd: %s: unsecure file", pathname); 1214 close(fd); 1215 return -1; 1216 } 1217 1218 return fd; 1219 } 1220 1221 void 1222 imsg_dispatch(struct mproc *p, struct imsg *imsg) 1223 { 1224 struct timespec t0, t1, dt; 1225 int msg; 1226 1227 if (imsg == NULL) { 1228 exit(1); 1229 return; 1230 } 1231 1232 log_imsg(smtpd_process, p->proc, imsg); 1233 1234 if (profiling & PROFILE_IMSG) 1235 clock_gettime(CLOCK_MONOTONIC, &t0); 1236 1237 msg = imsg->hdr.type; 1238 imsg_callback(p, imsg); 1239 1240 if (profiling & PROFILE_IMSG) { 1241 clock_gettime(CLOCK_MONOTONIC, &t1); 1242 timespecsub(&t1, &t0, &dt); 1243 1244 log_debug("profile-imsg: %s %s %s %d %lld.%09ld", 1245 proc_name(smtpd_process), 1246 proc_name(p->proc), 1247 imsg_to_str(msg), 1248 (int)imsg->hdr.len, 1249 (long long)dt.tv_sec, 1250 dt.tv_nsec); 1251 1252 if (profiling & PROFILE_TOSTAT) { 1253 char key[STAT_KEY_SIZE]; 1254 /* can't profstat control process yet */ 1255 if (smtpd_process == PROC_CONTROL) 1256 return; 1257 1258 if (! bsnprintf(key, sizeof key, 1259 "profiling.imsg.%s.%s.%s", 1260 proc_name(smtpd_process), 1261 proc_name(p->proc), 1262 imsg_to_str(msg))) 1263 return; 1264 stat_set(key, stat_timespec(&dt)); 1265 } 1266 } 1267 } 1268 1269 void 1270 log_imsg(int to, int from, struct imsg *imsg) 1271 { 1272 1273 if (to == PROC_CONTROL && imsg->hdr.type == IMSG_STAT_SET) 1274 return; 1275 1276 if (imsg->fd != -1) 1277 log_trace(TRACE_IMSG, "imsg: %s <- %s: %s (len=%zu, fd=%d)", 1278 proc_name(to), 1279 proc_name(from), 1280 imsg_to_str(imsg->hdr.type), 1281 imsg->hdr.len - IMSG_HEADER_SIZE, 1282 imsg->fd); 1283 else 1284 log_trace(TRACE_IMSG, "imsg: %s <- %s: %s (len=%zu)", 1285 proc_name(to), 1286 proc_name(from), 1287 imsg_to_str(imsg->hdr.type), 1288 imsg->hdr.len - IMSG_HEADER_SIZE); 1289 } 1290 1291 const char * 1292 proc_title(enum smtp_proc_type proc) 1293 { 1294 switch (proc) { 1295 case PROC_PARENT: 1296 return "[priv]"; 1297 case PROC_LKA: 1298 return "lookup"; 1299 case PROC_QUEUE: 1300 return "queue"; 1301 case PROC_CONTROL: 1302 return "control"; 1303 case PROC_SCHEDULER: 1304 return "scheduler"; 1305 case PROC_PONY: 1306 return "pony express"; 1307 case PROC_CA: 1308 return "klondike"; 1309 default: 1310 return "unknown"; 1311 } 1312 } 1313 1314 const char * 1315 proc_name(enum smtp_proc_type proc) 1316 { 1317 switch (proc) { 1318 case PROC_PARENT: 1319 return "parent"; 1320 case PROC_LKA: 1321 return "lka"; 1322 case PROC_QUEUE: 1323 return "queue"; 1324 case PROC_CONTROL: 1325 return "control"; 1326 case PROC_SCHEDULER: 1327 return "scheduler"; 1328 case PROC_PONY: 1329 return "pony"; 1330 case PROC_CA: 1331 return "ca"; 1332 case PROC_FILTER: 1333 return "filter-proc"; 1334 case PROC_CLIENT: 1335 return "client-proc"; 1336 default: 1337 return "unknown"; 1338 } 1339 } 1340 1341 #define CASE(x) case x : return #x 1342 1343 const char * 1344 imsg_to_str(int type) 1345 { 1346 static char buf[32]; 1347 1348 switch (type) { 1349 CASE(IMSG_NONE); 1350 1351 CASE(IMSG_CTL_OK); 1352 CASE(IMSG_CTL_FAIL); 1353 1354 CASE(IMSG_CTL_GET_DIGEST); 1355 CASE(IMSG_CTL_GET_STATS); 1356 CASE(IMSG_CTL_LIST_MESSAGES); 1357 CASE(IMSG_CTL_LIST_ENVELOPES); 1358 CASE(IMSG_CTL_MTA_SHOW_HOSTS); 1359 CASE(IMSG_CTL_MTA_SHOW_RELAYS); 1360 CASE(IMSG_CTL_MTA_SHOW_ROUTES); 1361 CASE(IMSG_CTL_MTA_SHOW_HOSTSTATS); 1362 CASE(IMSG_CTL_MTA_BLOCK); 1363 CASE(IMSG_CTL_MTA_UNBLOCK); 1364 CASE(IMSG_CTL_MTA_SHOW_BLOCK); 1365 CASE(IMSG_CTL_PAUSE_EVP); 1366 CASE(IMSG_CTL_PAUSE_MDA); 1367 CASE(IMSG_CTL_PAUSE_MTA); 1368 CASE(IMSG_CTL_PAUSE_SMTP); 1369 CASE(IMSG_CTL_PROFILE); 1370 CASE(IMSG_CTL_PROFILE_DISABLE); 1371 CASE(IMSG_CTL_PROFILE_ENABLE); 1372 CASE(IMSG_CTL_RESUME_EVP); 1373 CASE(IMSG_CTL_RESUME_MDA); 1374 CASE(IMSG_CTL_RESUME_MTA); 1375 CASE(IMSG_CTL_RESUME_SMTP); 1376 CASE(IMSG_CTL_RESUME_ROUTE); 1377 CASE(IMSG_CTL_REMOVE); 1378 CASE(IMSG_CTL_SCHEDULE); 1379 CASE(IMSG_CTL_SHOW_STATUS); 1380 CASE(IMSG_CTL_SHUTDOWN); 1381 CASE(IMSG_CTL_TRACE_DISABLE); 1382 CASE(IMSG_CTL_TRACE_ENABLE); 1383 CASE(IMSG_CTL_UPDATE_TABLE); 1384 CASE(IMSG_CTL_VERBOSE); 1385 1386 CASE(IMSG_CTL_SMTP_SESSION); 1387 1388 CASE(IMSG_CONF_START); 1389 CASE(IMSG_CONF_END); 1390 1391 CASE(IMSG_STAT_INCREMENT); 1392 CASE(IMSG_STAT_DECREMENT); 1393 CASE(IMSG_STAT_SET); 1394 1395 CASE(IMSG_LKA_AUTHENTICATE); 1396 CASE(IMSG_LKA_OPEN_FORWARD); 1397 CASE(IMSG_LKA_ENVELOPE_SUBMIT); 1398 CASE(IMSG_LKA_ENVELOPE_COMMIT); 1399 1400 CASE(IMSG_QUEUE_DELIVER); 1401 CASE(IMSG_QUEUE_DELIVERY_OK); 1402 CASE(IMSG_QUEUE_DELIVERY_TEMPFAIL); 1403 CASE(IMSG_QUEUE_DELIVERY_PERMFAIL); 1404 CASE(IMSG_QUEUE_DELIVERY_LOOP); 1405 CASE(IMSG_QUEUE_ENVELOPE_ACK); 1406 CASE(IMSG_QUEUE_ENVELOPE_COMMIT); 1407 CASE(IMSG_QUEUE_ENVELOPE_REMOVE); 1408 CASE(IMSG_QUEUE_ENVELOPE_SCHEDULE); 1409 CASE(IMSG_QUEUE_ENVELOPE_SUBMIT); 1410 CASE(IMSG_QUEUE_HOLDQ_HOLD); 1411 CASE(IMSG_QUEUE_HOLDQ_RELEASE); 1412 CASE(IMSG_QUEUE_MESSAGE_COMMIT); 1413 CASE(IMSG_QUEUE_MESSAGE_ROLLBACK); 1414 CASE(IMSG_QUEUE_SMTP_SESSION); 1415 CASE(IMSG_QUEUE_TRANSFER); 1416 1417 CASE(IMSG_MDA_DELIVERY_OK); 1418 CASE(IMSG_MDA_DELIVERY_TEMPFAIL); 1419 CASE(IMSG_MDA_DELIVERY_PERMFAIL); 1420 CASE(IMSG_MDA_DELIVERY_LOOP); 1421 CASE(IMSG_MDA_DELIVERY_HOLD); 1422 CASE(IMSG_MDA_DONE); 1423 CASE(IMSG_MDA_FORK); 1424 CASE(IMSG_MDA_HOLDQ_RELEASE); 1425 CASE(IMSG_MDA_LOOKUP_USERINFO); 1426 CASE(IMSG_MDA_KILL); 1427 CASE(IMSG_MDA_OPEN_MESSAGE); 1428 1429 CASE(IMSG_MTA_DELIVERY_OK); 1430 CASE(IMSG_MTA_DELIVERY_TEMPFAIL); 1431 CASE(IMSG_MTA_DELIVERY_PERMFAIL); 1432 CASE(IMSG_MTA_DELIVERY_LOOP); 1433 CASE(IMSG_MTA_DELIVERY_HOLD); 1434 CASE(IMSG_MTA_DNS_HOST); 1435 CASE(IMSG_MTA_DNS_HOST_END); 1436 CASE(IMSG_MTA_DNS_PTR); 1437 CASE(IMSG_MTA_DNS_MX); 1438 CASE(IMSG_MTA_DNS_MX_PREFERENCE); 1439 CASE(IMSG_MTA_HOLDQ_RELEASE); 1440 CASE(IMSG_MTA_LOOKUP_CREDENTIALS); 1441 CASE(IMSG_MTA_LOOKUP_SOURCE); 1442 CASE(IMSG_MTA_LOOKUP_HELO); 1443 CASE(IMSG_MTA_OPEN_MESSAGE); 1444 CASE(IMSG_MTA_SCHEDULE); 1445 CASE(IMSG_MTA_SSL_INIT); 1446 CASE(IMSG_MTA_SSL_VERIFY_CERT); 1447 CASE(IMSG_MTA_SSL_VERIFY_CHAIN); 1448 CASE(IMSG_MTA_SSL_VERIFY); 1449 1450 CASE(IMSG_SCHED_ENVELOPE_BOUNCE); 1451 CASE(IMSG_SCHED_ENVELOPE_DELIVER); 1452 CASE(IMSG_SCHED_ENVELOPE_EXPIRE); 1453 CASE(IMSG_SCHED_ENVELOPE_INJECT); 1454 CASE(IMSG_SCHED_ENVELOPE_REMOVE); 1455 CASE(IMSG_SCHED_ENVELOPE_TRANSFER); 1456 1457 CASE(IMSG_SMTP_AUTHENTICATE); 1458 CASE(IMSG_SMTP_DNS_PTR); 1459 CASE(IMSG_SMTP_MESSAGE_COMMIT); 1460 CASE(IMSG_SMTP_MESSAGE_CREATE); 1461 CASE(IMSG_SMTP_MESSAGE_ROLLBACK); 1462 CASE(IMSG_SMTP_MESSAGE_OPEN); 1463 CASE(IMSG_SMTP_EXPAND_RCPT); 1464 CASE(IMSG_SMTP_LOOKUP_HELO); 1465 CASE(IMSG_SMTP_SSL_INIT); 1466 CASE(IMSG_SMTP_SSL_VERIFY_CERT); 1467 CASE(IMSG_SMTP_SSL_VERIFY_CHAIN); 1468 CASE(IMSG_SMTP_SSL_VERIFY); 1469 1470 CASE(IMSG_SMTP_REQ_CONNECT); 1471 CASE(IMSG_SMTP_REQ_HELO); 1472 CASE(IMSG_SMTP_REQ_MAIL); 1473 CASE(IMSG_SMTP_REQ_RCPT); 1474 CASE(IMSG_SMTP_REQ_DATA); 1475 CASE(IMSG_SMTP_REQ_EOM); 1476 CASE(IMSG_SMTP_EVENT_RSET); 1477 CASE(IMSG_SMTP_EVENT_COMMIT); 1478 CASE(IMSG_SMTP_EVENT_ROLLBACK); 1479 CASE(IMSG_SMTP_EVENT_DISCONNECT); 1480 1481 CASE(IMSG_CA_PRIVENC); 1482 CASE(IMSG_CA_PRIVDEC); 1483 default: 1484 (void)snprintf(buf, sizeof(buf), "IMSG_??? (%d)", type); 1485 1486 return buf; 1487 } 1488 } 1489 1490 int 1491 parent_auth_user(const char *username, const char *password) 1492 { 1493 char user[SMTPD_MAXLOGNAME]; 1494 char pass[SMTPD_MAXLINESIZE]; 1495 int ret; 1496 1497 (void)strlcpy(user, username, sizeof(user)); 1498 (void)strlcpy(pass, password, sizeof(pass)); 1499 1500 ret = auth_userokay(user, NULL, "auth-smtp", pass); 1501 if (ret) 1502 return LKA_OK; 1503 return LKA_PERMFAIL; 1504 } 1505