38778f109b0248eb9d861a8324adda4547985b20
[mono.git] / mcs / class / System / Mono.AppleTls / Trust.cs
1 #if SECURITY_DEP && MONO_FEATURE_APPLETLS
2 // 
3 // Trust.cs: Implements the managed SecTrust wrapper.
4 //
5 // Authors: 
6 //      Miguel de Icaza
7 //  Sebastien Pouliot  <sebastien@xamarin.com>
8 //
9 // Copyright 2010 Novell, Inc
10 // Copyright 2012-2014 Xamarin Inc.
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31 using System;
32 using System.Runtime.InteropServices;
33 using System.Security;
34 using System.Security.Cryptography.X509Certificates;
35 using ObjCRuntimeInternal;
36 using Mono.Net;
37
38 namespace Mono.AppleTls {
39         partial class SecTrust : INativeObject, IDisposable {
40                 IntPtr handle;
41
42                 internal SecTrust (IntPtr handle, bool owns = false)
43                 {
44                         if (handle == IntPtr.Zero)
45                                 throw new Exception ("Invalid handle");
46
47                         this.handle = handle;
48                         if (!owns)
49                                 CFObject.CFRetain (handle);
50                 }
51
52                 [DllImport (AppleTlsContext.SecurityLibrary)]
53                 extern static SecStatusCode SecTrustCreateWithCertificates (
54                         /* CFTypeRef */            IntPtr certOrCertArray,
55                         /* CFTypeRef __nullable */ IntPtr policies,
56                         /* SecTrustRef *__nonull */ out IntPtr sectrustref);
57                 
58
59                 public SecTrust (X509CertificateCollection certificates, SecPolicy policy)
60                 {
61                         if (certificates == null)
62                                 throw new ArgumentNullException ("certificates");
63
64                         SecCertificate[] array = new SecCertificate [certificates.Count];
65                         int i = 0;
66                         foreach (var certificate in certificates)
67                                 array [i++] = new SecCertificate (certificate);
68                         Initialize (array, policy);
69                         for (i = 0; i < array.Length; i++)
70                                 array [i].Dispose ();
71                 }
72
73                 void Initialize (SecCertificate[] array, SecPolicy policy)
74                 {
75                         using (var certs = CFArray.CreateArray (array)) {
76                                 Initialize (certs.Handle, policy);
77                         }
78                 }
79
80                 void Initialize (IntPtr certHandle, SecPolicy policy)
81                 {
82                         SecStatusCode result = SecTrustCreateWithCertificates (certHandle, policy == null ? IntPtr.Zero : policy.Handle, out handle);
83                         if (result != SecStatusCode.Success)
84                                 throw new ArgumentException (result.ToString ());
85                 }
86
87                 [DllImport (AppleTlsContext.SecurityLibrary)]
88                 extern static SecStatusCode /* OSStatus */ SecTrustEvaluate (IntPtr /* SecTrustRef */ trust, out /* SecTrustResultType */ SecTrustResult result);
89
90                 public SecTrustResult Evaluate ()
91                 {
92                         if (handle == IntPtr.Zero)
93                                 throw new ObjectDisposedException ("SecTrust");
94
95                         SecTrustResult trust;
96                         SecStatusCode result = SecTrustEvaluate (handle, out trust);
97                         if (result != SecStatusCode.Success)
98                                 throw new InvalidOperationException (result.ToString ());
99                         return trust;
100                 }
101
102                 [DllImport (AppleTlsContext.SecurityLibrary)]
103                 extern static IntPtr /* CFIndex */ SecTrustGetCertificateCount (IntPtr /* SecTrustRef */ trust);
104
105                 public int Count {
106                         get {
107                                 if (handle == IntPtr.Zero)
108                                         return 0;
109                                 return (int) SecTrustGetCertificateCount (handle);
110                         }
111                 }
112
113                 [DllImport (AppleTlsContext.SecurityLibrary)]
114                 extern static IntPtr /* SecCertificateRef */ SecTrustGetCertificateAtIndex (IntPtr /* SecTrustRef */ trust, IntPtr /* CFIndex */ ix);
115
116                 public SecCertificate this [IntPtr index] {
117                         get {
118                                 if (handle == IntPtr.Zero)
119                                         throw new ObjectDisposedException ("SecTrust");
120                                 if (((long)index < 0) || ((long)index >= Count))
121                                         throw new ArgumentOutOfRangeException ("index");
122
123                                 return new SecCertificate (SecTrustGetCertificateAtIndex (handle, index));
124                         }
125                 }
126
127                 internal X509Certificate GetCertificate (int index)
128                 {
129                         if (handle == IntPtr.Zero)
130                                 throw new ObjectDisposedException ("SecTrust");
131                         if (((long)index < 0) || ((long)index >= Count))
132                                 throw new ArgumentOutOfRangeException ("index");
133
134                         var ptr = SecTrustGetCertificateAtIndex (handle, (IntPtr)index);
135                         return new X509Certificate (ptr);
136                 }
137
138                 [DllImport (AppleTlsContext.SecurityLibrary)]
139                 extern static SecStatusCode /* OSStatus */ SecTrustSetAnchorCertificates (IntPtr /* SecTrustRef */ trust, IntPtr /* CFArrayRef */ anchorCertificates);
140
141                 public SecStatusCode SetAnchorCertificates (X509CertificateCollection certificates)
142                 {
143                         if (handle == IntPtr.Zero)
144                                 throw new ObjectDisposedException ("SecTrust");
145                         if (certificates == null)
146                                 return SecTrustSetAnchorCertificates (handle, IntPtr.Zero);
147
148                         SecCertificate[] array = new SecCertificate [certificates.Count];
149                         int i = 0;
150                         foreach (var certificate in certificates)
151                                 array [i++] = new SecCertificate (certificate);
152                         return SetAnchorCertificates (array);
153                 }
154
155                 public SecStatusCode SetAnchorCertificates (SecCertificate[] array)
156                 {
157                         if (array == null)
158                                 return SecTrustSetAnchorCertificates (handle, IntPtr.Zero);
159                         using (var certs = CFArray.FromNativeObjects (array)) {
160                                 return SecTrustSetAnchorCertificates (handle, certs.Handle);
161                         }
162                 }
163
164                 [DllImport (AppleTlsContext.SecurityLibrary)]
165                 extern static SecStatusCode /* OSStatus */ SecTrustSetAnchorCertificatesOnly (IntPtr /* SecTrustRef */ trust, bool anchorCertificatesOnly);
166
167                 public SecStatusCode SetAnchorCertificatesOnly (bool anchorCertificatesOnly)
168                 {
169                         if (handle == IntPtr.Zero)
170                                 throw new ObjectDisposedException ("SecTrust");
171
172                         return SecTrustSetAnchorCertificatesOnly (handle, anchorCertificatesOnly);
173                 }
174
175                 [DllImport (AppleTlsContext.SecurityLibrary)]
176                 extern static SecStatusCode /* OSStatus */ SecTrustSetVerifyDate (IntPtr /* SecTrustRef */ trust, IntPtr /* CFDateRef */ date);
177
178                 public SecStatusCode SetVerifyDate (DateTime date)
179                 {
180                         using (var nativeDate = CFDate.Create (date))
181                                 return SecTrustSetVerifyDate (handle, nativeDate.Handle);
182                 }
183
184                 ~SecTrust ()
185                 {
186                         Dispose (false);
187                 }
188
189                 protected virtual void Dispose (bool disposing)
190                 {
191                         if (handle != IntPtr.Zero) {
192                                 CFObject.CFRelease (handle);
193                                 handle = IntPtr.Zero;
194                         }
195                 }
196
197                 public void Dispose ()
198                 {
199                         Dispose (true);
200                         GC.SuppressFinalize (this);
201                 }
202
203                 public IntPtr Handle {
204                         get { return handle; }
205                 }
206         }
207 }
208 #endif