Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline EgorOkhotin  
#1 Оставлено : 20 июня 2019 г. 15:49:19(UTC)
EgorOkhotin

Статус: Активный участник

Группы: Участники
Зарегистрирован: 13.06.2019(UTC)
Сообщений: 30
Российская Федерация
Откуда: Самара

Сказал(а) «Спасибо»: 4 раз
Есть задача получить список сертификтов и связанных с ними имена контейнеров.
Можно запросить certmgr для просмотра сертификатов и распарсить вывод но это костыль. У меня вопрос как сделать через p/invoke данную задачу и возможно ли это?
Пишу под .NET Core 2.1

Отредактировано пользователем 28 июня 2019 г. 8:49:48(UTC)  | Причина: точно указал платформу

Offline EgorOkhotin  
#2 Оставлено : 21 июня 2019 г. 9:16:00(UTC)
EgorOkhotin

Статус: Активный участник

Группы: Участники
Зарегистрирован: 13.06.2019(UTC)
Сообщений: 30
Российская Федерация
Откуда: Самара

Сказал(а) «Спасибо»: 4 раз
Нашел как через P/Invoke сделать вызов информации по сертификатам но вылетает access violation exception. Не совсем понимаю по чему.

Код:

 [DllImport("CRYPT32.DLL", SetLastError = true)]
        public static extern IntPtr CertOpenStore(
            uint lpszStoreProvider,
            uint dwEncodingType,
            IntPtr hCryptProv, //HCRYPTPROV_LEGACY
            uint dwFlags,
            String pvPara //const void*
            );

        [DllImport("CRYPT32.DLL", SetLastError = true)]
        public static extern CERT_CONTEXT CertEnumCertificatesInStore(
            [In]IntPtr hCertStore,
            [In]CERT_CONTEXT pPrevCertContext);

        [DllImport("CRYPT32.DLL", SetLastError = true, CharSet =CharSet.Auto)]
        public static extern uint CertGetNameString(
            [In]CERT_CONTEXT pCertContext,
            uint dwType,
            uint dvFlags,
            IntPtr pvTypePara,
            StringBuilder pszNameString,
            uint cchNameString);


Код:

            IntPtr hStoreHandle = IntPtr.Zero;
            CERT_CONTEXT pCertContext = new CERT_CONTEXT();
            var pszStoreName = ("My");
            var CERT_STORE_PROV_SYSTEM = 10U;
            var CERT_SYSTEM_STORE_CURRENT_USER = (uint)(1 << 16);

            hStoreHandle = CertOpenStore(
                CERT_STORE_PROV_SYSTEM,
                0,
                IntPtr.Zero,
                CERT_SYSTEM_STORE_CURRENT_USER,
                pszStoreName);

            var cchNameString = 256U;
            var pszNameString = new StringBuilder((int)cchNameString);
            var list = new List<uint>();
            do
            {
                pCertContext = CertEnumCertificatesInStore(hStoreHandle, pCertContext);
                
                var chars = CertGetNameString(
                    pCertContext,
                    CERT_NAME_SIMPLE_DISPLAY_TYPE,
                    0,
                    IntPtr.Zero,
                    pszNameString,
                    cchNameString);

                list.Add(chars);

            } while (!pCertContext.Equals(default(CERT_CONTEXT)));


Аccess Violation вылетает при попытке получить имя. Я пробовал разные флаги передавать но он кидает эксепшн. Может кто помочь?

CertInfo из pCertContext содержит IssuerId но не содержит указател на Issuer(он равен 0 остается).

Отредактировано пользователем 21 июня 2019 г. 9:21:24(UTC)  | Причина: Информация о CertInfo

Offline Андрей Писарев  
#3 Оставлено : 21 июня 2019 г. 9:43:42(UTC)
Андрей *

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 12,727
Мужчина
Российская Федерация

Сказал «Спасибо»: 501 раз
Поблагодарили: 2058 раз в 1598 постах
Здравствуйте.


Цитата:

CERT_KEY_PROV_INFO_PROP_ID = 2;

Certificate: PCCERT_CONTEXT;

KeyInfo: PCRYPT_KEY_PROV_INFO;
...
CertGetCertificateContextProperty(Certificate, CERT_KEY_PROV_INFO_PROP_ID, nil, pcbData)
выделить память для KeyInfo
CertGetCertificateContextProperty(Certificate, CERT_KEY_PROV_INFO_PROP_ID, KeyInfo, pcbData)
ProvName := KeyInfo.pwszProvName;
ProvType := KeyInfo.dwProvType;
ContainerName := KeyInfo.pwszContainerName;
освободить память KeyInfo
Техническую поддержку оказываем тут
Наша база знаний
Offline EgorOkhotin  
#4 Оставлено : 21 июня 2019 г. 10:42:34(UTC)
EgorOkhotin

Статус: Активный участник

Группы: Участники
Зарегистрирован: 13.06.2019(UTC)
Сообщений: 30
Российская Федерация
Откуда: Самара

Сказал(а) «Спасибо»: 4 раз
Автор: Андрей Писарев Перейти к цитате
Здравствуйте.


Цитата:

CERT_KEY_PROV_INFO_PROP_ID = 2;

Certificate: PCCERT_CONTEXT;

KeyInfo: PCRYPT_KEY_PROV_INFO;
...
CertGetCertificateContextProperty(Certificate, CERT_KEY_PROV_INFO_PROP_ID, nil, pcbData)
выделить память для KeyInfo
CertGetCertificateContextProperty(Certificate, CERT_KEY_PROV_INFO_PROP_ID, KeyInfo, pcbData)
ProvName := KeyInfo.pwszProvName;
ProvType := KeyInfo.dwProvType;
ContainerName := KeyInfo.pwszContainerName;
освободить память KeyInfo


CertGetCertificateContextProperty кидает AccessViolation.

Код:

                var pcbData = 0U;
                var ptr = IntPtr.Zero;

                pCertContext = CertEnumCertificatesInStore(hStoreHandle, pCertContext);

                CertGetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, ptr, ref pcbData);
Offline two_oceans  
#5 Оставлено : 21 июня 2019 г. 11:49:09(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 05.03.2015(UTC)
Сообщений: 1,602
Российская Федерация
Откуда: Иркутская область

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 394 раз в 366 постах
Что-то я подозреваю такую схему: У Вас проверка pСertContext только в самом цикле, после перечисления всех сертификатов функция CertEnumCertificatesInStore возвращает nil как признак что все закончилось, но Вы без проверки на nil передаете полученное на получение имени или на получение свойства контекста, тут и вылетает исключение доступа к nil. Исправить легко - добавьте проверку на не nil перед действиями с pCertContext.

Отредактировано пользователем 21 июня 2019 г. 11:50:27(UTC)  | Причина: Не указана

thanks 1 пользователь поблагодарил two_oceans за этот пост.
EgorOkhotin оставлено 21.06.2019(UTC)
Offline EgorOkhotin  
#6 Оставлено : 21 июня 2019 г. 13:19:03(UTC)
EgorOkhotin

Статус: Активный участник

Группы: Участники
Зарегистрирован: 13.06.2019(UTC)
Сообщений: 30
Российская Федерация
Откуда: Самара

Сказал(а) «Спасибо»: 4 раз
Автор: two_oceans Перейти к цитате
Что-то я подозреваю такую схему: У Вас проверка pСertContext только в самом цикле, после перечисления всех сертификатов функция CertEnumCertificatesInStore возвращает nil как признак что все закончилось, но Вы без проверки на nil передаете полученное на получение имени или на получение свойства контекста, тут и вылетает исключение доступа к nil. Исправить легко - добавьте проверку на не nil перед действиями с pCertContext.


Спасибо, разобрался. Но есть последняя загвоздка. На Линукс машине некорректныйй вывод. Есть идеи? linuxOutput.png (15kb) загружен 14 раз(а).
Offline two_oceans  
#7 Оставлено : 21 июня 2019 г. 13:33:42(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 05.03.2015(UTC)
Сообщений: 1,602
Российская Федерация
Откуда: Иркутская область

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 394 раз в 366 постах
Выглядит как первая буква каждого имени.. идеи: 1) возможно дело в вариациях A W функций (когда не юникод-программа получает юникод данные для вывода в консоль); 2) неправильно выставлена длина строки (возвращается CertGetNameString).
Offline EgorOkhotin  
#8 Оставлено : 21 июня 2019 г. 14:58:13(UTC)
EgorOkhotin

Статус: Активный участник

Группы: Участники
Зарегистрирован: 13.06.2019(UTC)
Сообщений: 30
Российская Федерация
Откуда: Самара

Сказал(а) «Спасибо»: 4 раз
Автор: two_oceans Перейти к цитате
Выглядит как первая буква каждого имени.. идеи: 1) возможно дело в вариациях A W функций (когда не юникод-программа получает юникод данные для вывода в консоль); 2) неправильно выставлена длина строки (возвращается CertGetNameString).


Проблема решена. В Windows используется Unicode а в Linux(проверял на CentOS 7) UTF32
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.