Ureader.com  
Microsoft software help and Community
   home   |   control panel login   |   archive   |  
 
platform
active.directory
adsi
adsi.iis-admin
base
com_ole
complus_mts
component_svcs
database
directx
gdi
graphics_mm
internet.client
internet.server
internet.server.isapi-dev
localization
mapi
messaging
msi
mslayerforunicode
multimedia
networking
networking.ipv6
sdk_install
security
shell
telephony.tapi_2
telephony.tapi_3
telephony.tsp
telephony.wte
tools
ui
ui_shell
win_base_svcs
win16
  
 
date: Mon, 28 Apr 2008 07:59:03 -0700,    group: microsoft.public.platformsdk.security        back       


Programmatic smartcard logon certificate renewal on behalf of...   
Hello everyone,
Apologies for the double post, and the premature decision to put this 
question on microsoft.public.security.crypto first (I've since found articles 
on MSDN mentioning this as the go-to newsgroup for these questions)...

I am having the following problem:
Consider an application for domain administrators, that allows them to 
manage smartcards, assign them to domain users and request smartcard logon 
certificates on behalf of those users. Most of this functionality uses the 
IEnroll API automatically wrapped by visual studio in an interop assembly.

All works fine, until the time comes to renew those certificates. Based on 
the MSDN Article "Creating Certificate Requests Using the Certificate 
Enrollment Control and CryptoAPI", "Creating a renewal request" topic 
(http://msdn2.microsoft.com/en-us/library/ms867026.aspx#certenroll_topic8), 
I've created a certificate renewal request, let's say for a user called 
DEV\e. The currently logged on user is DEV\administrator. Once I submit the 
renewal request to the CA, it gets accepted and issued. The certificate that 
gets issued though, is not for the user DEV\e but for the user 
DEV\administrator.

The certificate renewal request is created using the IEnroll4 interface 
(I've omitted the error handling/initialization code for the sake of brevity):

IEnroll4* enroll = NULL;
CoCreateInstance(CLSID_CEnroll, NULL, CLSCTX_INPROC_SERVER, IID_IEnroll4, 
(void **) &enroll);
CryptAcquireContext(&cryptoProvider, NULL, "provider name", PROV_RSA_FULL, 
contextFlags);
CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, cryptoProvider, 
CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
certificate = CertFindCertificateInStore(certStore, X509_ASN_ENCODING | 
PKCS_7_ASN_ENCODING, 0, CERT_FIND_ENHKEY_USAGE, &enhancedKeyUsage, NULL);
CertGetCertificateContextProperty(certificate, CERT_KEY_PROV_INFO_PROP_ID, 
NULL, &providerInfoSize);
CertGetCertificateContextProperty(certificate, CERT_KEY_PROV_INFO_PROP_ID, 
providerInfo, &providerInfoSize);
enroll->AddCertTypeToRequestWStr(templateFriendlyName);
enroll->put_RenewalCertificate(certificate);
enroll->put_UseExistingKeySet(useExistingKeySet);
enroll->put_ProviderNameWStr(providerInfo->pwszProvName);
enroll->put_ContainerNameWStr(providerInfo->pwszContainerName)
enroll->put_KeySpec(providerInfo->dwKeySpec);
enroll->put_ProviderType(PROV_RSA_FULL);
enroll->put_EnableSMIMECapabilities(TRUE);
enroll->createRequestWStr(XECR_CMC, NULL, L"", &requestBlob);

enroll->binaryBlobToString(CRYPT_STRING_BASE64REQUESTHEADER, &requestBlob, 
&requestString);

requestString now contains the base64 encoded request. This string gets 
returned to .NET code and submitted to the CA using the auto generated 
wrapper for ICertRequest2. As mentioned above, the certificate gets issued 
with no error message, only for the wrong user.
Is there something I'm missing? Is it even possible to request renewal 
certificates on behalf of a different user this way? I can also post the 
certutil.exe dumped request, but it is rather long...

Thanks in advance for any help or hints!

-- 
PS
date: Mon, 28 Apr 2008 07:59:03 -0700   author:   ps

RE: Programmatic smartcard logon certificate renewal on behalf of...   
Hi,

By reading your code, it appears clearly that you are using the first 
certificate you find on the store "MY". Since you are logged as 
DEV\administrator, this certificate logically belongs to him. 
If you want to renew the certificate of the user DEV\e, you must to find his 
certificate explicitly by looping on the function CertFindCertificateInStore 
and stopping on the one that belongs to this user (for example, you can use 
the property CERT_FRIENDLY_NAME_PROP_ID for that purpose).
Of course, in order for the to work, you must have the smart card of the 
user inserted in the administrator machine and his certificate loaded into 
the "MY" store using the appropriate tool.

Cheers,
-- 
Mounir IDRASSI
IDRIX
http://www.idrix.fr


"ps" wrote:

> Hello everyone,
> Apologies for the double post, and the premature decision to put this 
> question on microsoft.public.security.crypto first (I've since found articles 
> on MSDN mentioning this as the go-to newsgroup for these questions)...
> 
> I am having the following problem:
> Consider an application for domain administrators, that allows them to 
> manage smartcards, assign them to domain users and request smartcard logon 
> certificates on behalf of those users. Most of this functionality uses the 
> IEnroll API automatically wrapped by visual studio in an interop assembly.
> 
> All works fine, until the time comes to renew those certificates. Based on 
> the MSDN Article "Creating Certificate Requests Using the Certificate 
> Enrollment Control and CryptoAPI", "Creating a renewal request" topic 
> (http://msdn2.microsoft.com/en-us/library/ms867026.aspx#certenroll_topic8), 
> I've created a certificate renewal request, let's say for a user called 
> DEV\e. The currently logged on user is DEV\administrator. Once I submit the 
> renewal request to the CA, it gets accepted and issued. The certificate that 
> gets issued though, is not for the user DEV\e but for the user 
> DEV\administrator.
> 
> The certificate renewal request is created using the IEnroll4 interface 
> (I've omitted the error handling/initialization code for the sake of brevity):
> 
> IEnroll4* enroll = NULL;
> CoCreateInstance(CLSID_CEnroll, NULL, CLSCTX_INPROC_SERVER, IID_IEnroll4, 
> (void **) &enroll);
> CryptAcquireContext(&cryptoProvider, NULL, "provider name", PROV_RSA_FULL, 
> contextFlags);
> CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, cryptoProvider, 
> CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
> certificate = CertFindCertificateInStore(certStore, X509_ASN_ENCODING | 
> PKCS_7_ASN_ENCODING, 0, CERT_FIND_ENHKEY_USAGE, &enhancedKeyUsage, NULL);
> CertGetCertificateContextProperty(certificate, CERT_KEY_PROV_INFO_PROP_ID, 
> NULL, &providerInfoSize);
> CertGetCertificateContextProperty(certificate, CERT_KEY_PROV_INFO_PROP_ID, 
> providerInfo, &providerInfoSize);
> enroll->AddCertTypeToRequestWStr(templateFriendlyName);
> enroll->put_RenewalCertificate(certificate);
> enroll->put_UseExistingKeySet(useExistingKeySet);
> enroll->put_ProviderNameWStr(providerInfo->pwszProvName);
> enroll->put_ContainerNameWStr(providerInfo->pwszContainerName)
> enroll->put_KeySpec(providerInfo->dwKeySpec);
> enroll->put_ProviderType(PROV_RSA_FULL);
> enroll->put_EnableSMIMECapabilities(TRUE);
> enroll->createRequestWStr(XECR_CMC, NULL, L"", &requestBlob);
> 
> enroll->binaryBlobToString(CRYPT_STRING_BASE64REQUESTHEADER, &requestBlob, 
> &requestString);
> 
> requestString now contains the base64 encoded request. This string gets 
> returned to .NET code and submitted to the CA using the auto generated 
> wrapper for ICertRequest2. As mentioned above, the certificate gets issued 
> with no error message, only for the wrong user.
> Is there something I'm missing? Is it even possible to request renewal 
> certificates on behalf of a different user this way? I can also post the 
> certutil.exe dumped request, but it is rather long...
> 
> Thanks in advance for any help or hints!
> 
> -- 
> PS
date: Mon, 28 Apr 2008 13:05:05 -0700   author:   Mounir IDRASSI am

RE: Programmatic smartcard logon certificate renewal on behalf of.   
Hey,
thanks for the reply!

I am using the first certificate in the store, but the certificate store is 
not the computer store, but the smartcard store. The smartcard (and the 
certificate on it) belongs to the DEV\e user. For this sample we assume there 
is only one certificate there, the one to be renewed. I can verify in the 
debugger, that the certificate used in the put_RenewalCertificate method is 
the correct one.
-- 
PS


"Mounir IDRASSI" wrote:

> Hi,
> 
> By reading your code, it appears clearly that you are using the first 
> certificate you find on the store "MY". Since you are logged as 
> DEV\administrator, this certificate logically belongs to him. 
> If you want to renew the certificate of the user DEV\e, you must to find his 
> certificate explicitly by looping on the function CertFindCertificateInStore 
> and stopping on the one that belongs to this user (for example, you can use 
> the property CERT_FRIENDLY_NAME_PROP_ID for that purpose).
> Of course, in order for the to work, you must have the smart card of the 
> user inserted in the administrator machine and his certificate loaded into 
> the "MY" store using the appropriate tool.
> 
> Cheers,
> -- 
> Mounir IDRASSI
> IDRIX
> http://www.idrix.fr
> 
> 
> "ps" wrote:
> 
> > Hello everyone,
> > Apologies for the double post, and the premature decision to put this 
> > question on microsoft.public.security.crypto first (I've since found articles 
> > on MSDN mentioning this as the go-to newsgroup for these questions)...
> > 
> > I am having the following problem:
> > Consider an application for domain administrators, that allows them to 
> > manage smartcards, assign them to domain users and request smartcard logon 
> > certificates on behalf of those users. Most of this functionality uses the 
> > IEnroll API automatically wrapped by visual studio in an interop assembly.
> > 
> > All works fine, until the time comes to renew those certificates. Based on 
> > the MSDN Article "Creating Certificate Requests Using the Certificate 
> > Enrollment Control and CryptoAPI", "Creating a renewal request" topic 
> > (http://msdn2.microsoft.com/en-us/library/ms867026.aspx#certenroll_topic8), 
> > I've created a certificate renewal request, let's say for a user called 
> > DEV\e. The currently logged on user is DEV\administrator. Once I submit the 
> > renewal request to the CA, it gets accepted and issued. The certificate that 
> > gets issued though, is not for the user DEV\e but for the user 
> > DEV\administrator.
> > 
> > The certificate renewal request is created using the IEnroll4 interface 
> > (I've omitted the error handling/initialization code for the sake of brevity):
> > 
> > IEnroll4* enroll = NULL;
> > CoCreateInstance(CLSID_CEnroll, NULL, CLSCTX_INPROC_SERVER, IID_IEnroll4, 
> > (void **) &enroll);
> > CryptAcquireContext(&cryptoProvider, NULL, "provider name", PROV_RSA_FULL, 
> > contextFlags);
> > CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, cryptoProvider, 
> > CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
> > certificate = CertFindCertificateInStore(certStore, X509_ASN_ENCODING | 
> > PKCS_7_ASN_ENCODING, 0, CERT_FIND_ENHKEY_USAGE, &enhancedKeyUsage, NULL);
> > CertGetCertificateContextProperty(certificate, CERT_KEY_PROV_INFO_PROP_ID, 
> > NULL, &providerInfoSize);
> > CertGetCertificateContextProperty(certificate, CERT_KEY_PROV_INFO_PROP_ID, 
> > providerInfo, &providerInfoSize);
> > enroll->AddCertTypeToRequestWStr(templateFriendlyName);
> > enroll->put_RenewalCertificate(certificate);
> > enroll->put_UseExistingKeySet(useExistingKeySet);
> > enroll->put_ProviderNameWStr(providerInfo->pwszProvName);
> > enroll->put_ContainerNameWStr(providerInfo->pwszContainerName)
> > enroll->put_KeySpec(providerInfo->dwKeySpec);
> > enroll->put_ProviderType(PROV_RSA_FULL);
> > enroll->put_EnableSMIMECapabilities(TRUE);
> > enroll->createRequestWStr(XECR_CMC, NULL, L"", &requestBlob);
> > 
> > enroll->binaryBlobToString(CRYPT_STRING_BASE64REQUESTHEADER, &requestBlob, 
> > &requestString);
> > 
> > requestString now contains the base64 encoded request. This string gets 
> > returned to .NET code and submitted to the CA using the auto generated 
> > wrapper for ICertRequest2. As mentioned above, the certificate gets issued 
> > with no error message, only for the wrong user.
> > Is there something I'm missing? Is it even possible to request renewal 
> > certificates on behalf of a different user this way? I can also post the 
> > certutil.exe dumped request, but it is rather long...
> > 
> > Thanks in advance for any help or hints!
> > 
> > -- 
> > PS
date: Tue, 29 Apr 2008 00:15:01 -0700   author:   ps

Google
 
Web ureader.com


    COPYRIGHT 2007, YARDI TECHNOLOGY LIMITED, ALL RIGHT RESERVE  |   contact us