private static void AddX509Names(SafeX509NameStackHandle nameStack, StoreLocation storeLocation, HashSet <string> issuerNameHashSet) { using (var store = new X509Store(StoreName.Root, storeLocation)) { store.Open(OpenFlags.ReadOnly); foreach (var certificate in store.Certificates) { //Check if issuer name is already present //Avoiding duplicate names if (!issuerNameHashSet.Add(certificate.Issuer)) { continue; } using (SafeX509Handle certHandle = Crypto.X509Duplicate(certificate.Handle)) { using (SafeX509NameHandle nameHandle = Crypto.DuplicateX509Name(Crypto.X509GetIssuerName(certHandle))) { if (Crypto.PushX509NameStackField(nameStack, nameHandle)) { // The handle ownership has been transferred into the STACK_OF(X509_NAME). nameHandle.SetHandleAsInvalid(); } else { throw new CryptographicException(SR.net_ssl_x509Name_push_failed_error); } } } } } }
private static void UpdateCAListFromRootStore(SafeSslContextHandle context) { using (SafeX509NameStackHandle nameStack = Crypto.NewX509NameStack()) { //maintaining the HashSet of Certificate's issuer name to keep track of duplicates HashSet <string> issuerNameHashSet = new HashSet <string>(); //Enumerate Certificates from LocalMachine and CurrentUser root store AddX509Names(nameStack, StoreLocation.LocalMachine, issuerNameHashSet); AddX509Names(nameStack, StoreLocation.CurrentUser, issuerNameHashSet); Ssl.SslCtxSetClientCAList(context, nameStack); // The handle ownership has been transferred into the CTX. nameStack.SetHandleAsInvalid(); } }
internal static extern bool PushX509NameStackField(SafeX509NameStackHandle stack, SafeX509NameHandle x509_Name);
internal static extern void SslCtxSetClientCAList(SafeSslContextHandle ctx, SafeX509NameStackHandle x509NameStackPtr);
internal static extern void SSL_CTX_set_client_CA_list(SafeSslContextHandle ctx, SafeX509NameStackHandle x509NameStackPtr);