1 /* $OpenBSD: mda.c,v 1.128 2017/11/21 12:20:34 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 * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include <sys/types.h> 23 #include <sys/queue.h> 24 #include <sys/tree.h> 25 #include <sys/socket.h> 26 27 #include <ctype.h> 28 #include <err.h> 29 #include <errno.h> 30 #include <event.h> 31 #include <imsg.h> 32 #include <inttypes.h> 33 #include <pwd.h> 34 #include <signal.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <time.h> 39 #include <unistd.h> 40 #include <limits.h> 41 #include <vis.h> 42 43 #include "smtpd.h" 44 #include "log.h" 45 46 #define MDA_HIWAT 65536 47 48 struct mda_envelope { 49 TAILQ_ENTRY(mda_envelope) entry; 50 uint64_t id; 51 time_t creation; 52 char *sender; 53 char *dest; 54 char *rcpt; 55 enum action_type method; 56 char *user; 57 char *buffer; 58 }; 59 60 #define USER_WAITINFO 0x01 61 #define USER_RUNNABLE 0x02 62 #define USER_ONHOLD 0x04 63 #define USER_HOLDQ 0x08 64 65 struct mda_user { 66 uint64_t id; 67 TAILQ_ENTRY(mda_user) entry; 68 TAILQ_ENTRY(mda_user) entry_runnable; 69 char name[LOGIN_NAME_MAX]; 70 char usertable[PATH_MAX]; 71 size_t evpcount; 72 TAILQ_HEAD(, mda_envelope) envelopes; 73 int flags; 74 size_t running; 75 struct userinfo userinfo; 76 }; 77 78 struct mda_session { 79 uint64_t id; 80 struct mda_user *user; 81 struct mda_envelope *evp; 82 struct io *io; 83 FILE *datafp; 84 }; 85 86 static void mda_io(struct io *, int, void *); 87 static int mda_check_loop(FILE *, struct mda_envelope *); 88 static int mda_getlastline(int, char *, size_t); 89 static void mda_done(struct mda_session *); 90 static void mda_fail(struct mda_user *, int, const char *, 91 enum enhanced_status_code); 92 static void mda_drain(void); 93 static void mda_log(const struct mda_envelope *, const char *, const char *); 94 static void mda_queue_ok(uint64_t); 95 static void mda_queue_tempfail(uint64_t, const char *, 96 enum enhanced_status_code); 97 static void mda_queue_permfail(uint64_t, const char *, enum enhanced_status_code); 98 static void mda_queue_loop(uint64_t); 99 static struct mda_user *mda_user(const struct envelope *); 100 static void mda_user_free(struct mda_user *); 101 static const char *mda_user_to_text(const struct mda_user *); 102 static struct mda_envelope *mda_envelope(const struct envelope *); 103 static void mda_envelope_free(struct mda_envelope *); 104 static struct mda_session * mda_session(struct mda_user *); 105 106 static struct tree sessions; 107 static struct tree users; 108 109 static TAILQ_HEAD(, mda_user) runnable; 110 111 void 112 mda_imsg(struct mproc *p, struct imsg *imsg) 113 { 114 struct mda_session *s; 115 struct mda_user *u; 116 struct mda_envelope *e; 117 struct envelope evp; 118 struct userinfo *userinfo; 119 struct deliver deliver; 120 struct msg m; 121 const void *data; 122 const char *error, *parent_error; 123 uint64_t reqid; 124 time_t now; 125 size_t sz; 126 char out[256], buf[LINE_MAX]; 127 int n; 128 enum lka_resp_status status; 129 130 switch (imsg->hdr.type) { 131 case IMSG_MDA_LOOKUP_USERINFO: 132 m_msg(&m, imsg); 133 m_get_id(&m, &reqid); 134 m_get_int(&m, (int *)&status); 135 if (status == LKA_OK) 136 m_get_data(&m, &data, &sz); 137 m_end(&m); 138 139 u = tree_xget(&users, reqid); 140 141 if (status == LKA_TEMPFAIL) 142 mda_fail(u, 0, 143 "Temporary failure in user lookup", 144 ESC_OTHER_ADDRESS_STATUS); 145 else if (status == LKA_PERMFAIL) 146 mda_fail(u, 1, 147 "Permanent failure in user lookup", 148 ESC_DESTINATION_MAILBOX_HAS_MOVED); 149 else { 150 if (sz != sizeof(u->userinfo)) 151 fatalx("mda: userinfo size mismatch"); 152 memmove(&u->userinfo, data, sz); 153 u->flags &= ~USER_WAITINFO; 154 u->flags |= USER_RUNNABLE; 155 TAILQ_INSERT_TAIL(&runnable, u, entry_runnable); 156 mda_drain(); 157 } 158 return; 159 160 case IMSG_QUEUE_DELIVER: 161 m_msg(&m, imsg); 162 m_get_envelope(&m, &evp); 163 m_end(&m); 164 165 u = mda_user(&evp); 166 167 if (u->evpcount >= env->sc_mda_task_hiwat) { 168 if (!(u->flags & USER_ONHOLD)) { 169 log_debug("debug: mda: hiwat reached for " 170 "user \"%s\": holding envelopes", 171 mda_user_to_text(u)); 172 u->flags |= USER_ONHOLD; 173 } 174 } 175 176 if (u->flags & USER_ONHOLD) { 177 u->flags |= USER_HOLDQ; 178 m_create(p_queue, IMSG_MDA_DELIVERY_HOLD, 179 0, 0, -1); 180 m_add_evpid(p_queue, evp.id); 181 m_add_id(p_queue, u->id); 182 m_close(p_queue); 183 return; 184 } 185 186 e = mda_envelope(&evp); 187 TAILQ_INSERT_TAIL(&u->envelopes, e, entry); 188 u->evpcount += 1; 189 stat_increment("mda.pending", 1); 190 191 if (!(u->flags & USER_RUNNABLE) && 192 !(u->flags & USER_WAITINFO)) { 193 u->flags |= USER_RUNNABLE; 194 TAILQ_INSERT_TAIL(&runnable, u, entry_runnable); 195 } 196 197 mda_drain(); 198 return; 199 200 case IMSG_MDA_OPEN_MESSAGE: 201 m_msg(&m, imsg); 202 m_get_id(&m, &reqid); 203 m_end(&m); 204 205 s = tree_xget(&sessions, reqid); 206 e = s->evp; 207 208 if (imsg->fd == -1) { 209 log_debug("debug: mda: cannot get message fd"); 210 mda_queue_tempfail(e->id, 211 "Cannot get message fd", 212 ESC_OTHER_MAIL_SYSTEM_STATUS); 213 mda_log(e, "TempFail", "Cannot get message fd"); 214 mda_done(s); 215 return; 216 } 217 218 log_debug("debug: mda: got message fd %d " 219 "for session %016"PRIx64 " evpid %016"PRIx64, 220 imsg->fd, s->id, e->id); 221 222 if ((s->datafp = fdopen(imsg->fd, "r")) == NULL) { 223 log_warn("warn: mda: fdopen"); 224 close(imsg->fd); 225 mda_queue_tempfail(e->id, "fdopen failed", 226 ESC_OTHER_MAIL_SYSTEM_STATUS); 227 mda_log(e, "TempFail", "fdopen failed"); 228 mda_done(s); 229 return; 230 } 231 232 /* check delivery loop */ 233 if (mda_check_loop(s->datafp, e)) { 234 log_debug("debug: mda: loop detected"); 235 mda_queue_loop(e->id); 236 mda_log(e, "PermFail", "Loop detected"); 237 mda_done(s); 238 return; 239 } 240 241 n = 0; 242 /* 243 * prepend "From " separator ... for 244 * A_MDA and A_FILENAME backends only 245 */ 246 if (e->method == A_MDA || e->method == A_FILENAME) { 247 time(&now); 248 if (e->sender[0]) 249 n = io_printf(s->io, "From %s %s", 250 e->sender, ctime(&now)); 251 else 252 n = io_printf(s->io, 253 "From MAILER-DAEMON@%s %s", 254 env->sc_hostname, ctime(&now)); 255 } 256 if (n != -1) { 257 /* start queueing delivery headers */ 258 if (e->sender[0]) 259 /* 260 * XXX: remove existing Return-Path, 261 * if any 262 */ 263 n = io_printf(s->io, 264 "Return-Path: %s\n" 265 "Delivered-To: %s\n", 266 e->sender, 267 e->rcpt ? e->rcpt : e->dest); 268 else 269 n = io_printf(s->io, 270 "Delivered-To: %s\n", 271 e->rcpt ? e->rcpt : e->dest); 272 } 273 if (n == -1) { 274 log_warn("warn: mda: " 275 "fail to write delivery info"); 276 mda_queue_tempfail(e->id, "Out of memory", 277 ESC_OTHER_MAIL_SYSTEM_STATUS); 278 mda_log(e, "TempFail", "Out of memory"); 279 mda_done(s); 280 return; 281 } 282 283 /* request parent to fork a helper process */ 284 userinfo = &s->user->userinfo; 285 memset(&deliver, 0, sizeof deliver); 286 switch (e->method) { 287 case A_MDA: 288 deliver.mode = A_MDA; 289 deliver.userinfo = *userinfo; 290 (void)strlcpy(deliver.user, userinfo->username, 291 sizeof(deliver.user)); 292 if (strlcpy(deliver.to, e->buffer, 293 sizeof(deliver.to)) 294 >= sizeof(deliver.to)) { 295 mda_queue_tempfail(e->id, 296 "mda command too long", 297 ESC_OTHER_MAIL_SYSTEM_STATUS); 298 mda_log(e, "TempFail", 299 "mda command too long"); 300 mda_done(s); 301 return; 302 } 303 break; 304 305 case A_MBOX: 306 /* 307 * MBOX is a special case as we MUST 308 * deliver as root, just override the uid. 309 */ 310 deliver.mode = A_MBOX; 311 deliver.userinfo = *userinfo; 312 deliver.userinfo.uid = 0; 313 (void)strlcpy(deliver.user, "root", 314 sizeof(deliver.user)); 315 (void)strlcpy(deliver.from, e->sender, 316 sizeof(deliver.from)); 317 (void)strlcpy(deliver.to, userinfo->username, 318 sizeof(deliver.to)); 319 break; 320 321 case A_MAILDIR: 322 deliver.mode = A_MAILDIR; 323 deliver.userinfo = *userinfo; 324 (void)strlcpy(deliver.user, userinfo->username, 325 sizeof(deliver.user)); 326 (void)strlcpy(deliver.dest, e->dest, 327 sizeof(deliver.dest)); 328 if (strlcpy(deliver.to, e->buffer, 329 sizeof(deliver.to)) 330 >= sizeof(deliver.to)) { 331 log_warn("warn: mda: " 332 "deliver buffer too large"); 333 mda_queue_tempfail(e->id, 334 "Maildir path too long", 335 ESC_OTHER_MAIL_SYSTEM_STATUS); 336 mda_log(e, "TempFail", 337 "Maildir path too long"); 338 mda_done(s); 339 return; 340 } 341 break; 342 343 case A_FILENAME: 344 deliver.mode = A_FILENAME; 345 deliver.userinfo = *userinfo; 346 (void)strlcpy(deliver.user, userinfo->username, 347 sizeof deliver.user); 348 if (strlcpy(deliver.to, e->buffer, 349 sizeof(deliver.to)) 350 >= sizeof(deliver.to)) { 351 log_warn("warn: mda: " 352 "deliver buffer too large"); 353 mda_queue_tempfail(e->id, 354 "filename path too long", 355 ESC_OTHER_MAIL_SYSTEM_STATUS); 356 mda_log(e, "TempFail", 357 "filename path too long"); 358 mda_done(s); 359 return; 360 } 361 break; 362 363 case A_LMTP: 364 deliver.mode = A_LMTP; 365 deliver.userinfo = *userinfo; 366 (void)strlcpy(deliver.user, e->user, 367 sizeof(deliver.user)); 368 (void)strlcpy(deliver.from, e->sender, 369 sizeof(deliver.from)); 370 (void)strlcpy(deliver.dest, e->dest, 371 sizeof(deliver.dest)); 372 if (strlcpy(deliver.to, e->buffer, 373 sizeof(deliver.to)) 374 >= sizeof(deliver.to)) { 375 log_warn("warn: mda: " 376 "deliver buffer too large"); 377 mda_queue_tempfail(e->id, 378 "socket path too long", 379 ESC_OTHER_MAIL_SYSTEM_STATUS); 380 mda_log(e, "TempFail", 381 "socket path too long"); 382 mda_done(s); 383 return; 384 } 385 break; 386 387 default: 388 errx(1, "mda: unknown delivery method: %d", 389 e->method); 390 } 391 392 log_debug("debug: mda: querying mda fd " 393 "for session %016"PRIx64 " evpid %016"PRIx64, 394 s->id, s->evp->id); 395 396 m_create(p_parent, IMSG_MDA_FORK, 0, 0, -1); 397 m_add_id(p_parent, reqid); 398 m_add_data(p_parent, &deliver, sizeof(deliver)); 399 m_close(p_parent); 400 return; 401 402 case IMSG_MDA_FORK: 403 m_msg(&m, imsg); 404 m_get_id(&m, &reqid); 405 m_end(&m); 406 407 s = tree_xget(&sessions, reqid); 408 e = s->evp; 409 if (imsg->fd == -1) { 410 log_warn("warn: mda: fail to retrieve mda fd"); 411 mda_queue_tempfail(e->id, "Cannot get mda fd", 412 ESC_OTHER_MAIL_SYSTEM_STATUS); 413 mda_log(e, "TempFail", "Cannot get mda fd"); 414 mda_done(s); 415 return; 416 } 417 418 log_debug("debug: mda: got mda fd %d " 419 "for session %016"PRIx64 " evpid %016"PRIx64, 420 imsg->fd, s->id, s->evp->id); 421 422 io_set_nonblocking(imsg->fd); 423 io_set_fd(s->io, imsg->fd); 424 io_set_write(s->io); 425 return; 426 427 case IMSG_MDA_DONE: 428 m_msg(&m, imsg); 429 m_get_id(&m, &reqid); 430 m_get_string(&m, &parent_error); 431 m_end(&m); 432 433 s = tree_xget(&sessions, reqid); 434 e = s->evp; 435 /* 436 * Grab last line of mda stdout/stderr if available. 437 */ 438 out[0] = '\0'; 439 if (imsg->fd != -1) 440 mda_getlastline(imsg->fd, out, sizeof(out)); 441 /* 442 * Choose between parent's description of error and 443 * child's output, the latter having preference over 444 * the former. 445 */ 446 error = NULL; 447 if (strcmp(parent_error, "exited okay") == 0) { 448 if (s->datafp || (s->io && io_queued(s->io))) 449 error = "mda exited prematurely"; 450 } else 451 error = out[0] ? out : parent_error; 452 453 /* update queue entry */ 454 if (error) { 455 mda_queue_tempfail(e->id, error, 456 ESC_OTHER_MAIL_SYSTEM_STATUS); 457 (void)snprintf(buf, sizeof buf, 458 "Error (%s)", error); 459 mda_log(e, "TempFail", buf); 460 } 461 else { 462 mda_queue_ok(e->id); 463 mda_log(e, "Ok", "Delivered"); 464 } 465 mda_done(s); 466 return; 467 } 468 469 errx(1, "mda_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); 470 } 471 472 void 473 mda_postfork() 474 { 475 } 476 477 void 478 mda_postprivdrop() 479 { 480 tree_init(&sessions); 481 tree_init(&users); 482 TAILQ_INIT(&runnable); 483 } 484 485 static void 486 mda_io(struct io *io, int evt, void *arg) 487 { 488 struct mda_session *s = arg; 489 char *ln = NULL; 490 size_t sz = 0; 491 ssize_t len; 492 493 log_trace(TRACE_IO, "mda: %p: %s %s", s, io_strevent(evt), 494 io_strio(io)); 495 496 switch (evt) { 497 case IO_LOWAT: 498 499 /* done */ 500 done: 501 if (s->datafp == NULL) { 502 log_debug("debug: mda: all data sent for session" 503 " %016"PRIx64 " evpid %016"PRIx64, 504 s->id, s->evp->id); 505 io_free(io); 506 s->io = NULL; 507 return; 508 } 509 510 while (io_queued(s->io) < MDA_HIWAT) { 511 if ((len = getline(&ln, &sz, s->datafp)) == -1) 512 break; 513 if (io_write(s->io, ln, len) == -1) { 514 m_create(p_parent, IMSG_MDA_KILL, 515 0, 0, -1); 516 m_add_id(p_parent, s->id); 517 m_add_string(p_parent, "Out of memory"); 518 m_close(p_parent); 519 io_pause(io, IO_OUT); 520 free(ln); 521 return; 522 } 523 } 524 525 free(ln); 526 ln = NULL; 527 if (ferror(s->datafp)) { 528 log_debug("debug: mda: ferror on session %016"PRIx64, 529 s->id); 530 m_create(p_parent, IMSG_MDA_KILL, 0, 0, -1); 531 m_add_id(p_parent, s->id); 532 m_add_string(p_parent, "Error reading body"); 533 m_close(p_parent); 534 io_pause(io, IO_OUT); 535 return; 536 } 537 538 if (feof(s->datafp)) { 539 log_debug("debug: mda: end-of-file for session" 540 " %016"PRIx64 " evpid %016"PRIx64, 541 s->id, s->evp->id); 542 fclose(s->datafp); 543 s->datafp = NULL; 544 if (io_queued(s->io) == 0) 545 goto done; 546 } 547 return; 548 549 case IO_TIMEOUT: 550 log_debug("debug: mda: timeout on session %016"PRIx64, s->id); 551 io_pause(io, IO_OUT); 552 return; 553 554 case IO_ERROR: 555 log_debug("debug: mda: io error on session %016"PRIx64": %s", 556 s->id, io_error(io)); 557 io_pause(io, IO_OUT); 558 return; 559 560 case IO_DISCONNECTED: 561 log_debug("debug: mda: io disconnected on session %016"PRIx64, 562 s->id); 563 io_pause(io, IO_OUT); 564 return; 565 566 default: 567 log_debug("debug: mda: unexpected event on session %016"PRIx64, 568 s->id); 569 io_pause(io, IO_OUT); 570 return; 571 } 572 } 573 574 static int 575 mda_check_loop(FILE *fp, struct mda_envelope *e) 576 { 577 char *buf = NULL; 578 size_t sz = 0; 579 ssize_t len; 580 int ret = 0; 581 582 while ((len = getline(&buf, &sz, fp)) != -1) { 583 if (buf[len - 1] == '\n') 584 buf[len - 1] = '\0'; 585 586 if (strchr(buf, ':') == NULL && !isspace((unsigned char)*buf)) 587 break; 588 589 if (strncasecmp("Delivered-To: ", buf, 14) == 0) { 590 if (strcasecmp(buf + 14, e->dest) == 0) { 591 ret = 1; 592 break; 593 } 594 } 595 } 596 597 free(buf); 598 fseek(fp, SEEK_SET, 0); 599 return (ret); 600 } 601 602 static int 603 mda_getlastline(int fd, char *dst, size_t dstsz) 604 { 605 FILE *fp; 606 char *ln = NULL; 607 size_t sz = 0; 608 ssize_t len; 609 int out = 0; 610 611 if (lseek(fd, 0, SEEK_SET) < 0) { 612 log_warn("warn: mda: lseek"); 613 close(fd); 614 return (-1); 615 } 616 fp = fdopen(fd, "r"); 617 if (fp == NULL) { 618 log_warn("warn: mda: fdopen"); 619 close(fd); 620 return (-1); 621 } 622 while ((len = getline(&ln, &sz, fp)) != -1) { 623 if (ln[len - 1] == '\n') 624 ln[len - 1] = '\0'; 625 out = 1; 626 } 627 fclose(fp); 628 629 if (out) { 630 (void)strlcpy(dst, "\"", dstsz); 631 (void)strnvis(dst + 1, ln, dstsz - 2, VIS_SAFE | VIS_CSTYLE); 632 (void)strlcat(dst, "\"", dstsz); 633 } 634 635 free(ln); 636 return (0); 637 } 638 639 static void 640 mda_fail(struct mda_user *user, int permfail, const char *error, 641 enum enhanced_status_code code) 642 { 643 struct mda_envelope *e; 644 645 while ((e = TAILQ_FIRST(&user->envelopes))) { 646 TAILQ_REMOVE(&user->envelopes, e, entry); 647 if (permfail) { 648 mda_log(e, "PermFail", error); 649 mda_queue_permfail(e->id, error, code); 650 } 651 else { 652 mda_log(e, "TempFail", error); 653 mda_queue_tempfail(e->id, error, code); 654 } 655 mda_envelope_free(e); 656 } 657 658 mda_user_free(user); 659 } 660 661 static void 662 mda_drain(void) 663 { 664 struct mda_user *u; 665 666 while ((u = (TAILQ_FIRST(&runnable)))) { 667 668 TAILQ_REMOVE(&runnable, u, entry_runnable); 669 670 if (u->evpcount == 0 && u->running == 0) { 671 log_debug("debug: mda: all done for user \"%s\"", 672 mda_user_to_text(u)); 673 mda_user_free(u); 674 continue; 675 } 676 677 if (u->evpcount == 0) { 678 log_debug("debug: mda: no more envelope for \"%s\"", 679 mda_user_to_text(u)); 680 u->flags &= ~USER_RUNNABLE; 681 continue; 682 } 683 684 if (u->running >= env->sc_mda_max_user_session) { 685 log_debug("debug: mda: " 686 "maximum number of session reached for user \"%s\"", 687 mda_user_to_text(u)); 688 u->flags &= ~USER_RUNNABLE; 689 continue; 690 } 691 692 if (tree_count(&sessions) >= env->sc_mda_max_session) { 693 log_debug("debug: mda: " 694 "maximum number of session reached"); 695 TAILQ_INSERT_HEAD(&runnable, u, entry_runnable); 696 return; 697 } 698 699 mda_session(u); 700 701 if (u->evpcount == env->sc_mda_task_lowat) { 702 if (u->flags & USER_ONHOLD) { 703 log_debug("debug: mda: down to lowat for user " 704 "\"%s\": releasing", 705 mda_user_to_text(u)); 706 u->flags &= ~USER_ONHOLD; 707 } 708 if (u->flags & USER_HOLDQ) { 709 m_create(p_queue, IMSG_MDA_HOLDQ_RELEASE, 710 0, 0, -1); 711 m_add_id(p_queue, u->id); 712 m_add_int(p_queue, env->sc_mda_task_release); 713 m_close(p_queue); 714 } 715 } 716 717 /* re-add the user at the tail of the queue */ 718 TAILQ_INSERT_TAIL(&runnable, u, entry_runnable); 719 } 720 } 721 722 static void 723 mda_done(struct mda_session *s) 724 { 725 log_debug("debug: mda: session %016" PRIx64 " done", s->id); 726 727 tree_xpop(&sessions, s->id); 728 729 mda_envelope_free(s->evp); 730 731 s->user->running--; 732 if (!(s->user->flags & USER_RUNNABLE)) { 733 log_debug("debug: mda: user \"%s\" becomes runnable", 734 s->user->name); 735 TAILQ_INSERT_TAIL(&runnable, s->user, entry_runnable); 736 s->user->flags |= USER_RUNNABLE; 737 } 738 739 if (s->datafp) 740 fclose(s->datafp); 741 if (s->io) 742 io_free(s->io); 743 744 free(s); 745 746 stat_decrement("mda.running", 1); 747 748 mda_drain(); 749 } 750 751 static void 752 mda_log(const struct mda_envelope *evp, const char *prefix, const char *status) 753 { 754 char rcpt[LINE_MAX]; 755 const char *method; 756 757 rcpt[0] = '\0'; 758 if (evp->rcpt) 759 (void)snprintf(rcpt, sizeof rcpt, "rcpt=<%s>, ", evp->rcpt); 760 761 if (evp->method == A_MAILDIR) 762 method = "maildir"; 763 else if (evp->method == A_MBOX) 764 method = "mbox"; 765 else if (evp->method == A_FILENAME) 766 method = "file"; 767 else if (evp->method == A_MDA) 768 method = "mda"; 769 else if (evp->method == A_LMTP) 770 method = "lmtp"; 771 else 772 method = "???"; 773 774 log_info("%016"PRIx64" mda event=delivery evpid=%016" PRIx64 " from=<%s> to=<%s> " 775 "%suser=%s method=%s delay=%s result=%s stat=%s", 776 (uint64_t)0, 777 evp->id, 778 evp->sender ? evp->sender : "", 779 evp->dest, 780 rcpt, 781 evp->user, 782 method, 783 duration_to_text(time(NULL) - evp->creation), 784 prefix, 785 status); 786 } 787 788 static void 789 mda_queue_ok(uint64_t evpid) 790 { 791 m_create(p_queue, IMSG_MDA_DELIVERY_OK, 0, 0, -1); 792 m_add_evpid(p_queue, evpid); 793 m_close(p_queue); 794 } 795 796 static void 797 mda_queue_tempfail(uint64_t evpid, const char *reason, 798 enum enhanced_status_code code) 799 { 800 m_create(p_queue, IMSG_MDA_DELIVERY_TEMPFAIL, 0, 0, -1); 801 m_add_evpid(p_queue, evpid); 802 m_add_string(p_queue, reason); 803 m_add_int(p_queue, (int)code); 804 m_close(p_queue); 805 } 806 807 static void 808 mda_queue_permfail(uint64_t evpid, const char *reason, 809 enum enhanced_status_code code) 810 { 811 m_create(p_queue, IMSG_MDA_DELIVERY_PERMFAIL, 0, 0, -1); 812 m_add_evpid(p_queue, evpid); 813 m_add_string(p_queue, reason); 814 m_add_int(p_queue, (int)code); 815 m_close(p_queue); 816 } 817 818 static void 819 mda_queue_loop(uint64_t evpid) 820 { 821 m_create(p_queue, IMSG_MDA_DELIVERY_LOOP, 0, 0, -1); 822 m_add_evpid(p_queue, evpid); 823 m_close(p_queue); 824 } 825 826 static struct mda_user * 827 mda_user(const struct envelope *evp) 828 { 829 struct mda_user *u; 830 void *i; 831 832 i = NULL; 833 while (tree_iter(&users, &i, NULL, (void**)(&u))) { 834 if (!strcmp(evp->agent.mda.username, u->name) && 835 !strcmp(evp->agent.mda.usertable, u->usertable)) 836 return (u); 837 } 838 839 u = xcalloc(1, sizeof *u, "mda_user"); 840 u->id = generate_uid(); 841 TAILQ_INIT(&u->envelopes); 842 (void)strlcpy(u->name, evp->agent.mda.username, sizeof(u->name)); 843 (void)strlcpy(u->usertable, evp->agent.mda.usertable, 844 sizeof(u->usertable)); 845 846 tree_xset(&users, u->id, u); 847 848 m_create(p_lka, IMSG_MDA_LOOKUP_USERINFO, 0, 0, -1); 849 m_add_id(p_lka, u->id); 850 m_add_string(p_lka, evp->agent.mda.usertable); 851 if (evp->agent.mda.delivery_user[0]) 852 m_add_string(p_lka, evp->agent.mda.delivery_user); 853 else 854 m_add_string(p_lka, evp->agent.mda.username); 855 m_close(p_lka); 856 u->flags |= USER_WAITINFO; 857 858 stat_increment("mda.user", 1); 859 860 if (evp->agent.mda.delivery_user[0]) 861 log_debug("mda: new user %016" PRIx64 862 " for \"%s\" delivering as \"%s\"", 863 u->id, mda_user_to_text(u), evp->agent.mda.delivery_user); 864 else 865 log_debug("mda: new user %016" PRIx64 866 " for \"%s\"", u->id, mda_user_to_text(u)); 867 868 return (u); 869 } 870 871 static void 872 mda_user_free(struct mda_user *u) 873 { 874 tree_xpop(&users, u->id); 875 876 if (u->flags & USER_HOLDQ) { 877 m_create(p_queue, IMSG_MDA_HOLDQ_RELEASE, 0, 0, -1); 878 m_add_id(p_queue, u->id); 879 m_add_int(p_queue, 0); 880 m_close(p_queue); 881 } 882 883 free(u); 884 stat_decrement("mda.user", 1); 885 } 886 887 static const char * 888 mda_user_to_text(const struct mda_user *u) 889 { 890 static char buf[1024]; 891 892 (void)snprintf(buf, sizeof(buf), "%s:%s", u->usertable, u->name); 893 894 return (buf); 895 } 896 897 static struct mda_envelope * 898 mda_envelope(const struct envelope *evp) 899 { 900 struct mda_envelope *e; 901 char buf[LINE_MAX]; 902 903 e = xcalloc(1, sizeof *e, "mda_envelope"); 904 e->id = evp->id; 905 e->creation = evp->creation; 906 buf[0] = '\0'; 907 if (evp->sender.user[0] && evp->sender.domain[0]) 908 (void)snprintf(buf, sizeof buf, "%s@%s", 909 evp->sender.user, evp->sender.domain); 910 e->sender = xstrdup(buf, "mda_envelope:sender"); 911 (void)snprintf(buf, sizeof buf, "%s@%s", evp->dest.user, 912 evp->dest.domain); 913 e->dest = xstrdup(buf, "mda_envelope:dest"); 914 (void)snprintf(buf, sizeof buf, "%s@%s", evp->rcpt.user, 915 evp->rcpt.domain); 916 if (strcmp(buf, e->dest)) 917 e->rcpt = xstrdup(buf, "mda_envelope:rcpt"); 918 e->method = evp->agent.mda.method; 919 e->buffer = xstrdup(evp->agent.mda.buffer, "mda_envelope:buffer"); 920 e->user = xstrdup(evp->agent.mda.username, "mda_envelope:user"); 921 922 stat_increment("mda.envelope", 1); 923 924 return (e); 925 } 926 927 static void 928 mda_envelope_free(struct mda_envelope *e) 929 { 930 free(e->sender); 931 free(e->dest); 932 free(e->rcpt); 933 free(e->user); 934 free(e->buffer); 935 free(e); 936 937 stat_decrement("mda.envelope", 1); 938 } 939 940 static struct mda_session * 941 mda_session(struct mda_user * u) 942 { 943 struct mda_session *s; 944 945 s = xcalloc(1, sizeof *s, "mda_session"); 946 s->id = generate_uid(); 947 s->user = u; 948 s->io = io_new(); 949 io_set_callback(s->io, mda_io, s); 950 951 tree_xset(&sessions, s->id, s); 952 953 s->evp = TAILQ_FIRST(&u->envelopes); 954 TAILQ_REMOVE(&u->envelopes, s->evp, entry); 955 u->evpcount--; 956 u->running++; 957 958 stat_decrement("mda.pending", 1); 959 stat_increment("mda.running", 1); 960 961 log_debug("debug: mda: new session %016" PRIx64 962 " for user \"%s\" evpid %016" PRIx64, s->id, 963 mda_user_to_text(u), s->evp->id); 964 965 m_create(p_queue, IMSG_MDA_OPEN_MESSAGE, 0, 0, -1); 966 m_add_id(p_queue, s->id); 967 m_add_msgid(p_queue, evpid_to_msgid(s->evp->id)); 968 m_close(p_queue); 969 970 return (s); 971 } 972