Other posts in the series:


Abstract

In previous posts we discussed and explored certificate enrollment APIs (CertEnroll) to perform various basic enrollment operations. In this section we will talk about advanced certificate enrollment called Enroll On Behalf Of (EOBO). This type of enrollment involves additional mechanism called registration authority (RA). This commonly is used during smart card deployments. For example, an employee prior to get a smart card is went through face-to-face interview with Enrollment Agent where he is instructed about smart card usage rules and is registered in accounting documents. After all formalities are completed, an enrollment agent creates a special certificate request where he put employee's user name (which is obtained from Active Directory) and signs it with his own special Enrollment Agent certificate. And only then the certificate request is submitted to a CA server.

Normally automatic subject construction uses requester information to build the subject. Therefore it is not possible to issue the certificate for other user account. Enroll On Behalf Of functionality allows to explicitly specify target user account name. However, EOBO requires multiple signatures in the request:

  1. Original PKCS#10 request is signed by a key pair generated during request creation;
  2. When PKCS#10 request is signed, it is wrapped to a PKCS#7 (in most cases) container;
  3. Entire PKCS#7 container is signed by a special enrollment agent certificate;

The second signature proves that the caller (or requester) is eligible to enroll certificate one behalf of other user (in other words, impersonate another user).

Because of the powerful capability of the Enrollment Agent certificate, it is strongly recommended that your organization maintain very strong security policies for these certificates.

 

By using this topic, an organization can develop a custom tool for enrollment agents to perform employee registration and certificate enrollment/issuance.

Hold the ice

Today we will start with IX509CertificateRequestPkcs10 interface that will create original PKCS#10 certificate request:

$PKCS10 = New-Object -ComObject X509Enrollment.CX509CertificateRequestPkcs10

use IX509CertificateRequestPkcs10::InitializeFromTemplateName method to initialize the request object. I will show the basic scenario which do not involve smart cards.

$PKCS10.InitializeFromTemplateName(0x1,"User")

and finalize the request by using generic Encode method:

$PKCS10.Encode()

Request encoding is necessary to generate a key pair and sign the PKCS#10 request object. After calling this method, the PKCS#10 object become signed and is ready to be wrapped in PKCS#7 object:

$pkcs7 = New-Object -ComObject X509enrollment.CX509CertificateRequestPkcs7
$pkcs7.InitializeFromInnerRequest($pkcs10)

The IX509CertificateRequestPkcs7 interface has two properties: RequesterName and SignerCertificate. First property is used to specify target user name (to whom this certificate is intended). The syntax of this property is very simple. Assuming, we have 'sballmer' user account in Adatum domain, then the RequesterName property is assigned in this way:

$pkcs7.RequesterName = "ADATUM\sballmer"

The SignerCertificate property is much complex. It accepts an ISignerCertificate interface object. Therefore we must instantiate the interface object:

$signer = New-Object -ComObject X509Enrollment.CSignerCertificate

The ISignerCertificate interface has only single initialization method: ISignerCertificate::Initialize. This method accepts 4 parameters and we are interesting in the last two: Encoding and strCertificate. With Windows Vista and Windows Server 2008 we have to manually find enrollment agent certificate (with Certificate Request Agent EKU) in the personal store. The following syntax could be used to find the certificate:

$cert = Get-ChildItem Cert:\CurrentUser\My | Where-Object {$_.Extensions | Where-Object {$_.Oid.Value -eq "2.5.29.37" -and $_.EnhancedKeyUsages["1.3.6.1.4.1.311.20.2.1"]}}

If the $cert contains a single certificate object (you could specify additional filters, because the command may return multiple enrollment agent certificates) we must convert it to a base64 string and add the string as a strCertificate parameter:

$Base64 = [Convert]::ToBase64String($Cert.RawData)
$signer = New-Object -ComObject X509Enrollment.CSignerCertificate
$signer.Initialize(0,0,1,$Base64)

With Windows 7, Windows Server 2008 R2 and newer systems (Windows 8 and Windows Server 2012) you can put just thumbprint information:

$signer = New-Object -ComObject X509Enrollment.CSignerCertificate
$signer.Initialize(0,0,0xc,"3A47D2C3CF064E13FE90442DA77412CBC5FA8824")

Once the ISignerCertificate object is ready, we add it to our PKCS#7 object SignerCertificate property:

$pkcs7.SignerCertificate = $signer

ok, that is enough. Now we are ready to create enrollment object and perform actual enrollment:

$Request = New-Object -ComObject X509Enrollment.CX509Enrollment
$Request.InitializeFromRequest($pkcs7)
$Request.Enroll()

if everything is completed successfully, then you should see a new certificate in personal store:

PS C:\> dir Cert:\CurrentUser\My


    Directory: Microsoft.PowerShell.Security\Certificate::CurrentUser\My


Thumbprint                                Subject
----------                                -------
3A47D2C3CF064E13FE90442DA77412CBC5FA8824  CN=Administrator, CN=Users, DC=adatum, DC=lv
42AB649452F23E9DB506B67A295A18453CE4C5EA  CN=Steve Ballmer, CN=Users, DC=adatum, DC=lv


PS C:\>

WOW, the certificate is successfully enrolled!!!11oneone Now enrollment agent should export the certificate (only if smart card CSP is not used) and distribute it to a target user. In the case of smart card CSP, you may have to type a PIN to save the certificate to smart card and no export actions are necessary.

The End

I think this is enough for you to get the fast start with EOBO automation. In the next post I will show several advanced techniques and will discuss about several security concerns regarding the series subject.

to be continued…


Share this article:

Comments:

PSNewby

Great post. We use smartcards for VPN login and I was able to enroll smartcards for users with this. I have one question- We have few users where their smartcard certs are expiring soon. Would it be possible for us to renew (one card at a time or even in bulk if that's possible) the cert on the card using the same key. is there a method called renew or reenroll? e.g. $Request.Renew()

Vadims Podans

You should use autoenrollment functionality for certificate renewals. In addition you may need to configure certificate template for renewals: in the Issuance Requirements switch "Certificate renewal requirements" radiobutton to "Valid existing certificate".

PSNewby

Thanks for your response. I explored that option, but its not possible in our environment, because 1. We don't want to assign enroll and auto-enroll access to users 2. More than 60% of our users are MAC users. Is there any way to renew the cert on smartcard with (on) same key from powershell/command prompt. Our insurance requirement for re-enroll are same as enrol.

Vadims Podans

I will look what options are there and, probably, will write a new post.

PSNewby

Thank you, please post the link for your new post here.

Vadims Podans

I don't think it is worth for a new article, so I'm posting a link to a appropriate method which you can use for certificate renewals: http://msdn.microsoft.com/en-us/library/windows/desktop/aa377523(v=vs.85).aspx there is a bunch of options, where you can reuse existing key pair.

Marco Mariani

Hello, I'm facing an issue trying to enroll a certificate for someone else. I was able to enroll for myself although when trying to enroll on behalf of I get following error in event viewer and in powershell Certificate enrollment for <domain>\<my-username> failed to enroll for a <template> certificate with request ID N/A from <certificate_server> (No such interface supported 0x80004002 (-2147467262)). Which is the interface the error is referrring to? When I enroll for myself the template is found and it is working. Many thanks for any suggestion, Marco

Vadims Podans

I don't know. Never had this error.

Marco

Hi, sorry to be a pain. Just wanted to confirm a couple of settings 1. $PKCS10 is the standard request with the template: mine is Mobile_devices 2. $PKCS7 is the request with the template which has rights to enrol on behalf of (in my case enroll_agent) Whe I run this through the standard Windows certificate wizard, it works properly. When I try to run it through powershell it returns the above error (Exception calling "Enroll" with "0" argument(s): "CertEnroll::CX509Enrollment::_EnrollWizard: No such interface support ed 0x80004002 (-2147467262)"). I just would like to know where I should start looking at. In the Cetificate server I can't see any entry, neither when successful submit, nor when


Post your comment:

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