On 28/04/2024 22:32, Mark Hills via Exim-users wrote:
"verify = certificate" no longer passes after some system upgrade.

Some?  What, precisely?

My systems running OpenSMTPD submit mail to an Exim smarthost.

Authentication used "verify = certificate", then checks for known
certificate fingerprint. This has worked for many years. Extracts from
configuration at the end of this mail.

But now "verify = certificate" no longer passes in _one_ case (others are
fine), which becomes my test case:

- client: opensmtpd 7.4.0p1-r1 (Alpine Linux 3.19.1)

- smarthost: exim 4.97.1_4 (FreeBSD 13.2-RELEASE-p11)

The client certificate has not been changed.

I also tested copying over the key + cert (and HELO identity) from a
working system, and it did not work on this system.

Using exim's +all logging is not very insightful; the result of a 'diff'
is that authentication simply disappeared:

  SSL SSL_accept,state_chg: SSLv3/TLS write finished
  SSL SSL_accept,state_chg: TLSv1.3 early data
  SSL SSL_accept,state_chg: TLSv1.3 early data
-SSL authenticated verify ok: depth=0 SN=/C=GB/L=London/CN=xxxxxx
  SSL SSL_accept,state_chg: SSLv3/TLS read client certificate
-SSL SSL_accept,state_chg: SSLv3/TLS read certificate verify

Further up the logs, is the only tangible difference I can see is SNI
being sent by the (newer) OpenSMTPd client:

  SSL SSL_accept,state_chg: before SSL initialization
  SSL SSL_accept,state_chg: before SSL initialization
+Received TLS SNI "mail.xxxxxxxxxx.uk" (unused for certificate selection)
  SSL SSL_accept,state_chg: SSLv3/TLS read client hello

The only other differences appear to be secrets, hostnames, PIDs, memory
addresses etc..

So where to go from here:

1) sending SNI is breaking "verify = certificate" at Exim? or

Unlikely, on it's own

2) some other TLS change which is invisible in the Exim log; or

I'd go for this


Lets log some more stuff.

a new main-section option:

event_action = ${acl {tls_inbound_event}}


and new ACLs:

# 2 args: name that cert should apply for, name of cert variable
# DO NOT CALL with unsafe data for arg2
is_certname_verify:
  accept set acl_m_tmp = \${certextract {subj_altname,dns}{\$$acl_arg2}}
         set acl_m_tmp = ${expand:$acl_m_tmp}
         condition =    ${if def:acl_m_tmp}
         endpass
         acl =          is_c_altname_v $acl_arg1 ${lc:$acl_m_tmp}
         set acl_m_tmp =
  accept set acl_m_tmp = \${certextract {subject,CN}{\$$acl_arg2}}
         acl =          is_name_match $acl_arg1 ${lc:${expand:$acl_m_tmp}}
         set acl_m_tmp =
  deny   set acl_m_tmp =
#         logwrite =    $event_name $acl_arg1: name DOES NOT verify

 inbound_user_cert:
   accept set acl_m_tmp = ${certextract {subj_altname,mail} {$tls_in_peercert}}
        condition =    ${if def:acl_m_tmp}
        logwrite =     potential user cert <$acl_m_tmp>
        set acl_m_tmp =

tls_inbound_event:
  accept condition =    ${if !eq {tls:cert} {$event_name}}

  # cert logging
  warn   logwrite =     [$sender_host_address] $sender_host_name \
                        $event_name depth=$event_data \
                        <${certextract {subject} {$tls_in_peercert}}>\
                        ${if ={0}{$event_data} \
                          { <${certextract {subj_altname}{$tls_in_peercert}}>}}
  accept condition =    ${if !={0}{$event_data}}
  accept acl =          inbound_user_cert
  deny   condition =    ${if !def:sender_host_name}
         logwrite =     [$sender_host_address] no rDNS - can't verify 
client-cert
         message =      fail
  deny   !acl =         is_certname_verify ${lc:$sender_host_name} 
tls_in_peercert
         logwrite =     [$sender_host_address] $sender_host_name client-cert 
name mismmatch; try relaxed-rDNS names
         !condition =   ${if forany {${lookup dnsdb{>: 
ptr=$sender_host_address}}} \
                            {and {{!eqi {$sender_host_name}{$item}} \
                                  
{acl{{is_certname_verify}{${lc:$item}}{tls_in_peercert}}} \
                         }  }    }
#        message =      client-cert hostname mismatch
         logwrite =     [$sender_host_address] client-cert hostname mismatch
  accept logwrite =     [$sender_host_address] $sender_host_name client-cert 
relaxed-rDNS name ok



I've hacked this out of my own config.  It should give a hint as to what stage
in the cert chain the verify fails, if it's not the leaf.  If it's the leaf
then it'll point the finger at a cert-name problem, if that's it.  Otherwise
we'll have to think harder.

You may need to tweak the notion of a "user cert" embedded in 
"inbound_user_cert" -
I don't know what yours look like.
--
Cheers,
  Jeremy


--
## subscription configuration (requires account):
##   https://lists.exim.org/mailman3/postorius/lists/exim-users.lists.exim.org/
## unsubscribe (doesn't require an account):
##   exim-users-unsubscr...@lists.exim.org
## Exim details at http://www.exim.org/
## Please use the Wiki with this list - http://wiki.exim.org/

Reply via email to