Contents of this directory is archived and no longer updated.

Update 05.12.2009: разработчики подтвердили баг в ICertAdmin2 интерфейсе. Проблема заключается в том, что после первого запроса указанных PropID они кешируются и при смене контекста конфигурации (Certification Authority), этот кеш не очищается.


Прежде чем продолжать исследование CryptoAPI COM интерфейсов, предлагаю посмотреть несколько полезных ссылок и поговорить о багах в интерфейсе ICertAdmin2.

При использовании интерфейса ICertAdmin2, ICertRequest2D (этот интерфейс мы ещё посмотрим в будущих постах) мы используем различные аргументы для получения свойст CA с использованием метода GetCAProerty(). И вот их где мы можем получить числовые значения этих аргументов:

А теперь поговорим о багах. Как выяснилось, ICertAdmin2::GetCAProperty(), который определён в библиотеке certadm.dll имеет баги с PropID, которые связаны с количественной информацией. Будь то количество сертификатов CA, количество агентов восстановления ключей (Key Recovery Agents) и т.д. И вот в чём это выражается:

  • DC1 — корневой CA с именем Contoso CA. Имеет 2 сертификата CA и одного назначенного агента восстановления;
  • DC2 — подчинённый CA с именем Contoso-DC2-CA. Имеет 1 сертификат CA и ни одного назначенного агента восстановления.

Мы будем получать данные как с локального CA, так и с удалённого CA запуская код с каждого сервера. Кратко об используемых PropID:

  • 0x0B — количество сертификатов CA;
  • 0x19 — общее количество агентов восстановления на CA;
  • 0x18 — общее количество используемых агентов восстановления;

И вот какие результаты мы видим, когда собираем эти свойства с сервера 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(). Чем это вызвано я пока не знаю, но задал я задал вопрос нужным людям, поэтому я дам знать в случае ответа на вопрос.


Share this article:

Comments:

Comments are closed.