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