DWORD VMCARestServiceStartup( VOID ) { DWORD dwError = 0; dwError = _VMCAHttpServiceStartup(); BAIL_ON_VMREST_ERROR(dwError); dwError = _VMCAHttpsServiceStartup(); //soft fail if (dwError != 0) { VMCA_LOG_ERROR("%s: failure while starting HTTPS service(expected before promote), error: %d", __FUNCTION__, dwError); dwError = 0; } cleanup: return dwError; error: VMCA_LOG_ERROR("%s: failure while starting REST service, error: %d", __FUNCTION__, dwError); goto cleanup; }
DWORD VMCARestServerInit( VOID ) { DWORD dwError = 0; MODULE_REG_MAP stRegMap[] = { //{"endpoint", VMCARestFunctionModule}, {NULL, NULL} }; /* * We can use the same REST_API_SPEC for both HTTP and HTTPS * if the rest init code refers to common API definitions */ dwError = coapi_load_from_file(REST_API_SPEC, &gpVMCARestApiDef); BAIL_ON_VMCA_ERROR(dwError); dwError = coapi_map_api_impl(gpVMCARestApiDef, stRegMap); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAOpensslInit(); BAIL_ON_VMCA_ERROR(dwError); dwError = _VMCARestServerInitHTTPS(); if (dwError != 0) { /* * Before promoting lightwave node, obtaining cert from VECS will fail which is expected * hence treat it as soft fail */ VMCA_LOG_WARNING( "VmRESTServerInit: HTTPS port init failed with error %d, (failure is expected before promote)", dwError); dwError = 0; } cleanup: return dwError; error: if (VMCARestServerStop() == 0) { VMCARestServerShutdown(); } VMCA_LOG_ERROR( "%s failed, error (%d)", __FUNCTION__, dwError); goto cleanup; }
static DWORD VMCASrvUpdateRootCerts( PVMCA_DIR_SYNC_PARAMS pDirSyncParams, PBOOLEAN pbSynced ) { DWORD dwError = 0; PVMCA_X509_CA pCA = NULL; PSTR pszAccount = NULL; PSTR pszPassword = NULL; PSTR pszDomainName = NULL; PSTR pszCAContainerDN = NULL; PSTR pszCertificate = NULL; PSTR pszCRL = NULL; X509_CRL* pCrl = NULL; DWORD dwCount = 0; DWORD dwIndex = 0; PVMCA_LDAP_CONTEXT pContext = NULL; PSTR pszUPN = NULL; dwError = VMCASrvValidateCA(); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCASrvGetCA(&pCA); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCASrvGetMachineAccountInfoA( &pszAccount, &pszDomainName, &pszPassword); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAAllocateStringPrintfA( &pszUPN, "%s@%s", pszAccount, pszDomainName); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCALdapConnect( "localhost", 0, /* use default port */ pszUPN, pszPassword, &pContext); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAGetDSERootAttribute( pContext, "configurationNamingContext", &pszCAContainerDN); BAIL_ON_VMCA_ERROR(dwError); dwError = VmcaSrvReGenCRL( &pCrl ); BAIL_ON_VMCA_ERROR (dwError); dwError = VMCACRLToPEM( pCrl, &pszCRL ); BAIL_ON_VMCA_ERROR (dwError); dwCount = sk_X509_num(pCA->skCAChain); for (; dwIndex <dwCount; dwIndex++) { X509 *pCert = sk_X509_value( pCA->skCAChain, dwIndex ); dwError = VMCAUpdatePkiCAAttribute( pContext, pszCAContainerDN, pCert ); BAIL_ON_VMCA_ERROR(dwError); } dwError = VMCAUpdateCrlCAAttribute( pContext, pszCAContainerDN, pszCRL ); BAIL_ON_VMCA_ERROR (dwError); *pbSynced = TRUE; cleanup: VMCA_SAFE_FREE_STRINGA(pszUPN); VMCA_SAFE_FREE_STRINGA(pszDomainName); VMCA_SAFE_FREE_STRINGA(pszCertificate); VMCA_SAFE_FREE_STRINGA(pszAccount); VMCA_SAFE_FREE_STRINGA(pszPassword); VMCA_SAFE_FREE_STRINGA(pszCRL); if (pContext) { VMCALdapClose(pContext); } if (pCA) { VMCAReleaseCA(pCA); } return dwError; error: *pbSynced = FALSE; VMCA_LOG_ERROR("Failed to update root certs due to error [%u]", dwError); // TODO : Check specific errors dwError = 0; goto cleanup; }
static PVOID VMCASrvDirSyncThrFunc( PVOID pData ) { DWORD dwError = 0; PVMCA_THREAD_DATA pThrData = (PVMCA_THREAD_DATA)pData; PVMCA_DIR_SYNC_PARAMS pDirSyncParams = NULL; BOOLEAN bShutdown = FALSE; VMCA_LOG_INFO("Directory sync thread starting"); pDirSyncParams = VMCASrvAcquireDirSyncParams( (PVMCA_DIR_SYNC_PARAMS)pThrData->pData); if (!pDirSyncParams) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMCA_ERROR(dwError); } while (!bShutdown) { BOOLEAN bSynced = FALSE; dwError = VMCACheckThreadShutdown(pThrData, &bShutdown); BAIL_ON_VMCA_ERROR(dwError); if (!bShutdown) { dwError = VMCASrvUpdateRootCerts(pDirSyncParams, &bSynced); BAIL_ON_VMCA_ERROR(dwError); } dwError = VMCACheckThreadShutdown(pThrData, &bShutdown); BAIL_ON_VMCA_ERROR(dwError); if (!bShutdown) { DWORD dwIntervalSecs = 60; // wait a minute on sync failure if (bSynced) { dwError = VMCASrvGetDirSyncNotifyInterval( pDirSyncParams, &dwIntervalSecs); BAIL_ON_VMCA_ERROR(dwError); } dwError = VMCAWaitNotifyThread(pThrData, dwIntervalSecs); if (dwError == ETIMEDOUT) { dwError = 0; } BAIL_ON_VMCA_ERROR(dwError); } } cleanup: if (pDirSyncParams) { VMCASrvReleaseDirSyncParams(pDirSyncParams); } VMCA_LOG_INFO("Directory sync thread exiting"); return NULL; error: VMCA_LOG_ERROR("Directory sync thread exiting due to error [%u]", dwError); goto cleanup; }
DWORD VMCAPolicySNLoad( json_t *pJsonRules, PVMCA_POLICY pPolicy ) { DWORD dwError = 0; json_t *pJsonRulesMatch = NULL; json_t *pJsonRulesValidate = NULL; VMCA_POLICY_RULES rules = { 0 }; if (!pJsonRules || !pPolicy) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMCA_ERROR(dwError); } if (!(pJsonRulesMatch = json_object_get(pJsonRules, "match"))) { VMCA_LOG_ERROR( "[%s,%d] Failed to get SN policy match rule from config (%s)", __FUNCTION__, __LINE__, VMCA_POLICY_FILE_PATH); dwError = VMCA_JSON_PARSE_ERROR; BAIL_ON_JSON_PARSE_ERROR(dwError); } if (!(pJsonRulesValidate = json_object_get(pJsonRules, "validate"))) { VMCA_LOG_ERROR( "[%s,%d] SN policy must have either validate rule or action rule in config (%s)", __FUNCTION__, __LINE__, VMCA_POLICY_FILE_PATH); dwError = VMCA_JSON_PARSE_ERROR; BAIL_ON_JSON_PARSE_ERROR(dwError); } dwError = VMCAPolicySNMatchOperationParse( pJsonRulesMatch, &rules.SN.pMatch); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAPolicySNValidateOperationParse( pJsonRulesValidate, &rules.SN.dwValidateLen, &rules.SN.ppValidate); BAIL_ON_VMCA_ERROR(dwError); rules.SN.bEnabled = TRUE; pPolicy->Rules = rules; cleanup: return dwError; error: VMCAPolicySNFree(&rules); if (pPolicy) { pPolicy->Rules.SN.bEnabled = FALSE; VMCAPolicySNOperationFree(pPolicy->Rules.SN.pMatch); VMCAPolicySNOperationArrayFree(pPolicy->Rules.SN.ppValidate, pPolicy->Rules.SN.dwValidateLen); pPolicy->Rules.SN.dwValidateLen = 0; } goto cleanup; }
static DWORD VMCAPolicySNValidateOperationParse( json_t *pJsonRule, PDWORD pdwOperationsLen, PVMCA_SNPOLICY_OPERATION **pppOperations ) { DWORD dwError = 0; DWORD dwIdx = 0; PCSTR pcszDataTemp = NULL; PCSTR pcszWithTemp = NULL; size_t szArrayLen = 0; json_t *pJsonTemp = NULL; json_t *pJsonDataTemp = NULL; json_t *pJsonWithTemp = NULL; PVMCA_SNPOLICY_OPERATION *ppOperations = NULL; if (!pJsonRule || !pppOperations) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMCA_ERROR(dwError); } if (!json_is_array(pJsonRule)) { VMCA_LOG_ERROR( "[%s,%d] SN policy validate rule in config (%s) must be an array", __FUNCTION__, __LINE__, VMCA_POLICY_FILE_PATH); dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMCA_ERROR(dwError); } szArrayLen = json_array_size(pJsonRule); if (szArrayLen < 1) { VMCA_LOG_ERROR( "[%s,%d] SN policy rule validate in config (%s) must be an array with at least 1 object", __FUNCTION__, __LINE__, VMCA_POLICY_FILE_PATH); dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMCA_ERROR(dwError); } dwError = VMCAAllocateMemory( sizeof(PVMCA_SNPOLICY_OPERATION) * (DWORD)szArrayLen, (PVOID *)&ppOperations); BAIL_ON_VMCA_ERROR(dwError); json_array_foreach(pJsonRule, dwIdx, pJsonTemp) { if (!(pJsonDataTemp = json_object_get(pJsonTemp, "data"))) { VMCA_LOG_ERROR( "[%s,%d] SN policy rule validate in config (%s) must have \"data\" clause", __FUNCTION__, __LINE__, VMCA_POLICY_FILE_PATH); dwError = VMCA_JSON_PARSE_ERROR; BAIL_ON_JSON_PARSE_ERROR(dwError); } if (!(pJsonWithTemp = json_object_get(pJsonTemp, "with"))) { VMCA_LOG_ERROR( "[%s,%d] SN policy validate rule in config (%s) must have \"with\" clause", __FUNCTION__, __LINE__, VMCA_POLICY_FILE_PATH); dwError = VMCA_JSON_PARSE_ERROR; BAIL_ON_JSON_PARSE_ERROR(dwError); } pcszDataTemp = json_string_value(pJsonDataTemp); if (IsNullOrEmptyString(pcszDataTemp)) { VMCA_LOG_ERROR( "[%s,%d] SN policy validate rule in config (%s) cannot have empty \"data\" clause", __FUNCTION__, __LINE__, VMCA_POLICY_FILE_PATH); dwError = VMCA_POLICY_CONFIG_ERROR; BAIL_ON_VMCA_ERROR(dwError); } if (VMCAStringCompareA(pcszDataTemp, VMCA_POLICY_REQ_CSR_SUBJ_ORGS, TRUE)) { VMCA_LOG_ERROR( "[%s,%d] Unknown SN policy validate rule \"data\" value. (%s)", __FUNCTION__, __LINE__, pcszDataTemp); dwError = VMCA_POLICY_CONFIG_ERROR; BAIL_ON_VMCA_ERROR(dwError); } pcszWithTemp = json_string_value(pJsonWithTemp); if (IsNullOrEmptyString(pcszWithTemp)) { VMCA_LOG_ERROR( "[%s,%d] SN policy validate rule in config (%s) cannot have empty \"with\" clause", __FUNCTION__, __LINE__, VMCA_POLICY_FILE_PATH); dwError = VMCA_POLICY_CONFIG_ERROR; BAIL_ON_VMCA_ERROR(dwError); } if (VMCAStringCompareA(pcszWithTemp, VMCA_POLICY_REQ_UPN_RDN, TRUE)) { VMCA_LOG_ERROR( "[%s,%d] Unknown SN policy validate rule \"with\" value. (%s)", __FUNCTION__, __LINE__, pcszWithTemp); dwError = VMCA_POLICY_CONFIG_ERROR; BAIL_ON_VMCA_ERROR(dwError); } dwError = VMCAAllocateMemory( sizeof(VMCA_SNPOLICY_OPERATION), (PVOID *)&ppOperations[dwIdx]); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAAllocateStringA( pcszWithTemp, &ppOperations[dwIdx]->pszWith); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAAllocateStringA( pcszDataTemp, &ppOperations[dwIdx]->pszData); BAIL_ON_VMCA_ERROR(dwError); } *pdwOperationsLen = (DWORD)szArrayLen; *pppOperations = ppOperations; cleanup: return dwError; error: VMCAPolicySNOperationArrayFree(ppOperations, (DWORD)szArrayLen); if (pppOperations) { *pppOperations = NULL; } goto cleanup; }
static DWORD VMCAPolicySNMatchOperationParse( json_t *pJsonRule, PVMCA_SNPOLICY_OPERATION *ppOperation ) { DWORD dwError = 0; PCSTR pcszDataTemp = NULL; PCSTR pcszConditionTemp = NULL; PCSTR pcszWithTemp = NULL; json_t *pJsonDataTemp = NULL; json_t *pJsonWithTemp = NULL; json_t *pJsonConditionTemp = NULL; PVMCA_SNPOLICY_OPERATION pOperation = NULL; if (!pJsonRule || !ppOperation) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMCA_ERROR(dwError); } if (!(pJsonDataTemp = json_object_get(pJsonRule, "data"))) { VMCA_LOG_ERROR( "[%s,%d] SN policy match rule in config (%s) must have \"data\" clause", __FUNCTION__, __LINE__, VMCA_POLICY_FILE_PATH); dwError = VMCA_JSON_PARSE_ERROR; BAIL_ON_JSON_PARSE_ERROR(dwError); } if (!(pJsonConditionTemp = json_object_get(pJsonRule, "condition"))) { VMCA_LOG_ERROR( "[%s,%d] SN policy match rule in config (%s) must have \"condition\" clause", __FUNCTION__, __LINE__, VMCA_POLICY_FILE_PATH); dwError = VMCA_JSON_PARSE_ERROR; BAIL_ON_JSON_PARSE_ERROR(dwError); } if (!(pJsonWithTemp = json_object_get(pJsonRule, "with"))) { VMCA_LOG_ERROR( "[%s,%d] SN policy match rule in config (%s) must have \"with\" clause", __FUNCTION__, __LINE__, VMCA_POLICY_FILE_PATH); dwError = VMCA_JSON_PARSE_ERROR; BAIL_ON_JSON_PARSE_ERROR(dwError); } pcszDataTemp = json_string_value(pJsonDataTemp); if (IsNullOrEmptyString(pcszDataTemp)) { VMCA_LOG_ERROR( "[%s,%d] SN policy match rule in config (%s) cannot have empty \"data\" clause", __FUNCTION__, __LINE__, VMCA_POLICY_FILE_PATH); dwError = VMCA_POLICY_CONFIG_ERROR; BAIL_ON_VMCA_ERROR(dwError); } if (VMCAStringCompareA(pcszDataTemp, VMCA_POLICY_REQ_UPN_DN, TRUE)) { VMCA_LOG_ERROR( "[%s,%d] Unknown SN policy match rule \"data\" value. (%s)", __FUNCTION__, __LINE__, pcszDataTemp); dwError = VMCA_POLICY_CONFIG_ERROR; BAIL_ON_VMCA_ERROR(dwError); } pcszConditionTemp = json_string_value(pJsonConditionTemp); if (IsNullOrEmptyString(pcszConditionTemp)) { VMCA_LOG_ERROR( "[%s,%d] SN policy match rule in config (%s) cannot have empty \"condition\" clause", __FUNCTION__, __LINE__, VMCA_POLICY_FILE_PATH); dwError = VMCA_POLICY_CONFIG_ERROR; BAIL_ON_VMCA_ERROR(dwError); } if (VMCAStringCompareA(pcszConditionTemp, VMCA_POLICY_COND_BEGINS, TRUE)) { VMCA_LOG_ERROR( "[%s,%d] Unknown SN policy match rule \"condition\" value. (%s)", __FUNCTION__, __LINE__, pcszConditionTemp); dwError = VMCA_POLICY_CONFIG_ERROR; BAIL_ON_VMCA_ERROR(dwError); } pcszWithTemp = json_string_value(pJsonWithTemp); if (IsNullOrEmptyString(pcszWithTemp)) { VMCA_LOG_ERROR( "[%s,%d] SN policy match rule in config (%s) cannot have empty \"with\" clause", __FUNCTION__, __LINE__, VMCA_POLICY_FILE_PATH); dwError = VMCA_POLICY_CONFIG_ERROR; BAIL_ON_VMCA_ERROR(dwError); } dwError = VMCAAllocateMemory( sizeof(VMCA_SNPOLICY_OPERATION), (PVOID *)&pOperation); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAAllocateStringA( pcszWithTemp, &pOperation->pszWith); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAAllocateStringA( pcszConditionTemp, &pOperation->pszCondition); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAAllocateStringA( pcszDataTemp, &pOperation->pszData); BAIL_ON_VMCA_ERROR(dwError); *ppOperation = pOperation; cleanup: return dwError; error: VMCAPolicySNOperationFree(pOperation); if (ppOperation) { *ppOperation = NULL; } goto cleanup; }
static DWORD _VMCAGetSSLCert( VMCA_LIB_HANDLE plibHandle, PSTR* ppszCert, PSTR* ppszKey ) { DWORD dwError = 0; PSTR pszCert = NULL; PSTR pszKey = NULL; PVECS_STORE pVECSStore = NULL; PVECS_CERT_ENTRY_A pCertEntry = NULL; if (plibHandle == NULL || ppszCert == NULL || ppszKey == NULL) { dwError = VMCA_ARGUMENT_ERROR; goto cleanup; } fpVecsOpenCertStoreA fpOpenStore = NULL; fpVecsGetEntryByAliasA fpGetEntry = NULL; fpVecsGetKeyByAliasA fpGetKey = NULL; fpVecsCloseCertStore fpCloseStore = NULL; fpVecsFreeCertEntryA fpFreeEntry = NULL; if ( (fpOpenStore = (fpVecsOpenCertStoreA) VMCAGetLibSym(plibHandle, FN_VECS_OPEN_CERT_STORE_A) ) == NULL || (fpGetEntry = (fpVecsGetEntryByAliasA) VMCAGetLibSym(plibHandle, FN_VECS_GET_ENTRY_BY_ALIAS_A) ) == NULL || (fpGetKey = (fpVecsGetKeyByAliasA) VMCAGetLibSym(plibHandle, FN_VECS_GET_KEY_BY_ALIAS_A) ) == NULL || (fpCloseStore = (fpVecsCloseCertStore) VMCAGetLibSym(plibHandle, FN_VECS_CLOSE_CERT_STORE) ) == NULL || (fpFreeEntry = (fpVecsFreeCertEntryA) VMCAGetLibSym(plibHandle, FN_VECS_FREE_ENTRY_A) ) == NULL ) { #ifdef _WIN32 VMCA_LOG_ERROR("VECS sym lookup failed, %d", WSAGetLastError()); #else VMCA_LOG_ERROR("VECS sym lookup failed, %s", VMCA_SAFE_STRING(dlerror())); #endif dwError = VMCA_UNKNOW_ERROR; } BAIL_ON_VMCA_ERROR(dwError); dwError = (*fpOpenStore)( "localhost", MACHINE_CERT_STORE_NAME, NULL, &pVECSStore ); BAIL_ON_VECS_ERROR(dwError); dwError = (*fpGetEntry)( pVECSStore, MACHINE_CERT_ALIAS, ENTRY_INFO_LEVEL_2, &pCertEntry ); BAIL_ON_VECS_ERROR(dwError); dwError = (*fpGetKey)( pVECSStore, MACHINE_CERT_ALIAS, NULL, &pszKey ); BAIL_ON_VECS_ERROR(dwError); dwError = VMCAAllocateStringA( pCertEntry->pszCertificate, &pszCert ); BAIL_ON_VECS_ERROR(dwError); *ppszCert = pszCert; *ppszKey = pszKey; cleanup: if ( fpFreeEntry && pCertEntry ) { (*fpFreeEntry)(pCertEntry); } if ( fpCloseStore && pVECSStore ) { (*fpCloseStore)(pVECSStore); } return dwError; error: *ppszCert = NULL; *ppszKey = NULL; VMCA_SAFE_FREE_MEMORY(pszCert); VMCA_SAFE_FREE_MEMORY(pszKey); VMCA_LOG_ERROR("%s failed, error (%u)", __FUNCTION__, dwError); goto cleanup; vecs_error: goto cleanup; }
static DWORD _VMCARestServerInitHTTPS( VOID ) { DWORD dwError = 0; REST_CONF config = {0}; PREST_PROCESSOR pHandlers = &sVMCARestApiHandlers; PREST_API_MODULE pModule = NULL; PVMREST_HANDLE pHTTPSHandle = NULL; config.serverPort = VMCA_HTTPS_V2_PORT_NUM; config.connTimeoutSec = VMCA_REST_CONN_TIMEOUT_SEC; config.maxDataPerConnMB = VMCA_MAX_DATA_PER_CONN_MB; config.pSSLContext = gVMCAServerGlobals.gpVMCASslCtx; config.nWorkerThr = VMCA_REST_WORKERTHCNT; config.nClientCnt = VMCA_REST_CLIENTCNT; config.SSLCtxOptionsFlag = 0; config.pszSSLCertificate = NULL; config.pszSSLKey = NULL; config.pszSSLCipherList = NULL; config.pszDebugLogFile = NULL; config.pszDaemonName = VMCA_DAEMON_NAME; config.isSecure = TRUE; config.useSysLog = TRUE; config.debugLogLevel = VMCAToCRestEngineLogLevel(); dwError = VmRESTInit(&config, &pHTTPSHandle); BAIL_ON_VMCA_ERROR(dwError); for (pModule = gpVMCARestApiDef->pModules; pModule; pModule = pModule->pNext) { PREST_API_ENDPOINT pEndPoint = pModule->pEndPoints; for (; pEndPoint; pEndPoint = pEndPoint->pNext) { dwError = VmRESTRegisterHandler( pHTTPSHandle, pEndPoint->pszName, pHandlers, NULL); BAIL_ON_VMCA_ERROR(dwError); } } dwError = VmRESTStart(pHTTPSHandle); BAIL_ON_VMCA_ERROR(dwError); gpVMCARestHTTPSHandle = pHTTPSHandle; cleanup: return dwError; error: if (_VMCAStopRestHandle(pHTTPSHandle) == 0) { _VMCAFreeRestHandle(pHTTPSHandle, gpVMCARestApiDef); } VMCA_LOG_ERROR( "%s failed, error (%d)", __FUNCTION__, dwError); goto cleanup; }
DWORD VMCACopyTempCRLtoCRL() { DWORD dwError = 0; PSTR pszTmpFile = NULL; PSTR pszCRLFile = NULL; BOOLEAN bLocked = FALSE; FILE* pIn = NULL; FILE* pOut = NULL; dwError = VMCAGetCRLNamePath(&pszCRLFile); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAGetTempCRLNamePath(&pszTmpFile); BAIL_ON_VMCA_ERROR(dwError); VMCA_LOCK_MUTEX_EXCLUSIVE(&gVMCAServerGlobals.svcMutex, bLocked); if ((pIn = fopen(pszTmpFile, "rb")) == NULL) { dwError = LwErrnoToWin32Error(errno); VMCA_LOG_ERROR("Failed to open file [%s] for reading", pszTmpFile); BAIL_ON_VMCA_ERROR(dwError); } if ((pOut = fopen(pszCRLFile, "wb")) == NULL) { dwError = LwErrnoToWin32Error(errno); VMCA_LOG_ERROR("Failed to open file [%s] for writing", pszCRLFile); BAIL_ON_VMCA_ERROR(dwError); } while (!feof(pIn)) { CHAR szBuf[4096]; size_t nRead = 0; nRead = fread(&szBuf[0], sizeof(szBuf[0]), sizeof(szBuf), pIn); if (nRead > 0) { size_t nWritten = fwrite(&szBuf[0], sizeof(szBuf[0]), nRead, pOut); if (nWritten != nRead) { #ifndef _WIN32 dwError = LwErrnoToWin32Error(errno); #else dwError = GetLastError(); #endif BAIL_ON_VMCA_ERROR(dwError); } } } cleanup: VMCA_LOCK_MUTEX_UNLOCK(&gVMCAServerGlobals.svcMutex, bLocked); if (pIn) { fclose(pIn); } if (pOut) { fclose(pOut); } VMCA_SAFE_FREE_STRINGA(pszCRLFile); VMCA_SAFE_FREE_STRINGA(pszTmpFile); return dwError; error: // TODO : Should we delete a partially written file? VMCA_LOG_ERROR("Failed to copy temporary CRL [Error code: %u ]", dwError); dwError = VMCA_FILE_IO_ERROR; goto cleanup; }
static DWORD _VMCAHttpsServiceStartup( VOID ) { DWORD dwError = 0; DWORD iter = 0; DWORD endPointCnt = 0; REST_CONF config = {0}; PSTR pszCert = NULL; PSTR pszKey = NULL; DWORD dwPort = 0; PREST_PROCESSOR pHandlers = &sVmcaRestHandlers; PVMREST_HANDLE pHTTPSHandle = NULL; (VOID)VMCAGetRegKeyValueDword( VMCA_KEY_PARAMETERS,//VMCA_CONFIG_PARAMETER_KEY_PATH, VMCA_HTTPS_PORT_REG_KEY, &dwPort, VMCA_HTTPS_PORT_NUM ); // port value '0' indicates don't start HTTPS service if (dwPort == 0) { goto cleanup; } config.serverPort = dwPort; config.connTimeoutSec = VMCA_REST_CONN_TIMEOUT_SEC; config.maxDataPerConnMB = VMCA_MAX_DATA_PER_CONN_MB; config.pSSLContext = NULL; config.nWorkerThr = VMCA_REST_WORKER_TH_CNT; config.nClientCnt = VMCA_REST_CLIENT_CNT; config.SSLCtxOptionsFlag = 0; config.pszSSLCertificate = NULL; config.pszSSLKey = NULL; config.pszSSLCipherList = NULL; config.pszDebugLogFile = NULL; config.pszDaemonName = VMCA_DAEMON_NAME; config.isSecure = TRUE; config.useSysLog = TRUE; config.debugLogLevel = VMREST_LOG_LEVEL_ERROR; //Get Certificate and Key from VECS and Set it to Rest Engine dwError = VMCAGetVecsMachineCert(&pszCert, &pszKey); BAIL_ON_VMREST_ERROR(dwError); dwError = VmRESTInit(&config, &pHTTPSHandle); BAIL_ON_VMREST_ERROR(dwError); dwError = VmRESTSetSSLInfo(pHTTPSHandle, pszCert, VMCAStringLenA(pszCert)+1, SSL_DATA_TYPE_CERT); BAIL_ON_VMREST_ERROR(dwError); dwError = VmRESTSetSSLInfo(pHTTPSHandle, pszKey, VMCAStringLenA(pszKey)+1, SSL_DATA_TYPE_KEY); BAIL_ON_VMREST_ERROR(dwError); endPointCnt = ARRAY_SIZE(restEndPoints); for (iter = 0; iter < endPointCnt; iter++) { dwError = VmRESTRegisterHandler( pHTTPSHandle, restEndPoints[iter], pHandlers, NULL); BAIL_ON_VMREST_ERROR(dwError); } dwError = VmRESTStart(pHTTPSHandle); BAIL_ON_VMREST_ERROR(dwError); gpVMCAHTTPSHandle = pHTTPSHandle; cleanup: VMCA_SAFE_FREE_MEMORY(pszCert); VMCA_SAFE_FREE_MEMORY(pszKey); return dwError; error: _VMCARestFreeHandle(pHTTPSHandle); VMCA_LOG_ERROR("%s: failure while starting REST HTTPS service, error: %d", __FUNCTION__, dwError); goto cleanup; }
int main( int argc, char* argv[] ) { DWORD dwError = 0; const char* pszSmNotify = NULL; int notifyFd = -1; int notifyCode = 0; int ret = -1; BOOL bEnableSysLog = FALSE; BOOL bConsoleLogging = FALSE; setlocale(LC_ALL, ""); VMCABlockSelectedSignals(); dwError = VMCAParseArgs(argc, argv, &bEnableSysLog, &bConsoleLogging); BAIL_ON_VMCA_ERROR(dwError); if (bEnableSysLog) { gVMCALogType = VMCA_LOG_TYPE_SYSLOG; } else if (bConsoleLogging) { gVMCALogType = VMCA_LOG_TYPE_CONSOLE; } else { gVMCALogType = VMCA_LOG_TYPE_FILE; } dwError = VMCAInitialize(0, 0); BAIL_ON_VMCA_ERROR(dwError); VMCA_LOG_INFO("VM Certificate Service started."); #ifdef REST_ENABLED #ifndef _WIN32 dwError = VMCARestServiceStartup(); BAIL_ON_VMCA_ERROR(dwError); VMCA_LOG_INFO("VM Certificate ReST Protocol started."); #endif #endif PrintCurrentState(); // interact with likewise service manager (start/stop control) if ((pszSmNotify = getenv("LIKEWISE_SM_NOTIFY")) != NULL) { notifyFd = atoi(pszSmNotify); do { ret = write(notifyFd, ¬ifyCode, sizeof(notifyCode)); } while (ret != sizeof(notifyCode) && errno == EINTR); if (ret < 0) { VMCA_LOG_ERROR("Could not notify service manager: %s (%i)", strerror(errno), errno); dwError = LwErrnoToWin32Error(errno); BAIL_ON_VMCA_ERROR(dwError); } close(notifyFd); } // main thread waits on signals dwError = VMCAHandleSignals(); BAIL_ON_VMCA_ERROR(dwError); VMCA_LOG_INFO("VM Certificate Service exiting..."); cleanup: VMCAShutdown(); #ifdef REST_ENABLED #ifndef _WIN32 VMCARestServiceShutdown(); #endif #endif return (dwError); error: VMCA_LOG_ERROR("VM Certificate exiting due to error [code:%d]", dwError); goto cleanup; }
DWORD VMCAUpdateCrlCAAttribute( PVMCA_LDAP_CONTEXT pContext, PSTR pszConfigurationDN, PSTR pszCrl ) { DWORD dwError = 0; PSTR pszCADN = NULL; PSTR pszCrlAuthorityKeyId = NULL; PSTR pszCAContainerDN = NULL; X509_CRL* pCrl = NULL; ATTR_SEARCH_RESULT attrSearchResult = ATTR_NOT_FOUND; X509_NAME* pIssuer = NULL; PSTR pszCAIssuerDN = NULL; PSTR pszFoundCADN = NULL; dwError = VMCAPEMToX509Crl(pszCrl, &pCrl); BAIL_ON_ERROR(dwError); dwError = VMCAAllocateStringPrintfA( &pszCAContainerDN, "CN=%s,%s", CA_CONTAINER_NAME, pszConfigurationDN); BAIL_ON_ERROR(dwError); dwError = VMCAGetCrlAuthKeyIdHexString(pCrl, &pszCrlAuthorityKeyId); if (dwError == ERROR_SUCCESS) { if (!IsNullOrEmptyString(pszCrlAuthorityKeyId)) { dwError = VMCAAllocateStringPrintfA( &pszCADN, "CN=%s,%s", pszCrlAuthorityKeyId, pszCAContainerDN); BAIL_ON_ERROR(dwError); } } if (!pszCADN) { pIssuer = X509_CRL_get_issuer(pCrl); // Don't free dwError = VMCAGetX509Name(pIssuer, XN_FLAG_COMPAT, &pszCAIssuerDN); BAIL_ON_ERROR(dwError); if (pszCAIssuerDN == NULL) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_ERROR(dwError); } } dwError = VMCACheckCAObject( pContext, pszCAContainerDN, pszCADN, pszCAIssuerDN, &pszFoundCADN ); if (dwError == ERROR_INVALID_STATE && pszCAIssuerDN) { VMCA_LOG_ERROR("More than one CA found with given issuer DN: %s", pszCAIssuerDN); } BAIL_ON_ERROR(dwError); if (!pszFoundCADN) { dwError = ERROR_NOT_FOUND; BAIL_ON_ERROR(dwError); } dwError = VMCACheckAttribute( pContext, pszFoundCADN, ATTR_CRL, pszCrl, &attrSearchResult ); BAIL_ON_ERROR(dwError); if (attrSearchResult != ATTR_MATCH) { dwError = VMCAUpdateAttribute(pContext, pszFoundCADN, ATTR_CRL, pszCrl, (attrSearchResult == ATTR_NOT_FOUND)); BAIL_ON_ERROR(dwError); } cleanup: VMCA_SAFE_FREE_MEMORY(pszFoundCADN); VMCA_SAFE_FREE_MEMORY(pszCAIssuerDN); VMCA_SAFE_FREE_STRINGA(pszCADN); VMCA_SAFE_FREE_STRINGA(pszCrlAuthorityKeyId); VMCA_SAFE_FREE_STRINGA(pszCAContainerDN); if (pCrl) { X509_CRL_free(pCrl); } return dwError; error: goto cleanup; }
DWORD VMCAConvertUPNToDN( PVMCA_LDAP_CONTEXT pConnection, PCSTR pszUPN, PSTR* ppszOutDN ) { DWORD dwError = 0; LDAPMessage* pEntry = NULL; LDAPMessage* pResult = NULL; PSTR pszFilter = NULL; PSTR pszEntryDN = NULL; PSTR pszOutDN = NULL; int iCount = 0; LDAP *pLd = NULL; if (!pConnection || !pConnection->pConnection || IsNullOrEmptyString(pszUPN) || !ppszOutDN) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMCA_ERROR(dwError); } pLd = pConnection->pConnection; dwError = VMCAAllocateStringPrintfA( &pszFilter, "%s=%s", ATTR_KRB_UPN, pszUPN); BAIL_ON_VMCA_ERROR(dwError); dwError = ldap_search_ext_s( pLd, "", LDAP_SCOPE_SUBTREE, pszFilter, NULL, FALSE, /* get values */ NULL, /* server controls */ NULL, /* client controls */ NULL, /* timeout */ 0, /* size limit */ &pResult); BAIL_ON_VMCA_ERROR(dwError); iCount = ldap_count_entries(pLd, pResult); // should have either 0 or 1 result if (iCount > 1) { dwError = VMCA_ERROR_INVALID_STATE; BAIL_ON_VMCA_ERROR(dwError); } else if (iCount == 0) { dwError = VMCA_ERROR_ENTRY_NOT_FOUND; BAIL_ON_VMCA_ERROR(dwError); } if ( (pEntry = ldap_first_entry(pLd, pResult)) != NULL ) { pszEntryDN = ldap_get_dn(pLd, pEntry); dwError = VMCAAllocateStringA( pszEntryDN, &pszOutDN ); BAIL_ON_VMCA_ERROR(dwError); *ppszOutDN = pszOutDN; } else { dwError = VMCA_ERROR_INVALID_ENTRY; BAIL_ON_VMCA_ERROR(dwError); } cleanup: if (pszEntryDN) { ldap_memfree( pszEntryDN ); } if (pResult) { ldap_msgfree( pResult ); } VMCA_SAFE_FREE_MEMORY(pszFilter); return dwError; error: VMCA_LOG_ERROR("[%s,%d] failed with error (%u)", __FUNCTION__, __LINE__, dwError); VMCA_SAFE_FREE_MEMORY(pszOutDN); if (ppszOutDN) { *ppszOutDN = NULL; } goto cleanup; }