1 /* $OpenBSD: smtp_session.c,v 1.63 2009/03/15 19:32:10 gilles Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> 5 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@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 <ctype.h> 30 #include <errno.h> 31 #include <event.h> 32 #include <pwd.h> 33 #include <regex.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <unistd.h> 38 39 #include <keynote.h> 40 41 #include "smtpd.h" 42 43 int session_rfc5321_helo_handler(struct session *, char *); 44 int session_rfc5321_ehlo_handler(struct session *, char *); 45 int session_rfc5321_rset_handler(struct session *, char *); 46 int session_rfc5321_noop_handler(struct session *, char *); 47 int session_rfc5321_data_handler(struct session *, char *); 48 int session_rfc5321_mail_handler(struct session *, char *); 49 int session_rfc5321_rcpt_handler(struct session *, char *); 50 int session_rfc5321_vrfy_handler(struct session *, char *); 51 int session_rfc5321_expn_handler(struct session *, char *); 52 int session_rfc5321_turn_handler(struct session *, char *); 53 int session_rfc5321_help_handler(struct session *, char *); 54 int session_rfc5321_quit_handler(struct session *, char *); 55 int session_rfc5321_none_handler(struct session *, char *); 56 57 int session_rfc1652_mail_handler(struct session *, char *); 58 59 int session_rfc3207_stls_handler(struct session *, char *); 60 61 int session_rfc4954_auth_handler(struct session *, char *); 62 int session_rfc4954_auth_plain(struct session *, char *, size_t); 63 int session_rfc4954_auth_login(struct session *, char *, size_t); 64 void session_auth_pickup(struct session *, char *, size_t); 65 66 void session_read(struct bufferevent *, void *); 67 int session_read_data(struct session *, char *, size_t); 68 void session_write(struct bufferevent *, void *); 69 void session_error(struct bufferevent *, short, void *); 70 void session_msg_submit(struct session *); 71 void session_command(struct session *, char *, char *); 72 int session_set_path(struct path *, char *); 73 void session_timeout(int, short, void *); 74 void session_cleanup(struct session *); 75 76 extern struct s_session s_smtp; 77 78 struct session_timeout { 79 enum session_state state; 80 time_t timeout; 81 }; 82 83 struct session_timeout rfc5321_timeouttab[] = { 84 { S_INIT, 300 }, 85 { S_GREETED, 300 }, 86 { S_HELO, 300 }, 87 { S_MAIL, 300 }, 88 { S_RCPT, 300 }, 89 { S_DATA, 120 }, 90 { S_DATACONTENT, 180 }, 91 { S_DONE, 600 } 92 }; 93 94 struct session_cmd { 95 char *name; 96 int (*func)(struct session *, char *); 97 }; 98 99 struct session_cmd rfc5321_cmdtab[] = { 100 { "helo", session_rfc5321_helo_handler }, 101 { "ehlo", session_rfc5321_ehlo_handler }, 102 { "rset", session_rfc5321_rset_handler }, 103 { "noop", session_rfc5321_noop_handler }, 104 { "data", session_rfc5321_data_handler }, 105 { "mail from", session_rfc5321_mail_handler }, 106 { "rcpt to", session_rfc5321_rcpt_handler }, 107 { "vrfy", session_rfc5321_vrfy_handler }, 108 { "expn", session_rfc5321_expn_handler }, 109 { "turn", session_rfc5321_turn_handler }, 110 { "help", session_rfc5321_help_handler }, 111 { "quit", session_rfc5321_quit_handler } 112 }; 113 114 struct session_cmd rfc1652_cmdtab[] = { 115 { "mail from", session_rfc1652_mail_handler }, 116 }; 117 118 struct session_cmd rfc3207_cmdtab[] = { 119 { "starttls", session_rfc3207_stls_handler } 120 }; 121 122 struct session_cmd rfc4954_cmdtab[] = { 123 { "auth", session_rfc4954_auth_handler } 124 }; 125 126 int 127 session_rfc3207_stls_handler(struct session *s, char *args) 128 { 129 if (s->s_state == S_GREETED) { 130 session_respond(s, "503 Polite people say HELO first"); 131 return 1; 132 } 133 134 if (args != NULL) { 135 session_respond(s, "501 No parameters allowed"); 136 return 1; 137 } 138 139 session_respond(s, "220 Ready to start TLS"); 140 141 s->s_state = S_TLS; 142 143 return 1; 144 } 145 146 int 147 session_rfc4954_auth_handler(struct session *s, char *args) 148 { 149 char *method; 150 char *eom; 151 152 if (s->s_state == S_GREETED) { 153 session_respond(s, "503 Polite people say HELO first"); 154 return 1; 155 } 156 157 if (args == NULL) { 158 session_respond(s, "501 No parameters given"); 159 return 1; 160 } 161 162 method = args; 163 eom = strchr(args, ' '); 164 if (eom == NULL) 165 eom = strchr(args, '\t'); 166 if (eom != NULL) 167 *eom++ = '\0'; 168 169 if (strcasecmp(method, "PLAIN") == 0) 170 return session_rfc4954_auth_plain(s, eom, eom ? strlen(eom) : 0); 171 else if (strcasecmp(method, "LOGIN") == 0) 172 return session_rfc4954_auth_login(s, eom, eom ? strlen(eom) : 0); 173 174 session_respond(s, "501 Syntax error"); 175 return 1; 176 177 } 178 179 int 180 session_rfc4954_auth_plain(struct session *s, char *arg, size_t nr) 181 { 182 if (arg == NULL) { 183 session_respond(s, "334"); 184 s->s_state = S_AUTH_INIT; 185 return 1; 186 } 187 188 s->s_auth.session_id = s->s_id; 189 if (strlcpy(s->s_auth.buffer, arg, sizeof(s->s_auth.buffer)) >= 190 sizeof(s->s_auth.buffer)) { 191 session_respond(s, "501 Syntax error"); 192 return 1; 193 } 194 195 s->s_state = S_AUTH_FINALIZE; 196 197 imsg_compose(s->s_env->sc_ibufs[PROC_PARENT], IMSG_PARENT_AUTHENTICATE, 198 0, 0, -1, &s->s_auth, sizeof(s->s_auth)); 199 s->s_flags |= F_EVLOCKED; 200 bufferevent_disable(s->s_bev, EV_READ); 201 202 return 1; 203 } 204 205 int 206 session_rfc4954_auth_login(struct session *s, char *arg, size_t nr) 207 { 208 struct session_auth_req req; 209 size_t len = 0; 210 211 switch (s->s_state) { 212 case S_HELO: 213 session_respond(s, "334 VXNlcm5hbWU6"); 214 s->s_auth.session_id = s->s_id; 215 s->s_state = S_AUTH_USERNAME; 216 return 1; 217 218 case S_AUTH_USERNAME: 219 bzero(s->s_auth.buffer, sizeof(s->s_auth.buffer)); 220 if (kn_decode_base64(arg, req.buffer, 1024) == -1 || 221 ! bsnprintf(s->s_auth.buffer + 1, sizeof(s->s_auth.buffer) - 1, "%s", req.buffer)) 222 goto err; 223 224 session_respond(s, "334 UGFzc3dvcmQ6"); 225 s->s_state = S_AUTH_PASSWORD; 226 227 return 1; 228 229 case S_AUTH_PASSWORD: { 230 len = strlen(s->s_auth.buffer + 1); 231 if (kn_decode_base64(arg, req.buffer, 1024) == -1 || 232 ! bsnprintf(s->s_auth.buffer + len + 2, sizeof(s->s_auth.buffer) - len - 2, "%s", req.buffer)) 233 goto err; 234 235 break; 236 } 237 default: 238 fatal("session_rfc4954_auth_login: unknown state"); 239 } 240 241 s->s_state = S_AUTH_FINALIZE; 242 243 req = s->s_auth; 244 len = strlen(s->s_auth.buffer + 1) + strlen(arg) + 2; 245 if (kn_encode_base64(req.buffer, len, s->s_auth.buffer, sizeof(s->s_auth.buffer)) == -1) 246 goto err; 247 248 imsg_compose(s->s_env->sc_ibufs[PROC_PARENT], IMSG_PARENT_AUTHENTICATE, 249 0, 0, -1, &s->s_auth, sizeof(s->s_auth)); 250 s->s_flags |= F_EVLOCKED; 251 bufferevent_disable(s->s_bev, EV_READ); 252 253 return 1; 254 err: 255 s->s_state = S_HELO; 256 session_respond(s, "535 Authentication failed"); 257 return 1; 258 } 259 260 int 261 session_rfc1652_mail_handler(struct session *s, char *args) 262 { 263 char *body; 264 265 if (s->s_state == S_GREETED) { 266 session_respond(s, "503 Polite people say HELO first"); 267 return 1; 268 } 269 270 body = strrchr(args, ' '); 271 if (body != NULL) { 272 *body++ = '\0'; 273 274 if (strcasecmp("body=7bit", body) == 0) { 275 s->s_flags &= ~F_8BITMIME; 276 } 277 278 else if (strcasecmp("body=8bitmime", body) != 0) { 279 session_respond(s, "503 Invalid BODY"); 280 return 1; 281 } 282 283 return session_rfc5321_mail_handler(s, args); 284 } 285 286 return 0; 287 } 288 289 int 290 session_rfc5321_helo_handler(struct session *s, char *args) 291 { 292 if (args == NULL) { 293 session_respond(s, "501 HELO requires domain address"); 294 return 1; 295 } 296 297 if (strlcpy(s->s_msg.session_helo, args, sizeof(s->s_msg.session_helo)) 298 >= sizeof(s->s_msg.session_helo)) { 299 session_respond(s, "501 Invalid domain name"); 300 return 1; 301 } 302 303 s->s_state = S_HELO; 304 s->s_flags &= F_SECURE; 305 306 session_respond(s, "250 %s Hello %s [%s], pleased to meet you", 307 s->s_env->sc_hostname, args, ss_to_text(&s->s_ss)); 308 309 return 1; 310 } 311 312 int 313 session_rfc5321_ehlo_handler(struct session *s, char *args) 314 { 315 if (args == NULL) { 316 session_respond(s, "501 EHLO requires domain address"); 317 return 1; 318 } 319 320 if (strlcpy(s->s_msg.session_helo, args, sizeof(s->s_msg.session_helo)) 321 >= sizeof(s->s_msg.session_helo)) { 322 session_respond(s, "501 Invalid domain name"); 323 return 1; 324 } 325 326 s->s_state = S_HELO; 327 s->s_flags &= F_SECURE; 328 s->s_flags |= F_EHLO; 329 s->s_flags |= F_8BITMIME; 330 331 session_respond(s, "250-%s Hello %s [%s], pleased to meet you", 332 s->s_env->sc_hostname, args, ss_to_text(&s->s_ss)); 333 session_respond(s, "250-8BITMIME"); 334 335 /* only advertise starttls if listener can support it */ 336 if (s->s_l->flags & F_STARTTLS) 337 session_respond(s, "250-STARTTLS"); 338 339 /* only advertise auth if session is secure */ 340 if ((s->s_l->flags & F_AUTH) && (s->s_flags & F_SECURE)) 341 session_respond(s, "250-AUTH PLAIN LOGIN"); 342 343 session_respond(s, "250 HELP"); 344 345 return 1; 346 } 347 348 int 349 session_rfc5321_rset_handler(struct session *s, char *args) 350 { 351 s->s_state = S_HELO; 352 session_respond(s, "250 Reset state"); 353 354 return 1; 355 } 356 357 int 358 session_rfc5321_noop_handler(struct session *s, char *args) 359 { 360 session_respond(s, "250 OK"); 361 362 return 1; 363 } 364 365 int 366 session_rfc5321_mail_handler(struct session *s, char *args) 367 { 368 char buffer[MAX_PATH_SIZE]; 369 370 if (s->s_state == S_GREETED) { 371 session_respond(s, "503 Polite people say HELO first"); 372 return 1; 373 } 374 375 if (strlcpy(buffer, args, sizeof(buffer)) >= sizeof(buffer)) { 376 session_respond(s, "553 Sender address syntax error"); 377 return 1; 378 } 379 380 if (! session_set_path(&s->s_msg.sender, buffer)) { 381 /* No need to even transmit to MFA, path is invalid */ 382 session_respond(s, "553 Sender address syntax error"); 383 return 1; 384 } 385 386 session_cleanup(s); 387 s->rcptcount = 0; 388 s->s_state = S_MAILREQUEST; 389 s->s_msg.id = s->s_id; 390 s->s_msg.session_id = s->s_id; 391 s->s_msg.session_ss = s->s_ss; 392 393 log_debug("session_mail_handler: sending notification to mfa"); 394 395 imsg_compose(s->s_env->sc_ibufs[PROC_MFA], IMSG_MFA_MAIL, 396 0, 0, -1, &s->s_msg, sizeof(s->s_msg)); 397 s->s_flags |= F_EVLOCKED; 398 bufferevent_disable(s->s_bev, EV_READ); 399 return 1; 400 } 401 402 int 403 session_rfc5321_rcpt_handler(struct session *s, char *args) 404 { 405 char buffer[MAX_PATH_SIZE]; 406 struct message_recipient mr; 407 408 if (s->s_state == S_GREETED) { 409 session_respond(s, "503 Polite people say HELO first"); 410 return 1; 411 } 412 413 if (s->s_state == S_HELO) { 414 session_respond(s, "503 Need MAIL before RCPT"); 415 return 1; 416 } 417 418 bzero(&mr, sizeof(mr)); 419 420 if (strlcpy(buffer, args, sizeof(buffer)) >= sizeof(buffer)) { 421 session_respond(s, "553 Recipient address syntax error"); 422 return 1; 423 } 424 425 if (! session_set_path(&mr.path, buffer)) { 426 /* No need to even transmit to MFA, path is invalid */ 427 session_respond(s, "553 Recipient address syntax error"); 428 return 1; 429 } 430 431 s->s_msg.session_rcpt = mr.path; 432 433 mr.id = s->s_msg.id; 434 s->s_state = S_RCPTREQUEST; 435 mr.ss = s->s_ss; 436 mr.msg = s->s_msg; 437 438 439 if (s->s_flags & F_AUTHENTICATED) { 440 s->s_msg.flags |= F_MESSAGE_AUTHENTICATED; 441 mr.flags |= F_MESSAGE_AUTHENTICATED; 442 } 443 444 imsg_compose(s->s_env->sc_ibufs[PROC_MFA], IMSG_MFA_RCPT, 445 0, 0, -1, &mr, sizeof(mr)); 446 s->s_flags |= F_EVLOCKED; 447 bufferevent_disable(s->s_bev, EV_READ); 448 return 1; 449 } 450 451 int 452 session_rfc5321_quit_handler(struct session *s, char *args) 453 { 454 session_respond(s, "221 %s Closing connection", s->s_env->sc_hostname); 455 456 s->s_flags |= F_QUIT; 457 458 return 1; 459 } 460 461 int 462 session_rfc5321_data_handler(struct session *s, char *args) 463 { 464 if (s->s_state == S_GREETED) { 465 session_respond(s, "503 Polite people say HELO first"); 466 return 1; 467 } 468 469 if (s->s_state == S_HELO) { 470 session_respond(s, "503 Need MAIL before DATA"); 471 return 1; 472 } 473 474 if (s->s_state == S_MAIL) { 475 session_respond(s, "503 Need RCPT before DATA"); 476 return 1; 477 } 478 479 s->s_state = S_DATAREQUEST; 480 session_pickup(s, NULL); 481 return 1; 482 } 483 484 int 485 session_rfc5321_vrfy_handler(struct session *s, char *args) 486 { 487 session_respond(s, "252 Cannot VRFY; try RCPT to attempt delivery"); 488 489 return 1; 490 } 491 492 int 493 session_rfc5321_expn_handler(struct session *s, char *args) 494 { 495 session_respond(s, "502 Sorry, we do not allow this operation"); 496 497 return 1; 498 } 499 500 int 501 session_rfc5321_turn_handler(struct session *s, char *args) 502 { 503 session_respond(s, "502 Sorry, we do not allow this operation"); 504 505 return 1; 506 } 507 508 int 509 session_rfc5321_help_handler(struct session *s, char *args) 510 { 511 session_respond(s, "214- This is OpenSMTPD"); 512 session_respond(s, "214- To report bugs in the implementation, please " 513 "contact bugs@openbsd.org"); 514 session_respond(s, "214- with full details"); 515 session_respond(s, "214 End of HELP info"); 516 517 return 1; 518 } 519 520 void 521 session_command(struct session *s, char *cmd, char *args) 522 { 523 int i; 524 525 if (!(s->s_flags & F_EHLO)) 526 goto rfc5321; 527 528 /* RFC 1652 - 8BITMIME */ 529 for (i = 0; i < (int)(sizeof(rfc1652_cmdtab) / sizeof(struct session_cmd)); ++i) 530 if (strcasecmp(rfc1652_cmdtab[i].name, cmd) == 0) 531 break; 532 if (i < (int)(sizeof(rfc1652_cmdtab) / sizeof(struct session_cmd))) { 533 if (rfc1652_cmdtab[i].func(s, args)) 534 return; 535 } 536 537 /* RFC 3207 - STARTTLS */ 538 for (i = 0; i < (int)(sizeof(rfc3207_cmdtab) / sizeof(struct session_cmd)); ++i) 539 if (strcasecmp(rfc3207_cmdtab[i].name, cmd) == 0) 540 break; 541 if (i < (int)(sizeof(rfc3207_cmdtab) / sizeof(struct session_cmd))) { 542 if (rfc3207_cmdtab[i].func(s, args)) 543 return; 544 } 545 546 /* RFC 4954 - AUTH */ 547 if ((s->s_l->flags & F_AUTH) && (s->s_flags & F_SECURE)) { 548 for (i = 0; i < (int)(sizeof(rfc4954_cmdtab) / sizeof(struct session_cmd)); ++i) 549 if (strcasecmp(rfc4954_cmdtab[i].name, cmd) == 0) 550 break; 551 if (i < (int)(sizeof(rfc4954_cmdtab) / sizeof(struct session_cmd))) { 552 if (rfc4954_cmdtab[i].func(s, args)) 553 return; 554 } 555 } 556 557 rfc5321: 558 /* RFC 5321 - SMTP */ 559 for (i = 0; i < (int)(sizeof(rfc5321_cmdtab) / sizeof(struct session_cmd)); ++i) 560 if (strcasecmp(rfc5321_cmdtab[i].name, cmd) == 0) 561 break; 562 if (i < (int)(sizeof(rfc5321_cmdtab) / sizeof(struct session_cmd))) { 563 if (rfc5321_cmdtab[i].func(s, args)) 564 return; 565 } 566 567 session_respond(s, "500 Command unrecognized"); 568 } 569 570 void 571 session_auth_pickup(struct session *s, char *arg, size_t nr) 572 { 573 if (s == NULL) 574 fatal("session_pickup: desynchronized"); 575 576 bufferevent_enable(s->s_bev, EV_READ); 577 578 switch (s->s_state) { 579 case S_AUTH_INIT: 580 session_rfc4954_auth_plain(s, arg, nr); 581 break; 582 case S_AUTH_USERNAME: 583 session_rfc4954_auth_login(s, arg, nr); 584 break; 585 case S_AUTH_PASSWORD: 586 session_rfc4954_auth_login(s, arg, nr); 587 break; 588 case S_AUTH_FINALIZE: 589 if (s->s_flags & F_AUTHENTICATED) 590 session_respond(s, "235 Authentication succeeded"); 591 else 592 session_respond(s, "535 Authentication failed"); 593 s->s_state = S_HELO; 594 break; 595 default: 596 fatal("session_auth_pickup: unknown state"); 597 } 598 return; 599 } 600 601 void 602 session_pickup(struct session *s, struct submit_status *ss) 603 { 604 if (s == NULL) 605 fatal("session_pickup: desynchronized"); 606 607 bufferevent_enable(s->s_bev, EV_READ); 608 609 if ((ss != NULL && ss->code == 421) || 610 (s->s_msg.status & S_MESSAGE_TEMPFAILURE)) 611 goto tempfail; 612 613 switch (s->s_state) { 614 case S_INIT: 615 s->s_state = S_GREETED; 616 log_debug("session_pickup: greeting client"); 617 session_respond(s, SMTPD_BANNER, s->s_env->sc_hostname); 618 break; 619 620 case S_GREETED: 621 case S_HELO: 622 break; 623 624 case S_TLS: 625 s->s_flags |= F_EVLOCKED; 626 bufferevent_disable(s->s_bev, EV_READ|EV_WRITE); 627 s->s_state = S_GREETED; 628 ssl_session_init(s); 629 break; 630 631 case S_MAILREQUEST: 632 if (ss == NULL) 633 fatalx("bad ss at S_MAILREQUEST"); 634 /* sender was not accepted, downgrade state */ 635 if (ss->code != 250) { 636 s->s_state = S_HELO; 637 session_respond(s, "%d Sender rejected", ss->code); 638 return; 639 } 640 641 s->s_state = S_MAIL; 642 s->s_msg.sender = ss->u.path; 643 644 imsg_compose(s->s_env->sc_ibufs[PROC_QUEUE], 645 IMSG_QUEUE_CREATE_MESSAGE, 0, 0, -1, &s->s_msg, 646 sizeof(s->s_msg)); 647 s->s_flags |= F_EVLOCKED; 648 bufferevent_disable(s->s_bev, EV_READ); 649 break; 650 651 case S_MAIL: 652 if (ss == NULL) 653 fatalx("bad ss at S_MAIL"); 654 session_respond(s, "%d Sender ok", ss->code); 655 break; 656 657 case S_RCPTREQUEST: 658 if (ss == NULL) 659 fatalx("bad ss at S_RCPTREQUEST"); 660 /* recipient was not accepted */ 661 if (ss->code != 250) { 662 /* We do not have a valid recipient, downgrade state */ 663 if (s->rcptcount == 0) 664 s->s_state = S_MAIL; 665 else 666 s->s_state = S_RCPT; 667 session_respond(s, "%d Recipient rejected", ss->code); 668 return; 669 } 670 671 s->s_state = S_RCPT; 672 s->rcptcount++; 673 s->s_msg.recipient = ss->u.path; 674 675 case S_RCPT: 676 if (ss == NULL) 677 fatalx("bad ss at S_RCPT"); 678 session_respond(s, "%d Recipient ok", ss->code); 679 break; 680 681 case S_DATAREQUEST: 682 s->s_state = S_DATA; 683 imsg_compose(s->s_env->sc_ibufs[PROC_QUEUE], 684 IMSG_QUEUE_MESSAGE_FILE, 0, 0, -1, &s->s_msg, 685 sizeof(s->s_msg)); 686 s->s_flags |= F_EVLOCKED; 687 bufferevent_disable(s->s_bev, EV_READ); 688 break; 689 690 case S_DATA: 691 if (ss == NULL) 692 fatalx("bad ss at S_DATA"); 693 if (s->datafp == NULL) 694 goto tempfail; 695 696 s->s_state = S_DATACONTENT; 697 session_respond(s, "354 Enter mail, end with \".\" on a line by" 698 " itself"); 699 break; 700 701 case S_DONE: 702 s->s_state = S_HELO; 703 session_respond(s, "250 %s Message accepted for delivery", 704 s->s_msg.message_id); 705 log_info("%s: from=<%s@%s>, nrcpts=%zd, proto=%s, relay=%s [%s]", 706 s->s_msg.message_id, 707 s->s_msg.sender.user, 708 s->s_msg.sender.domain, 709 s->rcptcount, 710 s->s_flags & F_EHLO ? "ESMTP" : "SMTP", 711 s->s_hostname, 712 ss_to_text(&s->s_ss)); 713 714 s->s_msg.message_id[0] = '\0'; 715 s->s_msg.message_uid[0] = '\0'; 716 break; 717 718 default: 719 fatal("session_pickup: unknown state"); 720 break; 721 } 722 723 return; 724 725 tempfail: 726 s->s_flags |= F_QUIT; 727 session_respond(s, "421 Service temporarily unavailable"); 728 return; 729 } 730 731 void 732 session_init(struct listener *l, struct session *s) 733 { 734 s->s_state = S_INIT; 735 736 if ((s->s_bev = bufferevent_new(s->s_fd, session_read, session_write, 737 session_error, s)) == NULL) 738 fatalx("session_init: bufferevent_new failed"); 739 740 if (l->flags & F_SSMTP) { 741 log_debug("session_init: initializing ssl"); 742 s->s_flags |= F_EVLOCKED; 743 bufferevent_disable(s->s_bev, EV_READ|EV_WRITE); 744 ssl_session_init(s); 745 return; 746 } 747 748 session_pickup(s, NULL); 749 } 750 751 void 752 session_read(struct bufferevent *bev, void *p) 753 { 754 struct session *s = p; 755 char *line; 756 char *ep; 757 char *args; 758 size_t nr; 759 760 read: 761 s->s_tm = time(NULL); 762 nr = EVBUFFER_LENGTH(bev->input); 763 line = evbuffer_readline(bev->input); 764 if (line == NULL) { 765 if (EVBUFFER_LENGTH(bev->input) > SMTP_ANYLINE_MAX) { 766 session_respond(s, "500 Line too long"); 767 s->s_flags |= F_QUIT; 768 } 769 return; 770 } 771 nr -= EVBUFFER_LENGTH(bev->input); 772 773 if (s->s_state == S_DATACONTENT) { 774 if (session_read_data(s, line, nr)) { 775 free(line); 776 return; 777 } 778 free(line); 779 goto read; 780 } 781 782 if (IS_AUTH(s->s_state)) { 783 session_auth_pickup(s, line, nr); 784 free(line); 785 return; 786 } 787 788 if (nr > SMTP_CMDLINE_MAX) { 789 session_respond(s, "500 Line too long"); 790 return; 791 } 792 793 if ((ep = strchr(line, ':')) == NULL) 794 ep = strchr(line, ' '); 795 if (ep != NULL) { 796 *ep = '\0'; 797 args = ++ep; 798 while (isspace((int)*args)) 799 args++; 800 } else 801 args = NULL; 802 log_debug("command: %s\targs: %s", line, args); 803 session_command(s, line, args); 804 free(line); 805 return; 806 } 807 808 int 809 session_read_data(struct session *s, char *line, size_t nread) 810 { 811 size_t len; 812 size_t i; 813 814 if (strcmp(line, ".") == 0) { 815 if (! safe_fclose(s->datafp)) 816 s->s_msg.status |= S_MESSAGE_TEMPFAILURE; 817 s->datafp = NULL; 818 819 if (s->s_msg.status & S_MESSAGE_PERMFAILURE) { 820 session_respond(s, "554 Transaction failed"); 821 s->s_state = S_HELO; 822 } else if (s->s_msg.status & S_MESSAGE_TEMPFAILURE) { 823 session_respond(s, "421 Temporary failure"); 824 s->s_state = S_HELO; 825 } else { 826 session_msg_submit(s); 827 s->s_state = S_DONE; 828 } 829 830 return 1; 831 } 832 833 /* Don't waste resources on message if it's going to bin anyway. */ 834 if (s->s_msg.status & (S_MESSAGE_PERMFAILURE|S_MESSAGE_TEMPFAILURE)) 835 return 0; 836 837 if (nread > SMTP_TEXTLINE_MAX) { 838 s->s_msg.status |= S_MESSAGE_PERMFAILURE; 839 return 0; 840 } 841 842 /* "If the first character is a period and there are other characters 843 * on the line, the first character is deleted." [4.5.2] 844 */ 845 if (*line == '.') 846 line++; 847 848 len = strlen(line); 849 850 if (fwrite(line, len, 1, s->datafp) != 1 || 851 fwrite("\n", 1, 1, s->datafp) != 1) { 852 s->s_msg.status |= S_MESSAGE_TEMPFAILURE; 853 return 0; 854 } 855 856 if (! (s->s_flags & F_8BITMIME)) { 857 for (i = 0; i < len; ++i) 858 if (line[i] & 0x80) 859 break; 860 if (i != len) { 861 s->s_msg.status |= S_MESSAGE_PERMFAILURE; 862 return 0; 863 } 864 } 865 866 return 0; 867 } 868 869 void 870 session_write(struct bufferevent *bev, void *p) 871 { 872 struct session *s = p; 873 874 if (!(s->s_flags & F_QUIT)) { 875 876 if (s->s_state == S_TLS) 877 session_pickup(s, NULL); 878 879 return; 880 } 881 882 session_destroy(s); 883 } 884 885 void 886 session_destroy(struct session *s) 887 { 888 session_cleanup(s); 889 890 log_debug("session_destroy: killing client: %p", s); 891 close(s->s_fd); 892 893 s_smtp.sessions_active--; 894 if (s_smtp.sessions_active < s->s_env->sc_maxconn) 895 event_add(&s->s_l->ev, NULL); 896 897 if (s->s_bev != NULL) { 898 bufferevent_free(s->s_bev); 899 } 900 ssl_session_destroy(s); 901 902 SPLAY_REMOVE(sessiontree, &s->s_env->sc_sessions, s); 903 bzero(s, sizeof(*s)); 904 free(s); 905 } 906 907 void 908 session_cleanup(struct session *s) 909 { 910 if (s->datafp != NULL) { 911 fclose(s->datafp); 912 s->datafp = NULL; 913 } 914 915 if (s->s_msg.message_id[0] != '\0') { 916 imsg_compose(s->s_env->sc_ibufs[PROC_QUEUE], 917 IMSG_QUEUE_REMOVE_MESSAGE, 0, 0, -1, &s->s_msg, 918 sizeof(s->s_msg)); 919 s->s_msg.message_id[0] = '\0'; 920 s->s_msg.message_uid[0] = '\0'; 921 s->s_flags |= F_EVLOCKED; 922 bufferevent_disable(s->s_bev, EV_READ); 923 } 924 } 925 926 void 927 session_error(struct bufferevent *bev, short event, void *p) 928 { 929 struct session *s = p; 930 931 /* If events are locked, do not destroy session 932 * but set F_QUIT flag so that we destroy it as 933 * soon as the event lock is removed. 934 */ 935 s_smtp.aborted++; 936 if (s->s_flags & F_EVLOCKED) 937 s->s_flags |= F_QUIT; 938 else 939 session_destroy(s); 940 } 941 942 void 943 session_msg_submit(struct session *s) 944 { 945 imsg_compose(s->s_env->sc_ibufs[PROC_QUEUE], 946 IMSG_QUEUE_COMMIT_MESSAGE, 0, 0, -1, &s->s_msg, 947 sizeof(s->s_msg)); 948 s->s_flags |= F_EVLOCKED; 949 bufferevent_disable(s->s_bev, EV_READ); 950 s->s_state = S_DONE; 951 } 952 953 int 954 session_cmp(struct session *s1, struct session *s2) 955 { 956 /* 957 * do not return u_int64_t's 958 */ 959 if (s1->s_id < s2->s_id) 960 return (-1); 961 962 if (s1->s_id > s2->s_id) 963 return (1); 964 965 return (0); 966 } 967 968 int 969 session_set_path(struct path *path, char *line) 970 { 971 size_t len; 972 973 len = strlen(line); 974 if (*line != '<' || line[len - 1] != '>') 975 return 0; 976 line[len - 1] = '\0'; 977 978 return recipient_to_path(path, line + 1); 979 } 980 981 void 982 session_timeout(int fd, short event, void *p) 983 { 984 struct smtpd *env = p; 985 struct session *sessionp; 986 struct session *rmsession; 987 struct timeval tv; 988 time_t tm; 989 u_int8_t i; 990 991 tm = time(NULL); 992 rmsession = NULL; 993 SPLAY_FOREACH(sessionp, sessiontree, &env->sc_sessions) { 994 995 if (rmsession != NULL) { 996 session_destroy(rmsession); 997 rmsession = NULL; 998 } 999 1000 for (i = 0; i < sizeof (rfc5321_timeouttab) / 1001 sizeof(struct session_timeout); ++i) 1002 if (rfc5321_timeouttab[i].state == sessionp->s_state) 1003 break; 1004 1005 if (i == sizeof (rfc5321_timeouttab) / sizeof (struct session_timeout)) { 1006 if (tm - SMTPD_SESSION_TIMEOUT < sessionp->s_tm) 1007 continue; 1008 } 1009 else if (tm - rfc5321_timeouttab[i].timeout < sessionp->s_tm) { 1010 continue; 1011 } 1012 1013 rmsession = sessionp; 1014 } 1015 1016 if (rmsession != NULL) 1017 session_destroy(rmsession); 1018 1019 tv.tv_sec = 1; 1020 tv.tv_usec = 0; 1021 evtimer_add(&env->sc_ev, &tv); 1022 } 1023 1024 void 1025 session_respond(struct session *s, char *fmt, ...) 1026 { 1027 va_list ap; 1028 1029 va_start(ap, fmt); 1030 if (evbuffer_add_vprintf(EVBUFFER_OUTPUT(s->s_bev), fmt, ap) == -1 || 1031 evbuffer_add_printf(EVBUFFER_OUTPUT(s->s_bev), "\r\n") == -1) 1032 fatal("session_respond: evbuffer_add_vprintf failed"); 1033 va_end(ap); 1034 1035 bufferevent_enable(s->s_bev, EV_WRITE); 1036 } 1037 1038 SPLAY_GENERATE(sessiontree, session, s_nodes, session_cmp); 1039