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