// // Used only by client SSL code, never returns null. // internal static string[] GetRequestCertificateAuthorities(SafeDeleteContext securityContext) { SafeSslHandle sslContext = ((SafeDeleteSslContext)securityContext).SslContext; if (sslContext == null) { return(Array.Empty <string>()); } using (SafeCFArrayHandle dnArray = Interop.AppleCrypto.SslCopyCADistinguishedNames(sslContext)) { long size = Interop.CoreFoundation.CFArrayGetCount(dnArray); if (size == 0) { return(Array.Empty <string>()); } string[] distinguishedNames = new string[size]; for (int i = 0; i < size; i++) { IntPtr element = Interop.CoreFoundation.CFArrayGetValueAtIndex(dnArray, i); using (SafeCFDataHandle cfData = new SafeCFDataHandle(element, ownsHandle: false)) { byte[] dnData = Interop.CoreFoundation.CFGetData(cfData); X500DistinguishedName dn = new X500DistinguishedName(dnData); distinguishedNames[i] = dn.Name; } } return(distinguishedNames); } }
public Uri GetProxy(Uri targetUri) { using (SafeCFDictionaryHandle systemProxySettings = CFNetworkCopySystemProxySettings()) using (SafeCreateHandle cfurl = CFURLCreateWithString(targetUri.AbsoluteUri)) using (SafeCFArrayHandle proxies = CFNetworkCopyProxiesForURL(cfurl, systemProxySettings)) { long proxyCount = CFArrayGetCount(proxies); for (int i = 0; i < proxyCount; i++) { IntPtr proxyValue = CFArrayGetValueAtIndex(proxies, i); using (SafeCFDictionaryHandle proxyDict = new SafeCFDictionaryHandle(proxyValue, false)) { CFProxy proxy = new CFProxy(proxyDict); if (proxy.ProxyType == CFProxy.kCFProxyTypeAutoConfigurationURL || proxy.ProxyType == CFProxy.kCFProxyTypeAutoConfigurationJavaScript) { Uri result = ExecuteProxyAutoConfiguration(cfurl, proxy); if (result != null) { return(result); } } else if (proxy.ProxyType == CFProxy.kCFProxyTypeHTTP || proxy.ProxyType == CFProxy.kCFProxyTypeHTTPS) { return(GetProxyUri("http", proxy)); } } } } return(null); }
public void CloneTo(X509Certificate2Collection collection) { HashSet <X509Certificate2> dedupedCerts = new HashSet <X509Certificate2>(); if (_storeName == StoreName.Root) { using (SafeCFArrayHandle certs = Interop.AppleCrypto.StoreEnumerateRoot(_location)) { ReadCollection(certs, dedupedCerts); } } else if (_storeName == StoreName.Disallowed) { using (SafeCFArrayHandle certs = Interop.AppleCrypto.StoreEnumerateDisallowed(_location)) { ReadCollection(certs, dedupedCerts); } } else { Debug.Fail($"No handler for trust store {_storeName}"); } foreach (X509Certificate2 cert in dedupedCerts) { collection.Add(cert); } }
public static ILoaderPal FromBlob(byte[] rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); X509ContentType contentType = X509Certificate2.GetCertContentType(rawData); if (contentType == X509ContentType.Pkcs12) { if ((keyStorageFlags & X509KeyStorageFlags.EphemeralKeySet) == X509KeyStorageFlags.EphemeralKeySet) { throw new PlatformNotSupportedException(SR.Cryptography_X509_NoEphemeralPfx); } bool exportable = (keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable; bool persist = (keyStorageFlags & X509KeyStorageFlags.PersistKeySet) == X509KeyStorageFlags.PersistKeySet; SafeKeychainHandle keychain = persist ? Interop.AppleCrypto.SecKeychainCopyDefault() : Interop.AppleCrypto.CreateTemporaryKeychain(); return(ImportPkcs12(rawData, password, exportable, keychain)); } SafeCFArrayHandle certs = Interop.AppleCrypto.X509ImportCollection( rawData, contentType, password, SafeTemporaryKeychainHandle.InvalidHandle, exportable: true); return(new AppleCertLoader(certs, null)); }
private static extern int AppleCryptoNative_X509ImportCollection( byte[] pbKeyBlob, int cbKeyBlob, X509ContentType contentType, SafeCreateHandle cfPfxPassphrase, SafeKeychainHandle tmpKeychain, int exportable, out SafeCFArrayHandle pCollectionOut, out int pOSStatus);
public static ILoaderPal FromBlob(byte[] rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); X509ContentType contentType = X509Certificate2.GetCertContentType(rawData); SafeKeychainHandle keychain; bool exportable = true; if (contentType == X509ContentType.Pkcs12) { if ((keyStorageFlags & X509KeyStorageFlags.EphemeralKeySet) == X509KeyStorageFlags.EphemeralKeySet) { throw new PlatformNotSupportedException(SR.Cryptography_X509_NoEphemeralPfx); } exportable = (keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable; bool persist = (keyStorageFlags & X509KeyStorageFlags.PersistKeySet) == X509KeyStorageFlags.PersistKeySet; keychain = persist ? Interop.AppleCrypto.SecKeychainCopyDefault() : Interop.AppleCrypto.CreateTemporaryKeychain(); } else { keychain = SafeTemporaryKeychainHandle.InvalidHandle; password = SafePasswordHandle.InvalidHandle; } // Only dispose tmpKeychain on the exception path, otherwise it's managed by AppleCertLoader. try { SafeCFArrayHandle certs = Interop.AppleCrypto.X509ImportCollection( rawData, contentType, password, keychain, exportable); // If the default keychain was used, null will be passed to the loader. return(new AppleCertLoader(certs, keychain as SafeTemporaryKeychainHandle)); } catch { keychain.Dispose(); throw; } }
public Uri?ExecuteProxyAutoConfiguration(SafeCreateHandle cfurl, CFProxy proxy) { Uri? result = null; CFRunLoopRef runLoop = CFRunLoopGetCurrent(); // Callback that will be called after executing the configuration script CFProxyAutoConfigurationResultCallback cb = (IntPtr client, IntPtr proxyListHandle, IntPtr error) => { if (proxyListHandle != IntPtr.Zero) { using (var proxyList = new SafeCFArrayHandle(proxyListHandle, false)) { long proxyCount = CFArrayGetCount(proxyList); for (int i = 0; i < proxyCount; i++) { IntPtr proxyValue = CFArrayGetValueAtIndex(proxyList, i); using (SafeCFDictionaryHandle proxyDict = new SafeCFDictionaryHandle(proxyValue, false)) { CFProxy proxy = new CFProxy(proxyDict); if (proxy.ProxyType == CFProxy.kCFProxyTypeHTTP || proxy.ProxyType == CFProxy.kCFProxyTypeHTTPS) { result = GetProxyUri("http", proxy); break; } } } } } CFRunLoopStop(runLoop); }; CFStreamClientContext clientContext = default; CFRunLoopSourceRef loopSource = proxy.ProxyType == CFProxy.kCFProxyTypeAutoConfigurationURL ? CFNetworkExecuteProxyAutoConfigurationURL(proxy.AutoConfigurationURL, cfurl, cb, ref clientContext) : CFNetworkExecuteProxyAutoConfigurationScript(proxy.AutoConfigurationJavaScript, cfurl, cb, ref clientContext); using (var mode = CFStringCreateWithCString(typeof(MacProxy).FullName !)) { IntPtr modeHandle = mode.DangerousGetHandle(); CFRunLoopAddSource(runLoop, loopSource, modeHandle); CFRunLoopRunInMode(modeHandle, double.MaxValue, 0); CFRunLoopSourceInvalidate(loopSource); } GC.KeepAlive(cb); return(result); }
public void CloneTo(X509Certificate2Collection collection) { HashSet <X509Certificate2> dedupedCerts = new HashSet <X509Certificate2>(); using (SafeCFArrayHandle identities = Interop.AppleCrypto.KeychainEnumerateIdentities(_keychainHandle)) { ReadCollection(identities, dedupedCerts); } using (SafeCFArrayHandle certs = Interop.AppleCrypto.KeychainEnumerateCerts(_keychainHandle)) { ReadCollection(certs, dedupedCerts); } foreach (X509Certificate2 cert in dedupedCerts) { collection.Add(cert); } }
private static void ReadCollection(SafeCFArrayHandle matches, HashSet <X509Certificate2> collection) { if (matches.IsInvalid) { return; } long count = Interop.CoreFoundation.CFArrayGetCount(matches); for (int i = 0; i < count; i++) { IntPtr handle = Interop.CoreFoundation.CFArrayGetValueAtIndex(matches, i); SafeSecCertificateHandle certHandle; SafeSecIdentityHandle identityHandle; if (Interop.AppleCrypto.X509DemuxAndRetainHandle(handle, out certHandle, out identityHandle)) { X509Certificate2 cert; if (certHandle.IsInvalid) { certHandle.Dispose(); cert = new X509Certificate2(new AppleCertificatePal(identityHandle)); } else { identityHandle.Dispose(); cert = new X509Certificate2(new AppleCertificatePal(certHandle)); } if (!collection.Add(cert)) { cert.Dispose(); } } } }
private static partial IntPtr CFArrayGetValueAtIndex(SafeCFArrayHandle cfArray, CFIndex index);
private static partial CFIndex _CFArrayGetCount(SafeCFArrayHandle cfArray);
private static extern int AppleCryptoNative_SecKeychainEnumerateCerts( out SafeCFArrayHandle matches);
public AppleCertLoader(SafeCFArrayHandle collectionHandle, SafeTemporaryKeychainHandle?tmpKeychain) { _collectionHandle = collectionHandle; _tmpKeychain = tmpKeychain; }
private static extern int AppleCryptoNative_SecKeychainEnumerateCerts( SafeKeychainHandle keychain, out SafeCFArrayHandle matches, out int pOSStatus);
public static ILoaderPal FromBlob(ReadOnlySpan <byte> rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { List <ICertificatePal>?certificateList = null; AppleCertificatePal.TryDecodePem( rawData, (derData, contentType) => { certificateList = certificateList ?? new List <ICertificatePal>(); certificateList.Add(AppleCertificatePal.FromDerBlob(derData, contentType, password, keyStorageFlags)); return(true); }); if (certificateList != null) { return(new CertCollectionLoader(certificateList)); } X509ContentType contentType = AppleCertificatePal.GetDerCertContentType(rawData); if (contentType == X509ContentType.Pkcs7) { throw new CryptographicException( SR.Cryptography_X509_PKCS7_Unsupported, new PlatformNotSupportedException(SR.Cryptography_X509_PKCS7_Unsupported)); } if (contentType == X509ContentType.Pkcs12) { ApplePkcs12Reader reader = new ApplePkcs12Reader(rawData); try { reader.Decrypt(password); return(new ApplePkcs12CertLoader(reader, password)); } catch { reader.Dispose(); throw; } } SafeCFArrayHandle certs = Interop.AppleCrypto.X509ImportCollection( rawData, contentType, password); using (certs) { long longCount = Interop.CoreFoundation.CFArrayGetCount(certs); if (longCount > int.MaxValue) { throw new CryptographicException(); } int count = (int)longCount; // Apple returns things in the opposite order from Windows, so read backwards. certificateList = new List <ICertificatePal>(count); for (int i = count - 1; i >= 0; i--) { IntPtr handle = Interop.CoreFoundation.CFArrayGetValueAtIndex(certs, i); if (handle != IntPtr.Zero) { ICertificatePal?certPal = CertificatePal.FromHandle(handle, throwOnFail: false); if (certPal != null) { certificateList.Add(certPal); } } } } return(new CertCollectionLoader(certificateList)); }
private static extern CFIndex _CFArrayGetCount(SafeCFArrayHandle cfArray);
private static partial int AppleCryptoNative_StoreEnumerateUserDisallowed( out SafeCFArrayHandle pCertsOut, out int pOSStatusOut);
private static extern int AppleCryptoNative_StoreEnumerateUserRoot( out SafeCFArrayHandle pCertsOut, out int pOSStatusOut);
private static extern int AppleCryptoNative_SslCopyCADistinguishedNames( SafeSslHandle sslHandle, out SafeCFArrayHandle pArrayOut, out int pOSStatus);
private static partial int AppleCryptoNative_X509ImportCollection( ref byte pbKeyBlob, int cbKeyBlob, X509ContentType contentType, SafeCreateHandle cfPfxPassphrase, out SafeCFArrayHandle pCollectionOut);
private static extern int AppleCryptoNative_StoreEnumerateMachineDisallowed( out SafeCFArrayHandle pCertsOut, out int pOSStatusOut);
internal static long CFArrayGetCount(SafeCFArrayHandle cfArray) { return(_CFArrayGetCount(cfArray).ToInt64()); }
private static partial int AppleCryptoNative_SecKeychainEnumerateIdentities( out SafeCFArrayHandle matches);
internal static IntPtr CFArrayGetValueAtIndex(SafeCFArrayHandle cfArray, int index) { return(CFArrayGetValueAtIndex(cfArray, new CFIndex(index))); }
private static extern IntPtr CFArrayGetValueAtIndex(SafeCFArrayHandle cfArray, CFIndex index);
private static partial int AppleCryptoNative_SecKeychainEnumerateIdentities( SafeKeychainHandle keychain, out SafeCFArrayHandle matches, out int pOSStatus);
private static partial int AppleCryptoNative_StoreEnumerateMachineRoot( out SafeCFArrayHandle pCertsOut, out int pOSStatusOut);