locked
Enumerate X509Store? RRS feed

  • Question

  • Hi,

    is there a way to enumerate the x509Store Object?

    I want to access the MS-Keystore like this:

    store = new X509Store(StoreLocation.CurrentUser);

    So it should detect all keystore inside the CurrentUser Location. This should the default keystores like:AdressBook, AuthRoot, CertificateAuthority, Disallowed, My, Root, TrustedPeople, TrustedPublisher.

    But on my Keystore for example are these two more Keystores: exampleKeystore (which i have created) and Active Directory User-Object Keystore. I know i can access them like this:

    store = new X509Store("exampleKeystore", StoreLocation.CurrentUser);

    But i want to enumerate these, because maybe i don't know which Keystore an other User has. So i want a Code like this:

    foreach x509Store in store { print storeName }
    I don't found any solution for this problem. Hope someone could help me!

    Tuesday, December 2, 2014 6:21 PM

All replies

  • Tuesday, December 2, 2014 6:28 PM
  • Thanks for help. But how can i use these functions in C#? There all the code is C++.
    Tuesday, December 2, 2014 6:30 PM
  • You can loop through the enumerations present in the System.Security.Cryptography.X509Certificates to check all the default store names of the default store locations. I'm not aware of anything that will enumerate everything in managed code only. You can always P/Invoke the methods mentioned or use C++/CLI to expose managed results from them.
    Tuesday, December 2, 2014 6:37 PM
  • ok i will take a look at P/invoke. Thanks!
    Tuesday, December 2, 2014 9:49 PM
  • Can you post your code for creating two new keystores here ? I think the problem must come from these keystores.
    Wednesday, December 3, 2014 2:00 PM
  • Can you post your code for creating two new keystores here ? I think the problem must come from these keystores.
    I did it that way.
    X509Store store = new X509Store ("teststore", StoreLocation.CurrentUser);
    store.Open(OpenFlags.ReadWrite);
    store.Cose();
    After this i see the keystore "teststore" in my keystores (when i run certmgr.msc)

    Wednesday, December 3, 2014 2:07 PM
  • no one an idea??
    Monday, December 8, 2014 12:27 PM
  • You need to the use APIs that I posted in my original answer to accomplish what you're wanting to accomplish.
    Monday, December 8, 2014 2:03 PM
  • sorry my fault. i was a little bit onfused. i tried the C code from above and it works like i want it. i tried to run this code in C# with p/invoke, too - but i did get i run. I'm not good in C and don't know how to run it all in C# with p/invoke. i watched some infos but they all on other issues and so it's hard for me to match the stuff from C in C#..

    an other opton is not possible to enumerate to all keystores in C#?

    • Edited by Opa114 Monday, December 8, 2014 3:25 PM
    Monday, December 8, 2014 3:08 PM
  • I don't see an example of this elsewhere on the internet, so I'll post a translation of the sample for you when I get time.
    Monday, December 8, 2014 3:45 PM
  • yes i don't see any example, too.

    So thank you very very much for the translation from you. Hope this will help me a lot.

    Monday, December 8, 2014 3:57 PM
  • This code doesn't cover everything needed for relocated store and thus is less flexible than the C sample, but I thought it worthwhile to reduce some of the complexity. I did include additional generally useful examples that would assist with implementing the rest to do relocated store if you wanted to do so such as how to declare the P/Invoke functions with overloads and marshal a structure too complex to do with just attribute tags.

    Hope this helps you and whomever else may need this in the future:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Security.Cryptography.X509Certificates;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace X509StoresFullEnumeration
    {
    
        class StoreHelper
        {
            const int FALSE = 0;
    
            const int TRUE = 1;
    
            static UIntPtr HKEY_CURRENT_USER
            {
                 get  
                {
                    return new UIntPtr((long)0x80000001);
                }
            }
    
            #region Structure Definitions
            //This is too complicated to make as a structure that marshal will understand by itself
            class CertPhysicalStoreInfo
            {
                private CertPhysicalStoreInfo1 part1;
                private CertPhysicalStoreInfo2 part2;
                private byte[] blob;
    
                [StructLayout(LayoutKind.Sequential)]
                struct CertPhysicalStoreInfo1
                {
                    public int Size;
                    [MarshalAs(UnmanagedType.LPWStr)]
                    public string StoreProvider;
                    public int EncodingType;
                    public int OpenFlags;
                    public int BlobSize;
                }
                
                [StructLayout(LayoutKind.Sequential)]
                struct CertPhysicalStoreInfo2
                {
                    public int Flags;
                    public int Priority;
                }
    
                public int Size
                {
                    get
                    {
                        return Marshal.SizeOf(part1) + Marshal.SizeOf(part2) + part1.BlobSize;
                    }
                }
    
                public string StoreProvider
                {
                    get
                    {
                        return part1.StoreProvider;
                    }
                    set
                    {
                        part1.StoreProvider = value;
                    }
                }
    
                public int EncodingType
                {
                    get
                    {
                        return part1.EncodingType;
                    }
                    set
                    {
                        part1.EncodingType = value;
                    }
                }
    
                public int OpenFlags
                {
                    get
                    {
                        return part1.OpenFlags;
                    }
                    set
                    {
                        part1.OpenFlags = value;
                    }
                }
    
                public int BlobSize
                {
                    get
                    {
                        return part1.BlobSize;
                    }
                    set
                    {
                        if(blob == null || part1.BlobSize != value)
                        {
                            blob = new byte[value];
                        }
                        part1.BlobSize = value;
                    }
                }
    
                public int Flags
                {
                    get
                    {
                        return part2.Flags;
                    }
                    set
                    {
                        part2.Flags = value;
                    }
                }
    
                public int Priority
                {
                    get
                    {
                        return part2.Priority;
                    }
                    set
                    {
                        part2.Priority = value;
                    }
                }
    
                public CertPhysicalStoreInfo(IntPtr store)
                {
                    part1 = (CertPhysicalStoreInfo1)Marshal.PtrToStructure(store, typeof(CertPhysicalStoreInfo1));
                    IntPtr tmpPointer = IntPtr.Add(store, Marshal.SizeOf(part1));
                    if(part1.BlobSize > 0)
                    {
                        blob = new byte[part1.BlobSize];
                        Marshal.Copy(tmpPointer, blob, 0, part1.BlobSize);
                    }
                    else
                    {
                        blob = new byte[0];
                    }
                    tmpPointer = IntPtr.Add(tmpPointer, part1.BlobSize);
                    part2 = (CertPhysicalStoreInfo2)Marshal.PtrToStructure(tmpPointer, typeof(CertPhysicalStoreInfo2));
                }
    
                public IntPtr CommitToHGlobalThatNeedsToBeFreed()
                {
                   IntPtr hGlobalStructure =  Marshal.AllocHGlobal(part1.Size);
                   part1.Size = Size;
                   Marshal.StructureToPtr(part1, hGlobalStructure, false);
                   IntPtr tempStructure = IntPtr.Add(hGlobalStructure, Marshal.SizeOf(part1));
                   if(part1.BlobSize > 0)
                   {
                       if (blob != null && blob.Length == part1.BlobSize)
                       {
                           Marshal.Copy(blob, 0, tempStructure, part1.BlobSize);
                       }
                   }
                   tempStructure = IntPtr.Add(tempStructure, part1.BlobSize);
                   Marshal.StructureToPtr(part2, tempStructure, false);
                   return hGlobalStructure;
                }
    
            }
    
            [StructLayout(LayoutKind.Sequential)]
            struct CERT_SYSTEM_STORE_RELOCATE_PARA
            {
                public IntPtr RegistryKey;
                public IntPtr StoreLocation;
            }
            
            [StructLayout(LayoutKind.Sequential)]
            struct CERT_SYSTEM_STORE_INFO
            {
                public int Size;
            }
            #endregion
            #region No argument required definitions - FYI
            delegate int EnumPhyCallback(IntPtr systemStore,
                int flags,
                [MarshalAs(UnmanagedType.LPWStr)]
                string storeName,
                IntPtr storeInfo,
                IntPtr reserved,
                IntPtr userArg);
    
            delegate int EnumStoreCallback(IntPtr systemStore,
                int flags,
                IntPtr storeInfo,
                IntPtr reserved,
                IntPtr userArg);
    
            delegate int EnumLocCallback(
                [MarshalAs(UnmanagedType.LPWStr)]
                string storeLocation,
                int flags,
                IntPtr reserved,
                IntPtr userArg);
            
            [DllImport("Crypt32", CharSet=CharSet.Unicode, SetLastError=true)]
    static extern int CertEnumSystemStore(
      int Flags,
      IntPtr SystemStoreLocationPara,
      IntPtr userArg,
      EnumStoreCallback callback
    );
            [DllImport("Crypt32", CharSet = CharSet.Unicode, SetLastError = true)]
            static extern int CertEnumSystemStoreLocation(
              int Flags,
              IntPtr userArg,
              EnumLocCallback callback
            );
    
            [DllImport("Crypt32", CharSet = CharSet.Unicode, SetLastError = true)]
            static extern int CertEnumPhysicalStore(
              IntPtr SystemStore,
              int Flags,
              IntPtr userArg,
              EnumPhyCallback callback
            );
    
            [DllImport("Crypt32", CharSet = CharSet.Unicode, SetLastError = true)]
            static extern int CertEnumPhysicalStore(
              [MarshalAs(UnmanagedType.LPWStr)]
                string SystemStore,
              int Flags,
              IntPtr userArg,
              EnumPhyCallback callback
            );
    
            #endregion
    
            #region Array list argument definitions
            delegate int EnumPhyCallbackWithArrayList(IntPtr systemStore,
                int flags,
                [MarshalAs(UnmanagedType.LPWStr)]
                string storeName,
                IntPtr storeInfo,
                IntPtr reserved,
                ArrayList userArg);
    
            delegate int EnumStoreCallbackWithArrayList(IntPtr systemStore,
                int flags,
                IntPtr storeInfo,
                IntPtr reserved,
                ArrayList userArg);
    
            delegate int EnumLocCallbackWithArrayList(
                [MarshalAs(UnmanagedType.LPWStr)]
                string storeLocation,
                int flags,
                IntPtr reserved,
                ArrayList userArg);
    
            [DllImport("Crypt32", CharSet = CharSet.Unicode, SetLastError = true)]
            static extern int CertEnumSystemStore(
              int Flags,
              IntPtr SystemStoreLocationPara,
              ArrayList userArg,
              EnumStoreCallbackWithArrayList callback
            );
    
            [DllImport("Crypt32", CharSet = CharSet.Unicode, SetLastError = true)]
            static extern int CertEnumSystemStore(
              int Flags,
              [MarshalAs(UnmanagedType.LPWStr)]
                string SystemStoreLocationPara,
              ArrayList userArg,
              EnumStoreCallbackWithArrayList callback
            );
    
            [DllImport("Crypt32", CharSet = CharSet.Unicode, SetLastError = true)]
            static extern int CertEnumSystemStoreLocation(
              int Flags,
              ArrayList userArg,
              EnumLocCallbackWithArrayList callback
            );
    
            [DllImport("Crypt32", CharSet = CharSet.Unicode, SetLastError = true)]
            static extern int CertEnumPhysicalStore(
              IntPtr SystemStore,
              int Flags,
              ArrayList userArg,
              EnumPhyCallbackWithArrayList callback
            );
    
            [DllImport("Crypt32", CharSet = CharSet.Unicode, SetLastError = true)]
            static extern int CertEnumPhysicalStore(
              [MarshalAs(UnmanagedType.LPWStr)]
                string SystemStore,
              int Flags,
              ArrayList userArg,
              EnumPhyCallbackWithArrayList callback
            );
    
            #endregion
    
            #region Reimplemented Helper Functions
            bool TryGetSystemName(IntPtr systemStore, int flags, out string SystemName)
            {
                SystemName = string.Empty;
                if (systemStore == IntPtr.Zero) return false;
                    if(flags < 0)
                    {
                       CERT_SYSTEM_STORE_RELOCATE_PARA cssrp =  (CERT_SYSTEM_STORE_RELOCATE_PARA)Marshal.PtrToStructure(systemStore, typeof(CERT_SYSTEM_STORE_RELOCATE_PARA));
                       SystemName = Marshal.PtrToStringUni(cssrp.StoreLocation);
                       return true;
                    }
                    else
                    {
                        SystemName = Marshal.PtrToStringUni(systemStore);
                        return true;
                    }
            }
    
            #endregion
            int MyEnumLocCallbackWithArrayList(
                string storeLocation,
                int flags,
                IntPtr reserved,
                ArrayList userArg)
             {
                 Console.WriteLine("Location: {0} \t\t 0x{1}", storeLocation, flags.ToString("X"));
                switch(flags)
                {
    
                    case 0x20000: //Local Machine
                    case 0x80000: //LocalMachineGroupPolicy
                    case 0x10000: //Current User
                    case 0x40000: //Current Service
                    case 0x70000: //CurrentUserGroupPolicy
                    case 0x90000: //LocalMachineEnterprise
                        CertEnumSystemStore(flags, IntPtr.Zero, userArg, MyEnumStoreCallbackWithArrayList);
                
                        break;
                    case 0x50000: //Services
                    case 0x60000: //Users
    
                    default:
                 CertEnumSystemStore(flags, storeLocation, userArg, MyEnumStoreCallbackWithArrayList);
                 break; 
                }
                return TRUE;
             }
    
            int MyEnumStoreCallbackWithArrayList(IntPtr systemStore,
                int flags,
                IntPtr storeInfo,
                IntPtr reserved,
                ArrayList userArg)
             {
                 Console.WriteLine("\tStore Name: {0}", Marshal.PtrToStringUni(systemStore));
                if(CertEnumPhysicalStore(systemStore, flags, userArg, MyEnumPhyCallbackWithArrayList) == 0)
                {
                    Exception ex = Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error( ));
                    Console.WriteLine(ex.ToString( ));
                }
                return TRUE;
             }
    
            int MyEnumPhyCallbackWithArrayList(IntPtr systemStore,
                int flags,
                string storeName,
                IntPtr storeInfo,
                IntPtr reserved,
                ArrayList userArg)
            {
                string systemName;
                if (TryGetSystemName(systemStore, flags, out systemName)) userArg.Add(new Tuple<string,string>(storeName, systemName));
                return TRUE;
            }
    
    
            ArrayList PhysicalStores
            {
                get
                {
                    ArrayList al = new ArrayList( );
                    CertEnumSystemStoreLocation(0, al, MyEnumLocCallbackWithArrayList);
                    return al;
                }
            }
            
            public static Dictionary<string,HashSet<string>> SortedPhysicalStores
            {
                get
                {
                    Dictionary<string, HashSet<string>> dic = new Dictionary<string, HashSet<string>>( );
                    StoreHelper s = new StoreHelper( );
                    foreach(Tuple<string,string> t in s.PhysicalStores)
                    {
                        if(!dic.ContainsKey(t.Item1))
                        {
                            dic.Add(t.Item1, new HashSet<string>( ));
                        }
                        dic[t.Item1].Add(t.Item2);
                    }
                    return dic;
                }
            }
    
        }
        class Program
        {
    
            static void Main(string[] args)
            {
                var dic = StoreHelper.SortedPhysicalStores;
                foreach(string key in dic.Keys)
                {
                    Console.WriteLine("{0}:", key);
                    foreach(string val in dic[key])
                    {
                        Console.WriteLine("\t{0}", val);
                    }
                    Console.WriteLine( );
                }
                if (System.Diagnostics.Debugger.IsAttached)
                {
                    Console.ReadLine( );
                }
            }
        }
    }
    

    Monday, December 8, 2014 6:21 PM
  • Thank you for the coee example in C#. i will take a deeper on look on this. Hope i understand all the things there - look a little bit complex but i will try. Thanks!
    Tuesday, December 9, 2014 12:28 PM