Here is the project: I'm creating a TcpListener in C#, that will host on a Linux box using Mono.
Then I will have a TcpClient (also Mono on Linux) that will connect to it, and because I can't have a username/password auth, I would like it that clients connect with a "client certificate", that I will generate with my Root CA (also self-generated)
I can't only have the client connect securely to the server, I need my TcpListener to trust my client connection too.
What i have done so far: I have exported my server certificate as PFX:
And loaded this into the code:
sslCertificate = new X509Certificate2("myCert.pfx", "password");
Now, if I run the code as below:
bool requireClientCertificate = false; // <== turn on/off SslStream sslStream = new SslStream(netStream, false, new RemoteCertificateValidationCallback(AcceptRemoteCertificate)); sslStream.AuthenticateAsServer(sslCertificate, requireClientCertificate, SslProtocols.Tls, false);
requireClientCertificate = false, then I can use a browser to view this page perfectly fine. Of course, I would have already imported my Root CA, in order to see this page, otherwise Chrome gives me a certificate warning.
Right, so there is no problem with this so far... and SSL is established, but technically anyone could connect to this TcpListner.
Now I set
requireClientCertificate = true, and this is where things fall apart.
I realize I need to generate a client certificate, so I did that, exported that, and imported it into my PC. I can see it under the certificate list in Chrome, and I am prompted to use it when I first attempt to connect the TcpListner.
However, doing all that, still does not solve things.
I have also installed the Root CA onto the server using:
- copy to /usr/share/ca-certificates/mozilla/MyRootCA.crt
- editing /etc/ca-certificates.conf
- update-ca-certificates (This showed 1 new certificate installed.. but still did'nt help)
Then I tried:
certmgr -add -c -v -m Trust /home/Certs/MyRootCA.crt
Still not working, so i tried:
certmgr -add -c -v -m CA /home/Certs/MyRootCA.crt
So from what I can see the RootCA is installed.
If I try connect with Chrome I'm getting:
RemoteCertificateChainErrors in the
And if I loop thought the chain, I get :
PartialChain in the Status Information.
And if I test with OpenSSL, I get:
UntrustedRoot in the Status Information
The totally confusing part on this, is that, my RemoteCertificate of the TcpListner is not null - it is in fact a the certificate that I installed on the browser, and can see the RootCA that singed it too (Issuer).
If I actually do a:
wget https://api.myserver.com --certificate=/my.crt --private-key=/my.key --ca-certificate=/MyRootCA.crt, it connects and downloaded my expedited results.
- Is this connection actually mutually secure?
- What are those errors about? UntrustedRoot and PartialChain
- If it has these errors, but still can present a RemoteCertificate, does that mean its a mutually secure connection or not?
In the past I have done this on Windows Server with a commercial CA certificates (DigiCert E.V.), and other (out of my control) CPE's, and they worked without errors. This is the only difference I have noticed. Is this the reason? Does Linux / Mono, have some sort of additional knowledge about certificates, that if you generate your own Root CA... it can't trust it completely?