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;