Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1146 lines
36 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: unattend.cpp
//
// Contents: handling unattended attributes
//
// History: 8/97 XTan
//
//----------------------------------------------------------------------------
#include "pch.cpp"
#pragma hdrstop
// includes
#include <assert.h>
#include "cscsp.h"
#include "certmsg.h"
#include "usecert.h"
#include "dssetup.h"
#include "wizpage.h"
//defines
#define __dwFILE__ __dwFILE_OCMSETUP_UNATTEND_CPP__
#define wszCOMPONENTS L"Components"
#define wszAttrCAMACHINE L"camachine" //L"CAMachine"
#define wszAttrCANAME L"caname" //L"CAName"
#define wszAttrPARENTCAMACHINE L"parentcamachine" //L"ParentCAMachine"
#define wszAttrPARENTCANAME L"parentcaname" //L"ParentCAName"
#define wszAttrCATYPE L"catype" //L"CAType"
#define wszAttrNAME L"name" //L"Name"
#define wszAttrCADISTINGUISHEDNAME L"cadistinguishedname" //L"CADistinguishedName"
#define wszAttrORGANIZATION L"organization" //L"Organization" // dead
#define wszAttrORGANIZATIONUNIT L"organizationalunit" //L"OrganizationalUnit" // dead
#define wszAttrLOCALITY L"locality" //L"Locality" // dead
#define wszAttrSTATE L"state" //L"State" // dead
#define wszAttrCOUNTRY L"country" //L"Country" // dead
#define wszAttrDESCRIPTION L"description" //L"Description" // dead
#define wszAttrEMAIL L"email" //L"Email" // dead
#define wszAttrVALIDITYPERIODSTRING L"validityperiod" //L"ValidityPeriod"
#define wszAttrVALIDITYPERIODCOUNT L"validityperiodunits" //L"ValidityPeriodUnits"
#define wszAttrSHAREDFOLDER L"sharedfolder" //L"SharedFolder"
#define wszAttrREQUESTFILE L"requestfile" //L"RequestFile"
#define wszAttrCSPPROVIDER L"cspprovider" //L"CSPProvider"
#define wszAttrHASHALGORITHM L"hashalgorithm" //L"HashAlgorithm"
#define wszAttrKEYLENGTH L"keylength" //L"KeyLength"
#define wszAttrEXISTINGKEY L"existingkey" //L"ExistingKey"
#define wszAttrUSEEXISTINGCERT L"useexistingcert" //L"UseExistingCert"
#define wszAttrPRESERVEDB L"preservedb" //L"PreserveDB"
#define wszAttrDBDIR L"dbdir" //L"DBDir"
#define wszAttrLOGDIR L"logdir" //L"LogDir"
#define wszAttrINTERACTIVESERVICE L"interactive" //L"Interactive"
#define wszValueENTERPRISEROOT L"enterpriseroot"
#define wszValueENTERPRISESUBORDINATE L"enterprisesubordinate"
#define wszValueSTANDALONEROOT L"standaloneroot"
#define wszValueSTANDALONESUBORDINATE L"standalonesubordinate"
#define wszValueYES L"yes"
#define wszValueNO L"no"
#define wszValueSHA1 L"sha1"
#define wszValueMD2 L"md2"
#define wszValueMD4 L"md4"
#define wszValueMD5 L"md5"
//typedefs
// globals
UNATTENDPARM aUnattendParmClient[] =
{
{ wszAttrCAMACHINE, NULL/*pClient->pwszWebCAMachine*/ },
{ wszAttrCANAME, NULL/*pClient->pwszWebCAName*/ },
// add more code in HookUnattendedClientAttributes if you add
{ NULL, NULL/*end*/ },
};
UNATTENDPARM aUnattendParmServer[] =
{
{ wszAttrCATYPE, NULL/*pServer->pwszCAType*/ },
{ wszAttrNAME, NULL/*pServer->pwszCACommonName*/ },
{ wszAttrCADISTINGUISHEDNAME,NULL/*pServer->pwszCADistinguishedName*/ },
/* dead params
{ wszAttrORGANIZATION, NULL },
{ wszAttrORGANIZATIONUNIT, NULL },
{ wszAttrLOCALITY, NULL },
{ wszAttrSTATE, NULL },
{ wszAttrCOUNTRY, NULL },
{ wszAttrDESCRIPTION, NULL },
{ wszAttrEMAIL, NULL },*/
{ wszAttrVALIDITYPERIODCOUNT, NULL/*pServer->pwszValidityPeriodCount*/ },
{ wszAttrVALIDITYPERIODSTRING, NULL/*pServer->pwszValidityPeriodString*/ },
{ wszAttrSHAREDFOLDER, NULL/*pServer->pwszSharedFolder*/ },
{ wszAttrREQUESTFILE, NULL/*pServer->pwszRequestFile*/ },
{ wszAttrCSPPROVIDER, NULL/*pServer->pwszProvName*/ },
{ wszAttrHASHALGORITHM, NULL/*pServer->pwszHashAlgorithm*/ },
{ wszAttrKEYLENGTH, NULL/*pServer->pwszKeyLength*/ },
{ wszAttrEXISTINGKEY, NULL/*pServer->pwszKeyContainerName*/ },
{ wszAttrUSEEXISTINGCERT, NULL/*pServer->pwszUseExistingCert*/ },
{ wszAttrPRESERVEDB, NULL/*pServer->pwszPreserveDB*/ },
{ wszAttrPARENTCAMACHINE, NULL/*pServer->pwszParentCAMachine*/ },
{ wszAttrPARENTCANAME, NULL/*pServer->pwszParentCAName*/ },
{ wszAttrDBDIR, NULL/*pServer->pwszDBDirectory*/ },
{ wszAttrLOGDIR, NULL/*pServer->pwszLogDirectory*/ },
{ wszAttrINTERACTIVESERVICE, NULL/*pServer->pwszInteractiveService*/ },
// add more code in HookUnattendedServerAttributes if you add
{ NULL, NULL/*end*/ },
};
HRESULT
HookUnattendedClientAttributes(
IN OUT PER_COMPONENT_DATA *pComp,
IN OUT const SUBCOMP *pClientComp)
{
HRESULT hr;
DWORD i;
CAWEBCLIENTSETUPINFO *pClient = pComp->CA.pClient;
for (i = 0; NULL != pClientComp->aUnattendParm[i].pwszName; ++i)
{
if (0 == lstrcmpi( wszAttrCAMACHINE,
pClientComp->aUnattendParm[i].pwszName) )
{
pClientComp->aUnattendParm[i].ppwszValue =
&pClient->pwszWebCAMachine;
}
else if (0 == lstrcmpi( wszAttrCANAME,
pClientComp->aUnattendParm[i].pwszName) )
{
pClientComp->aUnattendParm[i].ppwszValue =
&pClient->pwszWebCAName;
}
else
{
hr = E_INVALIDARG;
_JumpError(hr, error, "Internal error, incorrect attr.");
}
}
hr = S_OK;
error:
return hr;
}
HRESULT
HookUnattendedServerAttributes(
IN OUT PER_COMPONENT_DATA *pComp,
IN OUT const SUBCOMP *pServerComp)
{
HRESULT hr;
DWORD i;
CASERVERSETUPINFO *pServer = (pComp->CA).pServer;
for (i = 0; NULL != pServerComp->aUnattendParm[i].pwszName; ++i)
{
if (0 == lstrcmpi( wszAttrCATYPE,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszCAType;
}
else if (0 == lstrcmpi( wszAttrNAME,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszCACommonName;
}
else if (0 == lstrcmpi( wszAttrCADISTINGUISHEDNAME,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszFullCADN;
}
else if (0 == lstrcmpi( wszAttrORGANIZATION,
pServerComp->aUnattendParm[i].pwszName) )
{
// dead
}
else if (0 == lstrcmpi( wszAttrORGANIZATIONUNIT,
pServerComp->aUnattendParm[i].pwszName) )
{
// dead
}
else if (0 == lstrcmpi( wszAttrLOCALITY,
pServerComp->aUnattendParm[i].pwszName) )
{
// dead
}
else if (0 == lstrcmpi( wszAttrSTATE,
pServerComp->aUnattendParm[i].pwszName) )
{
// dead
}
else if (0 == lstrcmpi( wszAttrCOUNTRY,
pServerComp->aUnattendParm[i].pwszName) )
{
// dead
}
else if (0 == lstrcmpi( wszAttrDESCRIPTION,
pServerComp->aUnattendParm[i].pwszName) )
{
// dead
}
else if (0 == lstrcmpi( wszAttrEMAIL,
pServerComp->aUnattendParm[i].pwszName) )
{
// dead
}
else if (0 == lstrcmpi( wszAttrVALIDITYPERIODCOUNT,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszValidityPeriodCount;
}
else if (0 == lstrcmpi( wszAttrVALIDITYPERIODSTRING,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszValidityPeriodString;
}
else if (0 == lstrcmpi( wszAttrSHAREDFOLDER,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszSharedFolder;
}
else if (0 == lstrcmpi( wszAttrREQUESTFILE,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszRequestFile;
}
else if (0 == lstrcmpi( wszAttrCSPPROVIDER,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pCSPInfo->pwszProvName;
}
else if (0 == lstrcmpi( wszAttrHASHALGORITHM,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszHashAlgorithm;
}
else if (0 == lstrcmpi( wszAttrKEYLENGTH,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszKeyLength;
}
else if (0 == lstrcmpi( wszAttrEXISTINGKEY,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszKeyContainerName;
}
else if (0 == lstrcmpi( wszAttrUSEEXISTINGCERT,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszUseExistingCert;
}
else if (0 == lstrcmpi( wszAttrPRESERVEDB,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszPreserveDB;
}
else if (0 == lstrcmpi( wszAttrPARENTCAMACHINE,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszParentCAMachine;
}
else if (0 == lstrcmpi( wszAttrPARENTCANAME,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszParentCAName;
}
else if (0 == lstrcmpi( wszAttrDBDIR,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszDBDirectory;
}
else if (0 == lstrcmpi( wszAttrLOGDIR,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszLogDirectory;
}
else if (0 == lstrcmpi( wszAttrINTERACTIVESERVICE,
pServerComp->aUnattendParm[i].pwszName) )
{
pServerComp->aUnattendParm[i].ppwszValue =
&pServer->pwszInteractiveService;
}
else
{
hr = E_INVALIDARG;
_JumpError(hr, error, "Internal error, incorrect attr.");
}
}
hr = S_OK;
error:
return hr;
}
HRESULT
certocmRetrieveUnattendedText(
IN WCHAR const *pwszComponent,
IN WCHAR const *pwszSubComponent,
IN PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
SUBCOMP *psc;
WCHAR *pwsz = NULL;
WCHAR *pwszLoad;
HANDLE hUnattendedFile = (*pComp->HelperRoutines.GetInfHandle)(
INFINDEX_UNATTENDED,
pComp->HelperRoutines.OcManagerContext);
psc = TranslateSubComponent(pwszComponent, pwszSubComponent);
if (NULL == psc)
{
hr = E_INVALIDARG;
_JumpError(hr, error, "Internal error, unsupported component");
}
psc->fInstallUnattend = FALSE;
hr = certocmReadInfString(
hUnattendedFile,
pComp->pwszUnattendedFile,
wszCOMPONENTS,
pwszSubComponent,
&pwsz);
CSILOG(hr, IDS_LOG_UNATTENDED_ATTRIBUTE, pwszSubComponent, pwsz, NULL);
_JumpIfError(hr, error, "certocmReadInfString");
if (0 == lstrcmpi(pwsz, L"DEFAULT"))
{
psc->fInstallUnattend = psc->fDefaultInstallUnattend;
}
else
{
psc->fInstallUnattend = 0 == lstrcmpi(pwsz, L"ON");
}
if (psc->fInstallUnattend)
{
DWORD i;
for (i = 0; NULL != psc->aUnattendParm[i].pwszName; i++)
{
pwszLoad = NULL;
hr = certocmReadInfString(
hUnattendedFile,
pComp->pwszUnattendedFile,
psc->pwszSubComponent,
psc->aUnattendParm[i].pwszName,
&pwszLoad);
if (S_OK != hr || NULL == pwszLoad)
{
// allow missing attributes
_PrintErrorStr(
hr,
"Ignoring certocmReadInfString",
psc->aUnattendParm[i].pwszName);
continue;
}
if (0x0 == pwszLoad[0])
{
// if a attribute is given as empty, put it in log
CSILOG(
hr,
IDS_LOG_EMPTY_UNATTENDED_ATTRIBUTE,
psc->aUnattendParm[i].pwszName,
NULL,
NULL);
// continue to take default
LocalFree(pwszLoad);
continue;
}
if (NULL != psc->aUnattendParm[i].ppwszValue &&
NULL != *(psc->aUnattendParm[i].ppwszValue) )
{
// free old or default attributes
LocalFree(*(psc->aUnattendParm[i].ppwszValue));
}
// get new
*(psc->aUnattendParm[i].ppwszValue) = pwszLoad;
CSILOG(
S_OK,
IDS_LOG_UNATTENDED_ATTRIBUTE,
psc->aUnattendParm[i].pwszName,
pwszLoad,
NULL);
}
}
hr = S_OK;
error:
if (NULL != pwsz)
{
LocalFree(pwsz);
}
return hr;
}
HRESULT BuildDistinguishedName(
LPCWSTR pcwszCN,
LPWSTR *ppwszDN)
{
HRESULT hr = S_OK;
LPWSTR pwszDN = NULL;
LPWSTR pwszMachineDN = NULL;
LPCWSTR pcwszCNEqual = L"CN=";
DWORD dwLen = 0;
CSASSERT(pcwszCN);
CSASSERT(ppwszDN);
myGetComputerObjectName(NameFullyQualifiedDN, &pwszMachineDN);
//ignore failure
dwLen = wcslen(pcwszCNEqual)+wcslen(pcwszCN)+1;
if(pwszMachineDN)
{
dwLen += wcslen(pwszMachineDN)+1; // add 1 for comma
}
dwLen *= sizeof(WCHAR);
pwszDN = (LPWSTR)LocalAlloc(LMEM_FIXED, dwLen);
_JumpIfAllocFailed(pwszDN, error);
wcscpy(pwszDN, pcwszCNEqual);
wcscat(pwszDN, pcwszCN);
if (pwszMachineDN)
{
_wcsupr(pwszMachineDN);
WCHAR *pwszFirstDCComponent = wcsstr(pwszMachineDN, L"DC=");
if (pwszFirstDCComponent != NULL)
{
wcscat(pwszDN, L",");
wcscat(pwszDN, pwszFirstDCComponent);
}
}
*ppwszDN = pwszDN;
error:
LOCAL_FREE(pwszMachineDN);
return hr;
}
HRESULT
PrepareServerUnattendedAttributes(
HWND hwnd,
PER_COMPONENT_DATA *pComp,
SUBCOMP *psc)
{
HRESULT hr;
CASERVERSETUPINFO *pServer = (pComp->CA).pServer;
BOOL fUpdateAlg = FALSE;
BOOL fCoInit = FALSE;
BOOL fNotContinue = FALSE;
BOOL fValidDigitString;
WCHAR *pwszConfig = NULL;
// determine CA type
if (NULL != pServer->pwszCAType)
{
// case insensitive
if (0 == lstrcmpi(wszValueENTERPRISEROOT, pServer->pwszCAType))
{
pServer->CAType = ENUM_ENTERPRISE_ROOTCA;
}
else if (0 == lstrcmpi(wszValueENTERPRISESUBORDINATE, pServer->pwszCAType))
{
pServer->CAType = ENUM_ENTERPRISE_SUBCA;
}
else if (0 == lstrcmpi(wszValueSTANDALONEROOT, pServer->pwszCAType))
{
pServer->CAType = ENUM_STANDALONE_ROOTCA;
}
else if (0 == lstrcmpi(wszValueSTANDALONESUBORDINATE, pServer->pwszCAType))
{
pServer->CAType = ENUM_STANDALONE_SUBCA;
}
else
{
// unknown ca type in unattended file
hr = E_INVALIDARG;
CSILOG(hr, IDS_LOG_BAD_CATYPE, pServer->pwszCAType, NULL, NULL);
_JumpError(hr, error, "unknown ca type in unattended file");
}
}
// determine if ca type and DS combination is legal
if (IsEnterpriseCA(pServer->CAType))
{
// enterprise cas require DS
if (!pServer->fUseDS)
{
// no ds, let it failure
hr = E_INVALIDARG;
CSILOG(hr, IDS_LOG_ENTERPRISE_NO_DS, NULL, NULL, NULL);
_JumpError(hr, error, "No DS is available for enterprise CA. Either select standalone or install DS first");
}
}
// build full CA DN
if(EmptyString(pServer->pwszCACommonName))
{
hr = E_INVALIDARG;
CSILOG(hr, IDS_LOG_CA_NAME_REQUIRED, NULL, NULL, NULL);
_JumpError(hr, error, "CA name not specified");
}
if(!EmptyString(pServer->pwszFullCADN))
{
LPWSTR pwszTempFullName;
hr = BuildFullDN(
pServer->pwszCACommonName,
pServer->pwszFullCADN,
&pwszTempFullName);
_JumpIfError(hr, error, "BuildFullDN");
LocalFree(pServer->pwszFullCADN);
pServer->pwszFullCADN = pwszTempFullName;
}
else
{
hr = BuildDistinguishedName(
pServer->pwszCACommonName,
&pServer->pwszFullCADN);
_JumpIfError(hr, error, "BuildDistinguishedName");
}
// determine advance attributes
hr = csiGetProviderTypeFromProviderName(
pServer->pCSPInfo->pwszProvName,
&pServer->pCSPInfo->dwProvType);
_JumpIfError(hr, error, "csiGetProviderTypeFromProviderName");
if (NULL != pServer->pwszHashAlgorithm)
{
// case insensitive
if (0 == lstrcmpi(wszValueSHA1, pServer->pwszHashAlgorithm) )
{
pServer->pHashInfo->idAlg = CALG_SHA1;
}
else if (0 == lstrcmpi(wszValueMD2, pServer->pwszHashAlgorithm) )
{
pServer->pHashInfo->idAlg = CALG_MD2;
}
else if (0 == lstrcmpi(wszValueMD4, pServer->pwszHashAlgorithm) )
{
pServer->pHashInfo->idAlg = CALG_MD4;
}
else if (0 == lstrcmpi(wszValueMD5, pServer->pwszHashAlgorithm) )
{
pServer->pHashInfo->idAlg = CALG_MD5;
}
else
{
// undone, support oid ???
// otherwise convert to calg id
pServer->pHashInfo->idAlg = myWtoI(
pServer->pwszHashAlgorithm,
&fValidDigitString);
}
}
// update algorithm oid anyway (for any changes from csp name, type, hash)
if (NULL != pServer->pszAlgId)
{
// free old
LocalFree(pServer->pszAlgId);
}
hr = myGetSigningOID(
NULL, // hProv
pServer->pCSPInfo->pwszProvName,
pServer->pCSPInfo->dwProvType,
pServer->pHashInfo->idAlg,
&pServer->pszAlgId);
_JumpIfError(hr, error, "myGetSigningOID");
if (NULL != pServer->pwszKeyLength)
{
pServer->dwKeyLength = myWtoI(
pServer->pwszKeyLength,
&fValidDigitString);
}
// Import from PFX file?
if(NULL != pServer->pwszPFXFile)
{
hr = ImportPFXAndUpdateCSPInfo(
hwnd,
pComp);
_JumpIfError(hr, error, "ImportPFXAndUpdateCSPInfo");
}
if (NULL != pServer->pwszKeyContainerName)
{
if (NULL != pServer->pwszKeyLength)
{
CSILOG(hr, IDS_LOG_IGNORE_KEYLENGTH, NULL, NULL, NULL);
_PrintError(0, "Defined key length is ignored because of reusing key");
}
// to revert key container name to common name
if (NULL != pServer->pwszCACommonName)
{
LocalFree(pServer->pwszCACommonName);
pServer->pwszCACommonName = NULL;
}
hr = myRevertSanitizeName(pServer->pwszKeyContainerName,
&pServer->pwszCACommonName);
_JumpIfError(hr, error, "myRevertSanitizeName");
}
// set preserveDB flag
pServer->fPreserveDB = FALSE;
if (NULL != pServer->pwszPreserveDB)
{
// case insensitive
if (0 == lstrcmpi(wszValueYES, pServer->pwszPreserveDB))
{
pServer->fPreserveDB = TRUE;
}
}
// set fInteractiveService flag
pServer->fInteractiveService = FALSE;
if (NULL != pServer->pwszInteractiveService)
{
// case insensitive
if (0 == lstrcmpi(wszValueYES, pServer->pwszInteractiveService))
{
pServer->fInteractiveService = TRUE;
}
}
// ca idinfo attributes
// Reuse cert?
if (NULL!=pServer->pwszUseExistingCert &&
0==lstrcmpi(wszValueYES, pServer->pwszUseExistingCert))
{
//
// User wants to reuse an existing cert
//
// must have a key container name to reuse a cert
if (NULL==pServer->pwszKeyContainerName) {
hr=E_INVALIDARG;
CSILOG(hr, IDS_LOG_REUSE_CERT_NO_REUSE_KEY, NULL, NULL, NULL);
_JumpError(hr, error, "cannot reuse ca cert without reuse key");
}
// see if a matching certificate exists
CERT_CONTEXT const * pccExistingCert;
hr = FindCertificateByKey(pServer, &pccExistingCert);
if (S_OK != hr)
{
CSILOG(hr, IDS_LOG_NO_CERT, NULL, NULL, NULL);
_JumpError(hr, error, "FindCertificateByKey");
}
// use the matching cert
hr = SetExistingCertToUse(pServer, pccExistingCert);
_JumpIfError(hr, error, "SetExistingCertToUse");
} else {
//
// User does not want to reuse an existing cert
// Get the information that we would have pulled from the cert
//
// must reuse an existing cert to preserve the DB
if (pServer->fPreserveDB){
hr = E_INVALIDARG;
CSILOG(hr, IDS_LOG_REUSE_DB_WITHOUT_REUSE_CERT, NULL, NULL, NULL);
_JumpError(hr, error, "cannot preserve DB if don't reuse both key and ca cert");
}
// determine extended idinfo attributes
// validity period
DWORD dwValidityPeriodCount;
ENUM_PERIOD enumValidityPeriod = ENUM_PERIOD_INVALID;
BOOL fSwap;
if (NULL != pServer->pwszValidityPeriodCount ||
NULL != pServer->pwszValidityPeriodString)
{
hr = myInfGetValidityPeriod(
NULL, // hInf
pServer->pwszValidityPeriodCount,
pServer->pwszValidityPeriodString,
&dwValidityPeriodCount,
&enumValidityPeriod,
&fSwap);
_JumpIfError(hr, error, "myGetValidityPeriod");
if (ENUM_PERIOD_INVALID != enumValidityPeriod)
{
pServer->enumValidityPeriod = enumValidityPeriod;
}
if (0 != dwValidityPeriodCount)
{
pServer->dwValidityPeriodCount = dwValidityPeriodCount;
}
}
if (!IsValidPeriod(pServer))
{
hr = E_INVALIDARG;
CSILOG(
hr,
IDS_LOG_BAD_VALIDITY_PERIOD_COUNT,
pServer->pwszValidityPeriodCount,
NULL,
&pServer->dwValidityPeriodCount);
_JumpError(hr, error, "validity period count");
}
pServer->NotAfter = pServer->NotBefore;
myMakeExprDateTime(
&pServer->NotAfter,
pServer->dwValidityPeriodCount,
pServer->enumValidityPeriod);
//if swap, swap pointer before validation
if (fSwap)
{
WCHAR *pwszTemp = pServer->pwszValidityPeriodCount;
pServer->pwszValidityPeriodCount = pServer->pwszValidityPeriodString;
pServer->pwszValidityPeriodString = pwszTemp;
}
//the following WizardPageValidation requires
//pServer->pwszValidityPeriodCount so load from count before validation
if (NULL == pServer->pwszValidityPeriodCount)
{
WCHAR wszCount[10]; //should be enough
wsprintf(wszCount, L"%d", pServer->dwValidityPeriodCount);
pServer->pwszValidityPeriodCount = (WCHAR*)LocalAlloc(LMEM_FIXED,
(wcslen(wszCount) + 1) * sizeof(WCHAR));
_JumpIfOutOfMemory(hr, error, pServer->pwszValidityPeriodCount);
wcscpy(pServer->pwszValidityPeriodCount, wszCount);
}
// hook with g_aIdPageString
hr = HookIdInfoPageStrings(
NULL, // hDlg
g_aIdPageString,
pServer);
_JumpIfError(hr, error, "HookIdInfoPageStrings");
hr = WizardPageValidation(
pComp->hInstance,
pComp->fUnattended,
NULL,
g_aIdPageString);
_JumpIfError(hr, error, "WizardPageValidation");
// make sure no invalid rdn characters
if (IsAnyInvalidRDN(NULL, pComp))
{
hr = E_INVALIDARG;
CSILOG(
hr,
IDS_LOG_BAD_OR_MISSING_CANAME,
pServer->pwszCACommonName,
NULL,
NULL);
_JumpError(hr, error, "Invalid RDN characters");
}
} // <- End if reuse/not-reuse cert
// determine CA name
if (NULL != pServer->pwszSanitizedName)
{
// free old
LocalFree(pServer->pwszSanitizedName);
pServer->pwszSanitizedName = NULL;
}
// derive ca name from common name
hr = mySanitizeName(
pServer->pwszCACommonName,
&(pServer->pwszSanitizedName) );
_JumpIfError(hr, error, "mySanitizeName");
if (MAX_PATH <= wcslen(pServer->pwszSanitizedName) + cwcSUFFIXMAX)
{
hr = CO_E_PATHTOOLONG;
CSILOG(
hr,
IDS_LOG_CANAME_TOO_LONG,
pServer->pwszSanitizedName,
NULL,
NULL);
_JumpErrorStr(hr, error, "CA Name", pServer->pwszSanitizedName);
}
// store attributes
hr = StorePageValidation(NULL, pComp, &fNotContinue);
_JumpIfError(hr, error, "StorePageValidation");
if (fNotContinue)
{
hr = S_FALSE;
_JumpError(hr, error, "StorePageValidation failed");
}
// ca cert file name
if (NULL != pServer->pwszCACertFile)
{
// free old one
LocalFree(pServer->pwszCACertFile);
}
hr = csiBuildCACertFileName(
pComp->hInstance,
hwnd,
pComp->fUnattended,
pServer->pwszSharedFolder,
pServer->pwszSanitizedName,
L".crt",
0, // CANAMEIDTOICERT(pServer->dwCertNameId),
&pServer->pwszCACertFile);
if (S_OK != hr)
{
CSILOG(
hr,
IDS_LOG_PATH_CAFILE_BUILD_FAIL,
pServer->pwszSharedFolder, //likely by invalid shared folder path
NULL,
NULL);
_JumpError(hr, error, "csiBuildFileName");
}
// validate path length
if (MAX_PATH <= wcslen(pServer->pwszCACertFile) + cwcSUFFIXMAX)
{
hr = CO_E_PATHTOOLONG;
CSILOG(
hr,
IDS_LOG_PATH_TOO_LONG_CANAME,
pServer->pwszCACertFile,
NULL,
NULL);
_JumpErrorStr(hr, error, "csiBuildFileName", pServer->pwszCACertFile);
}
// request attributes
// if subordinate ca, determine online or request file
if (IsSubordinateCA(pServer->CAType))
{
// default
pServer->fSaveRequestAsFile = TRUE;
if (NULL != pServer->pwszParentCAMachine)
{
// online case
pServer->fSaveRequestAsFile = FALSE;
hr = CoInitialize(NULL);
if (S_OK != hr && S_FALSE != hr)
{
_JumpError(hr, error, "CoInitialize");
}
fCoInit = TRUE;
if (NULL != pServer->pwszParentCAName)
{
// answer file provides both machine and ca names
hr = myFormConfigString(
pServer->pwszParentCAMachine,
pServer->pwszParentCAName,
&pwszConfig);
_JumpIfError(hr, error, "myFormConfigString");
// answer file has complete config string, try to ping it
hr = myPingCertSrv(pwszConfig, NULL, NULL, NULL, NULL, NULL, NULL);
if (S_OK != hr)
{
// can't finish without pingable ca
CSILOG(
hr,
IDS_LOG_PING_PARENT_FAIL,
pwszConfig,
NULL,
NULL);
_JumpErrorStr(hr, error, "myPingCertSrv", pwszConfig);
}
}
else
{
WCHAR *pwszzCAList = NULL;
// answer file only has machine name, try to get ca name
hr = myPingCertSrv(
pServer->pwszParentCAMachine,
NULL,
&pwszzCAList,
NULL,
NULL,
NULL,
NULL);
if (S_OK != hr)
{
// can't finish without pingable ca
CSILOG(
hr,
IDS_LOG_PING_PARENT_FAIL,
pServer->pwszParentCAMachine,
NULL,
NULL);
_JumpErrorStr(hr, error, "myPingCertSrv",
pServer->pwszParentCAMachine);
}
// pick the first one as the choice
pServer->pwszParentCAName = pwszzCAList;
}
}
if (NULL == pServer->pwszRequestFile)
{
// in any case, construct request file name if not defined
hr = BuildRequestFileName(
pServer->pwszCACertFile,
&pServer->pwszRequestFile);
_JumpIfError(hr, error, "BuildRequestFileName");
// make sure in limit
if (MAX_PATH <= wcslen(pServer->pwszRequestFile) + cwcSUFFIXMAX)
{
hr = CO_E_PATHTOOLONG;
CSILOG(
hr,
IDS_LOG_REQUEST_FILE_TOO_LONG,
pServer->pwszRequestFile,
NULL,
NULL);
_JumpErrorStr(hr, error, "Request File", pServer->pwszRequestFile);
}
}
}
// other attributes
if(pServer->fUseDS)
{
pServer->dwRevocationFlags = REVEXT_DEFAULT_DS;
}
else
{
pServer->dwRevocationFlags = REVEXT_DEFAULT_NODS;
}
hr = S_OK;
error:
if (fCoInit)
{
CoUninitialize();
}
if (NULL!=pwszConfig) {
LocalFree(pwszConfig);
}
CSILOG(hr, IDS_LOG_SERVER_UNATTENDED_ATTRIBUTES, NULL, NULL, NULL);
return hr;
}
HRESULT
PrepareClientUnattendedAttributes(
PER_COMPONENT_DATA *pComp,
SUBCOMP *psc)
{
HRESULT hr;
CAWEBCLIENTSETUPINFO *pClient = pComp->CA.pClient;
WCHAR *pwszConfig = NULL;
CAINFO *pCAInfo = NULL;
BOOL fCoInit = FALSE;
WCHAR * pwszDnsName = NULL;
if ((IS_CLIENT_INSTALL & pComp->dwInstallStatus) &&
!(IS_SERVER_INSTALL & pComp->dwInstallStatus))
{
// no extra setting and converting
if (NULL == pClient->pwszWebCAMachine)
{
hr = E_INVALIDARG;
CSILOG(hr, IDS_LOG_CA_MACHINE_REQUIRED, NULL, NULL, NULL);
_JumpError(hr, error, "ca machine name is required");
}
hr = CoInitialize(NULL);
if (S_OK != hr && S_FALSE != hr)
{
_JumpError(hr, error, "CoInitialize");
}
fCoInit = TRUE;
if (NULL == pClient->pwszWebCAName)
{
WCHAR *pwszzCAList = NULL;
// answer file only has machine name, try to get ca name
hr = myPingCertSrv(
pClient->pwszWebCAMachine,
NULL,
&pwszzCAList,
NULL,
NULL,
NULL,
NULL);
if (S_OK != hr)
{
// can't finish without pingable ca
CSILOG(
hr,
IDS_LOG_PING_PARENT_FAIL,
pClient->pwszWebCAMachine,
NULL,
NULL);
_JumpErrorStr(hr, error, "myPingCertSrv",
pClient->pwszWebCAMachine);
}
// pick the first one as the choice
pClient->pwszWebCAName = pwszzCAList;
}
hr = mySanitizeName(pClient->pwszWebCAName, &pClient->pwszSanitizedWebCAName);
_JumpIfError(hr, error, "mySanitizeName");
// build the config string so we can ping the parent CA
hr = myFormConfigString(
pClient->pwszWebCAMachine,
pClient->pwszWebCAName,
&pwszConfig);
_JumpIfError(hr, error, "myFormConfigString");
// ping the CA to retrieve the CA type and DNS name.
hr = myPingCertSrv(pwszConfig, NULL, NULL, NULL, &pCAInfo, NULL, &pwszDnsName);
if (S_OK != hr)
{
// can't finish without pingable ca
CSILOG(
hr,
IDS_LOG_PING_PARENT_FAIL,
pwszConfig,
NULL,
NULL);
_JumpErrorStr(hr, error, "myPingCertSrv", pwszConfig);
}
pClient->WebCAType = pCAInfo->CAType;
// use the FQDN if available
if (NULL!=pwszDnsName) {
LocalFree(pClient->pwszWebCAMachine);
pClient->pwszWebCAMachine=pwszDnsName;
}
}
hr = S_OK;
error:
if (NULL!=pwszConfig)
{
LocalFree(pwszConfig);
}
if (NULL != pCAInfo)
{
LocalFree(pCAInfo);
}
if (fCoInit)
{
CoUninitialize();
}
CSILOG(hr, IDS_LOG_CLIENT_UNATTENDED_ATTRIBUTES, NULL, NULL, NULL);
return hr;
}
HRESULT
PrepareUnattendedAttributes(
IN HWND hwnd,
IN WCHAR const *pwszComponent,
IN WCHAR const *pwszSubComponent,
IN PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
SUBCOMP *psc = TranslateSubComponent(pwszComponent, pwszSubComponent);
if (NULL == psc)
{
hr = E_INVALIDARG;
_JumpError(hr, error, "Internal error, unsupported component");
}
switch (psc->cscSubComponent)
{
case cscServer:
hr = PrepareServerUnattendedAttributes(hwnd, pComp, psc);
_JumpIfError(hr, error, "PrepareServerUnattendedAttributes");
break;
case cscClient:
hr = PrepareClientUnattendedAttributes(pComp, psc);
_JumpIfError(hr, error, "PrepareClientUnattendedAttributes");
break;
default:
hr = E_INVALIDARG;
_JumpError(hr, error, "Internal error, unsupported component");
}
hr = S_OK;
error:
return hr;
}