Wietse Venema: > Wietse Venema: > > There are two sides to this story. One side is that in Postfix > > 2.3..2.6 the SMTP client's error handling had a bug that was exposed > > by postscreen's peculiar manner of blocking clients. But that is > > not the real problem. > > > > The other side of the story is that postscreen's error handling is > > questionable. When postscreen is unable to hand off a connection > > to an smtpd process after sending the "220-" partial greeting, > > postscreen sends a 421 response and hangs up. Now, sending 220- > > followed by 421 violates SMTP. And that is the real problem. > > This patch addresses the protocol problem on the postscreen side. > With this, postscreen completes the 220 greeting and then it replies > 4xx to all RCPT TO commands. This is safe, but it allows the client > to send more commands than is strictly necessary. > > I'll optimize the fix later to reply with 421 (and hang up) to the > first client command, so that postscreen can handle more traffic.
This workaround is technically more correct (it doesn't keep the postscreen-to-smtpd socket open while delivering the bad news to the remote SMTP client). Wietse 20111025 Workaround (introduced: Postfix 2.8): postcreen sent non-compliant SMTP responses (220- followed by 421) when it could not hand off a connection to a real smtpd process, causing undefined behavior in the remote SMTP client. This workaround simply redirects the client to the after-greeting tests, replying with 4XX to all RCPT TO commands. A final fix will reply with 421 (and hang up) to the first client command. File: postscreen/spostscreen-send.c. *** /var/tmp/postfix-2.9-20111024/src/postscreen/postscreen_send.c Wed Feb 16 08:40:32 2011 --- src/postscreen/postscreen_send.c Tue Oct 25 11:03:47 2011 *************** *** 187,203 **** PASS_CONNECT(psc_smtpd_service_name, NON_BLOCKING, PSC_SEND_SOCK_CONNECT_TIMEOUT)) < 0) { msg_warn("cannot connect to service %s: %m", psc_smtpd_service_name); ! PSC_SEND_REPLY(state, "421 4.3.2 All server ports are busy\r\n"); ! psc_free_session_state(state); return; } ! PSC_ADD_SERVER_STATE(state, server_fd); ! if (LOCAL_SEND_FD(state->smtp_server_fd, vstream_fileno(state->smtp_client_stream)) < 0) { msg_warn("cannot pass connection to service %s: %m", psc_smtpd_service_name); ! PSC_SEND_REPLY(state, "421 4.3.2 No system resources\r\n"); ! psc_free_session_state(state); return; } else { --- 187,203 ---- PASS_CONNECT(psc_smtpd_service_name, NON_BLOCKING, PSC_SEND_SOCK_CONNECT_TIMEOUT)) < 0) { msg_warn("cannot connect to service %s: %m", psc_smtpd_service_name); ! /* XXX This assumes no connection hand-off with after-220 tests. */ ! psc_smtpd_tests(state); return; } ! if (LOCAL_SEND_FD(server_fd, vstream_fileno(state->smtp_client_stream)) < 0) { msg_warn("cannot pass connection to service %s: %m", psc_smtpd_service_name); ! (void) close(server_fd); ! /* XXX This assumes no connection hand-off with after-220 tests. */ ! psc_smtpd_tests(state); return; } else { *************** *** 209,214 **** --- 209,215 ---- #if 0 PSC_DEL_CLIENT_STATE(state); #endif + PSC_ADD_SERVER_STATE(state, server_fd); PSC_READ_EVENT_REQUEST(state->smtp_server_fd, psc_send_socket_close_event, (char *) state, PSC_SEND_SOCK_NOTIFY_TIMEOUT); return;