//+------------------------------------------------------------------------- // // Microsoft Windows NT // // Copyright (C) Microsoft Corporation, 1995 - 1998 // // File: cepca.cpp // // Contents: Cisco enrollment protocal implementation. // This file has the control's (ra) specific code. // //-------------------------------------------------------------------------- #include "global.hxx" #include //-------------------------------------------------------------------------- // // FreeRAInformation // //-------------------------------------------------------------------------- BOOL FreeRAInformation(CEP_RA_INFO *pRAInfo) { if(pRAInfo) { if(pRAInfo->fFree) { if(pRAInfo->hRAProv) CryptReleaseContext(pRAInfo->hRAProv, 0); } if(pRAInfo->fSignFree) { if(pRAInfo->hSignProv) CryptReleaseContext(pRAInfo->hSignProv, 0); } if(pRAInfo->pRACert) CertFreeCertificateContext(pRAInfo->pRACert); if(pRAInfo->pRASign) CertFreeCertificateContext(pRAInfo->pRASign); memset(pRAInfo, 0, sizeof(CEP_RA_INFO)); } return TRUE; } /* //-------------------------------------------------------------------------- // // GetRAInfo // //-------------------------------------------------------------------------- BOOL GetRAInfo(CEP_RA_INFO *pRAInfo) { BOOL fResult = FALSE; HCERTSTORE hCEPStore=NULL; DWORD dwSize=0; DWORD dwIndex=0; HANDLE hThread=NULL; //no need to close HANDLE hToken=NULL; HCERTSTORE hSignStore=NULL; CERT_ENHKEY_USAGE *pKeyUsage = NULL; memset(pRAInfo, 0, sizeof(CEP_RA_INFO)); // so we can get access to the local machine's private key hThread=GetCurrentThread(); if(NULL != hThread) { if(OpenThreadToken(hThread, TOKEN_IMPERSONATE | TOKEN_QUERY, FALSE, &hToken)) { if(hToken) { //no need to check for return here. If this failed, just go on RevertToSelf(); } } } //sign RA if(!(hSignStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W, ENCODE_TYPE, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG, L"CEPSIGN"))) goto TraceErr; if(!(pRAInfo->pRASign=CertEnumCertificatesInStore( hSignStore, NULL))) goto TraceErr; //the RA cert should have private key and enrollment agent usage dwSize=0; if(!CertGetCertificateContextProperty( pRAInfo->pRASign, CERT_KEY_PROV_INFO_PROP_ID, NULL, &dwSize) || (0==dwSize)) goto InvalidArgErr; if(!CryptAcquireCertificatePrivateKey(pRAInfo->pRASign, CRYPT_ACQUIRE_COMPARE_KEY_FLAG | CRYPT_ACQUIRE_CACHE_FLAG, NULL, &(pRAInfo->hSignProv), &(pRAInfo->dwSignKeySpec), &(pRAInfo->fSignFree))) goto TraceErr; //exchange RA if(!(hCEPStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W, ENCODE_TYPE, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG, CEP_STORE_NAME))) goto TraceErr; if(!(pRAInfo->pRACert=CertEnumCertificatesInStore( hCEPStore, NULL))) goto TraceErr; //the RA cert should have private key and enrollment agent usage dwSize=0; if(!CertGetCertificateContextProperty( pRAInfo->pRACert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &dwSize) || (0==dwSize)) goto InvalidArgErr; if(!CryptAcquireCertificatePrivateKey(pRAInfo->pRACert, CRYPT_ACQUIRE_COMPARE_KEY_FLAG | CRYPT_ACQUIRE_CACHE_FLAG, NULL, &(pRAInfo->hRAProv), &(pRAInfo->dwKeySpec), &(pRAInfo->fFree))) goto TraceErr; if(!CertGetEnhancedKeyUsage(pRAInfo->pRACert, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &dwSize)) goto InvalidArgErr; if(NULL==(pKeyUsage=(CERT_ENHKEY_USAGE *)malloc(dwSize))) goto MemoryErr; if (!CertGetEnhancedKeyUsage(pRAInfo->pRACert, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pKeyUsage, &dwSize)) goto InvalidArgErr; for(dwIndex=0; dwIndex < pKeyUsage->cUsageIdentifier; dwIndex++) { if(0 == strcmp(pKeyUsage->rgpszUsageIdentifier[dwIndex], szOID_ENROLLMENT_AGENT)) { fResult=TRUE; break; } } if(!fResult) goto ErrorReturn; CommonReturn: if(hCEPStore) CertCloseStore(hCEPStore, 0); if(hSignStore) CertCloseStore(hSignStore, 0); if(pKeyUsage) free(pKeyUsage); //if hToken is valid, we reverted to ourselves. if(hToken) { SetThreadToken(&hThread, hToken); CloseHandle(hToken); } return fResult; ErrorReturn: FreeRAInformation(pRAInfo); fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); SET_ERROR(MemoryErr, E_OUTOFMEMORY); TRACE_ERROR(TraceErr); } */ //-------------------------------------------------------------------------- // // SigningCert // //-------------------------------------------------------------------------- BOOL WINAPI SigningCert(PCCERT_CONTEXT pCertContext) { BOOL fSign=FALSE; PCERT_EXTENSION pExt=NULL; DWORD cbSize=0; CRYPT_BIT_BLOB *pKeyUsage=NULL; if(!pCertContext) goto CLEANUP; if(!(pExt=CertFindExtension( szOID_KEY_USAGE, pCertContext->pCertInfo->cExtension, pCertContext->pCertInfo->rgExtension))) goto CLEANUP; if(!CryptDecodeObject(ENCODE_TYPE, X509_KEY_USAGE, pExt->Value.pbData, pExt->Value.cbData, 0, NULL, &cbSize)) goto CLEANUP; pKeyUsage=(CRYPT_BIT_BLOB *)malloc(cbSize); if(NULL==pKeyUsage) goto CLEANUP; if(!CryptDecodeObject(ENCODE_TYPE, X509_KEY_USAGE, pExt->Value.pbData, pExt->Value.cbData, 0, pKeyUsage, &cbSize)) goto CLEANUP; if(CERT_DIGITAL_SIGNATURE_KEY_USAGE & (pKeyUsage->pbData[0])) fSign=TRUE; CLEANUP: if(pKeyUsage) free(pKeyUsage); return fSign; } //-------------------------------------------------------------------------- // // GetConfigInfo // //-------------------------------------------------------------------------- BOOL WINAPI GetConfigInfo(DWORD *pdwRefreshDays, BOOL *pfPassword) { DWORD cbData=0; DWORD dwData=0; DWORD dwType=0; BOOL fResult=FALSE; long dwErr=0; HKEY hKeyRefresh=NULL; HKEY hKeyPassword=NULL; if(!pdwRefreshDays || !pfPassword) goto InvalidArgErr; //default the refresh days *pdwRefreshDays=CEP_REFRESH_DAY; *pfPassword=FALSE; if(ERROR_SUCCESS == RegOpenKeyExU( HKEY_LOCAL_MACHINE, MSCEP_REFRESH_LOCATION, 0, KEY_READ, &hKeyRefresh)) { cbData=sizeof(dwData); if(ERROR_SUCCESS == RegQueryValueExU( hKeyRefresh, MSCEP_KEY_REFRESH, NULL, &dwType, (BYTE *)&dwData, &cbData)) { if ((dwType == REG_DWORD) || (dwType == REG_BINARY)) { *pdwRefreshDays=dwData; } } } dwType=0; dwData=0; cbData=sizeof(dwData); //we have to have the knowledge of the password policy if(ERROR_SUCCESS != (dwErr = RegOpenKeyExU( HKEY_LOCAL_MACHINE, MSCEP_PASSWORD_LOCATION, 0, KEY_READ, &hKeyPassword))) goto RegErr; if(ERROR_SUCCESS != (dwErr = RegQueryValueExU( hKeyPassword, MSCEP_KEY_PASSWORD, NULL, &dwType, (BYTE *)&dwData, &cbData))) goto RegErr; if ((dwType != REG_DWORD) && (dwType != REG_BINARY)) goto RegErr; if(0 == dwData) *pfPassword=FALSE; else *pfPassword=TRUE; fResult=TRUE; CommonReturn: if(hKeyRefresh) RegCloseKey(hKeyRefresh); if(hKeyPassword) RegCloseKey(hKeyPassword); return fResult; ErrorReturn: if(pdwRefreshDays) *pdwRefreshDays=0; if(pfPassword) *pfPassword=FALSE; fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); SET_ERROR_VAR(RegErr, dwErr); } //-------------------------------------------------------------------------- // // GetRAInfo // // We need to have two RA cert: One for signature cert (also the enrollment // agent) and one for the key encipherment. //-------------------------------------------------------------------------- BOOL GetRAInfo(CEP_RA_INFO *pRAInfo) { BOOL fResult = FALSE; BOOL fFound = FALSE; DWORD dwSize=0; DWORD dwIndex=0; HANDLE hThread=NULL; //no need to close PCCERT_CONTEXT pPreCert=NULL; HCERTSTORE hCEPStore=NULL; CERT_ENHKEY_USAGE *pKeyUsage = NULL; PCCERT_CONTEXT pCurCert=NULL; HANDLE hToken=NULL; memset(pRAInfo, 0, sizeof(CEP_RA_INFO)); if(!GetConfigInfo(&(pRAInfo->dwRefreshDays), &(pRAInfo->fPassword))) goto TraceErr; // so we can get access to the local machine's private key hThread=GetCurrentThread(); if(NULL != hThread) { if(OpenThreadToken(hThread, TOKEN_IMPERSONATE | TOKEN_QUERY, FALSE, &hToken)) { if(hToken) { //no need to check for return here. If this failed, just go on RevertToSelf(); } } } if(!(hCEPStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W, ENCODE_TYPE, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG, CEP_STORE_NAME))) goto TraceErr; while(pCurCert=CertEnumCertificatesInStore(hCEPStore, pPreCert)) { //has to have a private key dwSize=0; if(!CertGetCertificateContextProperty( pCurCert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &dwSize) || (0==dwSize)) goto InvalidArgErr; //decide based on the key usage if(SigningCert(pCurCert)) { //one signing RA Only if(pRAInfo->pRASign) goto InvalidArgErr; if(!(pRAInfo->pRASign=CertDuplicateCertificateContext(pCurCert))) goto TraceErr; if(!CryptAcquireCertificatePrivateKey(pRAInfo->pRASign, CRYPT_ACQUIRE_COMPARE_KEY_FLAG | CRYPT_ACQUIRE_CACHE_FLAG, NULL, &(pRAInfo->hSignProv), &(pRAInfo->dwSignKeySpec), &(pRAInfo->fSignFree))) goto TraceErr; //has to have the enrollment agent eku dwSize=0; if(!CertGetEnhancedKeyUsage(pCurCert, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &dwSize)) goto InvalidArgErr; if(NULL==(pKeyUsage=(CERT_ENHKEY_USAGE *)malloc(dwSize))) goto MemoryErr; if (!CertGetEnhancedKeyUsage(pCurCert, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pKeyUsage, &dwSize)) goto InvalidArgErr; fFound=FALSE; for(dwIndex=0; dwIndex < pKeyUsage->cUsageIdentifier; dwIndex++) { if(0 == strcmp(pKeyUsage->rgpszUsageIdentifier[dwIndex], szOID_ENROLLMENT_AGENT)) { fFound=TRUE; break; } } if(!fFound) goto InvalidArgErr; } else { //one encryption RA only if(pRAInfo->pRACert) goto InvalidArgErr; if(!(pRAInfo->pRACert=CertDuplicateCertificateContext(pCurCert))) goto TraceErr; if(!CryptAcquireCertificatePrivateKey(pRAInfo->pRACert, CRYPT_ACQUIRE_COMPARE_KEY_FLAG | CRYPT_ACQUIRE_CACHE_FLAG, NULL, &(pRAInfo->hRAProv), &(pRAInfo->dwKeySpec), &(pRAInfo->fFree))) goto TraceErr; } if(pKeyUsage) { free(pKeyUsage); pKeyUsage=NULL; } pPreCert=pCurCert; } //we have to have both RA certs if((NULL == pRAInfo->pRACert) || (NULL == pRAInfo->pRASign)) goto InvalidArgErr; fResult=TRUE; CommonReturn: if(hCEPStore) CertCloseStore(hCEPStore, 0); if(pKeyUsage) free(pKeyUsage); //if hToken is valid, we reverted to ourselves. if(hToken) { SetThreadToken(&hThread, hToken); CloseHandle(hToken); } if(pCurCert) CertFreeCertificateContext(pCurCert); return fResult; ErrorReturn: FreeRAInformation(pRAInfo); fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); SET_ERROR(MemoryErr, E_OUTOFMEMORY); TRACE_ERROR(TraceErr); } //-------------------------------------------------------------------------- // // OperationGetPKI // //-------------------------------------------------------------------------- BOOL OperationGetPKI( CEP_RA_INFO *pRAInfo, CEP_CA_INFO *pCAInfo, LPSTR szMsg, BYTE **ppbData, DWORD *pcbData) { BOOL fResult = FALSE; CEP_MESSAGE_INFO MsgInfo; DWORD cbContent=0; DWORD cbEnvelop=1; BYTE bFoo=0; BYTE *pbContent=NULL; BYTE *pbEnvelop=&bFoo; memset(&MsgInfo, 0, sizeof(CEP_MESSAGE_INFO)); if(!GetReturnInfoAndContent(pRAInfo, pCAInfo, szMsg, &pbContent, &cbContent, &MsgInfo)) goto TraceErr; //envelop the data if(MESSAGE_STATUS_SUCCESS == MsgInfo.dwStatus) { if(!EnvelopData(MsgInfo.pSigningCert, pbContent, cbContent, &pbEnvelop, &cbEnvelop)) { LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_TO_ENCRYPT, 1, g_pwszComputerName); goto TraceErr; } } //sign the data with authenticated attributes //when the dwStatus is not SUCCESS, the pbEnvelop is NULL and cbEnvelop is 0. if(!SignData(&MsgInfo, pRAInfo, pbEnvelop, cbEnvelop, ppbData, pcbData)) { LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_TO_SIGN, 1, g_pwszComputerName); goto TraceErr; } fResult = TRUE; CommonReturn: if(pbContent) free(pbContent); if(&bFoo != pbEnvelop) free(pbEnvelop); FreeMessageInfo(&MsgInfo); return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; TRACE_ERROR(TraceErr); } //-------------------------------------------------------------------------- // // SignData // // the messageType is always response and the senderNonce should be generated // in case the pending and failure, pbEnvelop will be NULL. // // In the initial GetContentFromPKCS7, we retrive MessageType, TransactionID, // RecipientNonce, signing Cert serial number. // // In the process, we get the dwStatus and dwErrorInfo when applicable. ////-------------------------------------------------------------------------- BOOL SignData(CEP_MESSAGE_INFO *pMsgInfo, CEP_RA_INFO *pRAInfo, BYTE *pbEnvelop, DWORD cbEnvelop, BYTE **ppbData, DWORD *pcbData) { BOOL fResult = FALSE; CMSG_SIGNER_ENCODE_INFO SignerInfo; CMSG_SIGNED_ENCODE_INFO SignEncodedInfo; CERT_BLOB CertBlob; BOOL fProvFree=FALSE; PCCRYPT_OID_INFO pOIDInfo=NULL; ALG_ID AlgValue=CALG_MD5; DWORD cAttr=0; CRYPT_ATTR_BLOB rgAttrBlob[CEP_RESPONSE_AUTH_ATTR_COUNT]; DWORD dwIndex=0; HCRYPTMSG hMsg=NULL; CRYPT_ATTRIBUTE rgAttr[CEP_RESPONSE_AUTH_ATTR_COUNT]; if(!pMsgInfo || !pRAInfo || !ppbData || !pcbData) goto InvalidArgErr; *ppbData=NULL; *pcbData=0; pMsgInfo->dwMessageType=MESSAGE_TYPE_CERT_RESPONSE; if(!GenerateSenderNonce(&(pMsgInfo->SenderNonce))) goto TraceErr; memset(&SignerInfo, 0, sizeof(SignerInfo)); memset(&SignEncodedInfo, 0, sizeof(SignEncodedInfo)); SignEncodedInfo.cbSize=sizeof(SignEncodedInfo); SignEncodedInfo.cSigners=1; SignEncodedInfo.rgSigners=&SignerInfo, /* SignEncodedInfo.cCertEncoded=1; SignEncodedInfo.rgCertEncoded=&CertBlob; */ SignEncodedInfo.cCertEncoded=0; SignEncodedInfo.rgCertEncoded=NULL; SignEncodedInfo.cCrlEncoded=0; SignEncodedInfo.rgCrlEncoded=NULL; CertBlob.cbData=pRAInfo->pRASign->cbCertEncoded; CertBlob.pbData=pRAInfo->pRASign->pbCertEncoded; SignerInfo.cbSize=sizeof(SignerInfo); SignerInfo.pCertInfo=pRAInfo->pRASign->pCertInfo; //specify AlgID if(pOIDInfo=CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY, &AlgValue, CRYPT_HASH_ALG_OID_GROUP_ID)) SignerInfo.HashAlgorithm.pszObjId=(LPSTR)(pOIDInfo->pszOID); else SignerInfo.HashAlgorithm.pszObjId=szOID_RSA_MD5; //get the private key SignerInfo.hCryptProv=pRAInfo->hSignProv; SignerInfo.dwKeySpec=pRAInfo->dwSignKeySpec; //get the autheticated attributes //together we should have 6 attributes: TransactionID, MessageType, PkiStatus, //ErrorInfo, senderNonce, and recipientNonce memset(rgAttr, 0, CEP_RESPONSE_AUTH_ATTR_COUNT * sizeof(CRYPT_ATTRIBUTE)); memset(rgAttrBlob, 0, CEP_RESPONSE_AUTH_ATTR_COUNT * sizeof(CRYPT_ATTR_BLOB)); for(dwIndex=0; dwIndexTransactionID.cbData=strlen((LPSTR)(pMsgInfo->TransactionID.pbData)); if(!CEPAllocAndEncodeName(CERT_RDN_PRINTABLE_STRING, pMsgInfo->TransactionID.pbData, pMsgInfo->TransactionID.cbData, &(rgAttr[cAttr].rgValue[0].pbData), &(rgAttr[cAttr].rgValue[0].cbData))) goto TraceErr; cAttr++; //MessageType rgAttr[cAttr].pszObjId=szOIDVerisign_MessageType; if(!CEPAllocAndEncodeDword(CERT_RDN_PRINTABLE_STRING, pMsgInfo->dwMessageType, &(rgAttr[cAttr].rgValue[0].pbData), &(rgAttr[cAttr].rgValue[0].cbData))) goto TraceErr; cAttr++; //Status rgAttr[cAttr].pszObjId=szOIDVerisign_PkiStatus; if(!CEPAllocAndEncodeDword(CERT_RDN_PRINTABLE_STRING, pMsgInfo->dwStatus, &(rgAttr[cAttr].rgValue[0].pbData), &(rgAttr[cAttr].rgValue[0].cbData))) goto TraceErr; cAttr++; //ErrorInfo only if the error case if(MESSAGE_STATUS_FAILURE == pMsgInfo->dwStatus) { rgAttr[cAttr].pszObjId=szOIDVerisign_FailInfo; if(!CEPAllocAndEncodeDword(CERT_RDN_PRINTABLE_STRING, pMsgInfo->dwErrorInfo, &(rgAttr[cAttr].rgValue[0].pbData), &(rgAttr[cAttr].rgValue[0].cbData))) goto TraceErr; cAttr++; } //senderNonce rgAttr[cAttr].pszObjId=szOIDVerisign_SenderNonce; if(!CEPAllocAndEncodeName(CERT_RDN_OCTET_STRING, pMsgInfo->SenderNonce.pbData, pMsgInfo->SenderNonce.cbData, &(rgAttr[cAttr].rgValue[0].pbData), &(rgAttr[cAttr].rgValue[0].cbData))) goto TraceErr; cAttr++; //recipientNonce rgAttr[cAttr].pszObjId=szOIDVerisign_RecipientNonce; if(!CEPAllocAndEncodeName(CERT_RDN_OCTET_STRING, pMsgInfo->RecipientNonce.pbData, pMsgInfo->RecipientNonce.cbData, &(rgAttr[cAttr].rgValue[0].pbData), &(rgAttr[cAttr].rgValue[0].cbData))) goto TraceErr; cAttr++; SignerInfo.cAuthAttr=cAttr; SignerInfo.rgAuthAttr=rgAttr; //message encoding if(NULL==(hMsg=CryptMsgOpenToEncode(ENCODE_TYPE, 0, CMSG_SIGNED, &SignEncodedInfo, NULL, //we are encoding as CMSG_DATA(7.1) NULL))) goto TraceErr; if(!CryptMsgUpdate(hMsg, pbEnvelop, cbEnvelop, TRUE)) goto TraceErr; if(!CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, NULL, pcbData)) goto TraceErr; *ppbData=(BYTE *)malloc(*pcbData); if(NULL==(*ppbData)) goto MemoryErr; if(!CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, *ppbData, pcbData)) goto TraceErr; fResult = TRUE; CommonReturn: for(dwIndex=0; dwIndex < cAttr; dwIndex ++) { if(rgAttrBlob[dwIndex].pbData) free(rgAttrBlob[dwIndex].pbData); } if(hMsg) CryptMsgClose(hMsg); return fResult; ErrorReturn: if(ppbData) { if(*ppbData) { free(*ppbData); *ppbData=NULL; } } if(pcbData) *pcbData=0; fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); TRACE_ERROR(TraceErr); SET_ERROR(MemoryErr, E_OUTOFMEMORY); } //-------------------------------------------------------------------------- // // CEPAllocAndEncodeDword // // PreCondition: ppbEncoded and pcbEncoded should not be NULL. // The dwData is no more than 11 //-------------------------------------------------------------------------- BOOL CEPAllocAndEncodeDword(DWORD dwValueType, DWORD dwData, BYTE **ppbEncoded, DWORD *pcbEncoded) { BOOL fResult = FALSE; CHAR szString[12]; BYTE *pbData=NULL; DWORD cbData=0; _ltoa(dwData, szString, 10); pbData=(BYTE *)szString; cbData=strlen(szString); return CEPAllocAndEncodeName(dwValueType, pbData, cbData, ppbEncoded, pcbEncoded); } //-------------------------------------------------------------------------- // // CEPAllocAndEncodeName // // PreCondition: ppbEncoded and pcbEncoded should not be NULL. //-------------------------------------------------------------------------- BOOL CEPAllocAndEncodeName(DWORD dwValueType, BYTE *pbData, DWORD cbData, BYTE **ppbEncoded, DWORD *pcbEncoded) { CERT_NAME_VALUE CertName; *ppbEncoded=NULL; *pcbEncoded=0; CertName.dwValueType=dwValueType; CertName.Value.pbData=pbData; CertName.Value.cbData=cbData; return CEPAllocAndEncode(X509_ANY_STRING, &CertName, ppbEncoded, pcbEncoded); } //-------------------------------------------------------------------------- // // GenerateSenderNonce // // We use GUID to generate a random 16 byte number // //-------------------------------------------------------------------------- BOOL GenerateSenderNonce(CRYPT_INTEGER_BLOB *pBlob) { BOOL fResult = FALSE; GUID guid; BYTE *pData=NULL; UuidCreate(&guid); pBlob->cbData=sizeof(guid.Data1) + sizeof(guid.Data2) + sizeof(guid.Data3) + sizeof(guid.Data4); pBlob->pbData=(BYTE *)malloc(pBlob->cbData); if(NULL==(pBlob->pbData)) goto MemoryErr; pData=pBlob->pbData; memcpy(pData, &(guid.Data1), sizeof(guid.Data1)); pData += sizeof(guid.Data1); memcpy(pData, &(guid.Data2), sizeof(guid.Data2)); pData += sizeof(guid.Data2); memcpy(pData, &(guid.Data3), sizeof(guid.Data3)); pData += sizeof(guid.Data3); memcpy(pData, &(guid.Data4), sizeof(guid.Data4)); fResult = TRUE; CommonReturn: return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; SET_ERROR(MemoryErr, E_OUTOFMEMORY); } //-------------------------------------------------------------------------- // // EnvelopData // // In the initial GetContentFromPKCS7, we retrieve pSigningCert for // GetCertInitial, CertReq, and GetCert request. // // In the process,we retrieve pSigningCert for GetCRL request. //-------------------------------------------------------------------------- BOOL EnvelopData(PCCERT_CONTEXT pSigningCert, BYTE *pbContent, DWORD cbContent, BYTE **ppbEnvelop, DWORD *pcbEnvelop) { BOOL fResult = FALSE; CMSG_ENVELOPED_ENCODE_INFO EnvInfo; HCRYPTMSG hMsg=NULL; if(!pSigningCert || !pbContent || !ppbEnvelop || !pcbEnvelop) goto InvalidArgErr; *ppbEnvelop=NULL; *pcbEnvelop=0; memset(&EnvInfo, 0, sizeof(CMSG_ENVELOPED_ENCODE_INFO)); EnvInfo.cbSize=sizeof(CMSG_ENVELOPED_ENCODE_INFO); EnvInfo.hCryptProv=NULL; EnvInfo.ContentEncryptionAlgorithm.pszObjId=szOID_OIWSEC_desCBC; EnvInfo.pvEncryptionAuxInfo=NULL; EnvInfo.cRecipients=1; EnvInfo.rgpRecipients=(PCERT_INFO *)(&(pSigningCert->pCertInfo)); if(NULL==(hMsg=CryptMsgOpenToEncode(ENCODE_TYPE, 0, CMSG_ENVELOPED, &EnvInfo, NULL, //we are encoding as CMSG_DATA(7.1) NULL))) goto TraceErr; if(!CryptMsgUpdate(hMsg, pbContent, cbContent, TRUE)) goto TraceErr; if(!CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, NULL, pcbEnvelop)) goto TraceErr; *ppbEnvelop=(BYTE *)malloc(*pcbEnvelop); if(NULL==(*ppbEnvelop)) goto MemoryErr; if(!CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, *ppbEnvelop, pcbEnvelop)) goto TraceErr; fResult = TRUE; CommonReturn: if(hMsg) CryptMsgClose(hMsg); return fResult; ErrorReturn: if(ppbEnvelop) { if(*ppbEnvelop) { free(*ppbEnvelop); *ppbEnvelop=NULL; } } if(pcbEnvelop) *pcbEnvelop=0; fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); TRACE_ERROR(TraceErr); SET_ERROR(MemoryErr, E_OUTOFMEMORY); } //-------------------------------------------------------------------------- // // DecodeCertW // //-------------------------------------------------------------------------- HRESULT DecodeCertW( IN void const *pchIn, IN DWORD cchIn, IN DWORD Flags, OUT BYTE **ppbOut, OUT DWORD *pcbOut) { HRESULT hr; BYTE *pbOut = NULL; DWORD cbOut; BOOL fRet; //init *ppbOut = NULL; *pcbOut = 0; while (TRUE) { fRet = CryptStringToBinaryW((LPCWSTR)pchIn, cchIn, Flags, pbOut, &cbOut, NULL, NULL); if (!fRet) { hr = GetLastError(); goto error; } if (NULL != pbOut) { break; //done } pbOut = (BYTE*)LocalAlloc(LMEM_FIXED, cbOut); if (NULL == pbOut) { hr = E_OUTOFMEMORY; goto error; } } *ppbOut = pbOut; pbOut = NULL; *pcbOut = cbOut; hr = S_OK; error: if (NULL != pbOut) { LocalFree(pbOut); } return hr; } //-------------------------------------------------------------------------- // // GetReturnInfoAndContent // //-------------------------------------------------------------------------- BOOL GetReturnInfoAndContent(CEP_RA_INFO *pRAInfo, CEP_CA_INFO *pCAInfo, LPSTR szMsg, BYTE **ppbData, DWORD *pcbData, CEP_MESSAGE_INFO *pMsgInfo) { BOOL fResult = FALSE; DWORD cbBase64Decoded=0; DWORD cbReqEnv=0; DWORD cbReqDecrypt=0; DWORD cbSize=0; HRESULT hr=E_FAIL; BYTE *pbBase64Decoded=NULL; BYTE *pbReqEnv=NULL; BYTE *pbReqDecrypt=NULL; WCHAR wszBuffer[INTERNET_MAX_PATH_LENGTH * 2 +1]; LPWSTR pwszMsg=NULL; LPWSTR pwszBuffer=NULL; //convert sz to wsz pwszMsg=MkWStr(szMsg); if(NULL==pwszMsg) goto MemoryErr; //we need to get rid of the escape characters if(S_OK != (hr=CoInternetParseUrl(pwszMsg, PARSE_UNESCAPE, 0, wszBuffer, INTERNET_MAX_PATH_LENGTH*2, &cbSize, 0))) { //S_FALSE means that the buffer is too small if(S_FALSE != hr) { LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_FAIL_TO_CONVERT, 1, g_pwszComputerName); goto TraceErr; } if(0==cbSize) { LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_FAIL_TO_CONVERT, 1, g_pwszComputerName); goto TraceErr; } //allocate the buffer pwszBuffer=(LPWSTR)malloc(cbSize * sizeof(WCHAR)); if(NULL==pwszBuffer) goto MemoryErr; *pwszBuffer=L'\0'; if(S_OK != (hr = CoInternetParseUrl(pwszMsg, PARSE_UNESCAPE, 0, pwszBuffer, cbSize, &cbSize, 0))) { LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_FAIL_TO_CONVERT, 1, g_pwszComputerName); goto TraceErr; } } if(S_OK != (hr = DecodeCertW( pwszBuffer ? pwszBuffer : wszBuffer, pwszBuffer ? wcslen(pwszBuffer) : wcslen(wszBuffer), CRYPT_STRING_BASE64_ANY, //DECF_BASE64_ANY, &pbBase64Decoded, &cbBase64Decoded))) { LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_FAIL_TO_DECODE, 1, g_pwszComputerName); goto FailureStatusReturn; } //get the message type, transaction ID, recepientNonce, serial number in the //signer_info of the most outer PKCS#7 and inner content if(!GetContentFromPKCS7(pbBase64Decoded, cbBase64Decoded, &pbReqEnv, &cbReqEnv, pMsgInfo)) { LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_TO_RETRIEVE_INFO, 1, g_pwszComputerName); goto FailureStatusReturn; } //decrypt the inner content if(!DecryptMsg(pRAInfo, pbReqEnv, cbReqEnv, &pbReqDecrypt, &cbReqDecrypt)) { LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_TO_DECRYPT_INNER, 1, g_pwszComputerName); goto FailureStatusReturn; } //get the return inner content based on the message type switch(pMsgInfo->dwMessageType) { case MESSAGE_TYPE_CERT_REQUEST: //we use the signing RA cert as the enrollment agent if(!ProcessCertRequest( pRAInfo->dwRefreshDays, pRAInfo->fPassword, pRAInfo->pRACert, pRAInfo->pRASign, pCAInfo, pbReqDecrypt, cbReqDecrypt, ppbData, pcbData, pMsgInfo)) { LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_CERT_REQ, 1, g_pwszComputerName); goto TraceErr; } break; case MESSAGE_TYPE_GET_CERT_INITIAL: if(!ProcessCertInitial(pRAInfo->dwRefreshDays, pCAInfo, pbReqDecrypt, cbReqDecrypt, ppbData, pcbData, pMsgInfo)) { LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_GET_CERT_INITIAL, 1, g_pwszComputerName); goto TraceErr; } break; case MESSAGE_TYPE_GET_CERT: if(!ProcessGetCert(pCAInfo, pbReqDecrypt, cbReqDecrypt, ppbData, pcbData, pMsgInfo)) { LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_GET_CERT, 1, g_pwszComputerName); goto TraceErr; } break; case MESSAGE_TYPE_GET_CRL: if(!ProcessGetCRL(pCAInfo, pbReqDecrypt, cbReqDecrypt, ppbData, pcbData, pMsgInfo)) { LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_GET_CRL, 1, g_pwszComputerName); goto TraceErr; } break; default: LogSCEPEvent(0, FALSE, S_OK, EVENT_MSCEP_BAD_MESSAGE_TYPE, 1, g_pwszComputerName); goto InvalidArgErr; break; } fResult = TRUE; CommonReturn: if(pwszBuffer) free(pwszBuffer); if(pwszMsg) FreeWStr(pwszMsg); //memory from certcli.dll. Has to be freed by LocalFree() if(pbBase64Decoded) LocalFree(pbBase64Decoded); if(pbReqEnv) free(pbReqEnv); if(pbReqDecrypt) free(pbReqDecrypt); return fResult; FailureStatusReturn: //we set the error status for the return message //and consider this http transation a success pMsgInfo->dwStatus=MESSAGE_STATUS_FAILURE; pMsgInfo->dwErrorInfo=MESSAGE_FAILURE_BAD_MESSAGE_CHECK; *ppbData=NULL; *pcbData=0; fResult=TRUE; goto CommonReturn; ErrorReturn: fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); TRACE_ERROR(TraceErr); SET_ERROR(MemoryErr, E_OUTOFMEMORY); } //-------------------------------------------------------------------------- // // RetrieveContextFromSerialNumber // // //-------------------------------------------------------------------------- BOOL WINAPI RetrieveContextFromSerialNumber(CEP_CA_INFO *pCAInfo, CERT_BLOB *pSerialNumber, PCCERT_CONTEXT *ppCertContext) { BOOL fResult = FALSE; DWORD cb=0; long dwDisposition=0; HRESULT hr=E_FAIL; DWORD cbCert=0; BYTE *pbCert=NULL; LPWSTR pwsz=NULL; BSTR bstrCert=NULL; LPWSTR pwszNewConfig=NULL; BSTR bstrNewConfig=NULL; if(S_OK != (hr=MultiByteIntegerToWszBuf( FALSE, pSerialNumber->cbData, pSerialNumber->pbData, &cb, NULL))) goto SetHrErr; pwsz=(LPWSTR)malloc(cb); if(NULL==pwsz) goto MemoryErr; if(S_OK != (hr=MultiByteIntegerToWszBuf( FALSE, pSerialNumber->cbData, pSerialNumber->pbData, &cb, pwsz))) goto SetHrErr; //contatenate the serialNumber with the config string pwszNewConfig=(LPWSTR)malloc(sizeof(WCHAR) * (wcslen(pCAInfo->bstrCAConfig)+wcslen(pwsz)+wcslen(L"\\")+1)); if(NULL==pwszNewConfig) goto MemoryErr; //the config string to retrieve the cert based on the //serialNumber is configString\SerialNumber // wcscpy(pwszNewConfig, pCAInfo->bstrCAConfig); wcscat(pwszNewConfig, L"\\"); wcscat(pwszNewConfig, pwsz); bstrNewConfig=SysAllocString(pwszNewConfig); if(NULL==bstrNewConfig) goto MemoryErr; if(S_OK != (hr=pCAInfo->pICertRequest->RetrievePending(0, bstrNewConfig, &dwDisposition))) goto SetHrErr; if(S_OK != (hr= pCAInfo->pICertRequest->GetCertificate(CR_OUT_BINARY, &bstrCert))) goto SetHrErr; cbCert = (DWORD)SysStringByteLen(bstrCert); pbCert = (BYTE *)bstrCert; if(!(*ppCertContext=CertCreateCertificateContext(ENCODE_TYPE, pbCert, cbCert))) goto TraceErr; fResult = TRUE; CommonReturn: if(pwsz) free(pwsz); if(bstrCert) SysFreeString(bstrCert); if(pwszNewConfig) free(pwszNewConfig); if(bstrNewConfig) SysFreeString(bstrNewConfig); return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; SET_ERROR(MemoryErr, E_OUTOFMEMORY); SET_ERROR_VAR(SetHrErr, hr); TRACE_ERROR(TraceErr); } //-------------------------------------------------------------------------- // // ProcessGetCRL // // //-------------------------------------------------------------------------- BOOL WINAPI ProcessGetCRL(CEP_CA_INFO *pCAInfo, BYTE *pbRequest, DWORD cbRequest, BYTE **ppbData, DWORD *pcbData, CEP_MESSAGE_INFO *pMsgInfo) { BOOL fResult = FALSE; DWORD dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST; DWORD cbUrlArray=0; DWORD dwIndex=0; PCCERT_CONTEXT pCertContext=NULL; PCCRL_CONTEXT pCRLContext=NULL; PCRYPT_URL_ARRAY pUrlArray = NULL; if(!pCAInfo || !ppbData || !pcbData || !pMsgInfo) goto InvalidArgErr; *ppbData=NULL; *pcbData=0; //retrieve the cert context from the serialNumber //protected by the critical Section since it uses ICertRequest interface if(!RetrieveContextFromSerialNumber(pCAInfo, &(pMsgInfo->SerialNumber), &pCertContext)) { LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_TO_GET_CERT_FROM_NUMBER, 1, g_pwszComputerName); goto FailureStatusReturn; } if(!CryptGetObjectUrl( URL_OID_CERTIFICATE_CRL_DIST_POINT, (LPVOID)pCertContext, CRYPT_GET_URL_FROM_EXTENSION, NULL, &cbUrlArray, NULL, NULL, NULL)) goto FailureStatusReturn; pUrlArray=(PCRYPT_URL_ARRAY)malloc(cbUrlArray); if(NULL == pUrlArray) goto FailureStatusReturn; if(!CryptGetObjectUrl( URL_OID_CERTIFICATE_CRL_DIST_POINT, (LPVOID)pCertContext, CRYPT_GET_URL_FROM_EXTENSION, pUrlArray, &cbUrlArray, NULL, NULL, NULL)) goto FailureStatusReturn; for(dwIndex=0; dwIndex < pUrlArray->cUrl; dwIndex++) { if(CryptRetrieveObjectByUrlW ( pUrlArray->rgwszUrl[dwIndex], CONTEXT_OID_CRL, CRYPT_WIRE_ONLY_RETRIEVAL, //we should try to hit the wire 0, (LPVOID *)&pCRLContext, NULL, NULL, NULL, NULL)) break; } if(NULL==pCRLContext) goto FailureStatusReturn; //package the CRL in an empty PKCS7 if(!PackageBlobToPKCS7(CEP_CONTEXT_CRL, pCRLContext->pbCrlEncoded, pCRLContext->cbCrlEncoded, ppbData, pcbData)) goto FailureStatusReturn; //this is the signing cert to which our response should be encrypted if(NULL==(pMsgInfo->pSigningCert=CertDuplicateCertificateContext(pCertContext))) goto FailureStatusReturn; fResult = TRUE; CommonReturn: if(pCertContext) CertFreeCertificateContext(pCertContext); if(pCRLContext) CertFreeCRLContext(pCRLContext); if(pUrlArray) free(pUrlArray); return fResult; FailureStatusReturn: //we set the error status for the return message //and consider this http transation a success pMsgInfo->dwStatus=MESSAGE_STATUS_FAILURE; pMsgInfo->dwErrorInfo=dwErrorInfo; if(ppbData) { if(*ppbData) free(*ppbData); *ppbData=NULL; } if(pcbData) *pcbData=0; fResult=TRUE; goto CommonReturn; ErrorReturn: fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); } //-------------------------------------------------------------------------- // // ProcessGetCert // // //-------------------------------------------------------------------------- BOOL WINAPI ProcessGetCert(CEP_CA_INFO *pCAInfo, BYTE *pbRequest, DWORD cbRequest, BYTE **ppbData, DWORD *pcbData, CEP_MESSAGE_INFO *pMsgInfo) { BOOL fResult = FALSE; DWORD dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST; CRYPT_INTEGER_BLOB SerialNumber; PCCERT_CONTEXT pCertContext=NULL; if(!pCAInfo || !pbRequest || !ppbData || !pcbData || !pMsgInfo) goto InvalidArgErr; *ppbData=NULL; *pcbData=0; memset(&SerialNumber, 0, sizeof(CRYPT_INTEGER_BLOB)); //get the serialnumber from the request if(!GetSerialNumberFromBlob(pbRequest, cbRequest, &SerialNumber)) { LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_NUMBER_FROM_MESSAGE, 1, g_pwszComputerName); goto FailureStatusReturn; } //retrieve the cert context from the serialNumber //protected by the critical Section since it uses ICertRequest interface if(!RetrieveContextFromSerialNumber(pCAInfo, (CERT_BLOB*)&SerialNumber, &pCertContext)) { LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_TO_GET_CERT_FROM_NUMBER, 1, g_pwszComputerName); goto FailureStatusReturn; } //package it in an empty PKCS7 if(!PackageBlobToPKCS7(CEP_CONTEXT_CERT, pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, ppbData, pcbData)) goto FailureStatusReturn; //this is the signing cert to which our response should be encrypted /* if(NULL==(pMsgInfo->pSigningCert=CertDuplicateCertificateContext(pCertContext))) goto FailureStatusReturn; */ fResult = TRUE; CommonReturn: if(SerialNumber.pbData) free(SerialNumber.pbData); if(pCertContext) CertFreeCertificateContext(pCertContext); return fResult; FailureStatusReturn: //we set the error status for the return message //and consider this http transation a success pMsgInfo->dwStatus=MESSAGE_STATUS_FAILURE; pMsgInfo->dwErrorInfo=dwErrorInfo; if(ppbData) { if(*ppbData) free(*ppbData); *ppbData=NULL; } if(pcbData) *pcbData=0; fResult=TRUE; goto CommonReturn; ErrorReturn: fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); } //-------------------------------------------------------------------------- // // ProcessCertInitial // // //-------------------------------------------------------------------------- BOOL ProcessCertInitial( DWORD dwRefreshDays, CEP_CA_INFO *pCAInfo, BYTE *pbRequest, DWORD cbRequest, BYTE **ppbData, DWORD *pcbData, CEP_MESSAGE_INFO *pMsgInfo) { BOOL fResult = FALSE; DWORD dwRequestID=0; DWORD cbCert=0; BYTE *pbCert=NULL; DWORD dwErrorInfo=MESSAGE_FAILURE_BAD_CERT_ID; long dwDisposition=0; HRESULT hr=S_OK; BSTR bstrCert=NULL; if(!pCAInfo || !pbRequest || !ppbData || !pcbData || !pMsgInfo) goto InvalidArgErr; *ppbData=NULL; *pcbData=0; //map the trasactionID to the request ID if(!CEPHashGetRequestID(dwRefreshDays, &(pMsgInfo->TransactionID), &dwRequestID)) { LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_TO_GET_ID, 1, g_pwszComputerName); goto FailureStatusReturn; } if(S_OK != (hr = pCAInfo->pICertRequest->RetrievePending(dwRequestID, pCAInfo->bstrCAConfig, &dwDisposition))) { LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_FAIL_QUERY_CA, 1, g_pwszComputerName); goto FailureStatusReturn; } switch(dwDisposition) { case CR_DISP_ISSUED: if(S_OK != (hr = pCAInfo->pICertRequest->GetCertificate(CR_OUT_BINARY, &bstrCert))) { LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_FAIL_QUERY_CERT, 1, g_pwszComputerName); goto FailureStatusReturn; } cbCert = (DWORD)SysStringByteLen(bstrCert); pbCert = (BYTE *)bstrCert; //package it in an empty PKCS7 if(!PackageBlobToPKCS7(CEP_CONTEXT_CERT, pbCert, cbCert, ppbData, pcbData)) goto FailureStatusReturn; pMsgInfo->dwStatus=MESSAGE_STATUS_SUCCESS; //mark the finished for RequesetID/TransactionID pair CEPHashMarkTransactionFinished(dwRequestID, &(pMsgInfo->TransactionID)); break; case CR_DISP_UNDER_SUBMISSION: pMsgInfo->dwStatus=MESSAGE_STATUS_PENDING; break; case CR_DISP_INCOMPLETE: case CR_DISP_ERROR: case CR_DISP_DENIED: case CR_DISP_ISSUED_OUT_OF_BAND: //we consider it a failure in this case case CR_DISP_REVOKED: default: //mark the finished for RequesetID/TransactionID pair CEPHashMarkTransactionFinished(dwRequestID, &(pMsgInfo->TransactionID)); dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST; goto FailureStatusReturn; break; } fResult = TRUE; CommonReturn: if(bstrCert) SysFreeString(bstrCert); return fResult; FailureStatusReturn: //we set the error status for the return message //and consider this http transation a success pMsgInfo->dwStatus=MESSAGE_STATUS_FAILURE; pMsgInfo->dwErrorInfo=dwErrorInfo; *ppbData=NULL; *pcbData=0; fResult=TRUE; goto CommonReturn; ErrorReturn: fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); } //-------------------------------------------------------------------------- // // PackageBlobToPKCS7 // // Precondition: ppbData and pcbData is guaranteed not to be NULL //-------------------------------------------------------------------------- BOOL PackageBlobToPKCS7(DWORD dwCEP_Context, BYTE *pbEncoded, DWORD cbEncoded, BYTE **ppbData, DWORD *pcbData) { BOOL fResult=FALSE; CERT_BLOB CertBlob; HCERTSTORE hCertStore=NULL; if((!pbEncoded) || (0==cbEncoded)) goto InvalidArgErr; *ppbData=NULL; *pcbData=0; if(NULL == (hCertStore = CertOpenStore( CERT_STORE_PROV_MEMORY, ENCODE_TYPE, NULL, 0, NULL))) goto TraceErr; switch(dwCEP_Context) { case CEP_CONTEXT_CERT: if(!CertAddEncodedCertificateToStore(hCertStore, ENCODE_TYPE, pbEncoded, cbEncoded, CERT_STORE_ADD_ALWAYS, NULL)) goto TraceErr; break; case CEP_CONTEXT_CRL: if(!CertAddEncodedCRLToStore(hCertStore, ENCODE_TYPE, pbEncoded, cbEncoded, CERT_STORE_ADD_ALWAYS, NULL)) goto TraceErr; break; default: goto InvalidArgErr; break; } CertBlob.cbData=0; CertBlob.pbData=NULL; if(!CertSaveStore(hCertStore, ENCODE_TYPE, CERT_STORE_SAVE_AS_PKCS7, CERT_STORE_SAVE_TO_MEMORY, &CertBlob, 0)) goto TraceErr; CertBlob.pbData = (BYTE *)malloc(CertBlob.cbData); if(NULL == CertBlob.pbData) goto MemoryErr; if(!CertSaveStore(hCertStore, ENCODE_TYPE, CERT_STORE_SAVE_AS_PKCS7, CERT_STORE_SAVE_TO_MEMORY, &CertBlob, 0)) goto TraceErr; //copy the memory *ppbData=CertBlob.pbData; *pcbData=CertBlob.cbData; CertBlob.pbData=NULL; fResult = TRUE; CommonReturn: if(CertBlob.pbData) free(CertBlob.pbData); if(hCertStore) CertCloseStore(hCertStore, 0); return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); TRACE_ERROR(TraceErr); SET_ERROR(MemoryErr, E_OUTOFMEMORY); } //-------------------------------------------------------------------------- // // CEPRetrievePasswordFromRequest // //-------------------------------------------------------------------------- BOOL WINAPI CEPRetrievePasswordFromRequest(BYTE *pbRequest, DWORD cbRequest, LPWSTR *ppwszPassword, DWORD *pdwUsage) { BOOL fResult=FALSE; DWORD cbData=0; DWORD dwIndex=0; DWORD cbNameValue=0; DWORD dwExt=0; DWORD cbExtensions=0; DWORD cbSize=0; CERT_REQUEST_INFO *pCertRequestInfo=NULL; CERT_NAME_VALUE *pbNameValue=NULL; CERT_EXTENSIONS *pExtensions=NULL; CRYPT_BIT_BLOB *pKeyUsage=NULL; *ppwszPassword=NULL; *pdwUsage=0; if(!CEPAllocAndDecode(X509_CERT_REQUEST_TO_BE_SIGNED, pbRequest, cbRequest, (void **)&pCertRequestInfo, &cbData)) goto TraceErr; //get the key usage for(dwIndex=0; dwIndex < pCertRequestInfo->cAttribute; dwIndex++) { if((0 == strcmp(szOID_RSA_certExtensions, pCertRequestInfo->rgAttribute[dwIndex].pszObjId)) || (0 == strcmp(szOID_CERT_EXTENSIONS, pCertRequestInfo->rgAttribute[dwIndex].pszObjId)) ) { if(CEPAllocAndDecode(X509_EXTENSIONS, pCertRequestInfo->rgAttribute[dwIndex].rgValue[0].pbData, pCertRequestInfo->rgAttribute[dwIndex].rgValue[0].cbData, (void **)&pExtensions, &cbExtensions)) { for(dwExt=0; dwExt < pExtensions->cExtension; dwExt++) { if(0==strcmp(szOID_KEY_USAGE, pExtensions->rgExtension[dwExt].pszObjId)) { if(CEPAllocAndDecode(X509_KEY_USAGE, pExtensions->rgExtension[dwExt].Value.pbData, pExtensions->rgExtension[dwExt].Value.cbData, (void **)&pKeyUsage, &cbSize)) { if(pKeyUsage->pbData) { if(CERT_DIGITAL_SIGNATURE_KEY_USAGE & (pKeyUsage->pbData[0])) (*pdwUsage) = (*pdwUsage) | CEP_REQUEST_SIGNATURE; if(CERT_KEY_ENCIPHERMENT_KEY_USAGE & (pKeyUsage->pbData[0])) (*pdwUsage) = (*pdwUsage) | CEP_REQUEST_EXCHANGE; } } if(pKeyUsage) free(pKeyUsage); pKeyUsage=NULL; cbSize=0; } } } if(pExtensions) free(pExtensions); pExtensions=NULL; cbExtensions=0; } } //get the password for(dwIndex=0; dwIndex < pCertRequestInfo->cAttribute; dwIndex++) { if(0 == strcmp(szOID_RSA_challengePwd, pCertRequestInfo->rgAttribute[dwIndex].pszObjId)) break; } //the password is not required to be present in this function if(dwIndex != pCertRequestInfo->cAttribute) { if(!CEPAllocAndDecode(X509_UNICODE_ANY_STRING, pCertRequestInfo->rgAttribute[dwIndex].rgValue[0].pbData, pCertRequestInfo->rgAttribute[dwIndex].rgValue[0].cbData, (void **)&pbNameValue, &cbNameValue)) goto TraceErr; if(CERT_RDN_PRINTABLE_STRING != (pbNameValue->dwValueType)) goto InvalidArgErr; cbData=wcslen((LPWSTR)(pbNameValue->Value.pbData)); *ppwszPassword=(LPWSTR)malloc(sizeof(WCHAR) * (cbData + 1)); if(NULL==(*ppwszPassword)) goto MemoryErr; wcscpy(*ppwszPassword,(LPWSTR)(pbNameValue->Value.pbData)); } fResult=TRUE; CommonReturn: if(pExtensions) free(pExtensions); if(pKeyUsage) free(pKeyUsage); if(pbNameValue) free(pbNameValue); if(pCertRequestInfo) free(pCertRequestInfo); return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; TRACE_ERROR(TraceErr); SET_ERROR(InvalidArgErr, E_INVALIDARG); SET_ERROR(MemoryErr, E_OUTOFMEMORY); } //-------------------------------------------------------------------------- // // AltNameExist // // Return TRUE is szOID_SUBJECT_ALT_NAME2 is present in the PKCS10 // FALSE otherwise //-------------------------------------------------------------------------- BOOL WINAPI AltNameExist(BYTE *pbRequest, DWORD cbRequest) { BOOL fResult = FALSE; DWORD cbData=0; DWORD cbExtensions=0; DWORD dwIndex=0; DWORD dwExt=0; CERT_REQUEST_INFO *pCertRequestInfo=NULL; CERT_EXTENSIONS *pExtensions=NULL; if(!CEPAllocAndDecode(X509_CERT_REQUEST_TO_BE_SIGNED, pbRequest, cbRequest, (void **)&pCertRequestInfo, &cbData)) goto ErrorReturn; for(dwIndex=0; dwIndex < pCertRequestInfo->cAttribute; dwIndex++) { if((0 == strcmp(szOID_RSA_certExtensions, pCertRequestInfo->rgAttribute[dwIndex].pszObjId)) || (0 == strcmp(szOID_CERT_EXTENSIONS, pCertRequestInfo->rgAttribute[dwIndex].pszObjId)) ) { if(CEPAllocAndDecode(X509_EXTENSIONS, pCertRequestInfo->rgAttribute[dwIndex].rgValue[0].pbData, pCertRequestInfo->rgAttribute[dwIndex].rgValue[0].cbData, (void **)&pExtensions, &cbExtensions)) { for(dwExt=0; dwExt < pExtensions->cExtension; dwExt++) { if(0==strcmp(szOID_SUBJECT_ALT_NAME2, pExtensions->rgExtension[dwExt].pszObjId)) { fResult=TRUE; goto CommonReturn; } } } if(pExtensions) free(pExtensions); pExtensions=NULL; cbExtensions=0; } } CommonReturn: if(pExtensions) free(pExtensions); if(pCertRequestInfo) free(pCertRequestInfo); return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; } //-------------------------------------------------------------------------- // // CEPAllocAndEncode // //-------------------------------------------------------------------------- BOOL WINAPI CEPAllocAndEncode(LPCSTR lpszStructType, void *pStructInfo, BYTE **ppbEncoded, DWORD *pcbEncoded) { BOOL fResult=FALSE; *pcbEncoded=0; if(!CryptEncodeObject(ENCODE_TYPE, lpszStructType, pStructInfo, NULL, pcbEncoded)) goto TraceErr; *ppbEncoded=(BYTE *)malloc(*pcbEncoded); if(NULL==(*ppbEncoded)) goto MemoryErr; if(!CryptEncodeObject(ENCODE_TYPE, lpszStructType, pStructInfo, *ppbEncoded, pcbEncoded)) goto TraceErr; fResult = TRUE; CommonReturn: return fResult; ErrorReturn: if(*ppbEncoded) { free(*ppbEncoded); *ppbEncoded=NULL; } *pcbEncoded=0; fResult=FALSE; goto CommonReturn; TRACE_ERROR(TraceErr); SET_ERROR(MemoryErr, E_OUTOFMEMORY); } //-------------------------------------------------------------------------- // // ConvertIPStringToBinary // // Conver the IP address in the format of "xxx.xx.xx.xx" to an arry of // bytes. One byte per xxx //-------------------------------------------------------------------------- BOOL ConvertIPStringToBinary(LPWSTR pwszIP, CRYPT_DATA_BLOB *pIPAddress) { BOOL fResult = FALSE; LPWSTR pwszTok=NULL; DWORD cTok=0; DWORD dwIndex=0; if(!pwszIP || !pIPAddress) goto InvalidArgErr; pIPAddress->pbData=NULL; pIPAddress->cbData=0; pwszTok=wcstok(pwszIP, L"."); while(NULL != pwszTok) { cTok++; pwszTok=wcstok(NULL, L"."); } pIPAddress->pbData=(BYTE *)malloc(cTok); if(NULL==pIPAddress->pbData) goto MemoryErr; pIPAddress->cbData=cTok; pwszTok=pwszIP; for(dwIndex=0; dwIndex < cTok; dwIndex++) { pIPAddress->pbData[dwIndex]=(BYTE)_wtol(pwszTok); pwszTok=pwszTok+wcslen(pwszTok)+1; } fResult = TRUE; CommonReturn: return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); SET_ERROR(MemoryErr, E_OUTOFMEMORY); } //-------------------------------------------------------------------------- // // GetAltNameElement // // We create the subject alternative extension based on the PKCS10. // unstructedName(DNS name) and unstructedAddress (IP address) are included. // At lease one element should be present. //-------------------------------------------------------------------------- BOOL WINAPI GetAltNameElement(BYTE *pb10, DWORD cb10, LPWSTR *ppwszDNS, CRYPT_DATA_BLOB *pIPAddress) { BOOL fResult = FALSE; DWORD cbRequestInfo=0; DWORD cbNameInfo=0; DWORD dwRDN=0; DWORD dwAttr=0; PCERT_RDN_ATTR pAttr=NULL; DWORD cb=0; CERT_REQUEST_INFO *pRequestInfo=NULL; CERT_NAME_INFO *pNameInfo=NULL; if(!pb10 || !ppwszDNS || !pIPAddress) goto InvalidArgErr; *ppwszDNS=NULL; pIPAddress->cbData=0; pIPAddress->pbData=NULL; if(!CEPAllocAndDecode(X509_CERT_REQUEST_TO_BE_SIGNED, pb10, cb10, (void **)&pRequestInfo, &cbRequestInfo)) goto TraceErr; if(!CEPAllocAndDecode(X509_UNICODE_NAME, pRequestInfo->Subject.pbData, pRequestInfo->Subject.cbData, (void **)&pNameInfo, &cbNameInfo)) goto TraceErr; for(dwRDN=0; dwRDNcRDN; dwRDN++) { for(dwAttr=0; dwAttrrgRDN[dwRDN].cRDNAttr; dwAttr++) { pAttr=&(pNameInfo->rgRDN[dwRDN].rgRDNAttr[dwAttr]); //we are happy if we have found both the IPAddress and the fqdn if((*ppwszDNS) && (pIPAddress->pbData)) break; if((NULL==*ppwszDNS) && (0 == strcmp(szOID_RSA_unstructName,pAttr->pszObjId))) { cb=sizeof(WCHAR) * (1+wcslen((LPWSTR)(pAttr->Value.pbData))); *ppwszDNS=(LPWSTR)malloc(cb); if(NULL == *ppwszDNS) goto MemoryErr; wcscpy(*ppwszDNS, (LPWSTR)(pAttr->Value.pbData)); } else { if((NULL==pIPAddress->pbData) && (0 == strcmp(szOID_RSA_unstructAddr,pAttr->pszObjId))) { if(!ConvertIPStringToBinary((LPWSTR)(pAttr->Value.pbData), pIPAddress)) goto TraceErr; } } } } //we need to have some element if((NULL == *ppwszDNS) && (NULL==pIPAddress->pbData)) goto InvalidArgErr; fResult = TRUE; CommonReturn: if(pNameInfo) free(pNameInfo); if(pRequestInfo) free(pRequestInfo); return fResult; ErrorReturn: if(ppwszDNS) { if(*ppwszDNS) { free(*ppwszDNS); *ppwszDNS=NULL; } } if(pIPAddress) { if(pIPAddress->pbData) { free(pIPAddress->pbData); pIPAddress->pbData=NULL; } pIPAddress->cbData=0; } fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); TRACE_ERROR(TraceErr); SET_ERROR(MemoryErr, E_OUTOFMEMORY); } //-------------------------------------------------------------------------- // // CreateAltNameExtenions // //-------------------------------------------------------------------------- BOOL WINAPI CreateAltNameExtenions(LPWSTR pwszDNS, CRYPT_DATA_BLOB *pIPAddress, BYTE **ppbExt, DWORD *pcbExt) { BOOL fResult = FALSE; CERT_ALT_NAME_INFO AltNameInfo; CERT_ALT_NAME_ENTRY rgAltNameEntry[2]; DWORD cAltNameEntry=0; //DNS name if(pwszDNS) { rgAltNameEntry[cAltNameEntry].dwAltNameChoice=CERT_ALT_NAME_DNS_NAME; rgAltNameEntry[cAltNameEntry].pwszDNSName=pwszDNS; cAltNameEntry++; } //IP address if(pIPAddress->pbData) { rgAltNameEntry[cAltNameEntry].dwAltNameChoice=CERT_ALT_NAME_IP_ADDRESS; rgAltNameEntry[cAltNameEntry].IPAddress.cbData=pIPAddress->cbData; rgAltNameEntry[cAltNameEntry].IPAddress.pbData=pIPAddress->pbData; cAltNameEntry++; } memset(&AltNameInfo, 0, sizeof(CERT_ALT_NAME_INFO)); AltNameInfo.cAltEntry=cAltNameEntry; AltNameInfo.rgAltEntry=rgAltNameEntry; if(!CEPAllocAndEncode(szOID_SUBJECT_ALT_NAME2, &AltNameInfo, ppbExt, pcbExt)) goto TraceErr; fResult = TRUE; CommonReturn: return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; TRACE_ERROR(TraceErr); } //-------------------------------------------------------------------------- // // AddAltNameInRequest // //-------------------------------------------------------------------------- BOOL WINAPI AddAltNameInRequest(PCCERT_CONTEXT pRACert, BYTE *pb10, DWORD cb10, LPWSTR pwszDNS, CRYPT_DATA_BLOB *pIPAddress, BYTE **ppb7, DWORD *pcb7) { BOOL fResult = FALSE; DWORD cbExt=0; CERT_EXTENSIONS Exts; CERT_EXTENSION Ext; DWORD cbAllExt=0; CRYPT_SIGN_MESSAGE_PARA signPara; CRYPT_ATTRIBUTE AuthAttr; PCCRYPT_OID_INFO pOIDInfo=NULL; ALG_ID AlgValue=CALG_SHA1; CRYPT_ATTR_BLOB AttrBlob; BYTE *pbExt=NULL; BYTE *pbAllExt=NULL; if(!pRACert || !pb10 || !ppb7 || !pcb7) goto InvalidArgErr; *ppb7=NULL; *pcb7=0; if(!CreateAltNameExtenions(pwszDNS, pIPAddress, &pbExt, &cbExt)) goto TraceErr; Exts.cExtension=1; Exts.rgExtension=&Ext; Ext.pszObjId=szOID_SUBJECT_ALT_NAME2; Ext.fCritical=TRUE; Ext.Value.pbData=pbExt; Ext.Value.cbData=cbExt; if(!CEPAllocAndEncode(X509_EXTENSIONS, &Exts, &pbAllExt, &cbAllExt)) goto TraceErr; AuthAttr.pszObjId=szOID_CERT_EXTENSIONS; AuthAttr.cValue=1; AuthAttr.rgValue=&AttrBlob; AttrBlob.pbData=pbAllExt; AttrBlob.cbData=cbAllExt; memset(&signPara, 0, sizeof(signPara)); signPara.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA); signPara.dwMsgEncodingType = ENCODE_TYPE; signPara.pSigningCert = pRACert; signPara.cMsgCert = 1; signPara.rgpMsgCert = &pRACert; signPara.cAuthAttr = 1; signPara.rgAuthAttr = &AuthAttr; if(pOIDInfo=CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY, &AlgValue, CRYPT_HASH_ALG_OID_GROUP_ID)) signPara.HashAlgorithm.pszObjId=(LPSTR)(pOIDInfo->pszOID); else signPara.HashAlgorithm.pszObjId=szOID_OIWSEC_sha1; if(!CryptSignMessage( &signPara, FALSE, 1, (const BYTE **) &pb10, &cb10, NULL, pcb7)) goto TraceErr; *ppb7=(BYTE *)malloc(*pcb7); if(NULL==(*ppb7)) goto MemoryErr; if(!CryptSignMessage( &signPara, FALSE, 1, (const BYTE **) &pb10, &cb10, *ppb7, pcb7)) goto TraceErr; fResult = TRUE; CommonReturn: if(pbAllExt) free(pbAllExt); if(pbExt) free(pbExt); return fResult; ErrorReturn: if(ppb7) { if(*ppb7) { free(*ppb7); *ppb7=NULL; } } if(pcb7) *pcb7=0; fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); SET_ERROR(MemoryErr, E_OUTOFMEMORY); TRACE_ERROR(TraceErr); } //-------------------------------------------------------------------------- // // MakePKCS7Request // //-------------------------------------------------------------------------- BOOL WINAPI MakePKCS7Request(PCCERT_CONTEXT pRACert, BYTE *pb10, DWORD cb10, BYTE **ppb7, DWORD *pcb7) { BOOL fResult = FALSE; CRYPT_SIGN_MESSAGE_PARA signPara; PCCRYPT_OID_INFO pOIDInfo=NULL; ALG_ID AlgValue=CALG_SHA1; if(!pRACert || !pb10 || !ppb7 || !pcb7) goto InvalidArgErr; *ppb7=NULL; *pcb7=0; memset(&signPara, 0, sizeof(signPara)); signPara.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA); signPara.dwMsgEncodingType = ENCODE_TYPE; signPara.pSigningCert = pRACert; signPara.cMsgCert = 1; signPara.rgpMsgCert = &pRACert; signPara.cAuthAttr = 0; signPara.rgAuthAttr = NULL; if(pOIDInfo=CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY, &AlgValue, CRYPT_HASH_ALG_OID_GROUP_ID)) signPara.HashAlgorithm.pszObjId=(LPSTR)(pOIDInfo->pszOID); else signPara.HashAlgorithm.pszObjId=szOID_OIWSEC_sha1; if(!CryptSignMessage( &signPara, FALSE, 1, (const BYTE **) &pb10, &cb10, NULL, pcb7)) goto TraceErr; *ppb7=(BYTE *)malloc(*pcb7); if(NULL==(*ppb7)) goto MemoryErr; if(!CryptSignMessage( &signPara, FALSE, 1, (const BYTE **) &pb10, &cb10, *ppb7, pcb7)) goto TraceErr; fResult = TRUE; CommonReturn: return fResult; ErrorReturn: if(ppb7) { if(*ppb7) { free(*ppb7); *ppb7=NULL; } } if(pcb7) *pcb7=0; fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); SET_ERROR(MemoryErr, E_OUTOFMEMORY); TRACE_ERROR(TraceErr); } /*//-------------------------------------------------------------------------- // // GetLogonInfoFromValue // // The pwszString can be of format "name;password" or "domain\name;password" // //-------------------------------------------------------------------------- BOOL GetLogonInfoFromValue(PCCERT_CONTEXT pRAEncrypt, LPWSTR pwszString, LPWSTR *ppwszDomain, LPWSTR *ppwszUser, LPWSTR *ppwszPassword) { BOOL fResult=FALSE; LPWSTR pwsz=NULL; BOOL fDomain=FALSE; BOOL fPassword=FALSE; LPWSTR pwszPlainText=NULL; *ppwszDomain=NULL; *ppwszUser=NULL; *ppwszPassword=NULL; if(NULL==pwszString) goto InvalidArgErr; if(0 == wcslen(pwszString)) goto InvalidArgErr; for(pwsz=pwszString; *pwsz!=L'\0'; pwsz++) { if(*pwsz==L'\\') { if(fDomain) goto InvalidArgErr; fDomain=TRUE; *pwsz='\0'; } else { if(*pwsz==L';') { if(fPassword) goto InvalidArgErr; fPassword=TRUE; *pwsz='\0'; } } } //have to have userName and password. //One and only one ";" should be found if(!fPassword) goto InvalidArgErr; //one or no "\" should be found if(fDomain) { *ppwszDomain=pwszString; *ppwszUser=*ppwszDomain + wcslen(*ppwszDomain) + 1; } else { *ppwszDomain=NULL; *ppwszUser=pwszString; } *ppwszPassword = *ppwszUser + wcslen(*ppwszUser) + 1; if(fDomain) { if(L'\0'==(**ppwszDomain)) goto InvalidArgErr; } if((L'\0'==(**ppwszUser)) || (L'\0'==(**ppwszPassword))) goto InvalidArgErr; //convert the encrypted password to the plain text form if(!CEPDecryptPassword(pRAEncrypt, *ppwszPassword, &pwszPlainText)) goto TraceErr; *ppwszPassword=pwszPlainText; fResult = TRUE; CommonReturn: return fResult; ErrorReturn: *ppwszDomain=NULL; *ppwszUser=NULL; *ppwszPassword=NULL; fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); TRACE_ERROR(TraceErr); } */ /*//-------------------------------------------------------------------------- // // CEPGetTokenFromPKCS10 // // If fPassword is TRUE, an impersonation has to occur. //-------------------------------------------------------------------------- BOOL CEPGetTokenFromPKCS10(BOOL fPassword, PCCERT_CONTEXT pRAEncrypt, BYTE *pbRequest, DWORD cbRequest, HANDLE *phToken) { BOOL fResult=FALSE; DWORD cbRequestInfo=0; DWORD dwIndex=0; CRYPT_ATTRIBUTE *pAttr=NULL; DWORD cbData=0; LPWSTR pwszDomain=NULL; LPWSTR pwszUserName=NULL; LPWSTR pwszPassword=NULL; CERT_REQUEST_INFO *pRequestInfo=NULL; CERT_NAME_VALUE *pCertNameValue=NULL; *phToken=NULL; if((!pbRequest) || (0==cbRequest)) goto InvalidArgErr; if(!CEPAllocAndDecode(X509_CERT_REQUEST_TO_BE_SIGNED, pbRequest, cbRequest, (void **)&pRequestInfo, &cbRequestInfo)) goto TraceErr; for(dwIndex=0; dwIndex < pRequestInfo->cAttribute; dwIndex++) { if(0 == strcmp(szOID_RSA_challengePwd, (pRequestInfo->rgAttribute[dwIndex]).pszObjId)) { pAttr= &(pRequestInfo->rgAttribute[dwIndex]); break; } } if(NULL==pAttr) { if(fPassword) goto InvalidArgErr; else { *phToken=NULL; fResult=TRUE; goto CommonReturn; } } if(CEPAllocAndDecode(X509_UNICODE_ANY_STRING, pAttr->rgValue[0].pbData, pAttr->rgValue[0].cbData, (void **)&pCertNameValue, &cbData)) { if(GetLogonInfoFromValue(pRAEncrypt, (LPWSTR)(pCertNameValue->Value.pbData), &pwszDomain, &pwszUserName, &pwszPassword)) { if(!LogonUserW(pwszUserName, pwszDomain, pwszPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, phToken)) *phToken=NULL; } } if(NULL == *phToken) { if(fPassword) goto InvalidArgErr; } fResult = TRUE; CommonReturn: if(pRequestInfo) free(pRequestInfo); if(pCertNameValue) free(pCertNameValue); return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); TRACE_ERROR(TraceErr); } */ //-------------------------------------------------------------------------- // // CEPCopyRequestAndRequestID // //-------------------------------------------------------------------------- BOOL WINAPI CEPCopyRequestAndRequestID(BYTE *pbRequest, DWORD cbRequest, DWORD dwRequestID) { BOOL fResult=FALSE; BYTE pbHash[CEP_MD5_HASH_SIZE]; DWORD cbData=0; cbData=CEP_MD5_HASH_SIZE; if(!CryptHashCertificate( NULL, CALG_MD5, 0, pbRequest, cbRequest, pbHash, &cbData)) goto TraceErr; if(!CEPRequestAddHashAndRequestID(pbHash, dwRequestID)) goto TraceErr; fResult = TRUE; CommonReturn: return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; TRACE_ERROR(TraceErr); } //-------------------------------------------------------------------------- // // CEPGetCertFromPKCS10 // //-------------------------------------------------------------------------- BOOL WINAPI CEPGetCertFromPKCS10(CEP_CA_INFO *pCAInfo, BYTE *pbRequest, DWORD cbRequest, BYTE **ppbData, DWORD *pcbData, CEP_MESSAGE_INFO *pMsgInfo) { BOOL fResult = FALSE; DWORD dwRequestID=0; DWORD cbCert=0; BYTE *pbCert=NULL; DWORD dwErrorInfo=MESSAGE_FAILURE_BAD_CERT_ID; long dwDisposition=0; BYTE pbHash[CEP_MD5_HASH_SIZE]; DWORD cbData=0; BSTR bstrCert=NULL; if(!pCAInfo || !pbRequest || !ppbData || !pcbData || !pMsgInfo) goto InvalidArgErr; *ppbData=NULL; *pcbData=0; cbData=CEP_MD5_HASH_SIZE; if(!CryptHashCertificate( NULL, CALG_MD5, 0, pbRequest, cbRequest, pbHash, &cbData)) goto TraceErr; if(!CEPRequestRetrieveRequestIDFromHash(pbHash, &dwRequestID)) goto InvalidArgErr; if(S_OK != pCAInfo->pICertRequest->RetrievePending(dwRequestID, pCAInfo->bstrCAConfig, &dwDisposition)) goto InvalidArgErr; switch(dwDisposition) { case CR_DISP_ISSUED: if(S_OK != pCAInfo->pICertRequest->GetCertificate(CR_OUT_BINARY, &bstrCert)) goto FailureStatusReturn; cbCert = (DWORD)SysStringByteLen(bstrCert); pbCert = (BYTE *)bstrCert; //package it in an empty PKCS7 if(!PackageBlobToPKCS7(CEP_CONTEXT_CERT, pbCert, cbCert, ppbData, pcbData)) goto FailureStatusReturn; pMsgInfo->dwStatus=MESSAGE_STATUS_SUCCESS; break; case CR_DISP_UNDER_SUBMISSION: pMsgInfo->dwStatus=MESSAGE_STATUS_PENDING; break; case CR_DISP_INCOMPLETE: case CR_DISP_ERROR: case CR_DISP_DENIED: case CR_DISP_ISSUED_OUT_OF_BAND: //we consider it a failure in this case case CR_DISP_REVOKED: default: dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST; goto FailureStatusReturn; break; } fResult = TRUE; CommonReturn: if(bstrCert) SysFreeString(bstrCert); return fResult; FailureStatusReturn: //we set the error status for the return message //and consider this http transation a success pMsgInfo->dwStatus=MESSAGE_STATUS_FAILURE; pMsgInfo->dwErrorInfo=dwErrorInfo; *ppbData=NULL; *pcbData=0; fResult=TRUE; goto CommonReturn; ErrorReturn: fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); TRACE_ERROR(TraceErr); } //-------------------------------------------------------------------------- // // ProcessCertRequest // //-------------------------------------------------------------------------- BOOL ProcessCertRequest( DWORD dwRefreshDays, BOOL fPassword, PCCERT_CONTEXT pRAEncrypt, PCCERT_CONTEXT pRACert, CEP_CA_INFO *pCAInfo, BYTE *pbRequest, DWORD cbRequest, BYTE **ppbData, DWORD *pcbData, CEP_MESSAGE_INFO *pMsgInfo) { BOOL fResult = FALSE; HRESULT hr=E_FAIL; DWORD dwFlags=0; long dwDisposition=0; DWORD dwErrorInfo=MESSAGE_FAILURE_BAD_MESSAGE_CHECK; DWORD cbNewRequest=0; DWORD cbCert=0; BYTE *pbCert=NULL; DWORD dwRequestID=0; DWORD dwUsage=0; LPWSTR pwszTemplate=L"IPSECIntermediateOffline"; LPWSTR pwszAttr=NULL; BSTR bstrRequest=NULL; BYTE *pbNewRequest=NULL; BSTR bstrCert=NULL; BSTR bstrAttr=NULL; LPWSTR pwszDNS=NULL; CRYPT_DATA_BLOB IPAddress={0, NULL}; LPWSTR pwszPassword=NULL; if(!pCAInfo || !pbRequest || !ppbData || !pcbData || !pMsgInfo) goto InvalidArgErr; *ppbData=NULL; *pcbData=0; //check to see if the PKCS10 is in our cached request table //if so, we return messages based on the cached requestID if(CEPGetCertFromPKCS10(pCAInfo, pbRequest, cbRequest, ppbData, pcbData, pMsgInfo)) { fResult=TRUE; } else { //retrieve password and key usage from the request. The presence of password //or key usage is not required if(!CEPRetrievePasswordFromRequest(pbRequest, cbRequest, &pwszPassword, &dwUsage)) { LogSCEPEvent(0, FALSE, S_OK, EVENT_MSCEP_NO_KEY_USAGE, 1, g_pwszComputerName); dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST; goto FailureStatusReturn; } if(0 == dwUsage) { LogSCEPEvent(0, FALSE, S_OK, EVENT_MSCEP_NO_KEY_USAGE, 1, g_pwszComputerName); dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST; goto FailureStatusReturn; } //if the password is required, we need to make sure the password //supplied is valid. if(fPassword) { if(NULL == pwszPassword) { LogSCEPEvent(0, FALSE, S_OK, EVENT_MSCEP_NO_PASSWORD, 1, g_pwszComputerName); dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST; goto FailureStatusReturn; } if(!CEPVerifyPasswordAndDeleteFromTable(pwszPassword, dwUsage)) { LogSCEPEvent(0, FALSE, S_OK, EVENT_MSCEP_INVALID_PASSWORD, 1, g_pwszComputerName); dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST; goto FailureStatusReturn; } } //if the altname extention is not in the PKCS10, we need to add it //otherwise, just use the PKCS10 dwFlags = CR_IN_PKCS10; pbNewRequest=pbRequest; cbNewRequest=cbRequest; if(!AltNameExist(pbRequest, cbRequest)) { if(GetAltNameElement(pbRequest, cbRequest, &pwszDNS, &IPAddress)) { if(!AddAltNameInRequest(pRACert, pbRequest, cbRequest, pwszDNS, &IPAddress, &pbNewRequest, &cbNewRequest)) { LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_ADD_ALT, 1, g_pwszComputerName); goto TraceErr; } dwFlags = CR_IN_PKCS7; } } //we always want to make a PKCS7 request so that we can work with enterprise CA if(CR_IN_PKCS10 == dwFlags) { if(!MakePKCS7Request(pRACert, pbRequest, cbRequest, &pbNewRequest, &cbNewRequest)) goto TraceErr; dwFlags = CR_IN_PKCS7; } if(!(bstrRequest=SysAllocStringByteLen((LPCSTR)pbNewRequest, cbNewRequest))) goto MemoryErr; //we are requesting a IPSEC offline cert template for Standalone CA //or general purpose enterprise CA if((FALSE == pCAInfo->fEnterpriseCA) || ((dwUsage & CEP_REQUEST_SIGNATURE) && (dwUsage & CEP_REQUEST_EXCHANGE)) ) { if(!(bstrAttr=SysAllocString(L"CertificateTemplate:IPSECIntermediateOffline\r\n"))) goto MemoryErr; } else { if(dwUsage & CEP_REQUEST_SIGNATURE) { if(pCAInfo->pwszTemplateSig) pwszTemplate=pCAInfo->pwszTemplateSig; } else { //the encryption usage must be set if( 0 == (dwUsage & CEP_REQUEST_EXCHANGE)) { LogSCEPEvent(0, FALSE, S_OK, EVENT_MSCEP_NO_KEY_USAGE, 1, g_pwszComputerName); dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST; goto FailureStatusReturn; } if(pCAInfo->pwszTemplateEnt) pwszTemplate=pCAInfo->pwszTemplateEnt; } pwszAttr=(LPWSTR)malloc((wcslen(CEP_TEMPLATE_ATTR) + wcslen(pwszTemplate) + 5) * sizeof(WCHAR)); if(NULL == pwszAttr) goto MemoryErr; wcscpy(pwszAttr, CEP_TEMPLATE_ATTR); wcscat(pwszAttr, pwszTemplate); wcscat(pwszAttr, L"\r\n"); if(!(bstrAttr=SysAllocString(pwszAttr))) goto MemoryErr; } if(S_OK != (hr=pCAInfo->pICertRequest->Submit( CR_IN_BINARY | dwFlags, bstrRequest, bstrAttr, pCAInfo->bstrCAConfig, &dwDisposition))) { LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_FAIL_SUBMIT, 1, g_pwszComputerName); goto FailureStatusReturn; } dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST; switch(dwDisposition) { case CR_DISP_ISSUED: if(S_OK != (hr = pCAInfo->pICertRequest->GetCertificate(CR_OUT_BINARY, &bstrCert))) { LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_FAIL_QUERY_CERT, 1, g_pwszComputerName); goto FailureStatusReturn; } cbCert = (DWORD)SysStringByteLen(bstrCert); pbCert = (BYTE *)bstrCert; //package it in an empty PKCS7 if(!PackageBlobToPKCS7(CEP_CONTEXT_CERT, pbCert, cbCert, ppbData, pcbData)) goto FailureStatusReturn; pMsgInfo->dwStatus=MESSAGE_STATUS_SUCCESS; //copy the PKCS10 to the cached request table if(S_OK == (hr=pCAInfo->pICertRequest->GetRequestId((long*)(&dwRequestID)))) { CEPCopyRequestAndRequestID(pbRequest, cbRequest, dwRequestID); } break; case CR_DISP_UNDER_SUBMISSION: //copy the transactionID/requestID pair if(S_OK == (hr=pCAInfo->pICertRequest->GetRequestId((long*)(&dwRequestID)))) { if(!CEPHashAddRequestAndTransaction(dwRefreshDays, dwRequestID, &(pMsgInfo->TransactionID))) { LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_ADD_ID, 1, g_pwszComputerName); goto DatabaseErr; } //also copy the PKCS10 to the cached request table for retrial cases CEPCopyRequestAndRequestID(pbRequest, cbRequest, dwRequestID); } else { LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_GET_REQUEST_ID, 1, g_pwszComputerName); } pMsgInfo->dwStatus=MESSAGE_STATUS_PENDING; break; case CR_DISP_INCOMPLETE: case CR_DISP_ERROR: case CR_DISP_DENIED: case CR_DISP_ISSUED_OUT_OF_BAND: //we consider it a failure in this case case CR_DISP_REVOKED: default: dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST; goto FailureStatusReturn; break; } } fResult = TRUE; CommonReturn: if(pwszAttr) free(pwszAttr); if(pwszPassword) free(pwszPassword); if(bstrCert) SysFreeString(bstrCert); if(bstrRequest) SysFreeString(bstrRequest); if(bstrAttr) SysFreeString(bstrAttr); if(pwszDNS) free(pwszDNS); if(IPAddress.pbData) free(IPAddress.pbData); if(dwFlags == CR_IN_PKCS7) { if(pbNewRequest) free(pbNewRequest); } return fResult; FailureStatusReturn: //we set the error status for the return message //and consider this http transation a success pMsgInfo->dwStatus=MESSAGE_STATUS_FAILURE; pMsgInfo->dwErrorInfo=dwErrorInfo; *ppbData=NULL; *pcbData=0; fResult=TRUE; goto CommonReturn; ErrorReturn: fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); SET_ERROR(MemoryErr, E_OUTOFMEMORY); TRACE_ERROR(TraceErr); TRACE_ERROR(DatabaseErr); } //-------------------------------------------------------------------------- // // DecryptMsg // //-------------------------------------------------------------------------- BOOL WINAPI DecryptMsg(CEP_RA_INFO *pRAInfo, BYTE *pbReqEnv, DWORD cbReqEnv, BYTE **ppbReqDecrypt, DWORD *pcbReqDecrypt) { BOOL fResult = FALSE; CMSG_CTRL_DECRYPT_PARA DecryptPara; BOOL fProvFree=FALSE; HCRYPTMSG hMsg=NULL; if(!pRAInfo || !pbReqEnv || !ppbReqDecrypt || !pcbReqDecrypt) goto InvalidArgErr; *ppbReqDecrypt=NULL; *pcbReqDecrypt=0; if(NULL == (hMsg=CryptMsgOpenToDecode( ENCODE_TYPE, 0, 0, NULL, NULL, NULL))) goto TraceErr; if(!CryptMsgUpdate(hMsg, pbReqEnv, cbReqEnv, TRUE)) goto TraceErr; //decrypt memset(&DecryptPara, 0, sizeof(CMSG_CTRL_DECRYPT_PARA)); DecryptPara.cbSize=sizeof(CMSG_CTRL_DECRYPT_PARA); DecryptPara.dwRecipientIndex=0; DecryptPara.hCryptProv=pRAInfo->hRAProv; DecryptPara.dwKeySpec=pRAInfo->dwKeySpec; if(!CryptMsgControl(hMsg, 0, CMSG_CTRL_DECRYPT, &DecryptPara)) goto TraceErr; //get the content if(!CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, NULL, pcbReqDecrypt)) goto TraceErr; *ppbReqDecrypt=(BYTE *)malloc(*pcbReqDecrypt); if(NULL==(*ppbReqDecrypt)) goto MemoryErr; if(!CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, *ppbReqDecrypt, pcbReqDecrypt)) goto TraceErr; fResult = TRUE; CommonReturn: if(hMsg) CryptMsgClose(hMsg); return fResult; ErrorReturn: if(ppbReqDecrypt) { if(*ppbReqDecrypt) { free(*ppbReqDecrypt); *ppbReqDecrypt=NULL; } } if(pcbReqDecrypt) *pcbReqDecrypt=0; fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); TRACE_ERROR(TraceErr); SET_ERROR(MemoryErr, E_OUTOFMEMORY); } //-------------------------------------------------------------------------- // // GetContentFromPKCS7 // //-------------------------------------------------------------------------- BOOL WINAPI GetContentFromPKCS7(BYTE *pbMessage, DWORD cbMessage, BYTE **ppbContent, DWORD *pcbContent, CEP_MESSAGE_INFO *pMsgInfo) { BOOL fResult = FALSE; DWORD cbAuth=0; DWORD dwIndex=0; CRYPT_ATTRIBUTE *pOneAuth=NULL; DWORD cb=0; DWORD cbCertInfo=0; PCCERT_CONTEXT pCertPre=NULL; HCRYPTMSG hMsg=NULL; CRYPT_ATTRIBUTES *pbAuth=NULL; void *pb=NULL; CERT_INFO *pbCertInfo=NULL; HCERTSTORE hCertStore=NULL; PCCERT_CONTEXT pCertCur=NULL; if(!pMsgInfo || !ppbContent || !pcbContent) goto InvalidArgErr; *ppbContent=NULL; *pcbContent=0; memset(pMsgInfo, 0, sizeof(CEP_MESSAGE_INFO)); if(NULL == (hMsg=CryptMsgOpenToDecode( ENCODE_TYPE, 0, 0, NULL, NULL, NULL))) goto TraceErr; if(!CryptMsgUpdate(hMsg, pbMessage, cbMessage, TRUE)) goto TraceErr; //get the content if(!CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, NULL, pcbContent)) goto TraceErr; *ppbContent=(BYTE *)malloc(*pcbContent); if(NULL==(*ppbContent)) goto MemoryErr; if(!CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, *ppbContent, pcbContent)) goto TraceErr; //get message type if(!CryptMsgGetParam(hMsg, CMSG_SIGNER_AUTH_ATTR_PARAM, 0, NULL, &cbAuth)) goto TraceErr; pbAuth=(CRYPT_ATTRIBUTES *)malloc(cbAuth); if(NULL==pbAuth) goto MemoryErr; if(!CryptMsgGetParam(hMsg, CMSG_SIGNER_AUTH_ATTR_PARAM, 0, pbAuth, &cbAuth)) goto TraceErr; for(dwIndex=0; dwIndex < pbAuth->cAttr; dwIndex++) { pOneAuth=&(pbAuth->rgAttr[dwIndex]); if((!(pOneAuth->pszObjId)) || (!(pOneAuth->rgValue))) continue; if((0==(pOneAuth->rgValue[0].cbData)) || (!(pOneAuth->rgValue[0].pbData))) continue; if(0 == strcmp(pOneAuth->pszObjId, szOIDVerisign_MessageType)) { if(!CEPAllocAndDecode(X509_ANY_STRING, pOneAuth->rgValue[0].pbData, pOneAuth->rgValue[0].cbData, (void **)&pb, &cb)) goto TraceErr; if(CERT_RDN_PRINTABLE_STRING != ((CERT_NAME_VALUE *)pb)->dwValueType) goto InvalidArgErr; pMsgInfo->dwMessageType = atol((LPSTR)(((CERT_NAME_VALUE *)pb)->Value.pbData)); } else { if(0 == strcmp(pOneAuth->pszObjId, szOIDVerisign_SenderNonce)) { if(!CEPAllocAndDecode(X509_OCTET_STRING, pOneAuth->rgValue[0].pbData, pOneAuth->rgValue[0].cbData, (void **)&pb, &cb)) goto TraceErr; //the SenderNonce in the request is the recipienNonce in the response if(!AllocAndCopyBlob(&(pMsgInfo->RecipientNonce), (CERT_BLOB *)pb)) goto TraceErr; } else { if(0 == strcmp(pOneAuth->pszObjId, szOIDVerisign_TransactionID)) { if(!CEPAllocAndDecode(X509_ANY_STRING, pOneAuth->rgValue[0].pbData, pOneAuth->rgValue[0].cbData, (void **)&pb, &cb)) goto TraceErr; if(CERT_RDN_PRINTABLE_STRING != ((CERT_NAME_VALUE *)pb)->dwValueType) goto InvalidArgErr; if(!AllocAndCopyString(&(pMsgInfo->TransactionID), (LPSTR)(((CERT_NAME_VALUE *)pb)->Value.pbData))) goto TraceErr; } } } if(pb) free(pb); pb=NULL; cb=0; } //we have to have TrasanctionID and messageType if((0 == pMsgInfo->dwMessageType)||(NULL == (pMsgInfo->TransactionID.pbData))) goto InvalidArgErr; //we get the serial number of the signing certificate cbCertInfo=0; if(!CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_INFO_PARAM, 0, NULL, &cbCertInfo)) goto TraceErr; pbCertInfo=(CERT_INFO *)malloc(cbCertInfo); if(NULL==pbCertInfo) goto MemoryErr; if(!CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_INFO_PARAM, 0, pbCertInfo, &cbCertInfo)) goto TraceErr; if(!AllocAndCopyBlob(&(pMsgInfo->SerialNumber), (CERT_BLOB *)(&(pbCertInfo->SerialNumber)))) goto TraceErr; //we get the rounter's CA issued certificate for GetCertInitial message if((MESSAGE_TYPE_GET_CERT_INITIAL == pMsgInfo->dwMessageType) || (MESSAGE_TYPE_CERT_REQUEST == pMsgInfo->dwMessageType) || (MESSAGE_TYPE_GET_CERT == pMsgInfo->dwMessageType) ) { if(NULL == (hCertStore=CertOpenStore(CERT_STORE_PROV_MSG, ENCODE_TYPE, NULL, 0, hMsg))) goto TraceErr; pCertPre=NULL; while(pCertCur=CertEnumCertificatesInStore(hCertStore, pCertPre)) { if(SameCert(pCertCur->pCertInfo, pbCertInfo)) { if(NULL==(pMsgInfo->pSigningCert=CertDuplicateCertificateContext(pCertCur))) goto TraceErr; break; } pCertPre=pCertCur; } if(NULL == (pMsgInfo->pSigningCert)) goto InvalidArgErr; } fResult = TRUE; CommonReturn: if(pCertCur) CertFreeCertificateContext(pCertCur); if(hCertStore) CertCloseStore(hCertStore, 0); if(pbCertInfo) free(pbCertInfo); if(pb) free(pb); if(pbAuth) free(pbAuth); if(hMsg) CryptMsgClose(hMsg); return fResult; ErrorReturn: if(ppbContent) { if(*ppbContent) { free(*ppbContent); *ppbContent=NULL; } } if(pcbContent) *pcbContent=0; FreeMessageInfo(pMsgInfo); fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); TRACE_ERROR(TraceErr); SET_ERROR(MemoryErr, E_OUTOFMEMORY); } //-------------------------------------------------------------------------- // // SameCert // //-------------------------------------------------------------------------- BOOL WINAPI SameCert(CERT_INFO *pCertInfoOne, CERT_INFO *pCertInfoTwo) { if(!pCertInfoOne || !pCertInfoTwo) return FALSE; if(!SameBlob(&(pCertInfoOne->SerialNumber), &(pCertInfoTwo->SerialNumber))) return FALSE; if(!SameBlob((CRYPT_INTEGER_BLOB *)(&(pCertInfoOne->Issuer)), (CRYPT_INTEGER_BLOB *)(&(pCertInfoTwo->Issuer)))) return FALSE; return TRUE; } //-------------------------------------------------------------------------- // // SameBlob // //-------------------------------------------------------------------------- BOOL WINAPI SameBlob(CRYPT_INTEGER_BLOB *pBlobOne, CRYPT_INTEGER_BLOB *pBlobTwo) { if(!pBlobOne || !pBlobTwo) return FALSE; if(pBlobOne->cbData != pBlobTwo->cbData) return FALSE; if(0!=(memcmp(pBlobOne->pbData, pBlobTwo->pbData,pBlobTwo->cbData))) return FALSE; return TRUE; } //-------------------------------------------------------------------------- // // CEPAllocAndDecode // //-------------------------------------------------------------------------- BOOL WINAPI CEPAllocAndDecode( LPCSTR lpszStructType, BYTE *pbEncoded, DWORD cbEncoded, void **ppb, DWORD *pcb) { BOOL fResult = FALSE; *pcb=0; *ppb=NULL; if(!CryptDecodeObject(ENCODE_TYPE, lpszStructType, pbEncoded, cbEncoded, 0, NULL, pcb)) goto DecodeErr; *ppb=malloc(*pcb); if(NULL==(*ppb)) goto MemoryErr; if(!CryptDecodeObject(ENCODE_TYPE, lpszStructType, pbEncoded, cbEncoded, 0, *ppb, pcb)) goto DecodeErr; fResult = TRUE; CommonReturn: return fResult; ErrorReturn: if(ppb) { if(*ppb) { free(*ppb); *ppb=NULL; } } if(pcb) *pcb=0; fResult=FALSE; goto CommonReturn; TRACE_ERROR(DecodeErr); SET_ERROR(MemoryErr, E_OUTOFMEMORY); } //-------------------------------------------------------------------------- // // FreeMessageInfo // //-------------------------------------------------------------------------- void WINAPI FreeMessageInfo(CEP_MESSAGE_INFO *pMsgInfo) { if(pMsgInfo) { if(pMsgInfo->TransactionID.pbData) free(pMsgInfo->TransactionID.pbData); if(pMsgInfo->SenderNonce.pbData) free(pMsgInfo->SenderNonce.pbData); if(pMsgInfo->RecipientNonce.pbData) free(pMsgInfo->RecipientNonce.pbData); if(pMsgInfo->SerialNumber.pbData) free(pMsgInfo->SerialNumber.pbData); if(pMsgInfo->pSigningCert) CertFreeCertificateContext(pMsgInfo->pSigningCert); memset(pMsgInfo, 0, sizeof(CEP_MESSAGE_INFO)); } } //-------------------------------------------------------------------------- // // AllocAndCopyBlob // //-------------------------------------------------------------------------- BOOL WINAPI AllocAndCopyBlob(CERT_BLOB *pDestBlob, CERT_BLOB *pSrcBlob) { memset(pDestBlob, 0, sizeof(CERT_BLOB)); if(NULL==pSrcBlob->pbData) { SetLastError(E_INVALIDARG); return FALSE; } pDestBlob->pbData = (BYTE *)malloc(pSrcBlob->cbData); if(NULL==(pDestBlob->pbData)) { SetLastError(E_OUTOFMEMORY); return FALSE; } pDestBlob->cbData=pSrcBlob->cbData; memcpy(pDestBlob->pbData, pSrcBlob->pbData, pDestBlob->cbData); return TRUE; } //-------------------------------------------------------------------------- // // AllocAndCopyString // //-------------------------------------------------------------------------- BOOL WINAPI AllocAndCopyString(CERT_BLOB *pDestBlob, LPSTR psz) { if(!psz) { SetLastError(E_INVALIDARG); return FALSE; } pDestBlob->cbData=0; pDestBlob->pbData=NULL; pDestBlob->pbData=(BYTE*)malloc(strlen(psz) + 1); if(NULL == pDestBlob->pbData) { SetLastError(E_OUTOFMEMORY); return FALSE; } pDestBlob->cbData=strlen(psz); strcpy((LPSTR)pDestBlob->pbData, psz); return TRUE; } //-------------------------------------------------------------------------- // // GetTagValue // //-------------------------------------------------------------------------- LPSTR GetTagValue(LPSTR szString, LPSTR szTag) { LPSTR pszValue=NULL; DWORD cbString=0; DWORD cbTag=0; cbString = strlen(szString); cbTag = strlen(szTag); for(pszValue=szString; cbString > cbTag; pszValue++, cbString--) { if((*pszValue) == (*szTag)) { if(0==_strnicmp(pszValue, szTag, cbTag)) { //skip the tag pszValue += cbTag * sizeof(CHAR); return pszValue; } } } return NULL; }