2009-10-20 Gonzalo Paniagua Javier <gonzalo@novell.com>
authorGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Tue, 20 Oct 2009 15:25:31 +0000 (15:25 -0000)
committerGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Tue, 20 Oct 2009 15:25:31 +0000 (15:25 -0000)
* ServerContext.cs:
* SslServerStream.cs: add new parameter that forces sending the
CertificateRequest record. Make sure we raise the client certificate
validation event when it is requested or required.

svn path=/trunk/mcs/; revision=144459

mcs/class/Mono.Security/Mono.Security.Protocol.Tls/ChangeLog
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/ServerContext.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslServerStream.cs

index d0aaa78793d0e89b9a62a37a46b1a824b714aff9..2413ceebd8b025148228487d3217b6ad7b68b99e 100644 (file)
@@ -1,3 +1,10 @@
+2009-10-20 Gonzalo Paniagua Javier <gonzalo@novell.com>
+
+       * ServerContext.cs:
+       * SslServerStream.cs: add new parameter that forces sending the
+       CertificateRequest record. Make sure we raise the client certificate
+       validation event when it is requested or required.
+
 2009-07-02 Gonzalo Paniagua Javier <gonzalo@novell.com>
 
        * HttpsClientStream.cs: if there's only an ICertificatePolicy and no
index 818197414250cb186417668baaf46a133540c829..2652501669754c44f80062c015c6d856126cf948 100644 (file)
@@ -37,6 +37,7 @@ namespace Mono.Security.Protocol.Tls
                #region Fields
 
                private SslServerStream sslStream;
+               private bool request_client_certificate;
                private bool                    clientCertificateRequired;
 
                #endregion
@@ -53,6 +54,10 @@ namespace Mono.Security.Protocol.Tls
                        get { return this.clientCertificateRequired; }
                }
 
+               public bool RequestClientCertificate {
+                       get { return request_client_certificate; }
+               }
+
                #endregion
 
                #region Constructors
@@ -61,11 +66,13 @@ namespace Mono.Security.Protocol.Tls
                        SslServerStream                 stream,
                        SecurityProtocolType    securityProtocolType,
                        X509Certificate                 serverCertificate,
-                       bool                                    clientCertificateRequired)
+                       bool                                    clientCertificateRequired,
+                       bool                                    requestClientCertificate)
                        : base(securityProtocolType)
                {
                        this.sslStream                                  = stream;
                        this.clientCertificateRequired  = clientCertificateRequired;
+                       this.request_client_certificate = requestClientCertificate;
 
                        // Convert the System.Security cert to a Mono Cert
                        MonoX509.X509Certificate cert = new MonoX509.X509Certificate(serverCertificate.GetRawCertData());
index c453abbd95875230361f6f9a158cc5adb4963d41..750ab44a9403cf3eb29d2e6c6ffb15201e3946cc 100644 (file)
@@ -102,19 +102,41 @@ namespace Mono.Security.Protocol.Tls
                {
                }
 
+               public SslServerStream(
+                       Stream                  stream,
+                       X509Certificate serverCertificate,
+                       bool                    clientCertificateRequired,
+                       bool                    requestClientCertificate,
+                       bool                    ownsStream)
+                               : this (stream, serverCertificate, clientCertificateRequired, requestClientCertificate, ownsStream, SecurityProtocolType.Default)
+               {
+               }
+
                public SslServerStream(
                        Stream                                  stream,
                        X509Certificate                 serverCertificate,
                        bool                                    clientCertificateRequired,
                        bool                                    ownsStream,
                        SecurityProtocolType    securityProtocolType)
+                       : this (stream, serverCertificate, clientCertificateRequired, false, ownsStream, securityProtocolType)
+               {
+               }
+
+               public SslServerStream(
+                       Stream                                  stream,
+                       X509Certificate                 serverCertificate,
+                       bool                                    clientCertificateRequired,
+                       bool                                    requestClientCertificate,
+                       bool                                    ownsStream,
+                       SecurityProtocolType    securityProtocolType)
                        : base(stream, ownsStream)
                {
                        this.context = new ServerContext(
                                this,
                                securityProtocolType,
                                serverCertificate,
-                               clientCertificateRequired);
+                               clientCertificateRequired,
+                               requestClientCertificate);
 
                        this.protocol = new ServerRecordProtocol(innerStream, (ServerContext)this.context);
                }
@@ -216,7 +238,8 @@ namespace Mono.Security.Protocol.Tls
                        // If the negotiated cipher is a KeyEx cipher or
                        // the client certificate is required send the CertificateRequest message
                        if (this.context.Negotiating.Cipher.IsExportable ||
-                               ((ServerContext)this.context).ClientCertificateRequired)
+                               ((ServerContext)this.context).ClientCertificateRequired ||
+                               ((ServerContext)this.context).RequestClientCertificate)
                        {
                                this.protocol.SendRecord(HandshakeType.CertificateRequest);
                                certRequested = true;
@@ -239,16 +262,13 @@ namespace Mono.Security.Protocol.Tls
                                }
                        }
 
-                       if (certRequested && (this.context.ClientSettings.ClientCertificate == null))
-                       {
-                               // we asked for a certificate but didn't receive one
-                               // e.g. wget for SSL3
-                               if (!RaiseClientCertificateValidation(null, new int[0]))
-                               {
-                                       throw new TlsException(
-                                               AlertDescription.BadCertificate,
-                                               "No certificate received from client.");
-                               }
+                       if (certRequested) {
+                               X509Certificate client_cert = this.context.ClientSettings.ClientCertificate;
+                               if (client_cert == null && ((ServerContext)this.context).ClientCertificateRequired)
+                                       throw new TlsException (AlertDescription.BadCertificate, "No certificate received from client.");
+
+                               if (!RaiseClientCertificateValidation (client_cert, new int[0]))
+                                       throw new TlsException (AlertDescription.BadCertificate, "Client certificate not accepted.");
                        }
 
                        // Send ChangeCipherSpec and ServerFinished messages