smtp: Fixed dot stuffing when EOL characters were at end of input buffers

Fixed a problem with the CRLF. detection when multiple buffers were
used to upload an email to libcurl and the line ending character(s)
appeared at the end of each buffer. This meant any lines which started
with . would not be escaped into .. and could be interpreted as the end
of transmission string instead.

This only affected libcurl based applications that used a read function
and wasn't reproducible with the curl command-line tool.

Bug: http://curl.haxx.se/bug/view.cgi?id=1456
Assisted-by: Patrick Monnerat
This commit is contained in:
Steve Holme 2014-12-12 18:37:06 +00:00
parent 2f5c70b2b0
commit f0ecdd04d3

View File

@ -2322,6 +2322,7 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread)
struct SMTP *smtp = data->req.protop; struct SMTP *smtp = data->req.protop;
char *scratch = data->state.scratch; char *scratch = data->state.scratch;
char *oldscratch = NULL; char *oldscratch = NULL;
size_t eob_sent;
/* Do we need to allocate a scratch buffer? */ /* Do we need to allocate a scratch buffer? */
if(!scratch || data->set.crlf) { if(!scratch || data->set.crlf) {
@ -2335,6 +2336,9 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread)
} }
} }
/* Have we already sent part of the EOB? */
eob_sent = smtp->eob;
/* This loop can be improved by some kind of Boyer-Moore style of /* This loop can be improved by some kind of Boyer-Moore style of
approach but that is saved for later... */ approach but that is saved for later... */
for(i = 0, si = 0; i < nread; i++) { for(i = 0, si = 0; i < nread; i++) {
@ -2349,8 +2353,8 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread)
} }
else if(smtp->eob) { else if(smtp->eob) {
/* A previous substring matched so output that first */ /* A previous substring matched so output that first */
memcpy(&scratch[si], SMTP_EOB, smtp->eob); memcpy(&scratch[si], SMTP_EOB + eob_sent, smtp->eob - eob_sent);
si += smtp->eob; si += smtp->eob - eob_sent;
/* Then compare the first byte */ /* Then compare the first byte */
if(SMTP_EOB[0] == data->req.upload_fromhere[i]) if(SMTP_EOB[0] == data->req.upload_fromhere[i])
@ -2358,6 +2362,8 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread)
else else
smtp->eob = 0; smtp->eob = 0;
eob_sent = 0;
/* Reset the trailing CRLF flag as there was more data */ /* Reset the trailing CRLF flag as there was more data */
smtp->trailing_crlf = FALSE; smtp->trailing_crlf = FALSE;
} }
@ -2365,19 +2371,19 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread)
/* Do we have a match for CRLF. as per RFC-5321, sect. 4.5.2 */ /* Do we have a match for CRLF. as per RFC-5321, sect. 4.5.2 */
if(SMTP_EOB_FIND_LEN == smtp->eob) { if(SMTP_EOB_FIND_LEN == smtp->eob) {
/* Copy the replacement data to the target buffer */ /* Copy the replacement data to the target buffer */
memcpy(&scratch[si], SMTP_EOB_REPL, SMTP_EOB_REPL_LEN); memcpy(&scratch[si], SMTP_EOB_REPL + eob_sent, SMTP_EOB_REPL_LEN - eob_sent);
si += SMTP_EOB_REPL_LEN; si += SMTP_EOB_REPL_LEN - eob_sent;
smtp->eob = 0; smtp->eob = 0;
eob_sent = 0;
} }
else if(!smtp->eob) else if(!smtp->eob)
scratch[si++] = data->req.upload_fromhere[i]; scratch[si++] = data->req.upload_fromhere[i];
} }
if(smtp->eob) { if(smtp->eob - eob_sent) {
/* A substring matched before processing ended so output that now */ /* A substring matched before processing ended so output that now */
memcpy(&scratch[si], SMTP_EOB, smtp->eob); memcpy(&scratch[si], SMTP_EOB + eob_sent, smtp->eob - eob_sent);
si += smtp->eob; si += smtp->eob - eob_sent;
smtp->eob = 0;
} }
/* Only use the new buffer if we replaced something */ /* Only use the new buffer if we replaced something */