X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/90341c71c19c82ba8b1cbf4d1693940b8bb8f70b..57cc27852af9019c0c423bcfde0165e698a0ce54:/src/src/smtp_in.c diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index bd83de045..3c40a5c61 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -304,7 +304,6 @@ static int smtp_had_error; /* forward declarations */ -int bdat_ungetc(int ch); 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 **); @@ -486,12 +485,17 @@ uschar * log_msg; for(;;) { +#ifndef DISABLE_DKIM + BOOL dkim_save; +#endif + 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_save = dkim_collect_input; dkim_collect_input = FALSE; #endif @@ -592,7 +596,7 @@ next_cmd: receive_getc = bdat_getc; receive_ungetc = bdat_ungetc; #ifndef DISABLE_DKIM - dkim_collect_input = TRUE; + dkim_collect_input = dkim_save; #endif break; /* to top of main loop */ } @@ -945,43 +949,45 @@ Return the amount read. static int swallow_until_crlf(int fd, uschar *base, int already, int capacity) { - uschar *to = base + already; - uschar *cr; - int have = 0; - int ret; - int last = 0; - - /* For "PROXY UNKNOWN\r\n" we, at time of writing, expect to have read - up through the \r; for the _normal_ case, we haven't yet seen the \r. */ - cr = memchr(base, '\r', already); - if (cr != NULL) - { - if ((cr - base) < already - 1) - { - /* \r and presumed \n already within what we have; probably not - actually proxy protocol, but abort cleanly. */ - return 0; - } - /* \r is last character read, just need one more. */ - last = 1; - } +uschar *to = base + already; +uschar *cr; +int have = 0; +int ret; +int last = 0; + +/* For "PROXY UNKNOWN\r\n" we, at time of writing, expect to have read +up through the \r; for the _normal_ case, we haven't yet seen the \r. */ - while (capacity > 0) +cr = memchr(base, '\r', already); +if (cr != NULL) + { + if ((cr - base) < already - 1) { - do { ret = recv(fd, to, 1, 0); } while (ret == -1 && errno == EINTR); - if (ret == -1) - return -1; - have++; - if (last) - return have; - if (*to == '\r') - last = 1; - capacity--; - to++; + /* \r and presumed \n already within what we have; probably not + actually proxy protocol, but abort cleanly. */ + return 0; } - // reached end without having room for a final newline, abort - errno = EOVERFLOW; - return -1; + /* \r is last character read, just need one more. */ + last = 1; + } + +while (capacity > 0) + { + do { ret = recv(fd, to, 1, 0); } while (ret == -1 && errno == EINTR); + if (ret == -1) + return -1; + have++; + if (last) + return have; + if (*to == '\r') + last = 1; + capacity--; + to++; + } + +/* reached end without having room for a final newline, abort */ +errno = EOVERFLOW; +return -1; } /************************************************* @@ -1089,9 +1095,9 @@ if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CS &tv, sizeof(tv)) < 0) do { /* The inbound host was declared to be a Proxy Protocol host, so - don't do a PEEK into the data, actually slurp up enough to be - "safe". Can't take it all because TLS-on-connect clients follow - immediately with TLS handshake. */ + don't do a PEEK into the data, actually slurp up enough to be + "safe". Can't take it all because TLS-on-connect clients follow + immediately with TLS handshake. */ ret = recv(fd, &hdr, PROXY_INITIAL_READ, 0); } while (ret == -1 && errno == EINTR); @@ -1117,9 +1123,9 @@ if ((ret == PROXY_INITIAL_READ) && (memcmp(&hdr.v2, v2sig, sizeof(v2sig)) == 0)) ver = (hdr.v2.ver_cmd & 0xf0) >> 4; /* May 2014: haproxy combined the version and command into one byte to - allow two full bytes for the length field in order to proxy SSL - connections. SSL Proxy is not supported in this version of Exim, but - must still separate values here. */ + allow two full bytes for the length field in order to proxy SSL + connections. SSL Proxy is not supported in this version of Exim, but + must still separate values here. */ if (ver != 0x02) { @@ -1266,7 +1272,7 @@ else if (ret >= 8 && memcmp(hdr.v1.line, "PROXY", 5) == 0) DEBUG(D_receive) debug_printf("Detected PROXYv1 header\n"); DEBUG(D_receive) debug_printf("Bytes read not within PROXY header: %d\n", ret - size); /* Step through the string looking for the required fields. Ensure - strict adherence to required formatting, exit for any error. */ + strict adherence to required formatting, exit for any error. */ p += 5; if (!isspace(*(p++))) { @@ -1881,7 +1887,6 @@ smtp_reset(void *reset_point) recipients_list = NULL; rcpt_count = rcpt_defer_count = rcpt_fail_count = raw_recipients_count = recipients_count = recipients_list_max = 0; -cancel_cutthrough_connection("smtp reset"); message_linecount = 0; message_size = -1; acl_added_headers = NULL; @@ -2012,6 +2017,7 @@ bsmtp_transaction_linecount = receive_linecount; if ((receive_feof)()) return 0; /* Treat EOF as QUIT */ +cancel_cutthrough_connection(TRUE, US"smtp_setup_batch_msg"); smtp_reset(reset_point); /* Reset for start of message */ /* Deal with SMTP commands. This loop is exited by setting done to a POSITIVE @@ -2036,6 +2042,7 @@ while (done <= 0) /* Fall through */ case RSET_CMD: + cancel_cutthrough_connection(TRUE, US"RSET received"); smtp_reset(reset_point); bsmtp_transaction_linecount = receive_linecount; break; @@ -2059,6 +2066,7 @@ while (done <= 0) /* Reset to start of message */ + cancel_cutthrough_connection(TRUE, US"MAIL received"); smtp_reset(reset_point); /* Apply SMTP rewrite */ @@ -2218,6 +2226,19 @@ return done - 2; /* Convert yield values */ +static BOOL +smtp_log_tls_fail(uschar * errstr) +{ +uschar * conn_info = smtp_get_connection_info(); + +if (Ustrncmp(conn_info, US"SMTP ", 5) == 0) conn_info += 5; +/* I'd like to get separated H= here, but too hard for now */ + +log_write(0, LOG_MAIN, "TLS error on %s %s", conn_info, errstr); +return FALSE; +} + + /************************************************* * Start an SMTP session * *************************************************/ @@ -2706,8 +2727,8 @@ if (check_proxy_protocol_host()) smtps port for use with older style SSL MTAs. */ #ifdef SUPPORT_TLS - if (tls_in.on_connect && tls_server_start(tls_require_ciphers) != OK) - return FALSE; + if (tls_in.on_connect && tls_server_start(tls_require_ciphers, &user_msg) != OK) + return smtp_log_tls_fail(user_msg); #endif /* Run the connect ACL if it exists */ @@ -4234,6 +4255,7 @@ while (done <= 0) : pnormal) + (tls_in.active >= 0 ? pcrpted : 0) ]; + cancel_cutthrough_connection(TRUE, US"sent EHLO response"); smtp_reset(reset_point); toomany = FALSE; break; /* HELO/EHLO */ @@ -4288,6 +4310,7 @@ while (done <= 0) /* Reset for start of message - even if this is going to fail, we obviously need to throw away any previous data. */ + cancel_cutthrough_connection(TRUE, US"MAIL received"); smtp_reset(reset_point); toomany = FALSE; sender_data = recipient_data = NULL; @@ -5143,6 +5166,7 @@ while (done <= 0) do an implied RSET when STARTTLS is received. */ incomplete_transaction_log(US"STARTTLS"); + cancel_cutthrough_connection(TRUE, US"STARTTLS received"); smtp_reset(reset_point); toomany = FALSE; cmd_list[CMD_LIST_STARTTLS].is_mail_cmd = FALSE; @@ -5181,7 +5205,8 @@ while (done <= 0) We must allow for an extra EHLO command and an extra AUTH command after STARTTLS that don't add to the nonmail command count. */ - if ((rc = tls_server_start(tls_require_ciphers)) == OK) + s = NULL; + if ((rc = tls_server_start(tls_require_ciphers, &s)) == OK) { if (!tls_remember_esmtp) helo_seen = esmtp = auth_advertised = pipelining_advertised = FALSE; @@ -5210,11 +5235,13 @@ while (done <= 0) DEBUG(D_tls) debug_printf("TLS active\n"); break; /* Successful STARTTLS */ } + else + (void) smtp_log_tls_fail(s); /* Some local configuration problem was discovered before actually trying to do a TLS handshake; give a temporary error. */ - else if (rc == DEFER) + if (rc == DEFER) { smtp_printf("454 TLS currently unavailable\r\n"); break; @@ -5276,6 +5303,7 @@ while (done <= 0) case RSET_CMD: smtp_rset_handler(); + cancel_cutthrough_connection(TRUE, US"RSET received"); smtp_reset(reset_point); toomany = FALSE; break;