1

I am attempting to write a client-server library for letting my LAN computers talk to each other. As this is largely a self-education attempt, I am trying to make these connections occur over SSL. My plan is to maintain a single host machine, and have each client maintain a mutually authenticated System.Net.SslStream instance to the host. The host code looks (roughly speaking) like this (error handling omitted for brevity):

SslStream newStream = null;
newStream = new SslStream(this.client.GetStream(), false);
newStream.AuthenticateAsServer(
    this.Certificate as X509Certificate,
    true,
    System.Security.Authentication.SslProtocols.Tls,
    false);

if (!(
    newStream.IsMutuallyAuthenticated &&
    newStream.IsEncrypted &&
    newStream.IsSigned))
{
    throw new AuthenticationException("Authentication results unsatisfactory.");
}

In this, this.Certificate is an X509Certificate2. The client code looks like this:

SslStream connectionStream = new SslStream(this.client.GetStream(), false);

connectionStream.AuthenticateAsClient(
    this.ServerHostname,
    new X509CertificateCollection(new X509Certificate[] { (X509Certificate)this.Certificate }),
    SslProtocols.Tls,
    false);

if (!(
    connectionStream.IsEncrypted &&
    connectionStream.IsMutuallyAuthenticated &&
    connectionStream.IsSigned))
{
    throw new AuthenticationException("Authentication results unsatisfactory");
}

I have generated client and server certificates by following this post's instructions, and installed the root authority into Trusted Authorities for the local machine on both the client and server. I then generated certificates for both client and server, put copies of the .cer file in places accessible to the client/server (loaded to get the X509Certificate objects) and installed the with private keys in the Personal stores for the respective machines. Now, everything works when the client and server are on the same machine. But when I generate a new cert and put it on a second machine, the client and server now fail to mutually authenticate. The connection gets set up, encrypted and signed, but IsMutuallyAuthenticated is false. How can I fix this? What am I doing wrong?

Edit: LocalCertificateSelectionCallback and the other callback tell me that the client finds one local certificate, which is mine, no remote certificates, and no acceptable issuers. My certificate is selected and returned from the local certificate selection. There are no SSL policy errors on the client end, and on the host end, I still get RemoteCertificateNotAvailable. Sniffing this transaction with Wireshark, I see a standard TCP handshake, followed by a few hundred bytes of gibberish which includes the name of the host cert, and then the FIN, ACK packets that mark the end of the transaction. So the client certificate indeed isn't being sent, even though it's selected by the LocalCertificateSelectionCallback routine. What might cause this? How can I fix it?

Community
  • 1
  • 1
Octavianus
  • 421
  • 4
  • 12

1 Answers1

0

There is a constructor of SSLStream which have RemoteCertificateVAlidationCallback parameter. It should help.

Nickolay Olshevsky
  • 13,706
  • 1
  • 34
  • 48
  • I've just finished with this: On the client end, there's no issue with the remote cert validation. On the server end, it complains that the remote certificate is not available. I can clearly see the certificate with private key in the personal key store for local machine on the client. – Octavianus Dec 02 '12 at 20:55
  • You can try to use LocalCertificateSelectionCallback on client's side to check if certificate is actually selected and sent – Nickolay Olshevsky Dec 02 '12 at 21:00
  • It finds one local certificate, which is mine, no remote certificates, and no acceptable issuers. My certificate is selected and returned. On the host end, I still get RemoteCertificateNotAvailable. – Octavianus Dec 09 '12 at 07:54