//
        // 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);
            }
        }
Beispiel #2
0
        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);
                }
            }
Beispiel #4
0
        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);
Beispiel #6
0
        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;
            }
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
            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);
Beispiel #12
0
 private static extern int AppleCryptoNative_SecKeychainEnumerateCerts(
     out SafeCFArrayHandle matches);
Beispiel #13
0
 public AppleCertLoader(SafeCFArrayHandle collectionHandle, SafeTemporaryKeychainHandle?tmpKeychain)
 {
     _collectionHandle = collectionHandle;
     _tmpKeychain      = tmpKeychain;
 }
 private static extern int AppleCryptoNative_SecKeychainEnumerateCerts(
     SafeKeychainHandle keychain,
     out SafeCFArrayHandle matches,
     out int pOSStatus);
Beispiel #15
0
        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);
Beispiel #17
0
 private static partial int AppleCryptoNative_StoreEnumerateUserDisallowed(
     out SafeCFArrayHandle pCertsOut,
     out int pOSStatusOut);
Beispiel #18
0
 private static extern int AppleCryptoNative_StoreEnumerateUserRoot(
     out SafeCFArrayHandle pCertsOut,
     out int pOSStatusOut);
Beispiel #19
0
 private static extern int AppleCryptoNative_SslCopyCADistinguishedNames(
     SafeSslHandle sslHandle,
     out SafeCFArrayHandle pArrayOut,
     out int pOSStatus);
Beispiel #20
0
 private static partial int AppleCryptoNative_X509ImportCollection(
     ref byte pbKeyBlob,
     int cbKeyBlob,
     X509ContentType contentType,
     SafeCreateHandle cfPfxPassphrase,
     out SafeCFArrayHandle pCollectionOut);
Beispiel #21
0
 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);
Beispiel #26
0
 private static partial int AppleCryptoNative_SecKeychainEnumerateIdentities(
     SafeKeychainHandle keychain,
     out SafeCFArrayHandle matches,
     out int pOSStatus);
Beispiel #27
0
 private static partial int AppleCryptoNative_StoreEnumerateMachineRoot(
     out SafeCFArrayHandle pCertsOut,
     out int pOSStatusOut);