{
HDEBUG(D_verify) debug_printf("cannot callout via null transport\n");
}
+else if (Ustrcmp(addr->transport->driver_name, "smtp") != 0)
+ log_write(0, LOG_MAIN|LOG_PANIC|LOG_CONFIG_FOR, "callout transport '%s': %s is non-smtp",
+ addr->transport->name, addr->transport->driver_name);
else
{
smtp_transport_options_block *ob =
- (smtp_transport_options_block *)(addr->transport->options_block);
+ (smtp_transport_options_block *)addr->transport->options_block;
/* The information wasn't available in the cache, so we have to do a real
callout and save the result in the cache for next time, unless no_cache is set,
else active_hostname = s;
}
- deliver_host = deliver_host_address = NULL;
- deliver_domain = save_deliver_domain;
-
/* Wait for initial response, and send HELO. The smtp_write_command()
function leaves its command in big_buffer. This is used in error responses.
Initialize it in case the connection is rejected. */
/* STARTTLS accepted or ssl-on-connect: try to negotiate a TLS session. */
else
{
- int rc = tls_client_start(inblock.sock, host, addr,
- ob->tls_certificate, ob->tls_privatekey,
- ob->tls_sni,
- ob->tls_verify_certificates, ob->tls_crl,
- ob->tls_require_ciphers,
-#ifdef EXPERIMENTAL_OCSP
- ob->hosts_require_ocsp,
-#endif
- ob->tls_dh_min_bits, callout,
- ob->tls_verify_hosts, ob->tls_try_verify_hosts);
+ int oldtimeout = ob->command_timeout;
+ int rc;
+
+ ob->command_timeout = callout;
+ rc = tls_client_start(inblock.sock, host, addr, ob);
+ ob->command_timeout = oldtimeout;
/* TLS negotiation failed; give an error. Try in clear on a new connection,
if the options permit it for this host. */
if (rc != OK)
{
- if (rc == DEFER && ob->tls_tempfail_tryclear && !smtps &&
- verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name,
- host->address, NULL) != OK)
+ if ( rc == DEFER
+ && ob->tls_tempfail_tryclear
+ && !smtps
+ && verify_check_this_host(&(ob->hosts_require_tls), NULL,
+ host->name, host->address, NULL) != OK
+#ifdef EXPERIMENTAL_DANE
+ && verify_check_this_host(&(ob->hosts_require_dane), NULL,
+ host->name, host->address, NULL) != OK
+#endif
+ )
{
(void)close(inblock.sock);
log_write(0, LOG_MAIN, "TLS session failure: delivering unencrypted "
/* If the host is required to use a secure channel, ensure that we have one. */
if (tls_out.active < 0)
- if (verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name,
- host->address, NULL) == OK)
+ if ( verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name,
+ host->address, NULL) == OK
+#ifdef EXPERIMENTAL_DANE
+ || verify_check_this_host(&(ob->hosts_require_dane), NULL, host->name,
+ host->address, NULL) == OK
+#endif
+ )
{
/*save_errno = ERRNO_TLSREQUIRED;*/
log_write(0, LOG_MAIN, "a TLS session is required for %s [%s], but %s",
;
/* Clear down of the TLS, SMTP and TCP layers on error is handled below. */
-
/* Failure to accept HELO is cached; this blocks the whole domain for all
senders. I/O errors and defer responses are not cached. */
smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer),
'2', callout);
+ deliver_host = deliver_host_address = NULL;
+ deliver_domain = save_deliver_domain;
+
/* If the host does not accept MAIL FROM:<>, arrange to cache this
information, but again, don't record anything for an I/O error or a defer. Do
not cache rejections of MAIL when a non-empty sender has been used, because
{
cutthrough_fd= outblock.sock; /* We assume no buffer in use in the outblock */
cutthrough_addr = *addr; /* Save the address_item for later logging */
+ cutthrough_addr.next = NULL;
cutthrough_addr.host_used = store_get(sizeof(host_item));
cutthrough_addr.host_used->name = host->name;
cutthrough_addr.host_used->address = host->address;
}
+/* fd and use_crlf args only to match write_chunk() */
+static BOOL
+cutthrough_write_chunk(int fd, uschar * s, int len, BOOL use_crlf)
+{
+uschar * s2;
+while(s && (s2 = Ustrchr(s, '\n')))
+ {
+ if(!cutthrough_puts(s, s2-s) || !cutthrough_put_nl())
+ return FALSE;
+ s = s2+1;
+ }
+return TRUE;
+}
+
+
/* Buffered send of headers. Return success boolean. */
/* Expands newlines to wire format (CR,NL). */
/* Also sends header-terminating blank line. */
BOOL
cutthrough_headers_send( void )
{
-header_line * h;
-uschar * cp1, * cp2;
-
if(cutthrough_fd < 0)
return FALSE;
-for(h= header_list; h != NULL; h= h->next)
- if(h->type != htype_old && h->text != NULL)
- for (cp1 = h->text; *cp1 && (cp2 = Ustrchr(cp1, '\n')); cp1 = cp2+1)
- if( !cutthrough_puts(cp1, cp2-cp1)
- || !cutthrough_put_nl())
- return FALSE;
+/* We share a routine with the mainline transport to handle header add/remove/rewrites,
+ but having a separate buffered-output function (for now)
+*/
+HDEBUG(D_acl) debug_printf("----------- start cutthrough headers send -----------\n");
-HDEBUG(D_transport|D_acl|D_v) debug_printf(" SMTP>>(nl)\n");
-return cutthrough_put_nl();
+if (!transport_headers_send(&cutthrough_addr, cutthrough_fd,
+ cutthrough_addr.transport->add_headers, cutthrough_addr.transport->remove_headers,
+ &cutthrough_write_chunk, TRUE,
+ cutthrough_addr.transport->rewrite_rules, cutthrough_addr.transport->rewrite_existflags))
+ return FALSE;
+
+HDEBUG(D_acl) debug_printf("----------- done cutthrough headers send ------------\n");
+return TRUE;
}
they're used in the context of a transport used by verification. Reset them
at exit from this routine. */
-modify_variable(US"tls_bits", &tls_out.bits);
-modify_variable(US"tls_certificate_verified", &tls_out.certificate_verified);
-modify_variable(US"tls_cipher", &tls_out.cipher);
-modify_variable(US"tls_peerdn", &tls_out.peerdn);
-#if defined(SUPPORT_TLS) && !defined(USE_GNUTLS)
-modify_variable(US"tls_sni", &tls_out.sni);
-#endif
+tls_modify_variables(&tls_out);
/* Save a copy of the sender address for re-instating if we change it to <>
while verifying a sender address (a nice bit of self-reference there). */
string_is_ip_address(host->name, NULL) != 0)
(void)host_find_byname(host, NULL, flags, &canonical_name, TRUE);
else
+ {
+ uschar * d_request = NULL, * d_require = NULL;
+ if (Ustrcmp(addr->transport->driver_name, "smtp") == 0)
+ {
+ smtp_transport_options_block * ob =
+ (smtp_transport_options_block *)
+ addr->transport->options_block;
+ d_request = ob->dnssec_request_domains;
+ d_require = ob->dnssec_require_domains;
+ }
+
(void)host_find_bydns(host, NULL, flags, NULL, NULL, NULL,
- &canonical_name, NULL);
+ d_request, d_require, &canonical_name, NULL);
+ }
}
}
}
the -bv or -bt case). */
out:
-
-modify_variable(US"tls_bits", &tls_in.bits);
-modify_variable(US"tls_certificate_verified", &tls_in.certificate_verified);
-modify_variable(US"tls_cipher", &tls_in.cipher);
-modify_variable(US"tls_peerdn", &tls_in.peerdn);
-#if defined(SUPPORT_TLS) && !defined(USE_GNUTLS)
-modify_variable(US"tls_sni", &tls_in.sni);
-#endif
+tls_modify_variables(&tls_in);
return yield;
}
/* In case this is the first time the DNS resolver is being used. */
-dns_init(FALSE, FALSE);
+dns_init(FALSE, FALSE, FALSE); /*XXX dnssec? */
/* Loop through all the domains supplied, until something matches */
return FAIL;
}
+/* vi: aw ai sw=2
+*/
/* End of verify.c */