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