1 /* $OpenBSD: mta.c,v 1.39 2009/03/29 14:18:20 jacekm Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> 5 * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/types.h> 21 #include <sys/queue.h> 22 #include <sys/tree.h> 23 #include <sys/param.h> 24 #include <sys/socket.h> 25 26 #include <netinet/in.h> 27 #include <arpa/inet.h> 28 29 #include <ssl/ssl.h> 30 31 #include <errno.h> 32 #include <event.h> 33 #include <pwd.h> 34 #include <signal.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <unistd.h> 39 40 #include "smtpd.h" 41 42 __dead void mta_shutdown(void); 43 void mta_sig_handler(int, short, void *); 44 void mta_dispatch_parent(int, short, void *); 45 void mta_dispatch_queue(int, short, void *); 46 void mta_dispatch_runner(int, short, void *); 47 void mta_dispatch_lka(int, short, void *); 48 void mta_setup_events(struct smtpd *); 49 void mta_disable_events(struct smtpd *); 50 void mta_timeout(int, short, void *); 51 void mta_write(int, short, void *); 52 int mta_connect(struct session *); 53 void mta_read_handler(struct bufferevent *, void *); 54 void mta_write_handler(struct bufferevent *, void *); 55 void mta_error_handler(struct bufferevent *, short, void *); 56 int mta_reply_handler(struct bufferevent *, void *); 57 void mta_batch_update_queue(struct batch *); 58 void mta_mxlookup(struct smtpd *, struct session *, char *, struct rule *); 59 void ssl_client_init(struct session *); 60 61 void 62 mta_sig_handler(int sig, short event, void *p) 63 { 64 switch (sig) { 65 case SIGINT: 66 case SIGTERM: 67 mta_shutdown(); 68 break; 69 default: 70 fatalx("mta_sig_handler: unexpected signal"); 71 } 72 } 73 74 void 75 mta_dispatch_parent(int sig, short event, void *p) 76 { 77 struct smtpd *env = p; 78 struct imsgbuf *ibuf; 79 struct imsg imsg; 80 ssize_t n; 81 82 ibuf = env->sc_ibufs[PROC_PARENT]; 83 switch (event) { 84 case EV_READ: 85 if ((n = imsg_read(ibuf)) == -1) 86 fatal("imsg_read_error"); 87 if (n == 0) { 88 /* this pipe is dead, so remove the event handler */ 89 event_del(&ibuf->ev); 90 event_loopexit(NULL); 91 return; 92 } 93 break; 94 case EV_WRITE: 95 if (msgbuf_write(&ibuf->w) == -1) 96 fatal("msgbuf_write"); 97 imsg_event_add(ibuf); 98 return; 99 default: 100 fatalx("unknown event"); 101 } 102 103 for (;;) { 104 if ((n = imsg_get(ibuf, &imsg)) == -1) 105 fatal("parent_dispatch_mta: imsg_read error"); 106 if (n == 0) 107 break; 108 109 switch (imsg.hdr.type) { 110 default: 111 log_warnx("mta_dispatch_parent: got imsg %d", 112 imsg.hdr.type); 113 fatalx("mta_dispatch_parent: unexpected imsg"); 114 } 115 imsg_free(&imsg); 116 } 117 imsg_event_add(ibuf); 118 } 119 120 void 121 mta_dispatch_lka(int sig, short event, void *p) 122 { 123 struct smtpd *env = p; 124 struct imsgbuf *ibuf; 125 struct imsg imsg; 126 ssize_t n; 127 128 ibuf = env->sc_ibufs[PROC_LKA]; 129 switch (event) { 130 case EV_READ: 131 if ((n = imsg_read(ibuf)) == -1) 132 fatal("imsg_read_error"); 133 if (n == 0) { 134 /* this pipe is dead, so remove the event handler */ 135 event_del(&ibuf->ev); 136 event_loopexit(NULL); 137 return; 138 } 139 break; 140 case EV_WRITE: 141 if (msgbuf_write(&ibuf->w) == -1) 142 fatal("msgbuf_write"); 143 imsg_event_add(ibuf); 144 return; 145 default: 146 fatalx("unknown event"); 147 } 148 149 for (;;) { 150 if ((n = imsg_get(ibuf, &imsg)) == -1) 151 fatal("mta_dispatch_lka: imsg_read error"); 152 if (n == 0) 153 break; 154 155 switch (imsg.hdr.type) { 156 case IMSG_LKA_MX: { 157 struct session key; 158 struct mxrep *mxrep; 159 struct session *s; 160 struct mxhost *mxhost; 161 162 mxrep = imsg.data; 163 key.s_id = mxrep->id; 164 165 s = SPLAY_FIND(sessiontree, &env->sc_sessions, &key); 166 if (s == NULL) 167 fatal("mta_dispatch_lka: session is gone"); 168 169 mxhost = calloc(1, sizeof(struct mxhost)); 170 if (mxhost == NULL) 171 fatal("mta_dispatch_lka: calloc"); 172 173 *mxhost = mxrep->mxhost; 174 TAILQ_INSERT_TAIL(&s->mxhosts, mxhost, entry); 175 176 break; 177 } 178 case IMSG_LKA_MX_END: { 179 struct session key; 180 struct mxrep *mxrep; 181 struct session *s; 182 int ret; 183 184 mxrep = imsg.data; 185 key.s_id = mxrep->id; 186 187 s = SPLAY_FIND(sessiontree, &env->sc_sessions, &key); 188 if (s == NULL) 189 fatal("smtp_dispatch_parent: session is gone"); 190 191 s->batch->flags |= F_BATCH_RESOLVED; 192 193 do { 194 ret = mta_connect(s); 195 } while (ret == 0); 196 197 if (ret < 0) { 198 mta_batch_update_queue(s->batch); 199 session_destroy(s); 200 } 201 202 break; 203 } 204 default: 205 log_warnx("mta_dispatch_parent: got imsg %d", 206 imsg.hdr.type); 207 fatalx("mta_dispatch_lka: unexpected imsg"); 208 } 209 imsg_free(&imsg); 210 } 211 imsg_event_add(ibuf); 212 } 213 214 void 215 mta_dispatch_queue(int sig, short event, void *p) 216 { 217 struct smtpd *env = p; 218 struct imsgbuf *ibuf; 219 struct imsg imsg; 220 ssize_t n; 221 222 ibuf = env->sc_ibufs[PROC_QUEUE]; 223 switch (event) { 224 case EV_READ: 225 if ((n = imsg_read(ibuf)) == -1) 226 fatal("imsg_read_error"); 227 if (n == 0) { 228 /* this pipe is dead, so remove the event handler */ 229 event_del(&ibuf->ev); 230 event_loopexit(NULL); 231 return; 232 } 233 break; 234 case EV_WRITE: 235 if (msgbuf_write(&ibuf->w) == -1) 236 fatal("msgbuf_write"); 237 imsg_event_add(ibuf); 238 return; 239 default: 240 fatalx("unknown event"); 241 } 242 243 for (;;) { 244 if ((n = imsg_get(ibuf, &imsg)) == -1) 245 fatal("parent_dispatch_mta: imsg_read error"); 246 if (n == 0) 247 break; 248 249 switch (imsg.hdr.type) { 250 case IMSG_QUEUE_MESSAGE_FD: { 251 struct batch *batchp; 252 struct session *sessionp; 253 int fd; 254 255 if ((fd = imsg_get_fd(ibuf, &imsg)) == -1) { 256 /* NEEDS_FIX - unsure yet how it must be handled */ 257 fatalx("mta_dispatch_queue: imsg_get_fd"); 258 } 259 260 batchp = (struct batch *)imsg.data; 261 batchp = batch_by_id(env, batchp->id); 262 sessionp = batchp->sessionp; 263 264 if ((batchp->messagefp = fdopen(fd, "r")) == NULL) 265 fatal("mta_dispatch_queue: fdopen"); 266 267 session_respond(sessionp, "DATA"); 268 bufferevent_enable(sessionp->s_bev, EV_READ); 269 break; 270 } 271 default: 272 log_warnx("mta_dispatch_queue: got imsg %d", 273 imsg.hdr.type); 274 fatalx("mta_dispatch_queue: unexpected imsg"); 275 } 276 imsg_free(&imsg); 277 } 278 imsg_event_add(ibuf); 279 } 280 281 void 282 mta_dispatch_runner(int sig, short event, void *p) 283 { 284 struct smtpd *env = p; 285 struct imsgbuf *ibuf; 286 struct imsg imsg; 287 ssize_t n; 288 289 ibuf = env->sc_ibufs[PROC_RUNNER]; 290 switch (event) { 291 case EV_READ: 292 if ((n = imsg_read(ibuf)) == -1) 293 fatal("imsg_read_error"); 294 if (n == 0) { 295 /* this pipe is dead, so remove the event handler */ 296 event_del(&ibuf->ev); 297 event_loopexit(NULL); 298 return; 299 } 300 break; 301 case EV_WRITE: 302 if (msgbuf_write(&ibuf->w) == -1) 303 fatal("msgbuf_write"); 304 imsg_event_add(ibuf); 305 return; 306 default: 307 fatalx("unknown event"); 308 } 309 310 for (;;) { 311 if ((n = imsg_get(ibuf, &imsg)) == -1) 312 fatal("mta_dispatch_runner: imsg_read error"); 313 if (n == 0) 314 break; 315 316 switch (imsg.hdr.type) { 317 case IMSG_BATCH_CREATE: { 318 struct session *s; 319 struct batch *batchp; 320 321 /* create a client session */ 322 if ((s = calloc(1, sizeof(*s))) == NULL) 323 fatal(NULL); 324 s->s_state = S_INIT; 325 s->s_env = env; 326 s->s_id = queue_generate_id(); 327 TAILQ_INIT(&s->mxhosts); 328 SPLAY_INSERT(sessiontree, &s->s_env->sc_sessions, s); 329 330 /* create the batch for this session */ 331 batchp = calloc(1, sizeof (struct batch)); 332 if (batchp == NULL) 333 fatal("mta_dispatch_runner: calloc"); 334 335 *batchp = *(struct batch *)imsg.data; 336 batchp->session_id = s->s_id; 337 batchp->env = env; 338 batchp->flags = 0; 339 batchp->sessionp = s; 340 341 s->batch = batchp; 342 343 TAILQ_INIT(&batchp->messages); 344 SPLAY_INSERT(batchtree, &env->batch_queue, batchp); 345 346 break; 347 } 348 case IMSG_BATCH_APPEND: { 349 struct batch *batchp; 350 struct message *messagep; 351 352 messagep = calloc(1, sizeof (struct message)); 353 if (messagep == NULL) 354 fatal("mta_dispatch_runner: calloc"); 355 356 *messagep = *(struct message *)imsg.data; 357 358 batchp = batch_by_id(env, messagep->batch_id); 359 if (batchp == NULL) 360 fatalx("mta_dispatch_runner: internal inconsistency."); 361 362 batchp->session_ss = messagep->session_ss; 363 strlcpy(batchp->session_hostname, 364 messagep->session_hostname, 365 sizeof(batchp->session_hostname)); 366 strlcpy(batchp->session_helo, messagep->session_helo, 367 sizeof(batchp->session_helo)); 368 369 TAILQ_INSERT_TAIL(&batchp->messages, messagep, entry); 370 break; 371 } 372 case IMSG_BATCH_CLOSE: { 373 struct batch *batchp; 374 struct session *s; 375 376 batchp = (struct batch *)imsg.data; 377 batchp = batch_by_id(env, batchp->id); 378 if (batchp == NULL) 379 fatalx("mta_dispatch_runner: internal inconsistency."); 380 381 batchp->flags |= F_BATCH_COMPLETE; 382 383 log_debug("batch ready, we can initiate a session"); 384 385 s = batchp->sessionp; 386 387 mta_mxlookup(env, s, batchp->hostname, &batchp->rule); 388 389 break; 390 } 391 default: 392 log_warnx("mta_dispatch_runner: got imsg %d", 393 imsg.hdr.type); 394 fatalx("mta_dispatch_runner: unexpected imsg"); 395 } 396 imsg_free(&imsg); 397 } 398 imsg_event_add(ibuf); 399 } 400 401 void 402 mta_shutdown(void) 403 { 404 log_info("mail transfer agent exiting"); 405 _exit(0); 406 } 407 408 void 409 mta_setup_events(struct smtpd *env) 410 { 411 struct timeval tv; 412 413 evtimer_set(&env->sc_ev, mta_timeout, env); 414 tv.tv_sec = 3; 415 tv.tv_usec = 0; 416 evtimer_add(&env->sc_ev, &tv); 417 } 418 419 void 420 mta_disable_events(struct smtpd *env) 421 { 422 evtimer_del(&env->sc_ev); 423 } 424 425 void 426 mta_timeout(int fd, short event, void *p) 427 { 428 struct smtpd *env = p; 429 struct timeval tv; 430 431 tv.tv_sec = 3; 432 tv.tv_usec = 0; 433 evtimer_add(&env->sc_ev, &tv); 434 } 435 436 pid_t 437 mta(struct smtpd *env) 438 { 439 pid_t pid; 440 441 struct passwd *pw; 442 struct event ev_sigint; 443 struct event ev_sigterm; 444 445 struct peer peers[] = { 446 { PROC_QUEUE, mta_dispatch_queue }, 447 { PROC_RUNNER, mta_dispatch_runner }, 448 { PROC_LKA, mta_dispatch_lka } 449 }; 450 451 switch (pid = fork()) { 452 case -1: 453 fatal("mta: cannot fork"); 454 case 0: 455 break; 456 default: 457 return (pid); 458 } 459 460 ssl_init(); 461 purge_config(env, PURGE_EVERYTHING); 462 463 pw = env->sc_pw; 464 #ifndef DEBUG 465 if (chroot(pw->pw_dir) == -1) 466 fatal("mta: chroot"); 467 if (chdir("/") == -1) 468 fatal("mta: chdir(\"/\")"); 469 #else 470 #warning disabling privilege revocation and chroot in DEBUG MODE 471 #endif 472 473 setproctitle("mail transfer agent"); 474 smtpd_process = PROC_MTA; 475 476 #ifndef DEBUG 477 if (setgroups(1, &pw->pw_gid) || 478 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 479 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 480 fatal("mta: cannot drop privileges"); 481 #endif 482 483 event_init(); 484 485 signal_set(&ev_sigint, SIGINT, mta_sig_handler, env); 486 signal_set(&ev_sigterm, SIGTERM, mta_sig_handler, env); 487 signal_add(&ev_sigint, NULL); 488 signal_add(&ev_sigterm, NULL); 489 signal(SIGPIPE, SIG_IGN); 490 signal(SIGHUP, SIG_IGN); 491 492 config_pipes(env, peers, 3); 493 config_peers(env, peers, 3); 494 495 SPLAY_INIT(&env->batch_queue); 496 497 mta_setup_events(env); 498 event_dispatch(); 499 mta_shutdown(); 500 501 return (0); 502 } 503 504 void 505 mta_mxlookup(struct smtpd *env, struct session *sessionp, char *hostname, struct rule *rule) 506 { 507 struct mxreq mxreq; 508 509 mxreq.id = sessionp->s_id; 510 mxreq.rule = *rule; 511 (void)strlcpy(mxreq.hostname, hostname, MAXHOSTNAMELEN); 512 imsg_compose(env->sc_ibufs[PROC_LKA], IMSG_LKA_MX, 0, 0, -1, 513 &mxreq, sizeof(struct mxreq)); 514 } 515 516 /* shamelessly ripped usr.sbin/relayd/check_tcp.c ;) */ 517 int 518 mta_connect(struct session *sessionp) 519 { 520 int s; 521 int type; 522 struct linger lng; 523 struct sockaddr_in ssin; 524 struct sockaddr_in6 ssin6; 525 struct mxhost *mxhost; 526 527 mxhost = TAILQ_FIRST(&sessionp->mxhosts); 528 if (mxhost == NULL) 529 return -1; 530 531 if ((s = socket(mxhost->ss.ss_family, SOCK_STREAM, 0)) == -1) { 532 goto bad; 533 } 534 535 bzero(&lng, sizeof(lng)); 536 if (setsockopt(s, SOL_SOCKET, SO_LINGER, &lng, sizeof (lng)) == -1) { 537 goto bad; 538 } 539 540 type = 1; 541 if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &type, sizeof (type)) == -1) { 542 goto bad; 543 } 544 545 session_socket_blockmode(s, BM_NONBLOCK); 546 547 if (mxhost->ss.ss_family == PF_INET) { 548 ssin = *(struct sockaddr_in *)&mxhost->ss; 549 if (connect(s, (struct sockaddr *)&ssin, sizeof(struct sockaddr_in)) == -1) { 550 if (errno != EINPROGRESS) { 551 goto bad; 552 } 553 } 554 } 555 556 if (mxhost->ss.ss_family == PF_INET6) { 557 ssin6 = *(struct sockaddr_in6 *)&mxhost->ss; 558 if (connect(s, (struct sockaddr *)&ssin6, sizeof(struct sockaddr_in6)) == -1) { 559 if (errno != EINPROGRESS) { 560 goto bad; 561 } 562 } 563 } 564 sessionp->s_tv.tv_sec = SMTPD_CONNECT_TIMEOUT; 565 sessionp->s_tv.tv_usec = 0; 566 sessionp->s_fd = s; 567 event_set(&sessionp->s_ev, s, EV_TIMEOUT|EV_WRITE, mta_write, sessionp); 568 event_add(&sessionp->s_ev, &sessionp->s_tv); 569 570 return 1; 571 572 bad: 573 if (mxhost) { 574 TAILQ_REMOVE(&sessionp->mxhosts, mxhost, entry); 575 free(mxhost); 576 } 577 close(s); 578 return 0; 579 } 580 581 void 582 mta_write(int s, short event, void *arg) 583 { 584 struct session *sessionp = arg; 585 struct batch *batchp = sessionp->batch; 586 struct mxhost *mxhost; 587 int ret; 588 589 mxhost = TAILQ_FIRST(&sessionp->mxhosts); 590 591 if (event == EV_TIMEOUT) { 592 593 if (mxhost) { 594 TAILQ_REMOVE(&sessionp->mxhosts, mxhost, entry); 595 free(mxhost); 596 } 597 close(s); 598 599 if (sessionp->s_bev) { 600 bufferevent_free(sessionp->s_bev); 601 sessionp->s_bev = NULL; 602 } 603 strlcpy(batchp->errorline, "connection timed-out.", 604 sizeof(batchp->errorline)); 605 606 do { 607 ret = mta_connect(sessionp); 608 } while (ret == 0); 609 610 if (ret < 0) { 611 mta_batch_update_queue(batchp); 612 session_destroy(sessionp); 613 } 614 615 return; 616 } 617 618 sessionp->s_bev = bufferevent_new(s, mta_read_handler, mta_write_handler, 619 mta_error_handler, sessionp); 620 621 if (sessionp->s_bev == NULL) { 622 mta_batch_update_queue(batchp); 623 session_destroy(sessionp); 624 return; 625 } 626 627 if (mxhost && mxhost->flags & F_SSMTP) { 628 ssl_client_init(sessionp); 629 return; 630 } 631 bufferevent_enable(sessionp->s_bev, EV_READ); 632 } 633 634 void 635 mta_read_handler(struct bufferevent *bev, void *arg) 636 { 637 while (mta_reply_handler(bev, arg)) 638 ; 639 } 640 641 int 642 mta_reply_handler(struct bufferevent *bev, void *arg) 643 { 644 struct session *sessionp = arg; 645 struct batch *batchp = sessionp->batch; 646 struct smtpd *env = batchp->env; 647 struct message *messagep = NULL; 648 char *line; 649 int i; 650 int code; 651 #define F_ISINFO 0x1 652 #define F_ISPROTOERROR 0x2 653 char codebuf[4]; 654 const char *errstr; 655 int flags = 0; 656 struct mxhost *mxhost = TAILQ_FIRST(&sessionp->mxhosts); 657 658 line = evbuffer_readline(bev->input); 659 if (line == NULL) 660 return 0; 661 662 log_debug("remote server sent: [%s]", line); 663 664 strlcpy(codebuf, line, sizeof(codebuf)); 665 code = strtonum(codebuf, 0, UINT16_MAX, &errstr); 666 if (errstr || code < 100) { 667 /* Server sent invalid line, protocol error */ 668 batchp->status |= S_BATCH_PERMFAILURE; 669 strlcpy(batchp->errorline, line, sizeof(batchp->errorline)); 670 mta_batch_update_queue(batchp); 671 session_destroy(sessionp); 672 return 0; 673 } 674 675 if (line[3] == '-') { 676 if (strcasecmp(&line[4], "STARTTLS") == 0) 677 sessionp->s_flags |= F_PEERHASTLS; 678 else if (strncasecmp(&line[4], "AUTH ", 5) == 0 || 679 strncasecmp(&line[4], "AUTH-", 5) == 0) 680 sessionp->s_flags |= F_PEERHASAUTH; 681 return 1; 682 } 683 684 switch (code) { 685 case 250: 686 if (sessionp->s_state == S_DONE) { 687 mta_batch_update_queue(batchp); 688 session_destroy(sessionp); 689 return 0; 690 } 691 692 if (sessionp->s_state == S_GREETED && 693 (sessionp->s_flags & F_PEERHASTLS) && 694 !(sessionp->s_flags & F_SECURE)) { 695 session_respond(sessionp, "STARTTLS"); 696 sessionp->s_state = S_TLS; 697 return 0; 698 } 699 700 if (sessionp->s_state == S_GREETED && 701 (sessionp->s_flags & F_PEERHASAUTH) && 702 (sessionp->s_flags & F_SECURE) && 703 (mxhost->flags & F_AUTH) && 704 (mxhost->credentials[0] != '\0')) { 705 log_debug("AUTH PLAIN %s", mxhost->credentials); 706 session_respond(sessionp, "AUTH PLAIN %s", 707 mxhost->credentials); 708 sessionp->s_state = S_AUTH_INIT; 709 return 0; 710 } 711 712 if (sessionp->s_state == S_GREETED && 713 !(sessionp->s_flags & F_PEERHASTLS) && 714 mxhost->flags & F_STARTTLS) { 715 /* PERM - we want TLS but it is not advertised */ 716 batchp->status |= S_BATCH_PERMFAILURE; 717 mta_batch_update_queue(batchp); 718 session_destroy(sessionp); 719 return 0; 720 } 721 722 if (sessionp->s_state == S_GREETED && 723 !(sessionp->s_flags & F_PEERHASAUTH) && 724 mxhost->flags & F_AUTH) { 725 /* PERM - we want AUTH but it is not advertised */ 726 batchp->status |= S_BATCH_PERMFAILURE; 727 mta_batch_update_queue(batchp); 728 session_destroy(sessionp); 729 return 0; 730 } 731 732 break; 733 734 case 220: 735 if (sessionp->s_state == S_TLS) { 736 ssl_client_init(sessionp); 737 bufferevent_disable(bev, EV_READ|EV_WRITE); 738 sessionp->s_state = S_GREETED; 739 return 0; 740 } 741 742 session_respond(sessionp, "EHLO %s", env->sc_hostname); 743 sessionp->s_state = S_GREETED; 744 return 1; 745 746 case 235: 747 if (sessionp->s_state == S_AUTH_INIT) { 748 sessionp->s_flags |= F_AUTHENTICATED; 749 sessionp->s_state = S_GREETED; 750 break; 751 } 752 return 0; 753 case 421: 754 case 450: 755 case 451: 756 batchp->status |= S_BATCH_TEMPFAILURE; 757 strlcpy(batchp->errorline, line, sizeof(batchp->errorline)); 758 mta_batch_update_queue(batchp); 759 session_destroy(sessionp); 760 return 0; 761 762 /* The following codes are state dependant and will cause 763 * a batch rejection if returned at the wrong state. 764 */ 765 case 530: 766 case 550: 767 if (sessionp->s_state == S_RCPT) { 768 batchp->messagep->status = (S_MESSAGE_REJECTED|S_MESSAGE_PERMFAILURE); 769 strlcpy(batchp->messagep->session_errorline, line, 770 sizeof(batchp->messagep->session_errorline)); 771 break; 772 } 773 case 354: 774 if (sessionp->s_state == S_RCPT && batchp->messagep == NULL) { 775 sessionp->s_state = S_DATA; 776 break; 777 } 778 779 case 221: 780 if (sessionp->s_state == S_DONE) { 781 mta_batch_update_queue(batchp); 782 session_destroy(sessionp); 783 return 0; 784 } 785 786 case 535: 787 /* Authentication failed*/ 788 case 552: 789 case 553: 790 flags |= F_ISPROTOERROR; 791 default: 792 /* Server sent code we know nothing about, error */ 793 if (!(flags & F_ISPROTOERROR)) 794 log_debug("Ouch, SMTP session returned unhandled %d status.", code); 795 796 batchp->status |= S_BATCH_PERMFAILURE; 797 strlcpy(batchp->errorline, line, sizeof(batchp->errorline)); 798 mta_batch_update_queue(batchp); 799 session_destroy(sessionp); 800 return 0; 801 } 802 803 804 switch (sessionp->s_state) { 805 case S_GREETED: { 806 char *user; 807 char *domain; 808 809 if (batchp->type & T_DAEMON_BATCH) { 810 user = "MAILER-DAEMON"; 811 domain = env->sc_hostname; 812 } 813 else { 814 messagep = TAILQ_FIRST(&batchp->messages); 815 user = messagep->sender.user; 816 domain = messagep->sender.domain; 817 } 818 819 if (user[0] == '\0' && domain[0] == '\0') 820 session_respond(sessionp, "MAIL FROM:<>"); 821 else 822 session_respond(sessionp, "MAIL FROM:<%s@%s>", user, domain); 823 824 sessionp->s_state = S_MAIL; 825 826 break; 827 } 828 829 case S_MAIL: 830 sessionp->s_state = S_RCPT; 831 832 case S_RCPT: { 833 char *user; 834 char *domain; 835 836 /* Is this the first RCPT ? */ 837 if (batchp->messagep == NULL) 838 messagep = TAILQ_FIRST(&batchp->messages); 839 else { 840 /* We already had a RCPT, mark is as accepted and 841 * fetch next one from queue if we aren't dealing 842 * with a daemon batch. 843 */ 844 if (batchp->type & T_DAEMON_BATCH) 845 messagep = NULL; 846 else { 847 messagep = batchp->messagep; 848 if ((messagep->status & S_MESSAGE_REJECTED) == 0) 849 messagep->status = S_MESSAGE_ACCEPTED; 850 messagep = TAILQ_NEXT(batchp->messagep, entry); 851 } 852 } 853 batchp->messagep = messagep; 854 855 if (messagep) { 856 if (batchp->type & T_DAEMON_BATCH) { 857 user = messagep->sender.user; 858 domain = messagep->sender.domain; 859 } 860 else { 861 user = messagep->recipient.user; 862 domain = messagep->recipient.domain; 863 } 864 session_respond(sessionp, "RCPT TO:<%s@%s>", user, domain); 865 } 866 else { 867 /* Do we have at least one accepted recipient ? */ 868 if ((batchp->type & T_DAEMON_BATCH) == 0) { 869 TAILQ_FOREACH(messagep, &batchp->messages, entry) { 870 if (messagep->status & S_MESSAGE_ACCEPTED) 871 break; 872 } 873 if (messagep == NULL) { 874 batchp->status |= S_BATCH_PERMFAILURE; 875 mta_batch_update_queue(batchp); 876 session_destroy(sessionp); 877 return 0; 878 } 879 } 880 881 imsg_compose(env->sc_ibufs[PROC_QUEUE], IMSG_QUEUE_MESSAGE_FD, 882 0, 0, -1, batchp, sizeof(*batchp)); 883 bufferevent_disable(sessionp->s_bev, EV_READ); 884 } 885 break; 886 } 887 888 case S_DATA: { 889 session_respond(sessionp, "Received: from %s (%s [%s])", 890 batchp->session_helo, batchp->session_hostname, 891 ss_to_text(&batchp->session_ss)); 892 893 session_respond(sessionp, "\tby %s with ESMTP id %s;", 894 batchp->env->sc_hostname, batchp->message_id); 895 896 session_respond(sessionp, "\t%s", time_to_text(batchp->creation)); 897 898 if (sessionp->s_flags & F_SECURE) { 899 log_info("%s: version=%s cipher=%s bits=%d", 900 batchp->message_id, 901 SSL_get_cipher_version(sessionp->s_ssl), 902 SSL_get_cipher_name(sessionp->s_ssl), 903 SSL_get_cipher_bits(sessionp->s_ssl, NULL)); 904 } 905 906 TAILQ_FOREACH(messagep, &batchp->messages, entry) { 907 session_respond(sessionp, "X-OpenSMTPD-Loop: %s@%s", 908 messagep->session_rcpt.user, 909 messagep->session_rcpt.domain); 910 } 911 912 if (batchp->type & T_DAEMON_BATCH) { 913 session_respond(sessionp, "Hi !"); 914 session_respond(sessionp, "%s", ""); 915 session_respond(sessionp, "This is the MAILER-DAEMON, please DO NOT REPLY to this e-mail it is"); 916 session_respond(sessionp, "just a notification to let you know that an error has occured."); 917 session_respond(sessionp, "%s", ""); 918 919 if (batchp->status & S_BATCH_PERMFAILURE) { 920 session_respond(sessionp, "You ran into a PERMANENT FAILURE, which means that the e-mail can't"); 921 session_respond(sessionp, "be delivered to the remote host no matter how much I'll try."); 922 session_respond(sessionp, "%s", ""); 923 session_respond(sessionp, "Diagnostic:"); 924 session_respond(sessionp, "%s", batchp->errorline); 925 session_respond(sessionp, "%s", ""); 926 } 927 928 if (batchp->status & S_BATCH_TEMPFAILURE) { 929 session_respond(sessionp, "You ran into a TEMPORARY FAILURE, which means that the e-mail can't"); 930 session_respond(sessionp, "be delivered right now, but could be deliberable at a later time. I"); 931 session_respond(sessionp, "will attempt until it succeeds for the next four days, then let you"); 932 session_respond(sessionp, "know if it didn't work out."); 933 session_respond(sessionp, "%s", ""); 934 session_respond(sessionp, "Diagnostic:"); 935 session_respond(sessionp, "%s", batchp->errorline); 936 session_respond(sessionp, "%s", ""); 937 } 938 939 i = 0; 940 TAILQ_FOREACH(messagep, &batchp->messages, entry) { 941 if (messagep->status & S_MESSAGE_TEMPFAILURE) { 942 if (i == 0) { 943 session_respond(sessionp, "The following recipients caused a temporary failure:"); 944 ++i; 945 } 946 947 session_respond(sessionp, 948 "\t<%s@%s>:", messagep->recipient.user, messagep->recipient.domain); 949 session_respond(sessionp, 950 "%s", messagep->session_errorline); 951 session_respond(sessionp, "%s", ""); 952 } 953 } 954 955 i = 0; 956 TAILQ_FOREACH(messagep, &batchp->messages, entry) { 957 if (messagep->status & S_MESSAGE_PERMFAILURE) { 958 if (i == 0) { 959 session_respond(sessionp, 960 "The following recipients caused a permanent failure:"); 961 ++i; 962 } 963 964 session_respond(sessionp, 965 "\t<%s@%s>:", messagep->recipient.user, messagep->recipient.domain); 966 session_respond(sessionp, 967 "%s", messagep->session_errorline); 968 session_respond(sessionp, "%s", ""); 969 } 970 } 971 972 session_respond(sessionp, "Below is a copy of the original message:"); 973 session_respond(sessionp, "%s", ""); 974 } 975 976 break; 977 } 978 case S_DONE: 979 session_respond(sessionp, "QUIT"); 980 sessionp->s_state = S_QUIT; 981 break; 982 983 default: 984 log_info("unknown command: %d", sessionp->s_state); 985 } 986 987 return 1; 988 } 989 990 void 991 mta_write_handler(struct bufferevent *bev, void *arg) 992 { 993 struct session *sessionp = arg; 994 struct batch *batchp = sessionp->batch; 995 char *buf, *lbuf; 996 size_t len; 997 998 if (sessionp->s_state == S_QUIT) { 999 bufferevent_disable(bev, EV_READ|EV_WRITE); 1000 log_debug("closing connection because of QUIT"); 1001 close(sessionp->s_fd); 1002 return; 1003 } 1004 1005 /* Progressively fill the output buffer with data */ 1006 if (sessionp->s_state == S_DATA) { 1007 1008 lbuf = NULL; 1009 if ((buf = fgetln(batchp->messagefp, &len))) { 1010 if (buf[len - 1] == '\n') 1011 buf[len - 1] = '\0'; 1012 else { 1013 if ((lbuf = malloc(len + 1)) == NULL) 1014 fatal("mta_write_handler: malloc"); 1015 memcpy(lbuf, buf, len); 1016 lbuf[len] = '\0'; 1017 buf = lbuf; 1018 } 1019 1020 /* "If first character of the line is a period, one 1021 * additional period is inserted at the beginning." 1022 * [4.5.2] 1023 */ 1024 if (*buf == '.') 1025 evbuffer_add_printf(sessionp->s_bev->output, "."); 1026 1027 session_respond(sessionp, "%s", buf); 1028 free(lbuf); 1029 lbuf = NULL; 1030 } 1031 else { 1032 session_respond(sessionp, "."); 1033 sessionp->s_state = S_DONE; 1034 fclose(batchp->messagefp); 1035 batchp->messagefp = NULL; 1036 } 1037 } 1038 } 1039 1040 void 1041 mta_error_handler(struct bufferevent *bev, short error, void *arg) 1042 { 1043 struct session *sessionp = arg; 1044 1045 if (error & (EVBUFFER_TIMEOUT|EVBUFFER_EOF)) { 1046 bufferevent_disable(bev, EV_READ|EV_WRITE); 1047 log_debug("closing connection because of an error"); 1048 close(sessionp->s_fd); 1049 return; 1050 } 1051 } 1052 1053 void 1054 mta_batch_update_queue(struct batch *batchp) 1055 { 1056 struct smtpd *env = batchp->env; 1057 struct message *messagep; 1058 1059 while ((messagep = TAILQ_FIRST(&batchp->messages)) != NULL) { 1060 1061 if (batchp->status & S_BATCH_PERMFAILURE) { 1062 messagep->status |= S_MESSAGE_PERMFAILURE; 1063 } 1064 1065 if (batchp->status & S_BATCH_TEMPFAILURE) { 1066 if (messagep->status != S_MESSAGE_PERMFAILURE) 1067 messagep->status |= S_MESSAGE_TEMPFAILURE; 1068 } 1069 1070 if ((messagep->status & S_MESSAGE_TEMPFAILURE) == 0 && 1071 (messagep->status & S_MESSAGE_PERMFAILURE) == 0) { 1072 log_info("%s: to=<%s@%s>, delay=%d, stat=Sent", 1073 messagep->message_uid, 1074 messagep->recipient.user, 1075 messagep->recipient.domain, 1076 time(NULL) - messagep->creation); 1077 } 1078 1079 imsg_compose(env->sc_ibufs[PROC_QUEUE], 1080 IMSG_QUEUE_MESSAGE_UPDATE, 0, 0, -1, messagep, 1081 sizeof(struct message)); 1082 TAILQ_REMOVE(&batchp->messages, messagep, entry); 1083 free(messagep); 1084 } 1085 1086 SPLAY_REMOVE(batchtree, &env->batch_queue, batchp); 1087 1088 if (batchp->messagefp) 1089 fclose(batchp->messagefp); 1090 1091 free(batchp); 1092 1093 } 1094