From bd8fbe3606d80e5a3fc02fe71b521146c6938448 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Thu, 19 Jan 2017 15:37:16 +0000 Subject: [PATCH] Fix DKIM verify when used with CHUNKING. Bug 2016 --- doc/doc-txt/ChangeLog | 14 +++++- src/src/auths/get_data.c | 2 +- src/src/auths/get_no64_data.c | 2 +- src/src/dkim.c | 9 ++-- src/src/functions.h | 8 ++-- src/src/globals.c | 4 +- src/src/globals.h | 4 +- src/src/macros.h | 4 ++ src/src/pdkim/pdkim.c | 5 +++ src/src/receive.c | 22 +++++----- src/src/smtp_in.c | 80 +++++++++++++++++++++-------------- src/src/tls-gnu.c | 8 ++-- src/src/tls-openssl.c | 9 ++-- test/log/0901 | 6 ++- test/scripts/0000-Basic/0901 | 48 ++++++++++++++++++++- test/stderr/0021 | 4 ++ test/stderr/0022 | 12 ++++++ test/stderr/0303 | 6 +++ test/stderr/0371 | 5 +++ test/stderr/0386 | 11 +++++ test/stderr/0465 | 6 +++ test/stderr/0487 | 1 + test/stderr/0575 | 4 ++ test/stderr/5410 | 9 ++++ test/stderr/5420 | 9 ++++ test/stdout/0901 | 64 +++++++++++++++++++++++++++- 26 files changed, 283 insertions(+), 73 deletions(-) diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 50309b1f1..156a89f16 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -28,13 +28,23 @@ PP/02 GitHub PR 52: many spelling fixes, which include fixing parsing of no_require_dnssec option and creation of _HAVE_TRANSPORT_APPEND_MAILDIR macro. Patches provided by Josh Soref. -JH/05 Bug 2017: Fix DKIM verification in -bh test mode. The data feed into +JH/05 Have the EHLO response advertise VRFY, if there is a vrfy ACL defined. + Previously we did not; the RFC seems ambiguous and VRFY is not listed + by IANA as a service extension. However, John Klensin suggests that we + should. + +JH/06 Bug 2017: Fix DKIM verification in -bh test mode. The data feed into the dkim code may be unix-mode line endings rather than smtp wire-format CRLF, so prepend a CR to any bare LF. -JH/06 Rationalise the coding for callout smtp conversations and transport ones. +JH/07 Rationalise the coding for callout smtp conversations and transport ones. As a side-benfit, callouts can now use PIPELINING hence fewer round-trips. +JH/08 Bug 2016: Fix DKIM verification vs. CHUNKING. Any BDAT commands after + the first were themselves being wrongly included in the feed into dkim + processing; with most chunk sizes in use this resulted in an incorrect + body hash calculated value. + Exim version 4.88 ----------------- diff --git a/src/src/auths/get_data.c b/src/src/auths/get_data.c index f839a010e..11bc581b9 100644 --- a/src/src/auths/get_data.c +++ b/src/src/auths/get_data.c @@ -31,7 +31,7 @@ auth_get_data(uschar **aptr, uschar *challenge, int challen) int c; int p = 0; smtp_printf("334 %s\r\n", b64encode(challenge, challen)); -while ((c = receive_getc()) != '\n' && c != EOF) +while ((c = receive_getc(GETC_BUFFER_UNLIMITED)) != '\n' && c != EOF) { if (p >= big_buffer_size - 1) return BAD64; big_buffer[p++] = c; diff --git a/src/src/auths/get_no64_data.c b/src/src/auths/get_no64_data.c index d3ffe081e..71e71394c 100644 --- a/src/src/auths/get_no64_data.c +++ b/src/src/auths/get_no64_data.c @@ -32,7 +32,7 @@ auth_get_no64_data(uschar **aptr, uschar *challenge) int c; int p = 0; smtp_printf("334 %s\r\n", challenge); -while ((c = receive_getc()) != '\n' && c != EOF) +while ((c = receive_getc(GETC_BUFFER_UNLIMITED)) != '\n' && c != EOF) { if (p >= big_buffer_size - 1) return BAD64; big_buffer[p++] = c; diff --git a/src/src/dkim.c b/src/src/dkim.c index cc103c289..3573e45e6 100644 --- a/src/src/dkim.c +++ b/src/src/dkim.c @@ -18,6 +18,7 @@ int dkim_verify_oldpool; pdkim_ctx *dkim_verify_ctx = NULL; pdkim_signature *dkim_signatures = NULL; pdkim_signature *dkim_cur_sig = NULL; +static BOOL dkim_collect_error = FALSE; static int dkim_exim_query_dns_txt(char *name, char *answer) @@ -87,6 +88,7 @@ if (dkim_verify_ctx) dkim_verify_ctx = pdkim_init_verify(&dkim_exim_query_dns_txt, dot_stuffing); dkim_collect_input = !!dkim_verify_ctx; +dkim_collect_error = FALSE; /* Start feed up with any cached data */ receive_get_cache(); @@ -106,6 +108,7 @@ if ( dkim_collect_input { log_write(0, LOG_MAIN, "DKIM: validation error: %.100s", pdkim_errstr(rc)); + dkim_collect_error = TRUE; dkim_collect_input = FALSE; } store_pool = dkim_verify_oldpool; @@ -127,11 +130,7 @@ store_pool = POOL_PERM; dkim_signatures = NULL; -/* If we have arrived here with dkim_collect_input == FALSE, it -means there was a processing error somewhere along the way. -Log the incident and disable further verification. */ - -if (!dkim_collect_input) +if (dkim_collect_error) { log_write(0, LOG_MAIN, "DKIM: Error while running this message through validation," diff --git a/src/src/functions.h b/src/src/functions.h index bba8c446b..9c7dbe671 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -55,7 +55,7 @@ extern int tls_export_cert(uschar *, size_t, void *); extern int tls_feof(void); extern int tls_ferror(void); extern void tls_free_cert(void **); -extern int tls_getc(void); +extern int tls_getc(unsigned); extern void tls_get_cache(void); extern int tls_import_cert(const uschar *, void **); extern int tls_read(BOOL, uschar *, size_t); @@ -101,7 +101,7 @@ extern int auth_xtextdecode(uschar *, uschar **); extern uschar *b64encode(uschar *, int); extern int b64decode(uschar *, uschar **); -extern int bdat_getc(void); +extern int bdat_getc(unsigned); extern void bits_clear(unsigned int *, size_t, int *); extern void bits_set(unsigned int *, size_t, int *); @@ -394,7 +394,7 @@ extern uschar *smtp_get_connection_info(void); extern BOOL smtp_get_interface(uschar *, int, address_item *, uschar **, uschar *); extern BOOL smtp_get_port(uschar *, address_item *, int *, uschar *); -extern int smtp_getc(void); +extern int smtp_getc(unsigned); extern void smtp_get_cache(void); extern int smtp_handle_acl_fail(int, int, uschar *, uschar *); extern void smtp_log_no_mail(void); @@ -420,7 +420,7 @@ extern int spool_open_datafile(uschar *); extern int spool_open_temp(uschar *); extern int spool_read_header(uschar *, BOOL, BOOL); extern int spool_write_header(uschar *, int, uschar **); -extern int stdin_getc(void); +extern int stdin_getc(unsigned); extern int stdin_feof(void); extern int stdin_ferror(void); extern int stdin_ungetc(int); diff --git a/src/src/globals.c b/src/src/globals.c index 90e46dff5..bb5acb6fc 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -183,9 +183,9 @@ incoming TCP/IP. The defaults use stdin. We never need these for any stand-alone tests. */ #ifndef STAND_ALONE -int (*lwr_receive_getc)(void) = stdin_getc; +int (*lwr_receive_getc)(unsigned) = stdin_getc; int (*lwr_receive_ungetc)(int) = stdin_ungetc; -int (*receive_getc)(void) = stdin_getc; +int (*receive_getc)(unsigned) = stdin_getc; void (*receive_get_cache)(void)= NULL; int (*receive_ungetc)(int) = stdin_ungetc; int (*receive_feof)(void) = stdin_feof; diff --git a/src/src/globals.h b/src/src/globals.h index 6cd43c08e..62bcb7a98 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -136,9 +136,9 @@ extern uschar *dsn_advertise_hosts; /* host for which TLS is advertised */ /* Input-reading functions for messages, so we can use special ones for incoming TCP/IP. */ -extern int (*lwr_receive_getc)(void); +extern int (*lwr_receive_getc)(unsigned); extern int (*lwr_receive_ungetc)(int); -extern int (*receive_getc)(void); +extern int (*receive_getc)(unsigned); extern void (*receive_get_cache)(void); extern int (*receive_ungetc)(int); extern int (*receive_feof)(void); diff --git a/src/src/macros.h b/src/src/macros.h index 53ffe1b2a..2692714f7 100644 --- a/src/src/macros.h +++ b/src/src/macros.h @@ -968,5 +968,9 @@ enum { FILTER_UNSET, FILTER_FORWARD, FILTER_EXIM, FILTER_SIEVE }; #define PEER_OFFERED_SIZE BIT(6) #define PEER_OFFERED_CHUNKING BIT(7) +/* Argument for *_getc */ + +#define GETC_BUFFER_UNLIMITED UINT_MAX + /* End of macros.h */ diff --git a/src/src/pdkim/pdkim.c b/src/src/pdkim/pdkim.c index 1953c4bd6..4309675e6 100644 --- a/src/src/pdkim/pdkim.c +++ b/src/src/pdkim/pdkim.c @@ -959,6 +959,11 @@ if (ctx->flags & PDKIM_MODE_SIGN) /* DKIM-Signature: headers are added to the verification list */ else { + DEBUG(D_acl) + { + debug_printf("PDKIM >> raw hdr: "); + pdkim_quoteprint(CUS ctx->cur_header, Ustrlen(ctx->cur_header)); + } if (strncasecmp(CCS ctx->cur_header, DKIM_SIGNATURE_HEADERNAME, Ustrlen(DKIM_SIGNATURE_HEADERNAME)) == 0) diff --git a/src/src/receive.c b/src/src/receive.c index 73713aa97..48cdff88c 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -37,7 +37,7 @@ the file. (When SMTP input is occurring, different functions are used by changing the pointer variables.) */ int -stdin_getc(void) +stdin_getc(unsigned lim) { return getc(stdin); } @@ -626,7 +626,7 @@ if (!dot_ends) { register int last_ch = '\n'; - for (; (ch = (receive_getc)()) != EOF; last_ch = ch) + for (; (ch = (receive_getc)(GETC_BUFFER_UNLIMITED)) != EOF; last_ch = ch) { if (ch == 0) body_zerocount++; if (last_ch == '\r' && ch != '\n') @@ -668,7 +668,7 @@ if (!dot_ends) ch_state = 1; -while ((ch = (receive_getc)()) != EOF) +while ((ch = (receive_getc)(GETC_BUFFER_UNLIMITED)) != EOF) { if (ch == 0) body_zerocount++; switch (ch_state) @@ -786,7 +786,7 @@ int ch_state = 0; int ch; int linelength = 0; -while ((ch = (receive_getc)()) != EOF) +while ((ch = (receive_getc)(GETC_BUFFER_UNLIMITED)) != EOF) { if (ch == 0) body_zerocount++; switch (ch_state) @@ -913,7 +913,7 @@ read_message_bdat_smtp(FILE *fout) int ch; int linelength = 0; -for (;;) switch (ch = bdat_getc()) +for (;;) switch (ch = bdat_getc(GETC_BUFFER_UNLIMITED)) { case EOF: return END_EOF; case EOD: return END_DOT; @@ -1682,7 +1682,7 @@ next->text. */ for (;;) { - int ch = (receive_getc)(); + int ch = (receive_getc)(GETC_BUFFER_UNLIMITED); /* If we hit EOF on a SMTP connection, it's an error, since incoming SMTP must have a correct "." terminator. */ @@ -1761,10 +1761,10 @@ for (;;) if (ptr == 0 && ch == '.' && (smtp_input || dot_ends)) { - ch = (receive_getc)(); + ch = (receive_getc)(GETC_BUFFER_UNLIMITED); if (ch == '\r') { - ch = (receive_getc)(); + ch = (receive_getc)(GETC_BUFFER_UNLIMITED); if (ch != '\n') { receive_ungetc(ch); @@ -1795,7 +1795,7 @@ for (;;) if (ch == '\r') { - ch = (receive_getc)(); + ch = (receive_getc)(GETC_BUFFER_UNLIMITED); if (ch == '\n') { if (first_line_ended_crlf == TRUE_UNSET) first_line_ended_crlf = TRUE; @@ -1890,7 +1890,7 @@ for (;;) if (ch != EOF) { - int nextch = (receive_getc)(); + int nextch = (receive_getc)(GETC_BUFFER_UNLIMITED); if (nextch == ' ' || nextch == '\t') { next->text[ptr++] = nextch; @@ -4024,7 +4024,7 @@ if (smtp_input && sender_host_address != NULL && !sender_host_notsocket && if (select(fileno(smtp_in) + 1, &select_check, NULL, NULL, &tv) != 0) { - int c = (receive_getc)(); + int c = (receive_getc)(GETC_BUFFER_UNLIMITED); if (c != EOF) (receive_ungetc)(c); else { smtp_notquit_exit(US"connection-lost", NULL, NULL); diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 79a1ee02b..9c647efda 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -44,11 +44,11 @@ The maximum size of a Kerberos ticket under Windows 2003 is 12000 bytes, and we need room to handle large base64-encoded AUTHs for GSSAPI. */ -#define smtp_cmd_buffer_size 16384 +#define SMTP_CMD_BUFFER_SIZE 16384 /* Size of buffer for reading SMTP incoming packets */ -#define in_buffer_size 8192 +#define IN_BUFFER_SIZE 8192 /* Structure for SMTP command list */ @@ -305,7 +305,7 @@ static int smtp_had_error; /* forward declarations */ int bdat_ungetc(int ch); -static int smtp_read_command(BOOL check_sync); +static int smtp_read_command(BOOL check_sync, unsigned buffer_lim); static int synprot_error(int type, int code, uschar *data, uschar *errmess); static void smtp_quit_handler(uschar **, uschar **); static void smtp_rset_handler(void); @@ -352,7 +352,7 @@ tzero.tv_usec = 0; rc = select(fd + 1, (SELECT_ARG2_TYPE *)&fds, NULL, NULL, &tzero); if (rc <= 0) return TRUE; /* Not ready to read */ -rc = smtp_getc(); +rc = smtp_getc(GETC_BUFFER_UNLIMITED); if (rc < 0) return TRUE; /* End of file or error */ smtp_ungetc(rc); @@ -410,12 +410,12 @@ it flushes the output, and refills the buffer, with a timeout. The signal handler is set appropriately by the calling function. This function is not used after a connection has negotiated itself into an TLS/SSL state. -Arguments: none +Arguments: lim Maximum amount to read/buffer Returns: the next character or EOF */ int -smtp_getc(void) +smtp_getc(unsigned lim) { if (smtp_inptr >= smtp_inend) { @@ -423,7 +423,10 @@ if (smtp_inptr >= smtp_inend) if (!smtp_out) return EOF; fflush(smtp_out); if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout); - rc = read(fileno(smtp_in), smtp_inbuffer, in_buffer_size); + + /* Limit amount read, so non-message data is not fed to DKIM */ + + rc = read(fileno(smtp_in), smtp_inbuffer, MIN(IN_BUFFER_SIZE, lim)); save_errno = errno; alarm(0); if (rc <= 0) @@ -471,23 +474,26 @@ to handle the BDAT command/response. Placed here due to the correlation with the above smtp_getc(), which it wraps, and also by the need to do smtp command/response handling. -Arguments: none +Arguments: lim (ignored) Returns: the next character or ERR, EOD or EOF */ int -bdat_getc(void) +bdat_getc(unsigned lim) { uschar * user_msg = NULL; uschar * log_msg; for(;;) { - if (chunking_data_left-- > 0) - return lwr_receive_getc(); + if (chunking_data_left > 0) + return lwr_receive_getc(chunking_data_left--); receive_getc = lwr_receive_getc; receive_ungetc = lwr_receive_ungetc; +#ifndef DISABLE_DKIM + dkim_collect_input = FALSE; +#endif /* Unless PIPELINING was offered, there should be no next command until after we ack that chunk */ @@ -516,21 +522,22 @@ for(;;) return EOD; } - chunking_state = CHUNKING_OFFERED; smtp_printf("250 %u byte chunk received\r\n", chunking_datasize); + chunking_state = CHUNKING_OFFERED; + DEBUG(D_receive) debug_printf("chunking state %d\n", (int)chunking_state); /* Expect another BDAT cmd from input. RFC 3030 says nothing about QUIT, RSET or NOOP but handling them seems obvious */ next_cmd: - switch(smtp_read_command(TRUE)) + switch(smtp_read_command(TRUE, 1)) { default: (void) synprot_error(L_smtp_protocol_error, 503, NULL, US"only BDAT permissible after non-LAST BDAT"); repeat_until_rset: - switch(smtp_read_command(TRUE)) + switch(smtp_read_command(TRUE, 1)) { case QUIT_CMD: smtp_quit_handler(&user_msg, &log_msg); /*FALLTHROUGH */ case EOF_CMD: return EOF; @@ -569,6 +576,8 @@ next_cmd: chunking_state = strcmpic(smtp_cmd_data+n, US"LAST") == 0 ? CHUNKING_LAST : CHUNKING_ACTIVE; chunking_data_left = chunking_datasize; + DEBUG(D_receive) debug_printf("chunking state %d, %d bytes\n", + (int)chunking_state, chunking_data_left); if (chunking_datasize == 0) if (chunking_state == CHUNKING_LAST) @@ -582,6 +591,9 @@ next_cmd: receive_getc = bdat_getc; receive_ungetc = bdat_ungetc; +#ifndef DISABLE_DKIM + dkim_collect_input = TRUE; +#endif break; /* to top of main loop */ } } @@ -591,15 +603,18 @@ next_cmd: static void bdat_flush_data(void) { -while (chunking_data_left-- > 0) - if (lwr_receive_getc() < 0) +while (chunking_data_left > 0) + if (lwr_receive_getc(chunking_data_left--) < 0) break; receive_getc = lwr_receive_getc; receive_ungetc = lwr_receive_ungetc; if (chunking_state != CHUNKING_LAST) + { chunking_state = CHUNKING_OFFERED; + DEBUG(D_receive) debug_printf("chunking state %d\n", (int)chunking_state); + } } @@ -1234,13 +1249,14 @@ signal handler that closes down the session on a timeout. Control does not return when it runs. Arguments: - check_sync if TRUE, check synchronization rules if global option is TRUE + check_sync if TRUE, check synchronization rules if global option is TRUE + buffer_lim maximum to buffer in lower layer Returns: a code identifying the command (enumerated above) */ static int -smtp_read_command(BOOL check_sync) +smtp_read_command(BOOL check_sync, unsigned buffer_lim) { int c; int ptr = 0; @@ -1249,9 +1265,9 @@ BOOL hadnull = FALSE; os_non_restarting_signal(SIGALRM, command_timeout_handler); -while ((c = (receive_getc)()) != '\n' && c != EOF) +while ((c = (receive_getc)(buffer_lim)) != '\n' && c != EOF) { - if (ptr >= smtp_cmd_buffer_size) + if (ptr >= SMTP_CMD_BUFFER_SIZE) { os_non_restarting_signal(SIGALRM, sigalrm_handler); return OTHER_CMD; @@ -1391,7 +1407,7 @@ if (smtp_in == NULL || smtp_batched_input) return; receive_swallow_smtp(); smtp_printf("421 %s\r\n", message); -for (;;) switch(smtp_read_command(FALSE)) +for (;;) switch(smtp_read_command(FALSE, GETC_BUFFER_UNLIMITED)) { case EOF_CMD: return; @@ -1835,7 +1851,7 @@ while (done <= 0) uschar *recipient = NULL; int start, end, sender_domain, recipient_domain; - switch(smtp_read_command(FALSE)) + switch(smtp_read_command(FALSE, GETC_BUFFER_UNLIMITED)) { /* The HELO/EHLO commands set sender_address_helo if they have valid data; otherwise they are ignored, except that they do @@ -2094,12 +2110,12 @@ acl_var_c = NULL; /* Allow for trailing 0 in the command and data buffers. */ -if (!(smtp_cmd_buffer = US malloc(2*smtp_cmd_buffer_size + 2))) +if (!(smtp_cmd_buffer = US malloc(2*SMTP_CMD_BUFFER_SIZE + 2))) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "malloc() failed for SMTP command buffer"); smtp_cmd_buffer[0] = 0; -smtp_data_buffer = smtp_cmd_buffer + smtp_cmd_buffer_size + 1; +smtp_data_buffer = smtp_cmd_buffer + SMTP_CMD_BUFFER_SIZE + 1; /* For batched input, the protocol setting can be overridden from the command line by a trusted caller. */ @@ -2119,7 +2135,7 @@ else /* Set up the buffer for inputting using direct read() calls, and arrange to call the local functions instead of the standard C ones. */ -if (!(smtp_inbuffer = (uschar *)malloc(in_buffer_size))) +if (!(smtp_inbuffer = (uschar *)malloc(IN_BUFFER_SIZE))) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "malloc() failed for SMTP input buffer"); receive_getc = smtp_getc; @@ -3567,7 +3583,7 @@ while (done <= 0) US &off, sizeof(off)); #endif - switch(smtp_read_command(TRUE)) + switch(smtp_read_command(TRUE, GETC_BUFFER_UNLIMITED)) { /* The AUTH command is not permitted to occur inside a transaction, and may occur successfully only once per connection. Actually, that isn't quite @@ -4768,14 +4784,14 @@ while (done <= 0) chunking_state = strcmpic(smtp_cmd_data+n, US"LAST") == 0 ? CHUNKING_LAST : CHUNKING_ACTIVE; chunking_data_left = chunking_datasize; + DEBUG(D_receive) debug_printf("chunking state %d, %d bytes\n", + (int)chunking_state, chunking_data_left); lwr_receive_getc = receive_getc; lwr_receive_ungetc = receive_ungetc; receive_getc = bdat_getc; receive_ungetc = bdat_ungetc; - DEBUG(D_any) - debug_printf("chunking state %d\n", (int)chunking_state); goto DATA_BDAT; } @@ -4991,7 +5007,7 @@ while (done <= 0) It seems safest to just wipe away the content rather than leave it as a target to jump to. */ - memset(smtp_inbuffer, 0, in_buffer_size); + memset(smtp_inbuffer, 0, IN_BUFFER_SIZE); /* Attempt to start up a TLS session, and if successful, discard all knowledge that was obtained previously. At least, that's what the RFC says, @@ -5045,7 +5061,7 @@ while (done <= 0) set, but we must still reject all incoming commands. */ DEBUG(D_tls) debug_printf("TLS failed to start\n"); - while (done <= 0) switch(smtp_read_command(FALSE)) + while (done <= 0) switch(smtp_read_command(FALSE, GETC_BUFFER_UNLIMITED)) { case EOF_CMD: log_write(L_smtp_connection, LOG_MAIN, "%s closed by EOF", @@ -5333,8 +5349,8 @@ while (done <= 0) case BADSYN_CMD: SYNC_FAILURE: - if (smtp_inend >= smtp_inbuffer + in_buffer_size) - smtp_inend = smtp_inbuffer + in_buffer_size - 1; + if (smtp_inend >= smtp_inbuffer + IN_BUFFER_SIZE) + smtp_inend = smtp_inbuffer + IN_BUFFER_SIZE - 1; c = smtp_inend - smtp_inptr; if (c > 150) c = 150; smtp_inptr[c] = 0; diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index 9ed548a60..7b16fc811 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -2158,12 +2158,12 @@ Only used by the server-side TLS. This feeds DKIM and should be used for all message-body reads. -Arguments: none +Arguments: lim Maximum amount to read/bufffer Returns: the next character or EOF */ int -tls_getc(void) +tls_getc(unsigned lim) { exim_gnutls_state_st *state = &state_server; if (state->xfer_buffer_lwm >= state->xfer_buffer_hwm) @@ -2175,7 +2175,7 @@ if (state->xfer_buffer_lwm >= state->xfer_buffer_hwm) if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout); inbytes = gnutls_record_recv(state->session, state->xfer_buffer, - ssl_xfer_buffer_size); + MIN(ssl_xfer_buffer_size, lim)); alarm(0); /* Timeouts do not get this far; see command_timeout_handler(). @@ -2213,7 +2213,7 @@ if (state->xfer_buffer_lwm >= state->xfer_buffer_hwm) state->tlsp->peercert = NULL; state->tlsp->peerdn = NULL; - return smtp_getc(); + return smtp_getc(lim); } /* Handle genuine errors */ diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index f360f21ae..5a7e92a25 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -2360,14 +2360,14 @@ return OK; /* This gets the next byte from the TLS input buffer. If the buffer is empty, it refills the buffer via the SSL reading function. -Arguments: none +Arguments: lim Maximum amount to read/buffer Returns: the next character or EOF Only used by the server-side TLS. */ int -tls_getc(void) +tls_getc(unsigned lim) { if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm) { @@ -2378,7 +2378,8 @@ if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm) ssl_xfer_buffer, ssl_xfer_buffer_size); if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout); - inbytes = SSL_read(server_ssl, CS ssl_xfer_buffer, ssl_xfer_buffer_size); + inbytes = SSL_read(server_ssl, CS ssl_xfer_buffer, + MIN(ssl_xfer_buffer_size, lim)); error = SSL_get_error(server_ssl, inbytes); alarm(0); @@ -2405,7 +2406,7 @@ if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm) tls_in.peerdn = NULL; tls_in.sni = NULL; - return smtp_getc(); + return smtp_getc(lim); } /* Handle genuine errors */ diff --git a/test/log/0901 b/test/log/0901 index 01135920b..cd8c52e75 100644 --- a/test/log/0901 +++ b/test/log/0901 @@ -4,10 +4,12 @@ 1999-03-02 09:44:33 10HmaX-0005vi-00 <= someone1@some.domain H=(tester) [127.0.0.1] P=esmtp K S=sss for CALLER@test.ex 1999-03-02 09:44:33 10HmaY-0005vi-00 <= someone2@some.domain H=(tester) [127.0.0.1] P=esmtp K S=sss for CALLER@test.ex 1999-03-02 09:44:33 10HmaZ-0005vi-00 <= someone3@some.domain H=(tester) [127.0.0.1] P=esmtp K S=sss for CALLER@test.ex -1999-03-02 09:44:33 10HmbA-0005vi-00 SMTP data timeout (message abandoned) on connection from (tester) [127.0.0.1] F= +1999-03-02 09:44:33 10HmbA-0005vi-00 <= someone2A@some.domain H=(tester) [127.0.0.1] P=esmtp K S=sss for CALLER@test.ex +1999-03-02 09:44:33 10HmbB-0005vi-00 <= someone3A@some.domain H=(tester) [127.0.0.1] P=esmtp K S=sss for CALLER@test.ex +1999-03-02 09:44:33 10HmbC-0005vi-00 SMTP data timeout (message abandoned) on connection from (tester) [127.0.0.1] F= 1999-03-02 09:44:33 SMTP connection from (tester) [127.0.0.1] lost while reading message data 1999-03-02 09:44:33 SMTP connection from (tester) [127.0.0.1] lost while reading message data -1999-03-02 09:44:33 10HmbB-0005vi-00 <= someone8@some.domain H=(tester) [127.0.0.1] P=esmtp K S=sss for CALLER@test.ex +1999-03-02 09:44:33 10HmbD-0005vi-00 <= someone8@some.domain H=(tester) [127.0.0.1] P=esmtp K S=sss for CALLER@test.ex 1999-03-02 09:44:33 SMTP protocol synchronization error (next input sent too soon: pipelining was not advertised): rejected "bdat 1" H=(tester) [127.0.0.1] next input="bdat 87 last\r\n" 1999-03-02 09:44:33 SMTP call from (tester) [127.0.0.1] dropped: too many syntax or protocol errors (last command was "From: Sam@random.com") 1999-03-02 09:44:33 SMTP connection from (tester) [127.0.0.1] lost while reading message data (header) diff --git a/test/scripts/0000-Basic/0901 b/test/scripts/0000-Basic/0901 index a52359966..9908d5ecd 100644 --- a/test/scripts/0000-Basic/0901 +++ b/test/scripts/0000-Basic/0901 @@ -58,8 +58,54 @@ mail from:someone3@some.domain rcpt to:CALLER@test.ex ??? 250 bdat 10 -To: Susan@bdat 78 last +>>> To: Susan@ ??? 250 +bdat 78 last +random.com +From: Sam@random.com +Subject: This is a bodyless test message + +??? 250- +??? 250 +quit +??? 221 +**** +# +# plain, small message (with body) +# nonlast 1st bdat, noop, last-bdat(0) INCORRECTLY PIPELINED +# immediate followon 2nd message +client 127.0.0.1 PORT_D +??? 220 +ehlo tester +??? 250- +??? 250- +??? 250- +??? 250- +??? 250 +mail from:someone2A@some.domain +??? 250 +rcpt to:CALLER@test.ex +??? 250 +bdat 100 +To: Susan@random.com +From: Sam@random.com +Subject: This is a bodyfull test message + +1234567890 +??? 250 +noop +??? 250 +bdat 0 last +??? 250- +??? 250 +mail from:someone3A@some.domain +??? 250 +rcpt to:CALLER@test.ex +??? 250 +bdat 10 +>>> To: Susan@ +??? 250 +bdat 78 last random.com From: Sam@random.com Subject: This is a bodyless test message diff --git a/test/stderr/0021 b/test/stderr/0021 index 7c5a79ee9..4be6c99c5 100644 --- a/test/stderr/0021 +++ b/test/stderr/0021 @@ -178,9 +178,13 @@ LOG: PANIC rcpt accepted accept: condition test succeeded in ACL "rcpt" end of ACL "rcpt": ACCEPT +PDKIM >> raw hdr: {CR}{LF} +PDKIM >> raw hdr: Some{SP}message{CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} >>Headers added by MAIL or RCPT ACL: X-ACL-Warn: added header line >> +PDKIM >> raw hdr: quit{CR}{LF} LOG: MAIN <= ok@test3 H=[10.9.8.8] U=CALLER P=smtp S=sss Exim version x.yz .... diff --git a/test/stderr/0022 b/test/stderr/0022 index bcafb8589..e3269500f 100644 --- a/test/stderr/0022 +++ b/test/stderr/0022 @@ -41,6 +41,9 @@ DSN: orcpt: NULL flags: 0 SMTP<< data SMTP>> 354 Enter message, ending with "." on a line by itself search_tidyup called +PDKIM >> raw hdr: {CR}{LF} +PDKIM >> raw hdr: Testing{CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} >>Headers received: search_tidyup called @@ -54,6 +57,7 @@ P Received: from [V4NET.9.8.7] (envelope-from ) id 10HmbF-0005vi-00 for warn_empty@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 +PDKIM >> raw hdr: quit{CR}{LF} calling local_scan(); timeout=300 local_scan() returned 0 NULL LOG: MAIN @@ -112,6 +116,9 @@ DSN: orcpt: NULL flags: 0 SMTP<< data SMTP>> 354 Enter message, ending with "." on a line by itself search_tidyup called +PDKIM >> raw hdr: {CR}{LF} +PDKIM >> raw hdr: Testing{CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} >>Headers received: search_tidyup called @@ -125,6 +132,7 @@ P Received: from [V4NET.9.8.7] (envelope-from ) id 10HmbG-0005vi-00 for warn_log@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 +PDKIM >> raw hdr: quit{CR}{LF} calling local_scan(); timeout=300 local_scan() returned 0 NULL LOG: MAIN @@ -181,6 +189,9 @@ DSN: orcpt: NULL flags: 0 SMTP<< data SMTP>> 354 Enter message, ending with "." on a line by itself search_tidyup called +PDKIM >> raw hdr: {CR}{LF} +PDKIM >> raw hdr: Testing{CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} >>Headers received: search_tidyup called @@ -197,6 +208,7 @@ P Received: from [V4NET.9.8.7] >>Headers added by MAIL or RCPT ACL: X-ACL-Warn: warn user message >> +PDKIM >> raw hdr: quit{CR}{LF} calling local_scan(); timeout=300 local_scan() returned 0 NULL LOG: MAIN diff --git a/test/stderr/0303 b/test/stderr/0303 index 0a78b30f0..8a77fd613 100644 --- a/test/stderr/0303 +++ b/test/stderr/0303 @@ -89,6 +89,8 @@ DSN: orcpt: NULL flags: 0 SMTP<< data SMTP>> 354 Enter message, ending with "." on a line by itself search_tidyup called +PDKIM >> raw hdr: {CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} >>Headers received: search_tidyup called @@ -101,6 +103,7 @@ P Received: from [V4NET.2.3.4] by myhost.test.ex with esmtp (Exim x.yz) id 10HmaX-0005vi-00 for x@y; Tue, 2 Mar 1999 09:44:33 +0000 +PDKIM >> raw hdr: quit{CR}{LF} calling local_scan(); timeout=300 local_scan() returned 0 NULL LOG: MAIN @@ -165,6 +168,8 @@ DSN: orcpt: NULL flags: 0 SMTP<< data SMTP>> 354 Enter message, ending with "." on a line by itself search_tidyup called +PDKIM >> raw hdr: {CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} >>Headers received: search_tidyup called @@ -177,6 +182,7 @@ P Received: from host.name.tld ([V4NET.2.3.4]) by myhost.test.ex with esmtp (Exim x.yz) id 10HmaY-0005vi-00 for x@y; Tue, 2 Mar 1999 09:44:33 +0000 +PDKIM >> raw hdr: quit{CR}{LF} calling local_scan(); timeout=300 local_scan() returned 0 NULL LOG: MAIN diff --git a/test/stderr/0371 b/test/stderr/0371 index c59988723..25c6cdbee 100644 --- a/test/stderr/0371 +++ b/test/stderr/0371 @@ -74,6 +74,10 @@ DSN: orcpt: NULL flags: 0 SMTP<< data SMTP>> 354 Enter message, ending with "." on a line by itself search_tidyup called +PDKIM >> raw hdr: {CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} +PDKIM >> raw hdr: vrfy{SP}x@y{CR}{LF} +PDKIM >> raw hdr: mail{SP}from:{CR}{LF} >>Headers received: search_tidyup called @@ -87,6 +91,7 @@ P Received: from [V4NET.0.0.0] (helo=something) (envelope-from ) id 10HmaX-0005vi-00 for x@y; Tue, 2 Mar 1999 09:44:33 +0000 +PDKIM >> raw hdr: quit{CR}{LF} using ACL "data" processing "accept" check set acl_m0 = $acl_m0; data diff --git a/test/stderr/0386 b/test/stderr/0386 index 44e856da2..be777a736 100644 --- a/test/stderr/0386 +++ b/test/stderr/0386 @@ -191,6 +191,13 @@ DSN: orcpt: NULL flags: 0 SMTP<< data SMTP>> 354 Enter message, ending with "." on a line by itself search_tidyup called +PDKIM >> raw hdr: {CR}{LF} +PDKIM >> raw hdr: Message{SP}1{CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} +PDKIM >> raw hdr: rset{CR}{LF} +PDKIM >> raw hdr: mail{SP}from:{CR}{LF} +PDKIM >> raw hdr: rcpt{SP}to:<2@b>{CR}{LF} +PDKIM >> raw hdr: data{CR}{LF} >>Headers received: search_tidyup called @@ -372,6 +379,9 @@ DSN: orcpt: NULL flags: 0 SMTP<< data SMTP>> 354 Enter message, ending with "." on a line by itself search_tidyup called +PDKIM >> raw hdr: {CR}{LF} +PDKIM >> raw hdr: Message{SP}2{CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} >>Headers received: search_tidyup called @@ -389,6 +399,7 @@ P Received: from [V4NET.11.12.13] (ident=CALLER) X-Warning: V4NET.11.12.13 is listed at rbl.test.ex X-Warning: This is a test blacklisting message >> +PDKIM >> raw hdr: quit{CR}{LF} calling local_scan(); timeout=300 local_scan() returned 0 NULL Writing spool header file: TESTSUITE/spool//input//hdr.pppp diff --git a/test/stderr/0465 b/test/stderr/0465 index 92250956d..594bd002c 100644 --- a/test/stderr/0465 +++ b/test/stderr/0465 @@ -62,6 +62,8 @@ DSN: orcpt: NULL flags: 0 SMTP<< data SMTP>> 354 Enter message, ending with "." on a line by itself search_tidyup called +PDKIM >> raw hdr: To:{SP}abc@domain.{CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} >>Headers received: To: abc@domain. @@ -79,6 +81,7 @@ Data file written for message 10HmaY-0005vi-00 P Received: from CALLER by myhost.test.ex with local-smtp (Exim x.yz) id 10HmaY-0005vi-00 for abc@domain; Tue, 2 Mar 1999 09:44:33 +0000 +PDKIM >> raw hdr: quit{CR}{LF} using ACL "check_data" processing "accept" check verify = header_syntax @@ -135,6 +138,8 @@ DSN: orcpt: NULL flags: 0 SMTP<< data SMTP>> 354 Enter message, ending with "." on a line by itself search_tidyup called +PDKIM >> raw hdr: To:{SP}abc@xyz.{CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} >>Headers received: To: abc@xyz. @@ -152,6 +157,7 @@ Data file written for message 10HmaX-0005vi-00 P Received: from CALLER by myhost.test.ex with local-smtp (Exim x.yz) id 10HmaX-0005vi-00 for abc@xyz; Tue, 2 Mar 1999 09:44:33 +0000 +PDKIM >> raw hdr: quit{CR}{LF} using ACL "check_data" processing "accept" check verify = header_syntax diff --git a/test/stderr/0487 b/test/stderr/0487 index 7319b67dd..c16127b83 100644 --- a/test/stderr/0487 +++ b/test/stderr/0487 @@ -41,6 +41,7 @@ DSN: orcpt: NULL flags: 0 SMTP<< data SMTP>> 354 Enter message, ending with "." on a line by itself search_tidyup called +PDKIM >> raw hdr: From:{SP}unqualified{CR}{LF} >>Headers received: From: unqualified diff --git a/test/stderr/0575 b/test/stderr/0575 index 210f868ad..37176f114 100644 --- a/test/stderr/0575 +++ b/test/stderr/0575 @@ -35,6 +35,9 @@ DSN: orcpt: NULL flags: 0 SMTP<< data SMTP>> 354 Enter message, ending with "." on a line by itself search_tidyup called +PDKIM >> raw hdr: {CR}{LF} +PDKIM >> raw hdr: Message.{CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} >>Headers received: search_tidyup called @@ -48,6 +51,7 @@ P Received: from [V4NET.0.0.0] (envelope-from ) id 10HmaX-0005vi-00 for x@y; Tue, 2 Mar 1999 09:44:33 +0000 +PDKIM >> raw hdr: quit{CR}{LF} calling local_scan(); timeout=300 local_scan() returned 0 NULL LOG: MAIN diff --git a/test/stderr/5410 b/test/stderr/5410 index acfc011cc..04c805275 100644 --- a/test/stderr/5410 +++ b/test/stderr/5410 @@ -131,6 +131,8 @@ accept: condition test succeeded in inline ACL end of inline ACL: ACCEPT SMTP>> DATA SMTP<< 354 Enter message, ending with "." on a line by itself +PDKIM >> raw hdr: {CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} considering: ${tod_full} expanding: ${tod_full} result: Tue, 2 Mar 1999 09:44:33 +0000 @@ -227,6 +229,7 @@ considering: for userx@domain.com ----------- start cutthrough headers send ----------- ----------- done cutthrough headers send ------------ +PDKIM >> raw hdr: QUIT{CR}{LF} considering: ${tod_full} expanding: ${tod_full} result: Tue, 2 Mar 1999 09:44:33 +0000 @@ -345,6 +348,8 @@ accept: condition test succeeded in inline ACL end of inline ACL: ACCEPT SMTP>> DATA SMTP<< 354 Enter message, ending with "." on a line by itself +PDKIM >> raw hdr: {CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} considering: ${tod_full} expanding: ${tod_full} result: Tue, 2 Mar 1999 09:44:33 +0000 @@ -441,6 +446,7 @@ considering: for usery@domain.com ----------- start cutthrough headers send ----------- ----------- done cutthrough headers send ------------ +PDKIM >> raw hdr: QUIT{CR}{LF} considering: ${tod_full} expanding: ${tod_full} result: Tue, 2 Mar 1999 09:44:33 +0000 @@ -559,6 +565,8 @@ accept: condition test succeeded in inline ACL end of inline ACL: ACCEPT SMTP>> DATA SMTP<< 354 Enter message, ending with "." on a line by itself +PDKIM >> raw hdr: {CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} considering: ${tod_full} expanding: ${tod_full} result: Tue, 2 Mar 1999 09:44:33 +0000 @@ -655,6 +663,7 @@ considering: for usery@domain.com ----------- start cutthrough headers send ----------- ----------- done cutthrough headers send ------------ +PDKIM >> raw hdr: QUIT{CR}{LF} considering: ${tod_full} expanding: ${tod_full} result: Tue, 2 Mar 1999 09:44:33 +0000 diff --git a/test/stderr/5420 b/test/stderr/5420 index ff032e986..a4f64f2d1 100644 --- a/test/stderr/5420 +++ b/test/stderr/5420 @@ -130,6 +130,8 @@ accept: condition test succeeded in inline ACL end of inline ACL: ACCEPT SMTP>> DATA SMTP<< 354 Enter message, ending with "." on a line by itself +PDKIM >> raw hdr: {CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} considering: ${tod_full} expanding: ${tod_full} result: Tue, 2 Mar 1999 09:44:33 +0000 @@ -226,6 +228,7 @@ considering: for userx@domain.com ----------- start cutthrough headers send ----------- ----------- done cutthrough headers send ------------ +PDKIM >> raw hdr: QUIT{CR}{LF} considering: ${tod_full} expanding: ${tod_full} result: Tue, 2 Mar 1999 09:44:33 +0000 @@ -344,6 +347,8 @@ accept: condition test succeeded in inline ACL end of inline ACL: ACCEPT SMTP>> DATA SMTP<< 354 Enter message, ending with "." on a line by itself +PDKIM >> raw hdr: {CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} considering: ${tod_full} expanding: ${tod_full} result: Tue, 2 Mar 1999 09:44:33 +0000 @@ -440,6 +445,7 @@ considering: for usery@domain.com ----------- start cutthrough headers send ----------- ----------- done cutthrough headers send ------------ +PDKIM >> raw hdr: QUIT{CR}{LF} considering: ${tod_full} expanding: ${tod_full} result: Tue, 2 Mar 1999 09:44:33 +0000 @@ -558,6 +564,8 @@ accept: condition test succeeded in inline ACL end of inline ACL: ACCEPT SMTP>> DATA SMTP<< 354 Enter message, ending with "." on a line by itself +PDKIM >> raw hdr: {CR}{LF} +PDKIM >> raw hdr: .{CR}{LF} considering: ${tod_full} expanding: ${tod_full} result: Tue, 2 Mar 1999 09:44:33 +0000 @@ -654,6 +662,7 @@ considering: for usery@domain.com ----------- start cutthrough headers send ----------- ----------- done cutthrough headers send ------------ +PDKIM >> raw hdr: QUIT{CR}{LF} considering: ${tod_full} expanding: ${tod_full} result: Tue, 2 Mar 1999 09:44:33 +0000 diff --git a/test/stdout/0901 b/test/stdout/0901 index 0e35d76c3..99eb81231 100644 --- a/test/stdout/0901 +++ b/test/stdout/0901 @@ -74,9 +74,10 @@ Connecting to 127.0.0.1 port 1225 ... connected ??? 250 <<< 250 Accepted >>> bdat 10 ->>> To: Susan@bdat 78 last +>>> To: Susan@ ??? 250 <<< 250 10 byte chunk received +>>> bdat 78 last >>> random.com >>> From: Sam@random.com >>> Subject: This is a bodyless test message @@ -103,6 +104,65 @@ Connecting to 127.0.0.1 port 1225 ... connected <<< 250-CHUNKING ??? 250 <<< 250 HELP +>>> mail from:someone2A@some.domain +??? 250 +<<< 250 OK +>>> rcpt to:CALLER@test.ex +??? 250 +<<< 250 Accepted +>>> bdat 100 +>>> To: Susan@random.com +>>> From: Sam@random.com +>>> Subject: This is a bodyfull test message +>>> +>>> 1234567890 +??? 250 +<<< 250 100 byte chunk received +>>> noop +??? 250 +<<< 250 OK +>>> bdat 0 last +??? 250- +<<< 250- 0 byte chunk, total 100 +??? 250 +<<< 250 OK id=10HmbA-0005vi-00 +>>> mail from:someone3A@some.domain +??? 250 +<<< 250 OK +>>> rcpt to:CALLER@test.ex +??? 250 +<<< 250 Accepted +>>> bdat 10 +>>> To: Susan@ +??? 250 +<<< 250 10 byte chunk received +>>> bdat 78 last +>>> random.com +>>> From: Sam@random.com +>>> Subject: This is a bodyless test message +>>> +??? 250- +<<< 250- 78 byte chunk, total 88 +??? 250 +<<< 250 OK id=10HmbB-0005vi-00 +>>> quit +??? 221 +<<< 221 testhost.test.ex closing connection +End of script +Connecting to 127.0.0.1 port 1225 ... connected +??? 220 +<<< 220 testhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +>>> ehlo tester +??? 250- +<<< 250-testhost.test.ex Hello tester [127.0.0.1] +??? 250- +<<< 250-SIZE 52428800 +??? 250- +<<< 250-8BITMIME +??? 250- +<<< 250-CHUNKING +??? 250 +<<< 250 HELP >>> mail from:someone4@some.domain ??? 250 <<< 250 OK @@ -245,7 +305,7 @@ Connecting to 127.0.0.1 port 1225 ... connected ??? 250- <<< 250- 88 byte chunk, total 88 ??? 250 -<<< 250 OK id=10HmbB-0005vi-00 +<<< 250 OK id=10HmbD-0005vi-00 >>> quit ??? 221 <<< 221 testhost.test.ex closing connection -- 2.25.1