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