Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to specify certificate chain for AuthenticateAsServer?

Tags:

c#

ssl

chain

I'm struggling with the apparent lack of flexibility in SslStream AuthenticateAsServer. I have a self-signed rootCA, an intermediate CA, and an end-entity (host) certificate. I am only doing server authentication. The client has the rootCA cert baked in, and I am trying to come up with some way to send the full chain from the server to the client, so that the client can validate the server, and I can additionally compare the thumbprints of the trust anchor rootCA with that included in the client.

Ideally I would like to avoid using the cert store and send the certificates explicitly. If anyone knows how to do this, it is the immediate best solution to my problem.

But it seems that SslStream AuthenticateAsServer will not in any documented way let you explicitly specify a chain to send. You must just send the bottom cert, and let it dig the rest out of the cert store. This is less than ideal but it seems like the only option so I am trying it that way. The problem now, is that (with the self signed CA in the Trusted Root Certification Authorities, and the intermediate in the Intermediate Root Certification Authorities on the server) only the host cert and the intermedate cert are being "automagically" sent to the client. I am only getting those two certs on the client, not the rootCA cert. Why?

Is there a way to AuthenticateAsServer with an cert chain?

If not, is it a thing that it will cut the root cert off the top of the chain before sending?

If there are no answers to the above, is there at least a way to shunt the (auto)magic that digs the rest of the chain out of the store, where I can look at the result, rather than having to go through AuthenticateAsServer, to the client CertValidationCallback? Atleast this way I would be debugging a single black box, rather than a string of several black boxes.

like image 629
user1169420 Avatar asked Dec 15 '14 21:12

user1169420


1 Answers

Updating this question I asked 4 years ago. I was never able to find any way to do anything described in the above. SslStream really just has such a rigid interface. Sometimes I would get the root cert back in the chain (if the authenticating side is xamarin?), most other times I would not, and there is no way to force it one way or the other. So I ended up doing two things to work around this:

  1. Since the client has the root cert embedded as a resource I pull that out during the cert validation callback and explicitly add it to the chain.ChainPolicy.ExtraStore and then verify that the chain builds.
  2. Assuming the chain built, I then check the condition (chain.ChainElements[chain.ChainElements.Count - 1].Certificate.Thumbprint == rootCert.Thumbprint) This verifies that after adding the true root cert, the cert which was actually used as the root cert to build the chain, is indeed the true root cert. This prevents someone from using some other root cert and it passing validation just because the chain builds.

So we make sure that #1 with the root cert added a chain can be built and #2 the chain that is built is built includes our root cert.

like image 169
user1169420 Avatar answered Nov 09 '22 03:11

user1169420