Search code examples
sslhaproxyx509client-certificates

HAProxy SSL Termination - Client certificate Extended Key usage extension validation


We're using HAProxy (v1.6.9) to verify client certificates(X.509 v3) and do SSL termination. We want to validate the Extended key usage and the basic constraints extensions in the client certificate. By looking at the HAProxy source code and OpenSSL verify documentation, I guess the keyUsage extension would be validated. But, does it do validation of the Extended Key Usage as well as Basic constraints extensions? If not, then is there a way to set this information in the request header and forward it to the application, so that the application can validate it?

Based on my understanding of OpenSSL documentation, we need to set the "purpose" option in verify to validate these extensions and I couldn't find this option being set in HAProxy's source code. Please correct me, if I'm wrong.

Thank you.


Solution

  • When you use commandline verify or call X509_verify_cert you do need to specify 'purpose' if you want it checked, because these operations can handle cert chains used for any purpose (or combination of purposes). For SSL/TLS protocols this is handled automatically, because the libssl code knows that it received and is checking a cert/chain for an 'SSL' (including TLS) server or client; see function ssl_validate_cert_chain in ssl/ssl_cert.c -- this line has the effect of specifying 'purpose'. For release 1.1.0 only (so far) the purpose is also checked against optional local trust attributes for the anchor/root (in addition to ExtendedKeyUsage extension(s)).

    The statement on the man page that "If the -purpose option is not included then no checks [of untrusted cert extensions] are done." may be misleading. If purpose is not specified no checks for purpose are done, but some checks of extensions are always done regardless of purpose -- at least always for a proper chain with CA cert(s) distinct from the EE cert; for a selfsigned EE cert, which acts as its own anchor and effectively its own CA, some checks are inapplicable.

    In particular, as mentioned a few paragraphs earlier, during the build phase CA (aka issuer) certs are checked for KeyUsage.certSign and SKI/issuer/serial matching AKI. During the second phase all untrusted certs are checked for BasicConstraints (and the now-rare NetscapeCertType) and KeyUsage.certSign (again), and NameConstraints (since 1.0.0), and the EE SAN or Subject is matched if a peer id was configured (which generally makes sense only if the peer is the server, hence not your case, and only since 1.0.2); also revocation checking (which may involve extensions) if configured (not the default); and if purpose checking is configured (which it is for libssl) in addition to ExtKeyUsage on all untrusted certs it checks KeyUsage and NetscapeCertType of the EE cert. Although the EE KeyUsage check here is not specific to the ciphersuite and thus keyexchange method negotiated; that is checked separately in libssl.

    And the final phase in addition to checking signatures and validityperiod (as stated) also checks the RFC3779 extensions if used (almost never?) and if configured (probably rare) CertificatePolicies plus PolicyMappings, PolicyConstraints, and InhibitAnyPolicy.

    Do note extension checks only fail if the extension is present with an inconsistent value; if an extension is omitted (by the CA) from a given cert it effectively permits everything related to that extension.

    HTH.