[PATCH] Add provision to fetch certificate chain from Nginx

Maxim Dounin mdounin at mdounin.ru
Sun Jan 30 23:55:09 UTC 2022


Hello!

On Sat, Jan 29, 2022 at 01:50:24PM +0000, CHHABRA Mandeep Singh via nginx-devel wrote:

> > Sure, intermediate certificates are not required to be known 
> > by the server and can be provided by the client in the extra 
> > certificates during SSL/TLS handshake.
> 
> I am not sure what you mean by passing the intermediate CAs in 
> the extra certificates.  They are CA certificates and are passed 
> as CA certificate chain.  For example: curl has option --cacert 
> which can take the entire chain of CA certificates (from 
> immediate issuer to the trust anchor)
> # curl --cacert

The "extra" is as in SSL_CTX_add_extra_chain_cert, see
https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_add_extra_chain_cert.html.  

During SSL/TLS handshake client sends the list of certificates to 
the server.  The certificate list is expected to contain the 
client certificate itself, followed by optional/extra additional 
certificates (usually not including the root, since including it 
is just a waste of resources).  It is defined by TLSv1.2 
sepecification as follows
(https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.2):

   certificate_list
      This is a sequence (chain) of certificates.  The sender's
      certificate MUST come first in the list.  Each following
      certificate MUST directly certify the one preceding it.  Because
      certificate validation requires that root keys be distributed
      independently, the self-signed certificate that specifies the root
      certificate authority MAY be omitted from the chain, under the
      assumption that the remote end must already possess it in order to
      validate it in any case.

Note that the certificate list is used for both server and client 
certificates.  As previously suggested, it is believed that client 
certificates are almost always used without any additional 
intermediate certificates being sent by the client.

> > Further, it is not really possible to properly retrieve such 
> > client-provided intermediate certificates after the initial
> > handshake: these certificates are not saved to the session 
> > data and therefore not available after session reuse, see
> > 7653:8409f9df6219 
> > (http://hg.nginx.org/nginx/rev/8409f9df6219).
> 
> AFAIU, intermediate CA certificates are not supposed to be known 
> by Nginx anyway. I am not sure if we are referring to
> two different things here. But with the changes which I 
> proposed, I am able to retrieve the entire chain from Nginx(also 
> in cases
> when intermediate CAs are not known to the server). During 
> certificate verification, Nginx creates a verified chain from 
> the incoming certificate chain and the CA certificate which is 
> trusted on the web interface. Nginx only needs to know about the 
> trust anchor (the self signed CA certificate)

Try to retrieve the entire chain in a connection which is using an 
abbreviated handshake, not an initial one.

The information about intermediate certificates which are not 
known on the server is not preserved by OpenSSL in the session 
data.  As such, it is not possible to re-create the certificate 
chain in the connection using abbreviated handshake.

This is explicitly documented in the man page of the 
SSL_get0_verified_chain() function you are using, see 
https://www.openssl.org/docs/man1.1.1/man3/SSL_get0_verified_chain.html:

: If the session is resumed peers do not send certificates so a NULL 
: pointer is returned by these functions.

The client certificate itself is preserved in the session data, so 
it is available after session resumption.  This makes it possible 
to re-create the certificate chain if no client-provided 
certificates are used, see the 7653:8409f9df6219 change mentioned 
above.

Hope this helps.

> > And you want to allow access only to certificates signed by
> > Intermediate1 CA in some cases, and only certificates signed by
> > Intermediate2 CA in other cases.  Is that correct?
> 
> You are correct partially. Yes, we need to allow/deny a configuration based on the configuration available for the CA.
> There could be different combinations with the chain here
> 1- Cert-> Intermediate1 -> Root
> 2- Cert-> Intermediate2 -> Root
> 3- Cert-> Root
> 4- Cert-> Intermediate1 -> Intermediate2 -> Root
> 
> For example:-
> Consider the chain "Cert-> Intermediate1 -> Intermediate2 -> Root"
> We need to something based on Intermediate2's configuration and it is possible that the 
> Intermediate1 is not known to the server. 

As previously suggested, while technically it is possible, it is 
usually indicate that it might be a good idea to reconsider the 
configuration and make sure that all intermediate certificates are 
known on the server.

-- 
Maxim Dounin
http://mdounin.ru/



More information about the nginx-devel mailing list