1 // Copyright (C) 2010 Novell, Inc (http://www.novell.com)
3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 using System.Runtime.InteropServices;
25 using Mono.Security.X509;
26 using Mono.Security.X509.Extensions;
28 namespace Mono.Security.X509 {
30 internal class OSX509Certificates {
31 public const string SecurityLibrary = "/System/Library/Frameworks/Security.framework/Security";
32 public const string CoreFoundationLibrary = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation";
34 [DllImport (SecurityLibrary)]
35 extern static IntPtr SecCertificateCreateWithData (IntPtr allocator, IntPtr nsdataRef);
37 [DllImport (SecurityLibrary)]
38 extern static int SecTrustCreateWithCertificates (IntPtr certOrCertArray, IntPtr policies, out IntPtr sectrustref);
40 [DllImport (SecurityLibrary)]
41 extern static IntPtr SecPolicyCreateSSL (int server, IntPtr cfStringHostname);
43 [DllImport (SecurityLibrary)]
44 extern static int SecTrustEvaluate (IntPtr secTrustRef, out SecTrustResult secTrustResultTime);
46 [DllImport (CoreFoundationLibrary)]
47 unsafe extern static IntPtr CFDataCreate (IntPtr allocator, byte *bytes, IntPtr length);
49 [DllImport (CoreFoundationLibrary)]
50 unsafe extern static void CFRelease (IntPtr handle);
52 [DllImport (CoreFoundationLibrary)]
53 extern static IntPtr CFArrayCreate (IntPtr allocator, IntPtr values, IntPtr numValues, IntPtr callbacks);
55 public enum SecTrustResult {
61 RecoverableTrustFailure,
66 static IntPtr sslsecpolicy = SecPolicyCreateSSL (0, IntPtr.Zero);
68 static IntPtr MakeCFData (byte [] data)
71 fixed (byte *ptr = &data [0])
72 return CFDataCreate (IntPtr.Zero, ptr, (IntPtr) data.Length);
76 static unsafe IntPtr FromIntPtrs (IntPtr [] values)
78 fixed (IntPtr* pv = values) {
79 return CFArrayCreate (
82 (IntPtr) values.Length,
87 public static SecTrustResult TrustEvaluateSsl (X509CertificateCollection certificates)
90 return _TrustEvaluateSsl (certificates);
92 return SecTrustResult.Deny;
96 static SecTrustResult _TrustEvaluateSsl (X509CertificateCollection certificates)
98 if (certificates == null)
99 throw new ArgumentNullException ("certificates");
101 int certCount = certificates.Count;
102 IntPtr [] cfDataPtrs = new IntPtr [certCount];
103 IntPtr [] secCerts = new IntPtr [certCount];
104 IntPtr certArray = IntPtr.Zero;
107 for (int i = 0; i < certCount; i++)
108 cfDataPtrs [i] = MakeCFData (certificates [i].RawData);
110 for (int i = 0; i < certCount; i++){
111 secCerts [i] = SecCertificateCreateWithData (IntPtr.Zero, cfDataPtrs [i]);
112 if (secCerts [i] == IntPtr.Zero)
113 return SecTrustResult.Deny;
115 certArray = FromIntPtrs (secCerts);
117 int code = SecTrustCreateWithCertificates (certArray, sslsecpolicy, out sectrust);
119 SecTrustResult result;
120 code = SecTrustEvaluate (sectrust, out result);
122 return SecTrustResult.Deny;
124 CFRelease (sectrust);
128 return SecTrustResult.Deny;
130 for (int i = 0; i < certCount; i++)
131 if (cfDataPtrs [i] != IntPtr.Zero)
132 CFRelease (cfDataPtrs [i]);
134 if (certArray != IntPtr.Zero)
135 CFRelease (certArray);
137 for (int i = 0; i < certCount; i++)
138 if (secCerts [i] != IntPtr.Zero)
139 CFRelease (secCerts [i]);