Few days ago someone asked me how to programmatically test whether CA server is online, and which interfaces (both administration — ICertAdmin and/or enrollment — ICertRequest) are available.

At first, I want to mention that you can use the following CMD commands:

certutil –ping

Pings certificate management (ICertAdmin) and enrollment (ICertRequest) interfaces. Optionally you can ping remote CA interfaces: certutil –config CAHostName\CAName –ping

What if you want to do this programmatically? Nice question! Looking to CryptoAPI reference you can find the following methods: ICertAdminD::Ping and ICertRequestD::Ping methods. However, local COM interfaces does not support these methods. Workarounds? PowerShell has workaround! Here is a simple code example, that tests CA and interface availability:

function Test-CAOnline {
[CmdletBinding()]
    param(
        [Parameter(Position = 0)]
        [string]$Config,
        [switch]$ShowUI
    )
$signature = @"
[DllImport("Certadm.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool CertSrvIsServerOnline(
    string pwszServerName,
    ref bool pfServerOnline
);
"@
    Add-Type -MemberDefinition $signature -Namespace CryptoAPI -Name CertAdm
    $CertConfig = New-Object -ComObject CertificateAuthority.Config
    if ($Config -ne "" -and !$Config.Contains("\")) {
        Write-Error -Category InvalidArgument -ErrorId InvalidArgumentException `

        -Message "Config string must be passed in 'CAHostName\CAName' form."
        break
    } elseif ($Config -eq "" -and !$ShowUI) {
        try {$Config = $CertConfig.GetConfig(0x3)}
        catch {
            Write-Error -Category ObjectNotFound -ErrorId ObjectNotFoundElement `

            -Message "Certificate Services are not installed on local computer."
            break
        }
    } elseif ($Config -eq "" -and $ShowUI) {
        $Config = $CertConfig.GetConfig(0x1)
    }
    if ($Config) {
        [void]($Config -match "(.+)\\(.+)")
        $Server = $matches[1]
        $CAName = $matches[2]
        $ServerStatus = $false
        $hresult = [CryptoAPI.CertAdm]::CertSrvIsServerOnline($Server,[ref]$ServerStatus)
        if ($ServerStatus) {
            $CertAdmin = New-Object -ComObject CertificateAuthority.Admin
            $CertRequest = New-Object -ComObject CertificateAuthority.Request
            $CA = New-Object psobject -Property @{
                Name = $CAName;
                ICertAdmin = $true;
                ICertRequest = $true
            }
            try {$retn = $CertAdmin.GetCAProperty($Config,0x6,0,4,0)}
            catch {$CA.ICertAdmin = $false}
            try {$retn = $CertRequest.GetCAProperty($Config,0x6,0,4,0)}
            catch {$CA.ICertRequest = $false}
            $CA
        } else {
            Write-Error -Category ObjectNotFound -ErrorId ObjectNotFoundException `

            -Message "Unable to find a Certification Authority server on '$Server'."
        }
    } else {return}
}

This is more complicated, but more helpful example. If you want to test local CA (when CA server is installed on the same computer), or remote CA server. Remote server can be specified explicitly by using –Config parameter. Remote CA server must be passed in a 'CAHostName\CAName' form. Alternatively you can use –ShowUI parameter to select from Enterprise CA list. In that case you must omit –Config parameter. Here are some useful examples:

[Administrator] Test-CAOnline

Name                                                               ICertRequest                              ICertAdmin
----                                                               ------------                              ----------
Contoso CA                                                                 True                                    True


[Administrator] Test-CAOnline -Config "dc2\contoso-dc2-ca"

Name                                                               ICertRequest                              ICertAdmin
----                                                               ------------                              ----------
contoso-dc2-ca                                                             True                                    True


[Administrator] Test-CAOnline -ShowUI

Name                                                               ICertRequest                              ICertAdmin
----                                                               ------------                              ----------
contoso-DC2-CA                                                             True                                    True


[Administrator]

If CA server is unavailable — an error will be thrown.

HTH.


Share this article:

Comments:

David Wallis

works great however it requires the certification admin role be present on the box for that dll to be present :(

Vadims Podāns

ICertAdmin part requires permissions. From what I know, ICertRequest doesn't require specific permissions to succeed.

cert

Hi, Vadims.

Do you know how to interpret output of certutil -ping command? What does it mean: -> a (10) or -> 32 (50). Where i can read about it?

What is the prefered site (site awareness enabled) for requesting cert from Site5?

DsGetSiteName: PC -> Site5
DsGetSiteName[0]: EntSubca1 -> 0: site1 (2969ms)
DsGetSiteName[1]: subca02 -> 1: site2 (5406ms)
DsGetSiteName[2]: subca03 -> 0: site1 (2781ms)
DsGetSiteName[3]: subca04 -> 2: site3 (3672ms)
DsGetSiteName[4]: subca05 -> 0: site1 (2187ms)
DsGetSiteName[5]: subca06 -> 3: site4 (1594ms)
DsQuerySitesByCost: Site5
DsQuerySitesByCost[0]: site1: a (10)
DsQuerySitesByCost[1]: site2: 32 (50)
DsQuerySitesByCost[2]: site3: 32 (50)
DsQuerySitesByCost[3]: site4: 14 (20)
DsQuerySiteCosts[0.0]: EntSubca1(site1) -> a (10)
DsQuerySiteCosts[1.1]: subca02(site2) -> 32 (50)
DsQuerySiteCosts[2.0]: subca03(site1) -> a (10)
DsQuerySiteCosts[3.2]: subca04(site3) -> 32 (50)
DsQuerySiteCosts[4.0]: subca05(site1) -> a (10)
DsQuerySiteCosts[5.3]: subca06(site4) -> 14 (20)
CertUtil: -ping command completed successfully.

 

Vadims Podāns

I believe, these numbers are costs to particular AD site. First number is in hex format and decimal equivalent in parenthesis.

Cert

Ha, Indeed! Thank you, Vadims. Those hex numbers confused me. And what about, for example DsQuerySiteCosts[5.3], what are those numbers in square brackets?

Vadims Podāns

First index points to a site name, second index points to site cost.


Post your comment:

Please, solve this little equation and enter result below. Captcha