1 /* $OpenBSD: smtp_session.c,v 1.432 2021/07/01 07:42:16 eric Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org> 5 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> 6 * Copyright (c) 2008-2009 Jacek Masiulaniec <jacekm@dobremiasto.net> 7 * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include <ctype.h> 23 #include <errno.h> 24 #include <inttypes.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <tls.h> 28 #include <unistd.h> 29 #include <vis.h> 30 31 #include "smtpd.h" 32 #include "log.h" 33 #include "rfc5322.h" 34 35 #define SMTP_LINE_MAX 65535 36 #define DATA_HIWAT 65535 37 #define APPEND_DOMAIN_BUFFER_SIZE SMTP_LINE_MAX 38 39 enum smtp_state { 40 STATE_NEW = 0, 41 STATE_CONNECTED, 42 STATE_TLS, 43 STATE_HELO, 44 STATE_AUTH_INIT, 45 STATE_AUTH_USERNAME, 46 STATE_AUTH_PASSWORD, 47 STATE_AUTH_FINALIZE, 48 STATE_BODY, 49 STATE_QUIT, 50 }; 51 52 enum session_flags { 53 SF_EHLO = 0x0001, 54 SF_8BITMIME = 0x0002, 55 SF_SECURE = 0x0004, 56 SF_AUTHENTICATED = 0x0008, 57 SF_BOUNCE = 0x0010, 58 SF_VERIFIED = 0x0020, 59 SF_BADINPUT = 0x0080, 60 }; 61 62 enum { 63 TX_OK = 0, 64 TX_ERROR_ENVELOPE, 65 TX_ERROR_SIZE, 66 TX_ERROR_IO, 67 TX_ERROR_LOOP, 68 TX_ERROR_MALFORMED, 69 TX_ERROR_RESOURCES, 70 TX_ERROR_INTERNAL, 71 }; 72 73 enum smtp_command { 74 CMD_HELO = 0, 75 CMD_EHLO, 76 CMD_STARTTLS, 77 CMD_AUTH, 78 CMD_MAIL_FROM, 79 CMD_RCPT_TO, 80 CMD_DATA, 81 CMD_RSET, 82 CMD_QUIT, 83 CMD_HELP, 84 CMD_WIZ, 85 CMD_NOOP, 86 CMD_COMMIT, 87 }; 88 89 struct smtp_rcpt { 90 TAILQ_ENTRY(smtp_rcpt) entry; 91 uint64_t evpid; 92 struct mailaddr maddr; 93 size_t destcount; 94 }; 95 96 struct smtp_tx { 97 struct smtp_session *session; 98 uint32_t msgid; 99 100 struct envelope evp; 101 size_t rcptcount; 102 size_t destcount; 103 TAILQ_HEAD(, smtp_rcpt) rcpts; 104 105 time_t time; 106 int error; 107 size_t datain; 108 size_t odatalen; 109 FILE *ofile; 110 struct io *filter; 111 struct rfc5322_parser *parser; 112 int rcvcount; 113 int has_date; 114 int has_message_id; 115 116 uint8_t junk; 117 }; 118 119 struct smtp_session { 120 uint64_t id; 121 struct io *io; 122 struct listener *listener; 123 void *ssl_ctx; 124 struct sockaddr_storage ss; 125 char rdns[HOST_NAME_MAX+1]; 126 char smtpname[HOST_NAME_MAX+1]; 127 int fcrdns; 128 129 int flags; 130 enum smtp_state state; 131 132 uint8_t banner_sent; 133 char helo[LINE_MAX]; 134 char cmd[LINE_MAX]; 135 char username[SMTPD_MAXMAILADDRSIZE]; 136 137 size_t mailcount; 138 struct event pause; 139 140 struct smtp_tx *tx; 141 142 enum smtp_command last_cmd; 143 enum filter_phase filter_phase; 144 const char *filter_param; 145 146 uint8_t junk; 147 }; 148 149 #define ADVERTISE_TLS(s) \ 150 ((s)->listener->flags & F_STARTTLS && !((s)->flags & SF_SECURE)) 151 152 #define ADVERTISE_AUTH(s) \ 153 ((s)->listener->flags & F_AUTH && (s)->flags & SF_SECURE && \ 154 !((s)->flags & SF_AUTHENTICATED)) 155 156 #define ADVERTISE_EXT_DSN(s) \ 157 ((s)->listener->flags & F_EXT_DSN) 158 159 #define SESSION_FILTERED(s) \ 160 ((s)->listener->flags & F_FILTERED) 161 162 #define SESSION_DATA_FILTERED(s) \ 163 ((s)->listener->flags & F_FILTERED) 164 165 166 static int smtp_mailaddr(struct mailaddr *, char *, int, char **, const char *); 167 static void smtp_session_init(void); 168 static void smtp_lookup_servername(struct smtp_session *); 169 static void smtp_getnameinfo_cb(void *, int, const char *, const char *); 170 static void smtp_getaddrinfo_cb(void *, int, struct addrinfo *); 171 static void smtp_connected(struct smtp_session *); 172 static void smtp_send_banner(struct smtp_session *); 173 static void smtp_tls_init(struct smtp_session *); 174 static void smtp_tls_started(struct smtp_session *); 175 static void smtp_io(struct io *, int, void *); 176 static void smtp_enter_state(struct smtp_session *, int); 177 static void smtp_reply(struct smtp_session *, char *, ...); 178 static void smtp_command(struct smtp_session *, char *); 179 static void smtp_rfc4954_auth_plain(struct smtp_session *, char *); 180 static void smtp_rfc4954_auth_login(struct smtp_session *, char *); 181 static void smtp_free(struct smtp_session *, const char *); 182 static const char *smtp_strstate(int); 183 static void smtp_auth_failure_pause(struct smtp_session *); 184 static void smtp_auth_failure_resume(int, short, void *); 185 186 static int smtp_tx(struct smtp_session *); 187 static void smtp_tx_free(struct smtp_tx *); 188 static void smtp_tx_create_message(struct smtp_tx *); 189 static void smtp_tx_mail_from(struct smtp_tx *, const char *); 190 static void smtp_tx_rcpt_to(struct smtp_tx *, const char *); 191 static void smtp_tx_open_message(struct smtp_tx *); 192 static void smtp_tx_commit(struct smtp_tx *); 193 static void smtp_tx_rollback(struct smtp_tx *); 194 static int smtp_tx_dataline(struct smtp_tx *, const char *); 195 static int smtp_tx_filtered_dataline(struct smtp_tx *, const char *); 196 static void smtp_tx_eom(struct smtp_tx *); 197 static void smtp_filter_fd(struct smtp_tx *, int); 198 static int smtp_message_fd(struct smtp_tx *, int); 199 static void smtp_message_begin(struct smtp_tx *); 200 static void smtp_message_end(struct smtp_tx *); 201 static int smtp_filter_printf(struct smtp_tx *, const char *, ...) 202 __attribute__((__format__ (printf, 2, 3))); 203 static int smtp_message_printf(struct smtp_tx *, const char *, ...) 204 __attribute__((__format__ (printf, 2, 3))); 205 206 static int smtp_check_rset(struct smtp_session *, const char *); 207 static int smtp_check_helo(struct smtp_session *, const char *); 208 static int smtp_check_ehlo(struct smtp_session *, const char *); 209 static int smtp_check_auth(struct smtp_session *s, const char *); 210 static int smtp_check_starttls(struct smtp_session *, const char *); 211 static int smtp_check_mail_from(struct smtp_session *, const char *); 212 static int smtp_check_rcpt_to(struct smtp_session *, const char *); 213 static int smtp_check_data(struct smtp_session *, const char *); 214 static int smtp_check_noparam(struct smtp_session *, const char *); 215 216 static void smtp_filter_phase(enum filter_phase, struct smtp_session *, const char *); 217 218 static void smtp_proceed_connected(struct smtp_session *); 219 static void smtp_proceed_rset(struct smtp_session *, const char *); 220 static void smtp_proceed_helo(struct smtp_session *, const char *); 221 static void smtp_proceed_ehlo(struct smtp_session *, const char *); 222 static void smtp_proceed_auth(struct smtp_session *, const char *); 223 static void smtp_proceed_starttls(struct smtp_session *, const char *); 224 static void smtp_proceed_mail_from(struct smtp_session *, const char *); 225 static void smtp_proceed_rcpt_to(struct smtp_session *, const char *); 226 static void smtp_proceed_data(struct smtp_session *, const char *); 227 static void smtp_proceed_noop(struct smtp_session *, const char *); 228 static void smtp_proceed_help(struct smtp_session *, const char *); 229 static void smtp_proceed_wiz(struct smtp_session *, const char *); 230 static void smtp_proceed_quit(struct smtp_session *, const char *); 231 static void smtp_proceed_commit(struct smtp_session *, const char *); 232 static void smtp_proceed_rollback(struct smtp_session *, const char *); 233 234 static void smtp_filter_begin(struct smtp_session *); 235 static void smtp_filter_end(struct smtp_session *); 236 static void smtp_filter_data_begin(struct smtp_session *); 237 static void smtp_filter_data_end(struct smtp_session *); 238 239 static void smtp_report_link_connect(struct smtp_session *, const char *, int, 240 const struct sockaddr_storage *, 241 const struct sockaddr_storage *); 242 static void smtp_report_link_greeting(struct smtp_session *, const char *); 243 static void smtp_report_link_identify(struct smtp_session *, const char *, const char *); 244 static void smtp_report_link_tls(struct smtp_session *, const char *); 245 static void smtp_report_link_disconnect(struct smtp_session *); 246 static void smtp_report_link_auth(struct smtp_session *, const char *, const char *); 247 static void smtp_report_tx_reset(struct smtp_session *, uint32_t); 248 static void smtp_report_tx_begin(struct smtp_session *, uint32_t); 249 static void smtp_report_tx_mail(struct smtp_session *, uint32_t, const char *, int); 250 static void smtp_report_tx_rcpt(struct smtp_session *, uint32_t, const char *, int); 251 static void smtp_report_tx_envelope(struct smtp_session *, uint32_t, uint64_t); 252 static void smtp_report_tx_data(struct smtp_session *, uint32_t, int); 253 static void smtp_report_tx_commit(struct smtp_session *, uint32_t, size_t); 254 static void smtp_report_tx_rollback(struct smtp_session *, uint32_t); 255 static void smtp_report_protocol_client(struct smtp_session *, const char *); 256 static void smtp_report_protocol_server(struct smtp_session *, const char *); 257 static void smtp_report_filter_response(struct smtp_session *, int, int, const char *); 258 static void smtp_report_timeout(struct smtp_session *); 259 260 261 static struct { 262 int code; 263 enum filter_phase filter_phase; 264 const char *cmd; 265 266 int (*check)(struct smtp_session *, const char *); 267 void (*proceed)(struct smtp_session *, const char *); 268 } commands[] = { 269 { CMD_HELO, FILTER_HELO, "HELO", smtp_check_helo, smtp_proceed_helo }, 270 { CMD_EHLO, FILTER_EHLO, "EHLO", smtp_check_ehlo, smtp_proceed_ehlo }, 271 { CMD_STARTTLS, FILTER_STARTTLS, "STARTTLS", smtp_check_starttls, smtp_proceed_starttls }, 272 { CMD_AUTH, FILTER_AUTH, "AUTH", smtp_check_auth, smtp_proceed_auth }, 273 { CMD_MAIL_FROM, FILTER_MAIL_FROM, "MAIL FROM", smtp_check_mail_from, smtp_proceed_mail_from }, 274 { CMD_RCPT_TO, FILTER_RCPT_TO, "RCPT TO", smtp_check_rcpt_to, smtp_proceed_rcpt_to }, 275 { CMD_DATA, FILTER_DATA, "DATA", smtp_check_data, smtp_proceed_data }, 276 { CMD_RSET, FILTER_RSET, "RSET", smtp_check_rset, smtp_proceed_rset }, 277 { CMD_QUIT, FILTER_QUIT, "QUIT", smtp_check_noparam, smtp_proceed_quit }, 278 { CMD_NOOP, FILTER_NOOP, "NOOP", smtp_check_noparam, smtp_proceed_noop }, 279 { CMD_HELP, FILTER_HELP, "HELP", smtp_check_noparam, smtp_proceed_help }, 280 { CMD_WIZ, FILTER_WIZ, "WIZ", smtp_check_noparam, smtp_proceed_wiz }, 281 { CMD_COMMIT, FILTER_COMMIT, ".", smtp_check_noparam, smtp_proceed_commit }, 282 { -1, 0, NULL, NULL }, 283 }; 284 285 static struct tree wait_lka_helo; 286 static struct tree wait_lka_mail; 287 static struct tree wait_lka_rcpt; 288 static struct tree wait_parent_auth; 289 static struct tree wait_queue_msg; 290 static struct tree wait_queue_fd; 291 static struct tree wait_queue_commit; 292 static struct tree wait_ssl_init; 293 static struct tree wait_ssl_verify; 294 static struct tree wait_filters; 295 static struct tree wait_filter_fd; 296 297 static void 298 header_append_domain_buffer(char *buffer, char *domain, size_t len) 299 { 300 size_t i; 301 int escape, quote, comment, bracket; 302 int has_domain, has_bracket, has_group; 303 int pos_bracket, pos_component, pos_insert; 304 char copy[APPEND_DOMAIN_BUFFER_SIZE]; 305 306 escape = quote = comment = bracket = 0; 307 has_domain = has_bracket = has_group = 0; 308 pos_bracket = pos_insert = pos_component = 0; 309 for (i = 0; buffer[i]; ++i) { 310 if (buffer[i] == '(' && !escape && !quote) 311 comment++; 312 if (buffer[i] == '"' && !escape && !comment) 313 quote = !quote; 314 if (buffer[i] == ')' && !escape && !quote && comment) 315 comment--; 316 if (buffer[i] == '\\' && !escape && !comment && !quote) 317 escape = 1; 318 else 319 escape = 0; 320 if (buffer[i] == '<' && !escape && !comment && !quote && !bracket) { 321 bracket++; 322 has_bracket = 1; 323 } 324 if (buffer[i] == '>' && !escape && !comment && !quote && bracket) { 325 bracket--; 326 pos_bracket = i; 327 } 328 if (buffer[i] == '@' && !escape && !comment && !quote) 329 has_domain = 1; 330 if (buffer[i] == ':' && !escape && !comment && !quote) 331 has_group = 1; 332 333 /* update insert point if not in comment and not on a whitespace */ 334 if (!comment && buffer[i] != ')' && !isspace((unsigned char)buffer[i])) 335 pos_component = i; 336 } 337 338 /* parse error, do not attempt to modify */ 339 if (escape || quote || comment || bracket) 340 return; 341 342 /* domain already present, no need to modify */ 343 if (has_domain) 344 return; 345 346 /* address is group, skip */ 347 if (has_group) 348 return; 349 350 /* there's an address between brackets, just append domain */ 351 if (has_bracket) { 352 pos_bracket--; 353 while (isspace((unsigned char)buffer[pos_bracket])) 354 pos_bracket--; 355 if (buffer[pos_bracket] == '<') 356 return; 357 pos_insert = pos_bracket + 1; 358 } 359 else { 360 /* otherwise append address to last component */ 361 pos_insert = pos_component + 1; 362 363 /* empty address */ 364 if (buffer[pos_component] == '\0' || 365 isspace((unsigned char)buffer[pos_component])) 366 return; 367 } 368 369 if (snprintf(copy, sizeof copy, "%.*s@%s%s", 370 (int)pos_insert, buffer, 371 domain, 372 buffer+pos_insert) >= (int)sizeof copy) 373 return; 374 375 memcpy(buffer, copy, len); 376 } 377 378 static void 379 header_address_rewrite_buffer(char *buffer, const char *address, size_t len) 380 { 381 size_t i; 382 int address_len; 383 int escape, quote, comment, bracket; 384 int has_bracket, has_group; 385 int pos_bracket_beg, pos_bracket_end, pos_component_beg, pos_component_end; 386 int insert_beg, insert_end; 387 char copy[APPEND_DOMAIN_BUFFER_SIZE]; 388 389 escape = quote = comment = bracket = 0; 390 has_bracket = has_group = 0; 391 pos_bracket_beg = pos_bracket_end = pos_component_beg = pos_component_end = 0; 392 for (i = 0; buffer[i]; ++i) { 393 if (buffer[i] == '(' && !escape && !quote) 394 comment++; 395 if (buffer[i] == '"' && !escape && !comment) 396 quote = !quote; 397 if (buffer[i] == ')' && !escape && !quote && comment) 398 comment--; 399 if (buffer[i] == '\\' && !escape && !comment && !quote) 400 escape = 1; 401 else 402 escape = 0; 403 if (buffer[i] == '<' && !escape && !comment && !quote && !bracket) { 404 bracket++; 405 has_bracket = 1; 406 pos_bracket_beg = i+1; 407 } 408 if (buffer[i] == '>' && !escape && !comment && !quote && bracket) { 409 bracket--; 410 pos_bracket_end = i; 411 } 412 if (buffer[i] == ':' && !escape && !comment && !quote) 413 has_group = 1; 414 415 /* update insert point if not in comment and not on a whitespace */ 416 if (!comment && buffer[i] != ')' && !isspace((unsigned char)buffer[i])) 417 pos_component_end = i; 418 } 419 420 /* parse error, do not attempt to modify */ 421 if (escape || quote || comment || bracket) 422 return; 423 424 /* address is group, skip */ 425 if (has_group) 426 return; 427 428 /* there's an address between brackets, just replace everything brackets */ 429 if (has_bracket) { 430 insert_beg = pos_bracket_beg; 431 insert_end = pos_bracket_end; 432 } 433 else { 434 if (pos_component_end == 0) 435 pos_component_beg = 0; 436 else { 437 for (pos_component_beg = pos_component_end; pos_component_beg >= 0; --pos_component_beg) 438 if (buffer[pos_component_beg] == ')' || isspace((unsigned char)buffer[pos_component_beg])) 439 break; 440 pos_component_beg += 1; 441 pos_component_end += 1; 442 } 443 insert_beg = pos_component_beg; 444 insert_end = pos_component_end; 445 } 446 447 /* check that masquerade won' t overflow */ 448 address_len = strlen(address); 449 if (strlen(buffer) - (insert_end - insert_beg) + address_len >= len) 450 return; 451 452 (void)strlcpy(copy, buffer, sizeof copy); 453 (void)strlcpy(copy+insert_beg, address, sizeof (copy) - insert_beg); 454 (void)strlcat(copy, buffer+insert_end, sizeof (copy)); 455 memcpy(buffer, copy, len); 456 } 457 458 static void 459 header_domain_append_callback(struct smtp_tx *tx, const char *hdr, 460 const char *val) 461 { 462 size_t i, j, linelen; 463 int escape, quote, comment, skip; 464 char buffer[APPEND_DOMAIN_BUFFER_SIZE]; 465 const char *line, *end; 466 467 if (smtp_message_printf(tx, "%s:", hdr) == -1) 468 return; 469 470 j = 0; 471 escape = quote = comment = skip = 0; 472 memset(buffer, 0, sizeof buffer); 473 474 for (line = val; line; line = end) { 475 end = strchr(line, '\n'); 476 if (end) { 477 linelen = end - line; 478 end++; 479 } 480 else 481 linelen = strlen(line); 482 483 for (i = 0; i < linelen; ++i) { 484 if (line[i] == '(' && !escape && !quote) 485 comment++; 486 if (line[i] == '"' && !escape && !comment) 487 quote = !quote; 488 if (line[i] == ')' && !escape && !quote && comment) 489 comment--; 490 if (line[i] == '\\' && !escape && !comment && !quote) 491 escape = 1; 492 else 493 escape = 0; 494 495 /* found a separator, buffer contains a full address */ 496 if (line[i] == ',' && !escape && !quote && !comment) { 497 if (!skip && j + strlen(tx->session->listener->hostname) + 1 < sizeof buffer) { 498 header_append_domain_buffer(buffer, tx->session->listener->hostname, sizeof buffer); 499 if (tx->session->flags & SF_AUTHENTICATED && 500 tx->session->listener->sendertable[0] && 501 tx->session->listener->flags & F_MASQUERADE && 502 !(strcasecmp(hdr, "From"))) 503 header_address_rewrite_buffer(buffer, mailaddr_to_text(&tx->evp.sender), 504 sizeof buffer); 505 } 506 if (smtp_message_printf(tx, "%s,", buffer) == -1) 507 return; 508 j = 0; 509 skip = 0; 510 memset(buffer, 0, sizeof buffer); 511 } 512 else { 513 if (skip) { 514 if (smtp_message_printf(tx, "%c", line[i]) == -1) 515 return; 516 } 517 else { 518 buffer[j++] = line[i]; 519 if (j == sizeof (buffer) - 1) { 520 if (smtp_message_printf(tx, "%s", buffer) == -1) 521 return; 522 skip = 1; 523 j = 0; 524 memset(buffer, 0, sizeof buffer); 525 } 526 } 527 } 528 } 529 if (skip) { 530 if (smtp_message_printf(tx, "\n") == -1) 531 return; 532 } 533 else { 534 buffer[j++] = '\n'; 535 if (j == sizeof (buffer) - 1) { 536 if (smtp_message_printf(tx, "%s", buffer) == -1) 537 return; 538 skip = 1; 539 j = 0; 540 memset(buffer, 0, sizeof buffer); 541 } 542 } 543 } 544 545 /* end of header, if buffer is not empty we'll process it */ 546 if (buffer[0]) { 547 if (j + strlen(tx->session->listener->hostname) + 1 < sizeof buffer) { 548 header_append_domain_buffer(buffer, tx->session->listener->hostname, sizeof buffer); 549 if (tx->session->flags & SF_AUTHENTICATED && 550 tx->session->listener->sendertable[0] && 551 tx->session->listener->flags & F_MASQUERADE && 552 !(strcasecmp(hdr, "From"))) 553 header_address_rewrite_buffer(buffer, mailaddr_to_text(&tx->evp.sender), 554 sizeof buffer); 555 } 556 smtp_message_printf(tx, "%s", buffer); 557 } 558 } 559 560 static void 561 smtp_session_init(void) 562 { 563 static int init = 0; 564 565 if (!init) { 566 tree_init(&wait_lka_helo); 567 tree_init(&wait_lka_mail); 568 tree_init(&wait_lka_rcpt); 569 tree_init(&wait_parent_auth); 570 tree_init(&wait_queue_msg); 571 tree_init(&wait_queue_fd); 572 tree_init(&wait_queue_commit); 573 tree_init(&wait_ssl_init); 574 tree_init(&wait_ssl_verify); 575 tree_init(&wait_filters); 576 tree_init(&wait_filter_fd); 577 init = 1; 578 } 579 } 580 581 int 582 smtp_session(struct listener *listener, int sock, 583 const struct sockaddr_storage *ss, const char *hostname, struct io *io) 584 { 585 struct smtp_session *s; 586 587 smtp_session_init(); 588 589 if ((s = calloc(1, sizeof(*s))) == NULL) 590 return (-1); 591 592 s->id = generate_uid(); 593 s->listener = listener; 594 memmove(&s->ss, ss, sizeof(*ss)); 595 596 if (io != NULL) 597 s->io = io; 598 else 599 s->io = io_new(); 600 601 io_set_callback(s->io, smtp_io, s); 602 io_set_fd(s->io, sock); 603 io_set_timeout(s->io, SMTPD_SESSION_TIMEOUT * 1000); 604 io_set_write(s->io); 605 s->state = STATE_NEW; 606 607 (void)strlcpy(s->smtpname, listener->hostname, sizeof(s->smtpname)); 608 609 log_trace(TRACE_SMTP, "smtp: %p: connected to listener %p " 610 "[hostname=%s, port=%d, tag=%s]", s, listener, 611 listener->hostname, ntohs(listener->port), listener->tag); 612 613 /* For local enqueueing, the hostname is already set */ 614 if (hostname) { 615 s->flags |= SF_AUTHENTICATED; 616 /* A bit of a hack */ 617 if (!strcmp(hostname, "localhost")) 618 s->flags |= SF_BOUNCE; 619 (void)strlcpy(s->rdns, hostname, sizeof(s->rdns)); 620 s->fcrdns = 1; 621 smtp_lookup_servername(s); 622 } else { 623 resolver_getnameinfo((struct sockaddr *)&s->ss, 624 NI_NAMEREQD | NI_NUMERICSERV, smtp_getnameinfo_cb, s); 625 } 626 627 /* session may have been freed by now */ 628 629 return (0); 630 } 631 632 static void 633 smtp_getnameinfo_cb(void *arg, int gaierrno, const char *host, const char *serv) 634 { 635 struct smtp_session *s = arg; 636 struct addrinfo hints; 637 638 if (gaierrno) { 639 (void)strlcpy(s->rdns, "<unknown>", sizeof(s->rdns)); 640 641 if (gaierrno == EAI_NODATA || gaierrno == EAI_NONAME) 642 s->fcrdns = 0; 643 else { 644 log_warnx("getnameinfo: %s: %s", ss_to_text(&s->ss), 645 gai_strerror(gaierrno)); 646 s->fcrdns = -1; 647 } 648 649 smtp_lookup_servername(s); 650 return; 651 } 652 653 (void)strlcpy(s->rdns, host, sizeof(s->rdns)); 654 655 memset(&hints, 0, sizeof(hints)); 656 hints.ai_family = s->ss.ss_family; 657 hints.ai_socktype = SOCK_STREAM; 658 resolver_getaddrinfo(s->rdns, NULL, &hints, smtp_getaddrinfo_cb, s); 659 } 660 661 static void 662 smtp_getaddrinfo_cb(void *arg, int gaierrno, struct addrinfo *ai0) 663 { 664 struct smtp_session *s = arg; 665 struct addrinfo *ai; 666 char fwd[64], rev[64]; 667 668 if (gaierrno) { 669 if (gaierrno == EAI_NODATA || gaierrno == EAI_NONAME) 670 s->fcrdns = 0; 671 else { 672 log_warnx("getaddrinfo: %s: %s", s->rdns, 673 gai_strerror(gaierrno)); 674 s->fcrdns = -1; 675 } 676 } 677 else { 678 strlcpy(rev, ss_to_text(&s->ss), sizeof(rev)); 679 for (ai = ai0; ai; ai = ai->ai_next) { 680 strlcpy(fwd, sa_to_text(ai->ai_addr), sizeof(fwd)); 681 if (!strcmp(fwd, rev)) { 682 s->fcrdns = 1; 683 break; 684 } 685 } 686 freeaddrinfo(ai0); 687 } 688 689 smtp_lookup_servername(s); 690 } 691 692 void 693 smtp_session_imsg(struct mproc *p, struct imsg *imsg) 694 { 695 struct smtp_session *s; 696 struct smtp_rcpt *rcpt; 697 char user[SMTPD_MAXMAILADDRSIZE]; 698 char tmp[SMTP_LINE_MAX]; 699 struct msg m; 700 const char *line, *helo; 701 uint64_t reqid, evpid; 702 uint32_t msgid; 703 int status, success; 704 int filter_response; 705 const char *filter_param; 706 uint8_t i; 707 708 switch (imsg->hdr.type) { 709 710 case IMSG_SMTP_CHECK_SENDER: 711 m_msg(&m, imsg); 712 m_get_id(&m, &reqid); 713 m_get_int(&m, &status); 714 m_end(&m); 715 s = tree_xpop(&wait_lka_mail, reqid); 716 switch (status) { 717 case LKA_OK: 718 smtp_tx_create_message(s->tx); 719 break; 720 721 case LKA_PERMFAIL: 722 smtp_tx_free(s->tx); 723 smtp_reply(s, "%d %s", 530, "Sender rejected"); 724 break; 725 case LKA_TEMPFAIL: 726 smtp_tx_free(s->tx); 727 smtp_reply(s, "421 %s Temporary Error", 728 esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS)); 729 break; 730 } 731 return; 732 733 case IMSG_SMTP_EXPAND_RCPT: 734 m_msg(&m, imsg); 735 m_get_id(&m, &reqid); 736 m_get_int(&m, &status); 737 m_get_string(&m, &line); 738 m_end(&m); 739 s = tree_xpop(&wait_lka_rcpt, reqid); 740 741 tmp[0] = '\0'; 742 if (s->tx->evp.rcpt.user[0]) { 743 (void)strlcpy(tmp, s->tx->evp.rcpt.user, sizeof tmp); 744 if (s->tx->evp.rcpt.domain[0]) { 745 (void)strlcat(tmp, "@", sizeof tmp); 746 (void)strlcat(tmp, s->tx->evp.rcpt.domain, 747 sizeof tmp); 748 } 749 } 750 751 switch (status) { 752 case LKA_OK: 753 fatalx("unexpected ok"); 754 case LKA_PERMFAIL: 755 smtp_reply(s, "%s: <%s>", line, tmp); 756 break; 757 case LKA_TEMPFAIL: 758 smtp_reply(s, "%s: <%s>", line, tmp); 759 break; 760 } 761 return; 762 763 case IMSG_SMTP_LOOKUP_HELO: 764 m_msg(&m, imsg); 765 m_get_id(&m, &reqid); 766 s = tree_xpop(&wait_lka_helo, reqid); 767 m_get_int(&m, &status); 768 if (status == LKA_OK) { 769 m_get_string(&m, &helo); 770 (void)strlcpy(s->smtpname, helo, sizeof(s->smtpname)); 771 } 772 m_end(&m); 773 smtp_connected(s); 774 return; 775 776 case IMSG_SMTP_MESSAGE_CREATE: 777 m_msg(&m, imsg); 778 m_get_id(&m, &reqid); 779 m_get_int(&m, &success); 780 s = tree_xpop(&wait_queue_msg, reqid); 781 if (success) { 782 m_get_msgid(&m, &msgid); 783 s->tx->msgid = msgid; 784 s->tx->evp.id = msgid_to_evpid(msgid); 785 s->tx->rcptcount = 0; 786 smtp_reply(s, "250 %s Ok", 787 esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS)); 788 } else { 789 smtp_reply(s, "421 %s Temporary Error", 790 esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS)); 791 smtp_tx_free(s->tx); 792 smtp_enter_state(s, STATE_QUIT); 793 } 794 m_end(&m); 795 return; 796 797 case IMSG_SMTP_MESSAGE_OPEN: 798 m_msg(&m, imsg); 799 m_get_id(&m, &reqid); 800 m_get_int(&m, &success); 801 m_end(&m); 802 803 s = tree_xpop(&wait_queue_fd, reqid); 804 if (!success || imsg->fd == -1) { 805 if (imsg->fd != -1) 806 close(imsg->fd); 807 smtp_reply(s, "421 %s Temporary Error", 808 esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS)); 809 smtp_enter_state(s, STATE_QUIT); 810 return; 811 } 812 813 log_debug("smtp: %p: fd %d from queue", s, imsg->fd); 814 815 if (smtp_message_fd(s->tx, imsg->fd)) { 816 if (!SESSION_DATA_FILTERED(s)) 817 smtp_message_begin(s->tx); 818 else 819 smtp_filter_data_begin(s); 820 } 821 return; 822 823 case IMSG_FILTER_SMTP_DATA_BEGIN: 824 m_msg(&m, imsg); 825 m_get_id(&m, &reqid); 826 m_get_int(&m, &success); 827 m_end(&m); 828 829 s = tree_xpop(&wait_filter_fd, reqid); 830 if (!success || imsg->fd == -1) { 831 if (imsg->fd != -1) 832 close(imsg->fd); 833 smtp_reply(s, "421 %s Temporary Error", 834 esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS)); 835 smtp_enter_state(s, STATE_QUIT); 836 return; 837 } 838 839 log_debug("smtp: %p: fd %d from lka", s, imsg->fd); 840 841 smtp_filter_fd(s->tx, imsg->fd); 842 smtp_message_begin(s->tx); 843 return; 844 845 case IMSG_QUEUE_ENVELOPE_SUBMIT: 846 m_msg(&m, imsg); 847 m_get_id(&m, &reqid); 848 m_get_int(&m, &success); 849 s = tree_xget(&wait_lka_rcpt, reqid); 850 if (success) { 851 m_get_evpid(&m, &evpid); 852 s->tx->evp.id = evpid; 853 s->tx->destcount++; 854 smtp_report_tx_envelope(s, s->tx->msgid, evpid); 855 } 856 else 857 s->tx->error = TX_ERROR_ENVELOPE; 858 m_end(&m); 859 return; 860 861 case IMSG_QUEUE_ENVELOPE_COMMIT: 862 m_msg(&m, imsg); 863 m_get_id(&m, &reqid); 864 m_get_int(&m, &success); 865 m_end(&m); 866 if (!success) 867 fatalx("commit evp failed: not supposed to happen"); 868 s = tree_xpop(&wait_lka_rcpt, reqid); 869 if (s->tx->error) { 870 /* 871 * If an envelope failed, we can't cancel the last 872 * RCPT only so we must cancel the whole transaction 873 * and close the connection. 874 */ 875 smtp_reply(s, "421 %s Temporary failure", 876 esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS)); 877 smtp_enter_state(s, STATE_QUIT); 878 } 879 else { 880 rcpt = xcalloc(1, sizeof(*rcpt)); 881 rcpt->evpid = s->tx->evp.id; 882 rcpt->destcount = s->tx->destcount; 883 rcpt->maddr = s->tx->evp.rcpt; 884 TAILQ_INSERT_TAIL(&s->tx->rcpts, rcpt, entry); 885 886 s->tx->destcount = 0; 887 s->tx->rcptcount++; 888 smtp_reply(s, "250 %s %s: Recipient ok", 889 esc_code(ESC_STATUS_OK, ESC_DESTINATION_ADDRESS_VALID), 890 esc_description(ESC_DESTINATION_ADDRESS_VALID)); 891 } 892 return; 893 894 case IMSG_SMTP_MESSAGE_COMMIT: 895 m_msg(&m, imsg); 896 m_get_id(&m, &reqid); 897 m_get_int(&m, &success); 898 m_end(&m); 899 s = tree_xpop(&wait_queue_commit, reqid); 900 if (!success) { 901 smtp_reply(s, "421 %s Temporary failure", 902 esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS)); 903 smtp_tx_free(s->tx); 904 smtp_enter_state(s, STATE_QUIT); 905 return; 906 } 907 908 smtp_reply(s, "250 %s %08x Message accepted for delivery", 909 esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS), 910 s->tx->msgid); 911 smtp_report_tx_commit(s, s->tx->msgid, s->tx->odatalen); 912 smtp_report_tx_reset(s, s->tx->msgid); 913 914 log_info("%016"PRIx64" smtp message " 915 "msgid=%08x size=%zu nrcpt=%zu proto=%s", 916 s->id, 917 s->tx->msgid, 918 s->tx->odatalen, 919 s->tx->rcptcount, 920 s->flags & SF_EHLO ? "ESMTP" : "SMTP"); 921 TAILQ_FOREACH(rcpt, &s->tx->rcpts, entry) { 922 log_info("%016"PRIx64" smtp envelope " 923 "evpid=%016"PRIx64" from=<%s%s%s> to=<%s%s%s>", 924 s->id, 925 rcpt->evpid, 926 s->tx->evp.sender.user, 927 s->tx->evp.sender.user[0] == '\0' ? "" : "@", 928 s->tx->evp.sender.domain, 929 rcpt->maddr.user, 930 rcpt->maddr.user[0] == '\0' ? "" : "@", 931 rcpt->maddr.domain); 932 } 933 smtp_tx_free(s->tx); 934 s->mailcount++; 935 smtp_enter_state(s, STATE_HELO); 936 return; 937 938 case IMSG_SMTP_AUTHENTICATE: 939 m_msg(&m, imsg); 940 m_get_id(&m, &reqid); 941 m_get_int(&m, &success); 942 m_end(&m); 943 944 s = tree_xpop(&wait_parent_auth, reqid); 945 strnvis(user, s->username, sizeof user, VIS_WHITE | VIS_SAFE); 946 if (success == LKA_OK) { 947 log_info("%016"PRIx64" smtp " 948 "authentication user=%s " 949 "result=ok", 950 s->id, user); 951 s->flags |= SF_AUTHENTICATED; 952 smtp_report_link_auth(s, user, "pass"); 953 smtp_reply(s, "235 %s Authentication succeeded", 954 esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS)); 955 } 956 else if (success == LKA_PERMFAIL) { 957 log_info("%016"PRIx64" smtp " 958 "authentication user=%s " 959 "result=permfail", 960 s->id, user); 961 smtp_report_link_auth(s, user, "fail"); 962 smtp_auth_failure_pause(s); 963 return; 964 } 965 else if (success == LKA_TEMPFAIL) { 966 log_info("%016"PRIx64" smtp " 967 "authentication user=%s " 968 "result=tempfail", 969 s->id, user); 970 smtp_report_link_auth(s, user, "error"); 971 smtp_reply(s, "421 %s Temporary failure", 972 esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS)); 973 } 974 else 975 fatalx("bad lka response"); 976 977 smtp_enter_state(s, STATE_HELO); 978 return; 979 980 case IMSG_FILTER_SMTP_PROTOCOL: 981 m_msg(&m, imsg); 982 m_get_id(&m, &reqid); 983 m_get_int(&m, &filter_response); 984 if (filter_response != FILTER_PROCEED && 985 filter_response != FILTER_JUNK) 986 m_get_string(&m, &filter_param); 987 else 988 filter_param = NULL; 989 m_end(&m); 990 991 s = tree_xpop(&wait_filters, reqid); 992 993 switch (filter_response) { 994 case FILTER_REJECT: 995 case FILTER_DISCONNECT: 996 if (!valid_smtp_response(filter_param) || 997 (filter_param[0] != '4' && filter_param[0] != '5')) 998 filter_param = "421 Internal server error"; 999 if (!strncmp(filter_param, "421", 3)) 1000 filter_response = FILTER_DISCONNECT; 1001 1002 smtp_report_filter_response(s, s->filter_phase, 1003 filter_response, filter_param); 1004 1005 smtp_reply(s, "%s", filter_param); 1006 1007 if (filter_response == FILTER_DISCONNECT) 1008 smtp_enter_state(s, STATE_QUIT); 1009 else if (s->filter_phase == FILTER_COMMIT) 1010 smtp_proceed_rollback(s, NULL); 1011 break; 1012 1013 1014 case FILTER_JUNK: 1015 if (s->tx) 1016 s->tx->junk = 1; 1017 else 1018 s->junk = 1; 1019 /* fallthrough */ 1020 1021 case FILTER_PROCEED: 1022 filter_param = s->filter_param; 1023 /* fallthrough */ 1024 1025 case FILTER_REWRITE: 1026 smtp_report_filter_response(s, s->filter_phase, 1027 filter_response, 1028 filter_param == s->filter_param ? NULL : filter_param); 1029 if (s->filter_phase == FILTER_CONNECT) { 1030 smtp_proceed_connected(s); 1031 return; 1032 } 1033 for (i = 0; i < nitems(commands); ++i) 1034 if (commands[i].filter_phase == s->filter_phase) { 1035 if (filter_response == FILTER_REWRITE) 1036 if (!commands[i].check(s, filter_param)) 1037 break; 1038 commands[i].proceed(s, filter_param); 1039 break; 1040 } 1041 break; 1042 } 1043 return; 1044 } 1045 1046 log_warnx("smtp_session_imsg: unexpected %s imsg", 1047 imsg_to_str(imsg->hdr.type)); 1048 fatalx(NULL); 1049 } 1050 1051 static void 1052 smtp_tls_init(struct smtp_session *s) 1053 { 1054 io_set_read(s->io); 1055 if (io_accept_tls(s->io, s->listener->tls) == -1) { 1056 log_info("%016"PRIx64" smtp disconnected " 1057 "reason=tls-accept-failed", 1058 s->id); 1059 smtp_free(s, "accept failed"); 1060 } 1061 } 1062 1063 static void 1064 smtp_tls_started(struct smtp_session *s) 1065 { 1066 if (tls_peer_cert_provided(io_tls(s->io))) { 1067 log_info("%016"PRIx64" smtp " 1068 "cert-check result=\"%s\" fingerprint=\"%s\"", 1069 s->id, 1070 (s->flags & SF_VERIFIED) ? "verified" : "unchecked", 1071 tls_peer_cert_hash(io_tls(s->io))); 1072 } 1073 1074 if (s->listener->flags & F_SMTPS) { 1075 stat_increment("smtp.smtps", 1); 1076 io_set_write(s->io); 1077 smtp_send_banner(s); 1078 } 1079 else { 1080 stat_increment("smtp.tls", 1); 1081 smtp_enter_state(s, STATE_HELO); 1082 } 1083 } 1084 1085 static void 1086 smtp_io(struct io *io, int evt, void *arg) 1087 { 1088 struct smtp_session *s = arg; 1089 char *line; 1090 size_t len; 1091 int eom; 1092 1093 log_trace(TRACE_IO, "smtp: %p: %s %s", s, io_strevent(evt), 1094 io_strio(io)); 1095 1096 switch (evt) { 1097 1098 case IO_TLSREADY: 1099 log_info("%016"PRIx64" smtp tls ciphers=%s", 1100 s->id, tls_to_text(io_tls(s->io))); 1101 1102 smtp_report_link_tls(s, tls_to_text(io_tls(s->io))); 1103 1104 s->flags |= SF_SECURE; 1105 if (s->listener->flags & F_TLS_VERIFY) 1106 s->flags |= SF_VERIFIED; 1107 s->helo[0] = '\0'; 1108 1109 smtp_tls_started(s); 1110 break; 1111 1112 case IO_DATAIN: 1113 nextline: 1114 line = io_getline(s->io, &len); 1115 if ((line == NULL && io_datalen(s->io) >= SMTP_LINE_MAX) || 1116 (line && len >= SMTP_LINE_MAX)) { 1117 s->flags |= SF_BADINPUT; 1118 smtp_reply(s, "500 %s Line too long", 1119 esc_code(ESC_STATUS_PERMFAIL, ESC_OTHER_STATUS)); 1120 smtp_enter_state(s, STATE_QUIT); 1121 io_set_write(io); 1122 return; 1123 } 1124 1125 /* No complete line received */ 1126 if (line == NULL) 1127 return; 1128 1129 /* Strip trailing '\r' */ 1130 if (len && line[len - 1] == '\r') 1131 line[--len] = '\0'; 1132 1133 /* Message body */ 1134 eom = 0; 1135 if (s->state == STATE_BODY) { 1136 if (strcmp(line, ".")) { 1137 s->tx->datain += strlen(line) + 1; 1138 if (s->tx->datain > env->sc_maxsize) 1139 s->tx->error = TX_ERROR_SIZE; 1140 } 1141 eom = (s->tx->filter == NULL) ? 1142 smtp_tx_dataline(s->tx, line) : 1143 smtp_tx_filtered_dataline(s->tx, line); 1144 if (eom == 0) 1145 goto nextline; 1146 } 1147 1148 /* Pipelining not supported */ 1149 if (io_datalen(s->io)) { 1150 s->flags |= SF_BADINPUT; 1151 smtp_reply(s, "500 %s %s: Pipelining not supported", 1152 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1153 esc_description(ESC_INVALID_COMMAND)); 1154 smtp_enter_state(s, STATE_QUIT); 1155 io_set_write(io); 1156 return; 1157 } 1158 1159 if (eom) { 1160 io_set_write(io); 1161 if (s->tx->filter == NULL) 1162 smtp_tx_eom(s->tx); 1163 return; 1164 } 1165 1166 /* Must be a command */ 1167 if (strlcpy(s->cmd, line, sizeof(s->cmd)) >= sizeof(s->cmd)) { 1168 s->flags |= SF_BADINPUT; 1169 smtp_reply(s, "500 %s Command line too long", 1170 esc_code(ESC_STATUS_PERMFAIL, ESC_OTHER_STATUS)); 1171 smtp_enter_state(s, STATE_QUIT); 1172 io_set_write(io); 1173 return; 1174 } 1175 io_set_write(io); 1176 smtp_command(s, line); 1177 break; 1178 1179 case IO_LOWAT: 1180 if (s->state == STATE_QUIT) { 1181 log_info("%016"PRIx64" smtp disconnected " 1182 "reason=quit", 1183 s->id); 1184 smtp_free(s, "done"); 1185 break; 1186 } 1187 1188 /* Wait for the client to start tls */ 1189 if (s->state == STATE_TLS) { 1190 smtp_tls_init(s); 1191 break; 1192 } 1193 1194 io_set_read(io); 1195 break; 1196 1197 case IO_TIMEOUT: 1198 log_info("%016"PRIx64" smtp disconnected " 1199 "reason=timeout", 1200 s->id); 1201 smtp_report_timeout(s); 1202 smtp_free(s, "timeout"); 1203 break; 1204 1205 case IO_DISCONNECTED: 1206 log_info("%016"PRIx64" smtp disconnected " 1207 "reason=disconnect", 1208 s->id); 1209 smtp_free(s, "disconnected"); 1210 break; 1211 1212 case IO_ERROR: 1213 log_info("%016"PRIx64" smtp disconnected " 1214 "reason=\"io-error: %s\"", 1215 s->id, io_error(io)); 1216 smtp_free(s, "IO error"); 1217 break; 1218 1219 default: 1220 fatalx("smtp_io()"); 1221 } 1222 } 1223 1224 static void 1225 smtp_command(struct smtp_session *s, char *line) 1226 { 1227 char *args; 1228 int cmd, i; 1229 1230 log_trace(TRACE_SMTP, "smtp: %p: <<< %s", s, line); 1231 1232 /* 1233 * These states are special. 1234 */ 1235 if (s->state == STATE_AUTH_INIT) { 1236 smtp_report_protocol_client(s, "********"); 1237 smtp_rfc4954_auth_plain(s, line); 1238 return; 1239 } 1240 if (s->state == STATE_AUTH_USERNAME || s->state == STATE_AUTH_PASSWORD) { 1241 smtp_report_protocol_client(s, "********"); 1242 smtp_rfc4954_auth_login(s, line); 1243 return; 1244 } 1245 1246 if (s->state == STATE_HELO && strncasecmp(line, "AUTH PLAIN ", 11) == 0) 1247 smtp_report_protocol_client(s, "AUTH PLAIN ********"); 1248 else 1249 smtp_report_protocol_client(s, line); 1250 1251 1252 /* 1253 * Unlike other commands, "mail from" and "rcpt to" contain a 1254 * space in the command name. 1255 */ 1256 if (strncasecmp("mail from:", line, 10) == 0 || 1257 strncasecmp("rcpt to:", line, 8) == 0) 1258 args = strchr(line, ':'); 1259 else 1260 args = strchr(line, ' '); 1261 1262 if (args) { 1263 *args++ = '\0'; 1264 while (isspace((unsigned char)*args)) 1265 args++; 1266 } 1267 1268 cmd = -1; 1269 for (i = 0; commands[i].code != -1; i++) 1270 if (!strcasecmp(line, commands[i].cmd)) { 1271 cmd = commands[i].code; 1272 break; 1273 } 1274 1275 s->last_cmd = cmd; 1276 switch (cmd) { 1277 /* 1278 * INIT 1279 */ 1280 case CMD_HELO: 1281 if (!smtp_check_helo(s, args)) 1282 break; 1283 smtp_filter_phase(FILTER_HELO, s, args); 1284 break; 1285 1286 case CMD_EHLO: 1287 if (!smtp_check_ehlo(s, args)) 1288 break; 1289 smtp_filter_phase(FILTER_EHLO, s, args); 1290 break; 1291 1292 /* 1293 * SETUP 1294 */ 1295 case CMD_STARTTLS: 1296 if (!smtp_check_starttls(s, args)) 1297 break; 1298 1299 smtp_filter_phase(FILTER_STARTTLS, s, NULL); 1300 break; 1301 1302 case CMD_AUTH: 1303 if (!smtp_check_auth(s, args)) 1304 break; 1305 smtp_filter_phase(FILTER_AUTH, s, args); 1306 break; 1307 1308 case CMD_MAIL_FROM: 1309 if (!smtp_check_mail_from(s, args)) 1310 break; 1311 smtp_filter_phase(FILTER_MAIL_FROM, s, args); 1312 break; 1313 1314 /* 1315 * TRANSACTION 1316 */ 1317 case CMD_RCPT_TO: 1318 if (!smtp_check_rcpt_to(s, args)) 1319 break; 1320 smtp_filter_phase(FILTER_RCPT_TO, s, args); 1321 break; 1322 1323 case CMD_RSET: 1324 if (!smtp_check_rset(s, args)) 1325 break; 1326 smtp_filter_phase(FILTER_RSET, s, NULL); 1327 break; 1328 1329 case CMD_DATA: 1330 if (!smtp_check_data(s, args)) 1331 break; 1332 smtp_filter_phase(FILTER_DATA, s, NULL); 1333 break; 1334 1335 /* 1336 * ANY 1337 */ 1338 case CMD_QUIT: 1339 if (!smtp_check_noparam(s, args)) 1340 break; 1341 smtp_filter_phase(FILTER_QUIT, s, NULL); 1342 break; 1343 1344 case CMD_NOOP: 1345 if (!smtp_check_noparam(s, args)) 1346 break; 1347 smtp_filter_phase(FILTER_NOOP, s, NULL); 1348 break; 1349 1350 case CMD_HELP: 1351 if (!smtp_check_noparam(s, args)) 1352 break; 1353 smtp_proceed_help(s, NULL); 1354 break; 1355 1356 case CMD_WIZ: 1357 if (!smtp_check_noparam(s, args)) 1358 break; 1359 smtp_proceed_wiz(s, NULL); 1360 break; 1361 1362 default: 1363 smtp_reply(s, "500 %s %s: Command unrecognized", 1364 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1365 esc_description(ESC_INVALID_COMMAND)); 1366 break; 1367 } 1368 } 1369 1370 static int 1371 smtp_check_rset(struct smtp_session *s, const char *args) 1372 { 1373 if (!smtp_check_noparam(s, args)) 1374 return 0; 1375 1376 if (s->helo[0] == '\0') { 1377 smtp_reply(s, "503 %s %s: Command not allowed at this point.", 1378 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1379 esc_description(ESC_INVALID_COMMAND)); 1380 return 0; 1381 } 1382 return 1; 1383 } 1384 1385 static int 1386 smtp_check_helo(struct smtp_session *s, const char *args) 1387 { 1388 if (!s->banner_sent) { 1389 smtp_reply(s, "503 %s %s: Command not allowed at this point.", 1390 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1391 esc_description(ESC_INVALID_COMMAND)); 1392 return 0; 1393 } 1394 1395 if (s->helo[0]) { 1396 smtp_reply(s, "503 %s %s: Already identified", 1397 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1398 esc_description(ESC_INVALID_COMMAND)); 1399 return 0; 1400 } 1401 1402 if (args == NULL) { 1403 smtp_reply(s, "501 %s %s: HELO requires domain name", 1404 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1405 esc_description(ESC_INVALID_COMMAND)); 1406 return 0; 1407 } 1408 1409 if (!valid_domainpart(args)) { 1410 smtp_reply(s, "501 %s %s: Invalid domain name", 1411 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS), 1412 esc_description(ESC_INVALID_COMMAND_ARGUMENTS)); 1413 return 0; 1414 } 1415 1416 return 1; 1417 } 1418 1419 static int 1420 smtp_check_ehlo(struct smtp_session *s, const char *args) 1421 { 1422 if (!s->banner_sent) { 1423 smtp_reply(s, "503 %s %s: Command not allowed at this point.", 1424 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1425 esc_description(ESC_INVALID_COMMAND)); 1426 return 0; 1427 } 1428 1429 if (s->helo[0]) { 1430 smtp_reply(s, "503 %s %s: Already identified", 1431 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1432 esc_description(ESC_INVALID_COMMAND)); 1433 return 0; 1434 } 1435 1436 if (args == NULL) { 1437 smtp_reply(s, "501 %s %s: EHLO requires domain name", 1438 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1439 esc_description(ESC_INVALID_COMMAND)); 1440 return 0; 1441 } 1442 1443 if (!valid_domainpart(args)) { 1444 smtp_reply(s, "501 %s %s: Invalid domain name", 1445 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS), 1446 esc_description(ESC_INVALID_COMMAND_ARGUMENTS)); 1447 return 0; 1448 } 1449 1450 return 1; 1451 } 1452 1453 static int 1454 smtp_check_auth(struct smtp_session *s, const char *args) 1455 { 1456 if (s->helo[0] == '\0' || s->tx) { 1457 smtp_reply(s, "503 %s %s: Command not allowed at this point.", 1458 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1459 esc_description(ESC_INVALID_COMMAND)); 1460 return 0; 1461 } 1462 1463 if (s->flags & SF_AUTHENTICATED) { 1464 smtp_reply(s, "503 %s %s: Already authenticated", 1465 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1466 esc_description(ESC_INVALID_COMMAND)); 1467 return 0; 1468 } 1469 1470 if (!ADVERTISE_AUTH(s)) { 1471 smtp_reply(s, "503 %s %s: Command not supported", 1472 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1473 esc_description(ESC_INVALID_COMMAND)); 1474 return 0; 1475 } 1476 1477 if (args == NULL) { 1478 smtp_reply(s, "501 %s %s: No parameters given", 1479 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS), 1480 esc_description(ESC_INVALID_COMMAND_ARGUMENTS)); 1481 return 0; 1482 } 1483 1484 return 1; 1485 } 1486 1487 static int 1488 smtp_check_starttls(struct smtp_session *s, const char *args) 1489 { 1490 if (s->helo[0] == '\0' || s->tx) { 1491 smtp_reply(s, "503 %s %s: Command not allowed at this point.", 1492 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1493 esc_description(ESC_INVALID_COMMAND)); 1494 return 0; 1495 } 1496 1497 if (!(s->listener->flags & F_STARTTLS)) { 1498 smtp_reply(s, "503 %s %s: Command not supported", 1499 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1500 esc_description(ESC_INVALID_COMMAND)); 1501 return 0; 1502 } 1503 1504 if (s->flags & SF_SECURE) { 1505 smtp_reply(s, "503 %s %s: Channel already secured", 1506 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1507 esc_description(ESC_INVALID_COMMAND)); 1508 return 0; 1509 } 1510 1511 if (args != NULL) { 1512 smtp_reply(s, "501 %s %s: No parameters allowed", 1513 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS), 1514 esc_description(ESC_INVALID_COMMAND_ARGUMENTS)); 1515 return 0; 1516 } 1517 1518 return 1; 1519 } 1520 1521 static int 1522 smtp_check_mail_from(struct smtp_session *s, const char *args) 1523 { 1524 char *copy; 1525 char tmp[SMTP_LINE_MAX]; 1526 struct mailaddr sender; 1527 1528 (void)strlcpy(tmp, args, sizeof tmp); 1529 copy = tmp; 1530 1531 if (s->helo[0] == '\0' || s->tx) { 1532 smtp_reply(s, "503 %s %s: Command not allowed at this point.", 1533 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1534 esc_description(ESC_INVALID_COMMAND)); 1535 return 0; 1536 } 1537 1538 if (s->listener->flags & F_STARTTLS_REQUIRE && 1539 !(s->flags & SF_SECURE)) { 1540 smtp_reply(s, 1541 "530 %s %s: Must issue a STARTTLS command first", 1542 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1543 esc_description(ESC_INVALID_COMMAND)); 1544 return 0; 1545 } 1546 1547 if (s->listener->flags & F_AUTH_REQUIRE && 1548 !(s->flags & SF_AUTHENTICATED)) { 1549 smtp_reply(s, 1550 "530 %s %s: Must issue an AUTH command first", 1551 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1552 esc_description(ESC_INVALID_COMMAND)); 1553 return 0; 1554 } 1555 1556 if (s->mailcount >= env->sc_session_max_mails) { 1557 /* we can pretend we had too many recipients */ 1558 smtp_reply(s, "452 %s %s: Too many messages sent", 1559 esc_code(ESC_STATUS_TEMPFAIL, ESC_TOO_MANY_RECIPIENTS), 1560 esc_description(ESC_TOO_MANY_RECIPIENTS)); 1561 return 0; 1562 } 1563 1564 if (smtp_mailaddr(&sender, copy, 1, ©, 1565 s->smtpname) == 0) { 1566 smtp_reply(s, "553 %s Sender address syntax error", 1567 esc_code(ESC_STATUS_PERMFAIL, ESC_OTHER_ADDRESS_STATUS)); 1568 return 0; 1569 } 1570 1571 return 1; 1572 } 1573 1574 static int 1575 smtp_check_rcpt_to(struct smtp_session *s, const char *args) 1576 { 1577 char *copy; 1578 char tmp[SMTP_LINE_MAX]; 1579 1580 (void)strlcpy(tmp, args, sizeof tmp); 1581 copy = tmp; 1582 1583 if (s->tx == NULL) { 1584 smtp_reply(s, "503 %s %s: Command not allowed at this point.", 1585 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1586 esc_description(ESC_INVALID_COMMAND)); 1587 return 0; 1588 } 1589 1590 if (s->tx->rcptcount >= env->sc_session_max_rcpt) { 1591 smtp_reply(s->tx->session, "451 %s %s: Too many recipients", 1592 esc_code(ESC_STATUS_TEMPFAIL, ESC_TOO_MANY_RECIPIENTS), 1593 esc_description(ESC_TOO_MANY_RECIPIENTS)); 1594 return 0; 1595 } 1596 1597 if (smtp_mailaddr(&s->tx->evp.rcpt, copy, 0, ©, 1598 s->tx->session->smtpname) == 0) { 1599 smtp_reply(s->tx->session, 1600 "501 %s Recipient address syntax error", 1601 esc_code(ESC_STATUS_PERMFAIL, 1602 ESC_BAD_DESTINATION_MAILBOX_ADDRESS_SYNTAX)); 1603 return 0; 1604 } 1605 1606 return 1; 1607 } 1608 1609 static int 1610 smtp_check_data(struct smtp_session *s, const char *args) 1611 { 1612 if (!smtp_check_noparam(s, args)) 1613 return 0; 1614 1615 if (s->tx == NULL) { 1616 smtp_reply(s, "503 %s %s: Command not allowed at this point.", 1617 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1618 esc_description(ESC_INVALID_COMMAND)); 1619 return 0; 1620 } 1621 1622 if (s->tx->rcptcount == 0) { 1623 smtp_reply(s, "503 %s %s: No recipient specified", 1624 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS), 1625 esc_description(ESC_INVALID_COMMAND_ARGUMENTS)); 1626 return 0; 1627 } 1628 1629 return 1; 1630 } 1631 1632 static int 1633 smtp_check_noparam(struct smtp_session *s, const char *args) 1634 { 1635 if (args != NULL) { 1636 smtp_reply(s, "500 %s %s: command does not accept arguments.", 1637 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS), 1638 esc_description(ESC_INVALID_COMMAND_ARGUMENTS)); 1639 return 0; 1640 } 1641 return 1; 1642 } 1643 1644 static void 1645 smtp_query_filters(enum filter_phase phase, struct smtp_session *s, const char *args) 1646 { 1647 m_create(p_lka, IMSG_FILTER_SMTP_PROTOCOL, 0, 0, -1); 1648 m_add_id(p_lka, s->id); 1649 m_add_int(p_lka, phase); 1650 m_add_string(p_lka, args); 1651 m_close(p_lka); 1652 tree_xset(&wait_filters, s->id, s); 1653 } 1654 1655 static void 1656 smtp_filter_begin(struct smtp_session *s) 1657 { 1658 if (!SESSION_FILTERED(s)) 1659 return; 1660 1661 m_create(p_lka, IMSG_FILTER_SMTP_BEGIN, 0, 0, -1); 1662 m_add_id(p_lka, s->id); 1663 m_add_string(p_lka, s->listener->filter_name); 1664 m_close(p_lka); 1665 } 1666 1667 static void 1668 smtp_filter_end(struct smtp_session *s) 1669 { 1670 if (!SESSION_FILTERED(s)) 1671 return; 1672 1673 m_create(p_lka, IMSG_FILTER_SMTP_END, 0, 0, -1); 1674 m_add_id(p_lka, s->id); 1675 m_close(p_lka); 1676 } 1677 1678 static void 1679 smtp_filter_data_begin(struct smtp_session *s) 1680 { 1681 if (!SESSION_FILTERED(s)) 1682 return; 1683 1684 m_create(p_lka, IMSG_FILTER_SMTP_DATA_BEGIN, 0, 0, -1); 1685 m_add_id(p_lka, s->id); 1686 m_close(p_lka); 1687 tree_xset(&wait_filter_fd, s->id, s); 1688 } 1689 1690 static void 1691 smtp_filter_data_end(struct smtp_session *s) 1692 { 1693 if (!SESSION_FILTERED(s)) 1694 return; 1695 1696 if (s->tx->filter == NULL) 1697 return; 1698 1699 io_free(s->tx->filter); 1700 s->tx->filter = NULL; 1701 1702 m_create(p_lka, IMSG_FILTER_SMTP_DATA_END, 0, 0, -1); 1703 m_add_id(p_lka, s->id); 1704 m_close(p_lka); 1705 } 1706 1707 static void 1708 smtp_filter_phase(enum filter_phase phase, struct smtp_session *s, const char *param) 1709 { 1710 uint8_t i; 1711 1712 s->filter_phase = phase; 1713 s->filter_param = param; 1714 1715 if (SESSION_FILTERED(s)) { 1716 smtp_query_filters(phase, s, param ? param : ""); 1717 return; 1718 } 1719 1720 if (s->filter_phase == FILTER_CONNECT) { 1721 smtp_proceed_connected(s); 1722 return; 1723 } 1724 1725 for (i = 0; i < nitems(commands); ++i) 1726 if (commands[i].filter_phase == s->filter_phase) { 1727 commands[i].proceed(s, param); 1728 break; 1729 } 1730 } 1731 1732 static void 1733 smtp_proceed_rset(struct smtp_session *s, const char *args) 1734 { 1735 smtp_reply(s, "250 %s Reset state", 1736 esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS)); 1737 1738 if (s->tx) { 1739 if (s->tx->msgid) 1740 smtp_tx_rollback(s->tx); 1741 smtp_tx_free(s->tx); 1742 } 1743 } 1744 1745 static void 1746 smtp_proceed_helo(struct smtp_session *s, const char *args) 1747 { 1748 (void)strlcpy(s->helo, args, sizeof(s->helo)); 1749 s->flags &= SF_SECURE | SF_AUTHENTICATED | SF_VERIFIED; 1750 1751 smtp_report_link_identify(s, "HELO", s->helo); 1752 1753 smtp_enter_state(s, STATE_HELO); 1754 1755 smtp_reply(s, "250 %s Hello %s %s%s%s, pleased to meet you", 1756 s->smtpname, 1757 s->helo, 1758 s->ss.ss_family == AF_INET6 ? "" : "[", 1759 ss_to_text(&s->ss), 1760 s->ss.ss_family == AF_INET6 ? "" : "]"); 1761 } 1762 1763 static void 1764 smtp_proceed_ehlo(struct smtp_session *s, const char *args) 1765 { 1766 (void)strlcpy(s->helo, args, sizeof(s->helo)); 1767 s->flags &= SF_SECURE | SF_AUTHENTICATED | SF_VERIFIED; 1768 s->flags |= SF_EHLO; 1769 s->flags |= SF_8BITMIME; 1770 1771 smtp_report_link_identify(s, "EHLO", s->helo); 1772 1773 smtp_enter_state(s, STATE_HELO); 1774 smtp_reply(s, "250-%s Hello %s %s%s%s, pleased to meet you", 1775 s->smtpname, 1776 s->helo, 1777 s->ss.ss_family == AF_INET6 ? "" : "[", 1778 ss_to_text(&s->ss), 1779 s->ss.ss_family == AF_INET6 ? "" : "]"); 1780 1781 smtp_reply(s, "250-8BITMIME"); 1782 smtp_reply(s, "250-ENHANCEDSTATUSCODES"); 1783 smtp_reply(s, "250-SIZE %zu", env->sc_maxsize); 1784 if (ADVERTISE_EXT_DSN(s)) 1785 smtp_reply(s, "250-DSN"); 1786 if (ADVERTISE_TLS(s)) 1787 smtp_reply(s, "250-STARTTLS"); 1788 if (ADVERTISE_AUTH(s)) 1789 smtp_reply(s, "250-AUTH PLAIN LOGIN"); 1790 smtp_reply(s, "250 HELP"); 1791 } 1792 1793 static void 1794 smtp_proceed_auth(struct smtp_session *s, const char *args) 1795 { 1796 char tmp[SMTP_LINE_MAX]; 1797 char *eom, *method; 1798 1799 (void)strlcpy(tmp, args, sizeof tmp); 1800 1801 method = tmp; 1802 eom = strchr(tmp, ' '); 1803 if (eom == NULL) 1804 eom = strchr(tmp, '\t'); 1805 if (eom != NULL) 1806 *eom++ = '\0'; 1807 if (strcasecmp(method, "PLAIN") == 0) 1808 smtp_rfc4954_auth_plain(s, eom); 1809 else if (strcasecmp(method, "LOGIN") == 0) 1810 smtp_rfc4954_auth_login(s, eom); 1811 else 1812 smtp_reply(s, "504 %s %s: AUTH method \"%s\" not supported", 1813 esc_code(ESC_STATUS_PERMFAIL, ESC_SECURITY_FEATURES_NOT_SUPPORTED), 1814 esc_description(ESC_SECURITY_FEATURES_NOT_SUPPORTED), 1815 method); 1816 } 1817 1818 static void 1819 smtp_proceed_starttls(struct smtp_session *s, const char *args) 1820 { 1821 smtp_reply(s, "220 %s Ready to start TLS", 1822 esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS)); 1823 smtp_enter_state(s, STATE_TLS); 1824 } 1825 1826 static void 1827 smtp_proceed_mail_from(struct smtp_session *s, const char *args) 1828 { 1829 char *copy; 1830 char tmp[SMTP_LINE_MAX]; 1831 1832 (void)strlcpy(tmp, args, sizeof tmp); 1833 copy = tmp; 1834 1835 if (!smtp_tx(s)) { 1836 smtp_reply(s, "421 %s Temporary Error", 1837 esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS)); 1838 smtp_enter_state(s, STATE_QUIT); 1839 return; 1840 } 1841 1842 if (smtp_mailaddr(&s->tx->evp.sender, copy, 1, ©, 1843 s->smtpname) == 0) { 1844 smtp_reply(s, "553 %s Sender address syntax error", 1845 esc_code(ESC_STATUS_PERMFAIL, ESC_OTHER_ADDRESS_STATUS)); 1846 smtp_tx_free(s->tx); 1847 return; 1848 } 1849 1850 smtp_tx_mail_from(s->tx, args); 1851 } 1852 1853 static void 1854 smtp_proceed_rcpt_to(struct smtp_session *s, const char *args) 1855 { 1856 smtp_tx_rcpt_to(s->tx, args); 1857 } 1858 1859 static void 1860 smtp_proceed_data(struct smtp_session *s, const char *args) 1861 { 1862 smtp_tx_open_message(s->tx); 1863 } 1864 1865 static void 1866 smtp_proceed_quit(struct smtp_session *s, const char *args) 1867 { 1868 smtp_reply(s, "221 %s Bye", 1869 esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS)); 1870 smtp_enter_state(s, STATE_QUIT); 1871 } 1872 1873 static void 1874 smtp_proceed_noop(struct smtp_session *s, const char *args) 1875 { 1876 smtp_reply(s, "250 %s Ok", 1877 esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS)); 1878 } 1879 1880 static void 1881 smtp_proceed_help(struct smtp_session *s, const char *args) 1882 { 1883 const char *code = esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS); 1884 1885 smtp_reply(s, "214-%s This is " SMTPD_NAME, code); 1886 smtp_reply(s, "214-%s To report bugs in the implementation, " 1887 "please contact bugs@openbsd.org", code); 1888 smtp_reply(s, "214-%s with full details", code); 1889 smtp_reply(s, "214 %s End of HELP info", code); 1890 } 1891 1892 static void 1893 smtp_proceed_wiz(struct smtp_session *s, const char *args) 1894 { 1895 smtp_reply(s, "500 %s %s: this feature is not supported yet ;-)", 1896 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND), 1897 esc_description(ESC_INVALID_COMMAND)); 1898 } 1899 1900 static void 1901 smtp_proceed_commit(struct smtp_session *s, const char *args) 1902 { 1903 smtp_message_end(s->tx); 1904 } 1905 1906 static void 1907 smtp_proceed_rollback(struct smtp_session *s, const char *args) 1908 { 1909 struct smtp_tx *tx; 1910 1911 tx = s->tx; 1912 1913 fclose(tx->ofile); 1914 tx->ofile = NULL; 1915 1916 smtp_tx_rollback(tx); 1917 smtp_tx_free(tx); 1918 smtp_enter_state(s, STATE_HELO); 1919 } 1920 1921 static void 1922 smtp_rfc4954_auth_plain(struct smtp_session *s, char *arg) 1923 { 1924 char buf[1024], *user, *pass; 1925 int len; 1926 1927 switch (s->state) { 1928 case STATE_HELO: 1929 if (arg == NULL) { 1930 smtp_enter_state(s, STATE_AUTH_INIT); 1931 smtp_reply(s, "334 "); 1932 return; 1933 } 1934 smtp_enter_state(s, STATE_AUTH_INIT); 1935 /* FALLTHROUGH */ 1936 1937 case STATE_AUTH_INIT: 1938 /* String is not NUL terminated, leave room. */ 1939 if ((len = base64_decode(arg, (unsigned char *)buf, 1940 sizeof(buf) - 1)) == -1) 1941 goto abort; 1942 /* buf is a byte string, NUL terminate. */ 1943 buf[len] = '\0'; 1944 1945 /* 1946 * Skip "foo" in "foo\0user\0pass", if present. 1947 */ 1948 user = memchr(buf, '\0', len); 1949 if (user == NULL || user >= buf + len - 2) 1950 goto abort; 1951 user++; /* skip NUL */ 1952 if (strlcpy(s->username, user, sizeof(s->username)) 1953 >= sizeof(s->username)) 1954 goto abort; 1955 1956 pass = memchr(user, '\0', len - (user - buf)); 1957 if (pass == NULL || pass >= buf + len - 2) 1958 goto abort; 1959 pass++; /* skip NUL */ 1960 1961 m_create(p_lka, IMSG_SMTP_AUTHENTICATE, 0, 0, -1); 1962 m_add_id(p_lka, s->id); 1963 m_add_string(p_lka, s->listener->authtable); 1964 m_add_string(p_lka, user); 1965 m_add_string(p_lka, pass); 1966 m_close(p_lka); 1967 tree_xset(&wait_parent_auth, s->id, s); 1968 return; 1969 1970 default: 1971 fatal("smtp_rfc4954_auth_plain: unknown state"); 1972 } 1973 1974 abort: 1975 smtp_reply(s, "501 %s %s: Syntax error", 1976 esc_code(ESC_STATUS_PERMFAIL, ESC_SYNTAX_ERROR), 1977 esc_description(ESC_SYNTAX_ERROR)); 1978 smtp_enter_state(s, STATE_HELO); 1979 } 1980 1981 static void 1982 smtp_rfc4954_auth_login(struct smtp_session *s, char *arg) 1983 { 1984 char buf[LINE_MAX]; 1985 1986 switch (s->state) { 1987 case STATE_HELO: 1988 smtp_enter_state(s, STATE_AUTH_USERNAME); 1989 if (arg != NULL && *arg != '\0') { 1990 smtp_rfc4954_auth_login(s, arg); 1991 return; 1992 } 1993 smtp_reply(s, "334 VXNlcm5hbWU6"); 1994 return; 1995 1996 case STATE_AUTH_USERNAME: 1997 memset(s->username, 0, sizeof(s->username)); 1998 if (base64_decode(arg, (unsigned char *)s->username, 1999 sizeof(s->username) - 1) == -1) 2000 goto abort; 2001 2002 smtp_enter_state(s, STATE_AUTH_PASSWORD); 2003 smtp_reply(s, "334 UGFzc3dvcmQ6"); 2004 return; 2005 2006 case STATE_AUTH_PASSWORD: 2007 memset(buf, 0, sizeof(buf)); 2008 if (base64_decode(arg, (unsigned char *)buf, 2009 sizeof(buf)-1) == -1) 2010 goto abort; 2011 2012 m_create(p_lka, IMSG_SMTP_AUTHENTICATE, 0, 0, -1); 2013 m_add_id(p_lka, s->id); 2014 m_add_string(p_lka, s->listener->authtable); 2015 m_add_string(p_lka, s->username); 2016 m_add_string(p_lka, buf); 2017 m_close(p_lka); 2018 tree_xset(&wait_parent_auth, s->id, s); 2019 return; 2020 2021 default: 2022 fatal("smtp_rfc4954_auth_login: unknown state"); 2023 } 2024 2025 abort: 2026 smtp_reply(s, "501 %s %s: Syntax error", 2027 esc_code(ESC_STATUS_PERMFAIL, ESC_SYNTAX_ERROR), 2028 esc_description(ESC_SYNTAX_ERROR)); 2029 smtp_enter_state(s, STATE_HELO); 2030 } 2031 2032 static void 2033 smtp_lookup_servername(struct smtp_session *s) 2034 { 2035 if (s->listener->hostnametable[0]) { 2036 m_create(p_lka, IMSG_SMTP_LOOKUP_HELO, 0, 0, -1); 2037 m_add_id(p_lka, s->id); 2038 m_add_string(p_lka, s->listener->hostnametable); 2039 m_add_sockaddr(p_lka, (struct sockaddr*)&s->listener->ss); 2040 m_close(p_lka); 2041 tree_xset(&wait_lka_helo, s->id, s); 2042 return; 2043 } 2044 2045 smtp_connected(s); 2046 } 2047 2048 static void 2049 smtp_connected(struct smtp_session *s) 2050 { 2051 smtp_enter_state(s, STATE_CONNECTED); 2052 2053 log_info("%016"PRIx64" smtp connected address=%s host=%s", 2054 s->id, ss_to_text(&s->ss), s->rdns); 2055 2056 smtp_filter_begin(s); 2057 2058 smtp_report_link_connect(s, s->rdns, s->fcrdns, &s->ss, 2059 &s->listener->ss); 2060 2061 smtp_filter_phase(FILTER_CONNECT, s, ss_to_text(&s->ss)); 2062 } 2063 2064 static void 2065 smtp_proceed_connected(struct smtp_session *s) 2066 { 2067 if (s->listener->flags & F_SMTPS) 2068 smtp_tls_init(s); 2069 else 2070 smtp_send_banner(s); 2071 } 2072 2073 static void 2074 smtp_send_banner(struct smtp_session *s) 2075 { 2076 smtp_reply(s, "220 %s ESMTP %s", s->smtpname, SMTPD_NAME); 2077 s->banner_sent = 1; 2078 smtp_report_link_greeting(s, s->smtpname); 2079 } 2080 2081 void 2082 smtp_enter_state(struct smtp_session *s, int newstate) 2083 { 2084 log_trace(TRACE_SMTP, "smtp: %p: %s -> %s", s, 2085 smtp_strstate(s->state), 2086 smtp_strstate(newstate)); 2087 2088 s->state = newstate; 2089 } 2090 2091 static void 2092 smtp_reply(struct smtp_session *s, char *fmt, ...) 2093 { 2094 va_list ap; 2095 int n; 2096 char buf[LINE_MAX*2], tmp[LINE_MAX*2]; 2097 2098 va_start(ap, fmt); 2099 n = vsnprintf(buf, sizeof buf, fmt, ap); 2100 va_end(ap); 2101 if (n < 0) 2102 fatalx("smtp_reply: response format error"); 2103 if (n < 4) 2104 fatalx("smtp_reply: response too short"); 2105 if (n >= (int)sizeof buf) { 2106 /* only first three bytes are used by SMTP logic, 2107 * so if _our_ reply does not fit entirely in the 2108 * buffer, it's ok to truncate. 2109 */ 2110 } 2111 2112 log_trace(TRACE_SMTP, "smtp: %p: >>> %s", s, buf); 2113 smtp_report_protocol_server(s, buf); 2114 2115 switch (buf[0]) { 2116 case '2': 2117 if (s->tx) { 2118 if (s->last_cmd == CMD_MAIL_FROM) { 2119 smtp_report_tx_begin(s, s->tx->msgid); 2120 smtp_report_tx_mail(s, s->tx->msgid, s->cmd + 10, 1); 2121 } 2122 else if (s->last_cmd == CMD_RCPT_TO) 2123 smtp_report_tx_rcpt(s, s->tx->msgid, s->cmd + 8, 1); 2124 } 2125 break; 2126 case '3': 2127 if (s->tx) { 2128 if (s->last_cmd == CMD_DATA) 2129 smtp_report_tx_data(s, s->tx->msgid, 1); 2130 } 2131 break; 2132 case '5': 2133 case '4': 2134 /* do not report smtp_tx_mail/smtp_tx_rcpt errors 2135 * if they happened outside of a transaction. 2136 */ 2137 if (s->tx) { 2138 if (s->last_cmd == CMD_MAIL_FROM) 2139 smtp_report_tx_mail(s, s->tx->msgid, 2140 s->cmd + 10, buf[0] == '4' ? -1 : 0); 2141 else if (s->last_cmd == CMD_RCPT_TO) 2142 smtp_report_tx_rcpt(s, 2143 s->tx->msgid, s->cmd + 8, buf[0] == '4' ? -1 : 0); 2144 else if (s->last_cmd == CMD_DATA && s->tx->rcptcount) 2145 smtp_report_tx_data(s, s->tx->msgid, 2146 buf[0] == '4' ? -1 : 0); 2147 } 2148 2149 if (s->flags & SF_BADINPUT) { 2150 log_info("%016"PRIx64" smtp " 2151 "bad-input result=\"%.*s\"", 2152 s->id, n, buf); 2153 } 2154 else if (s->state == STATE_AUTH_INIT) { 2155 log_info("%016"PRIx64" smtp " 2156 "failed-command " 2157 "command=\"AUTH PLAIN (...)\" result=\"%.*s\"", 2158 s->id, n, buf); 2159 } 2160 else if (s->state == STATE_AUTH_USERNAME) { 2161 log_info("%016"PRIx64" smtp " 2162 "failed-command " 2163 "command=\"AUTH LOGIN (username)\" result=\"%.*s\"", 2164 s->id, n, buf); 2165 } 2166 else if (s->state == STATE_AUTH_PASSWORD) { 2167 log_info("%016"PRIx64" smtp " 2168 "failed-command " 2169 "command=\"AUTH LOGIN (password)\" result=\"%.*s\"", 2170 s->id, n, buf); 2171 } 2172 else { 2173 strnvis(tmp, s->cmd, sizeof tmp, VIS_SAFE | VIS_CSTYLE); 2174 log_info("%016"PRIx64" smtp " 2175 "failed-command command=\"%s\" " 2176 "result=\"%.*s\"", 2177 s->id, tmp, n, buf); 2178 } 2179 break; 2180 } 2181 2182 io_xprintf(s->io, "%s\r\n", buf); 2183 } 2184 2185 static void 2186 smtp_free(struct smtp_session *s, const char * reason) 2187 { 2188 if (s->tx) { 2189 if (s->tx->msgid) 2190 smtp_tx_rollback(s->tx); 2191 smtp_tx_free(s->tx); 2192 } 2193 2194 smtp_report_link_disconnect(s); 2195 smtp_filter_end(s); 2196 2197 if (s->flags & SF_SECURE && s->listener->flags & F_SMTPS) 2198 stat_decrement("smtp.smtps", 1); 2199 if (s->flags & SF_SECURE && s->listener->flags & F_STARTTLS) 2200 stat_decrement("smtp.tls", 1); 2201 2202 io_free(s->io); 2203 free(s); 2204 2205 smtp_collect(); 2206 } 2207 2208 static int 2209 smtp_mailaddr(struct mailaddr *maddr, char *line, int mailfrom, char **args, 2210 const char *domain) 2211 { 2212 char *p, *e; 2213 2214 if (line == NULL) 2215 return (0); 2216 2217 if (*line != '<') 2218 return (0); 2219 2220 e = strchr(line, '>'); 2221 if (e == NULL) 2222 return (0); 2223 *e++ = '\0'; 2224 while (*e == ' ') 2225 e++; 2226 *args = e; 2227 2228 if (!text_to_mailaddr(maddr, line + 1)) 2229 return (0); 2230 2231 p = strchr(maddr->user, ':'); 2232 if (p != NULL) { 2233 p++; 2234 memmove(maddr->user, p, strlen(p) + 1); 2235 } 2236 2237 /* accept empty return-path in MAIL FROM, required for bounces */ 2238 if (mailfrom && maddr->user[0] == '\0' && maddr->domain[0] == '\0') 2239 return (1); 2240 2241 /* no or invalid user-part, reject */ 2242 if (maddr->user[0] == '\0' || !valid_localpart(maddr->user)) 2243 return (0); 2244 2245 /* no domain part, local user */ 2246 if (maddr->domain[0] == '\0') { 2247 (void)strlcpy(maddr->domain, domain, 2248 sizeof(maddr->domain)); 2249 } 2250 2251 if (!valid_domainpart(maddr->domain)) 2252 return (0); 2253 2254 return (1); 2255 } 2256 2257 static void 2258 smtp_auth_failure_resume(int fd, short event, void *p) 2259 { 2260 struct smtp_session *s = p; 2261 2262 smtp_reply(s, "535 Authentication failed"); 2263 smtp_enter_state(s, STATE_HELO); 2264 } 2265 2266 static void 2267 smtp_auth_failure_pause(struct smtp_session *s) 2268 { 2269 struct timeval tv; 2270 2271 tv.tv_sec = 0; 2272 tv.tv_usec = arc4random_uniform(1000000); 2273 log_trace(TRACE_SMTP, "smtp: timing-attack protection triggered, " 2274 "will defer answer for %lu microseconds", tv.tv_usec); 2275 evtimer_set(&s->pause, smtp_auth_failure_resume, s); 2276 evtimer_add(&s->pause, &tv); 2277 } 2278 2279 static int 2280 smtp_tx(struct smtp_session *s) 2281 { 2282 struct smtp_tx *tx; 2283 2284 tx = calloc(1, sizeof(*tx)); 2285 if (tx == NULL) 2286 return 0; 2287 2288 TAILQ_INIT(&tx->rcpts); 2289 2290 s->tx = tx; 2291 tx->session = s; 2292 2293 /* setup the envelope */ 2294 tx->evp.ss = s->ss; 2295 (void)strlcpy(tx->evp.tag, s->listener->tag, sizeof(tx->evp.tag)); 2296 (void)strlcpy(tx->evp.smtpname, s->smtpname, sizeof(tx->evp.smtpname)); 2297 (void)strlcpy(tx->evp.hostname, s->rdns, sizeof tx->evp.hostname); 2298 (void)strlcpy(tx->evp.helo, s->helo, sizeof(tx->evp.helo)); 2299 (void)strlcpy(tx->evp.username, s->username, sizeof(tx->evp.username)); 2300 2301 if (s->flags & SF_BOUNCE) 2302 tx->evp.flags |= EF_BOUNCE; 2303 if (s->flags & SF_AUTHENTICATED) 2304 tx->evp.flags |= EF_AUTHENTICATED; 2305 2306 if ((tx->parser = rfc5322_parser_new()) == NULL) { 2307 free(tx); 2308 return 0; 2309 } 2310 2311 return 1; 2312 } 2313 2314 static void 2315 smtp_tx_free(struct smtp_tx *tx) 2316 { 2317 struct smtp_rcpt *rcpt; 2318 2319 rfc5322_free(tx->parser); 2320 2321 while ((rcpt = TAILQ_FIRST(&tx->rcpts))) { 2322 TAILQ_REMOVE(&tx->rcpts, rcpt, entry); 2323 free(rcpt); 2324 } 2325 2326 if (tx->ofile) 2327 fclose(tx->ofile); 2328 2329 tx->session->tx = NULL; 2330 2331 free(tx); 2332 } 2333 2334 static void 2335 smtp_tx_mail_from(struct smtp_tx *tx, const char *line) 2336 { 2337 char *opt; 2338 char *copy; 2339 char tmp[SMTP_LINE_MAX]; 2340 2341 (void)strlcpy(tmp, line, sizeof tmp); 2342 copy = tmp; 2343 2344 if (smtp_mailaddr(&tx->evp.sender, copy, 1, ©, 2345 tx->session->smtpname) == 0) { 2346 smtp_reply(tx->session, "553 %s Sender address syntax error", 2347 esc_code(ESC_STATUS_PERMFAIL, ESC_OTHER_ADDRESS_STATUS)); 2348 smtp_tx_free(tx); 2349 return; 2350 } 2351 2352 while ((opt = strsep(©, " "))) { 2353 if (*opt == '\0') 2354 continue; 2355 2356 if (strncasecmp(opt, "AUTH=", 5) == 0) 2357 log_debug("debug: smtp: AUTH in MAIL FROM command"); 2358 else if (strncasecmp(opt, "SIZE=", 5) == 0) 2359 log_debug("debug: smtp: SIZE in MAIL FROM command"); 2360 else if (strcasecmp(opt, "BODY=7BIT") == 0) 2361 /* XXX only for this transaction */ 2362 tx->session->flags &= ~SF_8BITMIME; 2363 else if (strcasecmp(opt, "BODY=8BITMIME") == 0) 2364 ; 2365 else if (ADVERTISE_EXT_DSN(tx->session) && strncasecmp(opt, "RET=", 4) == 0) { 2366 opt += 4; 2367 if (strcasecmp(opt, "HDRS") == 0) 2368 tx->evp.dsn_ret = DSN_RETHDRS; 2369 else if (strcasecmp(opt, "FULL") == 0) 2370 tx->evp.dsn_ret = DSN_RETFULL; 2371 } else if (ADVERTISE_EXT_DSN(tx->session) && strncasecmp(opt, "ENVID=", 6) == 0) { 2372 opt += 6; 2373 if (strlcpy(tx->evp.dsn_envid, opt, sizeof(tx->evp.dsn_envid)) 2374 >= sizeof(tx->evp.dsn_envid)) { 2375 smtp_reply(tx->session, 2376 "503 %s %s: option too large, truncated: %s", 2377 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS), 2378 esc_description(ESC_INVALID_COMMAND_ARGUMENTS), opt); 2379 smtp_tx_free(tx); 2380 return; 2381 } 2382 } else { 2383 smtp_reply(tx->session, "503 %s %s: Unsupported option %s", 2384 esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS), 2385 esc_description(ESC_INVALID_COMMAND_ARGUMENTS), opt); 2386 smtp_tx_free(tx); 2387 return; 2388 } 2389 } 2390 2391 /* only check sendertable if defined and user has authenticated */ 2392 if (tx->session->flags & SF_AUTHENTICATED && 2393 tx->session->listener->sendertable[0]) { 2394 m_create(p_lka, IMSG_SMTP_CHECK_SENDER, 0, 0, -1); 2395 m_add_id(p_lka, tx->session->id); 2396 m_add_string(p_lka, tx->session->listener->sendertable); 2397 m_add_string(p_lka, tx->session->username); 2398 m_add_mailaddr(p_lka, &tx->evp.sender); 2399 m_close(p_lka); 2400 tree_xset(&wait_lka_mail, tx->session->id, tx->session); 2401 } 2402 else 2403 smtp_tx_create_message(tx); 2404 } 2405 2406 static void 2407 smtp_tx_create_message(struct smtp_tx *tx) 2408 { 2409 m_create(p_queue, IMSG_SMTP_MESSAGE_CREATE, 0, 0, -1); 2410 m_add_id(p_queue, tx->session->id); 2411 m_close(p_queue); 2412 tree_xset(&wait_queue_msg, tx->session->id, tx->session); 2413 } 2414 2415 static void 2416 smtp_tx_rcpt_to(struct smtp_tx *tx, const char *line) 2417 { 2418 char *opt, *p; 2419 char *copy; 2420 char tmp[SMTP_LINE_MAX]; 2421 2422 (void)strlcpy(tmp, line, sizeof tmp); 2423 copy = tmp; 2424 2425 if (tx->rcptcount >= env->sc_session_max_rcpt) { 2426 smtp_reply(tx->session, "451 %s %s: Too many recipients", 2427 esc_code(ESC_STATUS_TEMPFAIL, ESC_TOO_MANY_RECIPIENTS), 2428 esc_description(ESC_TOO_MANY_RECIPIENTS)); 2429 return; 2430 } 2431 2432 if (smtp_mailaddr(&tx->evp.rcpt, copy, 0, ©, 2433 tx->session->smtpname) == 0) { 2434 smtp_reply(tx->session, 2435 "501 %s Recipient address syntax error", 2436 esc_code(ESC_STATUS_PERMFAIL, 2437 ESC_BAD_DESTINATION_MAILBOX_ADDRESS_SYNTAX)); 2438 return; 2439 } 2440 2441 while ((opt = strsep(©, " "))) { 2442 if (*opt == '\0') 2443 continue; 2444 2445 if (ADVERTISE_EXT_DSN(tx->session) && strncasecmp(opt, "NOTIFY=", 7) == 0) { 2446 opt += 7; 2447 while ((p = strsep(&opt, ","))) { 2448 if (strcasecmp(p, "SUCCESS") == 0) 2449 tx->evp.dsn_notify |= DSN_SUCCESS; 2450 else if (strcasecmp(p, "FAILURE") == 0) 2451 tx->evp.dsn_notify |= DSN_FAILURE; 2452 else if (strcasecmp(p, "DELAY") == 0) 2453 tx->evp.dsn_notify |= DSN_DELAY; 2454 else if (strcasecmp(p, "NEVER") == 0) 2455 tx->evp.dsn_notify |= DSN_NEVER; 2456 } 2457 2458 if (tx->evp.dsn_notify & DSN_NEVER && 2459 tx->evp.dsn_notify & (DSN_SUCCESS | DSN_FAILURE | 2460 DSN_DELAY)) { 2461 smtp_reply(tx->session, 2462 "553 NOTIFY option NEVER cannot be" 2463 " combined with other options"); 2464 return; 2465 } 2466 } else if (ADVERTISE_EXT_DSN(tx->session) && strncasecmp(opt, "ORCPT=", 6) == 0) { 2467 opt += 6; 2468 2469 if (strncasecmp(opt, "rfc822;", 7) == 0) 2470 opt += 7; 2471 2472 if (!text_to_mailaddr(&tx->evp.dsn_orcpt, opt) || 2473 !valid_localpart(tx->evp.dsn_orcpt.user) || 2474 (strlen(tx->evp.dsn_orcpt.domain) != 0 && 2475 !valid_domainpart(tx->evp.dsn_orcpt.domain))) { 2476 smtp_reply(tx->session, 2477 "553 ORCPT address syntax error"); 2478 return; 2479 } 2480 } else { 2481 smtp_reply(tx->session, "503 Unsupported option %s", opt); 2482 return; 2483 } 2484 } 2485 2486 m_create(p_lka, IMSG_SMTP_EXPAND_RCPT, 0, 0, -1); 2487 m_add_id(p_lka, tx->session->id); 2488 m_add_envelope(p_lka, &tx->evp); 2489 m_close(p_lka); 2490 tree_xset(&wait_lka_rcpt, tx->session->id, tx->session); 2491 } 2492 2493 static void 2494 smtp_tx_open_message(struct smtp_tx *tx) 2495 { 2496 m_create(p_queue, IMSG_SMTP_MESSAGE_OPEN, 0, 0, -1); 2497 m_add_id(p_queue, tx->session->id); 2498 m_add_msgid(p_queue, tx->msgid); 2499 m_close(p_queue); 2500 tree_xset(&wait_queue_fd, tx->session->id, tx->session); 2501 } 2502 2503 static void 2504 smtp_tx_commit(struct smtp_tx *tx) 2505 { 2506 m_create(p_queue, IMSG_SMTP_MESSAGE_COMMIT, 0, 0, -1); 2507 m_add_id(p_queue, tx->session->id); 2508 m_add_msgid(p_queue, tx->msgid); 2509 m_close(p_queue); 2510 tree_xset(&wait_queue_commit, tx->session->id, tx->session); 2511 smtp_filter_data_end(tx->session); 2512 } 2513 2514 static void 2515 smtp_tx_rollback(struct smtp_tx *tx) 2516 { 2517 m_create(p_queue, IMSG_SMTP_MESSAGE_ROLLBACK, 0, 0, -1); 2518 m_add_msgid(p_queue, tx->msgid); 2519 m_close(p_queue); 2520 smtp_report_tx_rollback(tx->session, tx->msgid); 2521 smtp_report_tx_reset(tx->session, tx->msgid); 2522 smtp_filter_data_end(tx->session); 2523 } 2524 2525 static int 2526 smtp_tx_dataline(struct smtp_tx *tx, const char *line) 2527 { 2528 struct rfc5322_result res; 2529 int r; 2530 2531 log_trace(TRACE_SMTP, "<<< [MSG] %s", line); 2532 2533 if (!strcmp(line, ".")) { 2534 smtp_report_protocol_client(tx->session, "."); 2535 log_trace(TRACE_SMTP, "<<< [EOM]"); 2536 if (tx->error) 2537 return 1; 2538 line = NULL; 2539 } 2540 else { 2541 /* ignore data line if an error is set */ 2542 if (tx->error) 2543 return 0; 2544 2545 /* escape lines starting with a '.' */ 2546 if (line[0] == '.') 2547 line += 1; 2548 } 2549 2550 if (rfc5322_push(tx->parser, line) == -1) { 2551 log_warnx("failed to push dataline"); 2552 tx->error = TX_ERROR_INTERNAL; 2553 return 0; 2554 } 2555 2556 for(;;) { 2557 r = rfc5322_next(tx->parser, &res); 2558 switch (r) { 2559 case -1: 2560 if (errno == ENOMEM) 2561 tx->error = TX_ERROR_INTERNAL; 2562 else 2563 tx->error = TX_ERROR_MALFORMED; 2564 return 0; 2565 2566 case RFC5322_NONE: 2567 /* Need more data */ 2568 return 0; 2569 2570 case RFC5322_HEADER_START: 2571 /* ignore bcc */ 2572 if (!strcasecmp("Bcc", res.hdr)) 2573 continue; 2574 2575 if (!strcasecmp("To", res.hdr) || 2576 !strcasecmp("Cc", res.hdr) || 2577 !strcasecmp("From", res.hdr)) { 2578 rfc5322_unfold_header(tx->parser); 2579 continue; 2580 } 2581 2582 if (!strcasecmp("Received", res.hdr)) { 2583 if (++tx->rcvcount >= MAX_HOPS_COUNT) { 2584 log_warnx("warn: loop detected"); 2585 tx->error = TX_ERROR_LOOP; 2586 return 0; 2587 } 2588 } 2589 else if (!tx->has_date && !strcasecmp("Date", res.hdr)) 2590 tx->has_date = 1; 2591 else if (!tx->has_message_id && 2592 !strcasecmp("Message-Id", res.hdr)) 2593 tx->has_message_id = 1; 2594 2595 smtp_message_printf(tx, "%s:%s\n", res.hdr, res.value); 2596 break; 2597 2598 case RFC5322_HEADER_CONT: 2599 2600 if (!strcasecmp("Bcc", res.hdr) || 2601 !strcasecmp("To", res.hdr) || 2602 !strcasecmp("Cc", res.hdr) || 2603 !strcasecmp("From", res.hdr)) 2604 continue; 2605 2606 smtp_message_printf(tx, "%s\n", res.value); 2607 break; 2608 2609 case RFC5322_HEADER_END: 2610 if (!strcasecmp("To", res.hdr) || 2611 !strcasecmp("Cc", res.hdr) || 2612 !strcasecmp("From", res.hdr)) 2613 header_domain_append_callback(tx, res.hdr, 2614 res.value); 2615 break; 2616 2617 case RFC5322_END_OF_HEADERS: 2618 if (tx->session->listener->local || 2619 tx->session->listener->port == 587) { 2620 2621 if (!tx->has_date) { 2622 log_debug("debug: %p: adding Date", tx); 2623 smtp_message_printf(tx, "Date: %s\n", 2624 time_to_text(tx->time)); 2625 } 2626 2627 if (!tx->has_message_id) { 2628 log_debug("debug: %p: adding Message-ID", tx); 2629 smtp_message_printf(tx, 2630 "Message-ID: <%016"PRIx64"@%s>\n", 2631 generate_uid(), 2632 tx->session->listener->hostname); 2633 } 2634 } 2635 break; 2636 2637 case RFC5322_BODY_START: 2638 case RFC5322_BODY: 2639 smtp_message_printf(tx, "%s\n", res.value); 2640 break; 2641 2642 case RFC5322_END_OF_MESSAGE: 2643 return 1; 2644 2645 default: 2646 fatalx("%s", __func__); 2647 } 2648 } 2649 } 2650 2651 static int 2652 smtp_tx_filtered_dataline(struct smtp_tx *tx, const char *line) 2653 { 2654 if (!strcmp(line, ".")) 2655 line = NULL; 2656 else { 2657 /* ignore data line if an error is set */ 2658 if (tx->error) 2659 return 0; 2660 } 2661 io_printf(tx->filter, "%s\n", line ? line : "."); 2662 return line ? 0 : 1; 2663 } 2664 2665 static void 2666 smtp_tx_eom(struct smtp_tx *tx) 2667 { 2668 smtp_filter_phase(FILTER_COMMIT, tx->session, NULL); 2669 } 2670 2671 static int 2672 smtp_message_fd(struct smtp_tx *tx, int fd) 2673 { 2674 struct smtp_session *s; 2675 2676 s = tx->session; 2677 2678 log_debug("smtp: %p: message fd %d", s, fd); 2679 2680 if ((tx->ofile = fdopen(fd, "w")) == NULL) { 2681 close(fd); 2682 smtp_reply(s, "421 %s Temporary Error", 2683 esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS)); 2684 smtp_enter_state(s, STATE_QUIT); 2685 return 0; 2686 } 2687 return 1; 2688 } 2689 2690 static void 2691 filter_session_io(struct io *io, int evt, void *arg) 2692 { 2693 struct smtp_tx*tx = arg; 2694 char*line = NULL; 2695 ssize_t len; 2696 2697 log_trace(TRACE_IO, "filter session io (smtp): %p: %s %s", tx, io_strevent(evt), 2698 io_strio(io)); 2699 2700 switch (evt) { 2701 case IO_DATAIN: 2702 nextline: 2703 line = io_getline(tx->filter, &len); 2704 /* No complete line received */ 2705 if (line == NULL) 2706 return; 2707 2708 if (smtp_tx_dataline(tx, line)) { 2709 smtp_tx_eom(tx); 2710 return; 2711 } 2712 2713 goto nextline; 2714 } 2715 } 2716 2717 static void 2718 smtp_filter_fd(struct smtp_tx *tx, int fd) 2719 { 2720 struct smtp_session *s; 2721 2722 s = tx->session; 2723 2724 log_debug("smtp: %p: filter fd %d", s, fd); 2725 2726 tx->filter = io_new(); 2727 io_set_fd(tx->filter, fd); 2728 io_set_callback(tx->filter, filter_session_io, tx); 2729 } 2730 2731 static void 2732 smtp_message_begin(struct smtp_tx *tx) 2733 { 2734 struct smtp_session *s; 2735 int (*m_printf)(struct smtp_tx *, const char *, ...); 2736 2737 m_printf = smtp_message_printf; 2738 if (tx->filter) 2739 m_printf = smtp_filter_printf; 2740 2741 s = tx->session; 2742 2743 log_debug("smtp: %p: message begin", s); 2744 2745 smtp_reply(s, "354 Enter mail, end with \".\"" 2746 " on a line by itself"); 2747 2748 if (s->junk || (s->tx && s->tx->junk)) 2749 m_printf(tx, "X-Spam: Yes\n"); 2750 2751 m_printf(tx, "Received: "); 2752 if (!(s->listener->flags & F_MASK_SOURCE)) { 2753 m_printf(tx, "from %s (%s %s%s%s)", 2754 s->helo, 2755 s->rdns, 2756 s->ss.ss_family == AF_INET6 ? "" : "[", 2757 ss_to_text(&s->ss), 2758 s->ss.ss_family == AF_INET6 ? "" : "]"); 2759 } 2760 m_printf(tx, "\n\tby %s (%s) with %sSMTP%s%s id %08x", 2761 s->smtpname, 2762 SMTPD_NAME, 2763 s->flags & SF_EHLO ? "E" : "", 2764 s->flags & SF_SECURE ? "S" : "", 2765 s->flags & SF_AUTHENTICATED ? "A" : "", 2766 tx->msgid); 2767 2768 if (s->flags & SF_SECURE) { 2769 m_printf(tx, " (%s:%s:%d:%s)", 2770 tls_conn_version(io_tls(s->io)), 2771 tls_conn_cipher(io_tls(s->io)), 2772 tls_conn_cipher_strength(io_tls(s->io)), 2773 (s->flags & SF_VERIFIED) ? "YES" : "NO"); 2774 2775 if (s->listener->flags & F_RECEIVEDAUTH) { 2776 m_printf(tx, " auth=%s", 2777 s->username[0] ? "yes" : "no"); 2778 if (s->username[0]) 2779 m_printf(tx, " user=%s", s->username); 2780 } 2781 } 2782 2783 if (tx->rcptcount == 1) { 2784 m_printf(tx, "\n\tfor <%s@%s>", 2785 tx->evp.rcpt.user, 2786 tx->evp.rcpt.domain); 2787 } 2788 2789 m_printf(tx, ";\n\t%s\n", time_to_text(time(&tx->time))); 2790 2791 smtp_enter_state(s, STATE_BODY); 2792 } 2793 2794 static void 2795 smtp_message_end(struct smtp_tx *tx) 2796 { 2797 struct smtp_session *s; 2798 2799 s = tx->session; 2800 2801 log_debug("debug: %p: end of message, error=%d", s, tx->error); 2802 2803 fclose(tx->ofile); 2804 tx->ofile = NULL; 2805 2806 switch(tx->error) { 2807 case TX_OK: 2808 smtp_tx_commit(tx); 2809 return; 2810 2811 case TX_ERROR_SIZE: 2812 smtp_reply(s, "554 %s %s: Transaction failed, message too big", 2813 esc_code(ESC_STATUS_PERMFAIL, ESC_MESSAGE_TOO_BIG_FOR_SYSTEM), 2814 esc_description(ESC_MESSAGE_TOO_BIG_FOR_SYSTEM)); 2815 break; 2816 2817 case TX_ERROR_LOOP: 2818 smtp_reply(s, "500 %s %s: Loop detected", 2819 esc_code(ESC_STATUS_PERMFAIL, ESC_ROUTING_LOOP_DETECTED), 2820 esc_description(ESC_ROUTING_LOOP_DETECTED)); 2821 break; 2822 2823 case TX_ERROR_MALFORMED: 2824 smtp_reply(s, "550 %s %s: Message is not RFC 2822 compliant", 2825 esc_code(ESC_STATUS_PERMFAIL, ESC_DELIVERY_NOT_AUTHORIZED_MESSAGE_REFUSED), 2826 esc_description(ESC_DELIVERY_NOT_AUTHORIZED_MESSAGE_REFUSED)); 2827 break; 2828 2829 case TX_ERROR_IO: 2830 case TX_ERROR_RESOURCES: 2831 smtp_reply(s, "421 %s Temporary Error", 2832 esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS)); 2833 break; 2834 2835 default: 2836 /* fatal? */ 2837 smtp_reply(s, "421 Internal server error"); 2838 } 2839 2840 smtp_tx_rollback(tx); 2841 smtp_tx_free(tx); 2842 smtp_enter_state(s, STATE_HELO); 2843 } 2844 2845 static int 2846 smtp_filter_printf(struct smtp_tx *tx, const char *fmt, ...) 2847 { 2848 va_list ap; 2849 int len; 2850 2851 if (tx->error) 2852 return -1; 2853 2854 va_start(ap, fmt); 2855 len = io_vprintf(tx->filter, fmt, ap); 2856 va_end(ap); 2857 2858 if (len < 0) { 2859 log_warn("smtp-in: session %016"PRIx64": vfprintf", tx->session->id); 2860 tx->error = TX_ERROR_IO; 2861 } 2862 else 2863 tx->odatalen += len; 2864 2865 return len; 2866 } 2867 2868 static int 2869 smtp_message_printf(struct smtp_tx *tx, const char *fmt, ...) 2870 { 2871 va_list ap; 2872 int len; 2873 2874 if (tx->error) 2875 return -1; 2876 2877 va_start(ap, fmt); 2878 len = vfprintf(tx->ofile, fmt, ap); 2879 va_end(ap); 2880 2881 if (len == -1) { 2882 log_warn("smtp-in: session %016"PRIx64": vfprintf", tx->session->id); 2883 tx->error = TX_ERROR_IO; 2884 } 2885 else 2886 tx->odatalen += len; 2887 2888 return len; 2889 } 2890 2891 #define CASE(x) case x : return #x 2892 2893 const char * 2894 smtp_strstate(int state) 2895 { 2896 static char buf[32]; 2897 2898 switch (state) { 2899 CASE(STATE_NEW); 2900 CASE(STATE_CONNECTED); 2901 CASE(STATE_TLS); 2902 CASE(STATE_HELO); 2903 CASE(STATE_AUTH_INIT); 2904 CASE(STATE_AUTH_USERNAME); 2905 CASE(STATE_AUTH_PASSWORD); 2906 CASE(STATE_AUTH_FINALIZE); 2907 CASE(STATE_BODY); 2908 CASE(STATE_QUIT); 2909 default: 2910 (void)snprintf(buf, sizeof(buf), "STATE_??? (%d)", state); 2911 return (buf); 2912 } 2913 } 2914 2915 2916 static void 2917 smtp_report_link_connect(struct smtp_session *s, const char *rdns, int fcrdns, 2918 const struct sockaddr_storage *ss_src, 2919 const struct sockaddr_storage *ss_dest) 2920 { 2921 if (! SESSION_FILTERED(s)) 2922 return; 2923 2924 report_smtp_link_connect("smtp-in", s->id, rdns, fcrdns, ss_src, ss_dest); 2925 } 2926 2927 static void 2928 smtp_report_link_greeting(struct smtp_session *s, 2929 const char *domain) 2930 { 2931 if (! SESSION_FILTERED(s)) 2932 return; 2933 2934 report_smtp_link_greeting("smtp-in", s->id, domain); 2935 } 2936 2937 static void 2938 smtp_report_link_identify(struct smtp_session *s, const char *method, const char *identity) 2939 { 2940 if (! SESSION_FILTERED(s)) 2941 return; 2942 2943 report_smtp_link_identify("smtp-in", s->id, method, identity); 2944 } 2945 2946 static void 2947 smtp_report_link_tls(struct smtp_session *s, const char *ssl) 2948 { 2949 if (! SESSION_FILTERED(s)) 2950 return; 2951 2952 report_smtp_link_tls("smtp-in", s->id, ssl); 2953 } 2954 2955 static void 2956 smtp_report_link_disconnect(struct smtp_session *s) 2957 { 2958 if (! SESSION_FILTERED(s)) 2959 return; 2960 2961 report_smtp_link_disconnect("smtp-in", s->id); 2962 } 2963 2964 static void 2965 smtp_report_link_auth(struct smtp_session *s, const char *user, const char *result) 2966 { 2967 if (! SESSION_FILTERED(s)) 2968 return; 2969 2970 report_smtp_link_auth("smtp-in", s->id, user, result); 2971 } 2972 2973 static void 2974 smtp_report_tx_reset(struct smtp_session *s, uint32_t msgid) 2975 { 2976 if (! SESSION_FILTERED(s)) 2977 return; 2978 2979 report_smtp_tx_reset("smtp-in", s->id, msgid); 2980 } 2981 2982 static void 2983 smtp_report_tx_begin(struct smtp_session *s, uint32_t msgid) 2984 { 2985 if (! SESSION_FILTERED(s)) 2986 return; 2987 2988 report_smtp_tx_begin("smtp-in", s->id, msgid); 2989 } 2990 2991 static void 2992 smtp_report_tx_mail(struct smtp_session *s, uint32_t msgid, const char *address, int ok) 2993 { 2994 char mailaddr[SMTPD_MAXMAILADDRSIZE]; 2995 char *p; 2996 2997 if (! SESSION_FILTERED(s)) 2998 return; 2999 3000 if ((p = strchr(address, '<')) == NULL) 3001 return; 3002 (void)strlcpy(mailaddr, p + 1, sizeof mailaddr); 3003 if ((p = strchr(mailaddr, '>')) == NULL) 3004 return; 3005 *p = '\0'; 3006 3007 report_smtp_tx_mail("smtp-in", s->id, msgid, mailaddr, ok); 3008 } 3009 3010 static void 3011 smtp_report_tx_rcpt(struct smtp_session *s, uint32_t msgid, const char *address, int ok) 3012 { 3013 char mailaddr[SMTPD_MAXMAILADDRSIZE]; 3014 char *p; 3015 3016 if (! SESSION_FILTERED(s)) 3017 return; 3018 3019 if ((p = strchr(address, '<')) == NULL) 3020 return; 3021 (void)strlcpy(mailaddr, p + 1, sizeof mailaddr); 3022 if ((p = strchr(mailaddr, '>')) == NULL) 3023 return; 3024 *p = '\0'; 3025 3026 report_smtp_tx_rcpt("smtp-in", s->id, msgid, mailaddr, ok); 3027 } 3028 3029 static void 3030 smtp_report_tx_envelope(struct smtp_session *s, uint32_t msgid, uint64_t evpid) 3031 { 3032 if (! SESSION_FILTERED(s)) 3033 return; 3034 3035 report_smtp_tx_envelope("smtp-in", s->id, msgid, evpid); 3036 } 3037 3038 static void 3039 smtp_report_tx_data(struct smtp_session *s, uint32_t msgid, int ok) 3040 { 3041 if (! SESSION_FILTERED(s)) 3042 return; 3043 3044 report_smtp_tx_data("smtp-in", s->id, msgid, ok); 3045 } 3046 3047 static void 3048 smtp_report_tx_commit(struct smtp_session *s, uint32_t msgid, size_t msgsz) 3049 { 3050 if (! SESSION_FILTERED(s)) 3051 return; 3052 3053 report_smtp_tx_commit("smtp-in", s->id, msgid, msgsz); 3054 } 3055 3056 static void 3057 smtp_report_tx_rollback(struct smtp_session *s, uint32_t msgid) 3058 { 3059 if (! SESSION_FILTERED(s)) 3060 return; 3061 3062 report_smtp_tx_rollback("smtp-in", s->id, msgid); 3063 } 3064 3065 static void 3066 smtp_report_protocol_client(struct smtp_session *s, const char *command) 3067 { 3068 if (! SESSION_FILTERED(s)) 3069 return; 3070 3071 report_smtp_protocol_client("smtp-in", s->id, command); 3072 } 3073 3074 static void 3075 smtp_report_protocol_server(struct smtp_session *s, const char *response) 3076 { 3077 if (! SESSION_FILTERED(s)) 3078 return; 3079 3080 report_smtp_protocol_server("smtp-in", s->id, response); 3081 } 3082 3083 static void 3084 smtp_report_filter_response(struct smtp_session *s, int phase, int response, const char *param) 3085 { 3086 if (! SESSION_FILTERED(s)) 3087 return; 3088 3089 report_smtp_filter_response("smtp-in", s->id, phase, response, param); 3090 } 3091 3092 static void 3093 smtp_report_timeout(struct smtp_session *s) 3094 { 3095 if (! SESSION_FILTERED(s)) 3096 return; 3097 3098 report_smtp_timeout("smtp-in", s->id); 3099 } 3100