[tpop3d-discuss] tpop3d and incompetently-written virus scanners (was: Re: Tpop3d Bug?)

Ben Schumacher ben at blahr.com
Tue, 30 Sep 2003 14:45:50 -0600 (MDT)


Chris-

Quick question... I was trying to track this through the code, but since
you now malloc here, where does this memory get freed? As far as I can
tell, it doesn't... but I thought I'd run it by you and see what you said.

Oh... and I agree... this is a totally ass-backwards way for them to write
their software. Really dumb. I work at a company that streams XML through
sockets, and while its a pain in the ass to write code that builds
parsable XML out of elements that will (inevitably) become fragmented, it
has to be done.

Packet fragmentation happens... and it happens for tons of reasons. To
write software that doesn't work as a result of this is just well... plain
lazy, as you said.

Cheers,

bs.

Chris Lightfoot said:
>   [ Cc: to list, in case anybody else is having the same
>     kind of trouble; and to Norman ASA, authors of the
>     offending product, who *just might* want to fix it. ]
>
> On Tue, Sep 30, 2003 at 06:52:16PM +0200, M. Boelen wrote:
>> Yes, we have tried to use 1.4.2. This version doesn't have the "bug". We
>> have a few FreeBSD servers now that use 1.4.2 and some that use 1.5.1
>> (and some 1.5.2).
>>
>> The products that have the problems are commercial (ie. Norton
>
> Well, I've discovered the problem with the Norman product,
> `Norman Virus Center'.
>
> It was written by morons.
>
> Did you know that it takes up 70 megabytes of memory just
> to be a POP3 proxy? I could sacrifice 70,000 times the
> computer memory that got men to the moon and back to the
> silly thing and it still wouldn't run.
>
>
> More germane to this problem... the idiots who wrote it
> assumed that a whole POP3 response (+OK/-ERR ... \r\n)
> would be received in a single recv call, that is, in a
> single TCP packet. This assumption is certainly wrong,
> since no protocol can make that guarantee, and is not
> present in the RFC, which defines the POP3 protocol. Only
> a very lazy programmer would make such an assumption --
> hardly the kind of person you'd want working on something
> security-critical like a virus scanner.
>
> Between tpop3d 1.4.2 and 1.5.1, I changed the way that
> command responses are sent so that they *may* be split
> over several write calls. This means that they *may* be
> split over several TCP segments -- more likely now than
> before, though either case was possible previously. (This
> change came with a rewrite of the tpop3d I/O layer to
> incorporate TLS support, and avoids an additional buffer
> copy.)
>
> This means that the idiot Norman program never sees
> responses from tpop3d. It's not restricted to the +OK
> response after the password -- it won't see a -ERR
> response, either.
>
> Here is the patch:
>
> diff -u -r1.49 connection.c
> --- connection.c        14 Jul 2003 23:31:20 -0000      1.49
> +++ connection.c        30 Sep 2003 18:52:19 -0000
> @@ -381,9 +381,30 @@
>   * Send a +OK... / -ERR... response to a message. Returns 1 on success or
>  on
>   * failure. */
>  int connection_sendresponse(connection c, const int success, const char
> *s) {
> -    if (connection_send(c, success ? "+OK " : "-ERR ", success ? 4 : 5)
> -            && connection_send(c, s, strlen(s))
> -            && connection_send(c, "\r\n", 2)) {
> +    /*
> +     * For efficiency's sake, we should send this bit-by-bit, avoiding
> another
> +     * buffer copy. But unfortunately, there are POP3 clients in the
> world
> +     * so stupid that they assume a whole response will arrive in a
> single TCP
> +     * segment. Particular examples include POP3 virus-scanning proxies,
> such
> +     * as Norman ASA's, which was evidently written by somebody very
> lazy.
> +     *
> +     * Obviously there's no way to guarantee how the packets in a TCP
> stream
> +     * are disposed, in general, but we can increase the probability of
> success
> +     * by trying to ensure here that our response is contained in a
> single
> +     * write call. It still might get split up by the ioabs layer, but we
> have
> +     * to take our chances....
> +     */
> +    static char *buf;
> +    static size_t buflen;
> +    size_t l;
> +
> +    l = (success ? 6 : 7) + strlen(s);
> +
> +    if (!buf || buflen < l + 1)
> +        buf = xmalloc(buflen = l + 1);
> +
> +    sprintf(buf, "%s %s\r\n", success ? "+OK" : "-ERR", s);
> +    if (connection_send(c, buf, l)) {
>          if (verbose)
>              log_print(LOG_DEBUG, _("connection_sendresponse: client %s:
> sent `%s %s'"), c->idstr, success ? "+OK" : "-ERR", s);
>          return 1;
>
> (This is now in CVS, though I much resent including it,
> since it damages my code -- albeit slightly -- in order to
> work around the incompetence of the people from Norman.
> I'd be interested to see whether Norton made the same
> mistake.)
>
> --
> Early [ethernet] developers... objected to a roundoff error that
> exceeded the ARPANET's entire bandwidth, but marketing won out.
> (Evi Nemeth)
>
> _______________________________________________
> tpop3d-discuss mailing list
> tpop3d-discuss@lists.beasts.org
> http://lists.beasts.org/mailman/listinfo/tpop3d-discuss
>