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