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: