Merge pull request #2802 from BrzVlad/feature-evacuation-opt2
[mono.git] / mcs / class / System / Mono.Net.Security / MonoTlsProviderFactory.cs
index c35ffe1af5148d0e09480f6f3305c6516d800cee..c4b17abcd0ee93d2c9f98af837dc3064598fd773 100644 (file)
@@ -33,10 +33,16 @@ using MX = MonoSecurity::Mono.Security.X509;
 using MSI = Mono.Security.Interface;
 using MX = Mono.Security.X509;
 #endif
+using System.Security.Cryptography.X509Certificates;
 #endif
 
 using System;
 using System.Net;
+using System.Collections.Generic;
+
+#if !MOBILE
+using System.Reflection;
+#endif
 
 namespace Mono.Net.Security
 {
@@ -44,7 +50,7 @@ namespace Mono.Net.Security
         * Keep in sync with Mono.Security/Mono.Security.Interface/MonoTlsProvider.cs.
         *
         */
-       static class MonoTlsProviderFactory
+       static partial class MonoTlsProviderFactory
        {
                #region Internal API
 
@@ -63,7 +69,7 @@ namespace Mono.Net.Security
                                        return currentProvider;
 
                                try {
-                                       defaultProvider = CreateDefaultProvider ();
+                                       defaultProvider = GetDefaultProviderInternal ();
                                } catch (Exception ex) {
                                        throw new NotSupportedException ("TLS Support not available.", ex);
                                }
@@ -95,6 +101,7 @@ namespace Mono.Net.Security
                        }
                }
 
+#if MONO_FEATURE_NEW_SYSTEM_SOURCE || (!MONOTOUCH && !XAMMAC)
                static IMonoTlsProvider CreateDefaultProvider ()
                {
 #if SECURITY_DEP
@@ -111,12 +118,13 @@ namespace Mono.Net.Security
                        var userProvider = MSI.MonoTlsProviderFactory.GetProvider ();
                        return new Private.MonoTlsProviderWrapper (userProvider);
 #else
-                       return new Private.MonoDefaultTlsProvider ();
+                       return CreateDefaultProviderImpl ();
 #endif
 #else
                        return null;
 #endif
                }
+#endif
 
                static object locker = new object ();
                static IMonoTlsProvider defaultProvider;
@@ -126,6 +134,78 @@ namespace Mono.Net.Security
 
 #if SECURITY_DEP && !MONO_FEATURE_NEW_SYSTEM_SOURCE
 
+               static Dictionary<string,string> providerRegistration;
+
+               static Type LookupProviderType (string name, bool throwOnError)
+               {
+                       lock (locker) {
+                               InitializeProviderRegistration ();
+                               string typeName;
+                               if (!providerRegistration.TryGetValue (name, out typeName)) {
+                                       if (throwOnError)
+                                               throw new NotSupportedException (string.Format ("No such TLS Provider: `{0}'.", name));
+                                       return null;
+                               }
+                               var type = Type.GetType (typeName, false);
+                               if (type == null && throwOnError)
+                                       throw new NotSupportedException (string.Format ("Could not find TLS Provider: `{0}'.", typeName));
+                               return type;
+                       }
+               }
+
+               static MSI.MonoTlsProvider LookupProvider (string name, bool throwOnError)
+               {
+                       var type = LookupProviderType (name, throwOnError);
+                       if (type == null)
+                               return null;
+
+                       try {
+                               return (MSI.MonoTlsProvider)Activator.CreateInstance (type);
+                       } catch (Exception ex) {
+                               throw new NotSupportedException (string.Format ("Unable to instantiate TLS Provider `{0}'.", type), ex);
+                       }
+               }
+
+               static void InitializeProviderRegistration ()
+               {
+                       lock (locker) {
+                               if (providerRegistration != null)
+                                       return;
+                               providerRegistration = new Dictionary<string,string> ();
+                               providerRegistration.Add ("newtls", "Mono.Security.Providers.NewTls.NewTlsProvider, Mono.Security.Providers.NewTls, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756");
+                               providerRegistration.Add ("oldtls", "Mono.Security.Providers.OldTls.OldTlsProvider, Mono.Security.Providers.OldTls, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756");
+                               providerRegistration.Add ("boringtls", "Xamarin.BoringTls.BoringTlsProvider, Xamarin.BoringTls, Version=4.0.0.0, Culture=neutral, PublicKeyToken=672c06b0b8f05406");
+                               X509Helper2.Initialize ();
+                       }
+               }
+
+#if !MOBILE
+               static IMonoTlsProvider TryDynamicLoad ()
+               {
+                       var variable = Environment.GetEnvironmentVariable ("MONO_TLS_PROVIDER");
+                       if (variable == null)
+                               return null;
+
+                       if (string.Equals (variable, "default", StringComparison.OrdinalIgnoreCase))
+                               return null;
+
+                       var provider = LookupProvider (variable, true);
+
+                       return new Private.MonoTlsProviderWrapper (provider);
+               }
+#endif
+
+               static IMonoTlsProvider CreateDefaultProviderImpl ()
+               {
+#if !MOBILE
+                       var provider = TryDynamicLoad ();
+                       if (provider != null)
+                               return provider;
+#endif
+
+                       return new Private.MonoDefaultTlsProvider ();
+               }
+
                #region Mono.Security visible API
 
                /*
@@ -152,6 +232,11 @@ namespace Mono.Net.Security
                        return provider.Provider;
                }
 
+               internal static MSI.MonoTlsProvider GetProvider (string name)
+               {
+                       return LookupProvider (name, false);
+               }
+
                internal static bool HasProvider {
                        get {
                                lock (locker) {
@@ -160,9 +245,10 @@ namespace Mono.Net.Security
                        }
                }
 
-               internal static void InstallProvider (MSI.MonoTlsProvider provider)
+               internal static void SetDefaultProvider (string name)
                {
                        lock (locker) {
+                               var provider = LookupProvider (name, true);
                                currentProvider = new Private.MonoTlsProviderWrapper (provider);
                        }
                }
@@ -174,6 +260,14 @@ namespace Mono.Net.Security
                                return new HttpWebRequest (requestUri, internalProvider, settings);
                        }
                }
+
+               internal static HttpListener CreateHttpListener (X509Certificate certificate, MSI.MonoTlsProvider provider, MSI.MonoTlsSettings settings)
+               {
+                       lock (locker) {
+                               var internalProvider = provider != null ? new Private.MonoTlsProviderWrapper (provider) : null;
+                               return new HttpListener (certificate, internalProvider, settings);
+                       }
+               }
                #endregion
 
 #endif