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