1 /* $NetBSD: postscreen_smtpd.c,v 1.1.1.3 2013/09/25 19:06:33 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* postscreen_smtpd 3 6 /* SUMMARY 7 /* postscreen built-in SMTP server engine 8 /* SYNOPSIS 9 /* #include <postscreen.h> 10 /* 11 /* void psc_smtpd_pre_jail_init(void) 12 /* 13 /* void psc_smtpd_init(void) 14 /* 15 /* void psc_smtpd_tests(state) 16 /* PSC_STATE *state; 17 /* 18 /* void PSC_SMTPD_X21(state, final_reply) 19 /* PSC_STATE *state; 20 /* const char *final_reply; 21 /* DESCRIPTION 22 /* psc_smtpd_pre_jail_init() performs one-time per-process 23 /* initialization during the "before chroot" execution phase. 24 /* 25 /* psc_smtpd_init() performs one-time per-process initialization. 26 /* 27 /* psc_smtpd_tests() starts up an SMTP server engine for deep 28 /* protocol tests and for collecting helo/sender/recipient 29 /* information. 30 /* 31 /* PSC_SMTPD_X21() redirects the SMTP client to an SMTP server 32 /* engine, which sends the specified final reply at the first 33 /* legitimate opportunity without doing any protocol tests. 34 /* 35 /* Unlike the Postfix SMTP server, this engine does not announce 36 /* PIPELINING support. This exposes spambots that pipeline 37 /* their commands anyway. Like the Postfix SMTP server, this 38 /* engine will accept input with bare newline characters. To 39 /* pass the "pipelining" and "bare newline" test, the client 40 /* has to properly speak SMTP all the way to the RCPT TO 41 /* command. These tests fail if the client violates the protocol 42 /* at any stage. 43 /* 44 /* No support is announced for AUTH, XCLIENT or XFORWARD. 45 /* Clients that need this should be whitelisted or should talk 46 /* directly to the submission service. 47 /* 48 /* The engine rejects RCPT TO and VRFY commands with the 49 /* state->rcpt_reply response which depends on program history, 50 /* rejects ETRN with a generic response, and closes the 51 /* connection after QUIT. 52 /* 53 /* Since this engine defers or rejects all non-junk commands, 54 /* there is no point maintaining separate counters for "error" 55 /* commands and "junk" commands. Instead, the engine maintains 56 /* a per-session command counter, and terminates the session 57 /* with a 421 reply when the command count exceeds the limit. 58 /* 59 /* We limit the command count, as well as the total time to 60 /* receive a command. This limits the time per client more 61 /* effectively than would be possible with read() timeouts. 62 /* 63 /* There is no concern about getting blocked on output. The 64 /* psc_send() routine uses non-blocking output, and discards 65 /* output that the client is not willing to receive. 66 /* PROTOCOL INSPECTION VERSUS CONTENT INSPECTION 67 /* The goal of postscreen is to keep spambots away from Postfix. 68 /* To recognize spambots, postscreen measures properties of 69 /* the client IP address and of the client SMTP protocol 70 /* implementation. These client properties don't change with 71 /* each delivery attempt. Therefore it is possible to make a 72 /* long-term decision after a single measurement. For example, 73 /* allow a good client to skip the DNSBL test for 24 hours, 74 /* or to skip the pipelining test for one week. 75 /* 76 /* If postscreen were to measure properties of message content 77 /* (MIME compliance, etc.) then it would measure properties 78 /* that may change with each delivery attempt. Here, it would 79 /* be wrong to make a long-term decision after a single 80 /* measurement. Instead, postscreen would need to develop a 81 /* ranking based on the content of multiple messages from the 82 /* same client. 83 /* 84 /* Many spambots avoid spamming the same site repeatedly. 85 /* Thus, postscreen must make decisions after a single 86 /* measurement. Message content is not a good indicator for 87 /* making long-term decisions after single measurements, and 88 /* that is why postscreen does not inspect message content. 89 /* REJECTING RCPT TO VERSUS SENDING LIVE SOCKETS TO SMTPD(8) 90 /* When post-handshake protocol tests are enabled, postscreen 91 /* rejects the RCPT TO command from a good client, and forces 92 /* it to deliver mail in a later session. This is why 93 /* post-handshake protocol tests have a longer expiration time 94 /* than pre-handshake tests. 95 /* 96 /* Instead, postscreen could send the network socket to smtpd(8) 97 /* and ship the session history (including TLS and other SMTP 98 /* or non-SMTP attributes) as auxiliary data. The Postfix SMTP 99 /* server would then use new code to replay the session history, 100 /* and would use existing code to validate the client, helo, 101 /* sender and recipient address. 102 /* 103 /* Such an approach would increase the implementation and 104 /* maintenance effort, because: 105 /* 106 /* 1) New replay code would be needed in smtpd(8), such that 107 /* the HELO, EHLO, and MAIL command handlers can delay their 108 /* error responses until the RCPT TO reply. 109 /* 110 /* 2) postscreen(8) would have to implement more of smtpd(8)'s 111 /* syntax checks, to avoid confusing delayed "syntax error" 112 /* and other error responses syntax error responses while 113 /* replaying history. 114 /* 115 /* 3) New code would be needed in postscreen(8) and smtpd(8) 116 /* to send and receive the session history (including TLS and 117 /* other SMTP or non-SMTP attributes) as auxiliary data while 118 /* sending the network socket from postscreen(8) to smtpd(8). 119 /* REJECTING RCPT TO VERSUS PROXYING LIVE SESSIONS TO SMTPD(8) 120 /* An alternative would be to proxy the session history to a 121 /* real Postfix SMTP process, presumably passing TLS and other 122 /* attributes via an extended XCLIENT implementation. That 123 /* would require all the work described in 2) above, plus 124 /* duplication of all the features of the smtpd(8) TLS engine, 125 /* plus additional XCLIENT support for a lot more attributes. 126 /* LICENSE 127 /* .ad 128 /* .fi 129 /* The Secure Mailer license must be distributed with this software. 130 /* AUTHOR(S) 131 /* Wietse Venema 132 /* IBM T.J. Watson Research 133 /* P.O. Box 704 134 /* Yorktown Heights, NY 10598, USA 135 /*--*/ 136 137 /* System library. */ 138 139 #include <sys_defs.h> 140 #include <string.h> 141 #include <ctype.h> 142 143 #ifdef STRCASECMP_IN_STRINGS_H 144 #include <strings.h> 145 #endif 146 147 /* Utility library. */ 148 149 #include <msg.h> 150 #include <stringops.h> 151 #include <mymalloc.h> 152 #include <iostuff.h> 153 #include <vstring.h> 154 155 /* Global library. */ 156 157 #include <mail_params.h> 158 #include <mail_proto.h> 159 #include <is_header.h> 160 #include <string_list.h> 161 #include <maps.h> 162 #include <ehlo_mask.h> 163 #include <lex_822.h> 164 165 /* TLS library. */ 166 167 #include <tls.h> 168 169 /* Application-specific. */ 170 171 #include <postscreen.h> 172 173 /* 174 * Plan for future body processing. See smtp-sink.c. For now, we have no 175 * per-session push-back except for the single-character push-back that 176 * VSTREAM guarantees after we read one character. 177 */ 178 #define PSC_SMTPD_HAVE_PUSH_BACK(state) (0) 179 #define PSC_SMTPD_PUSH_BACK_CHAR(state, ch) \ 180 vstream_ungetc((state)->smtp_client_stream, (ch)) 181 #define PSC_SMTPD_NEXT_CHAR(state) \ 182 VSTREAM_GETC((state)->smtp_client_stream) 183 184 #define PSC_SMTPD_BUFFER_EMPTY(state) \ 185 (!PSC_SMTPD_HAVE_PUSH_BACK(state) \ 186 && vstream_peek((state)->smtp_client_stream) <= 0) 187 188 #define PSC_SMTPD_PEEK_DATA(state) \ 189 vstream_peek_data((state)->smtp_client_stream) 190 #define PSC_SMTPD_PEEK_LEN(state) \ 191 vstream_peek((state)->smtp_client_stream) 192 193 /* 194 * Dynamic reply strings. To minimize overhead we format these once. 195 */ 196 static char *psc_smtpd_greeting; /* smtp banner */ 197 static char *psc_smtpd_helo_reply; /* helo reply */ 198 static char *psc_smtpd_ehlo_reply_plain;/* multi-line ehlo reply, non-TLS */ 199 static char *psc_smtpd_ehlo_reply_tls; /* multi-line ehlo reply, with TLS */ 200 static char *psc_smtpd_timeout_reply; /* timeout reply */ 201 static char *psc_smtpd_421_reply; /* generic final_reply value */ 202 203 /* 204 * Forward declaration, needed by PSC_CLEAR_EVENT_REQUEST. 205 */ 206 static void psc_smtpd_time_event(int, char *); 207 static void psc_smtpd_read_event(int, char *); 208 209 /* 210 * Encapsulation. The STARTTLS, EHLO and AUTH command handlers temporarily 211 * suspend SMTP command events, send an asynchronous proxy request, and 212 * resume SMTP command events after receiving the asynchrounous proxy 213 * response (the EHLO handler must asynchronously talk to the auth server 214 * before it can announce the SASL mechanism list; the list can depend on 215 * the client IP address and on the presence on TLS encryption). 216 */ 217 #define PSC_RESUME_SMTP_CMD_EVENTS(state) do { \ 218 PSC_READ_EVENT_REQUEST2(vstream_fileno((state)->smtp_client_stream), \ 219 psc_smtpd_read_event, psc_smtpd_time_event, \ 220 (char *) (state), PSC_EFF_CMD_TIME_LIMIT); \ 221 if (!PSC_SMTPD_BUFFER_EMPTY(state)) \ 222 psc_smtpd_read_event(EVENT_READ, (char *) state); \ 223 } while (0) 224 225 #define PSC_SUSPEND_SMTP_CMD_EVENTS(state) \ 226 PSC_CLEAR_EVENT_REQUEST(vstream_fileno((state)->smtp_client_stream), \ 227 psc_smtpd_time_event, (char *) (state)); 228 229 /* 230 * Make control characters and other non-text visible. 231 */ 232 #define PSC_SMTPD_ESCAPE_TEXT(dest, src, src_len, max_len) do { \ 233 ssize_t _s_len = (src_len); \ 234 ssize_t _m_len = (max_len); \ 235 (void) escape((dest), (src), _s_len < _m_len ? _s_len : _m_len); \ 236 } while (0) 237 238 /* 239 * Command parser support. 240 */ 241 #define PSC_SMTPD_NEXT_TOKEN(ptr) mystrtok(&(ptr), " ") 242 243 /* 244 * EHLO keyword filter 245 */ 246 static MAPS *psc_ehlo_discard_maps; 247 static int psc_ehlo_discard_mask; 248 249 /* 250 * Command editing filter. 251 */ 252 static DICT *psc_cmd_filter; 253 254 /* 255 * Encapsulation. We must not forget turn off input/timer events when we 256 * terminate the SMTP protocol engine. 257 * 258 * It would be safer to turn off input/timer events after each event, and to 259 * turn on input/timer events again when we want more input. But experience 260 * with the Postfix smtp-source and smtp-sink tools shows that this would 261 * noticeably increase the run-time cost. 262 */ 263 #define PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, event, reply) do { \ 264 PSC_CLEAR_EVENT_REQUEST(vstream_fileno((state)->smtp_client_stream), \ 265 (event), (char *) (state)); \ 266 PSC_DROP_SESSION_STATE((state), (reply)); \ 267 } while (0); 268 269 #define PSC_CLEAR_EVENT_HANGUP(state, event) do { \ 270 PSC_CLEAR_EVENT_REQUEST(vstream_fileno((state)->smtp_client_stream), \ 271 (event), (char *) (state)); \ 272 psc_hangup_event(state); \ 273 } while (0); 274 275 /* psc_helo_cmd - record HELO and respond */ 276 277 static int psc_helo_cmd(PSC_STATE *state, char *args) 278 { 279 char *helo_name = PSC_SMTPD_NEXT_TOKEN(args); 280 281 /* 282 * smtpd(8) incompatibility: we ignore extra words; smtpd(8) saves them. 283 */ 284 if (helo_name == 0) 285 return (PSC_SEND_REPLY(state, "501 Syntax: HELO hostname\r\n")); 286 287 PSC_STRING_UPDATE(state->helo_name, helo_name); 288 PSC_STRING_RESET(state->sender); 289 /* Don't downgrade state->protocol, in case some test depends on this. */ 290 return (PSC_SEND_REPLY(state, psc_smtpd_helo_reply)); 291 } 292 293 /* psc_smtpd_format_ehlo_reply - format EHLO response */ 294 295 static void psc_smtpd_format_ehlo_reply(VSTRING *buf, int discard_mask 296 /* , const char *sasl_mechanism_list */ ) 297 { 298 const char *myname = "psc_smtpd_format_ehlo_reply"; 299 int saved_len = 0; 300 301 if (msg_verbose) 302 msg_info("%s: discard_mask %s", myname, str_ehlo_mask(discard_mask)); 303 304 #define PSC_EHLO_APPEND(save, buf, fmt) do { \ 305 (save) = LEN(buf); \ 306 vstring_sprintf_append((buf), (fmt)); \ 307 } while (0) 308 309 #define PSC_EHLO_APPEND1(save, buf, fmt, arg1) do { \ 310 (save) = LEN(buf); \ 311 vstring_sprintf_append((buf), (fmt), (arg1)); \ 312 } while (0) 313 314 vstring_sprintf(psc_temp, "250-%s\r\n", var_myhostname); 315 if ((discard_mask & EHLO_MASK_SIZE) == 0) { 316 if (var_message_limit) 317 PSC_EHLO_APPEND1(saved_len, psc_temp, "250-SIZE %lu\r\n", 318 (unsigned long) var_message_limit); 319 else 320 PSC_EHLO_APPEND(saved_len, psc_temp, "250-SIZE\r\n"); 321 } 322 if ((discard_mask & EHLO_MASK_VRFY) == 0 && var_disable_vrfy_cmd == 0) 323 PSC_EHLO_APPEND(saved_len, psc_temp, "250-VRFY\r\n"); 324 if ((discard_mask & EHLO_MASK_ETRN) == 0) 325 PSC_EHLO_APPEND(saved_len, psc_temp, "250-ETRN\r\n"); 326 if ((discard_mask & EHLO_MASK_STARTTLS) == 0 && var_psc_use_tls) 327 PSC_EHLO_APPEND(saved_len, psc_temp, "250-STARTTLS\r\n"); 328 #ifdef TODO_SASL_AUTH 329 if ((discard_mask & EHLO_MASK_AUTH) == 0 && sasl_mechanism_list 330 && (!var_psc_tls_auth_only || (discard_mask & EHLO_MASK_STARTTLS))) { 331 PSC_EHLO_APPEND1(saved_len, psc_temp, "AUTH %s", sasl_mechanism_list); 332 if (var_broken_auth_clients) 333 PSC_EHLO_APPEND1(saved_len, psc_temp, "AUTH=%s", sasl_mechanism_list); 334 } 335 #endif 336 if ((discard_mask & EHLO_MASK_ENHANCEDSTATUSCODES) == 0) 337 PSC_EHLO_APPEND(saved_len, psc_temp, "250-ENHANCEDSTATUSCODES\r\n"); 338 if ((discard_mask & EHLO_MASK_8BITMIME) == 0) 339 PSC_EHLO_APPEND(saved_len, psc_temp, "250-8BITMIME\r\n"); 340 if ((discard_mask & EHLO_MASK_DSN) == 0) 341 PSC_EHLO_APPEND(saved_len, psc_temp, "250-DSN\r\n"); 342 STR(psc_temp)[saved_len + 3] = ' '; 343 } 344 345 /* psc_ehlo_cmd - record EHLO and respond */ 346 347 static int psc_ehlo_cmd(PSC_STATE *state, char *args) 348 { 349 char *helo_name = PSC_SMTPD_NEXT_TOKEN(args); 350 const char *ehlo_words; 351 int discard_mask; 352 char *reply; 353 354 /* 355 * smtpd(8) incompatibility: we ignore extra words; smtpd(8) saves them. 356 */ 357 if (helo_name == 0) 358 return (PSC_SEND_REPLY(state, "501 Syntax: EHLO hostname\r\n")); 359 360 PSC_STRING_UPDATE(state->helo_name, helo_name); 361 PSC_STRING_RESET(state->sender); 362 state->protocol = MAIL_PROTO_ESMTP; 363 364 /* 365 * smtpd(8) compatibility: dynamic reply filtering. 366 */ 367 if (psc_ehlo_discard_maps != 0 368 && (ehlo_words = psc_maps_find(psc_ehlo_discard_maps, 369 state->smtp_client_addr, 0)) != 0 370 && (discard_mask = ehlo_mask(ehlo_words)) != psc_ehlo_discard_mask) { 371 if (discard_mask && !(discard_mask & EHLO_MASK_SILENT)) 372 msg_info("[%s]%s: discarding EHLO keywords: %s", 373 PSC_CLIENT_ADDR_PORT(state), str_ehlo_mask(discard_mask)); 374 if (state->flags & PSC_STATE_FLAG_USING_TLS) 375 discard_mask |= EHLO_MASK_STARTTLS; 376 psc_smtpd_format_ehlo_reply(psc_temp, discard_mask); 377 reply = STR(psc_temp); 378 state->ehlo_discard_mask = discard_mask; 379 } else if (psc_ehlo_discard_maps && psc_ehlo_discard_maps->error) { 380 msg_fatal("%s lookup error for %s", 381 psc_ehlo_discard_maps->title, state->smtp_client_addr); 382 } else if (state->flags & PSC_STATE_FLAG_USING_TLS) { 383 reply = psc_smtpd_ehlo_reply_tls; 384 state->ehlo_discard_mask = psc_ehlo_discard_mask | EHLO_MASK_STARTTLS; 385 } else { 386 reply = psc_smtpd_ehlo_reply_plain; 387 state->ehlo_discard_mask = psc_ehlo_discard_mask; 388 } 389 return (PSC_SEND_REPLY(state, reply)); 390 } 391 392 /* psc_starttls_resume - resume the SMTP protocol after tlsproxy activation */ 393 394 static void psc_starttls_resume(int unused_event, char *context) 395 { 396 const char *myname = "psc_starttls_resume"; 397 PSC_STATE *state = (PSC_STATE *) context; 398 399 /* 400 * Reset SMTP server state if STARTTLS was successful. 401 */ 402 if (state->flags & PSC_STATE_FLAG_USING_TLS) { 403 /* Purge the push-back buffer, when implemented. */ 404 PSC_STRING_RESET(state->helo_name); 405 PSC_STRING_RESET(state->sender); 406 #ifdef TODO_SASL_AUTH 407 /* Reset SASL AUTH state. Dovecot responses may change. */ 408 #endif 409 } 410 411 /* 412 * Resume read/timeout events. If we still have unread input, resume the 413 * command processor immediately. 414 */ 415 PSC_RESUME_SMTP_CMD_EVENTS(state); 416 } 417 418 /* psc_starttls_cmd - activate the tlsproxy server */ 419 420 static int psc_starttls_cmd(PSC_STATE *state, char *args) 421 { 422 const char *myname = "psc_starttls_cmd"; 423 424 /* 425 * smtpd(8) incompatibility: we can't send a 4XX reply that TLS is 426 * unavailable when tlsproxy(8) detects the problem too late. 427 */ 428 if (PSC_SMTPD_NEXT_TOKEN(args) != 0) 429 return (PSC_SEND_REPLY(state, "501 Syntax: EHLO hostname\r\n")); 430 if (state->flags & PSC_STATE_FLAG_USING_TLS) 431 return (PSC_SEND_REPLY(state, 432 "554 5.5.1 Error: TLS already active\r\n")); 433 if (var_psc_use_tls == 0 || (state->ehlo_discard_mask & EHLO_MASK_STARTTLS)) 434 return (PSC_SEND_REPLY(state, 435 "502 5.5.1 Error: command not implemented\r\n")); 436 437 /* 438 * Suspend the SMTP protocol until psc_starttls_resume() is called. 439 */ 440 PSC_SUSPEND_SMTP_CMD_EVENTS(state); 441 psc_starttls_open(state, psc_starttls_resume); 442 return (0); 443 } 444 445 /* psc_extract_addr - extract MAIL/RCPT address, unquoted form */ 446 447 static char *psc_extract_addr(VSTRING *result, const char *string) 448 { 449 const unsigned char *cp = (const unsigned char *) string; 450 char *addr; 451 char *colon; 452 int stop_at; 453 int inquote = 0; 454 455 /* 456 * smtpd(8) incompatibility: we allow more invalid address forms, and we 457 * don't validate recipients. We are not going to deliver them so we 458 * won't have to worry about deliverability. This may have to change when 459 * we pass the socket to a real SMTP server and replay message envelope 460 * commands. 461 */ 462 463 /* Skip SP characters. */ 464 while (*cp && *cp == ' ') 465 cp++; 466 467 /* Choose the terminator for <addr> or bare addr. */ 468 if (*cp == '<') { 469 cp++; 470 stop_at = '>'; 471 } else { 472 stop_at = ' '; 473 } 474 475 /* Skip to terminator or end. */ 476 VSTRING_RESET(result); 477 for ( /* void */ ; *cp; cp++) { 478 if (!inquote && *cp == stop_at) 479 break; 480 if (*cp == '"') { 481 inquote = !inquote; 482 } else { 483 if (*cp == '\\' && *++cp == 0) 484 break; 485 VSTRING_ADDCH(result, *cp); 486 } 487 } 488 VSTRING_TERMINATE(result); 489 490 /* 491 * smtpd(8) compatibility: truncate deprecated route address form. This 492 * is primarily to simplify logfile analysis. 493 */ 494 addr = STR(result); 495 if (*addr == '@' && (colon = strchr(addr, ':')) != 0) 496 addr = colon + 1; 497 return (addr); 498 } 499 500 /* psc_mail_cmd - record MAIL and respond */ 501 502 static int psc_mail_cmd(PSC_STATE *state, char *args) 503 { 504 char *colon; 505 char *addr; 506 507 /* 508 * smtpd(8) incompatibility: we never reject the sender, and we ignore 509 * additional arguments. 510 */ 511 if (var_psc_helo_required && state->helo_name == 0) 512 return (PSC_SEND_REPLY(state, 513 "503 5.5.1 Error: send HELO/EHLO first\r\n")); 514 if (state->sender != 0) 515 return (PSC_SEND_REPLY(state, 516 "503 5.5.1 Error: nested MAIL command\r\n")); 517 if (args == 0 || (colon = strchr(args, ':')) == 0) 518 return (PSC_SEND_REPLY(state, 519 "501 5.5.4 Syntax: MAIL FROM:<address>\r\n")); 520 if ((addr = psc_extract_addr(psc_temp, colon + 1)) == 0) 521 return (PSC_SEND_REPLY(state, 522 "501 5.1.7 Bad sender address syntax\r\n")); 523 PSC_STRING_UPDATE(state->sender, addr); 524 return (PSC_SEND_REPLY(state, "250 2.1.0 Ok\r\n")); 525 } 526 527 /* psc_soften_reply - copy and soft-bounce a reply */ 528 529 static char *psc_soften_reply(const char *reply) 530 { 531 static VSTRING *buf = 0; 532 533 if (buf == 0) 534 buf = vstring_alloc(100); 535 vstring_strcpy(buf, reply); 536 if (reply[0] == '5') 537 STR(buf)[0] = '4'; 538 if (reply[4] == '5') 539 STR(buf)[4] = '4'; 540 return (STR(buf)); 541 } 542 543 /* psc_rcpt_cmd record RCPT and respond */ 544 545 static int psc_rcpt_cmd(PSC_STATE *state, char *args) 546 { 547 char *colon; 548 char *addr; 549 550 /* 551 * smtpd(8) incompatibility: we reject all recipients, and ignore 552 * additional arguments. 553 */ 554 if (state->sender == 0) 555 return (PSC_SEND_REPLY(state, 556 "503 5.5.1 Error: need MAIL command\r\n")); 557 if (args == 0 || (colon = strchr(args, ':')) == 0) 558 return (PSC_SEND_REPLY(state, 559 "501 5.5.4 Syntax: RCPT TO:<address>\r\n")); 560 if ((addr = psc_extract_addr(psc_temp, colon + 1)) == 0) 561 return (PSC_SEND_REPLY(state, 562 "501 5.1.3 Bad recipient address syntax\r\n")); 563 msg_info("NOQUEUE: reject: RCPT from [%s]:%s: %.*s; " 564 "from=<%s>, to=<%s>, proto=%s, helo=<%s>", 565 PSC_CLIENT_ADDR_PORT(state), 566 (int) strlen(state->rcpt_reply) - 2, 567 var_soft_bounce == 0 ? state->rcpt_reply : 568 psc_soften_reply(state->rcpt_reply), 569 state->sender, addr, state->protocol, 570 state->helo_name ? state->helo_name : ""); 571 return (PSC_SEND_REPLY(state, state->rcpt_reply)); 572 } 573 574 /* psc_data_cmd - respond to DATA and disconnect */ 575 576 static int psc_data_cmd(PSC_STATE *state, char *args) 577 { 578 579 /* 580 * smtpd(8) incompatibility: we reject all requests. 581 */ 582 if (PSC_SMTPD_NEXT_TOKEN(args) != 0) 583 return (PSC_SEND_REPLY(state, 584 "501 5.5.4 Syntax: DATA\r\n")); 585 if (state->sender == 0) 586 return (PSC_SEND_REPLY(state, 587 "503 5.5.1 Error: need RCPT command\r\n")); 588 589 /* 590 * We really would like to hang up the connection as early as possible, 591 * so that we dont't have to deal with broken zombies that fall silent at 592 * the first reject response. For now we rely on stress-dependent command 593 * read timeouts. 594 * 595 * If we proceed into the data phase, enforce over-all DATA time limit. 596 */ 597 return (PSC_SEND_REPLY(state, 598 "554 5.5.1 Error: no valid recipients\r\n")); 599 } 600 601 /* psc_rset_cmd - reset, send 250 OK */ 602 603 static int psc_rset_cmd(PSC_STATE *state, char *unused_args) 604 { 605 PSC_STRING_RESET(state->sender); 606 return (PSC_SEND_REPLY(state, "250 2.0.0 Ok\r\n")); 607 } 608 609 /* psc_noop_cmd - respond to something */ 610 611 static int psc_noop_cmd(PSC_STATE *state, char *unused_args) 612 { 613 return (PSC_SEND_REPLY(state, "250 2.0.0 Ok\r\n")); 614 } 615 616 /* psc_vrfy_cmd - respond to VRFY */ 617 618 static int psc_vrfy_cmd(PSC_STATE *state, char *args) 619 { 620 621 /* 622 * smtpd(8) incompatibility: we reject all requests, and ignore 623 * additional arguments. 624 */ 625 if (PSC_SMTPD_NEXT_TOKEN(args) == 0) 626 return (PSC_SEND_REPLY(state, 627 "501 5.5.4 Syntax: VRFY address\r\n")); 628 if (var_psc_disable_vrfy) 629 return (PSC_SEND_REPLY(state, 630 "502 5.5.1 VRFY command is disabled\r\n")); 631 return (PSC_SEND_REPLY(state, state->rcpt_reply)); 632 } 633 634 /* psc_etrn_cmd - reset, send 250 OK */ 635 636 static int psc_etrn_cmd(PSC_STATE *state, char *args) 637 { 638 639 /* 640 * smtpd(8) incompatibility: we reject all requests, and ignore 641 * additional arguments. 642 */ 643 if (var_psc_helo_required && state->helo_name == 0) 644 return (PSC_SEND_REPLY(state, 645 "503 5.5.1 Error: send HELO/EHLO first\r\n")); 646 if (PSC_SMTPD_NEXT_TOKEN(args) == 0) 647 return (PSC_SEND_REPLY(state, 648 "500 Syntax: ETRN domain\r\n")); 649 return (PSC_SEND_REPLY(state, "458 Unable to queue messages\r\n")); 650 } 651 652 /* psc_quit_cmd - respond to QUIT and disconnect */ 653 654 static int psc_quit_cmd(PSC_STATE *state, char *unused_args) 655 { 656 const char *myname = "psc_quit_cmd"; 657 658 PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event, 659 "221 2.0.0 Bye\r\n"); 660 /* Caution: state is now a dangling pointer. */ 661 return (0); 662 } 663 664 /* psc_smtpd_time_event - handle per-session time limit */ 665 666 static void psc_smtpd_time_event(int event, char *context) 667 { 668 const char *myname = "psc_smtpd_time_event"; 669 PSC_STATE *state = (PSC_STATE *) context; 670 671 if (msg_verbose > 1) 672 msg_info("%s: sq=%d cq=%d event %d on smtp socket %d from [%s]:%s flags=%s", 673 myname, psc_post_queue_length, psc_check_queue_length, 674 event, vstream_fileno(state->smtp_client_stream), 675 state->smtp_client_addr, state->smtp_client_port, 676 psc_print_state_flags(state->flags, myname)); 677 678 msg_info("COMMAND TIME LIMIT from [%s]:%s after %s", 679 PSC_CLIENT_ADDR_PORT(state), state->where); 680 PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event, 681 psc_smtpd_timeout_reply); 682 } 683 684 /* 685 * The table of all SMTP commands that we know. 686 */ 687 typedef struct { 688 const char *name; 689 int (*action) (PSC_STATE *, char *); 690 int flags; /* see below */ 691 } PSC_SMTPD_COMMAND; 692 693 #define PSC_SMTPD_CMD_FLAG_NONE (0) /* no flags (i.e. disabled) */ 694 #define PSC_SMTPD_CMD_FLAG_ENABLE (1<<0) /* command is enabled */ 695 #define PSC_SMTPD_CMD_FLAG_DESTROY (1<<1) /* dangling pointer alert */ 696 #define PSC_SMTPD_CMD_FLAG_PRE_TLS (1<<2) /* allowed with mandatory TLS */ 697 #define PSC_SMTPD_CMD_FLAG_SUSPEND (1<<3) /* suspend command engine */ 698 699 static const PSC_SMTPD_COMMAND command_table[] = { 700 "HELO", psc_helo_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_PRE_TLS, 701 "EHLO", psc_ehlo_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_PRE_TLS, 702 "STARTTLS", psc_starttls_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_PRE_TLS | PSC_SMTPD_CMD_FLAG_SUSPEND, 703 "XCLIENT", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_NONE, 704 "XFORWARD", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_NONE, 705 "AUTH", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_NONE, 706 "MAIL", psc_mail_cmd, PSC_SMTPD_CMD_FLAG_ENABLE, 707 "RCPT", psc_rcpt_cmd, PSC_SMTPD_CMD_FLAG_ENABLE, 708 "DATA", psc_data_cmd, PSC_SMTPD_CMD_FLAG_ENABLE, 709 /* ".", psc_dot_cmd, PSC_SMTPD_CMD_FLAG_NONE, */ 710 "RSET", psc_rset_cmd, PSC_SMTPD_CMD_FLAG_ENABLE, 711 "NOOP", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_PRE_TLS, 712 "VRFY", psc_vrfy_cmd, PSC_SMTPD_CMD_FLAG_ENABLE, 713 "ETRN", psc_etrn_cmd, PSC_SMTPD_CMD_FLAG_ENABLE, 714 "QUIT", psc_quit_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_DESTROY | PSC_SMTPD_CMD_FLAG_PRE_TLS, 715 0, 716 }; 717 718 /* psc_smtpd_read_event - pseudo responder */ 719 720 static void psc_smtpd_read_event(int event, char *context) 721 { 722 const char *myname = "psc_smtpd_read_event"; 723 PSC_STATE *state = (PSC_STATE *) context; 724 int ch; 725 struct cmd_trans { 726 int state; 727 int want; 728 int next_state; 729 }; 730 const char *saved_where; 731 732 #define PSC_SMTPD_CMD_ST_ANY 0 733 #define PSC_SMTPD_CMD_ST_CR 1 734 #define PSC_SMTPD_CMD_ST_CR_LF 2 735 736 static const struct cmd_trans cmd_trans[] = { 737 PSC_SMTPD_CMD_ST_ANY, '\r', PSC_SMTPD_CMD_ST_CR, 738 PSC_SMTPD_CMD_ST_CR, '\n', PSC_SMTPD_CMD_ST_CR_LF, 739 0, 0, 0, 740 }; 741 const struct cmd_trans *transp; 742 char *cmd_buffer_ptr; 743 char *command; 744 const PSC_SMTPD_COMMAND *cmdp; 745 int write_stat; 746 747 if (msg_verbose > 1) 748 msg_info("%s: sq=%d cq=%d event %d on smtp socket %d from [%s]:%s flags=%s", 749 myname, psc_post_queue_length, psc_check_queue_length, 750 event, vstream_fileno(state->smtp_client_stream), 751 state->smtp_client_addr, state->smtp_client_port, 752 psc_print_state_flags(state->flags, myname)); 753 754 /* 755 * Basic liveness requirements. 756 * 757 * Drain all input in the VSTREAM buffer, otherwise this socket will not 758 * receive further read event notification until the client disconnects! 759 * 760 * To suspend this loop temporarily before the buffer is drained, use the 761 * PSC_SUSPEND_SMTP_CMD_EVENTS() and PSC_RESUME_SMTP_CMD_EVENTS() macros, 762 * and set the PSC_SMTPD_CMD_FLAG_SUSPEND flag in the command table. 763 * 764 * Don't try to read input before it has arrived, otherwise we would starve 765 * the pseudo threads of other sessions. Get out of here as soon as the 766 * VSTREAM read buffer dries up. Do not look for more input in kernel 767 * buffers. That input wasn't likely there when psc_smtpd_read_event() 768 * was called. Also, yielding the pseudo thread will improve fairness for 769 * other pseudo threads. 770 */ 771 772 /* 773 * Note: on entry into this function the VSTREAM buffer may or may not be 774 * empty, so we test the "no more input" condition at the bottom of the 775 * loops. 776 */ 777 for (;;) { 778 779 /* 780 * Read one command line, possibly one fragment at a time. 781 */ 782 for (;;) { 783 784 if ((ch = PSC_SMTPD_NEXT_CHAR(state)) == VSTREAM_EOF) { 785 PSC_CLEAR_EVENT_HANGUP(state, psc_smtpd_time_event); 786 return; 787 } 788 789 /* 790 * Sanity check. We don't want to store infinitely long commands. 791 */ 792 if (state->read_state == PSC_SMTPD_CMD_ST_ANY 793 && VSTRING_LEN(state->cmd_buffer) >= var_line_limit) { 794 msg_info("COMMAND LENGTH LIMIT from [%s]:%s after %s", 795 PSC_CLIENT_ADDR_PORT(state), state->where); 796 PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event, 797 psc_smtpd_421_reply); 798 return; 799 } 800 VSTRING_ADDCH(state->cmd_buffer, ch); 801 802 /* 803 * Try to match the current character desired by the state 804 * machine. If that fails, try to restart the machine with a 805 * match for its first state. Like smtpd(8), we understand lines 806 * ending in <CR><LF> and bare <LF>. Unlike smtpd(8), we may 807 * treat lines ending in bare <LF> as an offense. 808 */ 809 for (transp = cmd_trans; transp->state != state->read_state; transp++) 810 if (transp->want == 0) 811 msg_panic("%s: command_read: unknown state: %d", 812 myname, state->read_state); 813 if (ch == transp->want) 814 state->read_state = transp->next_state; 815 else if (ch == cmd_trans[0].want) 816 state->read_state = cmd_trans[0].next_state; 817 else 818 state->read_state = PSC_SMTPD_CMD_ST_ANY; 819 if (state->read_state == PSC_SMTPD_CMD_ST_CR_LF) { 820 vstring_truncate(state->cmd_buffer, 821 VSTRING_LEN(state->cmd_buffer) - 2); 822 break; 823 } 824 825 /* 826 * Bare newline test. 827 */ 828 if (ch == '\n') { 829 if ((state->flags & PSC_STATE_MASK_BARLF_TODO_SKIP) 830 == PSC_STATE_FLAG_BARLF_TODO) { 831 PSC_SMTPD_ESCAPE_TEXT(psc_temp, STR(state->cmd_buffer), 832 VSTRING_LEN(state->cmd_buffer) - 1, 100); 833 msg_info("BARE NEWLINE from [%s]:%s after %s", 834 PSC_CLIENT_ADDR_PORT(state), STR(psc_temp)); 835 PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_BARLF_FAIL); 836 PSC_UNPASS_SESSION_STATE(state, PSC_STATE_FLAG_BARLF_PASS); 837 state->barlf_stamp = PSC_TIME_STAMP_DISABLED; /* XXX */ 838 /* Skip this test for the remainder of this session. */ 839 PSC_SKIP_SESSION_STATE(state, "bare newline test", 840 PSC_STATE_FLAG_BARLF_SKIP); 841 switch (psc_barlf_action) { 842 case PSC_ACT_DROP: 843 PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, 844 psc_smtpd_time_event, 845 "521 5.5.1 Protocol error\r\n"); 846 return; 847 case PSC_ACT_ENFORCE: 848 PSC_ENFORCE_SESSION_STATE(state, 849 "550 5.5.1 Protocol error\r\n"); 850 break; 851 case PSC_ACT_IGNORE: 852 PSC_UNFAIL_SESSION_STATE(state, 853 PSC_STATE_FLAG_BARLF_FAIL); 854 /* Temporarily whitelist until something expires. */ 855 PSC_PASS_SESSION_STATE(state, "bare newline test", 856 PSC_STATE_FLAG_BARLF_PASS); 857 state->barlf_stamp = event_time() + psc_min_ttl; 858 break; 859 default: 860 msg_panic("%s: unknown bare_newline action value %d", 861 myname, psc_barlf_action); 862 } 863 } 864 vstring_truncate(state->cmd_buffer, 865 VSTRING_LEN(state->cmd_buffer) - 1); 866 break; 867 } 868 869 /* 870 * Yield this pseudo thread when the VSTREAM buffer is empty in 871 * the middle of a command. 872 * 873 * XXX Do not reset the read timeout. The entire command must be 874 * received within the time limit. 875 */ 876 if (PSC_SMTPD_BUFFER_EMPTY(state)) 877 return; 878 } 879 880 /* 881 * Terminate the command buffer, and apply the last-resort command 882 * editing workaround. 883 */ 884 VSTRING_TERMINATE(state->cmd_buffer); 885 if (psc_cmd_filter != 0) { 886 const char *cp; 887 888 for (cp = STR(state->cmd_buffer); *cp && IS_SPACE_TAB(*cp); cp++) 889 /* void */ ; 890 if ((cp = psc_dict_get(psc_cmd_filter, cp)) != 0) { 891 msg_info("[%s]:%s: replacing command \"%.100s\" with \"%.100s\"", 892 state->smtp_client_addr, state->smtp_client_port, 893 STR(state->cmd_buffer), cp); 894 vstring_strcpy(state->cmd_buffer, cp); 895 } else if (psc_cmd_filter->error != 0) { 896 msg_fatal("%s:%s lookup error for \"%.100s\"", 897 psc_cmd_filter->type, psc_cmd_filter->name, cp); 898 } 899 } 900 901 /* 902 * Reset the command buffer write pointer and state machine in 903 * preparation for the next command. For this to work as expected, 904 * VSTRING_RESET() must be non-destructive. We just can't ask for the 905 * VSTRING_LEN() and vstring_end() results. 906 */ 907 state->read_state = PSC_SMTPD_CMD_ST_ANY; 908 VSTRING_RESET(state->cmd_buffer); 909 910 /* 911 * Process the command line. 912 * 913 * Caution: some command handlers terminate the session and destroy the 914 * session state structure. When this happens we must leave the SMTP 915 * engine to avoid a dangling pointer problem. 916 */ 917 cmd_buffer_ptr = STR(state->cmd_buffer); 918 if (msg_verbose) 919 msg_info("< [%s]:%s: %s", state->smtp_client_addr, 920 state->smtp_client_port, cmd_buffer_ptr); 921 922 /* Parse the command name. */ 923 if ((command = PSC_SMTPD_NEXT_TOKEN(cmd_buffer_ptr)) == 0) 924 command = ""; 925 926 /* 927 * The non-SMTP, PIPELINING and command COUNT tests depend on the 928 * client command handler. 929 * 930 * Caution: cmdp->name and cmdp->action may be null on loop exit. 931 */ 932 saved_where = state->where; 933 state->where = PSC_SMTPD_CMD_UNIMPL; 934 for (cmdp = command_table; cmdp->name != 0; cmdp++) { 935 if (strcasecmp(command, cmdp->name) == 0) { 936 state->where = cmdp->name; 937 break; 938 } 939 } 940 941 if ((state->flags & PSC_STATE_FLAG_SMTPD_X21) 942 && cmdp->action != psc_quit_cmd) { 943 PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event, 944 state->final_reply); 945 return; 946 } 947 /* Non-SMTP command test. */ 948 if ((state->flags & PSC_STATE_MASK_NSMTP_TODO_SKIP) 949 == PSC_STATE_FLAG_NSMTP_TODO && cmdp->name == 0 950 && (is_header(command) 951 /* Ignore forbid_cmds lookup errors. Non-critical feature. */ 952 || (*var_psc_forbid_cmds 953 && string_list_match(psc_forbid_cmds, command)))) { 954 printable(command, '?'); 955 PSC_SMTPD_ESCAPE_TEXT(psc_temp, cmd_buffer_ptr, 956 strlen(cmd_buffer_ptr), 100); 957 msg_info("NON-SMTP COMMAND from [%s]:%s after %s: %.100s %s", 958 PSC_CLIENT_ADDR_PORT(state), saved_where, 959 command, STR(psc_temp)); 960 PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_NSMTP_FAIL); 961 PSC_UNPASS_SESSION_STATE(state, PSC_STATE_FLAG_NSMTP_PASS); 962 state->nsmtp_stamp = PSC_TIME_STAMP_DISABLED; /* XXX */ 963 /* Skip this test for the remainder of this SMTP session. */ 964 PSC_SKIP_SESSION_STATE(state, "non-smtp test", 965 PSC_STATE_FLAG_NSMTP_SKIP); 966 switch (psc_nsmtp_action) { 967 case PSC_ACT_DROP: 968 PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, 969 psc_smtpd_time_event, 970 "521 5.7.0 Error: I can break rules, too. Goodbye.\r\n"); 971 return; 972 case PSC_ACT_ENFORCE: 973 PSC_ENFORCE_SESSION_STATE(state, 974 "550 5.5.1 Protocol error\r\n"); 975 break; 976 case PSC_ACT_IGNORE: 977 PSC_UNFAIL_SESSION_STATE(state, 978 PSC_STATE_FLAG_NSMTP_FAIL); 979 /* Temporarily whitelist until something else expires. */ 980 PSC_PASS_SESSION_STATE(state, "non-smtp test", 981 PSC_STATE_FLAG_NSMTP_PASS); 982 state->nsmtp_stamp = event_time() + psc_min_ttl; 983 break; 984 default: 985 msg_panic("%s: unknown non_smtp_command action value %d", 986 myname, psc_nsmtp_action); 987 } 988 } 989 /* Command PIPELINING test. */ 990 if ((state->flags & PSC_STATE_MASK_PIPEL_TODO_SKIP) 991 == PSC_STATE_FLAG_PIPEL_TODO && !PSC_SMTPD_BUFFER_EMPTY(state)) { 992 printable(command, '?'); 993 PSC_SMTPD_ESCAPE_TEXT(psc_temp, PSC_SMTPD_PEEK_DATA(state), 994 PSC_SMTPD_PEEK_LEN(state), 100); 995 msg_info("COMMAND PIPELINING from [%s]:%s after %.100s: %s", 996 PSC_CLIENT_ADDR_PORT(state), command, STR(psc_temp)); 997 PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_PIPEL_FAIL); 998 PSC_UNPASS_SESSION_STATE(state, PSC_STATE_FLAG_PIPEL_PASS); 999 state->pipel_stamp = PSC_TIME_STAMP_DISABLED; /* XXX */ 1000 /* Skip this test for the remainder of this SMTP session. */ 1001 PSC_SKIP_SESSION_STATE(state, "pipelining test", 1002 PSC_STATE_FLAG_PIPEL_SKIP); 1003 switch (psc_pipel_action) { 1004 case PSC_ACT_DROP: 1005 PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, 1006 psc_smtpd_time_event, 1007 "521 5.5.1 Protocol error\r\n"); 1008 return; 1009 case PSC_ACT_ENFORCE: 1010 PSC_ENFORCE_SESSION_STATE(state, 1011 "550 5.5.1 Protocol error\r\n"); 1012 break; 1013 case PSC_ACT_IGNORE: 1014 PSC_UNFAIL_SESSION_STATE(state, 1015 PSC_STATE_FLAG_PIPEL_FAIL); 1016 /* Temporarily whitelist until something else expires. */ 1017 PSC_PASS_SESSION_STATE(state, "pipelining test", 1018 PSC_STATE_FLAG_PIPEL_PASS); 1019 state->pipel_stamp = event_time() + psc_min_ttl; 1020 break; 1021 default: 1022 msg_panic("%s: unknown pipelining action value %d", 1023 myname, psc_pipel_action); 1024 } 1025 } 1026 1027 /* 1028 * The following tests don't pass until the client gets all the way 1029 * to the RCPT TO command. However, the client can still fail these 1030 * tests with some later command. 1031 */ 1032 if (cmdp->action == psc_rcpt_cmd) { 1033 if ((state->flags & PSC_STATE_MASK_BARLF_TODO_PASS_FAIL) 1034 == PSC_STATE_FLAG_BARLF_TODO) { 1035 PSC_PASS_SESSION_STATE(state, "bare newline test", 1036 PSC_STATE_FLAG_BARLF_PASS); 1037 /* XXX Reset to PSC_TIME_STAMP_DISABLED on failure. */ 1038 state->barlf_stamp = event_time() + var_psc_barlf_ttl; 1039 } 1040 if ((state->flags & PSC_STATE_MASK_NSMTP_TODO_PASS_FAIL) 1041 == PSC_STATE_FLAG_NSMTP_TODO) { 1042 PSC_PASS_SESSION_STATE(state, "non-smtp test", 1043 PSC_STATE_FLAG_NSMTP_PASS); 1044 /* XXX Reset to PSC_TIME_STAMP_DISABLED on failure. */ 1045 state->nsmtp_stamp = event_time() + var_psc_nsmtp_ttl; 1046 } 1047 if ((state->flags & PSC_STATE_MASK_PIPEL_TODO_PASS_FAIL) 1048 == PSC_STATE_FLAG_PIPEL_TODO) { 1049 PSC_PASS_SESSION_STATE(state, "pipelining test", 1050 PSC_STATE_FLAG_PIPEL_PASS); 1051 /* XXX Reset to PSC_TIME_STAMP_DISABLED on failure. */ 1052 state->pipel_stamp = event_time() + var_psc_pipel_ttl; 1053 } 1054 } 1055 /* Command COUNT limit test. */ 1056 if (++state->command_count > var_psc_cmd_count 1057 && cmdp->action != psc_quit_cmd) { 1058 msg_info("COMMAND COUNT LIMIT from [%s]:%s after %s", 1059 PSC_CLIENT_ADDR_PORT(state), saved_where); 1060 PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event, 1061 psc_smtpd_421_reply); 1062 return; 1063 } 1064 /* Finally, execute the command. */ 1065 if (cmdp->name == 0 || (cmdp->flags & PSC_SMTPD_CMD_FLAG_ENABLE) == 0) { 1066 write_stat = PSC_SEND_REPLY(state, 1067 "502 5.5.2 Error: command not recognized\r\n"); 1068 } else if (var_psc_enforce_tls 1069 && (state->flags & PSC_STATE_FLAG_USING_TLS) == 0 1070 && (cmdp->flags & PSC_SMTPD_CMD_FLAG_PRE_TLS) == 0) { 1071 write_stat = PSC_SEND_REPLY(state, 1072 "530 5.7.0 Must issue a STARTTLS command first\r\n"); 1073 } else { 1074 write_stat = cmdp->action(state, cmd_buffer_ptr); 1075 if (cmdp->flags & PSC_SMTPD_CMD_FLAG_DESTROY) 1076 return; 1077 } 1078 1079 /* 1080 * Terminate the session after a write error. 1081 */ 1082 if (write_stat < 0) { 1083 PSC_CLEAR_EVENT_HANGUP(state, psc_smtpd_time_event); 1084 return; 1085 } 1086 1087 /* 1088 * We're suspended, waiting for some external event to happen. 1089 * Hopefully, someone will call us back to process the remainder of 1090 * the pending input, otherwise we could hang. 1091 */ 1092 if (cmdp->flags & PSC_SMTPD_CMD_FLAG_SUSPEND) 1093 return; 1094 1095 /* 1096 * Reset the command read timeout before reading the next command. 1097 */ 1098 event_request_timer(psc_smtpd_time_event, (char *) state, 1099 PSC_EFF_CMD_TIME_LIMIT); 1100 1101 /* 1102 * Yield this pseudo thread when the VSTREAM buffer is empty. 1103 */ 1104 if (PSC_SMTPD_BUFFER_EMPTY(state)) 1105 return; 1106 } 1107 } 1108 1109 /* psc_smtpd_tests - per-session deep protocol test initialization */ 1110 1111 void psc_smtpd_tests(PSC_STATE *state) 1112 { 1113 static char *myname = "psc_smtpd_tests"; 1114 1115 /* 1116 * Report errors and progress in the context of this test. 1117 */ 1118 PSC_BEGIN_TESTS(state, "tests after SMTP handshake"); 1119 1120 /* 1121 * Initialize per-session state that is used only by the dummy engine: 1122 * the command read buffer and the command read state machine. 1123 */ 1124 state->cmd_buffer = vstring_alloc(100); 1125 state->read_state = PSC_SMTPD_CMD_ST_ANY; 1126 1127 /* 1128 * Opportunistically make postscreen more useful by turning on the 1129 * pipelining and non-SMTP command tests when a pre-handshake test 1130 * failed, or when some deep test is configured as enabled. 1131 * 1132 * XXX Make "opportunistically" configurable for each test. 1133 */ 1134 if ((state->flags & PSC_STATE_FLAG_SMTPD_X21) == 0) { 1135 state->flags |= PSC_STATE_MASK_SMTPD_TODO; 1136 } else { 1137 state->flags &= ~PSC_STATE_MASK_SMTPD_TODO; 1138 } 1139 1140 /* 1141 * Send no SMTP banner to pregreeting clients. This eliminates a lot of 1142 * "NON-SMTP COMMAND" events, and improves sender/recipient logging. 1143 */ 1144 if ((state->flags & PSC_STATE_FLAG_PREGR_FAIL) == 0 1145 && PSC_SEND_REPLY(state, psc_smtpd_greeting) != 0) { 1146 psc_hangup_event(state); 1147 return; 1148 } 1149 1150 /* 1151 * Wait for the client to respond. 1152 */ 1153 PSC_READ_EVENT_REQUEST2(vstream_fileno(state->smtp_client_stream), 1154 psc_smtpd_read_event, psc_smtpd_time_event, 1155 (char *) state, PSC_EFF_CMD_TIME_LIMIT); 1156 } 1157 1158 /* psc_smtpd_init - per-process deep protocol test initialization */ 1159 1160 void psc_smtpd_init(void) 1161 { 1162 1163 /* 1164 * Initialize the server banner. 1165 */ 1166 vstring_sprintf(psc_temp, "220 %s\r\n", var_smtpd_banner); 1167 psc_smtpd_greeting = mystrdup(STR(psc_temp)); 1168 1169 /* 1170 * Initialize the HELO reply. 1171 */ 1172 vstring_sprintf(psc_temp, "250 %s\r\n", var_myhostname); 1173 psc_smtpd_helo_reply = mystrdup(STR(psc_temp)); 1174 1175 /* 1176 * STARTTLS support. Note the complete absence of #ifdef USE_TLS 1177 * throughout the postscreen(8) source code. If Postfix is built without 1178 * TLS support, then the TLS proxy will simply report that TLS is not 1179 * available, and conventional error handling will take care of the 1180 * issue. 1181 * 1182 * Legacy code copied from smtpd(8). The pre-fabricated EHLO reply depends 1183 * on this. 1184 */ 1185 if (*var_psc_tls_level) { 1186 switch (tls_level_lookup(var_psc_tls_level)) { 1187 default: 1188 msg_fatal("Invalid TLS level \"%s\"", var_psc_tls_level); 1189 /* NOTREACHED */ 1190 break; 1191 case TLS_LEV_SECURE: 1192 case TLS_LEV_VERIFY: 1193 case TLS_LEV_FPRINT: 1194 msg_warn("%s: unsupported TLS level \"%s\", using \"encrypt\"", 1195 VAR_PSC_TLS_LEVEL, var_psc_tls_level); 1196 /* FALLTHROUGH */ 1197 case TLS_LEV_ENCRYPT: 1198 var_psc_enforce_tls = var_psc_use_tls = 1; 1199 break; 1200 case TLS_LEV_MAY: 1201 var_psc_enforce_tls = 0; 1202 var_psc_use_tls = 1; 1203 break; 1204 case TLS_LEV_NONE: 1205 var_psc_enforce_tls = var_psc_use_tls = 0; 1206 break; 1207 } 1208 } 1209 var_psc_use_tls = var_psc_use_tls || var_psc_enforce_tls; 1210 #ifdef TODO_SASL_AUTH 1211 var_psc_tls_auth_only = var_psc_tls_auth_only || var_psc_enforce_tls; 1212 #endif 1213 1214 /* 1215 * Initialize the EHLO reply. Once for plaintext sessions, and once for 1216 * TLS sessions. 1217 */ 1218 psc_smtpd_format_ehlo_reply(psc_temp, psc_ehlo_discard_mask); 1219 psc_smtpd_ehlo_reply_plain = mystrdup(STR(psc_temp)); 1220 1221 psc_smtpd_format_ehlo_reply(psc_temp, 1222 psc_ehlo_discard_mask | EHLO_MASK_STARTTLS); 1223 psc_smtpd_ehlo_reply_tls = mystrdup(STR(psc_temp)); 1224 1225 /* 1226 * Initialize the 421 timeout reply. 1227 */ 1228 vstring_sprintf(psc_temp, "421 4.4.2 %s Error: timeout exceeded\r\n", 1229 var_myhostname); 1230 psc_smtpd_timeout_reply = mystrdup(STR(psc_temp)); 1231 1232 /* 1233 * Initialize the generic 421 reply. 1234 */ 1235 vstring_sprintf(psc_temp, "421 %s Service unavailable - try again later\r\n", 1236 var_myhostname); 1237 psc_smtpd_421_reply = mystrdup(STR(psc_temp)); 1238 1239 /* 1240 * Initialize the reply footer. 1241 */ 1242 if (*var_psc_rej_footer) 1243 psc_expand_init(); 1244 } 1245 1246 /* psc_smtpd_pre_jail_init - per-process deep protocol test initialization */ 1247 1248 void psc_smtpd_pre_jail_init(void) 1249 { 1250 1251 /* 1252 * Determine what server ESMTP features to suppress, typically to avoid 1253 * inter-operability problems. We do the default filter here, and 1254 * determine client-dependent filtering on the fly. 1255 * 1256 * XXX Bugger. This means we have to restart when the table changes! 1257 */ 1258 if (*var_psc_ehlo_dis_maps) 1259 psc_ehlo_discard_maps = maps_create(VAR_PSC_EHLO_DIS_MAPS, 1260 var_psc_ehlo_dis_maps, 1261 DICT_FLAG_LOCK); 1262 psc_ehlo_discard_mask = ehlo_mask(var_psc_ehlo_dis_words); 1263 1264 /* 1265 * Last-resort command editing support. 1266 */ 1267 if (*var_psc_cmd_filter) 1268 psc_cmd_filter = dict_open(var_psc_cmd_filter, O_RDONLY, 1269 DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); 1270 } 1271