On Thu, 2014-06-19 14:44:30 -0400, Daniel Richard G. wrote:
> Well, sSMTP is my dumb forwarder of choice, and as the original
> reporter appears to have moved on, and sSMTP has been dropped from
> testing due to this bug, and no one else seems to care, it looks like
> I'll have to step in.
> 
> Attached is a patch against the original 2.64 source that should address
> this bug, and hopefully not break anything. An overview of my changes:
> 
> * Added code to standarise() to drop the trailing 'r' if the line
>   originally ended with "rn".
> 
> * Added a check to header_parse() that effectively converts an "rn" in
>   the input into 'n'.
> 
> * Added a conditional so that header_parse() doesn't pass the empty
>   string to header_save()---a behavior I observed in testing, at the end
>   of a header block with "rn" line endings.
> 
> * Simplified the last if(in_header) conditional in header_parse(),
>   because it erroneously assumes that if in_header == True, then c could
>   have some value other than EOF. (See the condition on the previous
>   "while" loop, and the lack of any other way to exit said loop.)
> 
>   header_parse() will now properly grab a header if fed a message
>   without a body (i.e. no "nn" ending the header block), although this
>   code will still drop a header if there is no newline at the end.
> 
> 
> Christoph, thank you for your excellent analysis, and the test cases. I
> made use of them, and with my changes sSMTP appears to do the right
> thing. I hope we can still count you as a Debian user, four years on!
> 
> Aníbal, please test this patch and let me know if there are any issues.
> If everything looks good, I have two requests:
> 
> 1. Convert all instances of (char)NULL in the source to '0'. The former
>    is silly, and if you add -Wall -Wextra to CFLAGS, GCC complains about
>    it voluminously. (I followed that convention in my patch, but only so
>    that this change could be applied across the board.)
> 
> 2. Integrate all/most of debian/patches/* into the original upstream
>    source, and bump the version to >= 2.65. It's about time.

Thank you!

I'll review/test/merge your patch this weekend. Hopefully, there will be
a 2.65 release in the next fwew days. :-)


> --- ssmtp-2.64/ssmtp.c.orig   2009-11-23 04:55:11.000000000 -0500
> +++ ssmtp-2.64/ssmtp.c        2014-06-19 01:21:01.907825184 -0400
> @@ -365,6 +365,12 @@
>       if((p = strchr(str, '\n'))) {
>               *p = (char)NULL;
>               *linestart = True;
> +
> +             /* If the line ended in "\r\n", then drop the '\r' too */
> +             sl = strlen(str);
> +             if(sl >= 1 && str[sl - 1] == '\r') {
> +                     str[sl - 1] = (char)NULL;
> +             }
>       }
>       return(leadingdot);
>  }
> @@ -758,6 +764,14 @@
>               }
>               len++;
>  
> +             if(l == '\r' && c == '\n') {
> +                     /* Properly handle input that already has "\r\n"
> +                        line endings; see https://bugs.debian.org/584162 */
> +                     l = (len >= 2 ? *(q - 2) : '\n');
> +                     q--;
> +                     len--;
> +             }
> +
>               if(l == '\n') {
>                       switch(c) {
>                               case ' ':
> @@ -780,7 +794,9 @@
>                                               if((q = strrchr(p, '\n'))) {
>                                                       *q = (char)NULL;
>                                               }
> -                                             header_save(p);
> +                                             if(len > 0) {
> +                                                     header_save(p);
> +                                             }
>  
>                                               q = p;
>                                               len = 0;
> @@ -790,35 +806,12 @@
>  
>               l = c;
>       }
> -     if(in_header) {
> -             if(l == '\n') {
> -                     switch(c) {
> -                             case ' ':
> -                             case '\t':
> -                                             /* Must insert '\r' before 
> '\n's embedded in header
> -                                                fields otherwise qmail won't 
> accept our mail
> -                                                because a bare '\n' violates 
> some RFC */
> -                                             
> -                                             *(q - 1) = '\r';        /* 
> Replace previous \n with \r */
> -                                             *q++ = '\n';            /* 
> Insert \n */
> -                                             len++;
> -                                             
> -                                             break;
> -
> -                             case '\n':
> -                                             in_header = False;
> -
> -                             default:
> -                                             *q = (char)NULL;
> -                                             if((q = strrchr(p, '\n'))) {
> -                                                     *q = (char)NULL;
> -                                             }
> -                                             header_save(p);
> -
> -                                             q = p;
> -                                             len = 0;
> -                     }
> +     if(in_header && l == '\n') {
> +             /* Got EOF while reading the header */
> +             if((q = strrchr(p, '\n'))) {
> +                     *q = (char)NULL;
>               }
> +             header_save(p);
>       }
>       (void)free(p);
>  }

Attachment: signature.asc
Description: Digital signature

Reply via email to