X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/8d960c19a447e105a4375c2cbcd0c9493622b6a2..b0e63c7efdc2133c61545b051042d3617ecd2bbd:/src/src/verify.c diff --git a/src/src/verify.c b/src/src/verify.c index 228f63020..194e9a76a 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) The Exim Maintainers 2020 - 2022 */ +/* Copyright (c) The Exim Maintainers 2020 - 2023 */ /* Copyright (c) University of Cambridge 1995 - 2023 */ /* See the file NOTICE for conditions of use and distribution. */ /* SPDX-License-Identifier: GPL-2.0-or-later */ @@ -105,8 +105,8 @@ Return: TRUE if result found */ static BOOL -cached_callout_lookup(address_item * addr, uschar * address_key, - uschar * from_address, int * opt_ptr, uschar ** pm_ptr, +cached_callout_lookup(address_item * addr, const uschar * address_key, + const uschar * from_address, int * opt_ptr, uschar ** pm_ptr, int * yield, uschar ** failure_ptr, dbdata_callout_cache * new_domain_record, int * old_domain_res) { @@ -278,10 +278,10 @@ return FALSE; */ static void cache_callout_write(dbdata_callout_cache * dom_rec, const uschar * domain, - int done, dbdata_callout_cache_address * addr_rec, uschar * address_key) + int done, dbdata_callout_cache_address * addr_rec, const uschar * address_key) { open_db dbblock; -open_db *dbm_file = NULL; +open_db * dbm_file = NULL; /* If we get here with done == TRUE, a successful callout happened, and yield will be set OK or FAIL according to the response to the RCPT command. @@ -502,11 +502,11 @@ do_callout(address_item *addr, host_item *host_list, transport_feedback *tf, int yield = OK; int old_domain_cache_result = ccache_accept; BOOL done = FALSE; -uschar *address_key; -uschar *from_address; -uschar *random_local_part = NULL; -const uschar *save_deliver_domain = deliver_domain; -uschar **failure_ptr = options & vopt_is_recipient +const uschar * address_key; +const uschar * from_address; +uschar * random_local_part = NULL; +const uschar * save_deliver_domain = deliver_domain; +uschar ** failure_ptr = options & vopt_is_recipient ? &recipient_verify_failure : &sender_verify_failure; dbdata_callout_cache new_domain_record; dbdata_callout_cache_address new_address_record; @@ -677,7 +677,7 @@ coding means skipping this whole loop and doing the append separately. */ sx->conn_args.interface = interface; sx->helo_data = tf->helo_data; sx->conn_args.tblock = addr->transport; - sx->conn_args.sock = -1; + sx->cctx.sock = sx->conn_args.sock = -1; sx->verify = TRUE; tls_retry_connection: @@ -709,6 +709,30 @@ tls_retry_connection: if (yield != OK) { errno = addr->basic_errno; + + /* For certain errors we want specifically to log the transport name, + for ease of fixing config errors. Slightly ugly doing it here, but we want + to not leak that also in the SMTP response. */ + switch (errno) + { + case EPROTOTYPE: + case ENOPROTOOPT: + case EPROTONOSUPPORT: + case ESOCKTNOSUPPORT: + case EOPNOTSUPP: + case EPFNOSUPPORT: + case EAFNOSUPPORT: + case EADDRINUSE: + case EADDRNOTAVAIL: + case ENETDOWN: + case ENETUNREACH: + log_write(0, LOG_MAIN|LOG_PANIC, + "%s verify %s (making calloout connection): T=%s %s", + options & vopt_is_recipient ? "sender" : "recipient", + yield == FAIL ? "fail" : "defer", + transport_name, strerror(errno)); + } + transport_name = NULL; deliver_host = deliver_host_address = NULL; deliver_domain = save_deliver_domain; @@ -747,7 +771,7 @@ tls_retry_connection: if (random_local_part) { - uschar * main_address = addr->address; + const uschar * main_address = addr->address; const uschar * rcpt_domain = addr->domain; #ifdef SUPPORT_I18N @@ -918,7 +942,7 @@ tls_retry_connection: if (done) { - uschar * main_address = addr->address; + const uschar * main_address = addr->address; /*XXX oops, affixes */ addr->address = string_sprintf("postmaster@%.1000s", addr->domain); @@ -1128,7 +1152,7 @@ no_conn: /* Ensure no cutthrough on multiple verifies that were incompatible */ if (options & vopt_callout_recipsender) cancel_cutthrough_connection(TRUE, US"not usable for cutthrough"); - if (sx->send_quit) + if (sx->send_quit && sx->cctx.sock >= 0) if (smtp_write_command(sx, SCMD_FLUSH, "QUIT\r\n") != -1) /* Wait a short time for response, and discard it */ smtp_read_response(sx, sx->buffer, sizeof(sx->buffer), '2', 1); @@ -1262,7 +1286,7 @@ return FALSE; static BOOL -_cutthrough_puts(uschar * cp, int n) +_cutthrough_puts(const uschar * cp, int n) { while(n--) { @@ -1277,7 +1301,7 @@ return TRUE; /* Buffered output of counted data block. Return boolean success */ static BOOL -cutthrough_puts(uschar * cp, int n) +cutthrough_puts(const uschar * cp, int n) { if (cutthrough.cctx.sock < 0) return TRUE; if (_cutthrough_puts(cp, n)) return TRUE; @@ -1383,9 +1407,9 @@ return cutthrough_response(&cutthrough.cctx, '3', NULL, CUTTHROUGH_DATA_TIMEOUT) /* tctx arg only to match write_chunk() */ static BOOL -cutthrough_write_chunk(transport_ctx * tctx, uschar * s, int len) +cutthrough_write_chunk(transport_ctx * tctx, const uschar * s, int len) { -uschar * s2; +const uschar * s2; while(s && (s2 = Ustrchr(s, '\n'))) { if(!cutthrough_puts(s, s2-s) || !cutthrough_put_nl()) @@ -1673,16 +1697,16 @@ int yield = OK; int verify_type = expn ? v_expn : f.address_test_mode ? v_none : options & vopt_is_recipient ? v_recipient : v_sender; -address_item *addr_list; -address_item *addr_new = NULL; -address_item *addr_remote = NULL; -address_item *addr_local = NULL; -address_item *addr_succeed = NULL; -uschar **failure_ptr = options & vopt_is_recipient +address_item * addr_list; +address_item * addr_new = NULL; +address_item * addr_remote = NULL; +address_item * addr_local = NULL; +address_item * addr_succeed = NULL; +uschar ** failure_ptr = options & vopt_is_recipient ? &recipient_verify_failure : &sender_verify_failure; -uschar *ko_prefix, *cr; -uschar *address = vaddr->address; -uschar *save_sender; +uschar * ko_prefix, * cr; +const uschar * address = vaddr->address; +const uschar * save_sender; uschar null_sender[] = { 0 }; /* Ensure writeable memory */ /* Clear, just in case */ @@ -1727,9 +1751,8 @@ may have been set by domains and local part tests during an ACL. */ if (global_rewrite_rules) { - uschar *old = address; - /* deconst ok as address was not const */ - address = US rewrite_address(address, options & vopt_is_recipient, FALSE, + const uschar * old = address; + address = rewrite_address(address, options & vopt_is_recipient, FALSE, global_rewrite_rules, rewrite_existflags); if (address != old) { @@ -1895,8 +1918,8 @@ while (addr_new) if (tf.hosts && (!host_list || tf.hosts_override)) { uschar *s; - const uschar *save_deliver_domain = deliver_domain; - uschar *save_deliver_localpart = deliver_localpart; + const uschar * save_deliver_domain = deliver_domain; + const uschar * save_deliver_localpart = deliver_localpart; host_list = NULL; /* Ignore the router's hosts */ @@ -2431,11 +2454,11 @@ verify_check_notblind(BOOL case_sensitive) for (int i = 0; i < recipients_count; i++) { BOOL found = FALSE; - uschar *address = recipients_list[i].address; + const uschar * address = recipients_list[i].address; for (header_line * h = header_list; !found && h; h = h->next) { - uschar *colon, *s; + uschar * colon, * s; if (h->type != htype_to && h->type != htype_cc) continue; @@ -2509,7 +2532,7 @@ Returns: pointer to an address item, or NULL */ address_item * -verify_checked_sender(uschar *sender) +verify_checked_sender(const uschar * sender) { for (address_item * addr = sender_verified_list; addr; addr = addr->next) if (Ustrcmp(sender, addr->address) == 0) return addr; @@ -2948,7 +2971,7 @@ if (*ss == '@') a (possibly masked) comparison with the current IP address. */ if (string_is_ip_address(ss, &maskoffset) != 0) - return (host_is_in_net(cb->host_address, ss, maskoffset)? OK : FAIL); + return host_is_in_net(cb->host_address, ss, maskoffset) ? OK : FAIL; /* The pattern is not an IP address. A common error that people make is to omit one component of an IPv4 address, either by accident, or believing that, for @@ -2959,13 +2982,25 @@ ancient specification.) To aid in debugging these cases, we give a specific error if the pattern contains only digits and dots or contains a slash preceded only by digits and dots (a slash at the start indicates a file name and of course slashes may be present in lookups, but not preceded only by digits and -dots). */ +dots). Then the equivalent for IPv6 (roughly). */ -for (t = ss; isdigit(*t) || *t == '.'; ) t++; -if (!*t || (*t == '/' && t != ss)) +if (Ustrchr(ss, ':')) { - *error = string_sprintf("malformed IPv4 address or address mask: %.*s", (int)(t - ss), ss); - return ERROR; + for (t = ss; isxdigit(*t) || *t == ':' || *t == '.'; ) t++; + if (!*t || (*t == '/' || *t == '%') && t != ss) + { + *error = string_sprintf("malformed IPv6 address or address mask: %.*s", (int)(t - ss), ss); + return ERROR; + } + } +else + { + for (t = ss; isdigit(*t) || *t == '.'; ) t++; + if (!*t || (*t == '/' && t != ss)) + { + *error = string_sprintf("malformed IPv4 address or address mask: %.*s", (int)(t - ss), ss); + return ERROR; + } } /* See if there is a semicolon in the pattern, separating a searchtype @@ -2982,6 +3017,8 @@ if ((semicolon = Ustrchr(ss, ';'))) endname = semicolon; opts = NULL; } +else + opts = NULL; /* If we are doing an IP address only match, then all lookups must be IP address lookups, even if there is no "net-". */