Convert blocking operations in HttpWebRequest and SslClientStream to non-blocking...
[mono.git] / mcs / class / Mono.Security / Mono.Security.Protocol.Tls / SslServerStream.cs
index c453abbd95875230361f6f9a158cc5adb4963d41..b0d8bba6ffc99cc8b92675f31d8318bc32d43ef7 100644 (file)
@@ -34,7 +34,12 @@ using Mono.Security.Protocol.Tls.Handshake;
 
 namespace Mono.Security.Protocol.Tls
 {
-       public class SslServerStream : SslStreamBase
+#if INSIDE_SYSTEM
+       internal
+#else
+       public
+#endif
+       class SslServerStream : SslStreamBase
        {
                #region Internal Events
                
@@ -76,6 +81,7 @@ namespace Mono.Security.Protocol.Tls
 
                #endregion
 
+               public event CertificateValidationCallback2 ClientCertValidation2;
                #region Constructors
 
                public SslServerStream(
@@ -102,19 +108,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);
                }
@@ -168,7 +196,7 @@ namespace Mono.Security.Protocol.Tls
                                        Fig. 1 - Message flow for a full handshake              
                */
 
-               internal override IAsyncResult OnBeginNegotiateHandshake(AsyncCallback callback, object state)
+               internal override IAsyncResult BeginNegotiateHandshake(AsyncCallback callback, object state)
                {
                        // Reset the context if needed
                        if (this.context.HandshakeState != HandshakeState.None)
@@ -187,7 +215,7 @@ namespace Mono.Security.Protocol.Tls
 
                }
 
-               internal override void OnNegotiateHandshakeCallback(IAsyncResult asyncResult)
+               internal override void EndNegotiateHandshake(IAsyncResult asyncResult)
                {
                        // Receive Client Hello message and ignore it
                        this.protocol.EndReceiveRecord(asyncResult);
@@ -211,15 +239,13 @@ namespace Mono.Security.Protocol.Tls
                                this.protocol.SendRecord(HandshakeType.ServerKeyExchange);
                        }
 
-                       bool certRequested = false;
-
                        // 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;
                        }
 
                        // Send ServerHelloDone message
@@ -239,18 +265,6 @@ 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.");
-                               }
-                       }
-
                        // Send ChangeCipherSpec and ServerFinished messages
                        this.protocol.SendChangeCipherSpec();
                        this.protocol.SendRecord (HandshakeType.Finished);
@@ -284,6 +298,18 @@ namespace Mono.Security.Protocol.Tls
                        return (errors != null && errors.Length == 0);
                }
 
+               internal override bool HaveRemoteValidation2Callback {
+                       get { return ClientCertValidation2 != null; }
+               }
+
+               internal override ValidationResult OnRemoteCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection)
+               {
+                       CertificateValidationCallback2 cb = ClientCertValidation2;
+                       if (cb != null)
+                               return cb (collection);
+                       return null;
+               }
+
                internal bool RaiseClientCertificateValidation(
                        X509Certificate certificate, 
                        int[]                   certificateErrors)