private static extern int SetX509ChainVerifyTime(
     SafeX509StoreCtxHandle ctx,
     int year,
     int month,
     int day,
     int hour,
     int minute,
     int second,
     [MarshalAs(UnmanagedType.Bool)] bool isDst);
            private static int VerifyCertChain(IntPtr storeCtxPtr, IntPtr arg)
            {
                List<X509Certificate2> otherCerts;
                bool success;

                using (SafeX509StoreCtxHandle storeCtx = new SafeX509StoreCtxHandle(storeCtxPtr, ownsHandle: false))
                using (X509Chain chain = new X509Chain())
                {
                    chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
                    chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;

                    IntPtr leafCertPtr = Interop.Crypto.X509StoreCtxGetTargetCert(storeCtx);

                    if (IntPtr.Zero == leafCertPtr)
                    {
                        Debug.Fail("Invalid target certificate");
                        return -1;
                    }

                    using (SafeSharedX509StackHandle extraStack = Interop.Crypto.X509StoreCtxGetSharedUntrusted(storeCtx))
                    {
                        int extraSize = extraStack.IsInvalid ? 0 : Interop.Crypto.GetX509StackFieldCount(extraStack);
                        otherCerts = new List<X509Certificate2>(extraSize);

                        for (int i = 0; i < extraSize; i++)
                        {
                            IntPtr certPtr = Interop.Crypto.GetX509StackField(extraStack, i);

                            if (certPtr != IntPtr.Zero)
                            {
                                X509Certificate2 cert = new X509Certificate2(certPtr);
                                otherCerts.Add(cert);
                                chain.ChainPolicy.ExtraStore.Add(cert);
                            }
                        }
                    }

                    using (X509Certificate2 leafCert = new X509Certificate2(leafCertPtr))
                    {
                        success = chain.Build(leafCert);
                    }
                }

                foreach (X509Certificate2 otherCert in otherCerts)
                {
                    otherCert.Dispose();
                }

                return success ? 1 : 0;
            }
            internal int VerifyCallback(int ok, IntPtr ctx)
            {
                if (ok < 0)
                {
                    return ok;
                }

                try
                {
                    using (var storeCtx = new SafeX509StoreCtxHandle(ctx, ownsHandle: false))
                    {
                        Interop.Crypto.X509VerifyStatusCode errorCode = Interop.Crypto.X509StoreCtxGetError(storeCtx);
                        int errorDepth = Interop.Crypto.X509StoreCtxGetErrorDepth(storeCtx);

                        if (errorCode != Interop.Crypto.X509VerifyStatusCode.X509_V_OK)
                        {
                            while (Errors.Count <= errorDepth)
                            {
                                Errors.Add(null);
                            }

                            if (Errors[errorDepth] == null)
                            {
                                Errors[errorDepth] = new List<Interop.Crypto.X509VerifyStatusCode>();
                            }

                            Errors[errorDepth].Add(errorCode);
                        }
                    }

                    return 1;
                }
                catch
                {
                    return -1;
                }
            }
Example #4
0
 internal static extern void X509StoreCtxSetVerifyCallback(SafeX509StoreCtxHandle ctx, X509StoreVerifyCallback callback);
Example #5
0
 internal static extern int X509StoreCtxGetErrorDepth(SafeX509StoreCtxHandle ctx);
Example #6
0
 internal static extern X509VerifyStatusCode X509StoreCtxGetError(SafeX509StoreCtxHandle ctx);
            internal int VerifyCallback(int ok, IntPtr ctx)
            {
                if (ok < 0)
                {
                    return ok;
                }

                try
                {
                    using (var storeCtx = new SafeX509StoreCtxHandle(ctx, ownsHandle: false))
                    {
                        Interop.Crypto.X509VerifyStatusCode errorCode = Interop.Crypto.X509StoreCtxGetError(storeCtx);
                        int errorDepth = Interop.Crypto.X509StoreCtxGetErrorDepth(storeCtx);

                        // We don't report "OK" as an error.
                        // For compatibility with Windows / .NET Framework, do not report X509_V_CRL_NOT_YET_VALID.
                        if (errorCode != Interop.Crypto.X509VerifyStatusCode.X509_V_OK &&
                            errorCode != Interop.Crypto.X509VerifyStatusCode.X509_V_ERR_CRL_NOT_YET_VALID)
                        {
                            while (Errors.Count <= errorDepth)
                            {
                                Errors.Add(null);
                            }

                            if (Errors[errorDepth] == null)
                            {
                                Errors[errorDepth] = new List<Interop.Crypto.X509VerifyStatusCode>();
                            }

                            Errors[errorDepth].Add(errorCode);
                        }
                    }

                    return 1;
                }
                catch
                {
                    return -1;
                }
            }
Example #8
0
 internal static extern IntPtr X509StoreCtxGetTargetCert(SafeX509StoreCtxHandle ctx);
            private static int VerifyCertChain(IntPtr storeCtxPtr, IntPtr arg)
            {
                using (SafeX509StoreCtxHandle storeCtx = new SafeX509StoreCtxHandle(storeCtxPtr, ownsHandle: false))
                {
                    // First use the default verification provided directly by OpenSSL.
                    // If it succeeds in verifying the cert chain, we're done.
                    // (Employing this instead of our custom implementation will need to be
                    // revisited if we ever decide to a) introduce a "disallowed" store
                    // that enables users to "untrust" certs the system trusts, or b) decide
                    // CRL checking is required, neither of which is done by OpenSSL).
                    int sslResult = Interop.Crypto.X509VerifyCert(storeCtx);
                    if (sslResult == 1)
                    {
                        return 1;
                    }

                    // X509_verify_cert can return < 0 in the case of programmer error
                    Debug.Assert(sslResult == 0, "Unexpected error from X509_verify_cert: " + sslResult);

                    // Only if the fast default verification fails do we then fall back to our more 
                    // manual and more expensive verification that includes checking the user's 
                    // certs and not just the system store ones.
                    List<X509Certificate2> otherCerts;
                    bool success;
                    using (X509Chain chain = new X509Chain())
                    {
                        chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
                        chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;

                        IntPtr leafCertPtr = Interop.Crypto.X509StoreCtxGetTargetCert(storeCtx);

                        if (IntPtr.Zero == leafCertPtr)
                        {
                            Debug.Fail("Invalid target certificate");
                            return -1;
                        }

                        using (SafeSharedX509StackHandle extraStack = Interop.Crypto.X509StoreCtxGetSharedUntrusted(storeCtx))
                        {
                            int extraSize = extraStack.IsInvalid ? 0 : Interop.Crypto.GetX509StackFieldCount(extraStack);
                            otherCerts = new List<X509Certificate2>(extraSize);

                            for (int i = 0; i < extraSize; i++)
                            {
                                IntPtr certPtr = Interop.Crypto.GetX509StackField(extraStack, i);

                                if (certPtr != IntPtr.Zero)
                                {
                                    X509Certificate2 cert = new X509Certificate2(certPtr);
                                    otherCerts.Add(cert);
                                    chain.ChainPolicy.ExtraStore.Add(cert);
                                }
                            }
                        }

                        using (X509Certificate2 leafCert = new X509Certificate2(leafCertPtr))
                        {
                            success = chain.Build(leafCert);
                            AddChannelBindingToken(leafCert, arg);
                        }
                    }

                    foreach (X509Certificate2 otherCert in otherCerts)
                    {
                        otherCert.Dispose();
                    }

                    return success ? 1 : 0;
                }
            }
Example #10
0
 internal static extern SafeX509StackHandle X509_STORE_CTX_get1_chain(SafeX509StoreCtxHandle ctx);
Example #11
0
 internal static extern int X509_verify_cert(SafeX509StoreCtxHandle ctx);
Example #12
0
 internal static extern bool X509_STORE_CTX_init(SafeX509StoreCtxHandle ctx, SafeX509StoreHandle store, SafeX509Handle x509, IntPtr zero);
Example #13
0
 internal static extern int X509_STORE_CTX_get_error_depth(SafeX509StoreCtxHandle ctx);
Example #14
0
 internal static extern X509VerifyStatusCode X509_STORE_CTX_get_error(SafeX509StoreCtxHandle ctx);
Example #15
0
        private static int VerifyClientCertificate(int preverify_ok, IntPtr x509_ctx_ptr)
        {
            using (SafeX509StoreCtxHandle storeHandle = new SafeX509StoreCtxHandle(x509_ctx_ptr, false))
            {
                using (var chain = new X509Chain())
                {
                    chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
                    chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;

                    using (SafeX509StackHandle chainStack = Crypto.X509StoreCtxGetChain(storeHandle))
                    {
                        if (chainStack.IsInvalid)
                        {
                            Debug.Fail("Invalid chain stack handle");
                            return 0;
                        }

                        IntPtr certPtr = Crypto.GetX509StackField(chainStack, 0);
                        if (IntPtr.Zero == certPtr)
                        {
                            return 0;
                        }

                        using (X509Certificate2 cert = new X509Certificate2(certPtr))
                        {
                            return chain.Build(cert) ? 1 : 0;
                        }
                    }
                }
            }
        }
Example #16
0
 internal static extern SafeX509StackHandle X509StoreCtxGetChain(SafeX509StoreCtxHandle ctx);
Example #17
0
 private static extern SafeSharedX509StackHandle X509StoreCtxGetSharedUntrusted_private(SafeX509StoreCtxHandle ctx);
Example #18
0
 internal static extern bool X509StoreCtxInit(SafeX509StoreCtxHandle ctx, SafeX509StoreHandle store, SafeX509Handle x509);
Example #19
0
 internal static SafeSharedX509StackHandle X509StoreCtxGetSharedUntrusted(SafeX509StoreCtxHandle ctx)
 {
     return SafeInteriorHandle.OpenInteriorHandle(
         x => X509StoreCtxGetSharedUntrusted_private(x),
         ctx);
 }
Example #20
0
 internal static extern int X509VerifyCert(SafeX509StoreCtxHandle ctx);
Example #21
0
            private static int VerifyCertChain(IntPtr storeCtxPtr, IntPtr curlPtr)
            {
                EasyRequest easy;
                if (!TryGetEasyRequest(curlPtr, out easy))
                {
                    EventSourceTrace("Could not find associated easy request: {0}", curlPtr);
                    return 0;
                }

                using (var storeCtx = new SafeX509StoreCtxHandle(storeCtxPtr, ownsHandle: false))
                {
                    IntPtr leafCertPtr = Interop.Crypto.X509StoreCtxGetTargetCert(storeCtx);
                    if (IntPtr.Zero == leafCertPtr)
                    {
                        EventSourceTrace("Invalid certificate pointer", easy: easy);
                        return 0;
                    }

                    using (X509Certificate2 leafCert = new X509Certificate2(leafCertPtr))
                    {
                        // We need to respect the user's server validation callback if there is one.  If there isn't one,
                        // we can start by first trying to use OpenSSL's verification, though only if CRL checking is disabled,
                        // as OpenSSL doesn't do that.
                        if (easy._handler.ServerCertificateValidationCallback == null &&
                            !easy._handler.CheckCertificateRevocationList)
                        {
                            // Start by using the default verification provided directly by OpenSSL.
                            // If it succeeds in verifying the cert chain, we're done. Employing this instead of 
                            // our custom implementation will need to be revisited if we ever decide to introduce a 
                            // "disallowed" store that enables users to "untrust" certs the system trusts.
                            int sslResult = Interop.Crypto.X509VerifyCert(storeCtx);
                            if (sslResult == 1)
                            {
                                return 1;
                            }

                            // X509_verify_cert can return < 0 in the case of programmer error
                            Debug.Assert(sslResult == 0, "Unexpected error from X509_verify_cert: " + sslResult);
                        }

                        // Either OpenSSL verification failed, or there was a server validation callback.
                        // Either way, fall back to manual and more expensive verification that includes 
                        // checking the user's certs (not just the system store ones as OpenSSL does).
                        X509Certificate2[] otherCerts;
                        int otherCertsCount = 0;
                        bool success;
                        using (X509Chain chain = new X509Chain())
                        {
                            chain.ChainPolicy.RevocationMode = easy._handler.CheckCertificateRevocationList ? X509RevocationMode.Online : X509RevocationMode.NoCheck;
                            chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;

                            using (SafeSharedX509StackHandle extraStack = Interop.Crypto.X509StoreCtxGetSharedUntrusted(storeCtx))
                            {
                                if (extraStack.IsInvalid)
                                {
                                    otherCerts = Array.Empty<X509Certificate2>();
                                }
                                else
                                {
                                    int extraSize = Interop.Crypto.GetX509StackFieldCount(extraStack);
                                    otherCerts = new X509Certificate2[extraSize];

                                    for (int i = 0; i < extraSize; i++)
                                    {
                                        IntPtr certPtr = Interop.Crypto.GetX509StackField(extraStack, i);
                                        if (certPtr != IntPtr.Zero)
                                        {
                                            X509Certificate2 cert = new X509Certificate2(certPtr);
                                            otherCerts[otherCertsCount++] = cert;
                                            chain.ChainPolicy.ExtraStore.Add(cert);
                                        }
                                    }
                                }
                            }

                            var serverCallback = easy._handler._serverCertificateValidationCallback;
                            if (serverCallback == null)
                            {
                                SslPolicyErrors errors = CertificateValidation.BuildChainAndVerifyProperties(chain, leafCert,
                                    checkCertName: false, hostName: null); // libcurl already verifies the host name
                                success = errors == SslPolicyErrors.None;
                            }
                            else
                            {
                                SslPolicyErrors errors = CertificateValidation.BuildChainAndVerifyProperties(chain, leafCert,
                                    checkCertName: true, hostName: easy._requestMessage.RequestUri.Host); // we disabled automatic host verification, so we do it here
                                try
                                {
                                    success = serverCallback(easy._requestMessage, leafCert, chain, errors);
                                }
                                catch (Exception exc)
                                {
                                    EventSourceTrace("Server validation callback threw exception: {0}", exc, easy: easy);
                                    easy.FailRequest(exc);
                                    success = false;
                                }
                            }
                        }

                        for (int i = 0; i < otherCertsCount; i++)
                        {
                            otherCerts[i].Dispose();
                        }

                        return success ? 1 : 0;
                    }
                }
            }
        internal static void SetX509ChainVerifyTime(SafeX509StoreCtxHandle ctx, DateTime verifyTime)
        {
            // Let Unspecified mean Local, so only convert if the source was UTC.
            if (verifyTime.Kind == DateTimeKind.Utc)
            {
                verifyTime = verifyTime.ToLocalTime();
            }

            int succeeded = SetX509ChainVerifyTime(
                ctx,
                verifyTime.Year,
                verifyTime.Month,
                verifyTime.Day,
                verifyTime.Hour,
                verifyTime.Minute,
                verifyTime.Second,
                verifyTime.IsDaylightSavingTime());

            if (succeeded != 1)
            {
                throw new CryptographicException();
            }
        }