1 /* $OpenBSD: smtp_session.c,v 1.121 2009/10/06 18:20:44 gilles Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> 5 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> 6 * Copyright (c) 2008-2009 Jacek Masiulaniec <jacekm@dobremiasto.net> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/types.h> 22 #include <sys/queue.h> 23 #include <sys/tree.h> 24 #include <sys/param.h> 25 #include <sys/socket.h> 26 27 #include <netinet/in.h> 28 #include <arpa/inet.h> 29 30 #include <openssl/ssl.h> 31 32 #include <ctype.h> 33 #include <errno.h> 34 #include <event.h> 35 #include <pwd.h> 36 #include <regex.h> 37 #include <resolv.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 43 #include "smtpd.h" 44 45 int session_rfc5321_helo_handler(struct session *, char *); 46 int session_rfc5321_ehlo_handler(struct session *, char *); 47 int session_rfc5321_rset_handler(struct session *, char *); 48 int session_rfc5321_noop_handler(struct session *, char *); 49 int session_rfc5321_data_handler(struct session *, char *); 50 int session_rfc5321_mail_handler(struct session *, char *); 51 int session_rfc5321_rcpt_handler(struct session *, char *); 52 int session_rfc5321_vrfy_handler(struct session *, char *); 53 int session_rfc5321_expn_handler(struct session *, char *); 54 int session_rfc5321_turn_handler(struct session *, char *); 55 int session_rfc5321_help_handler(struct session *, char *); 56 int session_rfc5321_quit_handler(struct session *, char *); 57 int session_rfc5321_none_handler(struct session *, char *); 58 59 int session_rfc1652_mail_handler(struct session *, char *); 60 61 int session_rfc3207_stls_handler(struct session *, char *); 62 63 int session_rfc4954_auth_handler(struct session *, char *); 64 void session_rfc4954_auth_plain(struct session *, char *); 65 void session_rfc4954_auth_login(struct session *, char *); 66 67 void session_read(struct bufferevent *, void *); 68 void session_read_data(struct session *, char *); 69 void session_write(struct bufferevent *, void *); 70 void session_error(struct bufferevent *, short event, void *); 71 void session_command(struct session *, char *); 72 char *session_readline(struct session *); 73 void session_respond_delayed(int, short, void *); 74 int session_set_path(struct path *, char *); 75 void session_imsg(struct session *, enum smtp_proc_type, 76 enum imsg_type, u_int32_t, pid_t, int, void *, u_int16_t); 77 78 struct session_cmd { 79 char *name; 80 int (*func)(struct session *, char *); 81 }; 82 83 struct session_cmd rfc5321_cmdtab[] = { 84 { "helo", session_rfc5321_helo_handler }, 85 { "ehlo", session_rfc5321_ehlo_handler }, 86 { "rset", session_rfc5321_rset_handler }, 87 { "noop", session_rfc5321_noop_handler }, 88 { "data", session_rfc5321_data_handler }, 89 { "mail from", session_rfc5321_mail_handler }, 90 { "rcpt to", session_rfc5321_rcpt_handler }, 91 { "vrfy", session_rfc5321_vrfy_handler }, 92 { "expn", session_rfc5321_expn_handler }, 93 { "turn", session_rfc5321_turn_handler }, 94 { "help", session_rfc5321_help_handler }, 95 { "quit", session_rfc5321_quit_handler } 96 }; 97 98 struct session_cmd rfc1652_cmdtab[] = { 99 { "mail from", session_rfc1652_mail_handler }, 100 }; 101 102 struct session_cmd rfc3207_cmdtab[] = { 103 { "starttls", session_rfc3207_stls_handler } 104 }; 105 106 struct session_cmd rfc4954_cmdtab[] = { 107 { "auth", session_rfc4954_auth_handler } 108 }; 109 110 int 111 session_rfc3207_stls_handler(struct session *s, char *args) 112 { 113 if (! ADVERTISE_TLS(s)) 114 return 0; 115 116 if (s->s_state == S_GREETED) { 117 session_respond(s, "503 Polite people say HELO first"); 118 return 1; 119 } 120 121 if (s->s_state != S_HELO) { 122 session_respond(s, "503 TLS not allowed at this stage"); 123 return 1; 124 } 125 126 if (args != NULL) { 127 session_respond(s, "501 No parameters allowed"); 128 return 1; 129 } 130 131 s->s_state = S_TLS; 132 session_respond(s, "220 Ready to start TLS"); 133 134 return 1; 135 } 136 137 int 138 session_rfc4954_auth_handler(struct session *s, char *args) 139 { 140 char *method; 141 char *eom; 142 143 if (! ADVERTISE_AUTH(s)) { 144 if (s->s_flags & F_AUTHENTICATED) { 145 session_respond(s, "503 Already authenticated"); 146 return 1; 147 } else 148 return 0; 149 } 150 151 if (s->s_state == S_GREETED) { 152 session_respond(s, "503 Polite people say HELO first"); 153 return 1; 154 } 155 156 if (s->s_state != S_HELO) { 157 session_respond(s, "503 Session already in progress"); 158 return 1; 159 } 160 161 if (args == NULL) { 162 session_respond(s, "501 No parameters given"); 163 return 1; 164 } 165 166 method = args; 167 eom = strchr(args, ' '); 168 if (eom == NULL) 169 eom = strchr(args, '\t'); 170 if (eom != NULL) 171 *eom++ = '\0'; 172 173 if (strcasecmp(method, "PLAIN") == 0) 174 session_rfc4954_auth_plain(s, eom); 175 else if (strcasecmp(method, "LOGIN") == 0) 176 session_rfc4954_auth_login(s, eom); 177 else 178 session_respond(s, "504 AUTH method '%s' unsupported", method); 179 180 return 1; 181 } 182 183 void 184 session_rfc4954_auth_plain(struct session *s, char *arg) 185 { 186 struct auth *a = &s->s_auth; 187 char buf[1024], *user, *pass; 188 int len; 189 190 switch (s->s_state) { 191 case S_HELO: 192 if (arg == NULL) { 193 s->s_state = S_AUTH_INIT; 194 session_respond(s, "334 "); 195 return; 196 } 197 s->s_state = S_AUTH_INIT; 198 /* FALLTHROUGH */ 199 200 case S_AUTH_INIT: 201 /* String is not NUL terminated, leave room. */ 202 if ((len = __b64_pton(arg, (unsigned char *)buf, sizeof(buf) - 1)) == -1) 203 goto abort; 204 /* buf is a byte string, NUL terminate. */ 205 buf[len] = '\0'; 206 207 /* 208 * Skip "foo" in "foo\0user\0pass", if present. 209 */ 210 user = memchr(buf, '\0', len); 211 if (user == NULL || user >= buf + len - 2) 212 goto abort; 213 user++; /* skip NUL */ 214 if (strlcpy(a->user, user, sizeof(a->user)) >= sizeof(a->user)) 215 goto abort; 216 217 pass = memchr(user, '\0', len - (user - buf)); 218 if (pass == NULL || pass >= buf + len - 2) 219 goto abort; 220 pass++; /* skip NUL */ 221 if (strlcpy(a->pass, pass, sizeof(a->pass)) >= sizeof(a->pass)) 222 goto abort; 223 224 s->s_state = S_AUTH_FINALIZE; 225 226 a->id = s->s_id; 227 session_imsg(s, PROC_PARENT, IMSG_PARENT_AUTHENTICATE, 0, 0, -1, 228 a, sizeof(*a)); 229 230 bzero(a->pass, sizeof(a->pass)); 231 return; 232 233 default: 234 fatal("session_rfc4954_auth_plain: unknown state"); 235 } 236 237 abort: 238 session_respond(s, "501 Syntax error"); 239 s->s_state = S_HELO; 240 } 241 242 void 243 session_rfc4954_auth_login(struct session *s, char *arg) 244 { 245 struct auth *a = &s->s_auth; 246 247 switch (s->s_state) { 248 case S_HELO: 249 s->s_state = S_AUTH_USERNAME; 250 session_respond(s, "334 VXNlcm5hbWU6"); 251 return; 252 253 case S_AUTH_USERNAME: 254 bzero(a->user, sizeof(a->user)); 255 if (__b64_pton(arg, (unsigned char *)a->user, sizeof(a->user) - 1) == -1) 256 goto abort; 257 258 s->s_state = S_AUTH_PASSWORD; 259 session_respond(s, "334 UGFzc3dvcmQ6"); 260 return; 261 262 case S_AUTH_PASSWORD: 263 bzero(a->pass, sizeof(a->pass)); 264 if (__b64_pton(arg, (unsigned char *)a->pass, sizeof(a->pass) - 1) == -1) 265 goto abort; 266 267 s->s_state = S_AUTH_FINALIZE; 268 269 a->id = s->s_id; 270 session_imsg(s, PROC_PARENT, IMSG_PARENT_AUTHENTICATE, 0, 0, -1, 271 a, sizeof(*a)); 272 273 bzero(a->pass, sizeof(a->pass)); 274 return; 275 276 default: 277 fatal("session_rfc4954_auth_login: unknown state"); 278 } 279 280 abort: 281 session_respond(s, "501 Syntax error"); 282 s->s_state = S_HELO; 283 } 284 285 int 286 session_rfc1652_mail_handler(struct session *s, char *args) 287 { 288 char *body; 289 290 if (s->s_state == S_GREETED) { 291 session_respond(s, "503 Polite people say HELO first"); 292 return 1; 293 } 294 295 for (body = strrchr(args, ' '); body != NULL; 296 body = strrchr(args, ' ')) { 297 *body++ = '\0'; 298 299 if (strncasecmp(body, "AUTH=", 5) == 0) { 300 log_debug("AUTH in MAIL FROM command, skipping"); 301 continue; 302 } 303 304 if (strncasecmp(body, "BODY=", 5) == 0) { 305 log_debug("BODY in MAIL FROM command"); 306 307 if (strncasecmp("body=7bit", body, 9) == 0) { 308 s->s_flags &= ~F_8BITMIME; 309 continue; 310 } 311 312 else if (strncasecmp("body=8bitmime", body, 13) != 0) { 313 session_respond(s, "503 Invalid BODY"); 314 return 1; 315 } 316 } 317 } 318 319 return session_rfc5321_mail_handler(s, args); 320 } 321 322 int 323 session_rfc5321_helo_handler(struct session *s, char *args) 324 { 325 if (args == NULL) { 326 session_respond(s, "501 HELO requires domain address"); 327 return 1; 328 } 329 330 if (strlcpy(s->s_msg.session_helo, args, sizeof(s->s_msg.session_helo)) 331 >= sizeof(s->s_msg.session_helo)) { 332 session_respond(s, "501 Invalid domain name"); 333 return 1; 334 } 335 336 s->s_state = S_HELO; 337 s->s_flags &= F_SECURE|F_AUTHENTICATED; 338 339 session_respond(s, "250 %s Hello %s [%s], pleased to meet you", 340 s->s_env->sc_hostname, args, ss_to_text(&s->s_ss)); 341 342 return 1; 343 } 344 345 int 346 session_rfc5321_ehlo_handler(struct session *s, char *args) 347 { 348 if (args == NULL) { 349 session_respond(s, "501 EHLO requires domain address"); 350 return 1; 351 } 352 353 if (strlcpy(s->s_msg.session_helo, args, sizeof(s->s_msg.session_helo)) 354 >= sizeof(s->s_msg.session_helo)) { 355 session_respond(s, "501 Invalid domain name"); 356 return 1; 357 } 358 359 s->s_state = S_HELO; 360 s->s_flags &= F_SECURE|F_AUTHENTICATED; 361 s->s_flags |= F_EHLO; 362 s->s_flags |= F_8BITMIME; 363 364 session_respond(s, "250-%s Hello %s [%s], pleased to meet you", 365 s->s_env->sc_hostname, args, ss_to_text(&s->s_ss)); 366 session_respond(s, "250-8BITMIME"); 367 368 if (ADVERTISE_TLS(s)) 369 session_respond(s, "250-STARTTLS"); 370 371 if (ADVERTISE_AUTH(s)) 372 session_respond(s, "250-AUTH PLAIN LOGIN"); 373 374 session_respond(s, "250 HELP"); 375 376 return 1; 377 } 378 379 int 380 session_rfc5321_rset_handler(struct session *s, char *args) 381 { 382 s->s_state = S_HELO; 383 session_respond(s, "250 Reset state"); 384 385 return 1; 386 } 387 388 int 389 session_rfc5321_noop_handler(struct session *s, char *args) 390 { 391 session_respond(s, "250 OK"); 392 393 return 1; 394 } 395 396 int 397 session_rfc5321_mail_handler(struct session *s, char *args) 398 { 399 if (s->s_state == S_GREETED) { 400 session_respond(s, "503 Polite people say HELO first"); 401 return 1; 402 } 403 404 if (s->s_state != S_HELO) { 405 session_respond(s, "503 Sender already specified"); 406 return 1; 407 } 408 409 if (! session_set_path(&s->s_msg.sender, args)) { 410 /* No need to even transmit to MFA, path is invalid */ 411 session_respond(s, "553 Sender address syntax error"); 412 return 1; 413 } 414 415 s->rcptcount = 0; 416 s->s_state = S_MAIL_MFA; 417 s->s_msg.id = s->s_id; 418 s->s_msg.session_id = s->s_id; 419 s->s_msg.session_ss = s->s_ss; 420 421 log_debug("session_rfc5321_mail_handler: sending notification to mfa"); 422 423 session_imsg(s, PROC_MFA, IMSG_MFA_MAIL, 0, 0, -1, &s->s_msg, 424 sizeof(s->s_msg)); 425 return 1; 426 } 427 428 int 429 session_rfc5321_rcpt_handler(struct session *s, char *args) 430 { 431 if (s->s_state == S_GREETED) { 432 session_respond(s, "503 Polite people say HELO first"); 433 return 1; 434 } 435 436 if (s->s_state == S_HELO) { 437 session_respond(s, "503 Need MAIL before RCPT"); 438 return 1; 439 } 440 441 if (! session_set_path(&s->s_msg.session_rcpt, args)) { 442 /* No need to even transmit to MFA, path is invalid */ 443 session_respond(s, "553 Recipient address syntax error"); 444 return 1; 445 } 446 447 s->s_state = S_RCPT_MFA; 448 449 session_imsg(s, PROC_MFA, IMSG_MFA_RCPT, 0, 0, -1, &s->s_msg, 450 sizeof(s->s_msg)); 451 return 1; 452 } 453 454 int 455 session_rfc5321_quit_handler(struct session *s, char *args) 456 { 457 session_respond(s, "221 %s Closing connection", s->s_env->sc_hostname); 458 459 s->s_flags |= F_QUIT; 460 461 return 1; 462 } 463 464 int 465 session_rfc5321_data_handler(struct session *s, char *args) 466 { 467 if (s->s_state == S_GREETED) { 468 session_respond(s, "503 Polite people say HELO first"); 469 return 1; 470 } 471 472 if (s->s_state == S_HELO) { 473 session_respond(s, "503 Need MAIL before DATA"); 474 return 1; 475 } 476 477 if (s->s_state == S_MAIL) { 478 session_respond(s, "503 Need RCPT before DATA"); 479 return 1; 480 } 481 482 s->s_state = S_DATA_QUEUE; 483 484 session_imsg(s, PROC_QUEUE, IMSG_QUEUE_MESSAGE_FILE, 0, 0, -1, 485 &s->s_msg, sizeof(s->s_msg)); 486 487 return 1; 488 } 489 490 int 491 session_rfc5321_vrfy_handler(struct session *s, char *args) 492 { 493 session_respond(s, "252 Cannot VRFY; try RCPT to attempt delivery"); 494 495 return 1; 496 } 497 498 int 499 session_rfc5321_expn_handler(struct session *s, char *args) 500 { 501 session_respond(s, "502 Sorry, we do not allow this operation"); 502 503 return 1; 504 } 505 506 int 507 session_rfc5321_turn_handler(struct session *s, char *args) 508 { 509 session_respond(s, "502 Sorry, we do not allow this operation"); 510 511 return 1; 512 } 513 514 int 515 session_rfc5321_help_handler(struct session *s, char *args) 516 { 517 session_respond(s, "214- This is OpenSMTPD"); 518 session_respond(s, "214- To report bugs in the implementation, please " 519 "contact bugs@openbsd.org"); 520 session_respond(s, "214- with full details"); 521 session_respond(s, "214 End of HELP info"); 522 523 return 1; 524 } 525 526 void 527 session_command(struct session *s, char *cmd) 528 { 529 char *ep, *args; 530 unsigned int i; 531 532 if ((ep = strchr(cmd, ':')) == NULL) 533 ep = strchr(cmd, ' '); 534 if (ep != NULL) { 535 *ep = '\0'; 536 args = ++ep; 537 while (isspace((int)*args)) 538 args++; 539 } else 540 args = NULL; 541 542 log_debug("command: %s\targs: %s", cmd, args); 543 544 if (!(s->s_flags & F_EHLO)) 545 goto rfc5321; 546 547 /* RFC 1652 - 8BITMIME */ 548 for (i = 0; i < nitems(rfc1652_cmdtab); ++i) 549 if (strcasecmp(rfc1652_cmdtab[i].name, cmd) == 0) 550 break; 551 if (i < nitems(rfc1652_cmdtab)) { 552 if (rfc1652_cmdtab[i].func(s, args)) 553 return; 554 } 555 556 /* RFC 3207 - STARTTLS */ 557 for (i = 0; i < nitems(rfc3207_cmdtab); ++i) 558 if (strcasecmp(rfc3207_cmdtab[i].name, cmd) == 0) 559 break; 560 if (i < nitems(rfc3207_cmdtab)) { 561 if (rfc3207_cmdtab[i].func(s, args)) 562 return; 563 } 564 565 /* RFC 4954 - AUTH */ 566 for (i = 0; i < nitems(rfc4954_cmdtab); ++i) 567 if (strcasecmp(rfc4954_cmdtab[i].name, cmd) == 0) 568 break; 569 if (i < nitems(rfc4954_cmdtab)) { 570 if (rfc4954_cmdtab[i].func(s, args)) 571 return; 572 } 573 574 rfc5321: 575 /* RFC 5321 - SMTP */ 576 for (i = 0; i < nitems(rfc5321_cmdtab); ++i) 577 if (strcasecmp(rfc5321_cmdtab[i].name, cmd) == 0) 578 break; 579 if (i < nitems(rfc5321_cmdtab)) { 580 if (rfc5321_cmdtab[i].func(s, args)) 581 return; 582 } 583 584 session_respond(s, "500 Command unrecognized"); 585 } 586 587 void 588 session_pickup(struct session *s, struct submit_status *ss) 589 { 590 if (s == NULL) 591 fatal("session_pickup: desynchronized"); 592 593 if ((ss != NULL && ss->code == 421) || 594 (s->s_msg.status & S_MESSAGE_TEMPFAILURE)) { 595 session_respond(s, "421 Service temporarily unavailable"); 596 s->s_env->stats->smtp.tempfail++; 597 s->s_flags |= F_QUIT; 598 return; 599 } 600 601 switch (s->s_state) { 602 case S_INIT: 603 s->s_state = S_GREETED; 604 log_debug("session_pickup: greeting client"); 605 session_respond(s, SMTPD_BANNER, s->s_env->sc_hostname); 606 break; 607 608 case S_TLS: 609 if (s->s_flags & F_WRITEONLY) 610 fatalx("session_pickup: corrupt session"); 611 bufferevent_enable(s->s_bev, EV_READ); 612 s->s_state = S_GREETED; 613 break; 614 615 case S_AUTH_FINALIZE: 616 if (s->s_flags & F_AUTHENTICATED) 617 session_respond(s, "235 Authentication succeeded"); 618 else 619 session_respond(s, "535 Authentication failed"); 620 s->s_state = S_HELO; 621 break; 622 623 case S_MAIL_MFA: 624 if (ss == NULL) 625 fatalx("bad ss at S_MAIL_MFA"); 626 if (ss->code != 250) { 627 s->s_state = S_HELO; 628 session_respond(s, "%d Sender rejected", ss->code); 629 return; 630 } 631 632 s->s_state = S_MAIL_QUEUE; 633 s->s_msg.sender = ss->u.path; 634 635 session_imsg(s, PROC_QUEUE, IMSG_QUEUE_CREATE_MESSAGE, 0, 0, -1, 636 &s->s_msg, sizeof(s->s_msg)); 637 break; 638 639 case S_MAIL_QUEUE: 640 if (ss == NULL) 641 fatalx("bad ss at S_MAIL_QUEUE"); 642 s->s_state = S_MAIL; 643 session_respond(s, "%d Sender ok", ss->code); 644 break; 645 646 case S_RCPT_MFA: 647 if (ss == NULL) 648 fatalx("bad ss at S_RCPT_MFA"); 649 /* recipient was not accepted */ 650 if (ss->code != 250) { 651 /* We do not have a valid recipient, downgrade state */ 652 if (s->rcptcount == 0) 653 s->s_state = S_MAIL; 654 else 655 s->s_state = S_RCPT; 656 session_respond(s, "%d Recipient rejected", ss->code); 657 return; 658 } 659 660 s->s_state = S_RCPT; 661 s->rcptcount++; 662 s->s_msg.recipient = ss->u.path; 663 664 session_respond(s, "%d Recipient ok", ss->code); 665 break; 666 667 case S_DATA_QUEUE: 668 s->s_state = S_DATACONTENT; 669 session_respond(s, "354 Enter mail, end with \".\" on a line by" 670 " itself"); 671 672 fprintf(s->datafp, "Received: from %s (%s [%s])\n", 673 s->s_msg.session_helo, s->s_hostname, ss_to_text(&s->s_ss)); 674 fprintf(s->datafp, "\tby %s (OpenSMTPD) with %sSMTP id %s", 675 s->s_env->sc_hostname, s->s_flags & F_EHLO ? "E" : "", 676 s->s_msg.message_id); 677 678 if (s->s_flags & F_SECURE) { 679 fprintf(s->datafp, "\n\t(version=%s cipher=%s bits=%d)", 680 SSL_get_cipher_version(s->s_ssl), 681 SSL_get_cipher_name(s->s_ssl), 682 SSL_get_cipher_bits(s->s_ssl, NULL)); 683 } 684 if (s->rcptcount == 1) 685 fprintf(s->datafp, "\n\tfor <%s@%s>; ", 686 s->s_msg.session_rcpt.user, 687 s->s_msg.session_rcpt.domain); 688 else 689 fprintf(s->datafp, ";\n\t"); 690 691 fprintf(s->datafp, "%s\n", time_to_text(time(NULL))); 692 break; 693 694 case S_DONE: 695 session_respond(s, "250 %s Message accepted for delivery", 696 s->s_msg.message_id); 697 log_info("%s: from=<%s%s%s>, size=%ld, nrcpts=%zd, proto=%s, " 698 "relay=%s [%s]", 699 s->s_msg.message_id, 700 s->s_msg.sender.user, 701 s->s_msg.sender.user[0] == '\0' ? "" : "@", 702 s->s_msg.sender.domain, 703 s->s_datalen, 704 s->rcptcount, 705 s->s_flags & F_EHLO ? "ESMTP" : "SMTP", 706 s->s_hostname, 707 ss_to_text(&s->s_ss)); 708 709 s->s_state = S_HELO; 710 s->s_msg.message_id[0] = '\0'; 711 s->s_msg.message_uid[0] = '\0'; 712 bzero(&s->s_nresp, sizeof(s->s_nresp)); 713 break; 714 715 default: 716 fatal("session_pickup: unknown state"); 717 } 718 } 719 720 void 721 session_init(struct listener *l, struct session *s) 722 { 723 s->s_state = S_INIT; 724 725 if (l->flags & F_SMTPS) { 726 ssl_session_init(s); 727 return; 728 } 729 730 session_bufferevent_new(s); 731 session_pickup(s, NULL); 732 } 733 734 void 735 session_bufferevent_new(struct session *s) 736 { 737 if (s->s_bev != NULL) 738 fatalx("session_bufferevent_new: attempt to override existing " 739 "bufferevent"); 740 741 if (s->s_flags & F_WRITEONLY) 742 fatalx("session_bufferevent_new: corrupt session"); 743 744 s->s_bev = bufferevent_new(s->s_fd, session_read, session_write, 745 session_error, s); 746 if (s->s_bev == NULL) 747 fatal("session_bufferevent_new"); 748 749 bufferevent_settimeout(s->s_bev, SMTPD_SESSION_TIMEOUT, 750 SMTPD_SESSION_TIMEOUT); 751 } 752 753 void 754 session_read(struct bufferevent *bev, void *p) 755 { 756 struct session *s = p; 757 char *line; 758 759 for (;;) { 760 line = session_readline(s); 761 if (line == NULL) 762 return; 763 764 switch (s->s_state) { 765 case S_AUTH_INIT: 766 if (s->s_msg.status & S_MESSAGE_TEMPFAILURE) 767 goto tempfail; 768 session_rfc4954_auth_plain(s, line); 769 break; 770 771 case S_AUTH_USERNAME: 772 case S_AUTH_PASSWORD: 773 if (s->s_msg.status & S_MESSAGE_TEMPFAILURE) 774 goto tempfail; 775 session_rfc4954_auth_login(s, line); 776 break; 777 778 case S_GREETED: 779 case S_HELO: 780 case S_MAIL: 781 case S_RCPT: 782 if (s->s_msg.status & S_MESSAGE_TEMPFAILURE) 783 goto tempfail; 784 session_command(s, line); 785 break; 786 787 case S_DATACONTENT: 788 session_read_data(s, line); 789 break; 790 791 default: 792 fatalx("session_read: unexpected state"); 793 } 794 795 free(line); 796 } 797 return; 798 799 tempfail: 800 session_respond(s, "421 Service temporarily unavailable"); 801 s->s_env->stats->smtp.tempfail++; 802 s->s_flags |= F_QUIT; 803 free(line); 804 } 805 806 void 807 session_read_data(struct session *s, char *line) 808 { 809 size_t len; 810 size_t i; 811 812 if (strcmp(line, ".") == 0) { 813 s->s_datalen = ftell(s->datafp); 814 if (! safe_fclose(s->datafp)) 815 s->s_msg.status |= S_MESSAGE_TEMPFAILURE; 816 s->datafp = NULL; 817 818 if (s->s_msg.status & S_MESSAGE_PERMFAILURE) { 819 session_respond(s, "554 Transaction failed"); 820 s->s_state = S_HELO; 821 } else if (s->s_msg.status & S_MESSAGE_TEMPFAILURE) { 822 session_respond(s, "421 Temporary failure"); 823 s->s_flags |= F_QUIT; 824 s->s_env->stats->smtp.tempfail++; 825 } else { 826 session_imsg(s, PROC_QUEUE, IMSG_QUEUE_COMMIT_MESSAGE, 827 0, 0, -1, &s->s_msg, sizeof(s->s_msg)); 828 s->s_state = S_DONE; 829 } 830 831 return; 832 } 833 834 /* Don't waste resources on message if it's going to bin anyway. */ 835 if (s->s_msg.status & (S_MESSAGE_PERMFAILURE|S_MESSAGE_TEMPFAILURE)) 836 return; 837 838 /* "If the first character is a period and there are other characters 839 * on the line, the first character is deleted." [4.5.2] 840 */ 841 if (*line == '.') 842 line++; 843 844 len = strlen(line); 845 846 if (fprintf(s->datafp, "%s\n", line) != (int)len + 1) { 847 s->s_msg.status |= S_MESSAGE_TEMPFAILURE; 848 return; 849 } 850 851 if (! (s->s_flags & F_8BITMIME)) { 852 for (i = 0; i < len; ++i) 853 if (line[i] & 0x80) 854 line[i] = line[i] & 0x7f; 855 } 856 } 857 858 void 859 session_write(struct bufferevent *bev, void *p) 860 { 861 struct session *s = p; 862 863 if (s->s_flags & F_WRITEONLY) { 864 /* 865 * Finished writing to a session that is waiting for an IMSG 866 * response, therefore can't destroy session nor re-enable 867 * reading from it. 868 * 869 * If session_respond caller used F_QUIT to request session 870 * destroy after final write, then session will be destroyed 871 * in session_lookup. 872 * 873 * Reading from session will be re-enabled in session_pickup 874 * using another call to session_respond. 875 */ 876 return; 877 } else if (s->s_flags & F_QUIT) { 878 /* 879 * session_respond caller requested the session to be dropped. 880 */ 881 session_destroy(s); 882 } else if (s->s_state == S_TLS) { 883 /* 884 * Start the TLS conversation. 885 * Destroy the bufferevent as the SSL module re-creates it. 886 */ 887 bufferevent_free(s->s_bev); 888 s->s_bev = NULL; 889 ssl_session_init(s); 890 } else { 891 /* 892 * Common case of responding to client's request. 893 * Re-enable reading from session so that more commands can 894 * be processed. 895 */ 896 bufferevent_enable(s->s_bev, EV_READ); 897 } 898 } 899 900 void 901 session_error(struct bufferevent *bev, short event, void *p) 902 { 903 struct session *s = p; 904 char *ip = ss_to_text(&s->s_ss); 905 906 if (event & EVBUFFER_READ) { 907 if (event & EVBUFFER_TIMEOUT) { 908 log_warnx("client %s read timeout", ip); 909 s->s_env->stats->smtp.read_timeout++; 910 } else if (event & EVBUFFER_EOF) 911 s->s_env->stats->smtp.read_eof++; 912 else if (event & EVBUFFER_ERROR) { 913 log_warn("client %s read error", ip); 914 s->s_env->stats->smtp.read_error++; 915 } 916 917 session_destroy(s); 918 return; 919 } 920 921 if (event & EVBUFFER_WRITE) { 922 if (event & EVBUFFER_TIMEOUT) { 923 log_warnx("client %s write timeout", ip); 924 s->s_env->stats->smtp.write_timeout++; 925 } else if (event & EVBUFFER_EOF) 926 s->s_env->stats->smtp.write_eof++; 927 else if (event & EVBUFFER_ERROR) { 928 log_warn("client %s write error", ip); 929 s->s_env->stats->smtp.write_error++; 930 } 931 932 if (s->s_flags & F_WRITEONLY) 933 s->s_flags |= F_QUIT; 934 else 935 session_destroy(s); 936 return; 937 } 938 939 fatalx("session_error: unexpected error"); 940 } 941 942 void 943 session_destroy(struct session *s) 944 { 945 log_debug("session_destroy: killing client: %p", s); 946 947 if (s->s_flags & F_WRITEONLY) 948 fatalx("session_destroy: corrupt session"); 949 950 if (s->datafp != NULL) 951 fclose(s->datafp); 952 953 if (s->s_msg.message_id[0] != '\0' && s->s_state != S_DONE) 954 imsg_compose_event(s->s_env->sc_ievs[PROC_QUEUE], 955 IMSG_QUEUE_REMOVE_MESSAGE, 0, 0, -1, &s->s_msg, 956 sizeof(s->s_msg)); 957 958 ssl_session_destroy(s); 959 960 if (s->s_bev != NULL) 961 bufferevent_free(s->s_bev); 962 963 if (s->s_fd != -1 && close(s->s_fd) == -1) 964 fatal("session_destroy: close"); 965 966 switch (smtpd_process) { 967 case PROC_MTA: 968 s->s_env->stats->mta.sessions_active--; 969 break; 970 case PROC_SMTP: 971 s->s_env->stats->smtp.sessions_active--; 972 if (s->s_env->stats->smtp.sessions_active < s->s_env->sc_maxconn && 973 !(s->s_msg.flags & F_MESSAGE_ENQUEUED)) { 974 /* 975 * if our session_destroy occurs because of a configuration 976 * reload, our listener no longer exist and s->s_l is NULL. 977 */ 978 if (s->s_l != NULL) 979 event_add(&s->s_l->ev, NULL); 980 } 981 break; 982 default: 983 fatalx("session_destroy: cannot be called from this process"); 984 } 985 986 SPLAY_REMOVE(sessiontree, &s->s_env->sc_sessions, s); 987 bzero(s, sizeof(*s)); 988 free(s); 989 } 990 991 char * 992 session_readline(struct session *s) 993 { 994 char *line, *line2; 995 size_t nr; 996 997 nr = EVBUFFER_LENGTH(s->s_bev->input); 998 line = evbuffer_readline(s->s_bev->input); 999 if (line == NULL) { 1000 if (EVBUFFER_LENGTH(s->s_bev->input) > SMTP_LINE_MAX) { 1001 session_respond(s, "500 Line too long"); 1002 s->s_env->stats->smtp.linetoolong++; 1003 s->s_flags |= F_QUIT; 1004 } 1005 return NULL; 1006 } 1007 nr -= EVBUFFER_LENGTH(s->s_bev->input); 1008 1009 if (s->s_flags & F_WRITEONLY) 1010 fatalx("session_readline: corrupt session"); 1011 1012 if (nr > SMTP_LINE_MAX) { 1013 session_respond(s, "500 Line too long"); 1014 s->s_env->stats->smtp.linetoolong++; 1015 s->s_flags |= F_QUIT; 1016 return NULL; 1017 } 1018 1019 if ((s->s_state != S_DATACONTENT || strcmp(line, ".") == 0) && 1020 (line2 = evbuffer_readline(s->s_bev->input)) != NULL) { 1021 session_respond(s, "500 Pipelining unsupported"); 1022 s->s_env->stats->smtp.toofast++; 1023 s->s_flags |= F_QUIT; 1024 free(line); 1025 free(line2); 1026 1027 return NULL; 1028 } 1029 1030 return line; 1031 } 1032 1033 int 1034 session_cmp(struct session *s1, struct session *s2) 1035 { 1036 /* 1037 * do not return u_int64_t's 1038 */ 1039 if (s1->s_id < s2->s_id) 1040 return (-1); 1041 1042 if (s1->s_id > s2->s_id) 1043 return (1); 1044 1045 return (0); 1046 } 1047 1048 int 1049 session_set_path(struct path *path, char *line) 1050 { 1051 size_t len; 1052 1053 len = strlen(line); 1054 if (*line != '<' || line[len - 1] != '>') 1055 return 0; 1056 line[len - 1] = '\0'; 1057 1058 return recipient_to_path(path, line + 1); 1059 } 1060 1061 void 1062 session_respond(struct session *s, char *fmt, ...) 1063 { 1064 va_list ap; 1065 int n, delay; 1066 1067 n = EVBUFFER_LENGTH(EVBUFFER_OUTPUT(s->s_bev)); 1068 1069 va_start(ap, fmt); 1070 if (evbuffer_add_vprintf(EVBUFFER_OUTPUT(s->s_bev), fmt, ap) == -1 || 1071 evbuffer_add_printf(EVBUFFER_OUTPUT(s->s_bev), "\r\n") == -1) 1072 fatal("session_respond: evbuffer_add_vprintf failed"); 1073 va_end(ap); 1074 1075 if (smtpd_process == PROC_MTA) { 1076 bufferevent_enable(s->s_bev, EV_WRITE); 1077 return; 1078 } 1079 1080 bufferevent_disable(s->s_bev, EV_READ); 1081 1082 /* 1083 * Log failures. Might be annoying in the long term, but it is a good 1084 * development aid for now. 1085 */ 1086 switch (EVBUFFER_DATA(EVBUFFER_OUTPUT(s->s_bev))[n]) { 1087 case '5': 1088 case '4': 1089 log_debug("session error: %s: \"%.*s\"", 1090 ss_to_text(&s->s_ss), 1091 (int)EVBUFFER_LENGTH(EVBUFFER_OUTPUT(s->s_bev)) - n - 2, 1092 EVBUFFER_DATA(EVBUFFER_OUTPUT(s->s_bev))); 1093 break; 1094 } 1095 1096 /* Detect multi-line response. */ 1097 if (EVBUFFER_LENGTH(EVBUFFER_OUTPUT(s->s_bev)) - n < 4) 1098 fatalx("session_respond: invalid response length"); 1099 switch (EVBUFFER_DATA(EVBUFFER_OUTPUT(s->s_bev))[n + 3]) { 1100 case '-': 1101 return; 1102 case ' ': 1103 break; 1104 default: 1105 fatalx("session_respond: invalid response"); 1106 } 1107 1108 /* 1109 * Deal with request flooding; avoid letting response rate keep up 1110 * with incoming request rate. 1111 */ 1112 s->s_nresp[s->s_state]++; 1113 1114 if (s->s_state == S_RCPT) 1115 delay = 0; 1116 else if ((n = s->s_nresp[s->s_state] - FAST_RESPONSES) > 0) 1117 delay = MIN(1 << (n - 1), MAX_RESPONSE_DELAY); 1118 else 1119 delay = 0; 1120 1121 if (delay > 0) { 1122 struct timeval tv = { delay, 0 }; 1123 1124 s->s_env->stats->smtp.delays++; 1125 evtimer_set(&s->s_ev, session_respond_delayed, s); 1126 evtimer_add(&s->s_ev, &tv); 1127 } else 1128 bufferevent_enable(s->s_bev, EV_WRITE); 1129 } 1130 1131 void 1132 session_respond_delayed(int fd, short event, void *p) 1133 { 1134 struct session *s = p; 1135 1136 bufferevent_enable(s->s_bev, EV_WRITE); 1137 } 1138 1139 /* 1140 * Send IMSG, waiting for reply safely. 1141 */ 1142 void 1143 session_imsg(struct session *s, enum smtp_proc_type proc, enum imsg_type type, 1144 u_int32_t peerid, pid_t pid, int fd, void *data, u_int16_t datalen) 1145 { 1146 if (s->s_flags & F_WRITEONLY) 1147 fatalx("session_imsg: corrupt session"); 1148 1149 /* 1150 * Each outgoing IMSG has a response IMSG associated that must be 1151 * waited for before the session can be progressed further. 1152 * During the wait period: 1153 * 1) session must not be destroyed, 1154 * 2) session must not be read from, 1155 * 3) session may be written to. 1156 * Session flag F_WRITEONLY is needed to enforce this policy. 1157 * 1158 * F_WRITEONLY is cleared in session_lookup. 1159 * Reading is re-enabled in session_pickup. 1160 */ 1161 s->s_flags |= F_WRITEONLY; 1162 bufferevent_disable(s->s_bev, EV_READ); 1163 imsg_compose_event(s->s_env->sc_ievs[proc], type, peerid, pid, fd, data, 1164 datalen); 1165 } 1166 1167 SPLAY_GENERATE(sessiontree, session, s_nodes, session_cmp); 1168