X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/4e910c01eea401e36044816744691789ef4656fa..a2701501f3e077cba8d3da47e0a5522acffcee3c:/src/src/verify.c diff --git a/src/src/verify.c b/src/src/verify.c index de4ffbe48..b957c709b 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -68,9 +68,7 @@ int length, expire; time_t now; dbdata_callout_cache *cache_record; -cache_record = dbfn_read_with_length(dbm_file, key, &length); - -if (cache_record == NULL) +if (!(cache_record = dbfn_read_with_length(dbm_file, key, &length))) { HDEBUG(D_verify) debug_printf("callout cache: no %s record found for %s\n", type, key); return NULL; @@ -785,19 +783,26 @@ tls_retry_connection: postmaster-verify. The sync_responses() would need to be taught about it and we'd need another return code filtering out to here. + + Avoid using a SIZE option on the MAIL for all randon-rcpt checks. */ + sx.avoid_option = OPTION_SIZE; + /* Remember when we last did a random test */ new_domain_record.random_stamp = time(NULL); if (smtp_write_mail_and_rcpt_cmds(&sx, &yield) == 0) switch(addr->transport_return) { - case PENDING_OK: + case PENDING_OK: /* random was accepted, unfortunately */ new_domain_record.random_result = ccache_accept; - break; - case FAIL: + yield = OK; /* Only usable verify result we can return */ + done = TRUE; + goto no_conn; + case FAIL: /* rejected: the preferred result */ new_domain_record.random_result = ccache_reject; + sx.avoid_option = 0; /* Between each check, issue RSET, because some servers accept only one recipient after MAIL FROM:<>. @@ -829,6 +834,8 @@ tls_retry_connection: sx.send_rset = TRUE; sx.completed_addr = FALSE; goto tls_retry_connection; + case DEFER: /* 4xx response to random */ + break; /* Just to be clear. ccache_unknown, !done. */ } /* Re-setup for main verify, or for the error message when failing */ @@ -842,12 +849,14 @@ tls_retry_connection: else done = TRUE; - /* Main verify. If the host is accepting all local parts, as determined - by the "random" check, we don't need to waste time doing any further - checking. */ + /* Main verify. For rcpt-verify use SIZE if we know it and we're not cacheing; + for sndr-verify never use it. */ if (done) { + if (!(options & vopt_is_recipient && options & vopt_callout_no_cache)) + sx.avoid_option = OPTION_SIZE; + done = FALSE; switch(smtp_write_mail_and_rcpt_cmds(&sx, &yield)) { @@ -856,12 +865,12 @@ tls_retry_connection: case PENDING_OK: done = TRUE; new_address_record.result = ccache_accept; break; - case FAIL: done = TRUE; + case FAIL: done = TRUE; yield = FAIL; *failure_ptr = US"recipient"; new_address_record.result = ccache_reject; break; - default: break; + default: break; } break; @@ -914,6 +923,7 @@ tls_retry_connection: sx.ok = FALSE; sx.send_rset = TRUE; sx.completed_addr = FALSE; + sx.avoid_option = OPTION_SIZE; if( smtp_write_mail_and_rcpt_cmds(&sx, &yield) == 0 && addr->transport_return == PENDING_OK @@ -983,7 +993,7 @@ no_conn: if (*sx.buffer == 0) Ustrcpy(sx.buffer, US"connection dropped"); /*XXX test here is ugly; seem to have a split of responsibility for - building this message. Need to reationalise. Where is it done + building this message. Need to rationalise. Where is it done before here, and when not? Not == 5xx resp to MAIL on main-verify */ @@ -1177,7 +1187,7 @@ if(cutthrough.fd < 0) if( #ifdef SUPPORT_TLS - (tls_out.active == cutthrough.fd) ? tls_write(FALSE, ctblock.buffer, n) : + tls_out.active == cutthrough.fd ? tls_write(FALSE, ctblock.buffer, n, FALSE) : #endif send(cutthrough.fd, ctblock.buffer, n, 0) > 0 ) @@ -1308,9 +1318,9 @@ return cutthrough_response(cutthrough.fd, '3', NULL, CUTTHROUGH_DATA_TIMEOUT) == } -/* fd and tctx args only to match write_chunk() */ +/* tctx arg only to match write_chunk() */ static BOOL -cutthrough_write_chunk(int fd, transport_ctx * tctx, uschar * s, int len) +cutthrough_write_chunk(transport_ctx * tctx, uschar * s, int len) { uschar * s2; while(s && (s2 = Ustrchr(s, '\n'))) @@ -1339,13 +1349,15 @@ if(cutthrough.fd < 0 || cutthrough.callout_hold_only) */ HDEBUG(D_acl) debug_printf_indent("----------- start cutthrough headers send -----------\n"); +tctx.u.fd = cutthrough.fd; tctx.tblock = cutthrough.addr.transport; tctx.addr = &cutthrough.addr; tctx.check_string = US"."; tctx.escape_string = US".."; +/*XXX check under spool_files_wireformat. Might be irrelevant */ tctx.options = topt_use_crlf; -if (!transport_headers_send(cutthrough.fd, &tctx, &cutthrough_write_chunk)) +if (!transport_headers_send(&tctx, &cutthrough_write_chunk)) return FALSE; HDEBUG(D_acl) debug_printf_indent("----------- done cutthrough headers send ------------\n"); @@ -1394,6 +1406,7 @@ cutthrough.delivery = cutthrough.callout_hold_only = FALSE; void release_cutthrough_connection(const uschar * why) { +if (cutthrough.fd < 0) return; HDEBUG(D_acl) debug_printf_indent("release cutthrough conn: %s\n", why); cutthrough.fd = -1; cutthrough.delivery = cutthrough.callout_hold_only = FALSE; @@ -1514,7 +1527,7 @@ va_list ap; va_start(ap, format); if (smtp_out && (f == smtp_out)) - smtp_vprintf(format, ap); + smtp_vprintf(format, FALSE, ap); else vfprintf(f, format, ap); va_end(ap); @@ -1776,16 +1789,16 @@ while (addr_new) transport. */ transport_feedback tf = { - NULL, /* interface (=> any) */ - US"smtp", /* port */ - US"smtp", /* protocol */ - NULL, /* hosts */ - US"$smtp_active_hostname", /* helo_data */ - FALSE, /* hosts_override */ - FALSE, /* hosts_randomize */ - FALSE, /* gethostbyname */ - TRUE, /* qualify_single */ - FALSE /* search_parents */ + .interface = NULL, /* interface (=> any) */ + .port = US"smtp", + .protocol = US"smtp", + .hosts = NULL, + .helo_data = US"$smtp_active_hostname", + .hosts_override = FALSE, + .hosts_randomize = FALSE, + .gethostbyname = FALSE, + .qualify_single = TRUE, + .search_parents = FALSE }; /* If verification yielded a remote transport, we want to use that @@ -2250,7 +2263,7 @@ for (h = header_list; h != NULL && yield == OK; h = h->next) /* deconst cast ok as we're passing a non-const to string_printing() */ *msgptr = US string_printing( string_sprintf("%s: failing address in \"%.*s:\" header %s: %.*s", - errmess, tt - h->text, h->text, verb, len, s)); + errmess, (int)(tt - h->text), h->text, verb, len, s)); yield = FAIL; break; /* Out of address loop */ @@ -2551,7 +2564,7 @@ for (i = 0; i < 3 && !done; i++) while (ss > s && isspace(ss[-1])) ss--; *log_msgptr = string_sprintf("syntax error in '%.*s' header when " "scanning for sender: %s in \"%.*s\"", - endname - h->text, h->text, *log_msgptr, ss - s, s); + (int)(endname - h->text), h->text, *log_msgptr, (int)(ss - s), s); yield = FAIL; done = TRUE; break; @@ -2579,11 +2592,9 @@ for (i = 0; i < 3 && !done; i++) { *verrno = vaddr->basic_errno; if (smtp_return_error_details) - { *user_msgptr = string_sprintf("Rejected after DATA: " "could not verify \"%.*s\" header address\n%s: %s", - endname - h->text, h->text, vaddr->address, vaddr->message); - } + (int)(endname - h->text), h->text, vaddr->address, vaddr->message); } /* Success or defer */ @@ -2644,6 +2655,7 @@ verify_get_ident(int port) int sock, host_af, qlen; int received_sender_port, received_interface_port, n; uschar *p; +blob early_data; uschar buffer[2048]; /* Default is no ident. Check whether we want to do an ident check for this @@ -2669,8 +2681,15 @@ if (ip_bind(sock, host_af, interface_address, 0) < 0) goto END_OFF; } +/* Construct and send the query. */ + +qlen = snprintf(CS buffer, sizeof(buffer), "%d , %d\r\n", + sender_host_port, interface_port); +early_data.data = buffer; +early_data.len = qlen; + if (ip_connect(sock, host_af, sender_host_address, port, - rfc1413_query_timeout, TRUE) < 0) + rfc1413_query_timeout, &early_data) < 0) { if (errno == ETIMEDOUT && LOGGING(ident_timeout)) log_write(0, LOG_MAIN, "ident connection to %s timed out", @@ -2681,16 +2700,6 @@ if (ip_connect(sock, host_af, sender_host_address, port, goto END_OFF; } -/* Construct and send the query. */ - -sprintf(CS buffer, "%d , %d\r\n", sender_host_port, interface_port); -qlen = Ustrlen(buffer); -if (send(sock, buffer, qlen, 0) < 0) - { - DEBUG(D_ident) debug_printf("ident send failed: %s\n", strerror(errno)); - goto END_OFF; - } - /* Read a response line. We put it into the rest of the buffer, using several recv() calls if necessary. */ @@ -3141,18 +3150,16 @@ verify_check_this_host(const uschar **listptr, unsigned int *cache_bits, int rc; unsigned int *local_cache_bits = cache_bits; const uschar *save_host_address = deliver_host_address; -check_host_block cb; -cb.host_name = host_name; -cb.host_address = host_address; +check_host_block cb = { .host_name = host_name, .host_address = host_address }; -if (valueptr != NULL) *valueptr = NULL; +if (valueptr) *valueptr = NULL; /* If the host address starts off ::ffff: it is an IPv6 address in IPv4-compatible mode. Find the IPv4 part for checking against IPv4 addresses. */ -cb.host_ipv4 = (Ustrncmp(host_address, "::ffff:", 7) == 0)? - host_address + 7 : host_address; +cb.host_ipv4 = Ustrncmp(host_address, "::ffff:", 7) == 0 + ? host_address + 7 : host_address; /* During the running of the check, put the IP address into $host_address. In the case of calls from the smtp transport, it will already be there. However,