- /* 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)
- {
- /*save_errno = ERRNO_TLSREQUIRED;*/
- log_write(0, LOG_MAIN, "a TLS session is required for %s [%s], but %s",
- host->name, host->address,
- tls_offered? "an attempt to start TLS failed" : "the server did not offer TLS support");
- done= FALSE;
- goto TLS_FAILED;
+ /* STARTTLS accepted or ssl-on-connect: try to negotiate a TLS session. */
+ else
+ {
+ int rc = tls_client_start(inblock.sock, host, addr,
+ NULL, /* No DH param */
+ ob->tls_certificate, ob->tls_privatekey,
+ ob->tls_sni,
+ ob->tls_verify_certificates, ob->tls_crl,
+ ob->tls_require_ciphers,
+ ob->gnutls_require_mac, ob->gnutls_require_kx, ob->gnutls_require_proto,
+ callout);
+
+ /* 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)
+ {
+ (void)close(inblock.sock);
+ log_write(0, LOG_MAIN, "TLS session failure: delivering unencrypted "
+ "to %s [%s] (not in hosts_require_tls)", host->name, host->address);
+ suppress_tls = TRUE;
+ goto tls_retry_connection;
+ }
+ /*save_errno = ERRNO_TLSFAILURE;*/
+ /*message = US"failure while setting up TLS session";*/
+ send_quit = FALSE;
+ done= FALSE;
+ goto TLS_FAILED;
+ }
+
+ /* TLS session is set up. Copy info for logging. */
+ addr->cipher = tls_out.cipher;
+ addr->peerdn = tls_out.peerdn;
+
+ /* For SMTPS we need to wait for the initial OK response, then do HELO. */
+ if (smtps)
+ goto smtps_redo_greeting;
+
+ /* For STARTTLS we need to redo EHLO */
+ goto tls_redo_helo;
+ }