[sre-save] Handle ConstructorBuilder custom attribute constructors.
[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 && !ONLY_APPLETLS // ONLY_APPLETLS uses MonoTlsProviderFactory.Apple.cs instead
28
29 #if MONO_SECURITY_ALIAS
30 extern alias MonoSecurity;
31 using MSI = MonoSecurity::Mono.Security.Interface;
32 using MX = MonoSecurity::Mono.Security.X509;
33 #else
34 using MSI = Mono.Security.Interface;
35 using MX = Mono.Security.X509;
36 #endif
37 using System.Security.Cryptography.X509Certificates;
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                  */
63
64                 internal static MSI.MonoTlsProvider GetProviderInternal ()
65                 {
66                         lock (locker) {
67                                 InitializeInternal ();
68                                 return defaultProvider;
69                         }
70                 }
71
72                 internal static void InitializeInternal ()
73                 {
74                         lock (locker) {
75                                 if (initialized)
76                                         return;
77
78                                 MSI.MonoTlsProvider provider;
79                                 try {
80                                         provider = CreateDefaultProviderImpl ();
81                                 } catch (Exception ex) {
82                                         throw new NotSupportedException ("TLS Support not available.", ex);
83                                 }
84
85                                 if (provider == null)
86                                         throw new NotSupportedException ("TLS Support not available.");
87
88                                 defaultProvider = provider;
89                                 initialized = true;
90                         }
91                 }
92
93                 internal static void InitializeInternal (string provider) 
94                 {
95                         lock (locker) {
96                                 if (initialized)
97                                         throw new NotSupportedException ("TLS Subsystem already initialized.");
98
99                                 defaultProvider = LookupProvider (provider, true);
100                                 initialized = true;
101                         }
102                 }
103
104                 [MethodImpl (MethodImplOptions.InternalCall)]
105                 internal extern static bool IsBtlsSupported ();
106
107                 static object locker = new object ();
108                 static bool initialized;
109
110                 static MSI.MonoTlsProvider defaultProvider;
111
112                 #endregion
113
114                 static Dictionary<string,string> providerRegistration;
115
116                 static Type LookupProviderType (string name, bool throwOnError)
117                 {
118                         lock (locker) {
119                                 InitializeProviderRegistration ();
120                                 string typeName;
121                                 if (!providerRegistration.TryGetValue (name, out typeName)) {
122                                         if (throwOnError)
123                                                 throw new NotSupportedException (string.Format ("No such TLS Provider: `{0}'.", name));
124                                         return null;
125                                 }
126                                 var type = Type.GetType (typeName, false);
127                                 if (type == null && throwOnError)
128                                         throw new NotSupportedException (string.Format ("Could not find TLS Provider: `{0}'.", typeName));
129                                 return type;
130                         }
131                 }
132
133                 static MSI.MonoTlsProvider LookupProvider (string name, bool throwOnError)
134                 {
135                         var type = LookupProviderType (name, throwOnError);
136                         if (type == null)
137                                 return null;
138
139                         try {
140                                 return (MSI.MonoTlsProvider)Activator.CreateInstance (type, true);
141                         } catch (Exception ex) {
142                                 throw new NotSupportedException (string.Format ("Unable to instantiate TLS Provider `{0}'.", type), ex);
143                         }
144                 }
145
146                 static void InitializeProviderRegistration ()
147                 {
148                         lock (locker) {
149                                 if (providerRegistration != null)
150                                         return;
151                                 providerRegistration = new Dictionary<string,string> ();
152                                 providerRegistration.Add ("legacy", "Mono.Net.Security.LegacyTlsProvider");
153                         
154                                 if (Platform.IsMacOS)
155                                         providerRegistration.Add ("default", "Mono.AppleTls.AppleTlsProvider");
156                                 else
157                                         providerRegistration.Add ("default", "Mono.Net.Security.LegacyTlsProvider");
158
159                                 if (IsBtlsSupported ())
160                                         providerRegistration.Add ("btls", "Mono.Btls.MonoBtlsProvider");
161                         
162                                 providerRegistration.Add ("apple", "Mono.AppleTls.AppleTlsProvider");
163                                 
164                                 X509Helper2.Initialize ();
165                         }
166                 }
167
168 #if !MONODROID && !MONOTOUCH && !XAMMAC
169                 static MSI.MonoTlsProvider TryDynamicLoad ()
170                 {
171                         var variable = Environment.GetEnvironmentVariable ("MONO_TLS_PROVIDER");
172                         if (string.IsNullOrEmpty (variable))
173                                 variable = "default";
174
175                         return LookupProvider (variable, true);
176                 }
177
178                 static MSI.MonoTlsProvider CreateDefaultProviderImpl ()
179                 {
180                         var provider = TryDynamicLoad ();
181                         if (provider != null)
182                                 return provider;
183
184                         return new LegacyTlsProvider ();
185                 }
186 #endif
187
188                 #region Mono.Security visible API
189
190                 /*
191                  * "Public" section, intended to be consumed via reflection.
192                  * 
193                  * Mono.Security.dll provides a public wrapper around these.
194                  */
195
196                 internal static MSI.MonoTlsProvider GetProvider ()
197                 {
198                         var provider = GetProviderInternal ();
199                         if (provider == null)
200                                 throw new NotSupportedException ("No TLS Provider available.");
201
202                         return provider;
203                 }
204
205                 internal static bool IsProviderSupported (string name)
206                 {
207                         return LookupProvider (name, false) != null;
208                 }
209
210                 internal static MSI.MonoTlsProvider GetProvider (string name)
211                 {
212                         return LookupProvider (name, false);
213                 }
214
215                 internal static bool IsInitialized {
216                         get {
217                                 lock (locker) {
218                                         return initialized;
219                                 }
220                         }
221                 }
222
223                 internal static void Initialize ()
224                 {
225                         InitializeInternal ();
226                 }
227
228                 internal static void Initialize (string provider)
229                 {
230                         InitializeInternal (provider);
231                 }
232                 #endregion
233         }
234 }
235 #endif