X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/08f3b11b36102a900f2ef3363938c4a8804f7c95..583b7f82cdcc5ea24d2afb572f61b10e0da676d4:/src/src/verify.c diff --git a/src/src/verify.c b/src/src/verify.c index 6c228abbf..53a1daade 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -174,9 +174,7 @@ dbdata_callout_cache new_domain_record; dbdata_callout_cache_address new_address_record; host_item *host; time_t callout_start_time; -#ifdef EXPERIMENTAL_INTERNATIONAL -BOOL utf8_offered = FALSE; -#endif +uschar peer_offered = 0; new_domain_record.result = ccache_unknown; new_domain_record.postmaster_result = ccache_unknown; @@ -542,6 +540,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. uschar inbuffer[4096]; uschar outbuffer[1024]; uschar responsebuffer[4096]; + uschar * size_str; clearflag(addr, af_verify_pmfail); /* postmaster callout flag */ clearflag(addr, af_verify_nsfail); /* null sender callout flag */ @@ -687,7 +686,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. if (!(done= smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), '2', callout))) goto RESPONSE_FAILED; -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT lookup_dnssec_authenticated = host->dnssec==DS_YES ? US"yes" : host->dnssec==DS_NO ? US"no" : NULL; if (event_raise(addr->transport->event_action, @@ -711,7 +710,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. #ifdef SUPPORT_TLS if (smtps && tls_out.active < 0) /* ssl-on-connect, first pass */ { - tls_offered = TRUE; + peer_offered &= ~PEER_OFFERED_TLS; ob->tls_tempfail_tryclear = FALSE; } else /* all other cases */ @@ -730,27 +729,40 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. goto RESPONSE_FAILED; } #ifdef SUPPORT_TLS - tls_offered = FALSE; + peer_offered &= ~PEER_OFFERED_TLS; #endif esmtp = FALSE; goto esmtp_retry; /* fallback to HELO */ } /* Set tls_offered if the response to EHLO specifies support for STARTTLS. */ -#ifdef SUPPORT_TLS - if (esmtp && !suppress_tls && tls_out.active < 0) - { - if (regex_STARTTLS == NULL) regex_STARTTLS = - regex_must_compile(US"\\n250[\\s\\-]STARTTLS(\\s|\\n|$)", FALSE, TRUE); - tls_offered = pcre_exec(regex_STARTTLS, NULL, CS responsebuffer, - Ustrlen(responsebuffer), 0, PCRE_EOPT, NULL, 0) >= 0; - } - else - tls_offered = FALSE; + peer_offered = esmtp + ? ehlo_response(responsebuffer, sizeof(responsebuffer), + (!suppress_tls && tls_out.active < 0 ? PEER_OFFERED_TLS : 0) + | 0 /* no IGNQ */ + | 0 /* no PRDR */ +#ifdef SUPPORT_I18N + | (addr->prop.utf8_msg && !addr->prop.utf8_downcvt + ? PEER_OFFERED_UTF8 : 0) #endif + | 0 /* no DSN */ + | 0 /* no PIPE */ + + /* only care about SIZE if we have size from inbound */ + | (message_size > 0 && ob->size_addition >= 0 + ? PEER_OFFERED_SIZE : 0) + ) + : 0; } + size_str = peer_offered & PEER_OFFERED_SIZE + ? string_sprintf(" SIZE=%d", message_size + ob->size_addition) : US""; + +#ifdef SUPPORT_TLS + tls_offered = !!(peer_offered & PEER_OFFERED_TLS); +#endif + /* If TLS is available on this connection attempt to start up a TLS session, unless the host is in hosts_avoid_tls. If successful, send another EHLO - the server may give a different answer in secure mode. We @@ -760,7 +772,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. for error analysis. */ #ifdef SUPPORT_TLS - if ( tls_offered + if ( peer_offered & PEER_OFFERED_TLS && verify_check_given_host(&ob->hosts_avoid_tls, host) != OK && verify_check_given_host(&ob->hosts_verify_avoid_tls, host) != OK ) @@ -811,7 +823,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. if (rc == DEFER) { (void)close(inblock.sock); -# ifdef EXPERIMENTAL_EVENT +# ifndef DISABLE_EVENT (void) event_raise(addr->transport->event_action, US"tcp:close", NULL); # endif @@ -875,8 +887,9 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. log_write(0, LOG_MAIN, "H=%s [%s]: a TLS session is required for this host, but %s", host->name, host->address, - tls_offered ? "an attempt to start TLS failed" - : "the server did not offer TLS support"); + peer_offered & PEER_OFFERED_TLS + ? "an attempt to start TLS failed" + : "the server did not offer TLS support"); done= FALSE; goto TLS_FAILED; } @@ -885,8 +898,6 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. done = TRUE; /* so far so good; have response to HELO */ - /*XXX the EHLO response would be analyzed here for IGNOREQUOTA, SIZE, PIPELINING */ - /* For now, transport_filter by cutthrough-delivery is not supported */ /* Need proper integration with the proper transport mechanism. */ if (cutthrough.delivery) @@ -924,20 +935,11 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. } } -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N else if ( addr->prop.utf8_msg && !addr->prop.utf8_downcvt - && !( esmtp - && ( regex_UTF8 - || ( (regex_UTF8 = regex_must_compile( - US"\\n250[\\s\\-]SMTPUTF8(\\s|\\n|$)", FALSE, TRUE)), - TRUE - ) ) - && ( (utf8_offered = pcre_exec(regex_UTF8, NULL, - CS responsebuffer, Ustrlen(responsebuffer), - 0, PCRE_EOPT, NULL, 0) >= 0) - || addr->prop.utf8_downcvt_maybe - ) ) ) + && !(peer_offered & PEER_OFFERED_UTF8) + ) { HDEBUG(D_acl|D_v) debug_printf("utf8 required but not offered\n"); errno = ERRNO_UTF8_FWD; @@ -945,7 +947,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. done = FALSE; } else if ( addr->prop.utf8_msg - && (addr->prop.utf8_downcvt || !utf8_offered) + && (addr->prop.utf8_downcvt || !(peer_offered & PEER_OFFERED_UTF8)) && (setflag(addr, af_utf8_downcvt), from_address = string_address_utf8_to_alabel(from_address, &addr->message), @@ -976,13 +978,13 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. /* Send the MAIL command */ (smtp_write_command(&outblock, FALSE, -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N addr->prop.utf8_msg && !addr->prop.utf8_downcvt - ? "MAIL FROM:<%s>%s SMTPUTF8\r\n" + ? "MAIL FROM:<%s>%s%s SMTPUTF8\r\n" : #endif - "MAIL FROM:<%s>%s\r\n", - from_address, responsebuffer) >= 0) + "MAIL FROM:<%s>%s%s\r\n", + from_address, responsebuffer, size_str) >= 0) ) && smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), @@ -1022,7 +1024,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. { const uschar * rcpt_domain = addr->domain; -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N uschar * errstr = NULL; if ( testflag(addr, af_utf8_downcvt) && (rcpt_domain = string_domain_utf8_to_alabel(rcpt_domain, @@ -1084,7 +1086,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. '2', callout) && smtp_write_command(&outblock, FALSE, -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N addr->prop.utf8_msg && !addr->prop.utf8_downcvt ? "MAIL FROM:<%s> SMTPUTF8\r\n" : @@ -1103,7 +1105,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. tls_close(FALSE, TRUE); #endif (void)close(inblock.sock); -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT (void) event_raise(addr->transport->event_action, US"tcp:close", NULL); #endif @@ -1124,7 +1126,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. uschar * rcpt = transport_rcpt_address(addr, addr->transport ? addr->transport->rcpt_include_affixes : FALSE); -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N /*XXX should the conversion be moved into transport_rcpt_address() ? */ uschar * dummy_errstr = NULL; if ( testflag(addr, af_utf8_downcvt) @@ -1229,7 +1231,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. HDEBUG(D_verify) debug_printf("SMTP timeout\n"); send_quit = FALSE; } -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N else if (errno == ERRNO_UTF8_FWD) { extern int acl_where; /* src/acl.c */ @@ -1312,7 +1314,7 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. tls_close(FALSE, TRUE); #endif (void)close(inblock.sock); -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT (void) event_raise(addr->transport->event_action, US"tcp:close", NULL); #endif } @@ -3876,7 +3878,9 @@ Note: an address for testing DUL is 192.203.178.4 Note: a domain for testing RFCI is example.tld.dsn.rfc-ignorant.org Arguments: + where the acl type listptr the domain/address/data list + log_msgptr log message on error Returns: OK successful lookup (i.e. the address is on the list), or lookup deferred after +include_unknown @@ -3886,7 +3890,7 @@ Returns: OK successful lookup (i.e. the address is on the list), or */ int -verify_check_dnsbl(const uschar **listptr) +verify_check_dnsbl(int where, const uschar ** listptr, uschar ** log_msgptr) { int sep = 0; int defer_return = FAIL; @@ -3933,21 +3937,19 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL /* See if there's explicit data to be looked up */ - key = Ustrchr(domain, '/'); - if (key != NULL) *key++ = 0; + if ((key = Ustrchr(domain, '/'))) *key++ = 0; /* See if there's a list of addresses supplied after the domain name. This is introduced by an = or a & character; if preceded by = we require all matches and if preceded by ! we invert the result. */ - iplist = Ustrchr(domain, '='); - if (iplist == NULL) + if (!(iplist = Ustrchr(domain, '='))) { bitmask = TRUE; iplist = Ustrchr(domain, '&'); } - if (iplist != NULL) /* Found either = or & */ + if (iplist) /* Found either = or & */ { if (iplist > domain && iplist[-1] == '!') /* Handle preceding ! */ { @@ -3966,6 +3968,7 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL } } + /* If there is a comma in the domain, it indicates that a second domain for looking up TXT records is provided, before the main domain. Otherwise we must set domain_txt == domain. */ @@ -4011,6 +4014,13 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL if (key == NULL) { + if (where == ACL_WHERE_NOTSMTP_START || where == ACL_WHERE_NOTSMTP) + { + *log_msgptr = string_sprintf + ("cannot test auto-keyed dnslists condition in %s ACL", + acl_wherenames[where]); + return ERROR; + } if (sender_host_address == NULL) return FAIL; /* can never match */ if (revadd[0] == 0) invert_address(revadd, sender_host_address); rc = one_check_dnsbl(domain, domain_txt, sender_host_address, revadd,