Add $tls_in_* variables; note the old names as deprecated.
authorJeremy Harris <jgh146exb@wizmail.org>
Mon, 4 Jun 2012 16:48:52 +0000 (17:48 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Mon, 4 Jun 2012 16:48:52 +0000 (17:48 +0100)
doc/doc-docbook/spec.xfpt
src/src/configure.default
src/src/expand.c
src/src/functions.h
src/src/tls-gnu.c
src/src/tls-openssl.c
src/src/verify.c

index 85843843189956eae65b2a36e8da6c51a50e2300..0ea36adc24fe15a3ff3727a026cd3ff1d0085b8e 100644 (file)
@@ -6073,7 +6073,7 @@ The example PLAIN authenticator looks like this:
 #  server_set_id           = $auth2
 #  server_prompts          = :
 #  server_condition        = Authentication is not yet configured
-#  server_advertise_condition = ${if def:tls_cipher }
+#  server_advertise_condition = ${if def:tls_in_cipher }
 .endd
 And the example LOGIN authenticator looks like this:
 .code
@@ -6082,7 +6082,7 @@ And the example LOGIN authenticator looks like this:
 #  server_set_id           = $auth1
 #  server_prompts          = <| Username: | Password:
 #  server_condition        = Authentication is not yet configured
-#  server_advertise_condition = ${if def:tls_cipher }
+#  server_advertise_condition = ${if def:tls_in_cipher }
 .endd
 
 The &%server_set_id%& option makes Exim remember the authenticated username
@@ -11957,20 +11957,43 @@ command in a filter file. Its use is explained in the description of that
 command, which can be found in the separate document entitled &'Exim's
 interfaces to mail filtering'&.
 
-.vitem &$tls_bits$&
-.vindex "&$tls_bits$&"
-Contains an approximation of the TLS cipher's bit-strength; the meaning of
+.vitem &$tls_in_bits$&
+.vindex "&$tls_in_bits$&"
+Contains an approximation of the TLS cipher's bit-strength
+on the inbound connection; the meaning of
 this depends upon the TLS implementation used.
 If TLS has not been negotiated, the value will be 0.
 The value of this is automatically fed into the Cyrus SASL authenticator
 when acting as a server, to specify the "external SSF" (a SASL term).
 
-.vitem &$tls_certificate_verified$&
-.vindex "&$tls_certificate_verified$&"
+The deprecated &$tls_bits$& variable refers to the inbound side
+except when used in the context of an outbound SMTP delivery, when it refers to
+the outbound.
+
+.vitem &$tls_out_bits$&
+.vindex "&$tls_out_bits$&"
+Contains an approximation of the TLS cipher's bit-strength
+on an outbound SMTP connection; the meaning of
+this depends upon the TLS implementation used.
+If TLS has not been negotiated, the value will be 0.
+
+.vitem &$tls_in_certificate_verified$&
+.vindex "&$tls_in_certificate_verified$&"
 This variable is set to &"1"& if a TLS certificate was verified when the
 message was received, and &"0"& otherwise.
 
-.vitem &$tls_cipher$&
+The deprecated &$tls_certificate_verfied$& variable refers to the inbound side
+except when used in the context of an outbound SMTP delivery, when it refers to
+the outbound.
+
+.vitem &$tls_out_certificate_verified$&
+.vindex "&$tls_out_certificate_verified$&"
+This variable is set to &"1"& if a TLS certificate was verified when an
+outbound SMTP connection was made,
+and &"0"& otherwise.
+
+.vitem &$tls_in_cipher$&
+.vindex "&$tls_in_cipher$&"
 .vindex "&$tls_cipher$&"
 When a message is received from a remote host over an encrypted SMTP
 connection, this variable is set to the cipher suite that was negotiated, for
@@ -11979,23 +12002,39 @@ received over unencrypted connections, the variable is empty. Testing
 &$tls_cipher$& for emptiness is one way of distinguishing between encrypted and
 non-encrypted connections during ACL processing.
 
-The &$tls_cipher$& variable retains its value during message delivery, except
-when an outward SMTP delivery takes place via the &(smtp)& transport. In this
-case, &$tls_cipher$& is cleared before any outgoing SMTP connection is made,
+The deprecated &$tls_cipher$& variable is the same as &$tls_in_cipher$& during message reception,
+but in the context of an outward SMTP delivery taking place via the &(smtp)& transport
+becomes the same as &$tls_out_cipher$&.
+
+.vitem &$tls_out_cipher$&
+.vindex "&$tls_out_cipher$&"
+This variable is
+cleared before any outgoing SMTP connection is made,
 and then set to the outgoing cipher suite if one is negotiated. See chapter
 &<<CHAPTLS>>& for details of TLS support and chapter &<<CHAPsmtptrans>>& for
 details of the &(smtp)& transport.
 
-.vitem &$tls_peerdn$&
+.vitem &$tls_in_peerdn$&
+.vindex "&$tls_in_peerdn$&"
 .vindex "&$tls_peerdn$&"
 When a message is received from a remote host over an encrypted SMTP
 connection, and Exim is configured to request a certificate from the client,
 the value of the Distinguished Name of the certificate is made available in the
-&$tls_peerdn$& during subsequent processing. Like &$tls_cipher$&, the
-value is retained during message delivery, except during outbound SMTP
-deliveries.
+&$tls_in_peerdn$& during subsequent processing.
+
+The deprecated &$tls_peerdn$& variable refers to the inbound side
+except when used in the context of an outbound SMTP delivery, when it refers to
+the outbound.
+
+.vitem &$tls_out_peerdn$&
+.vindex "&$tls_out_peerdn$&"
+When a message is being delivered to a remote host over an encrypted SMTP
+connection, and Exim is configured to request a certificate from the server,
+the value of the Distinguished Name of the certificate is made available in the
+&$tls_out_peerdn$& during subsequent processing.
 
-.vitem &$tls_sni$&
+.vitem &$tls_in_sni$&
+.vindex "&$tls_in_sni$&"
 .vindex "&$tls_sni$&"
 .cindex "TLS" "Server Name Indication"
 When a TLS session is being established, if the client sends the Server
@@ -12006,8 +12045,15 @@ will be re-expanded early in the TLS session, to permit
 a different certificate to be presented (and optionally a different key to be
 used) to the client, based upon the value of the SNI extension.
 
-The value will be retained for the lifetime of the message.  During outbound
-SMTP deliveries, it reflects the value of the &%tls_sni%& option on
+The deprecated &$tls_sni$& variable refers to the inbound side
+except when used in the context of an outbound SMTP delivery, when it refers to
+the outbound.
+
+.vitem &$tls_out_sni$&
+.vindex "&$tls_out_sni$&"
+.cindex "TLS" "Server Name Indication"
+During outbound
+SMTP deliveries, this variable reflects the value of the &%tls_sni%& option on
 the transport.
 
 .vitem &$tod_bsdinbox$&
@@ -13150,10 +13196,10 @@ If you want to advertise the availability of AUTH only when the connection
 is encrypted using TLS, you can make use of the fact that the value of this
 option is expanded, with a setting like this:
 .code
-auth_advertise_hosts = ${if eq{$tls_cipher}{}{}{*}}
+auth_advertise_hosts = ${if eq{$tls_in_cipher}{}{}{*}}
 .endd
-.vindex "&$tls_cipher$&"
-If &$tls_cipher$& is empty, the session is not encrypted, and the result of
+.vindex "&$tls_in_cipher$&"
+If &$tls_in_cipher$& is empty, the session is not encrypted, and the result of
 the expansion is empty, thus matching no hosts. Otherwise, the result of the
 expansion is *, which matches all hosts.
 
@@ -14878,7 +14924,7 @@ received_header_text = Received: \
   ${if def:sender_helo_name {(helo=$sender_helo_name)\n\t}}}}\
   by $primary_hostname \
   ${if def:received_protocol {with $received_protocol}} \
-  ${if def:tls_cipher {($tls_cipher)\n\t}}\
+  ${if def:tls_in_cipher {($tls_in_cipher)\n\t}}\
   (Exim $version_number)\n\t\
   ${if def:sender_address \
   {(envelope-from <$sender_address>)\n\t}}\
@@ -15741,7 +15787,7 @@ receiving incoming messages as a server. If you want to supply certificates for
 use when sending messages as a client, you must set the &%tls_certificate%&
 option in the relevant &(smtp)& transport.
 
-If the option contains &$tls_sni$& and Exim is built against OpenSSL, then
+If the option contains &$tls_out_sni$& and Exim is built against OpenSSL, then
 if the OpenSSL build supports TLS extensions and the TLS client sends the
 Server Name Indication extension, then this option and others documented in
 &<<SECTtlssni>>& will be re-expanded.
@@ -22020,6 +22066,9 @@ appropriate values for the outgoing connection, and these are the values that
 are in force when any authenticators are run and when the
 &%authenticated_sender%& option is expanded.
 
+These variables are deprecated in favour of &$tls_in_cipher$& et. al.
+and will be removed in a future release.
+
 
 .section "Private options for smtp" "SECID146"
 .cindex "options" "&(smtp)& transport"
@@ -22057,7 +22106,7 @@ ignored.
 
 The expansion happens after the outgoing connection has been made and TLS
 started, if required. This means that the &$host$&, &$host_address$&,
-&$tls_cipher$&, and &$tls_peerdn$& variables are set according to the
+&$tls_out_cipher$&, and &$tls_out_peerdn$& variables are set according to the
 particular connection.
 
 If the SMTP session is not authenticated, the expansion of
@@ -22618,7 +22667,7 @@ ciphers is a preference order.
 .option tls_sni smtp string&!! unset
 .cindex "TLS" "Server Name Indication"
 .vindex "&$tls_sni$&"
-If this option is set then it sets the $tls_sni variable and causes any
+If this option is set then it sets the $tls_out_sni variable and causes any
 TLS session to pass this value as the Server Name Indication extension to
 the remote side, which can be used by the remote side to select an appropriate
 certificate and private key for the session.
@@ -23890,11 +23939,8 @@ When Exim is authenticating as a client, it skips any authenticator whose
 used, for example, to skip plain text authenticators when the connection is not
 encrypted by a setting such as:
 .code
-client_condition = ${if !eq{$tls_cipher}{}}
+client_condition = ${if !eq{$tls_out_cipher}{}}
 .endd
-(Older documentation incorrectly states that &$tls_cipher$& contains the cipher
-used for incoming messages. In fact, during SMTP delivery, it contains the
-cipher used for the delivery.)
 
 
 .option driver authenticators string unset
@@ -24054,10 +24100,10 @@ authentication mechanisms. For example, it can be used to restrict the
 advertisement of a particular mechanism to encrypted connections, by a setting
 such as:
 .code
-server_advertise_condition = ${if eq{$tls_cipher}{}{no}{yes}}
+server_advertise_condition = ${if eq{$tls_in_cipher}{}{no}{yes}}
 .endd
-.vindex "&$tls_cipher$&"
-If the session is encrypted, &$tls_cipher$& is not empty, and so the expansion
+.vindex "&$tls_in_cipher$&"
+If the session is encrypted, &$tls_in_cipher$& is not empty, and so the expansion
 yields &"yes"&, which allows the advertisement to happen.
 
 When an Exim server receives an AUTH command from a client, it rejects it
@@ -25122,10 +25168,11 @@ name of a directory (for OpenSSL it can be either).
 .next
 The default value for &%tls_dhparam%& differs for historical reasons.
 .next
-.vindex "&$tls_peerdn$&"
+.vindex "&$tls_in_peerdn$&"
+.vindex "&$tls_out_peerdn$&"
 Distinguished Name (DN) strings reported by the OpenSSL library use a slash for
 separating fields; GnuTLS uses commas, in accordance with RFC 2253. This
-affects the value of the &$tls_peerdn$& variable.
+affects the value of the &$tls_in_peerdn$& and &$tls_out_peerdn$& variables.
 .next
 OpenSSL identifies cipher suites using hyphens as separators, for example:
 DES-CBC3-SHA. GnuTLS historically used underscores, for example:
@@ -25432,15 +25479,13 @@ forced to fail, Exim behaves as if the option is not set.
 
 .cindex "cipher" "logging"
 .cindex "log" "TLS cipher"
-.vindex "&$tls_cipher$&"
-The variable &$tls_cipher$& is set to the cipher suite that was negotiated for
+.vindex "&$tls_in_cipher$&"
+The variable &$tls_in_cipher$& is set to the cipher suite that was negotiated for
 an incoming TLS connection. It is included in the &'Received:'& header of an
 incoming message (by default &-- you can, of course, change this), and it is
 also included in the log line that records a message's arrival, keyed by
 &"X="&, unless the &%tls_cipher%& log selector is turned off. The &%encrypted%&
 condition can be used to test for specific cipher suites in ACLs.
-(For outgoing SMTP deliveries, &$tls_cipher$& is reset &-- see section
-&<<SECID185>>&.)
 
 Once TLS has been established, the ACLs that run for subsequent SMTP commands
 can check the name of the cipher suite and vary their actions accordingly. The
@@ -25449,6 +25494,9 @@ example, OpenSSL uses the name DES-CBC3-SHA for the cipher suite which in other
 contexts is known as TLS_RSA_WITH_3DES_EDE_CBC_SHA. Check the OpenSSL or GnuTLS
 documentation for more details.
 
+For outgoing SMTP deliveries, &$tls_out_cipher$& is used and logged
+(again depending on the &%tls_cipher%& log selector).
+
 
 .section "Requesting and verifying client certificates" "SECID183"
 .cindex "certificate" "verification of client"
@@ -25485,17 +25533,17 @@ fact that no certificate was verified, and vary their actions accordingly. For
 example, you can insist on a certificate before accepting a message for
 relaying, but not when the message is destined for local delivery.
 
-.vindex "&$tls_peerdn$&"
+.vindex "&$tls_in_peerdn$&"
 When a client supplies a certificate (whether it verifies or not), the value of
 the Distinguished Name of the certificate is made available in the variable
-&$tls_peerdn$& during subsequent processing of the message.
+&$tls_in_peerdn$& during subsequent processing of the message.
 
 .cindex "log" "distinguished name"
 Because it is often a long text string, it is not included in the log line or
 &'Received:'& header by default. You can arrange for it to be logged, keyed by
 &"DN="&, by setting the &%tls_peerdn%& log selector, and you can use
 &%received_header_text%& to change the &'Received:'& header. When no
-certificate is supplied, &$tls_peerdn$& is empty.
+certificate is supplied, &$tls_in_peerdn$& is empty.
 
 
 .section "Revoked certificates" "SECID184"
@@ -25576,12 +25624,12 @@ All the TLS options in the &(smtp)& transport are expanded before use, with
 which the client is connected. Forced failure of an expansion causes Exim to
 behave as if the relevant option were unset.
 
-.vindex &$tls_bits$&
-.vindex &$tls_cipher$&
-.vindex &$tls_peerdn$&
-.vindex &$tls_sni$&
+.vindex &$tls_out_bits$&
+.vindex &$tls_out_cipher$&
+.vindex &$tls_out_peerdn$&
+.vindex &$tls_out_sni$&
 Before an SMTP connection is established, the
-&$tls_bits$&, &$tls_cipher$&, &$tls_peerdn$& and &$tls_sni$&
+&$tls_out_bits$&, &$tls_out_cipher$&, &$tls_out_peerdn$& and &$tls_out_sni$&
 variables are emptied. (Until the first connection, they contain the values
 that were set when the message was received.) If STARTTLS is subsequently
 successfully obeyed, these variables are set to the relevant values for the
@@ -25591,8 +25639,8 @@ outgoing connection.
 
 .section "Use of TLS Server Name Indication" "SECTtlssni"
 .cindex "TLS" "Server Name Indication"
-.vindex "&$tls_sni$&"
-.oindex "&%tls_sni%&"
+.vindex "&$tls_in_sni$&"
+.oindex "&%tls_in_sni%&"
 With TLS1.0 or above, there is an extension mechanism by which extra
 information can be included at various points in the protocol.  One of these
 extensions, documented in RFC 6066 (and before that RFC 4366) is
@@ -25619,14 +25667,14 @@ different clients.  Or even negotiate different cipher suites.
 The &%tls_sni%& option on an SMTP transport is an expanded string; the result,
 if not empty, will be sent on a TLS session as part of the handshake.  There's
 nothing more to it.  Choosing a sensible value not derived insecurely is the
-only point of caution.  The &$tls_sni$& variable will be set to this string
+only point of caution.  The &$tls_out_sni$& variable will be set to this string
 for the lifetime of the client connection (including during authentication).
 
-Except during SMTP client sessions, if &$tls_sni$& is set then it is a string
+Except during SMTP client sessions, if &$tls_in_sni$& is set then it is a string
 received from a client.
 It can be logged with the &%log_selector%& item &`+tls_sni`&.
 
-If the string &`tls_sni`& appears in the main section's &%tls_certificate%&
+If the string &`tls_in_sni`& appears in the main section's &%tls_certificate%&
 option (prior to expansion) then the following options will be re-expanded
 during TLS session handshake, to permit alternative values to be chosen:
 
@@ -26640,7 +26688,7 @@ confusing to some people, so the use of &%endpass%& is no longer recommended as
 This modifier sets up a message that is used as part of the log message if the
 ACL denies access or a &%warn%& statement's conditions are true. For example:
 .code
-require log_message = wrong cipher suite $tls_cipher
+require log_message = wrong cipher suite $tls_in_cipher
         encrypted   = DES-CBC3-SHA
 .endd
 &%log_message%& is also used when recipients are discarded by &%discard%&. For
index 963ec16966961c1f09091a2c116ed525721ff420..0ccbbe85587dab805208322b1cdc0e5437f227e6 100644 (file)
@@ -771,7 +771,7 @@ begin authenticators
 #  server_set_id              = $auth2
 #  server_prompts             = :
 #  server_condition           = Authentication is not yet configured
-#  server_advertise_condition = ${if def:tls_cipher }
+#  server_advertise_condition = ${if def:tls_in_cipher }
 
 # LOGIN authentication has traditional prompts and responses. There is no
 # authorization ID in this mechanism, so unlike PLAIN the username and
@@ -783,7 +783,7 @@ begin authenticators
 #  server_set_id              = $auth1
 #  server_prompts             = <| Username: | Password:
 #  server_condition           = Authentication is not yet configured
-#  server_advertise_condition = ${if def:tls_cipher }
+#  server_advertise_condition = ${if def:tls_in_cipher }
 
 
 ######################################################################
index 1642c67b708178757e9bda28e927275397b0194b..62e8e5747e6cf61e78e3ed9ea3c18d33c450a8f7 100644 (file)
@@ -613,9 +613,18 @@ static var_entry var_table[] = {
 #endif
   { "thisaddress",         vtype_stringptr,   &filter_thisaddress },
 
+  /* The non-(in,out) variables are now deprecated */
   { "tls_bits",            vtype_int,         &tls_in.bits },
   { "tls_certificate_verified", vtype_int,    &tls_in.certificate_verified },
   { "tls_cipher",          vtype_stringptr,   &tls_in.cipher },
+
+  { "tls_in_bits",         vtype_int,         &tls_in.bits },
+  { "tls_in_certificate_verified", vtype_int, &tls_in.certificate_verified },
+  { "tls_in_cipher",       vtype_stringptr,   &tls_in.cipher },
+  { "tls_in_peerdn",       vtype_stringptr,   &tls_in.peerdn },
+#if defined(SUPPORT_TLS) && !defined(USE_GNUTLS)
+  { "tls_in_sni",          vtype_stringptr,   &tls_in.sni },
+#endif
   { "tls_out_bits",        vtype_int,         &tls_out.bits },
   { "tls_out_certificate_verified", vtype_int,&tls_out.certificate_verified },
   { "tls_out_cipher",      vtype_stringptr,   &tls_out.cipher },
@@ -623,6 +632,7 @@ static var_entry var_table[] = {
 #if defined(SUPPORT_TLS) && !defined(USE_GNUTLS)
   { "tls_out_sni",         vtype_stringptr,   &tls_out.sni },
 #endif
+
   { "tls_peerdn",          vtype_stringptr,   &tls_in.peerdn },        /* mind the alphabetical order! */
 #if defined(SUPPORT_TLS) && !defined(USE_GNUTLS)
   { "tls_sni",             vtype_stringptr,   &tls_in.sni },   /* mind the alphabetical order! */
@@ -1688,6 +1698,31 @@ return NULL;          /* Unknown variable name */
 
 
 
+void
+modify_variable(uschar *name, void * value)
+{
+int first = 0;
+int last = var_table_size;
+
+while (last > first)
+  {
+  int middle = (first + last)/2;
+  int c = Ustrcmp(name, var_table[middle].name);
+
+  if (c > 0) { first = middle + 1; continue; }
+  if (c < 0) { last = middle; continue; }
+
+  /* Found an existing variable; change the item it refers to */
+  var_table[middle].value = value;
+  return;
+  }
+return;          /* Unknown variable name, fail silently */
+}
+
+
+
+
+
 /*************************************************
 *           Read and expand substrings           *
 *************************************************/
index 02d152ad6168b55f58ce7e0d2182b7bdc531df8a..09f7ab95c86b71cf88a8a2293e6af4107bff4818 100644 (file)
@@ -131,6 +131,7 @@ extern BOOL    expand_check_condition(uschar *, uschar *, uschar *);
 extern uschar *expand_string(uschar *);
 extern uschar *expand_string_copy(uschar *);
 extern int_eximarith_t expand_string_integer(uschar *, BOOL);
+extern void    modify_variable(uschar *, void *);
 
 extern int     filter_interpret(uschar *, int, address_item **, uschar **);
 extern BOOL    filter_personal(string_item *, BOOL);
index f8172e76b0398639ed29b2c1a3c23ad364803625..c582af79f0c43472c434e6881c1ae9e666005fbc 100644 (file)
@@ -649,7 +649,11 @@ if (!state->host)
   {
   if (!state->received_sni)
     {
-    if (state->tls_certificate && Ustrstr(state->tls_certificate, US"tls_sni"))
+    if (state->tls_certificate &&
+        (Ustrstr(state->tls_certificate, US"tls_sni") ||
+         Ustrstr(state->tls_certificate, US"tls_in_sni") ||
+         Ustrstr(state->tls_certificate, US"tls_out_sni")
+       ))
       {
       DEBUG(D_tls) debug_printf("We will re-expand TLS session files if we receive SNI.\n");
       state->trigger_sni_changes = TRUE;
@@ -966,7 +970,7 @@ if (rc != OK) return rc;
 /* set SNI in client, only */
 if (host)
   {
-  if (!expand_check(state->tlsp->sni, "tls_sni", &state->exp_tls_sni))
+  if (!expand_check(state->tlsp->sni, "tls_out_sni", &state->exp_tls_sni))
     return DEFER;
   if (state->exp_tls_sni && *state->exp_tls_sni)
     {
index d5b31e72c646167204f34088621664acb790a0ee..a8a62fe8cbbc2ad7e263abe9342f7a9c585af0ee 100644 (file)
@@ -543,7 +543,10 @@ uschar *expanded;
 if (cbinfo->certificate == NULL)
   return OK;
 
-if (Ustrstr(cbinfo->certificate, US"tls_sni"))
+if (Ustrstr(cbinfo->certificate, US"tls_sni") ||
+    Ustrstr(cbinfo->certificate, US"tls_in_sni") ||
+    Ustrstr(cbinfo->certificate, US"tls_out_sni")
+   )
   reexpand_tls_files_for_sni = TRUE;
 
 if (!expand_check(cbinfo->certificate, US"tls_certificate", &expanded))
index eaab14dc97bd2361070d7837fa35bedbd8e744ca..a1b8142a9e75346571e47685374cde0e36078105 100644 (file)
@@ -1521,6 +1521,18 @@ addresses, such rewriting fails. */
 
 if (address[0] == 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
+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
+
 /* 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). */
 
@@ -1769,8 +1781,12 @@ while (addr_new != NULL)
       }
     cancel_cutthrough_connection("routing hard fail");
 
-    if (!full_info) return copy_error(vaddr, addr, FAIL);
-      else yield = FAIL;
+    if (!full_info)
+    {
+      yield = copy_error(vaddr, addr, FAIL);
+      goto out;
+    }
+    else yield = FAIL;
     }
 
   /* Soft failure */
@@ -1804,8 +1820,12 @@ while (addr_new != NULL)
       }
     cancel_cutthrough_connection("routing soft fail");
 
-    if (!full_info) return copy_error(vaddr, addr, DEFER);
-      else if (yield == OK) yield = DEFER;
+    if (!full_info)
+      {
+      yield = copy_error(vaddr, addr, DEFER);
+      goto out;
+      }
+    else if (yield == OK) yield = DEFER;
     }
 
   /* If we are handling EXPN, we do not want to continue to route beyond
@@ -1828,7 +1848,8 @@ while (addr_new != NULL)
       if (addr_new == NULL) ok_prefix = US"250 ";
       respond_printf(f, "%s<%s>\r\n", ok_prefix, addr2->address);
       }
-    return OK;
+    yield = OK;
+    goto out;
     }
 
   /* Successful routing other than EXPN. */
@@ -1863,7 +1884,8 @@ while (addr_new != NULL)
       of $address_data to be that of the child */
 
       vaddr->p.address_data = addr->p.address_data;
-      return OK;
+      yield = OK;
+      goto out;
       }
     }
   }     /* Loop for generated addresses */
@@ -1880,7 +1902,7 @@ discarded, usually because of the use of :blackhole: in an alias file. */
 if (allok && addr_local == NULL && addr_remote == NULL)
   {
   fprintf(f, "mail to %s is discarded\n", address);
-  return yield;
+  goto out;
   }
 
 for (addr_list = addr_local, i = 0; i < 2; addr_list = addr_remote, i++)
@@ -1964,9 +1986,19 @@ for (addr_list = addr_local, i = 0; i < 2; addr_list = addr_remote, i++)
     }
   }
 
-/* Will be DEFER or FAIL if any one address has, only for full_info (which is
+/* Yield will be DEFER or FAIL if any one address has, only for full_info (which is
 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
+
 return yield;
 }