X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/bb07bcd32250965a896b0856dd1b839b5795e2f4..2ddb4094c1b6861bebe191fa1466f53399e1e6d9:/src/src/verify.c diff --git a/src/src/verify.c b/src/src/verify.c index b957c709b..95876d1cd 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2017 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ /* Functions concerned with verifying things. The original code for callout @@ -196,6 +196,7 @@ else case ccache_accept: HDEBUG(D_verify) debug_printf("callout cache: domain accepts random addresses\n"); + *failure_ptr = US"random"; dbfn_close(dbm_file); return TRUE; /* Default yield is OK */ @@ -388,18 +389,21 @@ if (addr->transport == cutthrough.addr.transport) host_af = Ustrchr(host->address, ':') ? AF_INET6 : AF_INET; - if (!smtp_get_interface(tf->interface, host_af, addr, &interface, - US"callout") || - !smtp_get_port(tf->port, addr, &port, US"callout")) + if ( !smtp_get_interface(tf->interface, host_af, addr, &interface, + US"callout") + || !smtp_get_port(tf->port, addr, &port, US"callout") + ) log_write(0, LOG_MAIN|LOG_PANIC, "<%s>: %s", addr->address, addr->message); + smtp_port_for_connect(host, port); + if ( ( interface == cutthrough.interface || ( interface && cutthrough.interface && Ustrcmp(interface, cutthrough.interface) == 0 ) ) - && port == cutthrough.host.port + && host->port == cutthrough.host.port ) { uschar * resp = NULL; @@ -784,7 +788,7 @@ tls_retry_connection: 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. + Avoid using a SIZE option on the MAIL for all random-rcpt checks. */ sx.avoid_option = OPTION_SIZE; @@ -799,6 +803,7 @@ tls_retry_connection: new_domain_record.random_result = ccache_accept; yield = OK; /* Only usable verify result we can return */ done = TRUE; + *failure_ptr = US"random"; goto no_conn; case FAIL: /* rejected: the preferred result */ new_domain_record.random_result = ccache_reject; @@ -818,7 +823,7 @@ tls_retry_connection: debug_printf_indent("problem after random/rset/mfrom; reopen conn\n"); random_local_part = NULL; #ifdef SUPPORT_TLS - tls_close(FALSE, TRUE); + tls_close(FALSE, TLS_SHUTDOWN_NOWAIT); #endif HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SMTP(close)>>\n"); (void)close(sx.inblock.sock); @@ -1023,6 +1028,29 @@ no_conn: here is where we want to leave the conn open. Ditto for a lazy-close verify. */ + if (cutthrough.delivery) + { + if (addr->transport->filter_command) + { + cutthrough.delivery= FALSE; + HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of transport filter\n"); + } +#ifndef DISABLE_DKIM + if (ob->dkim.dkim_domain) + { + cutthrough.delivery= FALSE; + HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of DKIM signing\n"); + } +#endif +#ifdef EXPERIMENTAL_ARC + if (ob->arc_sign) + { + cutthrough.delivery= FALSE; + HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of ARC signing\n"); + } +#endif + } + if ( (cutthrough.delivery || options & vopt_callout_hold) && rcpt_count == 1 && done @@ -1085,7 +1113,7 @@ no_conn: if (sx.inblock.sock >= 0) { #ifdef SUPPORT_TLS - tls_close(FALSE, TRUE); + tls_close(FALSE, TLS_SHUTDOWN_NOWAIT); #endif HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SMTP(close)>>\n"); (void)close(sx.inblock.sock); @@ -1380,12 +1408,13 @@ if(fd >= 0) _cutthrough_puts(US"QUIT\r\n", 6); /* avoid recursion */ _cutthrough_flush_send(); cutthrough.fd = -1; /* avoid recursion via read timeout */ + cutthrough.nrcpt = 0; /* permit re-cutthrough on subsequent message */ /* Wait a short time for response, and discard it */ cutthrough_response(fd, '2', NULL, 1); #ifdef SUPPORT_TLS - tls_close(FALSE, TRUE); + tls_close(FALSE, TLS_SHUTDOWN_NOWAIT); #endif HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SMTP(close)>>\n"); (void)close(fd); @@ -1630,9 +1659,9 @@ else ko_prefix = cr = US""; if (parse_find_at(address) == NULL) { - if ((options & vopt_qualify) == 0) + if (!(options & vopt_qualify)) { - if (f != NULL) + if (f) respond_printf(f, "%sA domain is required for \"%s\"%s\n", ko_prefix, address, cr); *failure_ptr = US"qualify"; @@ -1650,7 +1679,7 @@ DEBUG(D_verify) /* Rewrite and report on it. Clear the domain and local part caches - these may have been set by domains and local part tests during an ACL. */ -if (global_rewrite_rules != NULL) +if (global_rewrite_rules) { uschar *old = address; address = rewrite_address(address, options & vopt_is_recipient, FALSE, @@ -1659,21 +1688,21 @@ if (global_rewrite_rules != NULL) { for (i = 0; i < (MAX_NAMED_LIST * 2)/32; i++) vaddr->localpart_cache[i] = 0; for (i = 0; i < (MAX_NAMED_LIST * 2)/32; i++) vaddr->domain_cache[i] = 0; - if (f != NULL && !expn) fprintf(f, "Address rewritten as: %s\n", address); + if (f && !expn) fprintf(f, "Address rewritten as: %s\n", address); } } /* If this is the real sender address, we must update sender_address at this point, because it may be referred to in the routers. */ -if ((options & (vopt_fake_sender|vopt_is_recipient)) == 0) +if (!(options & (vopt_fake_sender|vopt_is_recipient))) sender_address = address; /* If the address was rewritten to <> no verification can be done, and we have to return OK. This rewriting is permitted only for sender addresses; for other addresses, such rewriting fails. */ -if (address[0] == 0) return OK; +if (!address[0]) return OK; /* Flip the legacy TLS-related variables over to the outbound set in case they're used in the context of a transport used by verification. Reset them @@ -1725,7 +1754,7 @@ while (addr_new) if (testflag(addr, af_pfr)) { allok = FALSE; - if (f != NULL) + if (f) { BOOL allow; @@ -1736,8 +1765,8 @@ while (addr_new) } else { - allow = (addr->address[0] == '|')? - testflag(addr, af_allow_pipe) : testflag(addr, af_allow_file); + allow = addr->address[0] == '|' + ? testflag(addr, af_allow_pipe) : testflag(addr, af_allow_file); fprintf(f, "%s -> %s", addr->parent->address, addr->address); } @@ -1845,7 +1874,7 @@ while (addr_new) additional host items being inserted into the chain. Hence we must save the next host first. */ - flags = HOST_FIND_BY_A; + flags = HOST_FIND_BY_A | HOST_FIND_BY_AAAA; if (tf.qualify_single) flags |= HOST_FIND_QUALIFY_SINGLE; if (tf.search_parents) flags |= HOST_FIND_SEARCH_PARENTS; @@ -2165,7 +2194,7 @@ return yield; *************************************************/ /* This function checks those header lines that contain addresses, and verifies -that all the addresses therein are syntactially correct. +that all the addresses therein are 5322-syntactially correct. Arguments: msgptr where to put an error message @@ -2181,7 +2210,7 @@ header_line *h; uschar *colon, *s; int yield = OK; -for (h = header_list; h != NULL && yield == OK; h = h->next) +for (h = header_list; h && yield == OK; h = h->next) { if (h->type != htype_from && h->type != htype_reply_to && @@ -2200,7 +2229,7 @@ for (h = header_list; h != NULL && yield == OK; h = h->next) parse_allow_group = TRUE; - while (*s != 0) + while (*s) { uschar *ss = parse_find_address_end(s, FALSE); uschar *recipient, *errmess; @@ -2217,7 +2246,7 @@ for (h = header_list; h != NULL && yield == OK; h = h->next) /* Permit an unqualified address only if the message is local, or if the sending host is configured to be permitted to send them. */ - if (recipient != NULL && domain == 0) + if (recipient && !domain) { if (h->type == htype_from || h->type == htype_sender) { @@ -2233,7 +2262,7 @@ for (h = header_list; h != NULL && yield == OK; h = h->next) /* It's an error if no address could be extracted, except for the special case of an empty address. */ - if (recipient == NULL && Ustrcmp(errmess, "empty address") != 0) + if (!recipient && Ustrcmp(errmess, "empty address") != 0) { uschar *verb = US"is"; uschar *t = ss; @@ -2271,7 +2300,7 @@ for (h = header_list; h != NULL && yield == OK; h = h->next) /* Advance to the next address */ - s = ss + (terminator? 1:0); + s = ss + (terminator ? 1 : 0); while (isspace(*s)) s++; } /* Next address */ @@ -3072,7 +3101,7 @@ if (isquery) /* Not a query-style lookup; must ensure the host name is present, and then we do a check on the name and all its aliases. */ -if (sender_host_name == NULL) +if (!sender_host_name) { HDEBUG(D_host_lookup) debug_printf("sender host name required, to match against %s\n", ss); @@ -3087,8 +3116,7 @@ if (sender_host_name == NULL) /* Match on the sender host name, using the general matching function */ -switch(match_check_string(sender_host_name, ss, -1, TRUE, TRUE, TRUE, - valueptr)) +switch(match_check_string(sender_host_name, ss, -1, TRUE, TRUE, TRUE, valueptr)) { case OK: return OK; case DEFER: return DEFER; @@ -3097,14 +3125,12 @@ switch(match_check_string(sender_host_name, ss, -1, TRUE, TRUE, TRUE, /* If there are aliases, try matching on them. */ aliases = sender_host_aliases; -while (*aliases != NULL) - { +while (*aliases) switch(match_check_string(*aliases++, ss, -1, TRUE, TRUE, TRUE, valueptr)) { case OK: return OK; case DEFER: return DEFER; } - } return FAIL; } @@ -3403,25 +3429,23 @@ else for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); rr; rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) - { if (rr->type == T_A) { dns_address *da = dns_address_from_rr(&dnsa, rr); if (da) { *addrp = da; - while (da->next != NULL) da = da->next; - addrp = &(da->next); + while (da->next) da = da->next; + addrp = &da->next; if (ttl > rr->ttl) ttl = rr->ttl; } } - } /* If we didn't find any A records, change the return code. This can happen when there is a CNAME record but there are no A records for what it points to. */ - if (cb->rhs == NULL) cb->rc = DNS_NODATA; + if (!cb->rhs) cb->rc = DNS_NODATA; } cb->expiry = time(NULL)+ttl; @@ -3443,7 +3467,7 @@ if (cb->rc == DNS_SUCCEED) records. For A6 records (currently not expected to be used) there may be multiple addresses from a single record. */ - for (da = cb->rhs->next; da != NULL; da = da->next) + for (da = cb->rhs->next; da; da = da->next) addlist = string_sprintf("%s, %s", addlist, da->address); HDEBUG(D_dnsbl) debug_printf("DNS lookup for %s succeeded (yielding %s)\n", @@ -3452,9 +3476,9 @@ if (cb->rc == DNS_SUCCEED) /* Address list check; this can be either for equality, or via a bitmask. In the latter case, all the bits must match. */ - if (iplist != NULL) + if (iplist) { - for (da = cb->rhs; da != NULL; da = da->next) + for (da = cb->rhs; da; da = da->next) { int ipsep = ','; uschar ip[46]; @@ -3464,12 +3488,11 @@ if (cb->rc == DNS_SUCCEED) /* Handle exact matching */ if (!bitmask) - { - while ((res = string_nextinlist(&ptr, &ipsep, ip, sizeof(ip))) != NULL) - { - if (Ustrcmp(CS da->address, ip) == 0) break; - } - } + { + while ((res = string_nextinlist(&ptr, &ipsep, ip, sizeof(ip)))) + if (Ustrcmp(CS da->address, ip) == 0) + break; + } /* Handle bitmask matching */ @@ -3489,7 +3512,7 @@ if (cb->rc == DNS_SUCCEED) /* Scan the returned addresses, skipping any that are IPv6 */ - while ((res = string_nextinlist(&ptr, &ipsep, ip, sizeof(ip))) != NULL) + while ((res = string_nextinlist(&ptr, &ipsep, ip, sizeof(ip)))) { if (host_aton(ip, address) != 1) continue; if ((address[0] & mask) == address[0]) break; @@ -3522,17 +3545,13 @@ if (cb->rc == DNS_SUCCEED) switch(match_type) { case 0: - res = US"was no match"; - break; + res = US"was no match"; break; case MT_NOT: - res = US"was an exclude match"; - break; + res = US"was an exclude match"; break; case MT_ALL: - res = US"was an IP address that did not match"; - break; + res = US"was an IP address that did not match"; break; case MT_NOT|MT_ALL: - res = US"were no IP addresses that did not match"; - break; + res = US"were no IP addresses that did not match"; break; } debug_printf("=> but we are not accepting this block class because\n"); debug_printf("=> there %s for %s%c%s\n", @@ -3564,15 +3583,15 @@ if (cb->rc == DNS_SUCCEED) { dns_record *rr; for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); - rr != NULL; + rr; rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) if (rr->type == T_TXT) break; - if (rr != NULL) + if (rr) { int len = (rr->data)[0]; if (len > 511) len = 127; store_pool = POOL_PERM; - cb->text = string_sprintf("%.*s", len, (const uschar *)(rr->data+1)); + cb->text = string_sprintf("%.*s", len, CUS (rr->data+1)); store_pool = old_pool; } }