Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

4016 lines
117 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows NT Security
// Copyright (C) Microsoft Corporation, 1997 - 1998
//
// File: txenrol.cpp
//
// Contents: XEnroll C++ Tests
//
// History: 03-Nov-97 keithv Created
//
//----------------------------------------------------------------------------
#include <windows.h>
#include <assert.h>
#include "wincrypt.h"
#include "xenroll.h"
#include "unicode.h"
#define SECURITY_WIN32
#include <security.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <time.h>
#include <malloc.h>
#define NO_OSS_DEBUG
#include <dbgdef.h>
//globals
char *g_pszDNName = NULL;
char *g_pszCAXchgFileName = NULL;
char *g_pszCMCFileName = NULL;
char *g_pszCMCResponseFileName = NULL;
char *g_pszKeyContainer = NULL;
DWORD g_cStress = 1;
DWORD g_dwTestID = MAXDWORD;
BOOL g_fPause = FALSE;
BOOL g_fVerb = FALSE;
char *g_pszPKCS7FileName = NULL;
char *g_pszPFXFileName = NULL;
char *g_pszPFXPassword = NULL;
#define TXEnrollLocalScope(ScopeName) struct ScopeName##TheLocalScope { public
#define TXEnrollEndLocalScope } local
#define HASHFROMCERT(a, b) CryptHashCertificate(NULL, 0, X509_ASN_ENCODING, (a)->pbCertEncoded, (a)->cbCertEncoded, (b)->pbData, &(b)->cbData)
#define PRINT_ERROR(Error) \
Error##: \
printf("failed => %s, Error = %08x\n", #Error, GetLastError()); \
goto ERROR_RETURN_LABEL;
#define PRINT_ERROR2(Error, hr) \
Error##: \
printf("failed => %s, Error = 0x%08x\n", #Error, (hr)); \
goto ERROR_RETURN_LABEL;
#define PRINT_ERROR_IF(Error, hr, condition) \
Error##: \
{ \
if (condition) { \
printf("failed => %s, Error = 0x%08x\n", #Error, (hr)); \
} \
goto ERROR_RETURN_LABEL; \
}
static BOOL B64EncodeBlob(PCRYPT_DATA_BLOB pBlob, PCRYPT_DATA_BLOB pBlobB64) {
DWORD cchBlob = 0;
DWORD err = ERROR_SUCCESS;
assert(pBlobB64 != NULL && pBlob != NULL);
memset(pBlobB64, 0, sizeof(CRYPT_DATA_BLOB));
// base64 encode the cert
if (CryptBinaryToStringW(
pBlob->pbData,
pBlob->cbData,
CRYPT_STRING_BASE64,
NULL,
&cchBlob))
{
pBlobB64->pbData = (PBYTE) malloc(cchBlob * sizeof(WCHAR));
if(pBlobB64->pbData == NULL)
err = ERROR_NOT_ENOUGH_MEMORY;
}
else
{
err = GetLastError();
assert(ERROR_SUCCESS != err);
}
if(err == ERROR_SUCCESS) {
if (!CryptBinaryToStringW(
pBlob->pbData,
pBlob->cbData,
CRYPT_STRING_BASE64,
(LPWSTR) pBlobB64->pbData,
&cchBlob))
{
err = GetLastError();
assert(ERROR_SUCCESS != err);
}
}
if(err != ERROR_SUCCESS) {
SetLastError(err);
memset(pBlobB64, 0, sizeof(CRYPT_DATA_BLOB));
return(FALSE);
}
pBlobB64->cbData = cchBlob * sizeof(WCHAR);
return(TRUE);
}
static BOOL BSTREncodeBlob(PCRYPT_DATA_BLOB pBlob, BSTR * pbstr) {
CRYPT_DATA_BLOB blob64;
BOOL fRet = TRUE;
assert(pbstr != NULL);
memset(&blob64, 0, sizeof(CRYPT_DATA_BLOB));
if( !B64EncodeBlob(pBlob, &blob64) )
return(FALSE);
if( NULL == (*pbstr = SysAllocStringByteLen((LPCSTR) blob64.pbData, blob64.cbData)) )
fRet = FALSE;
if(blob64.pbData != NULL)
free(blob64.pbData);
return(fRet);
}
static HRESULT GetCertificateContextPropertySimple(IN PCCERT_CONTEXT pCertContext,
IN DWORD dwPropID,
OUT PCRYPT_DATA_BLOB dataBlob)
{
BOOL fDone = FALSE;
dataBlob->pbData = NULL;
dataBlob->cbData = 0x150;
do {
if (dataBlob->pbData != NULL) { LocalFree(dataBlob->pbData); }
dataBlob->pbData = (LPBYTE)LocalAlloc(LPTR, dataBlob->cbData);
if (dataBlob->pbData == NULL) { return E_OUTOFMEMORY; }
if (!CertGetCertificateContextProperty
(pCertContext,
dwPropID,
(LPVOID)dataBlob->pbData,
&(dataBlob->cbData)))
{
if (GetLastError() != ERROR_MORE_DATA)
return HRESULT_FROM_WIN32(GetLastError());
}
else
{
fDone = TRUE;
}
} while (!fDone);
return S_OK;
}
static HRESULT ResyncIEnrollRequestStore(IN OUT IEnroll4 **ppIEnroll4)
{
CRYPT_DATA_BLOB hashBlob;
HRESULT hr;
ZeroMemory(&hashBlob, sizeof(hashBlob));
// Get the thumbprint of the created request.
if (S_OK != (hr = (*ppIEnroll4)->get_ThumbPrintWStr(&hashBlob)))
goto get_ThumbPrintWStrError;
hashBlob.pbData = (LPBYTE)LocalAlloc(LPTR, hashBlob.cbData);
if (NULL == hashBlob.pbData)
goto MemoryError;
if (S_OK != (hr = (*ppIEnroll4)->get_ThumbPrintWStr(&hashBlob)))
goto get_ThumbPrintWStrError;
(*ppIEnroll4)->Release();
if (NULL == (*ppIEnroll4 = PIEnroll4GetNoCOM()))
goto PIEnroll4GetNoCOMError;
if (S_OK != (hr = (*ppIEnroll4)->put_ThumbPrintWStr(hashBlob)))
goto put_ThumbPrintWStrError;
hr = S_OK;
ErrorReturn:
return hr;
TRACE_ERROR(get_ThumbPrintWStrError);
SET_HRESULT(MemoryError, E_OUTOFMEMORY);
SET_HRESULT(PIEnroll4GetNoCOMError, HRESULT_FROM_WIN32(GetLastError()));
TRACE_ERROR(put_ThumbPrintWStrError);
}
static HRESULT FindPendingRequest(IN IEnroll4 *pIEnroll4,
IN PCCERT_CONTEXT pCertContext,
IN HRESULT hrExpected,
OUT LONG *plIndex)
{
CRYPT_DATA_BLOB hashBlob;
CRYPT_DATA_BLOB hashBlobExpected;
HRESULT hr;
LONG lIndex;
ZeroMemory(&hashBlob, sizeof(hashBlob));
ZeroMemory(&hashBlobExpected, sizeof(hashBlobExpected));
if (NULL == pIEnroll4 || NULL == pCertContext || NULL == plIndex)
goto InvalidArgError;
if (S_OK != (hr = GetCertificateContextPropertySimple
(pCertContext,
CERT_HASH_PROP_ID,
&hashBlobExpected)))
goto GetCertificateContextPropertySimpleError;
// Initialize the enumeration.
if (S_OK != (hr = pIEnroll4->enumPendingRequestWStr(XEPR_ENUM_FIRST, 0, NULL)))
goto enumPendingRequestWStrError1;
for (lIndex = 0; TRUE; lIndex++)
{
hashBlob.pbData = NULL;
hashBlob.cbData = 0;
if (S_OK != (hr = pIEnroll4->enumPendingRequestWStr
(lIndex,
XEPR_HASH,
(LPVOID)&hashBlob)))
goto enumPendingRequestWStrError2;
hashBlob.pbData = (LPBYTE)LocalAlloc(LPTR, hashBlob.cbData);
if (NULL == hashBlob.pbData)
goto MemoryError;
if (S_OK != (hr = pIEnroll4->enumPendingRequestWStr
(lIndex,
XEPR_HASH,
(LPVOID)&hashBlob)))
goto enumPendingRequestWStrError3;
// We've found the request we want.
if ((hashBlobExpected.cbData == hashBlob.cbData) &&
(0 == memcmp(hashBlobExpected.pbData, hashBlob.pbData, hashBlob.cbData)))
break;
}
// Success: assign the OUT param.
*plIndex = lIndex;
hr = S_OK;
CommonReturn:
if (NULL != hashBlob.pbData) { LocalFree(hashBlob.pbData); }
return hr;
ErrorReturn:
goto CommonReturn;
PRINT_ERROR_IF(enumPendingRequestWStrError1, hr, (hrExpected != hr));
PRINT_ERROR_IF(enumPendingRequestWStrError2, hr, (hrExpected != hr));
PRINT_ERROR_IF(enumPendingRequestWStrError3, hr, (hrExpected != hr));
PRINT_ERROR_IF(GetCertificateContextPropertySimpleError, hr, (hrExpected != hr));
PRINT_ERROR2(InvalidArgError, hr = E_INVALIDARG);
PRINT_ERROR2(MemoryError, hr = E_OUTOFMEMORY);
}
static PCCERT_CONTEXT GetCertOutOfStore(PCRYPT_DATA_BLOB pBlobRequest, DWORD dwStoreFlags, LPWSTR pwszStoreName)
{
HCERTSTORE hStoreRequest = NULL;
PCERT_REQUEST_INFO pReqInfo = NULL;
PCCERT_CONTEXT pCertContextRequest = NULL;
if( !CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
pBlobRequest,
CERT_QUERY_CONTENT_FLAG_PKCS10,
CERT_QUERY_FORMAT_FLAG_ALL,
CRYPT_DECODE_ALLOC_FLAG,
NULL,
NULL,
NULL,
NULL,
NULL,
(const void **) &pReqInfo) )
goto ErrorCryptQueryObject;
if( NULL == (hStoreRequest = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
X509_ASN_ENCODING,
NULL,
dwStoreFlags | CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG,
pwszStoreName)) )
goto ErrorOpenRequestStore;
// Now get this out of the request store
if( NULL == (pCertContextRequest = CertFindCertificateInStore(
hStoreRequest,
CRYPT_ASN_ENCODING,
0,
CERT_FIND_PUBLIC_KEY,
(void *) &pReqInfo->SubjectPublicKeyInfo,
NULL)) )
goto ErrorCertGetRequestCert;
CommonReturn:
if(hStoreRequest != NULL)
CertCloseStore(hStoreRequest, 0);
if(pReqInfo != NULL)
LocalFree(pReqInfo);
return(pCertContextRequest);
ErrorReturn:
if(pCertContextRequest != NULL)
CertFreeCertificateContext(pCertContextRequest);
pCertContextRequest = NULL;
goto CommonReturn;
PRINT_ERROR(ErrorCryptQueryObject);
PRINT_ERROR(ErrorOpenRequestStore);
PRINT_ERROR(ErrorCertGetRequestCert);
}
static PCCERT_CONTEXT GetCertOutOfRequestStoreMachine(PCRYPT_DATA_BLOB pBlobRequest) {
return GetCertOutOfStore
(pBlobRequest,
CERT_SYSTEM_STORE_LOCAL_MACHINE,
L"REQUEST");
}
static PCCERT_CONTEXT GetCertOutOfRequestStore(PCRYPT_DATA_BLOB pBlobRequest) {
return GetCertOutOfStore
(pBlobRequest,
CERT_SYSTEM_STORE_CURRENT_USER,
L"REQUEST");
}
// This version assumes the PKCS 10 is within a PKCS 7
static PCCERT_CONTEXT GetCertOutOfRequestStore2(
PCRYPT_DATA_BLOB pBlob7)
{
CRYPT_DATA_BLOB Blob10;
CRYPT_VERIFY_MESSAGE_PARA VerifyPara;
PCCERT_CONTEXT pCert;
Blob10.pbData = NULL;
Blob10.cbData = 0;
memset(&VerifyPara, 0, sizeof(VerifyPara));
VerifyPara.cbSize = sizeof(VerifyPara);
VerifyPara.dwMsgAndCertEncodingType =
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
if (!CryptVerifyMessageSignature(
&VerifyPara,
0, // dwSignerIndex
pBlob7->pbData,
pBlob7->cbData,
Blob10.pbData,
&Blob10.cbData,
NULL // ppSignerCert
) || 0 == Blob10.cbData)
goto ErrorCryptVerifyMessageSignature;
if (NULL == (Blob10.pbData = (PBYTE) _alloca(Blob10.cbData)))
goto ErrorOutOfMemory;
if (!CryptVerifyMessageSignature(
&VerifyPara,
0, // dwSignerIndex
pBlob7->pbData,
pBlob7->cbData,
Blob10.pbData,
&Blob10.cbData,
NULL // ppSignerCert
))
goto ErrorCryptVerifyMessageSignature;
pCert = GetCertOutOfRequestStore(&Blob10);
CommonReturn:
return pCert;
ErrorReturn:
pCert = NULL;
goto CommonReturn;
PRINT_ERROR(ErrorCryptVerifyMessageSignature);
PRINT_ERROR(ErrorOutOfMemory);
}
static PCRYPT_DATA_BLOB MakePKCS7ResponseEx(
PCRYPT_DATA_BLOB pBlobRequest,
PCRYPT_HASH_BLOB pHash,
BOOL fUser)
{
HCERTSTORE hStorePKCS7 = NULL;
PCCERT_CONTEXT pCertContextRequest = NULL;
PCRYPT_DATA_BLOB pBlobPKCS7 = NULL;
PCRYPT_KEY_PROV_INFO pKeyProvInfo = NULL;
DWORD cbKeyProvInfo = 0;
HCRYPTPROV hProv = NULL;
PCCERT_CONTEXT pCertContextNew = NULL;
CRYPT_DATA_BLOB blobPKCS7;
if (fUser)
{
pCertContextRequest = GetCertOutOfRequestStore(pBlobRequest);
}
else
{
pCertContextRequest = GetCertOutOfRequestStoreMachine(pBlobRequest);
}
if( NULL == pCertContextRequest)
goto ErrorGetCertOutOfRequestStore;
// get the prov info off of the cert
if(
!CertGetCertificateContextProperty(
pCertContextRequest,
CERT_KEY_PROV_INFO_PROP_ID,
NULL,
&cbKeyProvInfo
) ||
(NULL == (pKeyProvInfo = (PCRYPT_KEY_PROV_INFO) _alloca(cbKeyProvInfo))) ||
!CertGetCertificateContextProperty(
pCertContextRequest,
CERT_KEY_PROV_INFO_PROP_ID,
pKeyProvInfo,
&cbKeyProvInfo
) )
goto ErrorCertGetCertificateContextProperty;
// get and hProv off of this certificate
if( !CryptAcquireCertificatePrivateKey(
pCertContextRequest,
0,
NULL,
&hProv,
NULL,
NULL
) )
goto ErrorCryptAcquireCertificatePrivateKey;
// build a self-signed cert with this key
if( NULL == (pCertContextNew = CertCreateSelfSignCertificate(
hProv,
&pCertContextRequest->pCertInfo->Subject,
0,
pKeyProvInfo,
&pCertContextRequest->pCertInfo->SignatureAlgorithm,
NULL,
NULL,
NULL
)) )
goto ErrorCertCreateSelfSignCertificate;
// make a pkcs7
if( NULL == (hStorePKCS7 = CertOpenStore(
CERT_STORE_PROV_MEMORY,
X509_ASN_ENCODING,
NULL,
0,
NULL)) )
goto ErrorOpenPKCS7Store;
if( !CertAddCertificateContextToStore(
hStorePKCS7,
pCertContextNew,
CERT_STORE_ADD_USE_EXISTING,
NULL) )
goto ErrorCertAddToPKCS7Store;
assert(pHash != NULL);
if( !HASHFROMCERT(pCertContextNew, pHash))
goto ErrorHASHFROMCERT;
memset(&blobPKCS7, 0, sizeof(blobPKCS7));
if(!CertSaveStore(
hStorePKCS7,
PKCS_7_ASN_ENCODING | CRYPT_ASN_ENCODING,
CERT_STORE_SAVE_AS_PKCS7,
CERT_STORE_SAVE_TO_MEMORY,
&blobPKCS7,
0) )
goto ErrorCreatePKCS7;
pBlobPKCS7 = (PCRYPT_DATA_BLOB) malloc(sizeof(CRYPT_DATA_BLOB) + blobPKCS7.cbData);
if(NULL == pBlobPKCS7) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto OutOfMemory;
}
*pBlobPKCS7 = blobPKCS7;
pBlobPKCS7->pbData = ((PBYTE) pBlobPKCS7) + sizeof(CRYPT_DATA_BLOB);
if( !CertSaveStore(
hStorePKCS7,
PKCS_7_ASN_ENCODING | CRYPT_ASN_ENCODING,
CERT_STORE_SAVE_AS_PKCS7,
CERT_STORE_SAVE_TO_MEMORY,
pBlobPKCS7,
0))
goto ErrorCreatePKCS7;
CommonReturn:
if(hStorePKCS7 != NULL)
CertCloseStore(hStorePKCS7, 0);
if(pCertContextRequest != NULL)
CertFreeCertificateContext(pCertContextRequest);
if(pCertContextNew != NULL)
CertFreeCertificateContext(pCertContextNew);
if(hProv != NULL)
CryptReleaseContext(hProv, 0);
return(pBlobPKCS7);
ErrorReturn:
if(pBlobPKCS7 != NULL)
free(pBlobPKCS7);
pBlobPKCS7 = NULL;
goto CommonReturn;
PRINT_ERROR(ErrorCertCreateSelfSignCertificate);
PRINT_ERROR(ErrorCertGetCertificateContextProperty);
PRINT_ERROR(ErrorCryptAcquireCertificatePrivateKey);
PRINT_ERROR(ErrorGetCertOutOfRequestStore);
PRINT_ERROR(ErrorOpenPKCS7Store);
PRINT_ERROR(ErrorCertAddToPKCS7Store);
PRINT_ERROR(ErrorCreatePKCS7);
PRINT_ERROR(OutOfMemory);
PRINT_ERROR(ErrorHASHFROMCERT);
}
static PCRYPT_DATA_BLOB MakePKCS7ResponseMachine(
PCRYPT_DATA_BLOB pBlobRequest,
PCRYPT_HASH_BLOB pHash)
{
return MakePKCS7ResponseEx(pBlobRequest, pHash, FALSE);
}
static PCRYPT_DATA_BLOB MakePKCS7Response(
PCRYPT_DATA_BLOB pBlobRequest,
PCRYPT_HASH_BLOB pHash)
{
return MakePKCS7ResponseEx(pBlobRequest, pHash, TRUE);
}
static PCRYPT_DATA_BLOB GetPKCS10FromPKCS7(PCRYPT_DATA_BLOB pPKCS7) {
CRYPT_VERIFY_MESSAGE_PARA MsgPara;
PCCERT_CONTEXT pCert = NULL;
CRYPT_DATA_BLOB blob;
PCRYPT_DATA_BLOB pBlob = NULL;
assert(pPKCS7 != NULL);
memset(&blob, 0, sizeof(CRYPT_DATA_BLOB));
memset(&MsgPara, 0, sizeof(CRYPT_VERIFY_MESSAGE_PARA));
MsgPara.cbSize = sizeof(CRYPT_VERIFY_MESSAGE_PARA);
MsgPara.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
if( !CryptVerifyMessageSignature(
&MsgPara,
0,
pPKCS7->pbData,
pPKCS7->cbData,
NULL,
&blob.cbData,
NULL
) )
goto ErrorCryptVerifyMessageSignature;
if( (pBlob = (PCRYPT_DATA_BLOB) malloc(blob.cbData + sizeof(CRYPT_DATA_BLOB))) == NULL ) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto OutOfMemory;
}
pBlob->pbData = ((BYTE *) pBlob) + sizeof(CRYPT_DATA_BLOB);
pBlob->cbData = blob.cbData;
if( !CryptVerifyMessageSignature(
&MsgPara,
0,
pPKCS7->pbData,
pPKCS7->cbData,
pBlob->pbData,
&blob.cbData,
&pCert
) )
goto ErrorCryptVerifyMessageSignature;
CommonReturn:
if(pCert != NULL)
CertFreeCertificateContext(pCert);
return(pBlob);
ErrorReturn:
if(pBlob != NULL)
free(pBlob);
pBlob = NULL;
goto CommonReturn;
PRINT_ERROR(ErrorCryptVerifyMessageSignature);
PRINT_ERROR(OutOfMemory);
}
void DeleteCertPrivateKey(PCCERT_CONTEXT pCert) {
PCRYPT_KEY_PROV_INFO pKeyProvInfo = NULL;
DWORD cbKeyProvInfo = 0;
HCRYPTPROV hProv;
BYTE rgbKeyIdHash[20];
CRYPT_HASH_BLOB KeyIdentifier;
// get the prov info off of the cert
if(
!CertGetCertificateContextProperty(
pCert,
CERT_KEY_PROV_INFO_PROP_ID,
NULL,
&cbKeyProvInfo
) ||
(NULL == (pKeyProvInfo = (PCRYPT_KEY_PROV_INFO) _alloca(cbKeyProvInfo))) ||
!CertGetCertificateContextProperty(
pCert,
CERT_KEY_PROV_INFO_PROP_ID,
pKeyProvInfo,
&cbKeyProvInfo
) )
goto ErrorCertGetCertificateContextProperty;
// Note: for CRYPT_DELETEKEYSET, the returned hProv is undefined and
// must not be released.
if( !CryptAcquireContextU(&hProv,
pKeyProvInfo->pwszContainerName,
pKeyProvInfo->pwszProvName,
pKeyProvInfo->dwProvType,
(pKeyProvInfo->dwFlags & ~CERT_SET_KEY_CONTEXT_PROP_ID) |
CRYPT_DELETEKEYSET) )
goto ErrorCryptDeleteKeySet;
// Also delete the private key identifier
KeyIdentifier.pbData = rgbKeyIdHash;
KeyIdentifier.cbData = sizeof(rgbKeyIdHash);
if (!CertGetCertificateContextProperty(
pCert,
CERT_KEY_IDENTIFIER_PROP_ID,
KeyIdentifier.pbData,
&KeyIdentifier.cbData
))
goto ErrorCertGetCertificateKeyIdentifierProperty;
if (!CryptSetKeyIdentifierProperty(
&KeyIdentifier,
0, // dwPropId
CRYPT_KEYID_DELETE_FLAG |
pKeyProvInfo->dwFlags & CRYPT_KEYID_MACHINE_FLAG,
NULL, // pwszComputerName
NULL, // pvReserved
NULL // pvData
)) {
DWORD dwErr = GetLastError();
if (ERROR_FILE_NOT_FOUND != dwErr)
goto ErrorDeleteKeyIdentifier;
}
CommonReturn:
return;
ErrorReturn:
goto CommonReturn;
PRINT_ERROR(ErrorCertGetCertificateContextProperty)
PRINT_ERROR(ErrorCryptDeleteKeySet)
PRINT_ERROR(ErrorCertGetCertificateKeyIdentifierProperty)
PRINT_ERROR(ErrorDeleteKeyIdentifier)
}
BOOL RemoveCertFromStore(PCRYPT_HASH_BLOB pHash, LPCWSTR wszStore, DWORD dwStoreFlags) {
BOOL fRet = TRUE;
HCERTSTORE hStore = NULL;
DWORD err = GetLastError();
PCCERT_CONTEXT pCert = NULL;
// open the my store
if( NULL == (hStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
X509_ASN_ENCODING,
NULL,
dwStoreFlags,
wszStore)) )
goto ErrorOpenStore;
// find the cert by hash
if( NULL == (pCert = CertFindCertificateInStore(
hStore,
X509_ASN_ENCODING,
0,
CERT_FIND_HASH,
pHash,
NULL ) ))
goto ErrorCertFindCertificateInStore;
// delete the cert's private key
DeleteCertPrivateKey(pCert);
//delete the cert
if( !CertDeleteCertificateFromStore(pCert) ) {
pCert = NULL;
goto ErrorCertDeleteCertificateFromStore;
}
pCert = NULL;
CommonReturn:
if(pCert != NULL)
CertFreeCertificateContext(pCert);
if(hStore != NULL)
CertCloseStore(hStore, 0);
SetLastError(err);
return(fRet);
ErrorReturn:
fRet = FALSE;
err = GetLastError();
goto CommonReturn;
PRINT_ERROR(ErrorOpenStore);
PRINT_ERROR(ErrorCertFindCertificateInStore);
PRINT_ERROR(ErrorCertDeleteCertificateFromStore);
}
// Define a struct which will hold the data we need to test with.
typedef struct _PENDING_INFO {
DWORD dwRequestID;
LPWSTR pwszCADNS;
LPWSTR pwszCAName;
LPWSTR pwszFriendlyName;
DWORD dwStoreFlags;
LPWSTR pwszStoreName;
HRESULT hrExpectedResult;
} PENDING_INFO;
class TXEnrollPendingAPITester {
public:
BOOL TestMethod_enumPendingRequestWStr(IEnroll4 *pIEnroll4,
CRYPT_DATA_BLOB pkcs10Request,
PENDING_INFO *pPendingInfo);
BOOL TestMethod_removePendingRequestWStr(IEnroll4 *pIEnroll4);
BOOL TestMethod_setPendingInfoWStr(IEnroll4 *pIEnroll4,
CRYPT_DATA_BLOB pkcs10Request,
PENDING_INFO *pPendingInfo);
BOOL TestProperty_ThumbPrintWStr(IEnroll4 *pIEnroll4);
};
BOOL TXEnrollPendingAPITester::TestMethod_removePendingRequestWStr(IEnroll4 *pIEnroll4)
{
BOOL fResult;
CRYPT_DATA_BLOB hashBlob;
CRYPT_DATA_BLOB pkcs10Blob;
HRESULT hr;
LONG lIndex;
LONG lRequestID = 0;
PCCERT_CONTEXT pCertContext = NULL;
WCHAR pwszCADNS[] = L"duncanb1.ntdev.microsoft.com";
WCHAR pwszCAName[] = L"Test RPR";
WCHAR pwszFriendlyName[]= L"\0";
WCHAR wszDNName[] = L"CN=Xenroll TestMethod_removePendingRequestWStr Test";
ZeroMemory(&hashBlob, sizeof(hashBlob));
ZeroMemory(&pkcs10Blob, sizeof(pkcs10Blob));
//
// Case 0) Removal of a request in the REQUEST (normal case).
//
if (S_OK != (hr = pIEnroll4->resetExtensions()))
goto resetExtensionsError;
if (S_OK != (hr = pIEnroll4->resetAttributes()))
goto resetAttributesError;
// Small key size so the test runs faster.
if (S_OK != (hr = pIEnroll4->put_GenKeyFlags(384 << 16)))
goto put_GenKeyFlagsError;
// Create a request to test on.
if (S_OK != (hr = pIEnroll4->createRequestWStr
(XECR_PKCS10_V2_0,
wszDNName,
NULL,
&pkcs10Blob)))
goto createRequestWStrError;
// Set pending info on the request, so it can be accessed via the pending API:
if (S_OK != (hr = pIEnroll4->setPendingRequestInfoWStr
(lRequestID,
pwszCADNS,
pwszCAName,
pwszFriendlyName)))
goto setPendingRequestInfoWStrError;
if (S_OK != (hr = ResyncIEnrollRequestStore(&pIEnroll4)))
goto ResyncIEnrollRequestStoreError;
pCertContext = GetCertOutOfRequestStore(&pkcs10Blob);
if (NULL == pCertContext)
goto GetCertOutOfRequestStoreError;
// Verify that the request is in the REQUEST store:
if (S_OK != (hr = FindPendingRequest
(pIEnroll4,
pCertContext,
S_OK,
&lIndex)))
goto RequestNotAddedToStoreError;
// Get the thumbprint of the created request.
if (S_OK != (hr = pIEnroll4->get_ThumbPrintWStr(&hashBlob)))
goto get_ThumbPrintWStrError;
hashBlob.pbData = (LPBYTE)LocalAlloc(LPTR, hashBlob.cbData);
if (NULL == hashBlob.pbData)
goto MemoryError;
if (S_OK != (hr = pIEnroll4->get_ThumbPrintWStr(&hashBlob)))
goto get_ThumbPrintWStrError;
// Remove the request from the request store:
if (S_OK != (hr = pIEnroll4->removePendingRequestWStr(hashBlob)))
goto removePendingRequestWStrError;
// Verify that it is actually gone:
if (HRESULT_FROM_WIN32(CRYPT_E_NOT_FOUND) != (hr = FindPendingRequest
(pIEnroll4,
pCertContext,
HRESULT_FROM_WIN32(CRYPT_E_NOT_FOUND),
&lIndex)))
{
if (!FAILED(hr))
hr = E_FAIL;
goto PendingRequestNotRemovedError;
}
// No need to delete the request, the pending API has already done this.
pkcs10Blob.pbData = NULL;
//
// Case 1) invalid arg:
//
{
CRYPT_DATA_BLOB invalidBlob;
ZeroMemory(&invalidBlob, sizeof(invalidBlob));
if (E_INVALIDARG != (hr = pIEnroll4->removePendingRequestWStr(invalidBlob)))
goto removePendingRequestWStrError;
}
//
// Case 2) cert not found:
//
if (HRESULT_FROM_WIN32(CRYPT_E_NOT_FOUND) != (hr = pIEnroll4->removePendingRequestWStr
(hashBlob)))
{
if (!FAILED(hr))
hr = E_FAIL;
goto removePendingRequestWStrError;
}
fResult = TRUE;
CommonReturn:
if (NULL != pkcs10Blob.pbData)
{
pCertContext = GetCertOutOfRequestStore(&pkcs10Blob);
if (NULL != pCertContext)
{
CertDeleteCertificateFromStore(pCertContext);
}
LocalFree(pkcs10Blob.pbData);
}
if (NULL != hashBlob.pbData) { LocalFree(hashBlob.pbData); }
return fResult;
ErrorReturn:
SetLastError(hr);
fResult = FALSE;
goto CommonReturn;
PRINT_ERROR2(createRequestWStrError, hr);
PRINT_ERROR2(get_ThumbPrintWStrError, hr);
PRINT_ERROR2(GetCertOutOfRequestStoreError, hr = GetLastError());
PRINT_ERROR2(MemoryError, hr = E_OUTOFMEMORY);
PRINT_ERROR2(PendingRequestNotRemovedError, hr);
PRINT_ERROR2(put_GenKeyFlagsError, hr);
PRINT_ERROR2(RequestNotAddedToStoreError, hr);
PRINT_ERROR2(removePendingRequestWStrError, hr);
PRINT_ERROR2(resetExtensionsError, hr);
PRINT_ERROR2(resetAttributesError, hr);
PRINT_ERROR2(ResyncIEnrollRequestStoreError, hr);
PRINT_ERROR2(setPendingRequestInfoWStrError, hr);
}
BOOL TXEnrollPendingAPITester::TestProperty_ThumbPrintWStr(IEnroll4 *pIEnroll4)
{
DWORD const dw_NUM_CASES = 3;
BOOL fResult;
CRYPT_DATA_BLOB hashBlobs [dw_NUM_CASES];
CRYPT_DATA_BLOB hashBlobsExpected [dw_NUM_CASES];
CRYPT_DATA_BLOB pkcs10Blobs [dw_NUM_CASES];
DWORD dwCase;
DWORD dwRequestIDExpected;
HRESULT hr = S_OK;
LONG lIndex;
PCCERT_CONTEXT pCertContexts [dw_NUM_CASES];
WCHAR wszDNName[] = L"CN=Xenroll TestProperty_ThumbPrintWStr Test";
PENDING_INFO pendingInfo =
{ 100, L"duncanb.ntdev.microsoft.com", L"ThumbPrint Test", L"TT Test", 0, NULL, S_OK };
ZeroMemory(&hashBlobs[0], sizeof(hashBlobs));
ZeroMemory(&hashBlobsExpected[0], sizeof(hashBlobsExpected));
ZeroMemory(&pkcs10Blobs[0], sizeof(pkcs10Blobs));
ZeroMemory(&pCertContexts[0], sizeof(pCertContexts));
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Declare locally-scoped helper functions:
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
TXEnrollLocalScope(TestProperty_ThumbPrintWStrHelper):
HRESULT GetThumbPrintAndCertContext(IN IEnroll4 *pIEnroll4,
IN CRYPT_DATA_BLOB pkcs10Request,
OUT PCRYPT_DATA_BLOB pThumbPrintBlob,
OUT PCCERT_CONTEXT *ppCertContext)
{
HRESULT hr;
pThumbPrintBlob->pbData = NULL;
*ppCertContext = NULL;
*ppCertContext = GetCertOutOfRequestStore(&pkcs10Request);
if (NULL == *ppCertContext)
goto GetCertOutOfRequestStoreError;
// Use get_ThumbPrintWStr to get the hash of the request.
if (S_OK != (hr = pIEnroll4->get_ThumbPrintWStr(pThumbPrintBlob)))
goto get_ThumbPrintWStrError;
pThumbPrintBlob->pbData = (LPBYTE)LocalAlloc(LPTR, pThumbPrintBlob->cbData);
if (NULL == pThumbPrintBlob->pbData)
goto MemoryError;
if (S_OK != (hr = pIEnroll4->get_ThumbPrintWStr(pThumbPrintBlob)))
goto get_ThumbPrintWStrError;
hr = S_OK;
CommonReturn:
return hr;
ErrorReturn:
if (NULL != pThumbPrintBlob->pbData) { LocalFree(pThumbPrintBlob->pbData); }
if (NULL != *ppCertContext) { CertDeleteCertificateFromStore(*ppCertContext); }
pThumbPrintBlob->pbData = NULL;
*ppCertContext = NULL;
goto CommonReturn;
PRINT_ERROR2(get_ThumbPrintWStrError, hr);
PRINT_ERROR2(GetCertOutOfRequestStoreError, hr = GetLastError());
PRINT_ERROR2(MemoryError, hr = E_OUTOFMEMORY);
}
TXEnrollEndLocalScope;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Case 0: Check that thumbprint returned is the hash of the last created cert.
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
dwCase = 0;
if (S_OK != (hr = pIEnroll4->resetExtensions()))
goto resetExtensionsError;
if (S_OK != (hr = pIEnroll4->resetAttributes()))
goto resetAttributesError;
// Small key size so the test runs faster.
if (S_OK != (hr = pIEnroll4->put_GenKeyFlags(384 << 16)))
goto put_GenKeyFlagsError;
// Create a request to test on.
if (S_OK != (hr = pIEnroll4->createRequestWStr
(XECR_PKCS10_V2_0,
wszDNName,
NULL,
&pkcs10Blobs[dwCase])))
goto createRequestWStrError;
// Make sure xenroll syncs up its request store!
if (S_OK != (hr = ResyncIEnrollRequestStore(&pIEnroll4)))
goto ResyncIEnrollRequestStoreError;
// Get a PCCERT_CONTEXT and thumbprint from the request:
if (S_OK != (hr = local.GetThumbPrintAndCertContext
(pIEnroll4,
pkcs10Blobs[dwCase],
&hashBlobs[dwCase],
&pCertContexts[dwCase])))
goto GetThumbPrintAndCertContextError;
// Manually get the HASH of the request.
if (S_OK != (hr = GetCertificateContextPropertySimple
(pCertContexts[dwCase],
CERT_HASH_PROP_ID,
&hashBlobsExpected[dwCase])))
goto GetCertificateContextPropertySimpleError;
if (!
((hashBlobs[dwCase].cbData == hashBlobsExpected[dwCase].cbData) &&
(0 == memcmp(hashBlobs[dwCase].pbData, hashBlobsExpected[dwCase].pbData, hashBlobs[dwCase].cbData))))
goto get_ThumbPrintWStrError;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Case 1: Make sure that put_ThumbPrintWStr is used as the target of setPendingInfoWStr().
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
dwCase++;
// Flush the first request from the pending cache.
//
if (S_OK != (hr = pIEnroll4->createRequestWStr
(XECR_PKCS10_V2_0,
wszDNName,
NULL,
&pkcs10Blobs[dwCase])))
goto createRequestWStrError;
// Make sure xenroll syncs up its request store!
if (S_OK != (hr = ResyncIEnrollRequestStore(&pIEnroll4)))
goto ResyncIEnrollRequestStoreError;
// Get a PCCERT_CONTEXT and thumbprint from the request:
if (S_OK != (hr = local.GetThumbPrintAndCertContext
(pIEnroll4,
pkcs10Blobs[dwCase],
&hashBlobs[dwCase],
&pCertContexts[dwCase])))
goto GetThumbPrintAndCertContextError;
// Manually specify the previous request through put_ThumbPrint:
if (S_OK != (hr = pIEnroll4->put_ThumbPrintWStr(hashBlobs[dwCase-1])))
goto put_ThumbPrintWStrError;
if (S_OK != (hr = pIEnroll4->setPendingRequestInfoWStr
(pendingInfo.dwRequestID,
pendingInfo.pwszCADNS,
pendingInfo.pwszCAName,
pendingInfo.pwszFriendlyName)))
goto setPendingRequestInfoWStrError;
if (S_OK != (hr = FindPendingRequest(pIEnroll4, pCertContexts[dwCase-1], S_OK, &lIndex)))
goto FindPendingRequestError;
// Success -- if put_ThumbPrintWstr was not working correctly, it would not be possible
// to find pending info associated with the previous cert context.
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Case 2: Make sure that put_ThumbPrintWStr is used as the target of get_ThumbPrintWStr
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
dwCase++;
// Flush the previous request from the pending cache.
//
if (S_OK != (hr = pIEnroll4->createRequestWStr
(XECR_PKCS10_V2_0,
wszDNName,
NULL,
&pkcs10Blobs[dwCase])))
goto createRequestWStrError;
// Make sure xenroll syncs up its request store!
if (S_OK != (hr = ResyncIEnrollRequestStore(&pIEnroll4)))
goto ResyncIEnrollRequestStoreError;
pCertContexts[dwCase] = GetCertOutOfRequestStore(&pkcs10Blobs[dwCase]);
if (NULL == pCertContexts[dwCase])
goto GetCertOutOfRequestStoreError;
// Manually specify a request through put_ThumbPrint:
//
if (S_OK != (hr = pIEnroll4->put_ThumbPrintWStr(hashBlobs[dwCase-1])))
goto put_ThumbPrintWStrError;
// Extract the request through get_ThumbPrintWStr:
//
if (S_OK != (hr = pIEnroll4->get_ThumbPrintWStr(&hashBlobs[dwCase])))
goto put_ThumbPrintWStrError;
hashBlobs[dwCase].pbData = (LPBYTE)LocalAlloc(LPTR, hashBlobs[dwCase].cbData);
if (NULL == hashBlobs[dwCase].pbData)
goto MemoryError;
if (S_OK != (hr = pIEnroll4->get_ThumbPrintWStr(&hashBlobs[dwCase])))
goto put_ThumbPrintWStrError;
if (!
((hashBlobs[dwCase].cbData == hashBlobs[dwCase-1].cbData) &&
(0 == memcmp(hashBlobs[dwCase].pbData, hashBlobs[dwCase-1].pbData, hashBlobs[dwCase].cbData))))
goto get_ThumbPrintWStrError;
fResult = TRUE;
CommonReturn:
if (NULL != pIEnroll4) { pIEnroll4->Release(); }
for (dwCase = 0; dwCase < dw_NUM_CASES; dwCase++)
{
if (NULL != pkcs10Blobs[dwCase].pbData) { LocalFree(pkcs10Blobs[dwCase].pbData); }
if (NULL != hashBlobs[dwCase].pbData) { LocalFree(hashBlobs[dwCase].pbData); }
if (NULL != hashBlobsExpected[dwCase].pbData) { LocalFree(hashBlobsExpected[dwCase].pbData); }
if (NULL != pCertContexts[dwCase]) { CertDeleteCertificateFromStore(pCertContexts[dwCase]); }
}
return fResult;
ErrorReturn:
fResult = FALSE;
SetLastError(hr);
goto CommonReturn;
PRINT_ERROR2(createRequestWStrError, hr);
PRINT_ERROR2(FindPendingRequestError, hr);
PRINT_ERROR2(get_ThumbPrintWStrError, hr);
PRINT_ERROR(GetCertOutOfRequestStoreError);
PRINT_ERROR2(GetCertificateContextPropertySimpleError, hr);
PRINT_ERROR2(GetThumbPrintAndCertContextError, hr);
PRINT_ERROR2(MemoryError, E_OUTOFMEMORY);
PRINT_ERROR2(put_GenKeyFlagsError, hr);
PRINT_ERROR2(put_ThumbPrintWStrError, hr);
PRINT_ERROR2(resetAttributesError, hr);
PRINT_ERROR2(resetExtensionsError, hr);
PRINT_ERROR2(ResyncIEnrollRequestStoreError, hr);
PRINT_ERROR2(setPendingRequestInfoWStrError, hr);
}
BOOL TXEnrollPendingAPITester::TestMethod_enumPendingRequestWStr(IEnroll4 *pIEnroll4,
CRYPT_DATA_BLOB pkcs10Blob,
PENDING_INFO *pPendingInfo)
{
BOOL fResult;
CRYPT_DATA_BLOB caDNSBlob;
CRYPT_DATA_BLOB caNameBlob;
CRYPT_DATA_BLOB friendlyNameBlob;
CRYPT_DATA_BLOB hashBlob;
CRYPT_DATA_BLOB hashBlobExpected;
CRYPT_DATA_BLOB v1TemplateNameBlob;
DWORD dwRequestID;
FILETIME ftDate;
FILETIME ftDateExpected;
HRESULT hr = S_OK;
LONG lIndex;
PCCERT_CONTEXT pCertContext = NULL;
// Init:
ZeroMemory(&caDNSBlob, sizeof(CRYPT_DATA_BLOB));
ZeroMemory(&caNameBlob, sizeof(CRYPT_DATA_BLOB));
ZeroMemory(&friendlyNameBlob, sizeof(CRYPT_DATA_BLOB));
ZeroMemory(&hashBlob, sizeof(CRYPT_DATA_BLOB));
ZeroMemory(&hashBlobExpected, sizeof(CRYPT_DATA_BLOB));
ZeroMemory(&v1TemplateNameBlob, sizeof(CRYPT_DATA_BLOB));
if (NULL == pIEnroll4 || NULL == pPendingInfo)
goto InvalidArgError;
pCertContext = GetCertOutOfStore(&pkcs10Blob, pPendingInfo->dwStoreFlags, pPendingInfo->pwszStoreName);
if (NULL == pCertContext)
goto GetCertOutOfStoreError;
if (S_OK != (hr = GetCertificateContextPropertySimple
(pCertContext,
CERT_HASH_PROP_ID,
&hashBlobExpected)))
goto GetCertificateContextPropertySimpleError;
// Initialize the enumeration.
if (S_OK != (hr = pIEnroll4->enumPendingRequestWStr(XEPR_ENUM_FIRST, 0, NULL)))
goto enumPendingRequestWStrError;
for (lIndex = 0; TRUE; lIndex++) // Find the index of the pending request in the request store:
{
hashBlob.pbData = NULL;
hashBlob.cbData = 0;
if (S_OK != (hr = pIEnroll4->enumPendingRequestWStr
(lIndex,
XEPR_HASH,
(LPVOID)&hashBlob)))
goto enumPendingRequestWStrError;
hashBlob.pbData = (LPBYTE)LocalAlloc(LPTR, hashBlob.cbData);
if (NULL == hashBlob.pbData)
goto MemoryError;
if (S_OK != (hr = pIEnroll4->enumPendingRequestWStr
(lIndex,
XEPR_HASH,
(LPVOID)&hashBlob)))
goto enumPendingRequestWStrError;
// We've found the request we want.
if ((hashBlobExpected.cbData == hashBlob.cbData) &&
(0 == memcmp(hashBlobExpected.pbData, hashBlob.pbData, hashBlob.cbData)))
break;
}
// Test XEPR_REQUESTID property:
if (S_OK != (hr = pIEnroll4->enumPendingRequestWStr(lIndex, XEPR_REQUESTID, (LPVOID)&dwRequestID)))
goto enumPendingRequestWStrError;
if (dwRequestID != pPendingInfo->dwRequestID)
goto pendingInfoDoesntMatchError;
// Test XEPR_CANAME property:
caNameBlob.pbData = NULL;
if (S_OK != (hr = pIEnroll4->enumPendingRequestWStr(lIndex, XEPR_CANAME, (LPVOID)&caNameBlob)))
goto enumPendingRequestWStrError;
caNameBlob.pbData = (LPBYTE)LocalAlloc(LPTR, caNameBlob.cbData);
if (NULL == caNameBlob.pbData)
goto MemoryError;
if (S_OK != (hr = pIEnroll4->enumPendingRequestWStr(lIndex, XEPR_CANAME, (LPVOID)&caNameBlob)))
goto enumPendingRequestWStrError;
if (0 != wcscmp((LPWSTR)caNameBlob.pbData, pPendingInfo->pwszCAName))
goto enumPendingRequestWStrError;
// Test XEPR_CADNS property:
caDNSBlob.pbData = NULL;
if (S_OK != (hr = pIEnroll4->enumPendingRequestWStr(lIndex, XEPR_CADNS, (LPVOID)&caDNSBlob)))
goto enumPendingRequestWStrError;
caDNSBlob.pbData = (LPBYTE)LocalAlloc(LPTR, caDNSBlob.cbData);
if (NULL == caDNSBlob.pbData)
goto MemoryError;
if (S_OK != (hr = pIEnroll4->enumPendingRequestWStr(lIndex, XEPR_CADNS, (LPVOID)&caDNSBlob)))
goto enumPendingRequestWStrError;
if (0 != wcscmp((LPWSTR)caDNSBlob.pbData, pPendingInfo->pwszCADNS))
goto enumPendingRequestWStrError;
// Test XEPR_CAFRIENDLYNAME property:
// Note: it is legal to pass NULL when setting the friendly name property. In this case,
// the friendly name property is set to the empty string.
if (NULL == pPendingInfo->pwszFriendlyName) { pPendingInfo->pwszFriendlyName = L""; }
friendlyNameBlob.pbData = NULL;
if (S_OK != (hr = pIEnroll4->enumPendingRequestWStr(lIndex, XEPR_CAFRIENDLYNAME, (LPVOID)&friendlyNameBlob)))
goto enumPendingRequestWStrError;
friendlyNameBlob.pbData = (LPBYTE)LocalAlloc(LPTR, friendlyNameBlob.cbData);
if (NULL == friendlyNameBlob.pbData)
goto MemoryError;
if (S_OK != (hr = pIEnroll4->enumPendingRequestWStr(lIndex, XEPR_CAFRIENDLYNAME, (LPVOID)&friendlyNameBlob)))
goto enumPendingRequestWStrError;
if (0 != wcscmp((LPWSTR)friendlyNameBlob.pbData, pPendingInfo->pwszFriendlyName))
goto enumPendingRequestWStrError;
// Test XEPR_V1TEMPLATENAME property:
#if 0
v1TemplateNameBlob.pbData = NULL;
if (S_OK != (hr = pIEnroll4->enumPendingRequestWStr(lIndex, XEPR_V1TEMPLATENAME, (LPVOID)&v1TemplateNameBlob)))
goto enumPendingRequestWStrError;
v1TemplateNameBlob.pbData = (LPBYTE)LocalAlloc(LPTR, v1TemplateNameBlob.cbData);
if (NULL == v1TemplateNameBlob.pbData)
goto ErrorReturn;
if (S_OK != (hr = pIEnroll4->enumPendingRequestWStr(lIndex, XEPR_V1TEMPLATENAME, (LPVOID)&v1TemplateNameBlob)))
goto enumPendingRequestWStrError;
if (0 != wcscmp(pwszV1TemplateNameExpected, (LPWSTR)v1TemplateNameBlob.pbData))
goto enumPendingRequestWStrError;
#endif
// Test XEPR_DATE property:
if (S_OK != (hr = pIEnroll4->enumPendingRequestWStr(lIndex, XEPR_DATE, (LPVOID)&ftDate)))
goto enumPendingRequestWStrError;
ftDateExpected = pCertContext->pCertInfo->NotAfter;
if (0 != memcmp((LPVOID)&ftDateExpected, (LPVOID)&ftDate, sizeof(FILETIME)))
goto enumPendingRequestWStrError;
// Test XEPR_V2TEMPLATEOID property:
// XEPR_V2TEMPLATEOID property not yet impl.
// Test XEPR_VERSION property:
// XEPR_VERSION property not yet impl.
fResult = TRUE;
CommonReturn:
if (NULL != caDNSBlob.pbData) { LocalFree(caDNSBlob.pbData); }
if (NULL != caNameBlob.pbData) { LocalFree(caNameBlob.pbData); }
if (NULL != friendlyNameBlob.pbData) { LocalFree(friendlyNameBlob.pbData); }
if (NULL != hashBlob.pbData) { LocalFree(hashBlob.pbData); }
if (NULL != v1TemplateNameBlob.pbData) { LocalFree(v1TemplateNameBlob.pbData); }
if (NULL != pCertContext) { CertFreeCertificateContext(pCertContext); }
return fResult;
ErrorReturn:
fResult = FALSE;
SetLastError(hr);
goto CommonReturn;
PRINT_ERROR2(enumPendingRequestWStrError, hr);
PRINT_ERROR2(GetCertificateContextPropertySimpleError, hr);
PRINT_ERROR2(GetCertOutOfStoreError, hr = GetLastError());
PRINT_ERROR2(InvalidArgError, hr = E_INVALIDARG);
PRINT_ERROR2(MemoryError, hr = E_OUTOFMEMORY);
PRINT_ERROR2(pendingInfoDoesntMatchError, hr = E_FAIL);
}
BOOL TXEnrollPendingAPITester::TestMethod_setPendingInfoWStr(IEnroll4 *pIEnroll4,
CRYPT_DATA_BLOB pkcs10Blob,
PENDING_INFO *pPendingInfo)
{
BOOL fResult;
CRYPT_DATA_BLOB dataBlob;
DWORD dwSize;
LPBYTE pbPendingInfo;
HRESULT hr = S_OK;
PCCERT_CONTEXT pCertContext = NULL;
WCHAR wszDNNName[] = L"CN=Xenroll setPendingInfoWStr Test 1";
ZeroMemory(&dataBlob, sizeof(dataBlob));
if (NULL == pIEnroll4 || NULL == pPendingInfo)
goto InvalidArgError;
hr = pIEnroll4->setPendingRequestInfoWStr
(pPendingInfo->dwRequestID,
pPendingInfo->pwszCADNS,
pPendingInfo->pwszCAName,
pPendingInfo->pwszFriendlyName);
if (hr != pPendingInfo->hrExpectedResult)
goto setPendingRequestInfoWStrError;
if (hr != S_OK)
{
// This test was supposed to fail.
fResult = TRUE;
goto CommonReturn;
}
pCertContext = GetCertOutOfStore(&pkcs10Blob, pPendingInfo->dwStoreFlags, pPendingInfo->pwszStoreName);
if (NULL == pCertContext)
goto GetCertOutOfStoreError;
if (!CertGetCertificateContextProperty
(pCertContext,
CERT_ENROLLMENT_PROP_ID,
NULL,
&(dataBlob.cbData)))
goto CertGetCertificateContextPropertyError;
dataBlob.pbData = (LPBYTE)LocalAlloc(LPTR, dataBlob.cbData);
if (NULL == dataBlob.pbData)
goto MemoryError;
if (!CertGetCertificateContextProperty
(pCertContext,
CERT_ENROLLMENT_PROP_ID,
dataBlob.pbData,
&(dataBlob.cbData)))
goto CertGetCertificateContextPropertyError;
// Is request ID set correctly?
pbPendingInfo = dataBlob.pbData;
if (0 != memcmp(pbPendingInfo, &pPendingInfo->dwRequestID, sizeof(DWORD)))
goto setPendingRequestInfoWStrError;
pbPendingInfo += sizeof(DWORD);
// Is CADNS set correctly?
dwSize = wcslen(pPendingInfo->pwszCADNS) + 1;
if (0 != memcmp(pbPendingInfo, &dwSize, sizeof(DWORD)))
goto setPendingRequestInfoWStrError;
pbPendingInfo += sizeof(DWORD);
if (0 != memcmp(pbPendingInfo, pPendingInfo->pwszCADNS, sizeof(WCHAR) * dwSize))
goto setPendingRequestInfoWStrError;
pbPendingInfo += sizeof(WCHAR) * dwSize;
// Is CAName set correctly?
dwSize = wcslen(pPendingInfo->pwszCAName) + 1;
if (0 != memcmp(pbPendingInfo, &dwSize, sizeof(DWORD)))
goto setPendingRequestInfoWStrError;
pbPendingInfo += sizeof(DWORD);
if (0 != memcmp(pbPendingInfo, pPendingInfo->pwszCAName, sizeof(WCHAR) * dwSize))
goto setPendingRequestInfoWStrError;
pbPendingInfo += sizeof(WCHAR) * dwSize;
// Is friendly name set correctly?
// Note: it is legal to pass NULL when setting the friendly name property. In this case,
// the friendly name property is set to the empty string.
if (NULL == pPendingInfo->pwszFriendlyName) { pPendingInfo->pwszFriendlyName = L""; }
dwSize = wcslen(pPendingInfo->pwszFriendlyName) + 1;
if (0 != memcmp(pbPendingInfo, &dwSize, sizeof(DWORD)))
goto setPendingRequestInfoWStrError;
pbPendingInfo += sizeof(DWORD);
if (0 != memcmp(pbPendingInfo, pPendingInfo->pwszFriendlyName, sizeof(WCHAR) * dwSize))
goto setPendingRequestInfoWStrError;
pbPendingInfo += sizeof(WCHAR) * dwSize;
// Success!
fResult = TRUE;
CommonReturn:
if (NULL != dataBlob.pbData) { LocalFree(dataBlob.pbData); }
if (NULL != pCertContext) { CertFreeCertificateContext(pCertContext); }
return fResult;
ErrorReturn:
fResult = FALSE;
SetLastError(hr);
goto CommonReturn;
PRINT_ERROR2(CertGetCertificateContextPropertyError, hr = GetLastError());
PRINT_ERROR2(GetCertOutOfStoreError, hr = GetLastError());
PRINT_ERROR2(InvalidArgError, hr = E_INVALIDARG);
PRINT_ERROR2(MemoryError, hr = E_OUTOFMEMORY);
PRINT_ERROR2(setPendingRequestInfoWStrError, hr);
}
static BOOL WriteBlobToFile(LPCWSTR wszFile, DWORD dwFlags, PCRYPT_DATA_BLOB pBlob) {
HANDLE hFile = NULL;
BOOL fRet = TRUE;
DWORD cb = 0;
// open the File
if( fRet = ((hFile = CreateFileW(
wszFile,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL)) != NULL && hFile != INVALID_HANDLE_VALUE) ) {
// write out the data
fRet = WriteFile(
hFile,
pBlob->pbData,
pBlob->cbData,
&cb,
NULL);
CloseHandle(hFile);
}
return(fRet);
}
// Basic operation, create keys, gen request, accept cert.
BOOL Test1() {
IEnroll * pIEnroll = NULL;
PCRYPT_DATA_BLOB pBlobPKCS7 = NULL;
CRYPT_DATA_BLOB blobPKCS10;
BYTE arSha1Hash[20];
CRYPT_HASH_BLOB hash = {sizeof(arSha1Hash), arSha1Hash};
BOOL fRet = TRUE;
DWORD Err = GetLastError();
HRESULT hr = S_OK;
LPWSTR szwHashAlg = NULL;
memset(&blobPKCS10, 0, sizeof(blobPKCS10));
// TEST 1 Normal usage
pIEnroll = PIEnrollGetNoCOM();
if(S_OK != pIEnroll->get_HashAlgorithmWStr(&szwHashAlg) ||
wcscmp(szwHashAlg, L"1.3.14.3.2.26") ) {
SetLastError(NTE_BAD_HASH);
goto ErrorNoHashAlg;
}
if(S_OK != pIEnroll->put_HashAlgorithmWStr(L"MD2") ) {
SetLastError(NTE_BAD_HASH);
goto ErrorNoHashAlg;
}
if(S_OK != pIEnroll->get_HashAlgorithmWStr(&szwHashAlg) ||
wcscmp(szwHashAlg, L"1.2.840.113549.2.2") ) {
SetLastError(NTE_BAD_HASH);
goto ErrorNoHashAlg;
}
// enroll for a new cert
if( S_OK != (hr = pIEnroll->createPKCS10WStr(L"CN=XEnroll Test", L"1.2.3.4, 1.2.6.7", &blobPKCS10)) ) {
SetLastError(hr);
goto ErrorCreatePkCS10;
}
if( NULL == (pBlobPKCS7 = MakePKCS7Response(&blobPKCS10, &hash)) )
goto ErrorMakePKCS7Response;
// accept the new cert
if( S_OK != (hr = pIEnroll->acceptPKCS7Blob(pBlobPKCS7)) ) {
SetLastError(hr);
goto ErrorAcceptPKCS7;
}
if( !RemoveCertFromStore(&hash, L"MY", CERT_SYSTEM_STORE_CURRENT_USER) )
goto ErrorRemoveCertFromStore;
CommonReturn:
if(pBlobPKCS7 != NULL)
free(pBlobPKCS7);
if(pIEnroll != NULL)
pIEnroll->Release();
if(blobPKCS10.pbData != NULL)
LocalFree(blobPKCS10.pbData);
SetLastError(Err);
return(fRet);
ErrorReturn:
Err = GetLastError();
fRet = FALSE;
goto CommonReturn;
PRINT_ERROR(ErrorNoHashAlg);
PRINT_ERROR(ErrorCreatePkCS10);
PRINT_ERROR(ErrorAcceptPKCS7);
PRINT_ERROR(ErrorMakePKCS7Response);
PRINT_ERROR(ErrorRemoveCertFromStore);
}
// Test basic operation but with no EKU or no DN name
BOOL Test2() {
IEnroll * pIEnroll = NULL;
PCRYPT_DATA_BLOB pBlobPKCS7 = NULL;
CRYPT_DATA_BLOB blobPKCS10;
BYTE arSha1Hash[20];
CRYPT_HASH_BLOB hash = {sizeof(arSha1Hash), arSha1Hash};
BOOL fRet = TRUE;
DWORD Err = GetLastError();
HRESULT hr = S_OK;
// TEST 1 Normal usage
pIEnroll = PIEnrollGetNoCOM();
// enroll for a new cert
memset(&blobPKCS10, 0, sizeof(blobPKCS10));
if( S_OK != (hr = pIEnroll->createPKCS10WStr(NULL, NULL, &blobPKCS10)) ) {
SetLastError(hr);
goto ErrorCreatePkCS10;
}
if( NULL == (pBlobPKCS7 = MakePKCS7Response(&blobPKCS10, &hash)) )
goto ErrorMakePKCS7Response;
// accept the new cert
if( S_OK != (hr = pIEnroll->acceptPKCS7Blob(pBlobPKCS7)) ) {
SetLastError(hr);
goto ErrorAcceptPKCS7;
}
if( !RemoveCertFromStore(&hash, L"MY", CERT_SYSTEM_STORE_CURRENT_USER) )
goto ErrorRemoveCertFromStore;
CommonReturn:
if(pBlobPKCS7 != NULL)
free(pBlobPKCS7);
if(pIEnroll != NULL)
pIEnroll->Release();
if(blobPKCS10.pbData != NULL)
LocalFree(blobPKCS10.pbData);
SetLastError(Err);
return(fRet);
ErrorReturn:
Err = GetLastError();
fRet = FALSE;
goto CommonReturn;
PRINT_ERROR(ErrorCreatePkCS10);
PRINT_ERROR(ErrorAcceptPKCS7);
PRINT_ERROR(ErrorMakePKCS7Response);
PRINT_ERROR(ErrorRemoveCertFromStore);
}
// Test Renewal, Create original cert, create renewal request, create renewed cert
BOOL Test3() {
IEnroll * pIEnroll = NULL;
IEnroll * pIEnroll2 = NULL;
PCRYPT_DATA_BLOB pBlobPKCS7 = NULL;
PCRYPT_DATA_BLOB pBlobPKCS72 = NULL;
PCRYPT_DATA_BLOB pBlobPKCS102 = NULL;
PCCERT_CONTEXT pCert1 = NULL;
CRYPT_DATA_BLOB blobPKCS10;
CRYPT_DATA_BLOB blobPKCS102;
BYTE arSha1Hash[20];
BYTE arSha1Hash2[20];
CRYPT_HASH_BLOB hash = {sizeof(arSha1Hash), arSha1Hash};
CRYPT_HASH_BLOB hash2 = {sizeof(arSha1Hash2), arSha1Hash2};
BOOL fRet = TRUE;
DWORD Err = GetLastError();
HRESULT hr = S_OK;
// TEST 1 Normal usage
pIEnroll = PIEnrollGetNoCOM();
// enroll for a new cert
memset(&blobPKCS10, 0, sizeof(blobPKCS10));
if( S_OK != (hr = pIEnroll->createPKCS10WStr(NULL, NULL, &blobPKCS10)) ) {
SetLastError(hr);
goto ErrorCreatePkCS10;
}
if( NULL == (pBlobPKCS7 = MakePKCS7Response(&blobPKCS10, &hash)) )
goto ErrorMakePKCS7Response;
// accept the new cert
if( S_OK != (hr = pIEnroll->acceptPKCS7Blob(pBlobPKCS7)) ) {
SetLastError(hr);
goto ErrorAcceptPKCS7;
}
// get the cert just created
if( NULL == (pCert1 = pIEnroll->getCertContextFromPKCS7(pBlobPKCS7)) ) {
goto ErrorGetCertContextFromPKCS7;
}
pIEnroll2 = PIEnrollGetNoCOM();
// enroll for a new cert, Really I will get a 7 back with a 10 in it.
if( S_OK != (hr = pIEnroll2->put_RenewalCertificate(pCert1)) ) {
SetLastError(hr);
goto ErrorPut_RenewalCertificate;
}
memset(&blobPKCS102, 0, sizeof(blobPKCS102));
if( S_OK != (hr = pIEnroll2->createPKCS10WStr(NULL, NULL, &blobPKCS102)) ) {
SetLastError(hr);
goto ErrorCreatePkCS10;
}
// get the pkcs10 from the pkcs7
if( NULL == (pBlobPKCS102 = GetPKCS10FromPKCS7(&blobPKCS102)) )
goto ErrorGetPKCS10FromPKCS7;
// make the response
if( NULL == (pBlobPKCS72 = MakePKCS7Response(pBlobPKCS102, &hash2)) )
goto ErrorMakePKCS7Response;
// accept the new cert
if( S_OK != (hr = pIEnroll2->acceptPKCS7Blob(pBlobPKCS72)) ) {
SetLastError(hr);
goto ErrorAcceptPKCS7;
}
if( !RemoveCertFromStore(&hash2, L"MY", CERT_SYSTEM_STORE_CURRENT_USER) )
goto ErrorRemoveCertFromStore;
if( !RemoveCertFromStore(&hash, L"MY", CERT_SYSTEM_STORE_CURRENT_USER) )
goto ErrorRemoveCertFromStore;
CommonReturn:
if(pCert1 != NULL)
CertFreeCertificateContext(pCert1);
if(pBlobPKCS7 != NULL)
free(pBlobPKCS7);
if(pBlobPKCS72 != NULL)
free(pBlobPKCS72);
if(pBlobPKCS102 != NULL)
free(pBlobPKCS102);
if(pIEnroll != NULL)
pIEnroll->Release();
if(pIEnroll2 != NULL)
pIEnroll2->Release();
if(blobPKCS10.pbData != NULL)
LocalFree(blobPKCS10.pbData);
if(blobPKCS102.pbData != NULL)
LocalFree(blobPKCS102.pbData);
SetLastError(Err);
return(fRet);
ErrorReturn:
Err = GetLastError();
fRet = FALSE;
goto CommonReturn;
PRINT_ERROR(ErrorCreatePkCS10);
PRINT_ERROR(ErrorAcceptPKCS7);
PRINT_ERROR(ErrorMakePKCS7Response);
PRINT_ERROR(ErrorRemoveCertFromStore);
PRINT_ERROR(ErrorGetCertContextFromPKCS7);
PRINT_ERROR(ErrorGetPKCS10FromPKCS7);
PRINT_ERROR(ErrorPut_RenewalCertificate);
}
// Basic operation, create keys, gen request, accept cert, but put the certs in HKLM
BOOL Test4() {
IEnroll * pIEnroll = NULL;
PCRYPT_DATA_BLOB pBlobPKCS7 = NULL;
CRYPT_DATA_BLOB blobPKCS10;
BYTE arSha1Hash[20];
CRYPT_HASH_BLOB hash = {sizeof(arSha1Hash), arSha1Hash};
BOOL fRet = TRUE;
DWORD Err = GetLastError();
HRESULT hr = S_OK;
// TEST 1 Normal usage
if( NULL == (pIEnroll = PIEnrollGetNoCOM()))
goto ErrorPIEnrollGetNoCOM;
// say I want the result in HKLM
pIEnroll->put_MyStoreFlags(CERT_SYSTEM_STORE_LOCAL_MACHINE);
// enroll for a new cert
memset(&blobPKCS10, 0, sizeof(blobPKCS10));
if( S_OK != (hr = pIEnroll->createPKCS10WStr(L"CN=XEnroll Test", L"1.2.3.4", &blobPKCS10)) ) {
SetLastError(hr);
goto ErrorCreatePkCS10;
}
pIEnroll->Release();
if( NULL == (pIEnroll = PIEnrollGetNoCOM()))
goto ErrorPIEnrollGetNoCOM;
if( NULL == (pBlobPKCS7 = MakePKCS7ResponseMachine(&blobPKCS10, &hash)) )
goto ErrorMakePKCS7Response;
//this is new xenroll instance, set to machine store
pIEnroll->put_MyStoreFlags(CERT_SYSTEM_STORE_LOCAL_MACHINE);
// accept the new cert
if( S_OK != (hr = pIEnroll->acceptPKCS7Blob(pBlobPKCS7)) ) {
SetLastError(hr);
goto ErrorAcceptPKCS7;
}
if( !RemoveCertFromStore(&hash, L"MY", CERT_SYSTEM_STORE_LOCAL_MACHINE) )
goto ErrorRemoveCertFromStore;
CommonReturn:
if(pBlobPKCS7 != NULL)
free(pBlobPKCS7);
if(pIEnroll != NULL)
pIEnroll->Release();
if(blobPKCS10.pbData != NULL)
LocalFree(blobPKCS10.pbData);
SetLastError(Err);
return(fRet);
ErrorReturn:
Err = GetLastError();
fRet = FALSE;
goto CommonReturn;
PRINT_ERROR(ErrorPIEnrollGetNoCOM);
PRINT_ERROR(ErrorCreatePkCS10);
PRINT_ERROR(ErrorAcceptPKCS7);
PRINT_ERROR(ErrorMakePKCS7Response);
PRINT_ERROR(ErrorRemoveCertFromStore);
}
BOOL Test5() {
#define DNNAME L"CN=Test"
DWORD Err = GetLastError();
BOOL fRet = TRUE;
HCRYPTPROV hProv = NULL;
HCRYPTKEY hKey = NULL;
PCCERT_CONTEXT pCertContext = NULL;
DWORD dwFlagsT = 0;
CERT_NAME_BLOB nameBlob;
CRYPT_KEY_PROV_INFO keyProvInfo;
GUID guidContainerName;
SYSTEMTIME startTime;
SYSTEMTIME endTime;
memset(&keyProvInfo, 0, sizeof(CRYPT_KEY_PROV_INFO));
memset(&nameBlob, 0, sizeof(CERT_NAME_BLOB));
memset(&guidContainerName, 0, sizeof(GUID));
// get a container based on a guid
UuidCreate(&guidContainerName);
UuidToStringW(&guidContainerName, &keyProvInfo.pwszContainerName);
keyProvInfo.pwszProvName = L"";
keyProvInfo.dwProvType = PROV_RSA_FULL;
keyProvInfo.dwFlags = 0;
keyProvInfo.cProvParam = 0;
keyProvInfo.rgProvParam = NULL;
keyProvInfo.dwKeySpec = AT_SIGNATURE;
if( !CryptAcquireContextW(&hProv,
keyProvInfo.pwszContainerName,
keyProvInfo.pwszProvName,
keyProvInfo.dwProvType,
CRYPT_NEWKEYSET) ) {
hProv = NULL;
goto ErrorCryptAcquireContext;
}
// we better not have a key here, so gen it
if(!CryptGenKey( hProv,
keyProvInfo.dwKeySpec,
0,
&hKey) )
goto ErrorCryptGenKey;
// get the Subject DN only if one is specified
if( !CertStrToNameW(
CRYPT_ASN_ENCODING,
DNNAME,
0,
NULL,
NULL,
&nameBlob.cbData,
NULL) ||
(nameBlob.pbData = (BYTE *) _alloca(nameBlob.cbData)) == NULL ||
!CertStrToNameW(
CRYPT_ASN_ENCODING,
DNNAME,
0,
NULL,
nameBlob.pbData,
&nameBlob.cbData,
NULL) ) {
goto ErrorCertStrToNameW;
}
// check that predefine dates work
memset(&startTime, 0, sizeof(startTime));
startTime.wYear = 1998;
startTime.wMonth = 6;
startTime.wDay = 20;
startTime.wHour = 12;
memset(&endTime, 0, sizeof(endTime));
endTime.wYear = 1998;
endTime.wMonth = 7;
endTime.wDay = 10;
endTime.wHour = 4;
if ( NULL == (pCertContext = CertCreateSelfSignCertificate(
hProv,
&nameBlob,
0,
NULL,
NULL,
&startTime,
&endTime,
NULL
) ) )
goto ErrorCertCreateSelfSignCertificate;
dwFlagsT = CERT_STORE_SIGNATURE_FLAG | CERT_STORE_TIME_VALIDITY_FLAG;
if( !CertVerifySubjectCertificateContext(
pCertContext,
pCertContext,
&dwFlagsT
) )
goto ErrorCertVerifySubjectCertificateContext;
// check the time to see if it is correct
if( pCertContext->pCertInfo->NotBefore.dwLowDateTime != 0xF34E2000 ||
pCertContext->pCertInfo->NotBefore.dwHighDateTime != 0x1BD9C42 ||
pCertContext->pCertInfo->NotAfter.dwLowDateTime != 0x356DE000 ||
pCertContext->pCertInfo->NotAfter.dwHighDateTime != 0x1BDABB7 ) {
SetLastError(ERROR_INVALID_TIME);
goto ErrorDateTime;
}
CommonReturn:
if (hProv != NULL) {
HCRYPTPROV hDeleteProv;
CryptAcquireContextW(&hDeleteProv,
keyProvInfo.pwszContainerName,
keyProvInfo.pwszProvName,
keyProvInfo.dwProvType,
CRYPT_DELETEKEYSET);
}
if(pCertContext !=NULL)
CertFreeCertificateContext(pCertContext);
if(hKey != NULL)
CryptDestroyKey(hKey);
if(keyProvInfo.pwszContainerName != NULL)
RpcStringFreeW(&keyProvInfo.pwszContainerName);
if(hProv != NULL)
CryptReleaseContext(hProv, 0);
SetLastError(Err);
return(fRet);
ErrorReturn:
Err = GetLastError();
fRet = FALSE;
goto CommonReturn;
PRINT_ERROR(ErrorCryptAcquireContext);
PRINT_ERROR(ErrorCertStrToNameW);
PRINT_ERROR(ErrorCryptGenKey);
PRINT_ERROR(ErrorCertVerifySubjectCertificateContext);
PRINT_ERROR(ErrorCertCreateSelfSignCertificate);
PRINT_ERROR(ErrorDateTime);
}
// Basic operation, create keys, gen request, accept cert.
BOOL Test6() {
ICEnroll * pEnroll = NULL;
PCRYPT_DATA_BLOB pBlobPKCS7 = NULL;
BSTR bstrRequest = NULL;
CRYPT_DATA_BLOB blobPKCS10;
BYTE arSha1Hash[20];
CRYPT_HASH_BLOB hash = {sizeof(arSha1Hash), arSha1Hash};
BOOL fRet = TRUE;
DWORD Err = GetLastError();
HRESULT hr = S_OK;
BSTR bstrResponse = NULL;
if( S_OK != CoInitialize(NULL) )
goto ErrorCoInitializeEx;
// TEST 1 Normal usage
if( S_OK != (hr = CoCreateInstance(CLSID_CEnroll, NULL, CLSCTX_INPROC_SERVER, IID_ICEnroll, (void **) &pEnroll)) ) {
SetLastError(hr);
goto ErrorCoCreateInstance;
}
// enroll for a new cert
memset(&blobPKCS10, 0, sizeof(blobPKCS10));
if( S_OK != (hr = pEnroll->createPKCS10(L"CN=XEnroll Test", L"1.2.3.4, 1.2.6.7", &bstrRequest)) ) {
SetLastError(hr);
goto ErrorCreatePkCS10;
}
blobPKCS10.cbData = SysStringByteLen(bstrRequest);
blobPKCS10.pbData = (PBYTE) bstrRequest;
if( NULL == (pBlobPKCS7 = MakePKCS7Response(&blobPKCS10, &hash)) )
goto ErrorMakePKCS7Response;
if( NULL == (bstrResponse = SysAllocStringByteLen((LPCSTR) pBlobPKCS7->pbData, pBlobPKCS7->cbData)) )
goto ErrorSysAllocStringByteLen;
// accept the new cert
if( S_OK != (hr = pEnroll->acceptPKCS7(bstrResponse)) ) {
SetLastError(hr);
goto ErrorAcceptPKCS7;
}
if( !RemoveCertFromStore(&hash, L"MY", CERT_SYSTEM_STORE_CURRENT_USER) )
goto ErrorRemoveCertFromStore;
CommonReturn:
if(pBlobPKCS7 != NULL)
free(pBlobPKCS7);
if(pEnroll != NULL)
pEnroll->Release();
if(bstrResponse != NULL)
SysFreeString(bstrResponse);
CoUninitialize();
SetLastError(Err);
return(fRet);
ErrorReturn:
Err = GetLastError();
fRet = FALSE;
goto CommonReturn;
PRINT_ERROR(ErrorCoInitializeEx);
PRINT_ERROR(ErrorCoCreateInstance);
PRINT_ERROR(ErrorSysAllocStringByteLen);
PRINT_ERROR(ErrorCreatePkCS10);
PRINT_ERROR(ErrorAcceptPKCS7);
PRINT_ERROR(ErrorMakePKCS7Response);
PRINT_ERROR(ErrorRemoveCertFromStore);
}
// Basic operation, create keys, gen request, accept cert, but put the certs in HKLM
BOOL Test7() {
IEnroll * pIEnroll = NULL;
PCRYPT_DATA_BLOB pBlobPKCS7 = NULL;
CRYPT_DATA_BLOB blobPKCS10;
BYTE arSha1Hash[20];
CRYPT_HASH_BLOB hash = {sizeof(arSha1Hash), arSha1Hash};
BOOL fRet = TRUE;
DWORD Err = GetLastError();
HRESULT hr = S_OK;
// TEST 1 Normal usage
if( NULL == (pIEnroll = PIEnrollGetNoCOM()))
goto ErrorPIEnrollGetNoCOM;
// say I want the result in HKLM
pIEnroll->put_RequestStoreFlags(CERT_SYSTEM_STORE_LOCAL_MACHINE);
// enroll for a new cert
memset(&blobPKCS10, 0, sizeof(blobPKCS10));
if( S_OK != (hr = pIEnroll->createPKCS10WStr(L"CN=XEnroll Test", L"1.2.3.4", &blobPKCS10)) ) {
SetLastError(hr);
goto ErrorCreatePkCS10;
}
pIEnroll->Release();
if( NULL == (pIEnroll = PIEnrollGetNoCOM()))
goto ErrorPIEnrollGetNoCOM;
if( NULL == (pBlobPKCS7 = MakePKCS7ResponseMachine(&blobPKCS10, &hash)) )
goto ErrorMakePKCS7Response;
// say I want the result in HKLM
pIEnroll->put_MyStoreFlags(CERT_SYSTEM_STORE_LOCAL_MACHINE);
// accept the new cert
if( S_OK != (hr = pIEnroll->acceptPKCS7Blob(pBlobPKCS7)) ) {
SetLastError(hr);
goto ErrorAcceptPKCS7;
}
if( !RemoveCertFromStore(&hash, L"MY", CERT_SYSTEM_STORE_LOCAL_MACHINE) )
goto ErrorRemoveCertFromStore;
CommonReturn:
if(pBlobPKCS7 != NULL)
free(pBlobPKCS7);
if(pIEnroll != NULL)
pIEnroll->Release();
if(blobPKCS10.pbData != NULL)
LocalFree(blobPKCS10.pbData);
SetLastError(Err);
return(fRet);
ErrorReturn:
Err = GetLastError();
fRet = FALSE;
goto CommonReturn;
PRINT_ERROR(ErrorPIEnrollGetNoCOM);
PRINT_ERROR(ErrorCreatePkCS10);
PRINT_ERROR(ErrorAcceptPKCS7);
PRINT_ERROR(ErrorMakePKCS7Response);
PRINT_ERROR(ErrorRemoveCertFromStore);
}
// Test some alg enum stuff
BOOL Test8() {
IEnroll2 * pIEnroll = NULL;
PCRYPT_DATA_BLOB pBlobPKCS7 = NULL;
CRYPT_DATA_BLOB blobPKCS10;
BYTE arSha1Hash[20];
CRYPT_HASH_BLOB hash = {sizeof(arSha1Hash), arSha1Hash};
BOOL fRet = TRUE;
DWORD Err = GetLastError();
HRESULT hr = S_OK;
LONG lFlags = 0;
DWORD i = 0;
LPWSTR wsz = NULL;
// TEST 1 Normal usage
if( NULL == (pIEnroll = PIEnroll2GetNoCOM()))
goto ErrorPIEnrollGetNoCOM;
// enum the default algids
while( (S_OK == (hr = pIEnroll->EnumAlgs(i++, ALG_CLASS_HASH, &lFlags))) ) {
if( (S_OK == (hr = pIEnroll->GetAlgNameWStr(lFlags, &wsz))) ) {
LocalFree(wsz);
}
else {
goto ErrorGetAlgName;
}
}
if( i == 1 ) {
SetLastError(hr);
goto ErrorEnumAlgs;
}
if(S_OK != (hr = pIEnroll->GetSupportedKeySpec(&lFlags))) {
SetLastError(hr);
goto ErrorGetSupportedKeySpec;
}
if(S_OK != (hr = pIEnroll->GetKeyLen(FALSE, FALSE, &lFlags))) {
SetLastError(hr);
goto ErrorGetKeyLen;
}
if(S_OK != (hr = pIEnroll->GetKeyLen(FALSE, TRUE, &lFlags))) {
SetLastError(hr);
goto ErrorGetKeyLen;
}
if(S_OK != (hr = pIEnroll->GetKeyLen(TRUE, FALSE, &lFlags))) {
SetLastError(hr);
goto ErrorGetKeyLen;
}
if(S_OK != (hr = pIEnroll->GetKeyLen(TRUE, TRUE, &lFlags))) {
SetLastError(hr);
goto ErrorGetKeyLen;
}
// get the keyspec data
// enroll for a new cert
memset(&blobPKCS10, 0, sizeof(blobPKCS10));
if( S_OK != (hr = pIEnroll->createPKCS10WStr(L"CN=XEnroll Test", L"1.2.3.4", &blobPKCS10)) ) {
SetLastError(hr);
goto ErrorCreatePkCS10;
}
pIEnroll->Reset();
if( NULL == (pBlobPKCS7 = MakePKCS7Response(&blobPKCS10, &hash)) )
goto ErrorMakePKCS7Response;
// accept the new cert
if( S_OK != (hr = pIEnroll->acceptPKCS7Blob(pBlobPKCS7)) ) {
SetLastError(hr);
goto ErrorAcceptPKCS7;
}
if( !RemoveCertFromStore(&hash, L"MY", CERT_SYSTEM_STORE_CURRENT_USER) )
goto ErrorRemoveCertFromStore;
CommonReturn:
if(pBlobPKCS7 != NULL)
free(pBlobPKCS7);
if(pIEnroll != NULL)
pIEnroll->Release();
if(blobPKCS10.pbData != NULL)
LocalFree(blobPKCS10.pbData);
SetLastError(Err);
return(fRet);
ErrorReturn:
Err = GetLastError();
fRet = FALSE;
goto CommonReturn;
PRINT_ERROR(ErrorPIEnrollGetNoCOM);
PRINT_ERROR(ErrorCreatePkCS10);
PRINT_ERROR(ErrorAcceptPKCS7);
PRINT_ERROR(ErrorMakePKCS7Response);
PRINT_ERROR(ErrorRemoveCertFromStore);
PRINT_ERROR(ErrorEnumAlgs);
PRINT_ERROR(ErrorGetKeyLen);
PRINT_ERROR(ErrorGetSupportedKeySpec);
PRINT_ERROR(ErrorGetAlgName);
}
// Test some alg enum stuff
BOOL Test9() {
IEnroll2 * pIEnroll = NULL;
PCCERT_CONTEXT pCertContext = NULL;
CRYPT_DATA_BLOB blobPKCS10;
BOOL fRet = TRUE;
DWORD Err = GetLastError();
HRESULT hr = S_OK;
DWORD i = 0;
// TEST 1 Normal usage
if( NULL == (pIEnroll = PIEnroll2GetNoCOM()))
goto ErrorPIEnrollGetNoCOM;
for(i=0; i<100; i++) {
// get the keyspec data
// enroll for a new cert
memset(&blobPKCS10, 0, sizeof(blobPKCS10));
if( S_OK != (hr = pIEnroll->createPKCS10WStr(L"CN=XEnroll Test", L"1.2.3.4", &blobPKCS10)) ) {
SetLastError(hr);
goto ErrorCreatePkCS10;
}
pIEnroll->Reset();
// clean up after ourself
if(NULL != (pCertContext = GetCertOutOfRequestStore(&blobPKCS10)) ) {
// delete the cert's private key
DeleteCertPrivateKey(pCertContext);
CertDeleteCertificateFromStore(pCertContext);
pCertContext = NULL;
}
if(blobPKCS10.pbData != NULL)
LocalFree(blobPKCS10.pbData);
}
CommonReturn:
if(pIEnroll != NULL)
pIEnroll->Release();
SetLastError(Err);
return(fRet);
ErrorReturn:
Err = GetLastError();
fRet = FALSE;
goto CommonReturn;
PRINT_ERROR(ErrorPIEnrollGetNoCOM);
PRINT_ERROR(ErrorCreatePkCS10);
}
// test to see if we can build PVK and SPC files
BOOL TestUI1() {
IEnroll * pIEnroll = NULL;
PCRYPT_DATA_BLOB pBlobPKCS7 = NULL;
CRYPT_DATA_BLOB blobPKCS10;
BYTE arSha1Hash[20];
CRYPT_HASH_BLOB hash = {sizeof(arSha1Hash), arSha1Hash};
BOOL fRet = TRUE;
DWORD Err = GetLastError();
HRESULT hr = S_OK;
// TEST 1 Normal usage
pIEnroll = PIEnrollGetNoCOM();
if( S_OK != pIEnroll->put_PVKFileNameWStr(L"c:\\temp\\foo.pvk") )
goto ErrorPVKFileNameWStr;
// enroll for a new cert
memset(&blobPKCS10, 0, sizeof(blobPKCS10));
if( S_OK != (hr = pIEnroll->createPKCS10WStr(NULL, NULL, &blobPKCS10)) ) {
SetLastError(hr);
goto ErrorCreatePkCS10;
}
if( NULL == (pBlobPKCS7 = MakePKCS7Response(&blobPKCS10, &hash)) )
goto ErrorMakePKCS7Response;
// accept the new cert
if( S_OK != (hr = pIEnroll->acceptPKCS7Blob(pBlobPKCS7)) ) {
SetLastError(hr);
goto ErrorAcceptPKCS7;
}
if( !RemoveCertFromStore(&hash, L"MY", CERT_SYSTEM_STORE_CURRENT_USER) )
goto ErrorRemoveCertFromStore;
CommonReturn:
if(pBlobPKCS7 != NULL)
free(pBlobPKCS7);
if(pIEnroll != NULL)
pIEnroll->Release();
if(blobPKCS10.pbData != NULL)
LocalFree(blobPKCS10.pbData);
SetLastError(Err);
return(fRet);
ErrorReturn:
Err = GetLastError();
fRet = FALSE;
goto CommonReturn;
PRINT_ERROR(ErrorCreatePkCS10);
PRINT_ERROR(ErrorAcceptPKCS7);
PRINT_ERROR(ErrorMakePKCS7Response);
PRINT_ERROR(ErrorRemoveCertFromStore);
PRINT_ERROR(ErrorPVKFileNameWStr);
}
// Test Renewal, Create original cert, create renewal request, create renewed cert
BOOL Test10() {
BOOL fRet = TRUE;
DWORD Err = GetLastError();
HRESULT hr = S_OK;
// GetUserNameExW is NOT a 2 pass call, so I have to guess at the MAX
#define MAXUSERNAME 256
WCHAR wszUserName[MAXUSERNAME];
DWORD cchUserName = MAXUSERNAME;
IEnroll * pIEnrollRenew = NULL;
IEnroll * pIEnrollRA1 = NULL;
IEnroll * pIEnrollRA2 = NULL;
CRYPT_DATA_BLOB blobRenewRequest;
CRYPT_DATA_BLOB blobRA1Reqest;
CRYPT_DATA_BLOB blobRA2Reqest;
CRYPT_DATA_BLOB blobT;
CERT_NAME_BLOB blobNameRA1;
CERT_NAME_BLOB blobNameRA2;
CERT_NAME_BLOB blobNameOld;
PCCERT_CONTEXT pCertRA1 = NULL;
PCCERT_CONTEXT pCertRA2 = NULL;
PCCERT_CONTEXT pCertOld = NULL;
CERT_EXTENSION rgExtension[] = {
{szOID_ENHANCED_KEY_USAGE, FALSE, {0, NULL}}
};
CERT_EXTENSIONS Extensions = {sizeof(rgExtension)/sizeof(CERT_EXTENSION), rgExtension};
LPSTR rgszOIDUsages[] = {szOID_ENROLLMENT_AGENT};
CERT_ENHKEY_USAGE eku = {1 ,rgszOIDUsages};
memset(&blobRenewRequest, 0, sizeof(blobRenewRequest));
memset(&blobRA1Reqest, 0, sizeof(blobRA1Reqest));
memset(&blobRA2Reqest, 0, sizeof(blobRA2Reqest));
memset(&blobNameRA1, 0, sizeof(blobNameRA1));
memset(&blobNameRA2, 0, sizeof(blobNameRA2));
memset(&blobNameOld, 0, sizeof(blobNameOld));
// encode the enhanced key usage
if( !CryptEncodeObjectEx(
CRYPT_ASN_ENCODING,
X509_ENHANCED_KEY_USAGE,
&eku,
CRYPT_ENCODE_ALLOC_FLAG,
NULL,
&rgExtension[0].Value.pbData,
&rgExtension[0].Value.cbData
) )
goto ErrorCryptEncodeObjectEx;
// get the Subject DN only if one is specified
if( !CertStrToNameW(
CRYPT_ASN_ENCODING,
L"CN=Test RA1",
0,
NULL,
NULL,
&blobNameRA1.cbData,
NULL) ||
(blobNameRA1.pbData = (BYTE *) _alloca(blobNameRA1.cbData)) == NULL ||
!CertStrToNameW(
CRYPT_ASN_ENCODING,
L"CN=Test RA1",
0,
NULL,
blobNameRA1.pbData,
&blobNameRA1.cbData,
NULL) ) {
goto ErrorCertStrToNameW;
}
// get a Cert for the 1st RA
if( NULL == (pCertRA1 = CertCreateSelfSignCertificate(
NULL,
&blobNameRA1,
0,
NULL,
NULL,
NULL,
NULL,
&Extensions
) ) )
goto ErrorCertCreateSelfSignCertificate;
blobT.cbData = pCertRA1->cbCertEncoded;
blobT.pbData = pCertRA1->pbCertEncoded;
WriteBlobToFile(L"RA1.cer", 0, &blobT);
// get the Subject DN only if one is specified
if( !CertStrToNameW(
CRYPT_ASN_ENCODING,
L"CN=Test RA2",
0,
NULL,
NULL,
&blobNameRA2.cbData,
NULL) ||
(blobNameRA2.pbData = (BYTE *) _alloca(blobNameRA2.cbData)) == NULL ||
!CertStrToNameW(
CRYPT_ASN_ENCODING,
L"CN=Test RA2",
0,
NULL,
blobNameRA2.pbData,
&blobNameRA2.cbData,
NULL) ) {
goto ErrorCertStrToNameW;
}
// get a Cert for the 2'nd RA
if( NULL == (pCertRA2 = CertCreateSelfSignCertificate(
NULL,
&blobNameRA2,
0,
NULL,
NULL,
NULL,
NULL,
&Extensions
) ) )
goto ErrorCertCreateSelfSignCertificate;
blobT.cbData = pCertRA2->cbCertEncoded;
blobT.pbData = pCertRA2->pbCertEncoded;
WriteBlobToFile(L"RA2.cer", 0, &blobT);
// get the Subject DN only if one is specified
if( !CertStrToNameW(
CRYPT_ASN_ENCODING,
L"CN=Test Cert Old",
0,
NULL,
NULL,
&blobNameOld.cbData,
NULL) ||
(blobNameOld.pbData = (BYTE *) _alloca(blobNameOld.cbData)) == NULL ||
!CertStrToNameW(
CRYPT_ASN_ENCODING,
L"CN=Test Cert Old",
0,
NULL,
blobNameOld.pbData,
&blobNameOld.cbData,
NULL) ) {
goto ErrorCertStrToNameW;
}
// get a Cert for the Original cert
if( NULL == (pCertOld = CertCreateSelfSignCertificate(
NULL,
&blobNameOld,
0,
NULL,
NULL,
NULL,
NULL,
NULL
) ) )
goto ErrorCertCreateSelfSignCertificate;
blobT.cbData = pCertOld->cbCertEncoded;
blobT.pbData = pCertOld->pbCertEncoded;
WriteBlobToFile(L"Original.cer", 0, &blobT);
// Make an RA cert
if(NULL == (pIEnrollRenew = PIEnrollGetNoCOM()) )
goto ErrorPIEnrollGetNoCOM;
// enroll for a new cert.
if( S_OK != (hr = pIEnrollRenew->put_RenewalCertificate(pCertOld)) ) {
SetLastError(hr);
goto ErrorPut_RenewalCertificate;
}
// put in a certtype for laughs
if( S_OK != (hr = pIEnrollRenew->AddCertTypeToRequestWStr(L"MY CERT TYPE")) ) {
SetLastError(hr);
goto ErrorAddCertTypeToRequest;
}
// get the renewal PKCS7 (in the 10 blob)
if( S_OK != (hr = pIEnrollRenew->createPKCS10WStr(L"CN=XEnroll Test Renew", L"1.3.6.1.5.5.7.3.8", &blobRenewRequest)) ) {
SetLastError(hr);
goto ErrorCreatePkCS10;
}
WriteBlobToFile(L"Renewal.p7s", 0, &blobRenewRequest);
// Make an RA cert
if(NULL == (pIEnrollRA1 = PIEnrollGetNoCOM()) )
goto ErrorPIEnrollGetNoCOM;
if(S_OK != pIEnrollRA1->AddNameValuePairToSignatureWStr(L"CreateUserCertificate", L"stimpy.ntdev.microsoft.com"))
goto ErrorAddNameValuePairToSignatureWStr;
if( !GetUserNameExW(NameSamCompatible, wszUserName, &cchUserName) )
goto ErrorGetUserName;
if(S_OK != pIEnrollRA1->AddNameValuePairToSignatureWStr(L"UserName", wszUserName))
goto ErrorAddNameValuePairToSignatureWStr;
// get the 1st RA Request
if( S_OK != (hr = pIEnrollRA1->CreatePKCS7RequestFromRequest(
&blobRenewRequest,
pCertRA1,
&blobRA1Reqest) ) )
goto ErrorCreatePKCS7RequestFromRequest;
WriteBlobToFile(L"RA1.p7s", 0, &blobRA1Reqest);
// Make an RA cert
if(NULL == (pIEnrollRA2 = PIEnrollGetNoCOM()) )
goto ErrorPIEnrollGetNoCOM;
if(S_OK != pIEnrollRA2->AddNameValuePairToSignatureWStr(L"ChangeUserCertificate", L"stimpy.redmond.microsoft.com"))
goto ErrorAddNameValuePairToSignatureWStr;
// get the 2nd RA Request
if( S_OK != (hr = pIEnrollRA2->CreatePKCS7RequestFromRequest(
&blobRA1Reqest,
pCertRA2,
&blobRA2Reqest) ) )
goto ErrorCreatePKCS7RequestFromRequest;
// put this out to a file for Vic
WriteBlobToFile(L"RA2.p7s", 0, &blobRA2Reqest);
CommonReturn:
if(rgExtension[0].Value.pbData != NULL)
LocalFree(rgExtension[0].Value.pbData);
if(blobRenewRequest.pbData != NULL) {
// clean up after ourself
PCCERT_CONTEXT pCertRequest;
if(NULL != (pCertRequest = GetCertOutOfRequestStore2(
&blobRenewRequest)) ) {
// delete the cert's private key
DeleteCertPrivateKey(pCertRequest);
CertDeleteCertificateFromStore(pCertRequest);
}
LocalFree(blobRenewRequest.pbData);
}
if(pIEnrollRenew != NULL)
pIEnrollRenew->freeRequestInfoBlob(blobRenewRequest);
if(pCertRA1 != NULL) {
DeleteCertPrivateKey(pCertRA1);
CertFreeCertificateContext(pCertRA1);
}
if(pCertRA2 != NULL) {
DeleteCertPrivateKey(pCertRA2);
CertFreeCertificateContext(pCertRA2);
}
if(pCertOld != NULL) {
DeleteCertPrivateKey(pCertOld);
CertFreeCertificateContext(pCertOld);
}
if(blobRA1Reqest.pbData != NULL)
LocalFree(blobRA1Reqest.pbData);
if(blobRA2Reqest.pbData != NULL)
LocalFree(blobRA2Reqest.pbData);
if(pIEnrollRenew != NULL)
pIEnrollRenew->Release();
if(pIEnrollRA1 != NULL)
pIEnrollRA1->Release();
if(pIEnrollRA2 != NULL)
pIEnrollRA2->Release();
SetLastError(Err);
return(fRet);
ErrorReturn:
Err = GetLastError();
fRet = FALSE;
goto CommonReturn;
PRINT_ERROR(ErrorGetUserName);
PRINT_ERROR(ErrorAddNameValuePairToSignatureWStr);
PRINT_ERROR(ErrorPIEnrollGetNoCOM);
PRINT_ERROR(ErrorCertStrToNameW);
PRINT_ERROR(ErrorCertCreateSelfSignCertificate);
PRINT_ERROR(ErrorCreatePKCS7RequestFromRequest);
PRINT_ERROR(ErrorCreatePkCS10);
PRINT_ERROR(ErrorPut_RenewalCertificate);
PRINT_ERROR(ErrorCryptEncodeObjectEx);
PRINT_ERROR(ErrorAddCertTypeToRequest);
}
HRESULT
myMultiByteToWideChar(
IN char *psz,
OUT WCHAR **ppwsz)
{
HRESULT hr;
int cch = 0;
WCHAR *pwsz = NULL;
assert (NULL != psz);
while (TRUE)
{
cch = MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, cch);
assert((cch - 1) == (int)strlen(psz));
if (NULL != pwsz)
{
break; //done
}
pwsz = (WCHAR*)LocalAlloc(LMEM_FIXED, cch * sizeof(WCHAR));
if (NULL == pwsz)
{
hr = E_OUTOFMEMORY;
goto LocalAllocError;
}
}
*ppwsz = pwsz;
pwsz = NULL;
hr = S_OK;
ErrorReturn:
if (NULL != pwsz)
{
LocalFree(pwsz);
}
return hr;
PRINT_ERROR(LocalAllocError)
}
// test Enroll4 interface
BOOL Test11()
{
BOOL fRet = FALSE;
HRESULT hr;
IEnroll4 *pIEnroll4 = NULL;
HANDLE hCAFile = NULL;
CHAR *pchCACert = NULL;
BYTE *pbCACert = NULL;
DWORD cchCACert;
DWORD cbCACert;
DWORD cbRead;
PCCERT_CONTEXT pCACert = NULL;
WCHAR *pwszDNName = NULL;
WCHAR *pwszCMCFileName = NULL;
WCHAR *pwszKeyContainer = NULL;
CRYPT_DATA_BLOB blobCMC;
WCHAR wszMyDNName[] = L"CN=Xenroll CMC Test";
LONG lKeySize;
ZeroMemory(&blobCMC, sizeof(blobCMC));
pIEnroll4 = PIEnroll4GetNoCOM();
if(NULL == pIEnroll4)
{
goto PIEnroll4GetNoCOMError;
}
if (NULL != g_pszKeyContainer)
{
hr = myMultiByteToWideChar(g_pszKeyContainer, &pwszKeyContainer);
if (S_OK != hr)
{
goto myMultiByteToWideCharError;
}
}
if (NULL != pwszKeyContainer)
{
hr = pIEnroll4->put_ContainerNameWStr(pwszKeyContainer);
if (S_OK != hr)
{
goto put_ContainerNameWStrError;
}
}
hr = pIEnroll4->resetExtensions();
if (S_OK != hr)
{
goto resetExtensionsError;
}
hr = pIEnroll4->resetAttributes();
if (S_OK != hr)
{
goto resetAttributesError;
}
//add some extensions
//add some attributes
hr = pIEnroll4->addNameValuePairToRequestWStr(
0,
L"NameValue name",
L"NameValue value");
if (S_OK != hr)
{
goto addNameValuePairToRequestWStrError;
}
if (NULL != g_pszCAXchgFileName)
{
//get a ca cert
hCAFile = CreateFileA(
g_pszCAXchgFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
if (NULL != hCAFile)
{
cchCACert = GetFileSize(hCAFile, NULL);
assert(0 < cchCACert);
pchCACert = (CHAR*)LocalAlloc(LMEM_FIXED, cchCACert);
if (NULL == pchCACert)
{
goto LocalAllocError;
}
if (!ReadFile(hCAFile, pchCACert, cchCACert, &cbRead, NULL))
{
goto ReadFileError;
}
assert(cbRead <= cchCACert);
pbCACert = NULL;
while (TRUE)
{
if (!CryptStringToBinaryA(
pchCACert,
cchCACert,
CRYPT_STRING_ANY,
pbCACert,
&cbCACert,
NULL,
NULL))
{
goto CryptStringToBinaryAError;
}
if (NULL != pbCACert)
{
break;
}
pbCACert = (BYTE*)LocalAlloc(LMEM_FIXED, cbCACert);
if (NULL == pbCACert)
{
goto LocalAllocError;
}
}
pCACert = CertCreateCertificateContext(
X509_ASN_ENCODING,
pbCACert,
cbCACert);
if (NULL == pCACert)
{
goto CertCreateCertificateContextError;
}
hr = pIEnroll4->SetPrivateKeyArchiveCertificate(
pCACert);
if (S_OK != hr)
{
goto SetPrivateKeyArchiveCertificateError;
}
}
#if 0
hr = pIEnroll4->put_GenKeyFlags(CRYPT_EXPORTABLE);
if (S_OK != hr)
{
goto put_GenKeyFlagsError;
}
#endif
}
pwszDNName = wszMyDNName;
if (NULL != g_pszDNName)
{
hr = myMultiByteToWideChar(g_pszDNName, &pwszDNName);
if (S_OK != hr)
{
goto myMultiByteToWideCharError;
}
}
if (NULL != g_pszCMCFileName)
{
hr = myMultiByteToWideChar(g_pszCMCFileName, &pwszCMCFileName);
if (S_OK != hr)
{
goto myMultiByteToWideCharError;
}
}
// enroll for a new cert
if (NULL != pwszCMCFileName)
{
hr = pIEnroll4->createFileRequestWStr(
XECR_CMC,
pwszDNName,
NULL,
pwszCMCFileName);
}
else
{
hr = pIEnroll4->createRequestWStr(
XECR_CMC,
pwszDNName,
NULL,
&blobCMC);
}
if (S_OK != hr)
{
goto createRequestWStrError;
}
fRet = TRUE;
ErrorReturn:
if (NULL != pwszKeyContainer)
{
LocalFree(pwszKeyContainer);
}
if (NULL != pchCACert)
{
LocalFree(pchCACert);
}
if (NULL != pbCACert)
{
LocalFree(pbCACert);
}
if (NULL != pwszCMCFileName)
{
LocalFree(pwszCMCFileName);
}
if (NULL != pwszDNName && pwszDNName != wszMyDNName)
{
LocalFree(pwszDNName);
}
if(NULL != pIEnroll4)
{
pIEnroll4->Release();
}
if (NULL != hCAFile)
{
CloseHandle(hCAFile);
}
if (NULL != pCACert)
{
CertFreeCertificateContext(pCACert);
}
if (NULL != blobCMC.pbData)
{
LocalFree(blobCMC.pbData);
}
return fRet;
PRINT_ERROR(CryptStringToBinaryAError)
#if 0
PRINT_ERROR2(put_GenKeyFlagsError, hr)
#endif
PRINT_ERROR2(SetPrivateKeyArchiveCertificateError, hr)
PRINT_ERROR(CertCreateCertificateContextError)
PRINT_ERROR(ReadFileError)
PRINT_ERROR2(createRequestWStrError, hr)
PRINT_ERROR2(addNameValuePairToRequestWStrError, hr)
PRINT_ERROR2(resetExtensionsError, hr)
PRINT_ERROR2(resetAttributesError, hr)
PRINT_ERROR(PIEnroll4GetNoCOMError)
PRINT_ERROR2(put_ContainerNameWStrError, hr)
PRINT_ERROR2(LocalAllocError, E_OUTOFMEMORY)
PRINT_ERROR2(myMultiByteToWideCharError, hr)
}
// test Enroll4 interface, accept CMC response
BOOL Test12()
{
HRESULT hr;
BOOL fRet = FALSE;
IEnroll4 *pIEnroll4 = NULL;
int cch;
WCHAR *pwszResponseFile = NULL;
if (NULL == g_pszCMCResponseFileName)
{
//skip the test
printf("Test12 is skipped\n");
fRet = TRUE;
goto ErrorReturn;
}
pIEnroll4 = PIEnroll4GetNoCOM();
if(NULL == pIEnroll4)
{
goto PIEnroll4GetNoCOMError;
}
hr = myMultiByteToWideChar(g_pszCMCResponseFileName, &pwszResponseFile);
if (S_OK != hr)
{
goto myMultiByteToWideCharError;
}
hr = pIEnroll4->acceptFileResponseWStr(pwszResponseFile);
if (S_OK != hr)
{
goto acceptFileResponseWStrError;
}
fRet = TRUE;
ErrorReturn:
if (NULL != pwszResponseFile)
{
LocalFree(pwszResponseFile);
}
if(NULL != pIEnroll4)
{
pIEnroll4->Release();
}
return fRet;
PRINT_ERROR(PIEnroll4GetNoCOMError)
PRINT_ERROR(acceptFileResponseWStrError)
PRINT_ERROR(myMultiByteToWideCharError)
}
// Test pending API
BOOL Test13()
{
BOOL fRet;
CRYPT_DATA_BLOB pkcs10Blob;
DWORD dwIndex;
DWORD dwNumTests;
HRESULT hr;
IEnroll4 *pIEnroll4 = NULL;
PCCERT_CONTEXT pCertContext = NULL;
TXEnrollPendingAPITester *pTester = NULL;
WCHAR wszDNName[] = L"CN=Xenroll PendingAPI Test";
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// TEST CASES
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
PENDING_INFO rgPendingTests[] = {
// 0) Normal inputs
{
100,
L"duncanb1.ntdev.microsoft.com",
L"setPendingInfoWStr Test 1",
L"SPI Test 1",
0,
NULL,
S_OK
},
// 1) Negative Req ID
{
-1,
L"duncanb1.ntdev.microsoft.com",
L"setPendingInfoWStr Test 1",
L"SPI Test 1",
0,
NULL,
E_INVALIDARG
},
// 2) NULL CA location.
{
100,
NULL,
L"setPendingInfoWStr Test 1",
L"SPI Test 1",
0,
NULL,
E_INVALIDARG
},
// 3) NULL CA name.
{
100,
L"duncanb1.ntdev.microsoft.com",
NULL,
L"SPI Test 1",
0,
NULL,
E_INVALIDARG
},
// 4) NULL friendly name.
{
100,
L"duncanb1.ntdev.microsoft.com",
L"setPendingInfoWStr Test 1",
NULL,
0,
NULL,
S_OK
},
// 5) Specify USER store flags.
{
100,
L"duncanb1.ntdev.microsoft.com",
L"setPendingInfoWStr Test 1",
L"SPI Test 1",
CERT_SYSTEM_STORE_CURRENT_USER,
NULL,
S_OK
},
// 6) Specify LM store flags.
{
100,
L"duncanb1.ntdev.microsoft.com",
L"setPendingInfoWStr Test 1",
L"SPI Test 1",
CERT_SYSTEM_STORE_LOCAL_MACHINE,
NULL,
S_OK
},
// 7) Long names:
{
100,
L"duncanb1.ntdev.microsoft.comduncanb1.ntdev.microsoft.comduncanb1.ntdev.microsoft.com"
L"duncanb1.ntdev.microsoft.comduncanb1.ntdev.microsoft.comduncanb1.ntdev.microsoft.comcom"
L"duncanb1.ntdev.microsoft.comduncanb1.ntdev.microsoft.comduncanb1.ntdev.microsoft.comcom"
L"duncanb1.ntdev.microsoft.comduncanb1.ntdev.microsoft.comduncanb1.ntdev.microsoft.comcom"
L"duncanb1.ntdev.microsoft.comduncanb1.ntdev.microsoft.comduncanb1.ntdev.microsoft.comcom"
L"duncanb1.ntdev.microsoft.comduncanb1.ntdev.microsoft.comduncanb1.ntdev.microsoft.comcom"
L"duncanb1.ntdev.microsoft.comduncanb1.ntdev.microsoft.comduncanb1.ntdev.microsoft.comcom"
L"duncanb1.ntdev.microsoft.comduncanb1.ntdev.microsoft.comduncanb1.ntdev.microsoft.com",
L"setPendingInfoWStr Test 1setPendingInfoWStr Test 1setPendingInfoWStr Test 1"
L"setPendingInfoWStr Test 1setPendingInfoWStr Test 1setPendingInfoWStr Test 1"
L"setPendingInfoWStr Test 1Test 1setPendingInfoWStr Test 1setPendingInfoWStr Test 1"
L"setPendingInfoWStr Test 1setPendingInfoWStr Test 1Test 1setPendingInfoWStr Test 1"
L"setPendingInfoWStr Test 1setPendingInfoWStr Test 1setPendingInfoWStr Test 1Test 1"
L"setPendingInfoWStr Test 1setPendingInfoWStr Test 1setPendingInfoWStr Test 1"
L"setPendingInfoWStr Test 1Test 1setPendingInfoWStr Test 1setPendingInfoWStr Test 1"
L"setPendingInfoWStr Test 1setPendingInfoWStr Test 1Test 1setPendingInfoWStr Test 1"
L"setPendingInfoWStr Test 1setPendingInfoWStr Test 1setPendingInfoWStr Test 1Test 1"
L"setPendingInfoWStr Test 1setPendingInfoWStr Test 1setPendingInfoWStr Test 1"
L"setPendingInfoWStr Test 1",
L"SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1"
L"SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1"
L"Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1"
L"SPITest 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1"
L"SPITest 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1"
L"SPITest 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1"
L"SPITest 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1"
L"SPITest 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1"
L"SPITest 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1"
L"SPITest 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI Test 1SPI",
0,
NULL,
S_OK
}
};
ZeroMemory(&pkcs10Blob, sizeof(pkcs10Blob));
pIEnroll4 = PIEnroll4GetNoCOM();
if(NULL == pIEnroll4)
goto PIEnroll4GetNoCOMError;
pTester = new TXEnrollPendingAPITester;
if (NULL == pTester)
goto MemoryError;
// Test the ThumbPrintWStr property.
if (!pTester->TestProperty_ThumbPrintWStr(pIEnroll4))
goto TestProperty_ThumbPrintWStrError;
pIEnroll4 = PIEnroll4GetNoCOM();
if(NULL == pIEnroll4)
goto PIEnroll4GetNoCOMError;
// Test the removePendingRequestWStr method.
if (!pTester->TestMethod_removePendingRequestWStr(pIEnroll4))
goto TestMethod_removePendingRequestWStrError;
// Test all enumPending / setPendingInfo cases:
dwNumTests = sizeof(rgPendingTests) / sizeof(PENDING_INFO);
for (dwIndex = 0; dwIndex < dwNumTests; dwIndex++)
{
pIEnroll4 = PIEnroll4GetNoCOM();
if(NULL == pIEnroll4)
goto PIEnroll4GetNoCOMError;
if (S_OK != (hr = pIEnroll4->resetExtensions()))
goto resetExtensionsError;
if (S_OK != (hr = pIEnroll4->resetAttributes()))
goto resetAttributesError;
// Small key size so the test runs faster.
if (S_OK != (hr = pIEnroll4->put_GenKeyFlags(384 << 16)))
goto put_GenKeyFlagsError;
// Default to CURRENT_USER.
if (0 == rgPendingTests[dwIndex].dwStoreFlags)
rgPendingTests[dwIndex].dwStoreFlags = CERT_SYSTEM_STORE_CURRENT_USER;
// Default to REQUEST store.
if (NULL == rgPendingTests[dwIndex].pwszStoreName)
rgPendingTests[dwIndex].pwszStoreName = L"REQUEST";
if (S_OK != (hr = pIEnroll4->put_RequestStoreFlags(rgPendingTests[dwIndex].dwStoreFlags)))
goto put_RequestStoreFlagsError;
if (S_OK != (hr = pIEnroll4->put_RequestStoreNameWStr(rgPendingTests[dwIndex].pwszStoreName)))
goto put_RequestStoreNameWStrError;
// Create a request to test on.
if (S_OK != (hr = pIEnroll4->createRequestWStr
(XECR_PKCS10_V2_0,
wszDNName,
NULL,
&pkcs10Blob)))
goto createRequestWStrError;
if (!pTester->TestMethod_setPendingInfoWStr(pIEnroll4, pkcs10Blob, &rgPendingTests[dwIndex]))
goto TestMethod_setPendingInfoWStrError;
// only continue if we are not testing a failure case.
// Eventually this should be extended to test the failure cases for enumPendingRequestWStr.
if (S_OK == rgPendingTests[dwIndex].hrExpectedResult)
{
if (!pTester->TestMethod_enumPendingRequestWStr(pIEnroll4, pkcs10Blob, &rgPendingTests[dwIndex]))
goto TestMethod_enumPendingRequestWStrError;
}
pCertContext = GetCertOutOfStore(&pkcs10Blob, rgPendingTests[dwIndex].dwStoreFlags, rgPendingTests[dwIndex].pwszStoreName);
if (NULL == pCertContext)
goto GetCertOutOfStoreError;
CertDeleteCertificateFromStore(pCertContext);
LocalFree(pkcs10Blob.pbData);
ZeroMemory(&pkcs10Blob, sizeof(pkcs10Blob));
pCertContext = NULL;
pIEnroll4->Release();
}
fRet = TRUE;
CommonReturn:
if (NULL != pkcs10Blob.pbData)
{
pCertContext = GetCertOutOfStore(&pkcs10Blob, rgPendingTests[dwIndex].dwStoreFlags, rgPendingTests[dwIndex].pwszStoreName);
if (NULL != pCertContext) { CertDeleteCertificateFromStore(pCertContext); }
LocalFree(pkcs10Blob.pbData);
}
return fRet;
ErrorReturn:
fRet = FALSE;
SetLastError(hr);
goto CommonReturn;
PRINT_ERROR2(createRequestWStrError, hr);
PRINT_ERROR2(GetCertOutOfStoreError, hr = GetLastError());
PRINT_ERROR2(MemoryError, hr = E_OUTOFMEMORY);
PRINT_ERROR2(PIEnroll4GetNoCOMError, hr = GetLastError());
PRINT_ERROR2(put_GenKeyFlagsError, hr);
PRINT_ERROR2(put_RequestStoreFlagsError, hr);
PRINT_ERROR2(put_RequestStoreNameWStrError, hr);
PRINT_ERROR2(resetAttributesError, hr);
PRINT_ERROR2(resetExtensionsError, hr);
PRINT_ERROR2(TestMethod_enumPendingRequestWStrError, hr = GetLastError());
PRINT_ERROR2(TestMethod_removePendingRequestWStrError, hr = GetLastError());
PRINT_ERROR2(TestMethod_setPendingInfoWStrError, hr = GetLastError());
PRINT_ERROR2(TestProperty_ThumbPrintWStrError, hr = GetLastError());
}
// test Enroll4 misc. methods
BOOL Test14()
{
BOOL fRet = FALSE;
HRESULT hr;
ICEnroll4 *pICEnroll = NULL;
ICEnroll4 *pICEnroll2 = NULL;
ICEnroll4 *pICEnroll3 = NULL;
ICEnroll4 *pICEnroll4 = NULL;
IEnroll4 *pIEnroll = NULL;
IEnroll4 *pIEnroll2 = NULL;
IEnroll4 *pIEnroll4 = NULL;
LONG lKeySize;
BOOL fCoInit = FALSE;
hr = CoInitialize(NULL);
if (S_OK != hr && S_FALSE != hr)
{
goto CoInitializeError;
}
fCoInit = TRUE;
hr = CoCreateInstance(
CLSID_CEnroll,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICEnroll,
(void **) &pICEnroll);
if( S_OK != hr || NULL == pICEnroll)
{
goto CoCreateInstanceError;
}
if (g_fVerb)
{
printf("CoCreateInstance(ICEnroll) test passed\n");
}
hr = CoCreateInstance(
CLSID_CEnroll,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICEnroll2,
(void **) &pICEnroll2);
if( S_OK != hr || NULL == pICEnroll2)
{
goto CoCreateInstanceError;
}
if (g_fVerb)
{
printf("CoCreateInstance(ICEnroll2) test passed\n");
}
hr = CoCreateInstance(
CLSID_CEnroll,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICEnroll3,
(void **) &pICEnroll3);
if( S_OK != hr || NULL == pICEnroll3)
{
goto CoCreateInstanceError;
}
if (g_fVerb)
{
printf("CoCreateInstance(ICEnroll3) test passed\n");
}
hr = CoCreateInstance(
CLSID_CEnroll,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICEnroll4,
(void **) &pICEnroll4);
if( S_OK != hr || NULL == pICEnroll4)
{
goto CoCreateInstanceError;
}
if (g_fVerb)
{
printf("CoCreateInstance(ICEnroll4) test passed\n");
}
hr = CoCreateInstance(
CLSID_CEnroll,
NULL,
CLSCTX_INPROC_SERVER,
IID_IEnroll,
(void **) &pIEnroll);
if( S_OK != hr || NULL == pIEnroll)
{
goto CoCreateInstanceError;
}
if (g_fVerb)
{
printf("CoCreateInstance(IEnroll) test passed\n");
}
hr = CoCreateInstance(
CLSID_CEnroll,
NULL,
CLSCTX_INPROC_SERVER,
IID_IEnroll4,
(void **) &pIEnroll2);
if( S_OK != hr || NULL == pIEnroll2)
{
goto CoCreateInstanceError;
}
if (g_fVerb)
{
printf("CoCreateInstance(IEnroll2) test passed\n");
}
hr = CoCreateInstance(
CLSID_CEnroll,
NULL,
CLSCTX_INPROC_SERVER,
IID_IEnroll4,
(void **) &pIEnroll4);
if( S_OK != hr || NULL == pIEnroll4)
{
goto CoCreateInstanceError;
}
if (g_fVerb)
{
printf("CoCreateInstance(IEnroll4) test passed\n");
}
hr = pIEnroll4->GetKeyLenEx(XEKL_KEYSIZE_MIN, XEKL_KEYSPEC_KEYX, &lKeySize);
if (S_OK != hr)
{
goto GetKeyLenExError;
}
if (g_fVerb)
{
printf("Minimun exchange key size is %d\n", lKeySize);
}
hr = pIEnroll4->GetKeyLenEx(XEKL_KEYSIZE_MAX, XEKL_KEYSPEC_KEYX, &lKeySize);
if (S_OK != hr)
{
goto GetKeyLenExError;
}
if (g_fVerb)
{
printf("Maximun exchange key size is %d\n", lKeySize);
}
hr = pIEnroll4->GetKeyLenEx(XEKL_KEYSIZE_DEFAULT, XEKL_KEYSPEC_KEYX, &lKeySize);
if (S_OK != hr)
{
goto GetKeyLenExError;
}
if (g_fVerb)
{
printf("Default exchange key size is %d\n", lKeySize);
}
hr = pIEnroll4->GetKeyLenEx(XEKL_KEYSIZE_INC, XEKL_KEYSPEC_KEYX, &lKeySize);
if (S_OK != hr)
{
goto GetKeyLenExError;
}
if (g_fVerb)
{
printf("Exchange key increment size is %d\n", lKeySize);
}
//signature key
hr = pIEnroll4->GetKeyLenEx(XEKL_KEYSIZE_MIN, XEKL_KEYSPEC_SIG, &lKeySize);
if (S_OK != hr)
{
goto GetKeyLenExError;
}
if (g_fVerb)
{
printf("Minimun signature key size is %d\n", lKeySize);
}
hr = pIEnroll4->GetKeyLenEx(XEKL_KEYSIZE_MAX, XEKL_KEYSPEC_SIG, &lKeySize);
if (S_OK != hr)
{
goto GetKeyLenExError;
}
if (g_fVerb)
{
printf("Maximun signature key size is %d\n", lKeySize);
}
hr = pIEnroll4->GetKeyLenEx(XEKL_KEYSIZE_DEFAULT, XEKL_KEYSPEC_SIG, &lKeySize);
if (S_OK != hr)
{
goto GetKeyLenExError;
}
if (g_fVerb)
{
printf("Default signature key size is %d\n", lKeySize);
}
hr = pIEnroll4->GetKeyLenEx(XEKL_KEYSIZE_INC, XEKL_KEYSPEC_SIG, &lKeySize);
if (S_OK != hr)
{
goto GetKeyLenExError;
}
if (g_fVerb)
{
printf("Signature key increment size is %d\n", lKeySize);
}
fRet = TRUE;
ErrorReturn:
if(NULL != pICEnroll)
{
pICEnroll->Release();
}
if(NULL != pICEnroll2)
{
pICEnroll2->Release();
}
if(NULL != pICEnroll3)
{
pICEnroll3->Release();
}
if(NULL != pICEnroll4)
{
pICEnroll4->Release();
}
if(NULL != pIEnroll)
{
pIEnroll->Release();
}
if(NULL != pIEnroll2)
{
pIEnroll2->Release();
}
if(NULL != pIEnroll4)
{
pIEnroll4->Release();
}
if (fCoInit)
{
CoUninitialize();
}
return fRet;
PRINT_ERROR2(CoCreateInstanceError, hr)
PRINT_ERROR2(CoInitializeError, hr)
PRINT_ERROR2(GetKeyLenExError, hr)
}
// test acceptPKCS7 and PFX
BOOL Test15()
{
BOOL fRet = FALSE;
HRESULT hr;
IEnroll4 *pIEnroll4 = NULL;
BOOL fCoInit = FALSE;
WCHAR *pwszPKCS7FileName = NULL;
WCHAR *pwszPFXFileName = NULL;
WCHAR *pwszPFXPassword = NULL;
WCHAR wszEmptyPassword[] = L"";
if (MAXDWORD == g_dwTestID &&
NULL == g_pszPKCS7FileName)
{
printf("Test15 is skipped.\n");
goto done;
}
if (NULL == g_pszPKCS7FileName)
{
printf("You must provide a PKCS7 file\n");
goto MissedPKCS7FileError;
}
hr = CoInitialize(NULL);
if (S_OK != hr && S_FALSE != hr)
{
goto CoInitializeError;
}
fCoInit = TRUE;
hr = CoCreateInstance(
CLSID_CEnroll,
NULL,
CLSCTX_INPROC_SERVER,
IID_IEnroll4,
(void **) &pIEnroll4);
if( S_OK != hr || NULL == pIEnroll4)
{
goto CoCreateInstanceError;
}
hr = myMultiByteToWideChar(g_pszPKCS7FileName, &pwszPKCS7FileName);
if (S_OK != hr)
{
goto myMultiByteToWideCharError;
}
hr = pIEnroll4->acceptFilePKCS7WStr(pwszPKCS7FileName);
if (S_OK != hr)
{
goto acceptFilePKCS7WStrError;
}
if (NULL != g_pszPFXFileName)
{
if (NULL == g_pszPFXPassword)
{
pwszPFXPassword = wszEmptyPassword;
if (g_fVerb)
{
printf("Empty PFX password is used.\n");
}
}
hr = myMultiByteToWideChar(g_pszPFXFileName, &pwszPFXFileName);
if (S_OK != hr)
{
goto myMultiByteToWideCharError;
}
if (NULL != g_pszPFXPassword)
{
hr = myMultiByteToWideChar(g_pszPFXPassword, &pwszPFXPassword);
if (S_OK != hr)
{
goto myMultiByteToWideCharError;
}
}
//create pfx file
hr = pIEnroll4->createFilePFXWStr(pwszPFXPassword, pwszPFXFileName);
if (S_OK != hr)
{
goto createFilePFXWStrError;
}
}
done:
fRet = TRUE;
ErrorReturn:
if(NULL != pIEnroll4)
{
pIEnroll4->Release();
}
if (fCoInit)
{
CoUninitialize();
}
if (NULL != pwszPKCS7FileName)
{
LocalFree(pwszPKCS7FileName);
}
if (NULL != pwszPFXFileName)
{
LocalFree(pwszPFXFileName);
}
if (NULL != pwszPFXPassword && pwszPFXPassword != wszEmptyPassword)
{
LocalFree(pwszPFXPassword);
}
return fRet;
PRINT_ERROR2(CoCreateInstanceError, hr)
PRINT_ERROR2(myMultiByteToWideCharError, hr)
PRINT_ERROR2(acceptFilePKCS7WStrError, hr)
PRINT_ERROR2(createFilePFXWStrError, hr)
PRINT_ERROR2(CoInitializeError, hr)
PRINT_ERROR2(MissedPKCS7FileError, E_INVALIDARG)
}
//+---------------------------------------------------------------------------
//
// Function: Usage
//
// Synopsis: prints the usage statement
//
//----------------------------------------------------------------------------
static void Usage(DWORD cTest)
{
printf("Usage: txenrol [options]\n");
printf(" options:\n");
printf(" -h this help\n");
printf(" -k [KeyContainerName]\n");
printf(" -n [DNName]\n");
printf(" -x [CAExchangeCertFileName]\n");
printf(" -o [CMCRequestFileName]\n");
printf(" -s [#] stress test count\n");
printf(" -t [TestID] run single test. There are %d tests.\n", cTest);
printf(" -r [CMCResponseFile]\n");
printf(" -a [PKCS7FileName]\n");
printf(" -f [PFXFileName], -a is required\n");
printf(" -w [PFXPassword], -a is required. If no -p, empty password is used.\n");
printf(" -p pause before each test\n");
printf(" -v verbose\n");
printf("\n");
printf(" Test1: basic operation, gen keys, gen request, accept cert.\n");
printf(" Test2: basic operation but with no EKU or no DN name.\n");
printf(" Test3: test renewal cert.\n");
printf(" Test4: basic operation but put the certs in HKLM\n");
printf(" Test5: test self signed certificate creation\n");
printf(" Test6: basic operation with attributes\n");
printf(" Test7: basic operation but put the certs in HKLM\n");
printf(" Test8: test some alg enum stuff\n");
printf(" Test9: test some alg enum stuff\n");
printf(" Test10: test renewal\n");
printf(" Test11: test CMC request generation\n");
printf(" Test12: test CMC response. skipped except -r is passed\n");
printf(" Test13: test pending API\n");
printf(" Test14: test Enroll4 misc. methods\n");
printf(" Test15: test acceptPKCS7 and PFX\n");
}
BOOL
ParseOptions(int argc, char *argv[])
{
int i;
for (i = 1; i < argc; ++i)
{
if ('-' == argv[i][0])
{
switch (argv[i][1])
{
case 'n':
case 'N':
++i;
if (i < argc)
{
g_pszDNName = argv[i];
}
else
{
printf("missed DNName\n");
return FALSE;
}
break;
case 'x':
case 'X':
++i;
if (i < argc)
{
g_pszCAXchgFileName = argv[i];
}
else
{
printf("missed CAExchangeFileName\n");
return FALSE;
}
break;
case 'o':
case 'O':
++i;
if (i < argc)
{
g_pszCMCFileName = argv[i];
}
else
{
printf("missed CMCRequestFileName\n");
return FALSE;
}
break;
case 'w':
case 'W':
++i;
if (i < argc)
{
g_pszPFXPassword = argv[i];
}
else
{
printf("missed PFXPassword\n");
return FALSE;
}
break;
case 'f':
case 'F':
++i;
if (i < argc)
{
g_pszPFXFileName = argv[i];
}
else
{
printf("missed PFXFileName\n");
return FALSE;
}
break;
case 'a':
case 'A':
++i;
if (i < argc)
{
g_pszPKCS7FileName = argv[i];
}
else
{
printf("missed PKCS7FileName\n");
return FALSE;
}
break;
case 'r':
case 'R':
++i;
if (i < argc)
{
g_pszCMCResponseFileName = argv[i];
}
else
{
printf("missed CMCResponseFileName\n");
return FALSE;
}
break;
case 'k':
case 'K':
++i;
if (i < argc)
{
g_pszKeyContainer = argv[i];
}
else
{
printf("missed KeyContainerName\n");
return FALSE;
}
break;
case 's':
case 'S':
++i;
if (i < argc)
{
g_cStress = atoi(argv[i]);
}
break;
case 't':
case 'T':
++i;
if (i < argc)
{
g_dwTestID = atoi(argv[i]);
}
break;
case 'p':
case 'P':
g_fPause = TRUE;
break;
case 'v':
case 'V':
g_fVerb = TRUE;
break;
case 'h':
case 'H':
return FALSE;
default:
printf("Unrecognized options -%c\n", argv[i][1]);
return FALSE;
break;
}
}
else
{
printf("Unrecognized options %s\n", argv[i]);
return FALSE;
}
}
return TRUE;
}
//+---------------------------------------------------------------------------
//
// Function: main
//
// Synopsis: main program entry point
//
//----------------------------------------------------------------------------
typedef BOOL (* PFNTest)(void);
PFNTest arPfnTest[] = {Test1, Test2, Test3, Test4, Test5, Test6, Test7, Test8, Test9, Test10, Test11, Test12, Test13, Test14, Test15};
#define COUNT_TEST sizeof(arPfnTest)/sizeof(arPfnTest[0])
int _cdecl main(int argc, char * argv[])
{
int ErrReturn = 0;
DWORD i;
DWORD n;
DWORD NBRTests = sizeof(arPfnTest) / sizeof(PFNTest);
BOOL fPassed = TRUE;
if (1 > argc)
{
Usage(COUNT_TEST);
return( 1 );
}
//parse options
if (!ParseOptions(argc, argv))
{
Usage(COUNT_TEST);
return (1);
}
for (DWORD n = 0; n < g_cStress; ++n)
{
if (g_fPause)
{
char wszgets[3];
if (MAXDWORD == g_dwTestID)
{
printf("press enter key to start the tests ...");
}
else
{
printf("press enter key to run Test%d ...", g_dwTestID);
}
gets(wszgets);
}
if (MAXDWORD != g_dwTestID &&
COUNT_TEST >= g_dwTestID)
{
//only do one test
if (!arPfnTest[g_dwTestID - 1]())
{
printf("Test%d failed.\n", g_dwTestID);
fPassed = FALSE;
}
else
{
printf("Test%d finished.\n", g_dwTestID);
}
}
else
{
for(i=0; i<NBRTests; i++)
{
if( !arPfnTest[i]() )
{
printf("Test%d failed.\n", i+1);
fPassed = FALSE;
}
else
{
printf("Test%d finished.\n", i+1);
}
}
}
if (1 < g_cStress)
{
printf("test round %d finished\n", n+1);
}
}
if (fPassed)
{
printf("All XEnroll tests passed.\n");
}
else
{
printf("One or more XEnroll tests didn't pass.\n");
}
return(ErrReturn);
}