Willy Tarreau:
> > >Regardless of command format details, if the proxy prepends a command
> > >to the client's SMTP stream, then postscreen must use unbuffered
> > >I/O to read that command. If buffering were turned on, the buffering
> > >layer could read past the proxy's<CR><LF>  and eat up part of the
> > >client input kind-of like CVE-2011-0411.
> 
> Precisely on this point there is an easier way, it consists in using
> recv(MSG_PEEK). The big advantage is that you don't need to store the
> temporary bytes you've read since they remain in the kernel's buffers.
> So it more or less looks like this :
> 
>      len = recv(fd, trash, sizeof(trash), MSG_PEEK);
>      if (len == -1 && errno == EAGAIN)
>            return;
> 
>      lf = memchr(trash, '\n', len);
>      if (lf == NULL) {
>            if (len < trash) /* Huh?? */
>                return;
>            /* else abort the connection */
>      }

In an event-driven program such as postscreen, this code breaks
when the proxy line arrives as multiple fragments.

If the program does not drain proxy line fragments from the kernel
buffer, then the socket remains readable and the program will go
into a read-notification loop until the entire line is received.

This implies that the following suggestion is not valid for an
event-driven program such as postscreen:

> On the one hand, if it is as trivial to make smtpd parse the PROXY
> line as it was for postscreen, it can solve the problem by having
> postscreen not consume the first line, which makes sense in that
> postscreen remains the first layer analyser which doesn't mangle
> data on the connection.

Either you need to update the protocol spec (require non-fragmented
proxy lines) or provide a code example that doesn't go into a
read-notification loop when the proxy line arrives as multiple
fragments.

        Wietse

Reply via email to