[System]: Correctly implement close and shutdown in SslStream. (#4969)
[mono.git] / mcs / class / System / Mono.Net.Security / LegacySslStream.cs
index c5eff6948511472d57fcc9bd43cec37dbeb9597f..e4032496da167517db3ff54076a60e184a6ba167 100644 (file)
@@ -34,9 +34,6 @@
 
 #if SECURITY_DEP
 
-#if MONO_X509_ALIAS
-extern alias PrebuiltSystem;
-#endif
 #if MONO_SECURITY_ALIAS
 extern alias MonoSecurity;
 #endif
@@ -56,9 +53,6 @@ using MonoSecurityProtocolType = Mono.Security.Protocol.Tls.SecurityProtocolType
 using Mono.Security.Protocol.Tls;
 using Mono.Security.Interface;
 #endif
-#if MONO_X509_ALIAS
-using X509CertificateCollection = PrebuiltSystem::System.Security.Cryptography.X509Certificates.X509CertificateCollection;
-#endif
 
 using CipherAlgorithmType = System.Security.Authentication.CipherAlgorithmType;
 using HashAlgorithmType = System.Security.Authentication.HashAlgorithmType;
@@ -75,36 +69,29 @@ using System.Security.Cryptography;
 
 using System.Threading.Tasks;
 
-namespace Mono.Net.Security 
+namespace Mono.Net.Security.Private
 {
+       /*
+        * Strictly private - do not use outside the Mono.Net.Security directory.
+        */
        [MonoTODO ("Non-X509Certificate2 certificate is not supported")]
        internal class LegacySslStream : AuthenticatedStream, IMonoSslStream
        {
                #region Fields
 
                SslStreamBase ssl_stream;
-               MonoTlsSettings settings;
                ICertificateValidator certificateValidator;
 
                #endregion // Fields
 
                #region Constructors
 
-               public LegacySslStream (Stream innerStream)
-                       : this (innerStream, false)
-               {
-               }
-
-               public LegacySslStream (Stream innerStream, bool leaveInnerStreamOpen)
+               public LegacySslStream (Stream innerStream, bool leaveInnerStreamOpen, SslStream owner, MonoTlsProvider provider, MonoTlsSettings settings)
                        : base (innerStream, leaveInnerStreamOpen)
                {
-               }
-
-               public LegacySslStream (Stream innerStream, bool leaveInnerStreamOpen, MonoTlsSettings settings)
-                       : base (innerStream, leaveInnerStreamOpen)
-               {
-                       this.settings = settings;
-                       this.certificateValidator = settings.CertificateValidator;
+                       SslStream = owner;
+                       Provider = provider;
+                       certificateValidator = ChainValidationHelper.GetInternalValidator (provider, settings);
                }
                #endregion // Constructors
 
@@ -329,10 +316,14 @@ namespace Mono.Net.Security
 */
                X509Certificate OnCertificateSelection (X509CertificateCollection clientCerts, X509Certificate serverCert, string targetHost, X509CertificateCollection serverRequestedCerts)
                {
+#pragma warning disable 618
                        string [] acceptableIssuers = new string [serverRequestedCerts != null ? serverRequestedCerts.Count : 0];
                        for (int i = 0; i < acceptableIssuers.Length; i++)
                                acceptableIssuers [i] = serverRequestedCerts [i].GetIssuerName ();
-                       return certificateValidator.SelectClientCertificate (targetHost, clientCerts, serverCert, acceptableIssuers);
+                       X509Certificate clientCertificate;
+                       certificateValidator.SelectClientCertificate (targetHost, clientCerts, serverCert, acceptableIssuers, out clientCertificate);
+                       return clientCertificate;
+#pragma warning restore 618
                }
 
                public virtual IAsyncResult BeginAuthenticateAsClient (string targetHost, AsyncCallback asyncCallback, object asyncState)
@@ -366,15 +357,19 @@ namespace Mono.Net.Security
                                return null;
                        };
 
-#if MARTIN_FIXME
                        // Even if validation_callback is null this allows us to verify requests where the user
                        // does not provide a verification callback but attempts to authenticate with the website
                        // as a client (see https://bugzilla.xamarin.com/show_bug.cgi?id=18962 for an example)
-                       s.ServerCertValidation2 += (certs) => ((ChainValidationHelper)certificateValidator).ValidateChain (targetHost, certs);
+                       s.ServerCertValidation2 += (mcerts) => {
+                               X509CertificateCollection certs = null;
+                               if (mcerts != null) {
+                                       certs = new X509CertificateCollection ();
+                                       for (int i = 0; i < mcerts.Count; i++)
+                                               certs.Add (new X509Certificate2 (mcerts [i].RawData));
+                               }
+                               return ((ChainValidationHelper)certificateValidator).ValidateCertificate (targetHost, false, certs);
+                       };
                        s.ClientCertSelectionDelegate = OnCertificateSelection;
-#else
-                       throw new NotImplementedException ();
-#endif
 
                        ssl_stream = s;
 
@@ -398,7 +393,7 @@ namespace Mono.Net.Security
                        if (IsAuthenticated)
                                throw new InvalidOperationException ("This SslStream is already authenticated");
 
-                       SslServerStream s = new SslServerStream (InnerStream, serverCertificate, clientCertificateRequired, !LeaveInnerStreamOpen, GetMonoSslProtocol (enabledSslProtocols));
+                       SslServerStream s = new SslServerStream (InnerStream, serverCertificate, false, clientCertificateRequired, !LeaveInnerStreamOpen, GetMonoSslProtocol (enabledSslProtocols));
                        s.CheckCertRevocationStatus = checkCertificateRevocation;
                        // Due to the Mono.Security internal, it cannot reuse
                        // the delegated argument, as Mono.Security creates 
@@ -411,14 +406,10 @@ namespace Mono.Net.Security
                                return cert2 != null ? cert2.PrivateKey : null;
                        };
 
-#if MARTIN_FIXME
                        s.ClientCertValidationDelegate = delegate (X509Certificate cert, int[] certErrors) {
                                var errors = certErrors.Length > 0 ? MonoSslPolicyErrors.RemoteCertificateChainErrors : MonoSslPolicyErrors.None;
                                return ((ChainValidationHelper)certificateValidator).ValidateClientCertificate (cert, errors);
                        };
-#else
-                       throw new NotImplementedException ();
-#endif
 
                        ssl_stream = s;
 
@@ -584,6 +575,11 @@ namespace Mono.Net.Security
 
                #region IMonoSslStream
 
+               Task IMonoSslStream.ShutdownAsync ()
+               {
+                       return Task.CompletedTask;
+               }
+
                AuthenticatedStream IMonoSslStream.AuthenticatedStream {
                        get { return this; }
                }
@@ -592,6 +588,19 @@ namespace Mono.Net.Security
                        get { throw new NotSupportedException (); }
                }
 
+               public SslStream SslStream {
+                       get;
+               }
+
+               public MonoTlsProvider Provider {
+                       get;
+               }
+
+               public MonoTlsConnectionInfo GetConnectionInfo ()
+               {
+                       return null;
+               }
+
                #endregion
        }
 }