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.
1168 lines
37 KiB
1168 lines
37 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 == LSTRCMPIS(
|
|
pClientComp->aUnattendParm[i].pwszName,
|
|
wszAttrCAMACHINE))
|
|
{
|
|
pClientComp->aUnattendParm[i].ppwszValue =
|
|
&pClient->pwszWebCAMachine;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pClientComp->aUnattendParm[i].pwszName,
|
|
wszAttrCANAME))
|
|
{
|
|
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 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrCATYPE))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pwszCAType;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrNAME))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pwszCACommonName;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrCADISTINGUISHEDNAME))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pwszFullCADN;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrORGANIZATION))
|
|
{
|
|
// dead
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrORGANIZATIONUNIT))
|
|
{
|
|
// dead
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrLOCALITY))
|
|
{
|
|
// dead
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrSTATE))
|
|
{
|
|
// dead
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrCOUNTRY))
|
|
{
|
|
// dead
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrDESCRIPTION))
|
|
{
|
|
// dead
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrEMAIL))
|
|
{
|
|
// dead
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrVALIDITYPERIODCOUNT))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pwszValidityPeriodCount;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrVALIDITYPERIODSTRING))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pwszValidityPeriodString;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrSHAREDFOLDER))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pwszSharedFolder;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrREQUESTFILE))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pwszRequestFile;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrCSPPROVIDER))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pCSPInfo->pwszProvName;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrHASHALGORITHM))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pwszHashAlgorithm;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrKEYLENGTH))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pwszKeyLength;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrEXISTINGKEY))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pwszKeyContainerName;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrUSEEXISTINGCERT))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pwszUseExistingCert;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrPRESERVEDB))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pwszPreserveDB;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrPARENTCAMACHINE))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pwszParentCAMachine;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrPARENTCANAME))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pwszParentCAName;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrDBDIR))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pwszDBDirectory;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrLOGDIR))
|
|
{
|
|
pServerComp->aUnattendParm[i].ppwszValue =
|
|
&pServer->pwszLogDirectory;
|
|
}
|
|
else if (0 == LSTRCMPIS(
|
|
pServerComp->aUnattendParm[i].pwszName,
|
|
wszAttrINTERACTIVESERVICE))
|
|
{
|
|
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,
|
|
wszCOMPONENTS,
|
|
pwszSubComponent,
|
|
&pwsz);
|
|
CSILOG(hr, IDS_LOG_UNATTENDED_ATTRIBUTE, pwszSubComponent, pwsz, NULL);
|
|
_JumpIfError(hr, error, "certocmReadInfString");
|
|
|
|
if (0 == LSTRCMPIS(pwsz, L"DEFAULT"))
|
|
{
|
|
psc->fInstallUnattend = psc->fDefaultInstallUnattend;
|
|
}
|
|
else
|
|
{
|
|
psc->fInstallUnattend = 0 == LSTRCMPIS(pwsz, L"ON");
|
|
}
|
|
|
|
if (psc->fInstallUnattend)
|
|
{
|
|
DWORD i;
|
|
|
|
for (i = 0; NULL != psc->aUnattendParm[i].pwszName; i++)
|
|
{
|
|
pwszLoad = NULL;
|
|
hr = certocmReadInfString(
|
|
hUnattendedFile,
|
|
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)
|
|
{
|
|
HRESULT hr;
|
|
CASERVERSETUPINFO *pServer = (pComp->CA).pServer;
|
|
BOOL fCoInit = FALSE;
|
|
BOOL fNotContinue = FALSE;
|
|
BOOL fValidDigitString;
|
|
|
|
WCHAR *pwszConfig = NULL;
|
|
|
|
// determine CA type
|
|
if (NULL != pServer->pwszCAType)
|
|
{
|
|
// case insensitive
|
|
if (0 == LSTRCMPIS(pServer->pwszCAType, wszValueENTERPRISEROOT))
|
|
{
|
|
pServer->CAType = ENUM_ENTERPRISE_ROOTCA;
|
|
}
|
|
else if (0 == LSTRCMPIS(pServer->pwszCAType, wszValueENTERPRISESUBORDINATE))
|
|
{
|
|
pServer->CAType = ENUM_ENTERPRISE_SUBCA;
|
|
}
|
|
else if (0 == LSTRCMPIS(pServer->pwszCAType, wszValueSTANDALONEROOT))
|
|
{
|
|
pServer->CAType = ENUM_STANDALONE_ROOTCA;
|
|
}
|
|
else if (0 == LSTRCMPIS(pServer->pwszCAType, wszValueSTANDALONESUBORDINATE))
|
|
{
|
|
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 == LSTRCMPIS(pServer->pwszHashAlgorithm, wszValueSHA1))
|
|
{
|
|
pServer->pHashInfo->idAlg = CALG_SHA1;
|
|
}
|
|
else if (0 == LSTRCMPIS(pServer->pwszHashAlgorithm, wszValueMD2))
|
|
{
|
|
pServer->pHashInfo->idAlg = CALG_MD2;
|
|
}
|
|
else if (0 == LSTRCMPIS(pServer->pwszHashAlgorithm, wszValueMD4))
|
|
{
|
|
pServer->pHashInfo->idAlg = CALG_MD4;
|
|
}
|
|
else if (0 == LSTRCMPIS(pServer->pwszHashAlgorithm, wszValueMD5))
|
|
{
|
|
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 == LSTRCMPIS(pServer->pwszPreserveDB, wszValueYES))
|
|
{
|
|
pServer->fPreserveDB = TRUE;
|
|
}
|
|
}
|
|
|
|
// set fInteractiveService flag
|
|
pServer->fInteractiveService = FALSE;
|
|
if (NULL != pServer->pwszInteractiveService)
|
|
{
|
|
// case insensitive
|
|
if (0 == LSTRCMPIS(pServer->pwszInteractiveService, wszValueYES))
|
|
{
|
|
pServer->fInteractiveService = TRUE;
|
|
}
|
|
}
|
|
|
|
// ca idinfo attributes
|
|
|
|
// Reuse cert?
|
|
if (NULL!=pServer->pwszUseExistingCert &&
|
|
0==LSTRCMPIS(pServer->pwszUseExistingCert, wszValueYES))
|
|
{
|
|
//
|
|
// 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 = FALSE;
|
|
|
|
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(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)
|
|
{
|
|
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);
|
|
_JumpIfError(hr, error, "PrepareServerUnattendedAttributes");
|
|
break;
|
|
|
|
case cscClient:
|
|
hr = PrepareClientUnattendedAttributes(pComp);
|
|
_JumpIfError(hr, error, "PrepareClientUnattendedAttributes");
|
|
break;
|
|
|
|
default:
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "Internal error, unsupported component");
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return hr;
|
|
}
|