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;

Reply via email to