示例#1
0
        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);
                            }
                        }
                    }
                }
            }
        }
示例#2
0
        internal static unsafe string X500DistinguishedNameDecode(byte[] encodedDistinguishedName, OpenSslX09NameFormatFlags nativeFlags)
        {
            using (SafeX509NameHandle x509Name = Interop.libcrypto.OpenSslD2I(Interop.libcrypto.d2i_X509_NAME, encodedDistinguishedName))
            {
                Interop.libcrypto.CheckValidOpenSslHandle(x509Name);

                using (SafeBioHandle bioHandle = Interop.libcrypto.BIO_new(Interop.libcrypto.BIO_s_mem()))
                {
                    Interop.libcrypto.CheckValidOpenSslHandle(bioHandle);

                    int written = Interop.libcrypto.X509_NAME_print_ex(
                        bioHandle,
                        x509Name,
                        0,
                        new UIntPtr((uint)nativeFlags));

                    // X509_NAME_print_ex returns how many bytes were written into the buffer.
                    // BIO_gets wants to ensure that the response is NULL-terminated.
                    // So add one to leave space for the NULL.
                    StringBuilder builder = new StringBuilder(written + 1);
                    int           read    = Interop.libcrypto.BIO_gets(bioHandle, builder, builder.Capacity);

                    if (read < 0)
                    {
                        throw Interop.libcrypto.CreateOpenSslCryptographicException();
                    }

                    return(builder.ToString());
                }
            }
        }
示例#3
0
        internal static SafeSharedX509NameEntryHandle GetX509NameEntry(SafeX509NameHandle x509Name, int loc)
        {
            CheckValidOpenSslHandle(x509Name);

            return(SafeInteriorHandle.OpenInteriorHandle(
                       (nameHandle, i) => GetX509NameEntry_private(nameHandle, i),
                       x509Name,
                       loc));
        }
示例#4
0
        internal static SafeSharedX509NameEntryHandle GetX509NameEntry(SafeX509NameHandle x509Name, int loc)
        {
            CheckValidOpenSslHandle(x509Name);

            SafeSharedX509NameEntryHandle handle = GetX509NameEntry_private(x509Name, loc);

            if (!handle.IsInvalid)
            {
                handle.SetParent(x509Name);
            }

            return(handle);
        }
示例#5
0
 internal static extern int X509_NAME_print_ex(SafeBioHandle @out, SafeX509NameHandle nm, int indent, NativeULong flags);
示例#6
0
 internal static extern int GetX509NameEntryCount(SafeX509NameHandle x509Name);
示例#7
0
 internal static extern bool PushX509NameStackField(SafeX509NameStackHandle stack, SafeX509NameHandle x509_Name);
示例#8
0
 private static extern SafeSharedX509NameEntryHandle GetX509NameEntry_private(SafeX509NameHandle x509Name, int loc);
示例#9
0
        internal static string X500DistinguishedNameDecode(
            byte[] encodedName,
            bool printOid,
            X500DistinguishedNameFlags flags)
        {
            bool   reverse       = (flags & X500DistinguishedNameFlags.Reversed) == X500DistinguishedNameFlags.Reversed;
            bool   quoteIfNeeded = (flags & X500DistinguishedNameFlags.DoNotUseQuotes) != X500DistinguishedNameFlags.DoNotUseQuotes;
            string dnSeparator;

            if ((flags & X500DistinguishedNameFlags.UseSemicolons) == X500DistinguishedNameFlags.UseSemicolons)
            {
                dnSeparator = "; ";
            }
            else if ((flags & X500DistinguishedNameFlags.UseNewLines) == X500DistinguishedNameFlags.UseNewLines)
            {
                dnSeparator = Environment.NewLine;
            }
            else
            {
                // This is matching Windows (native) behavior, UseCommas does not need to be asserted,
                // it is just what happens if neither UseSemicolons nor UseNewLines is specified.
                dnSeparator = ", ";
            }

            using (SafeX509NameHandle x509Name = Interop.Crypto.DecodeX509Name(encodedName, encodedName.Length))
            {
                if (x509Name.IsInvalid)
                {
                    return("");
                }

                // We need to allocate a StringBuilder to hold the data as we're building it, and there's the usual
                // arbitrary process of choosing a number that's "big enough" to minimize reallocations without wasting
                // too much space in the average case.
                //
                // So, let's look at an example of what our output might be.
                //
                // GitHub.com's SSL cert has a "pretty long" subject (partially due to the unknown OIDs):
                //   businessCategory=Private Organization
                //   1.3.6.1.4.1.311.60.2.1.3=US
                //   1.3.6.1.4.1.311.60.2.1.2=Delaware
                //   serialNumber=5157550
                //   street=548 4th Street
                //   postalCode=94107
                //   C=US
                //   ST=California
                //   L=San Francisco
                //   O=GitHub, Inc.
                //   CN=github.com
                //
                // Which comes out to 228 characters using OpenSSL's default pretty-print
                // (openssl x509 -in github.cer -text -noout)
                // Throw in some "maybe-I-need-to-quote-this" quotes, and a couple of extra/extra-long O/OU values
                // and round that up to the next programmer number, and you get that 512 should avoid reallocations
                // in all but the most dire of cases.
                StringBuilder decodedName  = new StringBuilder(512);
                int           entryCount   = Interop.Crypto.GetX509NameEntryCount(x509Name);
                bool          printSpacing = false;

                for (int i = 0; i < entryCount; i++)
                {
                    int loc = reverse ? entryCount - i - 1 : i;

                    using (SafeSharedX509NameEntryHandle nameEntry = Interop.Crypto.GetX509NameEntry(x509Name, loc))
                    {
                        Interop.Crypto.CheckValidOpenSslHandle(nameEntry);

                        string thisOidValue;

                        using (SafeSharedAsn1ObjectHandle oidHandle = Interop.Crypto.GetX509NameEntryOid(nameEntry))
                        {
                            thisOidValue = Interop.Crypto.GetOidValue(oidHandle);
                        }

                        if (printSpacing)
                        {
                            decodedName.Append(dnSeparator);
                        }
                        else
                        {
                            printSpacing = true;
                        }

                        if (printOid)
                        {
                            AppendOid(decodedName, thisOidValue);
                        }

                        string rdnValue;

                        using (SafeSharedAsn1StringHandle valueHandle = Interop.Crypto.GetX509NameEntryData(nameEntry))
                        {
                            rdnValue = Interop.Crypto.Asn1StringToManagedString(valueHandle);
                        }

                        bool quote = quoteIfNeeded && NeedsQuoting(rdnValue);

                        if (quote)
                        {
                            decodedName.Append('"');

                            // If the RDN itself had a quote within it, that quote needs to be escaped
                            // with another quote.
                            rdnValue = rdnValue.Replace("\"", "\"\"");
                        }

                        decodedName.Append(rdnValue);

                        if (quote)
                        {
                            decodedName.Append('"');
                        }
                    }
                }

                return(decodedName.ToString());
            }
        }