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