Merge pull request #487 from mayerwin/patch-1
[mono.git] / mcs / class / Mono.Security / Mono.Security.Protocol.Tls / SslClientStream.cs
index 03d37d79ba2474339461c06d6b2a0acac31c26f8..0d4a4497200b008f15646c7bef888bce18d537a6 100644 (file)
@@ -41,6 +41,38 @@ namespace Mono.Security.Protocol.Tls
                X509Certificate certificate, 
                int[]                   certificateErrors);
 
+       public class ValidationResult {
+               bool trusted;
+               bool user_denied;
+               int error_code;
+
+               public ValidationResult (bool trusted, bool user_denied, int error_code)
+               {
+                       this.trusted = trusted;
+                       this.user_denied = user_denied;
+                       this.error_code = error_code;
+               }
+
+               public bool Trusted {
+                       get { return trusted; }
+               }
+
+               public bool UserDenied {
+                       get { return user_denied; }
+               }
+
+               public int ErrorCode {
+                       get { return error_code; }
+               }
+       }
+
+#if MOONLIGHT
+       internal
+#else
+       public
+#endif
+       delegate ValidationResult CertificateValidationCallback2 (Mono.Security.X509.X509CertificateCollection collection);
+
        public delegate X509Certificate CertificateSelectionCallback(
                X509CertificateCollection       clientCertificates, 
                X509Certificate                         serverCertificate, 
@@ -105,6 +137,12 @@ namespace Mono.Security.Protocol.Tls
                
                #endregion
 
+#if MOONLIGHT
+               internal event CertificateValidationCallback2 ServerCertValidation2;
+#else
+               public event CertificateValidationCallback2 ServerCertValidation2;
+#endif
+
                #region Constructors
                
                public SslClientStream(
@@ -192,6 +230,7 @@ namespace Mono.Security.Protocol.Tls
                                this.ServerCertValidation = null;
                                this.ClientCertSelection = null;
                                this.PrivateKeySelection = null;
+                               this.ServerCertValidation2 = null;
                        }
                }
 
@@ -252,10 +291,10 @@ namespace Mono.Security.Protocol.Tls
                        }
                }
 
-               private void SafeReceiveRecord (Stream s)
+               private void SafeReceiveRecord (Stream s, bool ignoreEmpty = false)
                {
                        byte[] record = this.protocol.ReceiveRecord (s);
-                       if ((record == null) || (record.Length == 0)) {
+                       if (!ignoreEmpty && ((record == null) || (record.Length == 0))) {
                                throw new TlsException (
                                        AlertDescription.HandshakeFailiure,
                                        "The server stopped the handshake.");
@@ -269,8 +308,8 @@ namespace Mono.Security.Protocol.Tls
                        // Read server response
                        while (this.context.LastHandshakeMsg != HandshakeType.ServerHelloDone) 
                        {
-                               // Read next record
-                               SafeReceiveRecord (this.innerStream);
+                               // Read next record (skip empty, e.g. warnings alerts)
+                               SafeReceiveRecord (this.innerStream, true);
 
                                // special case for abbreviated handshake where no ServerHelloDone is sent from the server
                                if (this.context.AbbreviatedHandshake && (this.context.LastHandshakeMsg == HandshakeType.ServerHello))
@@ -372,7 +411,19 @@ namespace Mono.Security.Protocol.Tls
 
                        return null;
                }
-               
+
+               internal override bool HaveRemoteValidation2Callback {
+                       get { return ServerCertValidation2 != null; }
+               }
+
+               internal override ValidationResult OnRemoteCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection)
+               {
+                       CertificateValidationCallback2 cb = ServerCertValidation2;
+                       if (cb != null)
+                               return cb (collection);
+                       return null;
+               }
+
                internal override bool OnRemoteCertificateValidation(X509Certificate certificate, int[] errors)
                {
                        if (this.ServerCertValidation != null)
@@ -390,6 +441,11 @@ namespace Mono.Security.Protocol.Tls
                        return base.RaiseRemoteCertificateValidation(certificate, certificateErrors);
                }
 
+               internal virtual ValidationResult RaiseServerCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection)
+               {
+                       return base.RaiseRemoteCertificateValidation2 (collection);
+               }
+
                internal X509Certificate RaiseClientCertificateSelection(
                        X509CertificateCollection       clientCertificates, 
                        X509Certificate                         serverCertificate,