Merge pull request #3442 from lateralusX/jlorenss/win-atexit-commands
[mono.git] / mcs / class / System / Mono.Btls / MonoBtlsSslCtx.cs
1 //
2 // MonoBtlsSslCtx.cs
3 //
4 // Author:
5 //       Martin Baulig <martin.baulig@xamarin.com>
6 //
7 // Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
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 #if SECURITY_DEP
27 using System;
28 using System.Runtime.CompilerServices;
29 using System.Runtime.InteropServices;
30
31 #if MONOTOUCH
32 using MonoTouch;
33 #endif
34
35 namespace Mono.Btls
36 {
37         class MonoBtlsSslCtx : MonoBtlsObject
38         {
39                 internal class BoringSslCtxHandle : MonoBtlsHandle
40                 {
41                         public BoringSslCtxHandle (IntPtr handle)
42                                 : base (handle, true)
43                         {
44                         }
45
46                         protected override bool ReleaseHandle ()
47                         {
48                                 mono_btls_ssl_ctx_free (handle);
49                                 return true;
50                         }
51                 }
52
53                 new internal BoringSslCtxHandle Handle {
54                         get { return (BoringSslCtxHandle)base.Handle; }
55                 }
56
57                 [DllImport (BTLS_DYLIB)]
58                 extern static IntPtr mono_btls_ssl_ctx_new ();
59
60                 [DllImport (BTLS_DYLIB)]
61                 extern static int mono_btls_ssl_ctx_free (IntPtr handle);
62
63                 [DllImport (BTLS_DYLIB)]
64                 extern static IntPtr mono_btls_ssl_ctx_up_ref (IntPtr handle);
65
66                 [DllImport (BTLS_DYLIB)]
67                 extern static void mono_btls_ssl_ctx_initialize (IntPtr handle, IntPtr instance);
68
69                 [DllImport (BTLS_DYLIB)]
70                 extern static void mono_btls_ssl_ctx_set_debug_bio (IntPtr handle, IntPtr bio);
71
72                 [DllImport (BTLS_DYLIB)]
73                 extern static void mono_btls_ssl_ctx_set_cert_verify_callback (IntPtr handle, IntPtr func, int cert_required);
74
75                 [DllImport (BTLS_DYLIB)]
76                 extern static void mono_btls_ssl_ctx_set_cert_select_callback (IntPtr handle, IntPtr func);
77
78                 [DllImport (BTLS_DYLIB)]
79                 extern static void mono_btls_ssl_ctx_set_min_version (IntPtr handle, int version);
80
81                 [DllImport (BTLS_DYLIB)]
82                 extern static void mono_btls_ssl_ctx_set_max_version (IntPtr handle, int version);
83
84                 [DllImport (BTLS_DYLIB)]
85                 extern static int mono_btls_ssl_ctx_is_cipher_supported (IntPtr handle, short value);
86
87                 [DllImport (BTLS_DYLIB)]
88                 extern static int mono_btls_ssl_ctx_set_ciphers (IntPtr handle, int count, IntPtr data, int allow_unsupported);
89
90                 [DllImport (BTLS_DYLIB)]
91                 extern static int mono_btls_ssl_ctx_set_verify_param (IntPtr handle, IntPtr param);
92
93                 delegate int NativeVerifyFunc (IntPtr instance, int preverify_ok, IntPtr ctx);
94                 delegate int NativeSelectFunc (IntPtr instance);
95
96                 NativeVerifyFunc verifyFunc;
97                 NativeSelectFunc selectFunc;
98                 IntPtr verifyFuncPtr;
99                 IntPtr selectFuncPtr;
100                 MonoBtlsVerifyCallback verifyCallback;
101                 MonoBtlsSelectCallback selectCallback;
102                 MonoBtlsX509Store store;
103                 GCHandle instance;
104                 IntPtr instancePtr;
105
106                 public MonoBtlsSslCtx ()
107                         : this (new BoringSslCtxHandle (mono_btls_ssl_ctx_new ()))
108                 {
109                 }
110
111                 internal MonoBtlsSslCtx (BoringSslCtxHandle handle)
112                         : base (handle)
113                 {
114                         instance = GCHandle.Alloc (this);
115                         instancePtr = GCHandle.ToIntPtr (instance);
116                         mono_btls_ssl_ctx_initialize (
117                                 handle.DangerousGetHandle (), instancePtr);
118
119                         verifyFunc = NativeVerifyCallback;
120                         selectFunc = NativeSelectCallback;
121                         verifyFuncPtr = Marshal.GetFunctionPointerForDelegate (verifyFunc);
122                         selectFuncPtr = Marshal.GetFunctionPointerForDelegate (selectFunc);
123
124                         store = new MonoBtlsX509Store (Handle);
125                 }
126
127                 internal MonoBtlsSslCtx Copy ()
128                 {
129                         var copy = mono_btls_ssl_ctx_up_ref (Handle.DangerousGetHandle ());
130                         return new MonoBtlsSslCtx (new BoringSslCtxHandle (copy));
131                 }
132
133                 public MonoBtlsX509Store CertificateStore {
134                         get { return store; }
135                 }
136
137                 int VerifyCallback (bool preverify_ok, MonoBtlsX509StoreCtx ctx)
138                 {
139                         if (verifyCallback != null)
140                                 return verifyCallback (ctx);
141                         return 0;
142                 }
143
144 #if MONOTOUCH
145                 [MonoPInvokeCallback (typeof (NativeVerifyFunc))]
146 #endif
147                 static int NativeVerifyCallback (IntPtr instance, int preverify_ok, IntPtr store_ctx)
148                 {
149                         var c = (MonoBtlsSslCtx)GCHandle.FromIntPtr (instance).Target;
150                         using (var ctx = new MonoBtlsX509StoreCtx (preverify_ok, store_ctx)) {
151                                 try {
152                                         return c.VerifyCallback (preverify_ok != 0, ctx);
153                                 } catch (Exception ex) {
154                                         c.SetException (ex);
155                                 }
156                         }
157                         return 0;
158                 }
159
160                 int SelectCallback ()
161                 {
162                         if (selectCallback != null)
163                                 return selectCallback ();
164                         return 1;
165                 }
166
167 #if MONOTOUCH
168                 [MonoPInvokeCallback (typeof (NativeSelectFunc))]
169 #endif
170                 static int NativeSelectCallback (IntPtr instance)
171                 {
172                         var c = (MonoBtlsSslCtx)GCHandle.FromIntPtr (instance).Target;
173                         try {
174                                 return c.SelectCallback ();
175                         } catch (Exception ex) {
176                                 c.SetException (ex);
177                                 return 0;
178                         }
179                 }
180
181                 public void SetDebugBio (MonoBtlsBio bio)
182                 {
183                         CheckThrow ();
184                         mono_btls_ssl_ctx_set_debug_bio (Handle.DangerousGetHandle (), bio.Handle.DangerousGetHandle ());
185                 }
186
187                 public void SetVerifyCallback (MonoBtlsVerifyCallback callback, bool client_cert_required)
188                 {
189                         CheckThrow ();
190
191                         verifyCallback = callback;
192                         mono_btls_ssl_ctx_set_cert_verify_callback (
193                                 Handle.DangerousGetHandle (), verifyFuncPtr,
194                                 client_cert_required ? 1 : 0);
195                 }
196
197                 public void SetSelectCallback (MonoBtlsSelectCallback callback)
198                 {
199                         CheckThrow ();
200
201                         selectCallback = callback;
202                         mono_btls_ssl_ctx_set_cert_select_callback (
203                                 Handle.DangerousGetHandle (), selectFuncPtr);
204                 }
205
206                 public void SetMinVersion (int version)
207                 {
208                         CheckThrow ();
209                         mono_btls_ssl_ctx_set_min_version (Handle.DangerousGetHandle (), version);
210                 }
211
212                 public void SetMaxVersion (int version)
213                 {
214                         CheckThrow ();
215                         mono_btls_ssl_ctx_set_max_version (Handle.DangerousGetHandle (), version);
216                 }
217
218                 public bool IsCipherSupported (short value)
219                 {
220                         CheckThrow ();
221                         return mono_btls_ssl_ctx_is_cipher_supported (Handle.DangerousGetHandle (), value) != 0;
222                 }
223
224                 public void SetCiphers (short[] ciphers, bool allow_unsupported)
225                 {
226                         CheckThrow ();
227                         var data = Marshal.AllocHGlobal (ciphers.Length * 2);
228                         try {
229                                 Marshal.Copy (ciphers, 0, data, ciphers.Length);
230                                 var ret = mono_btls_ssl_ctx_set_ciphers (
231                                         Handle.DangerousGetHandle (),
232                                         ciphers.Length, data, allow_unsupported ? 1 : 0);
233                                 CheckError (ret > 0);
234                         } finally {
235                                 Marshal.FreeHGlobal (data);
236                         }
237                 }
238
239                 public void SetVerifyParam (MonoBtlsX509VerifyParam param)
240                 {
241                         CheckThrow ();
242                         var ret = mono_btls_ssl_ctx_set_verify_param (
243                                 Handle.DangerousGetHandle (),
244                                 param.Handle.DangerousGetHandle ());
245                         CheckError (ret);
246                 }
247
248                 protected override void Close ()
249                 {
250                         if (store != null) {
251                                 store.Dispose ();
252                                 store = null;
253                         }
254                         if (instance.IsAllocated)
255                                 instance.Free ();
256                         base.Close ();
257                 }
258         }
259 }
260 #endif