1 //
2 // MonoBtlsX509StoreCtx.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 && MONO_FEATURE_BTLS
27 using System;
28 using System.IO;
29 using System.Runtime.InteropServices;
30 using System.Runtime.CompilerServices;
31 
32 namespace Mono.Btls
33 {
34 	class MonoBtlsX509StoreCtx : MonoBtlsObject
35 	{
36 		internal class BoringX509StoreCtxHandle : MonoBtlsHandle
37 		{
38 			bool dontFree;
39 
BoringX509StoreCtxHandle(IntPtr handle, bool ownsHandle = true)40 			internal BoringX509StoreCtxHandle (IntPtr handle, bool ownsHandle = true)
41 				: base (handle, ownsHandle)
42 			{
43 				dontFree = !ownsHandle;
44 			}
45 
46 			#if FIXME
BoringX509StoreCtxHandle(IntPtr handle)47 			internal BoringX509StoreCtxHandle (IntPtr handle)
48 				: base ()
49 			{
50 				base.handle = handle;
51 				this.dontFree = true;
52 			}
53 			#endif
54 
ReleaseHandle()55 			protected override bool ReleaseHandle ()
56 			{
57 				if (!dontFree)
58 					mono_btls_x509_store_ctx_free (handle);
59 				return true;
60 			}
61 		}
62 
63 		int? verifyResult;
64 
65 		new internal BoringX509StoreCtxHandle Handle {
66 			get { return (BoringX509StoreCtxHandle)base.Handle; }
67 		}
68 
69 		[DllImport (BTLS_DYLIB)]
mono_btls_x509_store_ctx_new()70 		extern static IntPtr mono_btls_x509_store_ctx_new ();
71 
72 		[DllImport (BTLS_DYLIB)]
mono_btls_x509_store_ctx_from_ptr(IntPtr ctx)73 		extern static IntPtr mono_btls_x509_store_ctx_from_ptr (IntPtr ctx);
74 
75 		[DllImport (BTLS_DYLIB)]
mono_btls_x509_store_ctx_get_error(IntPtr handle, out IntPtr error_string)76 		extern static MonoBtlsX509Error mono_btls_x509_store_ctx_get_error (IntPtr handle, out IntPtr error_string);
77 
78 		[DllImport (BTLS_DYLIB)]
mono_btls_x509_store_ctx_get_error_depth(IntPtr handle)79 		extern static int mono_btls_x509_store_ctx_get_error_depth (IntPtr handle);
80 
81 		[DllImport (BTLS_DYLIB)]
mono_btls_x509_store_ctx_get_chain(IntPtr handle)82 		extern static IntPtr mono_btls_x509_store_ctx_get_chain (IntPtr handle);
83 
84 		[DllImport (BTLS_DYLIB)]
mono_btls_x509_store_ctx_init(IntPtr handle, IntPtr store, IntPtr chain)85 		extern static int mono_btls_x509_store_ctx_init (IntPtr handle, IntPtr store, IntPtr chain);
86 
87 		[DllImport (BTLS_DYLIB)]
mono_btls_x509_store_ctx_set_param(IntPtr handle, IntPtr param)88 		extern static int mono_btls_x509_store_ctx_set_param (IntPtr handle, IntPtr param);
89 
90 		[DllImport (BTLS_DYLIB)]
mono_btls_x509_store_ctx_verify_cert(IntPtr handle)91 		extern static int mono_btls_x509_store_ctx_verify_cert (IntPtr handle);
92 
93 		[DllImport (BTLS_DYLIB)]
mono_btls_x509_store_ctx_get_by_subject(IntPtr handle, IntPtr name)94 		extern static IntPtr mono_btls_x509_store_ctx_get_by_subject (IntPtr handle, IntPtr name);
95 
96 		[DllImport (BTLS_DYLIB)]
mono_btls_x509_store_ctx_get_current_cert(IntPtr handle)97 		extern static IntPtr mono_btls_x509_store_ctx_get_current_cert (IntPtr handle);
98 
99 		[DllImport (BTLS_DYLIB)]
mono_btls_x509_store_ctx_get_current_issuer(IntPtr handle)100 		extern static IntPtr mono_btls_x509_store_ctx_get_current_issuer (IntPtr handle);
101 
102 		[DllImport (BTLS_DYLIB)]
mono_btls_x509_store_ctx_get_verify_param(IntPtr handle)103 		extern static IntPtr mono_btls_x509_store_ctx_get_verify_param (IntPtr handle);
104 
105 		[DllImport (BTLS_DYLIB)]
mono_btls_x509_store_ctx_get_untrusted(IntPtr handle)106 		extern static IntPtr mono_btls_x509_store_ctx_get_untrusted (IntPtr handle);
107 
108 		[DllImport (BTLS_DYLIB)]
mono_btls_x509_store_ctx_up_ref(IntPtr handle)109 		extern static IntPtr mono_btls_x509_store_ctx_up_ref (IntPtr handle);
110 
111 		[DllImport (BTLS_DYLIB)]
mono_btls_x509_store_ctx_free(IntPtr handle)112 		extern static void mono_btls_x509_store_ctx_free (IntPtr handle);
113 
MonoBtlsX509StoreCtx()114 		internal MonoBtlsX509StoreCtx ()
115 			: base (new BoringX509StoreCtxHandle (mono_btls_x509_store_ctx_new ()))
116 		{
117 		}
118 
Create_internal(IntPtr store_ctx)119 		static BoringX509StoreCtxHandle Create_internal (IntPtr store_ctx)
120 		{
121 			var handle = mono_btls_x509_store_ctx_from_ptr (store_ctx);
122 			if (handle == IntPtr.Zero)
123 				throw new MonoBtlsException ();
124 			return new BoringX509StoreCtxHandle (handle);
125 		}
126 
MonoBtlsX509StoreCtx(int preverify_ok, IntPtr store_ctx)127 		internal MonoBtlsX509StoreCtx (int preverify_ok, IntPtr store_ctx)
128 			: base (Create_internal (store_ctx))
129 		{
130 			verifyResult = preverify_ok;
131 		}
132 
MonoBtlsX509StoreCtx(BoringX509StoreCtxHandle ptr, int? verifyResult)133 		internal MonoBtlsX509StoreCtx (BoringX509StoreCtxHandle ptr, int? verifyResult)
134 			: base (ptr)
135 		{
136 			this.verifyResult = verifyResult;
137 		}
138 
GetError()139 		public MonoBtlsX509Error GetError ()
140 		{
141 			IntPtr error_string_ptr;
142 			return mono_btls_x509_store_ctx_get_error (Handle.DangerousGetHandle (), out error_string_ptr);
143 		}
144 
GetException()145 		public MonoBtlsX509Exception GetException ()
146 		{
147 			IntPtr error_string_ptr;
148 			var error = mono_btls_x509_store_ctx_get_error (Handle.DangerousGetHandle (), out error_string_ptr);
149 			if (error == 0)
150 				return null;
151 			if (error_string_ptr != IntPtr.Zero) {
152 				var error_string = Marshal.PtrToStringAnsi (error_string_ptr);
153 				return new MonoBtlsX509Exception (error, error_string);
154 			}
155 			return new MonoBtlsX509Exception (error, "Unknown verify error.");
156 		}
157 
GetChain()158 		public MonoBtlsX509Chain GetChain ()
159 		{
160 			var chain = mono_btls_x509_store_ctx_get_chain (Handle.DangerousGetHandle ());
161 			CheckError (chain != IntPtr.Zero);
162 			return new MonoBtlsX509Chain (new MonoBtlsX509Chain.BoringX509ChainHandle (chain));
163 		}
164 
GetUntrusted()165 		public MonoBtlsX509Chain GetUntrusted ()
166 		{
167 			var chain = mono_btls_x509_store_ctx_get_untrusted (Handle.DangerousGetHandle ());
168 			CheckError (chain != IntPtr.Zero);
169 			return new MonoBtlsX509Chain (new MonoBtlsX509Chain.BoringX509ChainHandle (chain));
170 		}
171 
Initialize(MonoBtlsX509Store store, MonoBtlsX509Chain chain)172 		public void Initialize (MonoBtlsX509Store store, MonoBtlsX509Chain chain)
173 		{
174 			var ret = mono_btls_x509_store_ctx_init (
175 				Handle.DangerousGetHandle (),
176 				store.Handle.DangerousGetHandle (),
177 				chain.Handle.DangerousGetHandle ());
178 			CheckError (ret);
179 		}
180 
SetVerifyParam(MonoBtlsX509VerifyParam param)181 		public void SetVerifyParam (MonoBtlsX509VerifyParam param)
182 		{
183 			var ret = mono_btls_x509_store_ctx_set_param (
184 				Handle.DangerousGetHandle (),
185 				param.Handle.DangerousGetHandle ());
186 			CheckError (ret);
187 		}
188 
189 		public int VerifyResult {
190 			get {
191 				if (verifyResult == null)
192 					throw new InvalidOperationException ();
193 				return verifyResult.Value;
194 			}
195 		}
196 
Verify()197 		public int Verify ()
198 		{
199 			verifyResult = mono_btls_x509_store_ctx_verify_cert (Handle.DangerousGetHandle ());
200 			return verifyResult.Value;
201 		}
202 
LookupBySubject(MonoBtlsX509Name name)203 		public MonoBtlsX509 LookupBySubject (MonoBtlsX509Name name)
204 		{
205 			var handle = mono_btls_x509_store_ctx_get_by_subject (
206 				Handle.DangerousGetHandle (), name.Handle.DangerousGetHandle ());
207 			if (handle == IntPtr.Zero)
208 				return null;
209 			return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (handle));
210 		}
211 
GetCurrentCertificate()212 		public MonoBtlsX509 GetCurrentCertificate ()
213 		{
214 			var x509 = mono_btls_x509_store_ctx_get_current_cert (Handle.DangerousGetHandle ());
215 			if (x509 == IntPtr.Zero)
216 				return null;
217 			return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (x509));
218 		}
219 
GetCurrentIssuer()220 		public MonoBtlsX509 GetCurrentIssuer ()
221 		{
222 			var x509 = mono_btls_x509_store_ctx_get_current_issuer (Handle.DangerousGetHandle ());
223 			if (x509 == IntPtr.Zero)
224 				return null;
225 			return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (x509));
226 		}
227 
GetVerifyParam()228 		public MonoBtlsX509VerifyParam GetVerifyParam ()
229 		{
230 			var param = mono_btls_x509_store_ctx_get_verify_param (Handle.DangerousGetHandle ());
231 			if (param == IntPtr.Zero)
232 				return null;
233 			return new MonoBtlsX509VerifyParam (new MonoBtlsX509VerifyParam.BoringX509VerifyParamHandle (param));
234 		}
235 
Copy()236 		public MonoBtlsX509StoreCtx Copy ()
237 		{
238 			var copy = mono_btls_x509_store_ctx_up_ref (Handle.DangerousGetHandle ());
239 			CheckError (copy != IntPtr.Zero);
240 			return new MonoBtlsX509StoreCtx (new BoringX509StoreCtxHandle (copy), verifyResult);
241 		}
242 	}
243 }
244 #endif
245