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; }
DWORD VMCASrvInitCA( VOID ) { DWORD dwError = 0; PVMCA_CERTIFICATE pRootCACert = NULL; PVMCA_KEY pPrivateKey = NULL; PSTR pszRootCertFile = NULL; PSTR pszPrivateKeyFile = NULL; PSTR pszPasswordFile = NULL; PVMCA_X509_CA pCA = NULL; DWORD dwCRLNumberCurrent = 0; BOOL bIsHoldingMutex = FALSE; dwError = VMCAGetRootCertificateFilePath(&pszRootCertFile); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAGetPrivateKeyPath(&pszPrivateKeyFile); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAGetPrivateKeyPasswordPath(&pszPasswordFile); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAReadCertificateChainFromFile(pszRootCertFile,&pRootCACert); BAIL_ON_VMCA_ERROR(dwError); // // TODO : Support Passwords for private key // dwError = VMCAReadPrivateKeyFromFilePrivate( pszPrivateKeyFile, NULL, &pPrivateKey); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAValidateCACertificatePrivate( (LPSTR) pRootCACert, NULL, pPrivateKey); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCACreateCA( pRootCACert, pPrivateKey, NULL, &pCA); BAIL_ON_VMCA_ERROR(dwError); if (BN_num_bits(pCA->pKey->pkey.rsa->n) < VMCA_MIN_CA_CERT_PRIV_KEY_LENGTH) { dwError = VMCA_ERROR_INVALID_KEY_LENGTH; BAIL_ON_VMCA_ERROR(dwError); } dwError = VMCASrvSetCA(pCA); BAIL_ON_VMCA_ERROR(dwError); pthread_mutex_lock (&gVMCAServerGlobals.mutexCRL); bIsHoldingMutex = TRUE; dwError = VmcaDbGetCurrentCRLNumber(&dwCRLNumberCurrent); if (dwError == ERROR_OBJECT_NOT_FOUND) { dwError = 0; dwCRLNumberCurrent = 0; } BAIL_ON_VMCA_ERROR (dwError); gVMCAServerGlobals.dwCurrentCRLNumber = dwCRLNumberCurrent; pthread_mutex_unlock (&gVMCAServerGlobals.mutexCRL); bIsHoldingMutex = FALSE; error: if ( pPrivateKey != NULL ) { VMCAFreeKey(pPrivateKey); } if (pRootCACert != NULL) { VMCAFreeCertificate(pRootCACert); } if (bIsHoldingMutex) { pthread_mutex_unlock(&gVMCAServerGlobals.mutexCRL); } VMCA_SAFE_FREE_STRINGA(pszRootCertFile); VMCA_SAFE_FREE_STRINGA(pszPrivateKeyFile); VMCA_SAFE_FREE_STRINGA(pszPasswordFile); if (pCA) { VMCAReleaseCA(pCA); } return dwError; }
unsigned int VMCAGenerateCRL () { DWORD dwCertCount = 0; DWORD dwError = 0; DWORD dwCount = 0; PVMCA_DB_CONTEXT pDbContext = NULL; PVMCA_DB_CERTIFICATE_ENTRY pCertEntryArray = NULL; PSTR pszCrlTempNamePath = NULL; time_t tmNextUpdate = 0; time_t tmLastUpdate = 0; X509_CRL *pCrl = NULL; X509 *pCert = NULL; DWORD dwCrlNum = 0; PVMCA_X509_CA pCA = NULL; BOOLEAN bLocked = FALSE; DWORD x = 0; VMCA_LOCK_MUTEX_SHARED(&gVMCAServerGlobals.svcMutex, bLocked); dwError = VMCASrvValidateCA(); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCASrvGetCA(&pCA); BAIL_ON_VMCA_ERROR(dwError); dwError = VmcaDbCreateContext(&pDbContext); BAIL_ON_VMCA_ERROR(dwError); dwError = VmcaDbGetTotalCertificateCount( pDbContext, &dwCertCount, VMCA_CERTIFICATE_REVOKED); BAIL_ON_VMCA_ERROR(dwError); if (dwCertCount) { dwError = VmcaDbQueryCertificatesPaged( pDbContext, 0, dwCertCount, VMCA_DB_CERTIFICATE_STATUS_REVOKED, &pCertEntryArray, &dwCount); BAIL_ON_VMCA_ERROR(dwError); } // Database operations are done VMCA_LOCK_MUTEX_UNLOCK(&gVMCAServerGlobals.svcMutex, bLocked); dwError = VMCAGetTempCRLNamePath(&pszCrlTempNamePath); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAOpenCRLPrivate(pCA, pszCrlTempNamePath, &pCrl); BAIL_ON_VMCA_ERROR(dwError); for (x = 0; x < dwCount; x++) { dwError = VMCAPEMToX509((PSTR)pCertEntryArray[x].pCertBlob, &pCert); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAAddCertToCRL(pCrl, pCert , 1); BAIL_ON_VMCA_ERROR(dwError); X509_free(pCert); pCert = NULL; } dwError = VMCAGetNextCrlNumber(pCrl, &dwCrlNum); BAIL_ON_VMCA_ERROR(dwError); tmLastUpdate = time(NULL); dwError = VMCAGetNextUpdateTime(pCrl, &tmNextUpdate); if (dwError == VMCA_CRL_NULL_TIME ) { tmNextUpdate = tmLastUpdate + ( VMCAGetDefaultValidityPeriod() * 24 * 60 * 60); dwError = 0; } BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAUpdateTimeStamps (pCrl, tmLastUpdate, tmNextUpdate, dwCrlNum); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCASortCRL(pCrl); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCACrlSign(pCrl, pCA); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCACRLToFile(pCrl, pszCrlTempNamePath); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCACopyTempCRLtoCRL(); BAIL_ON_VMCA_ERROR(dwError); error : VMCA_LOCK_MUTEX_UNLOCK(&gVMCAServerGlobals.svcMutex, bLocked); if (pCrl) { VMCACrlFree(pCrl); } if(pCert != NULL) { X509_free(pCert); } VMCA_SAFE_FREE_STRINGA(pszCrlTempNamePath); if (pCertEntryArray) { VmcaDbFreeCertEntryArray(pCertEntryArray, dwCount); } if (pDbContext) { VmcaDbReleaseContext(pDbContext); } if (pCA) { VMCAReleaseCA(pCA); } return dwError; }
unsigned int VMCAGetSignedCertificate( unsigned char *pszPEMEncodedCSRRequest, unsigned int dwtmNotBefore, unsigned int dwtmNotAfter, PVMCA_CERTIFICATE_CONTAINER *ppCertContainer ) { DWORD dwError = 0; time_t now = dwtmNotBefore; time_t expire = dwtmNotAfter; PSTR pCert = NULL; PVMCA_DB_CERTIFICATE_ENTRY pEntry = NULL; PVMCA_X509_CA pCA = NULL; PVMCA_CERTIFICATE_CONTAINER pCertContainer = NULL; BOOLEAN bLocked = FALSE; VMCA_LOCK_MUTEX_EXCLUSIVE(&gVMCAServerGlobals.svcMutex, bLocked); dwError = VMCASrvValidateCA(); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCASrvGetCA(&pCA); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCASignedRequestPrivate( pCA, (char *)pszPEMEncodedCSRRequest, (char**)&pCert, now, expire); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCARpcAllocateCertificateContainer(pCert, &pCertContainer); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCADecodeCert(pCert, &pEntry); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAInsertCertificate(pEntry); BAIL_ON_VMCA_ERROR(dwError); // TODO : check for errors strcpy((char*)pCertContainer->pCert, pCert); *ppCertContainer = pCertContainer; cleanup : VMCA_LOCK_MUTEX_UNLOCK(&gVMCAServerGlobals.svcMutex, bLocked); VMCAFreeDBEntryFields(pEntry); VMCA_SAFE_FREE_STRINGA(pCert); if (pCA) { VMCAReleaseCA(pCA); } return dwError; error: if (ppCertContainer) { *ppCertContainer = NULL; } if (pCertContainer) { VMCARpcFreeCertificateContainer(pCertContainer); } goto cleanup; }
DWORD VMCAUpdateCRL( PSTR pszCertificate, UINT32 uReason ) { DWORD dwError = 0; PSTR pszCRLFile = NULL; time_t tmLastUpdate = 0; time_t tmNextUpdate = 0; X509_CRL *pCrl = NULL; X509 *pCert = NULL; DWORD dwCrlNum = 0; PVMCA_X509_CA pCA = NULL; dwError = VMCASrvGetCA(&pCA); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAGetCRLNamePath(&pszCRLFile); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAOpenCRLPrivate(pCA, pszCRLFile, &pCrl); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAPEMToX509(pszCertificate, &pCert); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAAddCertToCRL(pCrl, pCert, 1); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCASortCRL(pCrl); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAGetNextCrlNumber(pCrl, &dwCrlNum); BAIL_ON_VMCA_ERROR(dwError); tmLastUpdate = time(NULL); dwError = VMCAGetNextUpdateTime(pCrl, &tmNextUpdate); if (dwError == VMCA_CRL_NULL_TIME ) { tmNextUpdate = tmLastUpdate + ( VMCAGetDefaultValidityPeriod() * 24 * 60 * 60); dwError = 0; } BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAUpdateTimeStamps (pCrl, tmLastUpdate, tmNextUpdate, dwCrlNum); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCACrlSign(pCrl, pCA); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCACRLToFile(pCrl, pszCRLFile); BAIL_ON_VMCA_ERROR(dwError); error: if (pCert != NULL) { X509_free(pCert); } VMCA_SAFE_FREE_STRINGA(pszCRLFile); if(pCrl != NULL) { VMCACrlFree(pCrl); } if (pCA) { VMCAReleaseCA(pCA); } return dwError; }