Update 05.12.2009: разработчики подтвердили баг в ICertAdmin2 интерфейсе. Проблема заключается в том, что после первого запроса указанных PropID они кешируются и при смене контекста конфигурации (Certification Authority), этот кеш не очищается.
Прежде чем продолжать исследование CryptoAPI COM интерфейсов, предлагаю посмотреть несколько полезных ссылок и поговорить о багах в интерфейсе ICertAdmin2.
При использовании интерфейса ICertAdmin2, ICertRequest2D (этот интерфейс мы ещё посмотрим в будущих постах) мы используем различные аргументы для получения свойст CA с использованием метода GetCAProerty(). И вот их где мы можем получить числовые значения этих аргументов:
А теперь поговорим о багах. Как выяснилось, ICertAdmin2::GetCAProperty(), который определён в библиотеке certadm.dll имеет баги с PropID, которые связаны с количественной информацией. Будь то количество сертификатов CA, количество агентов восстановления ключей (Key Recovery Agents) и т.д. И вот в чём это выражается:
Мы будем получать данные как с локального CA, так и с удалённого CA запуская код с каждого сервера. Кратко об используемых PropID:
И вот какие результаты мы видим, когда собираем эти свойства с сервера DC1:
[Administrator] # создаём COM объек: [Administrator] $CertAdmin = New-Object -com CertificateAuthority.Admin.1 [Administrator] # получаем список сертификатов CA на локальном серве [Administrator] # мы видим 2 сертификата, как положено [Administrator] $certadmin.GetCAProperty("dc1\contoso ca",0xb,0,1,0) 2 [Administrator] # и он то же самое показывает и для удалённого сервера, хотя там всего 1 сертификат [Administrator] $certadmin.GetCAProperty("dc2\contoso-dc2-ca",0xb,0,1,0) 2 [Administrator] # ладно, смотрим, сколько всего KRA у нас на локальном сервере. Их 1, как на самом деле [Administrator] $certadmin.GetCAProperty("dc1\contoso ca",0x19,0,1,0) 1 [Administrator] # используемых сертификатов тоже 1. [Administrator] $certadmin.GetCAProperty("dc1\contoso ca",0x18,0,1,0) 1 [Administrator] # как я уже говорил, на DC2 нет агентов восстановления, хотя метод показывает их по одному в обоих случаях [Administrator] $certadmin.GetCAProperty("dc2\contoso-dc2-ca",0x19,0,1,0) 1 [Administrator] $certadmin.GetCAProperty("dc2\contoso-dc2-ca",0x18,0,1,0) 1 [Administrator]
собираем ту же информацию, запуская код с сервера DC2:
PS C:\> # создаём COM объект: PS C:\> $CertAdmin = New-Object -com CertificateAuthority.Admin.1 PS C:\> # получаем список сертификатов CA с локального сервера. PS C:\> # их мы видим ровно 1, как и должно быть PS C:\> $certadmin.GetCAProperty("dc2\contoso-dc2-ca",0xb,0,1,0) 1 PS C:\> # в предыдущем примере мы видели, что на DC1 2 сертификата CA. PS C:\> # проверим, так ли это? PS C:\> $certadmin.GetCAProperty("dc1\contoso ca",0xb,0,1,0) 1 PS C:\> # wow! обломс, метод возвращает тоже 1. А сколько у нас агентов восстановления? PS C:\> # и снова облом. На сервере DC1 нет агентов восстановления (хотя предыдущий пример говорит об обратном): PS C:\> $certadmin.GetCAProperty("dc1\contoso ca",0x19,0,1,0) 0 PS C:\> $certadmin.GetCAProperty("dc1\contoso ca",0x18,0,1,0) 0
а теперь посмотрим на результаты с использованием того же метода и тех же PropID, но с использованием интерфейса ICertRequest, который определён в библиотеке certcli.dll. Те же тесты уже возвращают правильные результаты:
с DC1:
[Administrator] $request = New-Object -com CertificateAuthority.Request.1 [Administrator] $request.GetCAProperty("dc1\contoso ca",0xb,0,1,0) 2 [Administrator] $request.GetCAProperty("dc2\contoso-dc2-ca",0xb,0,1,0) 1 [Administrator] $request.GetCAProperty("dc1\contoso ca",0x19,0,1,0) 1 [Administrator] $request.GetCAProperty("dc1\contoso ca",0x18,0,1,0) 1 [Administrator] $request.GetCAProperty("dc2\contoso-dc2-ca",0x19,0,1,0) 0 [Administrator] $request.GetCAProperty("dc2\contoso-dc2-ca",0x18,0,1,0) 0 [Administrator]
с DC2:
PS C:\> $request = New-Object -com CertificateAuthority.Request.1 PS C:\> $request.GetCAProperty("dc2\contoso-dc2-ca",0xb,0,1,0) 1 PS C:\> $request.GetCAProperty("dc1\contoso ca",0xb,0,1,0) 2 PS C:\> $request.GetCAProperty("dc1\contoso ca",0x19,0,1,0) 1 PS C:\> $request.GetCAProperty("dc1\contoso ca",0x18,0,1,0) 1 PS C:\> $request.GetCAProperty("dc2\contoso-dc2-ca",0x19,0,1,0) 0 PS C:\> $request.GetCAProperty("dc2\contoso-dc2-ca",0x18,0,1,0) 0 PS C:\>
Поэтому следует с осторожностью относиться к выводу ICertAdmin2::GetCAProperty(), а ещё лучше — использовать этот метод, который реализован в интерфейсе ICertRequest::GetCAProperty(). Чем это вызвано я пока не знаю, но задал я задал вопрос нужным людям, поэтому я дам знать в случае ответа на вопрос.
Comments: