//+------------------------------------------------------------------------- // // 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 #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; }