You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2804 lines
67 KiB
2804 lines
67 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// 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);
|
|
}
|