X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/6d5c916cc5720591335fea53242dd6b97ea56fe3..60d10ce7e68a5f2cf771a5c079521c8e4f18d157:/src/src/smtp_in.c diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 3144b39ad..9484105d6 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -325,6 +325,7 @@ smtp_getc(void) if (smtp_inptr >= smtp_inend) { int rc, save_errno; + 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); @@ -352,6 +353,15 @@ if (smtp_inptr >= smtp_inend) return *smtp_inptr++; } +void +smtp_get_cache(void) +{ +#ifndef DISABLE_DKIM +int n = smtp_inend - smtp_inptr; +if (n > 0) + dkim_exim_verify_feed(smtp_inptr, n); +#endif +} /* Get a byte from the smtp input, in CHUNKING mode. Handle ack of the @@ -386,10 +396,14 @@ for(;;) /* If not the last, ack the received chunk. The last response is delayed until after the data ACL decides on it */ - /*XXX find that "last response" and append the chunk size */ if (chunking_state == CHUNKING_LAST) + { +#ifndef DISABLE_DKIM + dkim_exim_verify_feed(NULL, 0); /* notify EOD */ +#endif return EOD; + } chunking_state = CHUNKING_OFFERED; smtp_printf("250 %u byte chunk received\r\n", chunking_datasize); @@ -463,6 +477,20 @@ next_cmd: } } +static void +bdat_flush_data(void) +{ +while (chunking_data_left-- > 0) + if (lwr_receive_getc() < 0) + break; + +receive_getc = lwr_receive_getc; +receive_ungetc = lwr_receive_ungetc; + +if (chunking_state != CHUNKING_LAST) + chunking_state = CHUNKING_OFFERED; +} + @@ -1316,26 +1344,23 @@ if (smtp_in == NULL || smtp_batched_input) return; receive_swallow_smtp(); smtp_printf("421 %s\r\n", message); -for (;;) +for (;;) switch(smtp_read_command(FALSE)) { - switch(smtp_read_command(FALSE)) - { - case EOF_CMD: - return; + case EOF_CMD: + return; - case QUIT_CMD: - smtp_printf("221 %s closing connection\r\n", smtp_active_hostname); - mac_smtp_fflush(); - return; + case QUIT_CMD: + smtp_printf("221 %s closing connection\r\n", smtp_active_hostname); + mac_smtp_fflush(); + return; - case RSET_CMD: - smtp_printf("250 Reset OK\r\n"); - break; + case RSET_CMD: + smtp_printf("250 Reset OK\r\n"); + break; - default: - smtp_printf("421 %s\r\n", message); - break; - } + default: + smtp_printf("421 %s\r\n", message); + break; } } @@ -2022,10 +2047,10 @@ acl_var_c = NULL; /* Allow for trailing 0 in the command and data buffers. */ -smtp_cmd_buffer = (uschar *)malloc(2*smtp_cmd_buffer_size + 2); -if (smtp_cmd_buffer == NULL) +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; @@ -2034,7 +2059,7 @@ command line by a trusted caller. */ if (smtp_batched_input) { - if (received_protocol == NULL) received_protocol = US"local-bsmtp"; + if (!received_protocol) received_protocol = US"local-bsmtp"; } /* For non-batched SMTP input, the protocol setting is forced here. It will be @@ -2047,10 +2072,11 @@ else /* Set up the buffer for inputting using direct read() calls, and arrange to call the local functions instead of the standard C ones. */ -smtp_inbuffer = (uschar *)malloc(in_buffer_size); -if (smtp_inbuffer == NULL) +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; +receive_get_cache = smtp_get_cache; receive_ungetc = smtp_ungetc; receive_feof = smtp_feof; receive_ferror = smtp_ferror; @@ -2933,8 +2959,9 @@ if (lognl != NULL) *lognl = 0; always a 5xx one - see comments at the start of this function. If the original rc was FAIL_DROP we drop the connection and yield 2. */ -if (rc == FAIL) smtp_respond(smtp_code, codelen, TRUE, (user_msg == NULL)? - US"Administrative prohibition" : user_msg); +if (rc == FAIL) + smtp_respond(smtp_code, codelen, TRUE, + user_msg ? user_msg : US"Administrative prohibition"); /* Send temporary failure response to the command. Don't give any details, unless acl_temp_details is set. This is TRUE for a callout defer, a "defer" @@ -2945,21 +2972,19 @@ interactions between temp_details and return_error_details. One day it should be re-implemented in a tidier fashion. */ else - { - if (acl_temp_details && user_msg != NULL) + if (acl_temp_details && user_msg) { - if (smtp_return_error_details && - sender_verified_failed != NULL && - sender_verified_failed->message != NULL) - { + if ( smtp_return_error_details + && sender_verified_failed + && sender_verified_failed->message + ) smtp_respond(smtp_code, codelen, FALSE, sender_verified_failed->message); - } + smtp_respond(smtp_code, codelen, TRUE, user_msg); } else smtp_respond(smtp_code, codelen, TRUE, US"Temporary local problem - please try later"); - } /* Log the incident to the logs that are specified by log_reject_target (default main, reject). This can be empty to suppress logging of rejections. If @@ -3043,12 +3068,11 @@ smtp_exit_function_called = TRUE; /* Call the not-QUIT ACL, if there is one, unless no reason is given. */ -if (acl_smtp_notquit != NULL && reason != NULL) +if (acl_smtp_notquit && reason) { smtp_notquit_reason = reason; - rc = acl_check(ACL_WHERE_NOTQUIT, NULL, acl_smtp_notquit, &user_msg, - &log_msg); - if (rc == ERROR) + if ((rc = acl_check(ACL_WHERE_NOTQUIT, NULL, acl_smtp_notquit, &user_msg, + &log_msg)) == ERROR) log_write(0, LOG_MAIN|LOG_PANIC, "ACL for not-QUIT returned ERROR: %s", log_msg); } @@ -3058,9 +3082,11 @@ responses are all internal, they should always fit in the buffer, but code a warning, just in case. Note that string_vformat() still leaves a complete string, even if it is incomplete. */ -if (code != NULL && defaultrespond != NULL) +if (code && defaultrespond) { - if (user_msg == NULL) + if (user_msg) + smtp_respond(code, 3, TRUE, user_msg); + else { uschar buffer[128]; va_list ap; @@ -3070,8 +3096,6 @@ if (code != NULL && defaultrespond != NULL) smtp_printf("%s %s\r\n", code, buffer); va_end(ap); } - else - smtp_respond(code, 3, TRUE, user_msg); mac_smtp_fflush(); } } @@ -3377,7 +3401,7 @@ smtp_quit_handler(uschar ** user_msgp, uschar ** log_msgp) { HAD(SCH_QUIT); incomplete_transaction_log(US"QUIT"); -if (acl_smtp_quit != NULL) +if (acl_smtp_quit) { int rc = acl_check(ACL_WHERE_QUIT, NULL, acl_smtp_quit, user_msgp, log_msgp); if (rc == ERROR) @@ -4762,6 +4786,9 @@ while (done <= 0) smtp_connection_had[smtp_ch_index-1] == SCH_DATA ? US"valid RCPT command must precede DATA" : US"valid RCPT command must precede BDAT"); + + if (chunking_state > CHUNKING_OFFERED) + bdat_flush_data(); break; } @@ -4997,45 +5024,39 @@ 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) + while (done <= 0) switch(smtp_read_command(FALSE)) { - switch(smtp_read_command(FALSE)) - { - case EOF_CMD: - log_write(L_smtp_connection, LOG_MAIN, "%s closed by EOF", - smtp_get_connection_info()); - smtp_notquit_exit(US"tls-failed", NULL, NULL); - done = 2; - break; - - /* It is perhaps arguable as to which exit ACL should be called here, - but as it is probably a situation that almost never arises, it - probably doesn't matter. We choose to call the real QUIT ACL, which in - some sense is perhaps "right". */ + case EOF_CMD: + log_write(L_smtp_connection, LOG_MAIN, "%s closed by EOF", + smtp_get_connection_info()); + smtp_notquit_exit(US"tls-failed", NULL, NULL); + done = 2; + break; - case QUIT_CMD: - user_msg = NULL; - if (acl_smtp_quit != NULL) - { - rc = acl_check(ACL_WHERE_QUIT, NULL, acl_smtp_quit, &user_msg, - &log_msg); - if (rc == ERROR) - log_write(0, LOG_MAIN|LOG_PANIC, "ACL for QUIT returned ERROR: %s", - log_msg); - } - if (user_msg == NULL) - smtp_printf("221 %s closing connection\r\n", smtp_active_hostname); - else - smtp_respond(US"221", 3, TRUE, user_msg); - log_write(L_smtp_connection, LOG_MAIN, "%s closed by QUIT", - smtp_get_connection_info()); - done = 2; - break; + /* It is perhaps arguable as to which exit ACL should be called here, + but as it is probably a situation that almost never arises, it + probably doesn't matter. We choose to call the real QUIT ACL, which in + some sense is perhaps "right". */ + + case QUIT_CMD: + user_msg = NULL; + if ( acl_smtp_quit + && ((rc = acl_check(ACL_WHERE_QUIT, NULL, acl_smtp_quit, &user_msg, + &log_msg)) == ERROR)) + log_write(0, LOG_MAIN|LOG_PANIC, "ACL for QUIT returned ERROR: %s", + log_msg); + if (user_msg) + smtp_respond(US"221", 3, TRUE, user_msg); + else + smtp_printf("221 %s closing connection\r\n", smtp_active_hostname); + log_write(L_smtp_connection, LOG_MAIN, "%s closed by QUIT", + smtp_get_connection_info()); + done = 2; + break; - default: - smtp_printf("554 Security failure\r\n"); - break; - } + default: + smtp_printf("554 Security failure\r\n"); + break; } tls_close(TRUE, TRUE); break;