|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1995 - 1999
//
// File: cmc.cpp
//
// Contents: CMC request creation code shared between xenroll and CA
//
// History: 03-2000 vich created
// 03-2000 xtan moved from ca
// 05-2000 xtan moved from xenroll\xcertlib
//--------------------------------------------------------------------------
#define CMSG_SIGNER_ENCODE_INFO_HAS_CMS_FIELDS
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <assert.h>
#include <wincrypt.h>
#include <dbgdef.h>
#include <unicode.h>
#include "xelib.h"
#include "xenroll.h"
//#define USE_OLD_DUMMY_SIGNER
#ifndef SAVE_DUMMY_SIGNER
# define SAVE_DUMMY_SIGNER FALSE
#endif
#ifdef _XENROLL_SRC_
#define CryptAcquireContextW CryptAcquireContextU
#endif //_XENROLL_SRC_
HRESULT GenerateKeys( IN WCHAR const *pwszContainer, IN DWORD dwProvType, OUT HCRYPTPROV *phProv) { HRESULT hr; HCRYPTKEY hKey = NULL;
*phProv = NULL;
// see if the container already exists
// if (CryptAcquireContext(
if (CryptAcquireContextW( phProv, pwszContainer, NULL, // pwszProvName
dwProvType, 0)) // dwFlags
{ if (NULL != *phProv) { CryptReleaseContext(*phProv, 0); *phProv = NULL; }
// container exists -- remove old keys and generate new ones.
// if (!CryptAcquireContext(
if (!CryptAcquireContextW( phProv, pwszContainer, NULL, // pwszProvName
dwProvType, CRYPT_DELETEKEYSET)) { hr = myHLastError(); _JumpError(hr, error, "CryptAcquireContext"); } }
// create new container
// if (!CryptAcquireContext(
if (!CryptAcquireContextW( phProv, pwszContainer, NULL, // pwszProvName
dwProvType, CRYPT_NEWKEYSET)) // force new container
{ hr = myHLastError(); _JumpError(hr, error, "CryptAcquireContext"); } // create signature keys
if (!CryptGenKey(*phProv, AT_SIGNATURE, 0, &hKey)) { hr = myHLastError(); _JumpError(hr, error, "CryptGenKey"); } hr = S_OK;
error: if (NULL != hKey) { CryptDestroyKey(hKey); } return(hr); }
#define wszDUMMYSIGNER L"Dummy Signer"
#ifdef USE_OLD_DUMMY_SIGNER
HRESULT CreateDummySignerNameInfo( OUT BYTE **ppbEncodedName, OUT DWORD *pcbEncodedName) { HRESULT hr; CERT_RDN_ATTR rgRDNAttr[2]; CERT_RDN rgRDN[2]; CERT_NAME_INFO NameInfo; DWORD i;
CSASSERT(NULL != ppbEncodedName && NULL != pcbEncodedName);
NameInfo.cRDN = ARRAYSIZE(rgRDN); NameInfo.rgRDN = rgRDN;
for (i = 0; i < ARRAYSIZE(rgRDN); i++) { rgRDN[i].cRDNAttr = 1; rgRDN[i].rgRDNAttr = &rgRDNAttr[i];
rgRDNAttr[i].pszObjId = (0 == i)? szOID_RDN_DUMMY_SIGNER : szOID_COMMON_NAME;
rgRDNAttr[i].dwValueType = 0; rgRDNAttr[i].Value.pbData = (BYTE *) wszDUMMYSIGNER; rgRDNAttr[i].Value.cbData = 0; }
// if (!myEncodeName(
if (!myEncodeObject( X509_ASN_ENCODING, X509_UNICODE_NAME, &NameInfo, 0, CERTLIB_USE_LOCALALLOC, ppbEncodedName, pcbEncodedName)) { hr = myHLastError(); // _JumpError(hr, error, "myEncodeName");
_JumpError(hr, error, "myEncodeObject"); } hr = S_OK;
error: return(hr); }
HRESULT EncodeCertAndSign( IN HCRYPTPROV hProv, IN CERT_INFO *pCert, IN char const *pszAlgId, OUT BYTE **ppbSigned, OUT DWORD *pcbSigned) { HRESULT hr; BYTE *pbEncoded = NULL; DWORD cbEncoded; *ppbSigned = NULL; // if (!myEncodeToBeSigned(
if (!myEncodeObject( X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, pCert, 0, CERTLIB_USE_LOCALALLOC, &pbEncoded, &cbEncoded)) { hr = myHLastError(); // _JumpError(hr, error, "myEncodeToBeSigned");
_JumpError(hr, error, "myEncodeObject"); }
hr = myEncodeSignedContent( hProv, X509_ASN_ENCODING, pszAlgId, pbEncoded, cbEncoded, CERTLIB_USE_LOCALALLOC, ppbSigned, pcbSigned); _JumpIfError(hr, error, "myEncodeSignedContent");
error: if (NULL != pbEncoded) { LocalFree(pbEncoded); } return(hr); }
VOID GenerateSerialNumber( UUID *puuidSerialNumber) { HRESULT hr; BYTE *pb;
ZeroMemory(puuidSerialNumber, sizeof(*puuidSerialNumber)); hr = UuidCreate(puuidSerialNumber); if (S_OK != hr) { BYTE *pbEnd; CSASSERT(RPC_S_UUID_LOCAL_ONLY == hr);
// No net card? Fake up a GUID:
pb = (BYTE *) puuidSerialNumber; pbEnd = (BYTE *) pb + sizeof(*puuidSerialNumber);
GetSystemTimeAsFileTime((FILETIME *) pb); pb += sizeof(FILETIME);
while (pb < pbEnd) { *(DWORD *) pb = GetTickCount(); pb += sizeof(DWORD); } CSASSERT(pb == pbEnd); } pb = &((BYTE *) puuidSerialNumber)[sizeof(*puuidSerialNumber) - 1];
// make sure the last byte is never zero
if (0 == *pb) { *pb = 'z'; }
// Some clients can't handle negative serial numbers:
*pb &= 0x7f; }
HRESULT CreateKPI( IN CERT_CONTEXT const *pCert, IN BSTR strKeyContainer) { HRESULT hr; HCERTSTORE hStore = NULL; CRYPT_KEY_PROV_INFO kpi; CERT_CONTEXT const *pCertStore = NULL;
hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_W, X509_ASN_ENCODING, NULL, // hProv
CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, L"My"); if (NULL == hStore) { hr = myHLastError(); _JumpError(hr, error, "CertOpenStore"); }
if (!CertAddCertificateContextToStore( hStore, pCert, CERT_STORE_ADD_REPLACE_EXISTING, &pCertStore)) { hr = myHLastError(); _JumpError(hr, error, "CertAddCertificateContextToStore"); }
ZeroMemory(&kpi, sizeof(kpi)); kpi.pwszContainerName = strKeyContainer; kpi.pwszProvName = MS_DEF_PROV_W; kpi.dwProvType = PROV_RSA_FULL; kpi.dwKeySpec = AT_SIGNATURE;
if (!CertSetCertificateContextProperty( pCertStore, CERT_KEY_PROV_INFO_PROP_ID, 0, &kpi)) { hr = myHLastError(); _JumpError(hr, error, "CertSetCertificateContextProperty"); } hr = S_OK;
error: if (NULL != pCertStore) { CertFreeCertificateContext(pCertStore); } if (NULL != hStore) { CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG); } return(hr); }
VOID DestroyDummyCert( IN HCRYPTPROV hProv, IN BSTR strKeyContainer, IN CERT_CONTEXT const *pCert, IN BOOL fSaveDummySignerCert) { HRESULT hr; if (NULL != hProv) { CryptReleaseContext(hProv, 0); } if (NULL != strKeyContainer) { if (fSaveDummySignerCert && NULL != pCert) { CreateKPI(pCert, strKeyContainer); } else { // if (!CryptAcquireContext(
if (!CryptAcquireContextW( &hProv, strKeyContainer, NULL, // pwszProvName
PROV_RSA_FULL, CRYPT_DELETEKEYSET)) { hr = myHLastError(); _PrintError(hr, "CryptAcquireContext"); } } SysFreeString(strKeyContainer); } if (NULL != pCert) { CertFreeCertificateContext(pCert); } }
HRESULT EncodeDummyCert( OUT HCRYPTPROV *phProv, OUT BSTR *pstrKeyContainer, OUT CERT_CONTEXT const **ppCert) { HRESULT hr; HCRYPTPROV hProv = NULL; CERT_PUBLIC_KEY_INFO *pPubKey = NULL; DWORD cbPubKey; CERT_NAME_BLOB NameBlob; CERT_INFO Cert; char *pszAlgId = szOID_RSA_SHA1RSA; UUID uuidSerialNumber; BSTR strKeyContainer = NULL; BYTE *pbEncoded = NULL; DWORD cbEncoded;
//ZeroMemory(aext, sizeof(aext));
NameBlob.pbData = NULL;
*phProv = NULL; *pstrKeyContainer = NULL; *ppCert = NULL;
// Use a GUID for the serial number and the key container name
GenerateSerialNumber(&uuidSerialNumber);
hr = MultiByteIntegerToBstr( FALSE, sizeof(uuidSerialNumber), (BYTE const *) &uuidSerialNumber, &strKeyContainer); _JumpIfError(hr, error, "MultiByteIntegerToBstr");
hr = GenerateKeys(strKeyContainer, PROV_RSA_FULL, &hProv); _JumpIfError(hr, error, "GenerateKeys");
// SUBJECT & ISSUER:
hr = CreateDummySignerNameInfo(&NameBlob.pbData, &NameBlob.cbData); _JumpIfError(hr, error, "CreateDummySignerNameInfo");
if (!myCryptExportPublicKeyInfo( hProv, AT_SIGNATURE, CERTLIB_USE_LOCALALLOC, &pPubKey, &cbPubKey)) { hr = myHLastError(); _JumpError(hr, error, "myCryptExportPublicKeyInfo"); }
// CERT:
ZeroMemory(&Cert, sizeof(Cert)); Cert.dwVersion = CERT_V1;
Cert.SerialNumber.pbData = (BYTE *) &uuidSerialNumber; Cert.SerialNumber.cbData = sizeof(uuidSerialNumber); Cert.SignatureAlgorithm.pszObjId = pszAlgId; Cert.Issuer = NameBlob; // Structure assignment
GetSystemTimeAsFileTime(&Cert.NotBefore); Cert.NotAfter = Cert.NotBefore; myMakeExprDateTime( &Cert.NotBefore, -CCLOCKSKEWMINUTESDEFAULT, ENUM_PERIOD_MINUTES); myMakeExprDateTime(&Cert.NotAfter, 1, ENUM_PERIOD_MONTHS);
Cert.Subject = NameBlob; // Structure assignment
Cert.SubjectPublicKeyInfo = *pPubKey; // Structure assignment
//Cert.cExtension = 0;
//Cert.rgExtension = NULL;
hr = EncodeCertAndSign( hProv, &Cert, pszAlgId, &pbEncoded, &cbEncoded); _JumpIfError(hr, error, "EncodeCertAndSign");
*ppCert = CertCreateCertificateContext( X509_ASN_ENCODING, pbEncoded, cbEncoded); if (NULL == *ppCert) { hr = myHLastError(); _JumpError(hr, error, "CertCreateCertificateContext"); }
*phProv = hProv; hProv = NULL;
*pstrKeyContainer = strKeyContainer; strKeyContainer = NULL;
error: if (NULL != hProv) { CryptReleaseContext(hProv, 0); } if (NULL != strKeyContainer) { SysFreeString(strKeyContainer); } if (NULL != pbEncoded) { LocalFree(pbEncoded); } if (NULL != NameBlob.pbData) { LocalFree(NameBlob.pbData); } if (NULL != pPubKey) { LocalFree(pPubKey); } return(hr); } #endif // USE_OLD_DUMMY_SIGNER
HRESULT BuildCMCExtensions( IN DWORD cExt, IN CERT_EXTENSION const *rgExt, IN DWORD dwCMCDataReference, IN DWORD dwBodyPartIdOfRequest, IN DWORD dwBodyPartId, OUT CMC_TAGGED_ATTRIBUTE *pTaggedAttribute, OUT CRYPT_ATTR_BLOB *pBlob) { HRESULT hr; CMC_ADD_EXTENSIONS_INFO cmcExt;
ZeroMemory(&cmcExt, sizeof(cmcExt)); cmcExt.dwCmcDataReference = dwCMCDataReference; if (0 != dwBodyPartIdOfRequest) { cmcExt.cCertReference = 1; cmcExt.rgdwCertReference = &dwBodyPartIdOfRequest; } cmcExt.cExtension = cExt; cmcExt.rgExtension = const_cast<CERT_EXTENSION *>(rgExt); pTaggedAttribute->dwBodyPartID = dwBodyPartId; pTaggedAttribute->Attribute.pszObjId = szOID_CMC_ADD_EXTENSIONS; pTaggedAttribute->Attribute.cValue = 1; pTaggedAttribute->Attribute.rgValue = pBlob;
// Encode CMC_ADD_EXTENSIONS_INFO --> Extensions Blob
if (!myEncodeObject( X509_ASN_ENCODING, CMC_ADD_EXTENSIONS, &cmcExt, 0, CERTLIB_USE_LOCALALLOC, &pBlob->pbData, &pBlob->cbData)) { hr = myHLastError(); _JumpError(hr, error, "myEncodeObject"); } hr = S_OK;
error: return(hr); }
HRESULT BuildCMCAttributes( IN DWORD cAttribute, IN CRYPT_ATTRIBUTE const *rgAttribute, IN DWORD dwCMCDataReference, IN DWORD dwBodyPartIdOfRequest, IN DWORD dwBodyPartId, OUT CMC_TAGGED_ATTRIBUTE *pTaggedAttribute, OUT CRYPT_ATTR_BLOB *pBlob) { HRESULT hr; CMC_ADD_ATTRIBUTES_INFO cmcAttrib;
ZeroMemory(&cmcAttrib, sizeof(cmcAttrib)); cmcAttrib.dwCmcDataReference = dwCMCDataReference; if (0 != dwBodyPartIdOfRequest) { cmcAttrib.cCertReference = 1; cmcAttrib.rgdwCertReference = &dwBodyPartIdOfRequest; } cmcAttrib.cAttribute = cAttribute; cmcAttrib.rgAttribute = const_cast<CRYPT_ATTRIBUTE *>(rgAttribute);
//for (DWORD i = 0; i < cAttribute; i++)
//{
//DBGPRINT((DBG_SS_CERTLIBI, "Attr[%d]: %d values\n", i, rgAttribute[i].cValue));
//}
pTaggedAttribute->dwBodyPartID = dwBodyPartId;
// MS proprietary OID: encoded attribute name, value pairs
pTaggedAttribute->Attribute.pszObjId = szOID_CMC_ADD_ATTRIBUTES; pTaggedAttribute->Attribute.cValue = 1; pTaggedAttribute->Attribute.rgValue = pBlob;
// Encode CMC_ADD_ATTRIBUTES_INFO --> Attribute Blob
if (!myEncodeObject( X509_ASN_ENCODING, CMC_ADD_ATTRIBUTES, &cmcAttrib, 0, CERTLIB_USE_LOCALALLOC, &pBlob->pbData, &pBlob->cbData)) { hr = myHLastError(); _JumpError(hr, error, "myEncodeObject"); } hr = S_OK;
error: return(hr); }
HRESULT BuildCMCRegInfo( IN CHAR const *pszNameValuePairs, //IN DWORD dwCMCDataReference,
//IN DWORD dwBodyPartIdOfRequest,
IN DWORD dwBodyPartId, OUT CMC_TAGGED_ATTRIBUTE *pTaggedAttribute, OUT CRYPT_ATTR_BLOB *pBlob) { HRESULT hr; BYTE *pbOctet = NULL; CRYPT_DATA_BLOB Blob; pTaggedAttribute->dwBodyPartID = dwBodyPartId; pTaggedAttribute->Attribute.pszObjId = szOID_CMC_REG_INFO; pTaggedAttribute->Attribute.cValue = 1; pTaggedAttribute->Attribute.rgValue = pBlob;
// Encode CMC_REG_INFO --> Octet string Blob
Blob.pbData = (BYTE *) pszNameValuePairs; Blob.cbData = strlen(pszNameValuePairs);
if (!myEncodeObject( X509_ASN_ENCODING, X509_OCTET_STRING, &Blob, 0, CERTLIB_USE_LOCALALLOC, &pBlob->pbData, &pBlob->cbData)) { hr = myHLastError(); _JumpError(hr, error, "myEncodeObject"); } hr = S_OK;
error: if (NULL != pbOctet) { LocalFree(pbOctet); } return(hr); }
#ifndef WSZARRAYSIZE
#define WSZARRAYSIZE(a) ((sizeof(a)/sizeof((a)[0])) - 1)
#endif
HRESULT CanonicalizeURLParm( IN WCHAR const *pwszParmIn, OUT WCHAR **ppwszParmOut) { HRESULT hr; WCHAR *pwszUncanon = NULL; WCHAR *pwszCanon = NULL; static const WCHAR s_wszLdap[] = L"ldap:///";
*ppwszParmOut = NULL;
pwszUncanon = (WCHAR *) LocalAlloc( LMEM_FIXED, (WSZARRAYSIZE(s_wszLdap) + wcslen(pwszParmIn) + 1) * sizeof(WCHAR)); if (NULL == pwszUncanon) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } wcscpy(pwszUncanon, s_wszLdap); wcscat(pwszUncanon, pwszParmIn);
hr = myInternetCanonicalizeUrl(pwszUncanon, &pwszCanon); _JumpIfError(hr, error, "myInternetCanonicalizeUrl");
hr = myDupString(&pwszCanon[WSZARRAYSIZE(s_wszLdap)], ppwszParmOut); _JumpIfError(hr, error, "myDupString");
error: if (NULL != pwszUncanon) { LocalFree(pwszUncanon); } if (NULL != pwszCanon) { LocalFree(pwszCanon); } return(hr); }
// SeparateNameValuePairs
//
// Separate szOID_ENROLLMENT_NAME_VALUE_PAIR attributes from the rest,
// and construct a URL-style, UTF8-encoded parameter string.
HRESULT SeparateNameValuePairs( IN CRYPT_ATTRIBUTES const *rgAttributes, IN DWORD cAttributes, OUT CRYPT_ATTRIBUTE **prgAttr, OUT DWORD *pcAttr, OUT CHAR **ppszNameValuePairs) { HRESULT hr; DWORD i; DWORD j; DWORD k; DWORD cAttr; DWORD iAttr; CRYPT_ATTRIBUTE *rgAttr = NULL; CRYPT_ATTRIBUTE *pAttr; DWORD cNameValuePair; DWORD iNameValuePair; CRYPT_ENROLLMENT_NAME_VALUE_PAIR *pNameValuePair = NULL; CRYPT_ENROLLMENT_NAME_VALUE_PAIR *rgNameValuePair = NULL; CRYPT_ENROLLMENT_NAME_VALUE_PAIR *pnvp; DWORD cb; WCHAR *pwszNameValuePairs = NULL; CHAR *pszNameValuePairs = NULL; DWORD cwc; *prgAttr = NULL; *ppszNameValuePairs = NULL;
// Count the name/value pairs, as well as the rest of the attributes
cAttr = 0; cNameValuePair = 0; for (i = 0; i < cAttributes; i++) { for (j = 0; j < rgAttributes[i].cAttr; j++) { pAttr = &rgAttributes[i].rgAttr[j]; if (0 == strcmp(szOID_ENROLLMENT_NAME_VALUE_PAIR, pAttr->pszObjId)) { cNameValuePair += pAttr->cValue; } else { cAttr++; } } }
// Allocate an array of name/value pair pointers, and an array for the rest
// of the attributes.
if (0 != cAttr) { rgAttr = (CRYPT_ATTRIBUTE *) LocalAlloc( LMEM_FIXED, cAttr * sizeof(rgAttr[0])); if (NULL == rgAttr) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } } if (0 != cNameValuePair) { rgNameValuePair = (CRYPT_ENROLLMENT_NAME_VALUE_PAIR *) LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, cNameValuePair * sizeof(rgNameValuePair[0])); if (NULL == rgNameValuePair) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } }
// Decode name/values pairs, canonicalize each URL token, and compute
// total string length. Copy other attributes to the allocated array.
iAttr = 0; iNameValuePair = 0; cwc = 0; for (i = 0; i < cAttributes; i++) { for (j = 0; j < rgAttributes[i].cAttr; j++) { pAttr = &rgAttributes[i].rgAttr[j]; if (0 == strcmp(szOID_ENROLLMENT_NAME_VALUE_PAIR, pAttr->pszObjId)) { for (k = 0; k < pAttr->cValue; k++) { if (NULL != pNameValuePair) { LocalFree(pNameValuePair); pNameValuePair = NULL; } cb = 0; if (!myDecodeObject( X509_ASN_ENCODING, szOID_ENROLLMENT_NAME_VALUE_PAIR, pAttr->rgValue[k].pbData, pAttr->rgValue[k].cbData, CERTLIB_USE_LOCALALLOC, (VOID **) &pNameValuePair, &cb)) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); _JumpError(hr, error, "myDecodeObject"); } if (NULL != pNameValuePair->pwszName && L'\0' != pNameValuePair->pwszName && NULL != pNameValuePair->pwszValue && L'\0' != pNameValuePair->pwszValue) { pnvp = &rgNameValuePair[iNameValuePair];
hr = CanonicalizeURLParm( pNameValuePair->pwszName, &pnvp->pwszName); _JumpIfError(hr, error, "CanonicalizeURLParm");
hr = CanonicalizeURLParm( pNameValuePair->pwszValue, &pnvp->pwszValue); _JumpIfError(hr, error, "CanonicalizeURLParm");
cwc += wcslen(pnvp->pwszName) + 1 + wcslen(pnvp->pwszValue) + 1; iNameValuePair++; } } } else // copy other attributes
{ rgAttr[iAttr++] = *pAttr; } } } CSASSERT(cAttr == iAttr); CSASSERT(cNameValuePair >= iNameValuePair); cNameValuePair = iNameValuePair; if (0 != cwc) { pwszNameValuePairs = (WCHAR *) LocalAlloc( LMEM_FIXED, (cwc + 1) * sizeof(WCHAR)); if (NULL == pwszNameValuePairs) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } *pwszNameValuePairs = L'\0'; for (i = 0; i < cNameValuePair; i++) { pnvp = &rgNameValuePair[i];
wcscat(pwszNameValuePairs, pnvp->pwszName); wcscat(pwszNameValuePairs, L"="); wcscat(pwszNameValuePairs, pnvp->pwszValue); wcscat(pwszNameValuePairs, L"&"); } CSASSERT(wcslen(pwszNameValuePairs) == cwc);
// and construct a URL-style, UTF8-encoded parameter string.
if (!myConvertWszToUTF8(&pszNameValuePairs, pwszNameValuePairs, -1)) { hr = myHLastError(); _JumpError(hr, error, "myConvertWszToUTF8"); } }
*prgAttr = rgAttr; rgAttr = NULL; *pcAttr = cAttr;
*ppszNameValuePairs = pszNameValuePairs; pszNameValuePairs = NULL;
hr = S_OK;
error: if (NULL != pszNameValuePairs) { LocalFree(pszNameValuePairs); } if (NULL != pwszNameValuePairs) { LocalFree(pwszNameValuePairs); } if (NULL != rgAttr) { LocalFree(rgAttr); } if (NULL != pNameValuePair) { LocalFree(pNameValuePair); } if (NULL != rgNameValuePair) { for (i = 0; i < cNameValuePair; i++) { if (NULL != rgNameValuePair[i].pwszName) { LocalFree(rgNameValuePair[i].pwszName); } if (NULL != rgNameValuePair[i].pwszValue) { LocalFree(rgNameValuePair[i].pwszValue); } } LocalFree(rgNameValuePair); } return(hr); }
HRESULT BuildCMCRequest( IN DWORD dwClientId, IN BOOL fNestedCMCRequest, IN BYTE const *pbReq, IN DWORD cbReq, OPTIONAL IN CERT_EXTENSION const *rgExt, IN DWORD cExt, OPTIONAL IN CRYPT_ATTRIBUTES const *rgAttributes, IN DWORD cAttributes, OPTIONAL IN CRYPT_ATTRIBUTE const *rgAttributeUnauth, IN DWORD cAttributeUnauth, OPTIONAL IN BYTE const *pbKeyIdRequest, IN DWORD cbKeyIdRequest, OPTIONAL IN HCRYPTPROV hProvRequest, IN DWORD dwKeySpecRequest, OPTIONAL IN LPCSTR pszObjIdHashRequest, OPTIONAL IN CERT_CONTEXT const *pCertSigner, OPTIONAL IN HCRYPTPROV hProvSigner, IN DWORD dwKeySpecSigner, OPTIONAL IN LPCSTR pszObjIdHashSigner, OUT BYTE **ppbReqCMC, OUT DWORD *pcbReqCMC) { HRESULT hr; CMC_DATA_INFO cmcData; CRYPT_ATTRIBUTE *rgAttr = NULL; DWORD cAttr; CHAR *pszNameValuePairs = NULL; CMC_TAGGED_ATTRIBUTE *rgTaggedAttribute = NULL; CMC_TAGGED_ATTRIBUTE *pTaggedAttribute; CRYPT_ATTR_BLOB *rgBlob = NULL; CRYPT_ATTR_BLOB *pBlob; CMC_TAGGED_CERT_REQUEST cmcTaggedCertRequest; CMC_TAGGED_REQUEST cmcTaggedRequest; CMC_TAGGED_CONTENT_INFO cmcTaggedContentInfo; DWORD dwBodyPartId = 1; DWORD dwBodyPartIdOfRequest = 0; DWORD dwCMCDataReference = 0; BYTE *pbCMCContent = NULL; DWORD cbCMCContent; DWORD i; CMSG_SIGNER_ENCODE_INFO aSignerEncodeInfo[2]; CMSG_SIGNED_ENCODE_INFO SignedMsgEncodeInfo; CERT_BLOB aSignerCertBlob[2]; HCRYPTMSG hMsg = NULL; HCRYPTPROV hProvVerify = NULL;
CRYPT_ATTRIBUTE AttributeRequestClient; CRYPT_ATTR_BLOB BlobRequestClient;
CERT_ISSUER_SERIAL_NUMBER IssuerSerial; ZeroMemory(&IssuerSerial, sizeof(IssuerSerial)); BYTE Zero = 0; #define BCR_CTAGGEDATTR 3
#define BCR_CBLOB 3
#ifdef USE_OLD_DUMMY_SIGNER
HCRYPTPROV hProvDummy = NULL; BSTR strContainerDummy = NULL; CERT_CONTEXT const *pCertDummy = NULL; BOOL fSaveDummySignerCert = SAVE_DUMMY_SIGNER; #endif // USE_OLD_DUMMY_SIGNER
CERT_CONTEXT const *pCert; HCRYPTPROV hProv; DWORD dwKeySpec; CHAR const *pszObjIdHash; CERT_PUBLIC_KEY_INFO *pPubKey = NULL; DWORD cbPubKey;
*ppbReqCMC = NULL; ZeroMemory(&cmcData, sizeof(cmcData)); BlobRequestClient.pbData = NULL;
if ((NULL == pbKeyIdRequest) ^ (0 == cbKeyIdRequest) ^ (NULL == hProvRequest) ^ (0 == dwKeySpecRequest)) { hr = E_INVALIDARG; _JumpError(hr, error, "request parms inconsistent"); } if (NULL != pszObjIdHashRequest && NULL == hProvRequest) { hr = E_INVALIDARG; _JumpError(hr, error, "request signing OID parm inconsistent"); } if ((NULL == pCertSigner) ^ (NULL == hProvSigner)) { hr = E_INVALIDARG; _JumpError(hr, error, "signer parms inconsistent"); }
rgTaggedAttribute = (CMC_TAGGED_ATTRIBUTE *) LocalAlloc( LMEM_FIXED, BCR_CTAGGEDATTR * sizeof(rgTaggedAttribute[0])); if (NULL == rgTaggedAttribute) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } cmcData.rgTaggedAttribute = rgTaggedAttribute; pTaggedAttribute = rgTaggedAttribute;
rgBlob = (CRYPT_ATTR_BLOB *) LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, BCR_CBLOB * sizeof(rgBlob[0])); if (NULL == rgBlob) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } pBlob = rgBlob;
if (fNestedCMCRequest) { dwCMCDataReference = dwBodyPartId++;
// cmcData.rgTaggedContentInfo[0] = Nested CMC request
ZeroMemory(&cmcTaggedContentInfo, sizeof(cmcTaggedContentInfo)); cmcData.cTaggedContentInfo = 1; cmcData.rgTaggedContentInfo = &cmcTaggedContentInfo;
cmcTaggedContentInfo.dwBodyPartID = dwCMCDataReference; cmcTaggedContentInfo.EncodedContentInfo.pbData = const_cast<BYTE *>(pbReq); cmcTaggedContentInfo.EncodedContentInfo.cbData = cbReq; } else { // possibly unsigned PKCS10
dwBodyPartIdOfRequest = dwBodyPartId++;
// cmcData.rgTaggedRequest[0] = PKCS10 request
ZeroMemory(&cmcTaggedRequest, sizeof(cmcTaggedRequest)); ZeroMemory(&cmcTaggedCertRequest, sizeof(cmcTaggedCertRequest));
cmcData.cTaggedRequest = 1; cmcData.rgTaggedRequest = &cmcTaggedRequest; cmcTaggedRequest.dwTaggedRequestChoice = CMC_TAGGED_CERT_REQUEST_CHOICE; cmcTaggedRequest.pTaggedCertRequest = &cmcTaggedCertRequest;
cmcTaggedCertRequest.dwBodyPartID = dwBodyPartIdOfRequest; cmcTaggedCertRequest.SignedCertRequest.pbData = const_cast<BYTE *>(pbReq); cmcTaggedCertRequest.SignedCertRequest.cbData = cbReq; }
// *pTaggedAttribute++ = Collected Extensions
if (0 != cExt) { CSASSERT( pTaggedAttribute < &rgTaggedAttribute[BCR_CTAGGEDATTR + cAttributes); CSASSERT(pBlob < &rgBlob[BCR_CBLOB + cAttributes);
hr = BuildCMCExtensions( cExt, rgExt, dwCMCDataReference, dwBodyPartIdOfRequest, dwBodyPartId, pTaggedAttribute, pBlob); _JumpIfError(hr, error, "BuildCMCExtensions");
dwBodyPartId++; cmcData.cTaggedAttribute++; pTaggedAttribute++; pBlob++; }
// *pTaggedAttribute++ = Collected Request Attributes
if (0 != cAttributes) { hr = SeparateNameValuePairs( rgAttributes, cAttributes, &rgAttr, &cAttr, &pszNameValuePairs); _JumpIfError(hr, error, "SeparateNameValuePairs");
if (0 != cAttr) { CSASSERT( pTaggedAttribute < &rgTaggedAttribute[BCR_CTAGGEDATTR + cAttributes); CSASSERT(pBlob < &rgBlob[BCR_CBLOB + cAttributes);
hr = BuildCMCAttributes( cAttr, rgAttr, dwCMCDataReference, dwBodyPartIdOfRequest, dwBodyPartId, pTaggedAttribute, pBlob); _JumpIfError(hr, error, "BuildCMCAttributes");
dwBodyPartId++; cmcData.cTaggedAttribute++; pTaggedAttribute++; pBlob++; } if (NULL != pszNameValuePairs) { CSASSERT( pTaggedAttribute < &rgTaggedAttribute[BCR_CTAGGEDATTR + cAttributes); CSASSERT(pBlob < &rgBlob[BCR_CBLOB + cAttributes);
hr = BuildCMCRegInfo( pszNameValuePairs, //dwCMCDataReference,
//dwBodyPartIdOfRequest,
dwBodyPartId, pTaggedAttribute, pBlob); _JumpIfError(hr, error, "BuildCMCRegInfo");
dwBodyPartId++; cmcData.cTaggedAttribute++; pTaggedAttribute++; pBlob++; } }
// Encode CMC_DATA_INFO --> CMC Request Blob
if (!myEncodeObject( X509_ASN_ENCODING, CMC_DATA, &cmcData, 0, CERTLIB_USE_LOCALALLOC, &pbCMCContent, &cbCMCContent)) { hr = myHLastError(); _JumpError(hr, error, "myEncodeObject"); } if (XECI_DISABLE != dwClientId) { hr = myEncodeRequestClientAttributeFromClientId( dwClientId, &BlobRequestClient.pbData, &BlobRequestClient.cbData); _JumpIfError(hr, error, "myEncodeRequestClientAttributeFromClientId");
AttributeRequestClient.pszObjId = szOID_REQUEST_CLIENT_INFO; AttributeRequestClient.cValue = 1; AttributeRequestClient.rgValue = &BlobRequestClient; }
pCert = NULL; hProv = hProvRequest; dwKeySpec = dwKeySpecRequest; pszObjIdHash = pszObjIdHashRequest;
if (NULL == hProvRequest && NULL == pbKeyIdRequest) { #ifdef USE_OLD_DUMMY_SIGNER
hr = EncodeDummyCert(&hProvDummy, &strContainerDummy, &pCertDummy); _JumpIfError(hr, error, "EncodeDummyCert");
pCert = pCertDummy; hProv = hProvDummy; dwKeySpec = AT_SIGNATURE; pszObjIdHash = pszObjIdHashSigner; #else
// Fake up the NULL signature Signer info
CERT_RDN_ATTR rdnAttr; CERT_RDN rdn; CERT_NAME_INFO NameInfo; NameInfo.cRDN = 1; NameInfo.rgRDN = &rdn; rdn.cRDNAttr = 1; rdn.rgRDNAttr = &rdnAttr; rdnAttr.pszObjId = szOID_RDN_DUMMY_SIGNER; rdnAttr.dwValueType = 0; rdnAttr.Value.pbData = (BYTE *) wszDUMMYSIGNER; rdnAttr.Value.cbData = 0;
if (!myEncodeObject( X509_ASN_ENCODING, X509_UNICODE_NAME, &NameInfo, 0, CERTLIB_USE_LOCALALLOC, &IssuerSerial.Issuer.pbData, &IssuerSerial.Issuer.cbData)) { hr = myHLastError(); _JumpError(hr, error, "myEncodeObject"); } IssuerSerial.SerialNumber.pbData = &Zero; IssuerSerial.SerialNumber.cbData = sizeof(Zero); #endif // USE_OLD_DUMMY_SIGNER
}
ZeroMemory(aSignerEncodeInfo, sizeof(aSignerEncodeInfo)); ZeroMemory(&SignedMsgEncodeInfo, sizeof(SignedMsgEncodeInfo)); SignedMsgEncodeInfo.cbSize = sizeof(SignedMsgEncodeInfo); SignedMsgEncodeInfo.rgSigners = aSignerEncodeInfo; //SignedMsgEncodeInfo.cCrlEncoded = 0;
//SignedMsgEncodeInfo.rgCrlEncoded = NULL;
// Encode CMC content into a PKCS 7, signed by the request's private key
// if available, otherwise use a NULL signature.
// Initialize the CMSG_SIGNER_ENCODE_INFO structure for one signer.
// If the optional pCertSigner is non-NULL, add a second signature.
for (i = 0; i < 2; i++) { CMSG_SIGNER_ENCODE_INFO *pSignerEncodeInfo = &aSignerEncodeInfo[i]; CRYPT_OID_INFO const *pOIDInfo; CHAR const *pszObjIdPubKey; BOOL fDSSKey; pSignerEncodeInfo->cbSize = sizeof(*pSignerEncodeInfo); if (NULL != pCert) { pSignerEncodeInfo->pCertInfo = pCert->pCertInfo;
aSignerCertBlob[SignedMsgEncodeInfo.cCertEncoded].cbData = pCert->cbCertEncoded; aSignerCertBlob[SignedMsgEncodeInfo.cCertEncoded].pbData = pCert->pbCertEncoded;
SignedMsgEncodeInfo.rgCertEncoded = aSignerCertBlob; SignedMsgEncodeInfo.cCertEncoded++; } if (XECI_DISABLE != dwClientId) { pSignerEncodeInfo->cAuthAttr = 1; pSignerEncodeInfo->rgAuthAttr = &AttributeRequestClient; } pSignerEncodeInfo->HashAlgorithm.pszObjId = NULL != pszObjIdHash? const_cast<CHAR *>(pszObjIdHash) : szOID_OIWSEC_sha1;
if (NULL != pCert) { pszObjIdPubKey = pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId; } else if (NULL != hProv) { CSASSERT(0 == i); CSASSERT(NULL == pPubKey); if (!myCryptExportPublicKeyInfo( hProv, dwKeySpec, CERTLIB_USE_LOCALALLOC, &pPubKey, &cbPubKey)) { hr = myHLastError(); _JumpError(hr, error, "myCryptExportPublicKeyInfo"); } pszObjIdPubKey = pPubKey->Algorithm.pszObjId; } else { pszObjIdPubKey = szOID_PKIX_NO_SIGNATURE; if (NULL == hProvVerify) { if (!CryptAcquireContextW( &hProvVerify, NULL, // pwszContainer
NULL, // pwszProvName
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) // dwFlags
{ hr = myHLastError(); _JumpError(hr, error, "CryptAcquireContextW"); } } hProv = hProvVerify; dwKeySpec = AT_SIGNATURE; } pSignerEncodeInfo->hCryptProv = hProv; pSignerEncodeInfo->dwKeySpec = dwKeySpec;
fDSSKey = FALSE; #ifdef _XENROLL_SRC_
pOIDInfo = xeCryptFindOIDInfo( #else
pOIDInfo = CryptFindOIDInfo( #endif
CRYPT_OID_INFO_OID_KEY, const_cast<CHAR *>(pszObjIdPubKey), CRYPT_PUBKEY_ALG_OID_GROUP_ID); if (NULL != pOIDInfo && CALG_DSS_SIGN == pOIDInfo->Algid) { pszObjIdPubKey = szOID_X957_SHA1DSA; fDSSKey = TRUE; }
if (NULL == pCert || fDSSKey) { pSignerEncodeInfo->HashEncryptionAlgorithm.pszObjId = const_cast<CHAR *>(pszObjIdPubKey); } if (NULL == pCert) { if (NULL == pbKeyIdRequest) { pSignerEncodeInfo->SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; pSignerEncodeInfo->SignerId.IssuerSerialNumber = IssuerSerial; } else { pSignerEncodeInfo->SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER; pSignerEncodeInfo->SignerId.KeyId.cbData = cbKeyIdRequest; pSignerEncodeInfo->SignerId.KeyId.pbData = const_cast<BYTE *>(pbKeyIdRequest); } } SignedMsgEncodeInfo.cSigners++;
if (NULL == pCertSigner) { break; } pCert = pCertSigner; hProv = hProvSigner; dwKeySpec = dwKeySpecSigner; pszObjIdHash = pszObjIdHashSigner; }
// Unauthenticated attributes are attached to the first signature ONLY!
aSignerEncodeInfo[0].cUnauthAttr = cAttributeUnauth; aSignerEncodeInfo[0].rgUnauthAttr = const_cast<CRYPT_ATTRIBUTE *>(rgAttributeUnauth);
hMsg = CryptMsgOpenToEncode( PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, CMSG_CMS_ENCAPSULATED_CONTENT_FLAG, // dwFlags
CMSG_SIGNED, &SignedMsgEncodeInfo, szOID_CT_PKI_DATA, NULL); // pStreamInfo
if (NULL == hMsg) { hr = myHLastError(); _JumpError(hr, error, "CryptMsgOpenToEncode"); }
// Update the message with the CMC content
if (!CryptMsgUpdate(hMsg, pbCMCContent, cbCMCContent, TRUE)) { hr = myHLastError(); _JumpError(hr, error, "CryptMsgUpdate"); }
// Return the encoded and signed content.
// Use CMSG_CONTENT_PARAM to get the signed message.
hr = myCryptMsgGetParam( hMsg, CMSG_CONTENT_PARAM, 0, CERTLIB_USE_LOCALALLOC, (VOID **) ppbReqCMC, pcbReqCMC); _JumpIfError(hr, error, "myCryptMsgGetParam");
error: if (NULL != hMsg) { CryptMsgClose(hMsg); //make sure close before hProv release
} if (NULL != rgAttr) { LocalFree(rgAttr); } if (NULL != pszNameValuePairs) { LocalFree(pszNameValuePairs); } if (NULL != IssuerSerial.Issuer.pbData) { LocalFree(IssuerSerial.Issuer.pbData); } if (NULL != hProvVerify) { CryptReleaseContext(hProvVerify, 0); } if (NULL != BlobRequestClient.pbData) { LocalFree(BlobRequestClient.pbData); } #ifdef USE_OLD_DUMMY_SIGNER
DestroyDummyCert( hProvDummy, strContainerDummy, pCertDummy, fSaveDummySignerCert); #endif // USE_OLD_DUMMY_SIGNER
if (NULL != rgBlob) { for (i = 0; i < BCR_CBLOB; i++) { if (NULL != rgBlob[i].pbData) { LocalFree(rgBlob[i].pbData); } } LocalFree(rgBlob); } if (NULL != rgTaggedAttribute) { LocalFree(rgTaggedAttribute); } if (NULL != pbCMCContent) { LocalFree(pbCMCContent); } if (NULL != pPubKey) { LocalFree(pPubKey); } return(hr); }
VOID FreeCMCResponse( IN XCMCRESPONSE *rgResponse, IN DWORD cResponse) { DWORD i; if (NULL != rgResponse) { for (i = 0; i < cResponse; i++) { XCMCRESPONSE *pResponse = &rgResponse[i];
if (CMC_OTHER_INFO_PEND_CHOICE == pResponse->StatusInfo.dwOtherInfoChoice && NULL != pResponse->StatusInfo.pPendInfo) { if (NULL != pResponse->StatusInfo.pPendInfo->PendToken.pbData) { LocalFree(pResponse->StatusInfo.pPendInfo->PendToken.pbData); } LocalFree(pResponse->StatusInfo.pPendInfo); } if (NULL != pResponse->StatusInfo.pwszStatusString) { LocalFree(pResponse->StatusInfo.pwszStatusString); } if (NULL != pResponse->pbCertHash) { LocalFree(pResponse->pbCertHash); } if (NULL != pResponse->pbEncryptedKeyHash) { LocalFree(pResponse->pbEncryptedKeyHash); } if (NULL != pResponse->pwszBodyPart) { LocalFree(pResponse->pwszBodyPart); } } LocalFree(rgResponse); } }
HRESULT _AppendBodyPart( IN OUT WCHAR *pwszBodyPartBuffer, IN DWORD cwcBodyPartBuffer, IN DWORD cwcPrefix, IN DWORD dwBodyPart) { HRESULT hr; WCHAR awc[14]; // L".%u"
if (cwcBodyPartBuffer <= cwcPrefix + wsprintfW(awc, L".%u", dwBodyPart)) // wsprintf(awc, L".%u", dwBodyPart))
{ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); _JumpError(hr, error, "pwszBodyPartBuffer"); } wcscpy(&pwszBodyPartBuffer[cwcPrefix], awc); // DBGPRINT((DBG_SS_CERTLIBI, "BodyPartString: %ws\n", &pwszBodyPartBuffer[1]));
hr = S_OK;
error: return(hr); }
//+--------------------------------------------------------------------------
// _SaveCMCStatus -- Save CMC Status Info
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
HRESULT _SaveCMCStatus( IN BYTE *pbIn, IN DWORD cbIn, IN OUT WCHAR *pwszBodyPartBuffer, IN DWORD cwcBodyPartBuffer, IN OUT XCMCRESPONSE **prgResponse, IN OUT DWORD *pcResponse) { HRESULT hr; DWORD i; DWORD cwcPrefix; CMC_STATUS_INFO *pcmcStatus = NULL; XCMCRESPONSE *pResponse; DWORD cb; WCHAR *pwszBodyPartT = NULL; WCHAR *pwszStatusStringT = NULL; BYTE *pbToken = NULL;
cwcPrefix = wcslen(pwszBodyPartBuffer); // Decode CMC_STATUS_INFO from Attribute Blob
CSASSERT(NULL == pcmcStatus); if (!myDecodeObject( X509_ASN_ENCODING, CMC_STATUS, pbIn, cbIn, CERTLIB_USE_LOCALALLOC, (VOID **) &pcmcStatus, &cb)) { hr = myHLastError(); _JumpError(hr, error, "myDecodeObject"); }
for (i = 0; i < pcmcStatus->cBodyList; i++) { hr = _AppendBodyPart( pwszBodyPartBuffer, cwcBodyPartBuffer, cwcPrefix, pcmcStatus->rgdwBodyList[i]); _JumpIfError(hr, error, "_AppendBodyPart");
#if 0
DBGPRINT(( DBG_SS_CERTLIBI, " Status: %u\n", pcmcStatus->dwStatus));
if (NULL != pcmcStatus->pwszStatusString) { DBGPRINT(( DBG_SS_CERTLIBI, " StatusString: %ws\n", pcmcStatus->pwszStatusString)); }
DBGPRINT(( DBG_SS_CERTLIBI, " OtherInfoChoice: %u\n", pcmcStatus->dwOtherInfoChoice)); #endif //0
if (CMC_OTHER_INFO_PEND_CHOICE == pcmcStatus->dwOtherInfoChoice) { //pcmcStatus->pPendInfo->PendToken.pbData
//pcmcStatus->pPendInfo->PendToken.cbData
//pcmcStatus->pPendInfo->PendTime
} if (0 == *pcResponse) { pResponse = (XCMCRESPONSE *) LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, sizeof(**prgResponse)); } else { pResponse = (XCMCRESPONSE *) LocalReAlloc( *prgResponse, (1 + *pcResponse) * sizeof(**prgResponse), LMEM_MOVEABLE | LMEM_ZEROINIT); } if (NULL == pResponse) { hr = E_OUTOFMEMORY; _JumpError(hr, error, 0 == *pcResponse? "LocalAlloc" : "LocalReAlloc"); } *prgResponse = pResponse; pResponse += *pcResponse;
pResponse->StatusInfo.dwStatus = pcmcStatus->dwStatus; pResponse->StatusInfo.cBodyList = pcmcStatus->rgdwBodyList[i]; pResponse->StatusInfo.dwOtherInfoChoice = pcmcStatus->dwOtherInfoChoice;
if (CMC_OTHER_INFO_FAIL_CHOICE == pcmcStatus->dwOtherInfoChoice) { pResponse->StatusInfo.dwFailInfo = pcmcStatus->dwFailInfo; }
hr = myDupString(&pwszBodyPartBuffer[1], &pwszBodyPartT); _JumpIfError(hr, error, "myDupString");
if (NULL != pcmcStatus->pwszStatusString) { hr = myDupString(pcmcStatus->pwszStatusString, &pwszStatusStringT); _JumpIfError(hr, error, "myDupString"); }
if (CMC_OTHER_INFO_PEND_CHOICE == pcmcStatus->dwOtherInfoChoice && NULL != pcmcStatus->pPendInfo) { if (NULL != pcmcStatus->pPendInfo->PendToken.pbData && 0 != pcmcStatus->pPendInfo->PendToken.cbData) { pbToken = (BYTE *) LocalAlloc( LMEM_FIXED, pcmcStatus->pPendInfo->PendToken.cbData); if (NULL == pbToken) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } CopyMemory( pbToken, pcmcStatus->pPendInfo->PendToken.pbData, pcmcStatus->pPendInfo->PendToken.cbData); } pResponse->StatusInfo.pPendInfo = (CMC_PEND_INFO *) LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, sizeof(*pResponse->StatusInfo.pPendInfo)); if (NULL == pResponse->StatusInfo.pPendInfo) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); }
// Can't fail now.
pResponse->StatusInfo.pPendInfo->PendTime = pcmcStatus->pPendInfo->PendTime;
if (NULL != pbToken) { pResponse->StatusInfo.pPendInfo->PendToken.pbData = pbToken; pResponse->StatusInfo.pPendInfo->PendToken.cbData = pcmcStatus->pPendInfo->PendToken.cbData; pbToken = NULL; } } pResponse->pwszBodyPart = pwszBodyPartT; pwszBodyPartT = NULL;
pResponse->StatusInfo.pwszStatusString = pwszStatusStringT; pwszStatusStringT = NULL;
(*pcResponse)++; } hr = S_OK;
error: pwszBodyPartBuffer[cwcPrefix] = L'\0'; if (NULL != pwszBodyPartT) { LocalFree(pwszBodyPartT); } if (NULL != pwszStatusStringT) { LocalFree(pwszStatusStringT); } if (NULL != pbToken) { LocalFree(pbToken); } if (NULL != pcmcStatus) { LocalFree(pcmcStatus); } return(hr); }
//+--------------------------------------------------------------------------
// _SaveCertHashInResponse -- Save cert hash to response array
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
HRESULT _SaveCertHashInResponse( IN BYTE const *pbCertHash, IN DWORD cbCertHash, IN WCHAR const *pwszBodyPart, IN OUT XCMCRESPONSE *rgResponse, IN DWORD cResponse, IN BOOL fCertHash) { HRESULT hr; DWORD i; for (i = 0; i < cResponse; i++) { XCMCRESPONSE *pResponse = &rgResponse[i];
if (0 == lstrcmpW(pwszBodyPart, pResponse->pwszBodyPart)) { BYTE **ppbHash = fCertHash? &pResponse->pbCertHash : &pResponse->pbEncryptedKeyHash; DWORD *pcbHash = fCertHash? &pResponse->cbCertHash : &pResponse->cbEncryptedKeyHash;
if (NULL != *ppbHash) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); _JumpError(hr, error, "hash already set"); } *ppbHash = (BYTE *) LocalAlloc(LMEM_FIXED, cbCertHash); if (NULL == *ppbHash) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } *pcbHash = cbCertHash; CopyMemory(*ppbHash, pbCertHash, cbCertHash); break; } } if (i >= cResponse) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); _JumpError(hr, error, "unknown hash"); } hr = S_OK;
error: return(hr); }
//+--------------------------------------------------------------------------
// _SaveCMCCertHash -- Save CMC cert hash from attributes
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
#define BLOB_ROUND(cb) \
(((cb) + sizeof(CRYPT_DATA_BLOB) - 1) / sizeof(CRYPT_DATA_BLOB))
HRESULT _SaveCMCCertHash( IN BYTE *pbIn, IN DWORD cbIn, IN OUT WCHAR *pwszBodyPartBuffer, IN DWORD cwcBodyPartBuffer, IN OUT XCMCRESPONSE *rgResponse, IN OUT DWORD cResponse) { HRESULT hr; CMC_ADD_ATTRIBUTES_INFO *pcmcAttrib = NULL; CRYPT_ATTRIBUTE const *pAttr; CRYPT_ATTRIBUTE const *pAttrEnd; CRYPT_DATA_BLOB aBlob[1 + BLOB_ROUND(CBMAX_CRYPT_HASH_LEN)]; DWORD cb; DWORD cwcPrefix;
cwcPrefix = wcslen(pwszBodyPartBuffer);
// Decode CMC_ADD_ATTRIBUTES_INFO from Attribute Blob
CSASSERT(NULL == pcmcAttrib); if (!myDecodeObject( X509_ASN_ENCODING, CMC_ADD_ATTRIBUTES, pbIn, cbIn, CERTLIB_USE_LOCALALLOC, (VOID **) &pcmcAttrib, &cb)) { hr = myHLastError(); _JumpError(hr, error, "myDecodeObject"); } if (0 != pcmcAttrib->dwCmcDataReference) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); _JumpError(hr, error, "pcmcAttrib->dwCmcDataReference"); }
pAttrEnd = &pcmcAttrib->rgAttribute[pcmcAttrib->cAttribute]; for (pAttr = pcmcAttrib->rgAttribute; pAttr < pAttrEnd; pAttr++) { BOOL fCertHash = 0 == strcmp(pAttr->pszObjId, szOID_ISSUED_CERT_HASH);
if (fCertHash || 0 == strcmp(pAttr->pszObjId, szOID_ENCRYPTED_KEY_HASH)) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); if (1 != pAttr->cValue) { _JumpError(hr, error, "pAttr->cValue"); } if (1 != pcmcAttrib->cCertReference) { _JumpError(hr, error, "pcmcAttrib->dwCmcDataReference"); } hr = _AppendBodyPart( pwszBodyPartBuffer, cwcBodyPartBuffer, cwcPrefix, pcmcAttrib->rgdwCertReference[0]); _JumpIfError(hr, error, "_AppendBodyPart");
cb = sizeof(aBlob); if (!CryptDecodeObject( X509_ASN_ENCODING, X509_OCTET_STRING, pAttr->rgValue[0].pbData, pAttr->rgValue[0].cbData, 0, aBlob, &cb)) { hr = myHLastError(); _JumpError(hr, error, "myDecodeObject"); } hr = _SaveCertHashInResponse( aBlob[0].pbData, aBlob[0].cbData, &pwszBodyPartBuffer[1], rgResponse, cResponse, fCertHash); _JumpIfError(hr, error, "SaveCertHashInResponse"); } } hr = S_OK;
error: pwszBodyPartBuffer[cwcPrefix] = L'\0'; if (NULL != pcmcAttrib) { LocalFree(pcmcAttrib); } return(hr); }
//+--------------------------------------------------------------------------
// _DecodeCMCTaggedAttributes -- Decode CMC Tagged Attributes
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
HRESULT _DecodeCMCTaggedAttributes( IN DWORD cTaggedAttribute, IN CMC_TAGGED_ATTRIBUTE const *rgTaggedAttribute, IN OUT WCHAR *pwszBodyPartBuffer, IN DWORD cwcBodyPartBuffer, IN OUT XCMCRESPONSE **prgResponse, IN OUT DWORD *pcResponse) { HRESULT hr; DWORD i; CRYPT_ATTRIBUTE const *pAttribute; DWORD j;
for (i = 0; i < cTaggedAttribute; i++) { pAttribute = &rgTaggedAttribute[i].Attribute;
for (j = 0; j < pAttribute->cValue; j++) { if (0 == strcmp(szOID_CMC_STATUS_INFO, pAttribute->pszObjId)) { hr = _SaveCMCStatus( pAttribute->rgValue[j].pbData, pAttribute->rgValue[j].cbData, pwszBodyPartBuffer, cwcBodyPartBuffer, prgResponse, pcResponse); _JumpIfError(hr, error, "_SaveCMCStatus"); } } } for (i = 0; i < cTaggedAttribute; i++) { pAttribute = &rgTaggedAttribute[i].Attribute;
for (j = 0; j < pAttribute->cValue; j++) { if (0 == strcmp(szOID_CMC_ADD_ATTRIBUTES, pAttribute->pszObjId)) { hr = _SaveCMCCertHash( pAttribute->rgValue[j].pbData, pAttribute->rgValue[j].cbData, pwszBodyPartBuffer, cwcBodyPartBuffer, *prgResponse, *pcResponse); _JumpIfError(hr, error, "_SaveCMCCertHash"); } } } hr = S_OK;
error: return(hr); }
//+--------------------------------------------------------------------------
// _DecodeCMCResponse -- Decode a CMC Response Message
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
HRESULT _DecodeCMCResponse( IN BYTE *pbIn, IN DWORD cbIn, IN OUT WCHAR *pwszBodyPartBuffer, IN DWORD cwcBodyPartBuffer, IN OUT XCMCRESPONSE **prgResponse, IN OUT DWORD *pcResponse) { HRESULT hr; CMC_RESPONSE_INFO *pcmcResponse = NULL; DWORD cbcmcResponse;
if (!myDecodeObject( X509_ASN_ENCODING, CMC_RESPONSE, pbIn, cbIn, CERTLIB_USE_LOCALALLOC, (VOID **) &pcmcResponse, &cbcmcResponse)) { hr = myHLastError(); _JumpError(hr, error, "myDecodeObject"); }
hr = _DecodeCMCTaggedAttributes( pcmcResponse->cTaggedAttribute, pcmcResponse->rgTaggedAttribute, pwszBodyPartBuffer, cwcBodyPartBuffer, prgResponse, pcResponse); _JumpIfError(hr, error, "_DecodeTaggedAttributes");
#if 0
hr = _DecodeTaggedContent( pcmcResponse->cTaggedContentInfo, pcmcResponse->rgTaggedContentInfo); _JumpIfError(hr, error, "_DecodeTaggedContent");
hr = _DecodeTaggedOther( pcmcResponse->cTaggedOtherMsg, pcmcResponse->rgTaggedOtherMsg); _JumpIfError(hr, error, "_DecodeTaggedOther"); #endif
error: if (NULL != pcmcResponse) { LocalFree(pcmcResponse); } return(hr); }
//+--------------------------------------------------------------------------
// ParseCMCResponse -- Decode a Full Response Message
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
HRESULT ParseCMCResponse( IN BYTE *pbResponse, IN DWORD cbResponse, OPTIONAL OUT HCERTSTORE *phStoreResponse, OUT XCMCRESPONSE **prgResponse, OUT DWORD *pcResponse) { HRESULT hr; DWORD dwMsgType; char *pszInnerContentObjId = NULL; BYTE *pbContents = NULL; DWORD cbContents; HCERTSTORE hStore = NULL; WCHAR awcBodyPartBuffer[MAX_PATH];
if (NULL != phStoreResponse) { *phStoreResponse = NULL; } *prgResponse = NULL; *pcResponse = 0;
// Decode outer PKCS 7 signed message, which contains all of the certs.
hr = myDecodePKCS7( pbResponse, cbResponse, &pbContents, &cbContents, &dwMsgType, &pszInnerContentObjId, NULL, // &cSigner,
NULL, // &cRecipient,
&hStore, NULL); // phMsg
_JumpIfError(hr, error, "myDecodePKCS7(outer)");
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); if (CMSG_SIGNED != dwMsgType) { _JumpError(hr, error, "dwMsgType"); } if (NULL == pszInnerContentObjId || 0 != strcmp(pszInnerContentObjId, szOID_CT_PKI_RESPONSE)) { _JumpError(hr, error, "pszInnerContentObjId"); } awcBodyPartBuffer[0] = L'\0'; hr = _DecodeCMCResponse( pbContents, cbContents, awcBodyPartBuffer, ARRAYSIZE(awcBodyPartBuffer), prgResponse, pcResponse); _JumpIfError(hr, error, "_DecodeCMCResponse");
if (NULL != phStoreResponse) { *phStoreResponse = hStore; hStore = NULL; } hr = S_OK;
error: if (NULL != pbContents) { LocalFree(pbContents); } if (NULL != pszInnerContentObjId) { LocalFree(pszInnerContentObjId); } if (NULL != hStore) { CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG); } return(hr); }
HRESULT myCryptMsgGetParam( IN HCRYPTMSG hMsg, IN DWORD dwParamType, IN DWORD dwIndex, IN CERTLIB_ALLOCATOR allocType, OUT VOID **ppvData, OUT DWORD *pcbData) { HRESULT hr; VOID *pvData = NULL;
*ppvData = NULL; *pcbData = 0; if (!CryptMsgGetParam( hMsg, dwParamType, dwIndex, NULL, pcbData)) { hr = myHLastError(); if (CRYPT_E_ATTRIBUTES_MISSING == hr || CRYPT_E_INVALID_INDEX == hr) { hr = S_FALSE; } // _JumpError2(hr, error, "CryptMsgGetParam", S_FALSE);
_JumpError(hr, error, "CryptMsgGetParam"); }
pvData = myAlloc(*pcbData, allocType); if (NULL == pvData) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } ZeroMemory(pvData, *pcbData);
if (!CryptMsgGetParam( hMsg, dwParamType, dwIndex, pvData, pcbData)) { hr = myHLastError(); _JumpError(hr, error, "CryptMsgGetParam"); }
*ppvData = pvData; pvData = NULL; hr = S_OK;
error: if (NULL != pvData) { LocalFree(pvData); } return(hr); }
HRESULT myEncodeUTF8String( IN WCHAR const *pwszIn, OUT BYTE **ppbOut, OUT DWORD *pcbOut) { HRESULT hr; CERT_NAME_VALUE cnv;
*ppbOut = NULL;
cnv.dwValueType = CERT_RDN_UTF8_STRING; cnv.Value.pbData = (BYTE *) pwszIn; cnv.Value.cbData = 0;
if (!myEncodeObject( X509_ASN_ENCODING, X509_UNICODE_ANY_STRING, &cnv, 0, CERTLIB_USE_LOCALALLOC, ppbOut, pcbOut)) { hr = myHLastError(); _JumpIfError(hr, error, "myEncodeObject"); } hr = S_OK;
error: return(hr); }
HRESULT myDecodeUTF8String( IN BYTE const *pbIn, IN DWORD cbIn, OUT WCHAR **ppwszOut) { HRESULT hr; CERT_NAME_VALUE *pNameValue = NULL; DWORD cb;
*ppwszOut = NULL;
if (!myDecodeObject( X509_ASN_ENCODING, X509_UNICODE_ANY_STRING, pbIn, cbIn, CERTLIB_USE_LOCALALLOC, (VOID **) &pNameValue, &cb)) { hr = myHLastError(); _JumpError(hr, error, "myDecodeObject"); } if (NULL != pNameValue->Value.pbData) { hr = myDupString((WCHAR *) pNameValue->Value.pbData, ppwszOut); _JumpIfError(hr, error, "myDupString"); } hr = S_OK;
error: if (NULL != pNameValue) { LocalFree(pNameValue); } return(hr); }
HRESULT myEncodeRequestClientAttribute( IN CRYPT_REQUEST_CLIENT_INFO const *pcrci, OUT BYTE **ppbOut, OUT DWORD *pcbOut) { HRESULT hr; CRYPT_DER_BLOB aBlob[4]; CRYPT_SEQUENCE_OF_ANY Sequence; DWORD i;
ZeroMemory(aBlob, sizeof(aBlob));
Sequence.cValue = ARRAYSIZE(aBlob); Sequence.rgValue = aBlob;
if (!myEncodeObject( X509_ASN_ENCODING, X509_INTEGER, &pcrci->dwClientId, 0, CERTLIB_USE_LOCALALLOC, &aBlob[0].pbData, &aBlob[0].cbData)) { hr = myHLastError(); _JumpIfError(hr, error, "myEncodeObject"); } hr = myEncodeUTF8String( pcrci->pwszMachine, &aBlob[1].pbData, &aBlob[1].cbData); _JumpIfError(hr, error, "myEncodeUTF8String");
hr = myEncodeUTF8String( pcrci->pwszUser, &aBlob[2].pbData, &aBlob[2].cbData); _JumpIfError(hr, error, "myEncodeUTF8String");
hr = myEncodeUTF8String( pcrci->pwszProcess, &aBlob[3].pbData, &aBlob[3].cbData); _JumpIfError(hr, error, "myEncodeUTF8String");
if (!myEncodeObject( X509_ASN_ENCODING, X509_SEQUENCE_OF_ANY, &Sequence, 0, CERTLIB_USE_LOCALALLOC, ppbOut, pcbOut)) { hr = myHLastError(); _JumpIfError(hr, error, "myEncodeObject"); } hr = S_OK;
error: for (i = 0; i < ARRAYSIZE(aBlob); i++) { if (NULL != aBlob[i].pbData) { LocalFree(aBlob[i].pbData); } } return(hr); }
HRESULT myDecodeRequestClientAttribute( IN BYTE const *pbIn, IN DWORD cbIn, OUT CRYPT_REQUEST_CLIENT_INFO **ppcrci) { HRESULT hr; CRYPT_SEQUENCE_OF_ANY *pSequence = NULL; CRYPT_REQUEST_CLIENT_INFO crci; DWORD cb; BYTE *pb;
ZeroMemory(&crci, sizeof(crci)); *ppcrci = NULL;
if (!myDecodeObject( X509_ASN_ENCODING, X509_SEQUENCE_OF_ANY, pbIn, cbIn, CERTLIB_USE_LOCALALLOC, (VOID **) &pSequence, &cb)) { hr = myHLastError(); _JumpError(hr, error, "myDecodeObject"); } if (4 != pSequence->cValue) { hr = E_INVALIDARG; _JumpError(hr, error, "incomplete structure"); } cb = sizeof(crci.dwClientId); if (!CryptDecodeObject( X509_ASN_ENCODING, X509_INTEGER, pSequence->rgValue[0].pbData, pSequence->rgValue[0].cbData, 0, // dwFlags
(VOID *) &crci.dwClientId, &cb)) { hr = myHLastError(); _JumpError(hr, error, "myDecodeObject"); } hr = myDecodeUTF8String( pSequence->rgValue[1].pbData, pSequence->rgValue[1].cbData, &crci.pwszMachine); _JumpIfError(hr, error, "myDecodeUTF8String");
hr = myDecodeUTF8String( pSequence->rgValue[2].pbData, pSequence->rgValue[2].cbData, &crci.pwszUser); _JumpIfError(hr, error, "myDecodeUTF8String");
hr = myDecodeUTF8String( pSequence->rgValue[3].pbData, pSequence->rgValue[3].cbData, &crci.pwszProcess); _JumpIfError(hr, error, "myDecodeUTF8String");
cb = sizeof(crci); if (NULL != crci.pwszMachine) { cb += DWORDROUND(sizeof(WCHAR) * (wcslen(crci.pwszMachine) + 1)); } if (NULL != crci.pwszUser) { cb += DWORDROUND(sizeof(WCHAR) * (wcslen(crci.pwszUser) + 1)); } if (NULL != crci.pwszProcess) { cb += DWORDROUND(sizeof(WCHAR) * (wcslen(crci.pwszProcess) + 1)); } *ppcrci = (CRYPT_REQUEST_CLIENT_INFO *) LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, cb); if (NULL == *ppcrci) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } pb = (BYTE *) (*ppcrci + 1); (*ppcrci)->dwClientId = crci.dwClientId; if (NULL != crci.pwszMachine) { (*ppcrci)->pwszMachine = (WCHAR *) pb; wcscpy((*ppcrci)->pwszMachine, crci.pwszMachine); pb += DWORDROUND(sizeof(WCHAR) * (wcslen(crci.pwszMachine) + 1)); } if (NULL != crci.pwszUser) { (*ppcrci)->pwszUser = (WCHAR *) pb; wcscpy((*ppcrci)->pwszUser, crci.pwszUser); pb += DWORDROUND(sizeof(WCHAR) * (wcslen(crci.pwszUser) + 1)); } if (NULL != crci.pwszProcess) { (*ppcrci)->pwszProcess = (WCHAR *) pb; wcscpy((*ppcrci)->pwszProcess, crci.pwszProcess); pb += DWORDROUND(sizeof(WCHAR) * (wcslen(crci.pwszProcess) + 1)); } hr = S_OK;
error: if (NULL != pSequence) { LocalFree(pSequence); } if (NULL != crci.pwszMachine) { LocalFree(crci.pwszMachine); } if (NULL != crci.pwszUser) { LocalFree(crci.pwszUser); } if (NULL != crci.pwszProcess) { LocalFree(crci.pwszProcess); } return(hr); }
HRESULT myEncodeRequestClientAttributeFromClientId( IN DWORD dwClientId, OUT BYTE **ppbOut, OUT DWORD *pcbOut) { HRESULT hr; CRYPT_REQUEST_CLIENT_INFO crci;
*ppbOut = NULL; ZeroMemory(&crci, sizeof(crci)); crci.dwClientId = dwClientId; //crci.pwszMachine = NULL;
//crci.pwszUser = NULL;
//crci.pwszProcess = NULL;
hr = myGetMachineDnsName(&crci.pwszMachine); _PrintIfError(hr, "myGetMachineDnsName");
hr = myGetUserNameEx(NameSamCompatible, &crci.pwszUser); _PrintIfError(hr, "myGetUserNameEx");
hr = myGetProcessName(&crci.pwszProcess); _PrintIfError(hr, "myGetProcessName");
hr = myEncodeRequestClientAttribute(&crci, ppbOut, pcbOut); _JumpIfError(hr, error, "myEncodeRequestClientAttribute");
error: if (NULL != crci.pwszProcess) { LocalFree(crci.pwszProcess); } if (NULL != crci.pwszUser) { LocalFree(crci.pwszUser); } if (NULL != crci.pwszMachine) { LocalFree(crci.pwszMachine); } return(hr); }
#ifdef _XENROLL_SRC_
typedef BOOL (WINAPI * PFNGetComputerNameExW) ( COMPUTER_NAME_FORMAT NameType, // name type
WCHAR *lpBuffer, // name buffer
LPDWORD lpnSize // size of name buffer
);
typedef BOOL (WINAPI * PFNGetUserNameExW)( EXTENDED_NAME_FORMAT NameFormat, // name format
WCHAR *lpNameBuffer, // name buffer
PULONG nSize // size of name buffer
);
typedef WCHAR* (WINAPI * PFNGetCommandLineW)( VOID ); #endif //_XENROLL_SRC_
BOOL xeGetUserNameExW( IN EXTENDED_NAME_FORMAT NameFormat, IN WCHAR *pwszUserName, IN PULONG pcwc) { #ifdef _XENROLL_SRC_
BOOL b = FALSE; PFNGetUserNameExW pfnGetUserNameExW = NULL; HMODULE hModule = GetModuleHandle("secur32.dll"); if (NULL != hModule) { pfnGetUserNameExW = (PFNGetUserNameExW) GetProcAddress(hModule, "GetUserNameExW"); if (NULL != pfnGetUserNameExW) { return pfnGetUserNameExW(NameFormat, pwszUserName, pcwc); } //downlevel clients, do the hard work
if (NULL == pwszUserName) { //just get size
return GetUserName(NULL, pcwc); }
CHAR *pszUserName = (CHAR*)LocalAlloc(LMEM_FIXED, *pcwc * sizeof(CHAR)); if (NULL == pszUserName) { return FALSE; } if (GetUserName(pszUserName, pcwc)) { //convert to wide string
if (0 != MultiByteToWideChar( CP_ACP, 0, pszUserName, -1, pwszUserName, *pcwc)) { b = TRUE; } } LocalFree(pszUserName); } return b; #else
return GetUserNameExW(NameFormat, pwszUserName, pcwc); #endif //_XENROLL_SRC_
}
BOOL xeGetComputerNameExW( IN COMPUTER_NAME_FORMAT NameFormat, // name format
IN WCHAR *pwszComputerName, // name buffer
IN OUT DWORD *pcwc) // size of name buffer
{ #ifdef _XENROLL_SRC_
BOOL b = FALSE; PFNGetComputerNameExW pfnGetComputerNameExW = NULL; HMODULE hModule = GetModuleHandle("kernel32.dll"); if (NULL != hModule) { pfnGetComputerNameExW = (PFNGetComputerNameExW) GetProcAddress(hModule, "GetComputerNameExW"); if (NULL != pfnGetComputerNameExW) { return pfnGetComputerNameExW(NameFormat, pwszComputerName, pcwc); } //downlevel clients, do the hard work
if (NULL == pwszComputerName) { //just get size, donwlevel machine has max size
*pcwc = MAX_COMPUTERNAME_LENGTH + 1; SetLastError(ERROR_MORE_DATA); // caller check on
return FALSE; }
CHAR *pszComputerName = (CHAR*) LocalAlloc(LMEM_FIXED, *pcwc * sizeof(CHAR)); if (NULL == pszComputerName) { return FALSE; } if (GetComputerName(pszComputerName, pcwc)) { //convert to wide string
if (0 != MultiByteToWideChar( CP_ACP, 0, pszComputerName, -1, pwszComputerName, *pcwc + 1)) { b = TRUE; } } LocalFree(pszComputerName); } return b; #else
return GetComputerNameExW(NameFormat, pwszComputerName, pcwc); #endif // _XENROLL_SRC_
}
WCHAR* xeGetCommandLineW( OUT BOOL *pfNeedFree) { //init
*pfNeedFree = FALSE;
#ifdef _XENROLL_SRC_
WCHAR *pwszCommandLine = NULL; PFNGetCommandLineW pfnGetCommandLineW = NULL; HMODULE hModule = GetModuleHandle("kernel32.dll"); CHAR *pszCommandLine; int cch;
if (NULL != hModule) { pfnGetCommandLineW = (PFNGetCommandLineW) GetProcAddress(hModule, "GetCommandLineW"); if (NULL != pfnGetCommandLineW) { return pfnGetCommandLineW(); } //downlevel clients, do the hard work
pszCommandLine = GetCommandLine(); if (NULL == pszCommandLine) { //error
return NULL; } cch = strlen(pszCommandLine) + 1; pwszCommandLine = (WCHAR*)LocalAlloc(LMEM_FIXED, cch * sizeof(WCHAR)); if (NULL != pwszCommandLine) { //convert to wide string
if (0 == MultiByteToWideChar( CP_ACP, 0, pszCommandLine, -1, pwszCommandLine, cch)) { LocalFree(pwszCommandLine); pwszCommandLine = NULL; } else { //caller to free
*pfNeedFree = TRUE; } } } return pwszCommandLine; #else
return GetCommandLineW(); #endif // _XENROLL_SRC_
}
HRESULT myGetUserNameEx( IN EXTENDED_NAME_FORMAT NameFormat, OUT WCHAR **ppwszUserName) { HRESULT hr; DWORD cwc = 0; WCHAR *pwszUserName = NULL;
for (;;) { if (!xeGetUserNameExW(NameFormat, pwszUserName, &cwc)) { hr = myHLastError(); if (NULL != pwszUserName || HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr) { _JumpError(hr, error, "GetUserNameEx"); } } if (NULL != pwszUserName) { break; } pwszUserName = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR)); if (NULL == pwszUserName) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } } *ppwszUserName = pwszUserName; pwszUserName = NULL; hr = S_OK;
error: if (NULL != pwszUserName) { LocalFree(pwszUserName); } return(hr); }
HRESULT myGetMachineDnsName( OUT WCHAR **ppwszDnsName) { HRESULT hr; WCHAR *pwszDnsName = NULL; DWORD cwc; COMPUTER_NAME_FORMAT NameType = ComputerNameDnsFullyQualified;
*ppwszDnsName = NULL; for (;;) { cwc = 0; if (!xeGetComputerNameExW(NameType, NULL, &cwc)) { hr = myHLastError(); if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr && ComputerNameDnsFullyQualified == NameType) { _PrintError(hr, "GetComputerNameExW(DnsFullyQualified) -- switching to NetBIOS"); NameType = ComputerNameNetBIOS; continue; } if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr) { _JumpError(hr, error, "GetComputerNameEx"); } } else { cwc++; } break; } pwszDnsName = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR)); if (NULL == pwszDnsName) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); }
if (!xeGetComputerNameExW(NameType, pwszDnsName, &cwc)) { hr = myHLastError(); _JumpError(hr, error, "GetComputerNameEx"); }
*ppwszDnsName = pwszDnsName; pwszDnsName = NULL; hr = S_OK;
error: if (NULL != pwszDnsName) { LocalFree(pwszDnsName); } return(hr); }
HRESULT myGetProcessName( OUT WCHAR **ppwszProcessName) { HRESULT hr; WCHAR *pwszCommandLine; WCHAR const *pwsz; WCHAR const *pwszStart; WCHAR *pwszAlloc; DWORD cwc; WCHAR wc; BOOL fNeedFree; *ppwszProcessName = NULL; pwszCommandLine = xeGetCommandLineW(&fNeedFree); if (NULL == pwszCommandLine) { pwszCommandLine = L""; } wc = L' '; pwsz = pwszCommandLine; if ('"' == *pwsz) { wc = '"'; pwsz++; } pwszStart = pwsz; while (L'\0' != *pwsz && wc != *pwsz) { if (L'\\' == *pwsz++) { pwszStart = pwsz; } } cwc = SAFE_SUBTRACT_POINTERS(pwsz, pwszStart);
pwszAlloc = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR)); if (NULL == pwszAlloc) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } CopyMemory(pwszAlloc, pwszStart, cwc * sizeof(WCHAR)); pwszAlloc[cwc] = L'\0'; *ppwszProcessName = pwszAlloc; hr = S_OK;
error: if (fNeedFree && NULL != pwszCommandLine) { LocalFree(pwszCommandLine); } return(hr); }
|