X509CertificateStore.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / IdentityModel / System / IdentityModel / Selectors / X509CertificateStore.cs / 1305376 / X509CertificateStore.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.IdentityModel.Selectors 
{
    using Microsoft.Win32.SafeHandles; 
    using System.ComponentModel; 
    using System.Diagnostics;
    using System.Runtime.InteropServices; 
    using System.Runtime.CompilerServices;
    using System.Runtime.ConstrainedExecution;
    using System.Security;
    using System.Security.Cryptography; 
    using System.Security.Cryptography.X509Certificates;
 
    class X509CertificateStore 
    {
        SafeCertStoreHandle certStoreHandle = SafeCertStoreHandle.InvalidHandle; 
        string storeName;
        StoreLocation storeLocation;

        public X509CertificateStore(StoreName storeName, StoreLocation storeLocation) 
        {
            switch (storeName) 
            { 
                case StoreName.AddressBook:
                    this.storeName = "AddressBook"; 
                    break;
                case StoreName.AuthRoot:
                    this.storeName = "AuthRoot";
                    break; 
                case StoreName.CertificateAuthority:
                    this.storeName = "CA"; 
                    break; 
                case StoreName.Disallowed:
                    this.storeName = "Disallowed"; 
                    break;
                case StoreName.My:
                    this.storeName = "My";
                    break; 
                case StoreName.Root:
                    this.storeName = "Root"; 
                    break; 
                case StoreName.TrustedPeople:
                    this.storeName = "TrustedPeople"; 
                    break;
                case StoreName.TrustedPublisher:
                    this.storeName = "TrustedPublisher";
                    break; 
                default:
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidEnumArgumentException("storeName", (int)storeName, 
                        typeof(StoreName))); 

            } 

            if (storeLocation != StoreLocation.CurrentUser && storeLocation != StoreLocation.LocalMachine)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("storeLocation", SR.GetString(SR.X509CertStoreLocationNotValid))); 
            }
            this.storeLocation = storeLocation; 
        } 

        public void Close() 
        {
            // Accessing via IDisposable to avoid Security check (functionally the same)
            ((IDisposable)this.certStoreHandle).Dispose();
        } 

        public void Open(OpenFlags openFlags) 
        { 
            DiagnosticUtility.DebugAssert(this.certStoreHandle.IsInvalid, "");
 
            uint dwOpenFlags = MapX509StoreFlags(this.storeLocation, openFlags);
            SafeCertStoreHandle certStoreHandle = CAPI.CertOpenStore(new IntPtr(CAPI.CERT_STORE_PROV_SYSTEM),
                                                       CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
                                                       IntPtr.Zero, 
                                                       dwOpenFlags,
                                                       this.storeName); 
 
            if (certStoreHandle == null || certStoreHandle.IsInvalid)
            { 
                int error = Marshal.GetLastWin32Error();
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error));
            }
            this.certStoreHandle = certStoreHandle; 
        }
 
        public X509Certificate2Collection Find(X509FindType findType, object findValue, bool validOnly) 
        {
            DiagnosticUtility.DebugAssert(!this.certStoreHandle.IsInvalid, ""); 

            uint dwFindType;
            SafeHGlobalHandle pvFindPara = SafeHGlobalHandle.InvalidHandle;
            SafeCertContextHandle pCertContext = SafeCertContextHandle.InvalidHandle; 
            X509Certificate2Collection result = new X509Certificate2Collection();
            SafeHGlobalHandle pvTemp = SafeHGlobalHandle.InvalidHandle; 
            string strFindValue; 
            byte[] bytes;
 
            try
            {
                switch (findType)
                { 
                    case X509FindType.FindBySubjectName:
                        strFindValue = findValue as string; 
                        if (strFindValue == null) 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatch, findType, typeof(string), findValue.GetType())));
 
                        dwFindType = CAPI.CERT_FIND_SUBJECT_STR;
                        pvFindPara = SafeHGlobalHandle.AllocHGlobal(strFindValue);
                        break;
 
                    case X509FindType.FindByThumbprint:
                        bytes = findValue as byte[]; 
                        if (bytes == null) 
                        {
                            strFindValue = findValue as string; 
                            if (strFindValue == null)
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatchMulti, findType, typeof(string), typeof(byte[]), findValue.GetType())));

                            bytes = SecurityUtils.DecodeHexString(strFindValue); 
                        }
 
                        CAPI.CRYPTOAPI_BLOB blob = new CAPI.CRYPTOAPI_BLOB(); 
                        pvTemp = SafeHGlobalHandle.AllocHGlobal(bytes);
                        blob.pbData = pvTemp.DangerousGetHandle(); 
                        blob.cbData = (uint)bytes.Length;
                        dwFindType = CAPI.CERT_FIND_HASH;
                        pvFindPara = SafeHGlobalHandle.AllocHGlobal(CAPI.CRYPTOAPI_BLOB.Size);
                        Marshal.StructureToPtr(blob, pvFindPara.DangerousGetHandle(), false); 
                        break;
 
                    case X509FindType.FindBySubjectDistinguishedName: 
                        if (!(findValue is string))
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatch, findType, typeof(string), findValue.GetType()))); 

                        dwFindType = CAPI.CERT_FIND_ANY;
                        break;
 
                    case X509FindType.FindByIssuerName:
                        strFindValue = findValue as string; 
                        if (strFindValue == null) 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatch, findType, typeof(string), findValue.GetType())));
 
                        dwFindType = CAPI.CERT_FIND_ISSUER_STR;
                        pvFindPara = SafeHGlobalHandle.AllocHGlobal(strFindValue);
                        break;
 
                    case X509FindType.FindByIssuerDistinguishedName:
                        if (!(findValue is string)) 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatch, findType, typeof(string), findValue.GetType()))); 

                        dwFindType = CAPI.CERT_FIND_ANY; 
                        break;

                    case X509FindType.FindBySerialNumber:
                        bytes = findValue as byte[]; 
                        if (bytes == null)
                        { 
                            strFindValue = findValue as string; 
                            if (strFindValue == null)
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatchMulti, findType, typeof(string), typeof(byte[]), findValue.GetType()))); 

                            bytes = SecurityUtils.DecodeHexString(strFindValue);

                            // reverse bits 
                            int len = bytes.Length;
                            for (int i = 0, j = len - 1; i < bytes.Length / 2; ++i, --j) 
                            { 
                                byte tmp = bytes[i];
                                bytes[i] = bytes[j]; 
                                bytes[j] = tmp;
                            }
                        }
                        findValue = bytes; 
                        dwFindType = CAPI.CERT_FIND_ANY;
                        break; 
 
                    case X509FindType.FindBySubjectKeyIdentifier:
                        bytes = findValue as byte[]; 
                        if (bytes == null)
                        {
                            strFindValue = findValue as string;
                            if (strFindValue == null) 
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatchMulti, findType, typeof(string), typeof(byte[]), findValue.GetType())));
 
                            bytes = SecurityUtils.DecodeHexString(strFindValue); 

                        } 
                        findValue = bytes;
                        dwFindType = CAPI.CERT_FIND_ANY;
                        break;
 
                    default:
                        // Fallback to CLR implementation 
                        X509Store store = new X509Store(this.certStoreHandle.DangerousGetHandle()); 
                        try
                        { 
                            return store.Certificates.Find(findType, findValue, validOnly);
                        }
                        finally
                        { 
                            store.Close();
                        } 
                } 

#pragma warning suppress 56523 // We are not interested in CRYPT_E_NOT_FOUND error, it return null anyway. 
                pCertContext = CAPI.CertFindCertificateInStore(this.certStoreHandle,
                                                               CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
                                                               0,
                                                               dwFindType, 
                                                               pvFindPara,
                                                               pCertContext); 
 
                while (pCertContext != null && !pCertContext.IsInvalid)
                { 
                    X509Certificate2 cert;
                    if (TryGetMatchingX509Certificate(pCertContext.DangerousGetHandle(), findType,
                            dwFindType, findValue, validOnly, out cert))
                    { 
                        result.Add(cert);
                    } 
 
                    // CER
                    RuntimeHelpers.PrepareConstrainedRegions(); 
                    try { }
                    finally
                    {
                        // Suppress the finalizer 
#pragma warning suppress 56508 // CertFindCertificateInStore will release the prev one.
                        GC.SuppressFinalize(pCertContext); 
#pragma warning suppress 56523 // We are not interested in CRYPT_E_NOT_FOUND error, it return null anyway. 
                        pCertContext = CAPI.CertFindCertificateInStore(this.certStoreHandle,
                                                                       CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, 
                                                                       0,
                                                                       dwFindType,
                                                                       pvFindPara,
                                                                       pCertContext); 
                    }
                } 
            } 
            finally
            { 
                if (pCertContext != null)
                {
                    pCertContext.Close();
                } 
                pvFindPara.Close();
                pvTemp.Close(); 
            } 
            return result;
        } 

        bool TryGetMatchingX509Certificate(IntPtr certContext, X509FindType findType,
            uint dwFindType, object findValue, bool validOnly, out X509Certificate2 cert)
        { 
            cert = new X509Certificate2(certContext);
            if (dwFindType == CAPI.CERT_FIND_ANY) 
            { 
                switch (findType)
                { 
                    case X509FindType.FindBySubjectDistinguishedName:
                        if (0 != String.Compare((string)findValue, cert.SubjectName.Name, StringComparison.OrdinalIgnoreCase))
                        {
                            cert.Reset(); 
                            cert = null;
                            return false; 
                        } 
                        break;
 
                    case X509FindType.FindByIssuerDistinguishedName:
                        if (0 != String.Compare((string)findValue, cert.IssuerName.Name, StringComparison.OrdinalIgnoreCase))
                        {
                            cert.Reset(); 
                            cert = null;
                            return false; 
                        } 
                        break;
 
                    case X509FindType.FindBySerialNumber:
                        if (!BinaryMatches((byte[])findValue, cert.GetSerialNumber()))
                        {
                            cert.Reset(); 
                            cert = null;
                            return false; 
                        } 
                        break;
 
                    case X509FindType.FindBySubjectKeyIdentifier:
                        X509SubjectKeyIdentifierExtension skiExtension =
                            cert.Extensions[CAPI.SubjectKeyIdentifierOid] as X509SubjectKeyIdentifierExtension;
                        if (skiExtension == null || !BinaryMatches((byte[])findValue, skiExtension.RawData)) 
                        {
                            cert.Reset(); 
                            cert = null; 
                            return false;
                        } 
                        break;

                    default:
                        DiagnosticUtility.DebugAssert(findType + " is not supported!"); 
                        break;
                } 
            } 

            if (validOnly) 
            {
                X509Chain chain = new X509Chain(false);
                chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
                chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot; 
                if (!chain.Build(cert))
                { 
                    cert.Reset(); 
                    cert = null;
                    return false; 
                }
            }
            return cert != null;
        } 

        bool BinaryMatches(byte[] src, byte[] dst) 
        { 
            if (src.Length != dst.Length)
                return false; 

            for (int i = 0; i < src.Length; ++i)
            {
                if (src[i] != dst[i]) 
                    return false;
            } 
            return true; 
        }
 
        // this method maps X509Store OpenFlags to a combination of crypto API flags
        uint MapX509StoreFlags(StoreLocation storeLocation, OpenFlags flags)
        {
            uint dwFlags = 0; 
            uint openMode = ((uint)flags) & 0x3;
            switch (openMode) 
            { 
                case (uint)OpenFlags.ReadOnly:
                    dwFlags |= CAPI.CERT_STORE_READONLY_FLAG; 
                    break;
                case (uint)OpenFlags.MaxAllowed:
                    dwFlags |= CAPI.CERT_STORE_MAXIMUM_ALLOWED_FLAG;
                    break; 
            }
 
            if ((flags & OpenFlags.OpenExistingOnly) == OpenFlags.OpenExistingOnly) 
                dwFlags |= CAPI.CERT_STORE_OPEN_EXISTING_FLAG;
            if ((flags & OpenFlags.IncludeArchived) == OpenFlags.IncludeArchived) 
                dwFlags |= CAPI.CERT_STORE_ENUM_ARCHIVED_FLAG;

            if (storeLocation == StoreLocation.LocalMachine)
                dwFlags |= CAPI.CERT_SYSTEM_STORE_LOCAL_MACHINE; 
            else if (storeLocation == StoreLocation.CurrentUser)
                dwFlags |= CAPI.CERT_SYSTEM_STORE_CURRENT_USER; 
 
            return dwFlags;
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK