// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if SECURITY_DEP
-#if MONO_X509_ALIAS
-extern alias PrebuiltSystem;
-#endif
-#if MONO_X509_ALIAS
-using XX509CertificateCollection = PrebuiltSystem::System.Security.Cryptography.X509Certificates.X509CertificateCollection;
-#else
using XX509CertificateCollection = System.Security.Cryptography.X509Certificates.X509CertificateCollection;
-#endif
using System;
using System.Runtime.InteropServices;
[DllImport (SecurityLibrary)]
extern static /* OSStatus */ int SecTrustCreateWithCertificates (IntPtr certOrCertArray, IntPtr policies, out IntPtr sectrustref);
+ [DllImport (SecurityLibrary)]
+ extern static /* OSStatus */ int SecTrustSetAnchorCertificates (IntPtr /* SecTrustRef */ trust, IntPtr /* CFArrayRef */ anchorCertificates);
+
[DllImport (SecurityLibrary)]
extern static IntPtr SecPolicyCreateSSL ([MarshalAs (UnmanagedType.I1)] bool server, IntPtr cfStringHostname);
[DllImport (CoreFoundationLibrary)]
unsafe extern static IntPtr CFDataCreate (IntPtr allocator, byte *bytes, /* CFIndex */ IntPtr length);
+ [DllImport (CoreFoundationLibrary)]
+ extern static void CFRetain (IntPtr handle);
+
[DllImport (CoreFoundationLibrary)]
extern static void CFRelease (IntPtr handle);
IntPtr.Zero);
}
}
+
+ static IntPtr GetCertificate (X509Certificate certificate)
+ {
+ var handle = certificate.Impl.GetNativeAppleCertificate ();
+ if (handle != IntPtr.Zero) {
+ CFRetain (handle);
+ return handle;
+ }
+ var dataPtr = MakeCFData (certificate.GetRawCertData ());
+ handle = SecCertificateCreateWithData (IntPtr.Zero, dataPtr);
+ CFRelease (dataPtr);
+ return handle;
+ }
- public static SecTrustResult TrustEvaluateSsl (XX509CertificateCollection certificates, string host)
+ public static SecTrustResult TrustEvaluateSsl (XX509CertificateCollection certificates, XX509CertificateCollection anchors, string host)
{
if (certificates == null)
return SecTrustResult.Deny;
try {
- return _TrustEvaluateSsl (certificates, host);
+ return _TrustEvaluateSsl (certificates, anchors, host);
} catch {
return SecTrustResult.Deny;
}
}
- static SecTrustResult _TrustEvaluateSsl (XX509CertificateCollection certificates, string hostName)
+ static SecTrustResult _TrustEvaluateSsl (XX509CertificateCollection certificates, XX509CertificateCollection anchors, string hostName)
{
int certCount = certificates.Count;
- IntPtr [] cfDataPtrs = new IntPtr [certCount];
+ int anchorCount = anchors != null ? anchors.Count : 0;
IntPtr [] secCerts = new IntPtr [certCount];
+ IntPtr [] secCertAnchors = new IntPtr [anchorCount];
IntPtr certArray = IntPtr.Zero;
+ IntPtr anchorArray = IntPtr.Zero;
IntPtr sslsecpolicy = IntPtr.Zero;
IntPtr host = IntPtr.Zero;
IntPtr sectrust = IntPtr.Zero;
SecTrustResult result = SecTrustResult.Deny;
try {
- for (int i = 0; i < certCount; i++)
- cfDataPtrs [i] = MakeCFData (certificates [i].GetRawCertData ());
-
- for (int i = 0; i < certCount; i++){
- secCerts [i] = SecCertificateCreateWithData (IntPtr.Zero, cfDataPtrs [i]);
+ for (int i = 0; i < certCount; i++) {
+ secCerts [i] = GetCertificate (certificates [i]);
if (secCerts [i] == IntPtr.Zero)
return SecTrustResult.Deny;
}
+
+ for (int i = 0; i < anchorCount; i++) {
+ secCertAnchors [i] = GetCertificate (anchors [i]);
+ if (secCertAnchors [i] == IntPtr.Zero)
+ return SecTrustResult.Deny;
+ }
+
certArray = FromIntPtrs (secCerts);
+
host = CFStringCreateWithCharacters (IntPtr.Zero, hostName, (IntPtr) hostName.Length);
sslsecpolicy = SecPolicyCreateSSL (true, host);
int code = SecTrustCreateWithCertificates (certArray, sslsecpolicy, out sectrust);
- if (code == 0)
- code = SecTrustEvaluate (sectrust, out result);
+ if (code != 0)
+ return SecTrustResult.Deny;
+
+ if (anchorCount > 0) {
+ anchorArray = FromIntPtrs (secCertAnchors);
+ SecTrustSetAnchorCertificates (sectrust, anchorArray);
+ }
+
+ code = SecTrustEvaluate (sectrust, out result);
return result;
} finally {
- for (int i = 0; i < certCount; i++)
- if (cfDataPtrs [i] != IntPtr.Zero)
- CFRelease (cfDataPtrs [i]);
-
if (certArray != IntPtr.Zero)
CFRelease (certArray);
+
+ if (anchorArray != IntPtr.Zero)
+ CFRelease (anchorArray);
for (int i = 0; i < certCount; i++)
if (secCerts [i] != IntPtr.Zero)
CFRelease (secCerts [i]);
+ for (int i = 0; i < anchorCount; i++)
+ if (secCertAnchors [i] != IntPtr.Zero)
+ CFRelease (secCertAnchors [i]);
+
if (sslsecpolicy != IntPtr.Zero)
CFRelease (sslsecpolicy);
if (host != IntPtr.Zero)