[PATCH] Add provision to fetch certificate chain from Nginx

CHHABRA Mandeep Singh mandeep-singh.chhabra at thalesgroup.com
Sat Jan 29 13:50:24 UTC 2022


Hi Maxim, 

> 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


> 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)


> 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. 

Let me try to explain in detail :
1- There is a client certificate which is issued by an intermediate CA certificate and the intermediate CA is issued by a trust anchor.
i.e.
Cert1 -> Intermediate1 ->Root1 ( self signed CA).
The Root1 is a trust anchor and is trusted on the web interface. 
The Intermediate1 is not known on the server. 

When a client established a connection with the server, passing the chain as
Cert1 -> Intermediate1 -> Root1(optionally)
nginx accepts this connection and creates a verified chain, because the Root1 is trusted on the interface and it is a self signed certificate. 
Nginx passes the client certificate (Cert1) to the middleware. 

If the Intermediate1 was known to the server always, we could do what you are suggesting(using ssl_client_i_dn and ssl_client_escaped_cert)
If the Intermediate1 is not known to the server, there is no way to know/get the Root1 CA from the Cert1.

Probably, I can try to explain in a better format, if you need.
Please let me know. 

Regards,
Mandeep 






-----Original Message-----
From: nginx-devel <nginx-devel-bounces at nginx.org> On Behalf Of Maxim Dounin
Sent: Wednesday, January 12, 2022 2:11 AM
To: nginx-devel at nginx.org
Subject: Re: [PATCH] Add provision to fetch certificate chain from Nginx

Hello!

On Thu, Dec 30, 2021 at 09:35:26AM +0000, CHHABRA Mandeep Singh wrote:

> As far as my understanding goes, the intermediate CA certificates are 
> not required to be known to the server.
> It is only the trust anchor(the root CA certificate) which is required 
> to be known and trusted on the sever.
> And in our case also, the root CA certificate is trusted for the web.

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.

Such configurations are believed to be extremely rare though: in most cases intermediate certificates are well known and can be easily configured on the server side, and this saves extra configuration on clients.

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).

Hence the original question about the problem you trying to solve.

> I have tried to give a brief of the problem in the following section.
> 
> We have a product which supports multi-tenancy and uses Nginx as a 
> reverse proxy.
> There are different isolated domains which share the same trust 
> anchor. But there could be difference in the client certificate chain 
> in different domains. There is a need to do some extra validations 
> based on the CAs in the chain.
> To be more precise, we have option to specify if a CA could be used to 
> do client or user authentication. There is a possibility that in one 
> domain, a CA is enabled for client authentication and in another , the 
> same CA is disabled.
> 
> So, we need a way to get the certificate chain from Nginx, to do these 
> extra validations, apart from what Nginx does i.e.
> checking if the chain could be verified.
> But there is no way to get the chain, today.

Not sure I've understood your description correctly, but from what I understood it looks like you are not trying to retrieve client-provided intermediate certificates, but instead trying to do additional checking on the chain which contains client-provided end certificate and the chain constructed by nginx from the intermediate certificates known on the server during certificate verification.  That is, you have something like:

- Root CA, Intermediate1 CA, Intermediate2 CA - all known on the
  server;

- Client certs signed by Intermediate1 CA;

- Client certs signed by Intermediate2 CA.

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?

Such problem seems to be solvable by just looking at $ssl_client_escaped_cert and re-creating the certificate chain from the list of CA certificates known on the server.  In simple cases (assuming all intermediate CA DNs are unique) just checking the $ssl_client_i_dn variable would be enough.

Does it look reasonable, or I misunderstood something?

--
Maxim Dounin
http://mdounin.ru/
_______________________________________________
nginx-devel mailing list
nginx-devel at nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel



More information about the nginx-devel mailing list