Merge pull request #4222 from alexanderkyte/fix_mismatch_com_disabled
[mono.git] / mcs / class / System / Mono.Net.Security / MonoTlsProviderFactory.cs
1 //
2 // MonoTlsProviderFactory.cs
3 //
4 // Author:
5 //       Martin Baulig <martin.baulig@xamarin.com>
6 //
7 // Copyright (c) 2015 Xamarin, Inc.
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
15 //
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
18 //
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 // THE SOFTWARE.
26
27 #if SECURITY_DEP
28 #if MONO_SECURITY_ALIAS
29 extern alias MonoSecurity;
30 using MSI = MonoSecurity::Mono.Security.Interface;
31 using MX = MonoSecurity::Mono.Security.X509;
32 #else
33 using MSI = Mono.Security.Interface;
34 using MX = Mono.Security.X509;
35 #endif
36 using System.Security.Cryptography.X509Certificates;
37 #endif
38
39 using System;
40 using System.Net;
41 using System.Collections.Generic;
42 using System.Runtime.CompilerServices;
43
44 #if !MOBILE
45 using System.Reflection;
46 #endif
47
48 namespace Mono.Net.Security
49 {
50         /*
51          * Keep in sync with Mono.Security/Mono.Security.Interface/MonoTlsProvider.cs.
52          *
53          */
54         static partial class MonoTlsProviderFactory
55         {
56                 #region Internal API
57
58                 /*
59                  * APIs in this section are for consumption within System.dll only - do not access via
60                  * reflection or from friend assemblies.
61                  * 
62                  * @IMonoTlsProvider is defined as empty interface outside 'SECURITY_DEP', so we don't need
63                  * this conditional here.
64                  */
65
66                 internal static IMonoTlsProvider GetProviderInternal ()
67                 {
68                         #if SECURITY_DEP
69                         lock (locker) {
70                                 InitializeInternal ();
71                                 return defaultProvider;
72                         }
73                         #else
74                         throw new NotSupportedException ("TLS Support not available.");
75                         #endif
76                 }
77
78 #if SECURITY_DEP
79                 internal static void InitializeInternal ()
80                 {
81                         lock (locker) {
82                                 if (initialized)
83                                         return;
84
85                                 MSI.MonoTlsProvider provider;
86                                 try {
87                                         provider = CreateDefaultProviderImpl ();
88                                 } catch (Exception ex) {
89                                         throw new NotSupportedException ("TLS Support not available.", ex);
90                                 }
91
92                                 if (provider == null)
93                                         throw new NotSupportedException ("TLS Support not available.");
94
95                                 defaultProvider = new Private.MonoTlsProviderWrapper (provider);
96                                 initialized = true;
97                         }
98                 }
99
100                 internal static void InitializeInternal (string provider) 
101                 {
102                         lock (locker) {
103                                 if (initialized)
104                                         throw new NotSupportedException ("TLS Subsystem already initialized.");
105
106                                 var msiProvider = LookupProvider (provider, true);
107                                 defaultProvider = new Private.MonoTlsProviderWrapper (msiProvider);
108                                 initialized = true;
109                         }
110                 }
111
112                 [MethodImpl (MethodImplOptions.InternalCall)]
113                 internal extern static bool IsBtlsSupported ();
114
115                 static object locker = new object ();
116                 static bool initialized;
117
118                 static IMonoTlsProvider defaultProvider;
119 #endif
120                 #endregion
121
122 #if SECURITY_DEP
123
124                 static Dictionary<string,string> providerRegistration;
125
126                 static Type LookupProviderType (string name, bool throwOnError)
127                 {
128                         lock (locker) {
129                                 InitializeProviderRegistration ();
130                                 string typeName;
131                                 if (!providerRegistration.TryGetValue (name, out typeName)) {
132                                         if (throwOnError)
133                                                 throw new NotSupportedException (string.Format ("No such TLS Provider: `{0}'.", name));
134                                         return null;
135                                 }
136                                 var type = Type.GetType (typeName, false);
137                                 if (type == null && throwOnError)
138                                         throw new NotSupportedException (string.Format ("Could not find TLS Provider: `{0}'.", typeName));
139                                 return type;
140                         }
141                 }
142
143                 static MSI.MonoTlsProvider LookupProvider (string name, bool throwOnError)
144                 {
145                         var type = LookupProviderType (name, throwOnError);
146                         if (type == null)
147                                 return null;
148
149                         try {
150                                 return (MSI.MonoTlsProvider)Activator.CreateInstance (type, true);
151                         } catch (Exception ex) {
152                                 throw new NotSupportedException (string.Format ("Unable to instantiate TLS Provider `{0}'.", type), ex);
153                         }
154                 }
155
156                 static void InitializeProviderRegistration ()
157                 {
158                         lock (locker) {
159                                 if (providerRegistration != null)
160                                         return;
161                                 providerRegistration = new Dictionary<string,string> ();
162                                 providerRegistration.Add ("legacy", "Mono.Net.Security.LegacyTlsProvider");
163                                 providerRegistration.Add ("default", "Mono.Net.Security.LegacyTlsProvider");
164                                 if (IsBtlsSupported ())
165                                         providerRegistration.Add ("btls", "Mono.Btls.MonoBtlsProvider");
166                                 X509Helper2.Initialize ();
167                         }
168                 }
169
170 #if !MONODROID && !MONOTOUCH && !XAMMAC
171                 static MSI.MonoTlsProvider TryDynamicLoad ()
172                 {
173                         var variable = Environment.GetEnvironmentVariable ("MONO_TLS_PROVIDER");
174                         if (string.IsNullOrEmpty (variable))
175                                 variable = "default";
176
177                         return LookupProvider (variable, true);
178                 }
179
180                 static MSI.MonoTlsProvider CreateDefaultProviderImpl ()
181                 {
182                         var provider = TryDynamicLoad ();
183                         if (provider != null)
184                                 return provider;
185
186                         return new LegacyTlsProvider ();
187                 }
188 #endif
189
190                 #region Mono.Security visible API
191
192                 /*
193                  * "Public" section, intended to be consumed via reflection.
194                  * 
195                  * Mono.Security.dll provides a public wrapper around these.
196                  */
197
198                 internal static MSI.MonoTlsProvider GetProvider ()
199                 {
200                         var provider = GetProviderInternal ();
201                         if (provider == null)
202                                 throw new NotSupportedException ("No TLS Provider available.");
203
204                         return provider.Provider;
205                 }
206
207                 internal static bool IsProviderSupported (string name)
208                 {
209                         return LookupProvider (name, false) != null;
210                 }
211
212                 internal static MSI.MonoTlsProvider GetProvider (string name)
213                 {
214                         return LookupProvider (name, false);
215                 }
216
217                 internal static bool IsInitialized {
218                         get {
219                                 lock (locker) {
220                                         return initialized;
221                                 }
222                         }
223                 }
224
225                 internal static void Initialize ()
226                 {
227                         #if SECURITY_DEP
228                         InitializeInternal ();
229                         #else
230                         throw new NotSupportedException ("TLS Support not available.");
231                         #endif
232                 }
233
234                 internal static void Initialize (string provider)
235                 {
236                         #if SECURITY_DEP
237                         InitializeInternal (provider);
238                         #else
239                         throw new NotSupportedException ("TLS Support not available.");
240                         #endif
241                 }
242
243                 internal static HttpWebRequest CreateHttpsRequest (Uri requestUri, MSI.MonoTlsProvider provider, MSI.MonoTlsSettings settings)
244                 {
245                         lock (locker) {
246                                 var internalProvider = provider != null ? new Private.MonoTlsProviderWrapper (provider) : null;
247                                 return new HttpWebRequest (requestUri, internalProvider, settings);
248                         }
249                 }
250
251                 internal static HttpListener CreateHttpListener (X509Certificate certificate, MSI.MonoTlsProvider provider, MSI.MonoTlsSettings settings)
252                 {
253                         lock (locker) {
254                                 var internalProvider = provider != null ? new Private.MonoTlsProviderWrapper (provider) : null;
255                                 return new HttpListener (certificate, internalProvider, settings);
256                         }
257                 }
258                 #endregion
259
260 #endif
261
262         }
263 }
264