uint32_t make_negotiate_token( gss_buffer_desc *pBuffer, char **ppszNegotiate ) { uint32_t dwError = 0; char *pszEncodedData = NULL; char *pszNegotiate = NULL; //int len = 0; if (pBuffer) { dwError = base64_encode( pBuffer->value, pBuffer->length, &pszEncodedData); BAIL_ON_VMCA_ERROR(dwError); } dwError = VMCAAllocateStringPrintfA( &pszNegotiate, "Negotiate %s", pszEncodedData ? pszEncodedData : ""); BAIL_ON_VMCA_ERROR(dwError); *ppszNegotiate = pszNegotiate; cleanup: VMCA_SAFE_FREE_MEMORY(pszEncodedData); return dwError; error: VMCA_SAFE_FREE_MEMORY(pszNegotiate); goto cleanup; }
VOID VMCARESTFreeKrb( PVMCA_ACCESS_TOKEN pAccessToken ) { if (pAccessToken) { VMCA_SAFE_FREE_MEMORY(pAccessToken->bKrbTicketValid); VMCA_SAFE_FREE_MEMORY(pAccessToken); } }
DWORD VMCAHandleHttpRequest( PVMREST_HANDLE pRESTHandle, PREST_REQUEST pRequest, PREST_RESPONSE* ppResponse, uint32_t paramsCount ) { DWORD dwError = 0; PSTR pszStatusCode = NULL; PSTR pszResponsePayload = NULL; VMCA_HTTP_REQ_OBJ* pVMCARequest = NULL; dwError = VMCARESTParseHttpHeader(pRequest, &pVMCARequest); BAIL_ON_VMREST_ERROR(dwError); dwError = VMCARESTGetPayload(pRESTHandle, pRequest, pVMCARequest); BAIL_ON_VMREST_ERROR(dwError); dwError = VMCARESTExecuteHttpURI( pRequest, pVMCARequest, &pszStatusCode, &pszResponsePayload ); BAIL_ON_VMREST_ERROR(dwError); dwError = VMCARESTSetResponseHeaders(ppResponse, pszStatusCode); BAIL_ON_VMREST_ERROR(dwError); dwError = VMCARESTSetResponsePayload( pRESTHandle, ppResponse, pszResponsePayload); BAIL_ON_VMREST_ERROR(dwError); cleanup: VMCA_SAFE_FREE_MEMORY(pszResponsePayload); VMCA_SAFE_FREE_MEMORY(pszStatusCode); if (pVMCARequest) { VMCAFreeAccessToken(pVMCARequest->pAccessToken); VMCA_SAFE_FREE_MEMORY(pVMCARequest->pszPayload); VMCA_SAFE_FREE_MEMORY(pVMCARequest); } return dwError; error: if (dwError == EACCES) { dwError = VMCARESTRequestNegotiateAuth( pRESTHandle, pRequest, ppResponse, NULL); } goto cleanup; }
static DWORD VMCACopyQueryResultAttributeString( PVMCA_LDAP_CONTEXT pContext, LDAPMessage* pSearchResult, PCSTR pszAttribute, BOOL bOptional, PSTR* ppszOut ) { DWORD dwError = 0; struct berval** ppValues = NULL; PSTR pszOut = NULL; ppValues = ldap_get_values_len( pContext->pConnection, pSearchResult, pszAttribute); if (ppValues && ppValues[0]) { dwError = VMCAAllocateMemory( (DWORD)(sizeof(CHAR) * ppValues[0]->bv_len + 1), (PVOID*)&pszOut); BAIL_ON_ERROR(dwError); memcpy( (PVOID) pszOut, (PVOID) ppValues[0]->bv_val, (size_t) ppValues[0]->bv_len); } else if (!bOptional) { dwError = ERROR_INVALID_DATA; BAIL_ON_ERROR(dwError); } *ppszOut = pszOut; cleanup: if (ppValues) { ldap_value_free_len(ppValues); ppValues = NULL; } return dwError; error: if (ppszOut) { *ppszOut = NULL; } VMCA_SAFE_FREE_MEMORY(pszOut); goto cleanup; }
DWORD VMCARESTMakeKrbAccessToken( PVMCA_ACCESS_TOKEN* ppAccessToken ) { DWORD dwError = 0; PVMCA_ACCESS_TOKEN pAccessToken = NULL; if (!ppAccessToken) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMCA_ERROR(dwError); } dwError = VMCAAllocateMemory( sizeof(VMCA_ACCESS_TOKEN), (PVOID*)&pAccessToken ); BAIL_ON_VMCA_ERROR(dwError); pAccessToken->tokenType = VMCA_AUTHORIZATION_TOKEN_TYPE_KRB; dwError = VMCAAllocateMemory( sizeof(int), (PVOID*) &pAccessToken->bKrbTicketValid ); BAIL_ON_VMCA_ERROR(dwError); *pAccessToken->bKrbTicketValid = 1; *ppAccessToken = pAccessToken; cleanup: return dwError; error: if (pAccessToken) { VMCA_SAFE_FREE_MEMORY(pAccessToken->bKrbTicketValid); VMCA_SAFE_FREE_MEMORY(pAccessToken); } goto cleanup; }
DWORD VMCAGetVecsMachineCert( PSTR* ppszCert, PSTR* ppszKey ) { DWORD dwError = 0; VMCA_LIB_HANDLE plibHandle = NULL; PSTR pszCert = NULL; PSTR pszKey = NULL; if (ppszCert == NULL || ppszKey == NULL) { dwError = VMCA_ARGUMENT_ERROR; goto cleanup; } dwError = VMCAOpenVmAfdClientLib( &plibHandle ); BAIL_ON_VMCA_ERROR(dwError); dwError = _VMCAGetSSLCert( plibHandle, &pszCert, &pszKey ); BAIL_ON_VMCA_ERROR(dwError); *ppszCert = pszCert; *ppszKey = pszKey; VMCA_LOG_INFO("Acquired SSL Cert from VECS"); cleanup: VMCACloseLibrary( plibHandle ); return dwError; error: *ppszCert = NULL; *ppszKey = NULL; VMCA_SAFE_FREE_MEMORY(pszCert); VMCA_SAFE_FREE_MEMORY(pszKey); goto cleanup; }
static DWORD VMCAGetCrlAuthKeyIdHexString( X509_CRL* pCrl, PSTR* ppszAid ) { DWORD dwError = ERROR_SUCCESS; PSTR pszAid = NULL; AUTHORITY_KEYID *pId = NULL; if (!pCrl && !ppszAid) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_ERROR(dwError); } if (X509_CRL_get_ext_by_NID(pCrl, NID_authority_key_identifier, -1) == -1) { dwError = ERROR_NOT_FOUND; BAIL_ON_ERROR(dwError); } pId = (AUTHORITY_KEYID*)X509_CRL_get_ext_d2i(pCrl, NID_authority_key_identifier, NULL, NULL); if (!pId) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_ERROR(dwError); } dwError = VMCAKeyIdToHexString(pId->keyid, &pszAid); BAIL_ON_ERROR(dwError); *ppszAid = pszAid; cleanup: if (pId) { AUTHORITY_KEYID_free(pId); } return dwError; error: if (ppszAid) { *ppszAid = NULL; } VMCA_SAFE_FREE_MEMORY(pszAid); goto cleanup; }
static VOID VMCAPolicySNOperationFree( PVMCA_SNPOLICY_OPERATION pOperation ) { if (pOperation) { VMCA_SAFE_FREE_STRINGA(pOperation->pszData); VMCA_SAFE_FREE_STRINGA(pOperation->pszCondition); VMCA_SAFE_FREE_STRINGA(pOperation->pszWith); VMCA_SAFE_FREE_MEMORY(pOperation); } }
DWORD VMCARESTParseHttpHeader( PREST_REQUEST pRESTRequest, VMCA_HTTP_REQ_OBJ** ppVMCARequest ) { DWORD dwError = 0; PSTR pszBuff = NULL; VMCA_HTTP_REQ_OBJ* pVMCARequest; HANDLE_NULL_PARAM(ppVMCARequest, dwError); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAAllocateMemory( sizeof(VMCA_HTTP_REQ_OBJ), (PVOID*) &pVMCARequest ); BAIL_ON_VMREST_ERROR(dwError); dwError = VmRESTGetHttpMethod(pRESTRequest, &pszBuff); BAIL_ON_VMREST_ERROR(dwError); pVMCARequest->pszMethod = pszBuff; // TRUE - Request c-rest-engine to decode the URI dwError = VmRESTGetHttpURI(pRESTRequest, TRUE, &pszBuff); BAIL_ON_VMREST_ERROR(dwError); pVMCARequest->pszUri = pszBuff; dwError = VmRESTGetHttpVersion(pRESTRequest, &pszBuff); BAIL_ON_VMREST_ERROR(dwError); pVMCARequest->pszVer = pszBuff; dwError = VmRESTGetHttpHeader(pRESTRequest,"Content-Length", &pszBuff); BAIL_ON_VMREST_ERROR(dwError); pVMCARequest->pszContentLength = pszBuff; *ppVMCARequest = pVMCARequest; cleanup: return dwError; error: VMCA_SAFE_FREE_STRINGA(pVMCARequest->pszMethod); VMCA_SAFE_FREE_STRINGA(pVMCARequest->pszUri); VMCA_SAFE_FREE_STRINGA(pVMCARequest->pszVer); VMCA_SAFE_FREE_STRINGA(pszBuff); VMCA_SAFE_FREE_MEMORY(pVMCARequest); goto cleanup; }
DWORD VMCARESTSetResponsePayload( PVMREST_HANDLE pRESTHandle, PREST_RESPONSE* ppResponse, PSTR pszRespPayload ) { DWORD dwError = 0; DWORD bytesWritten = 0; PSTR pszPyldLen = NULL; size_t pyldLen = 0; size_t sentLen = 0; pyldLen = VMCAStringLenA(VMCA_SAFE_STRING(pszRespPayload)); dwError = VMCAAllocateStringPrintfA(&pszPyldLen, "%ld", pyldLen); BAIL_ON_VMREST_ERROR(dwError); dwError = VmRESTSetDataLength( ppResponse, pyldLen > VMCARESTMAXPAYLOADLENGTH ? NULL : pszPyldLen); BAIL_ON_VMREST_ERROR(dwError); do { size_t chunkLen = pyldLen > VMCARESTMAXPAYLOADLENGTH ? VMCARESTMAXPAYLOADLENGTH : pyldLen; dwError = VmRESTSetData( pRESTHandle, ppResponse, VMCA_SAFE_STRING(pszRespPayload) + sentLen, chunkLen, &bytesWritten); sentLen += bytesWritten; pyldLen -= bytesWritten; } while (dwError == REST_ENGINE_MORE_IO_REQUIRED); BAIL_ON_VMREST_ERROR(dwError); cleanup: VMCA_SAFE_FREE_MEMORY(pszPyldLen); return dwError; error: goto cleanup; }
VOID VMCAFreeCommandLineA( int argc, PSTR* pUtf8Args ) { if (pUtf8Args) { for (int i = 0; i < argc; ++i) { VMCA_SAFE_FREE_STRINGA(pUtf8Args[i]); } VMCA_SAFE_FREE_MEMORY(pUtf8Args); } }
DWORD VMCARESTGetPayload( PVMREST_HANDLE pRESTHandle, PREST_REQUEST pRESTRequest, VMCA_HTTP_REQ_OBJ* pVMCARequest ) { DWORD dwError = 0; DWORD bytesRead = 0; size_t len = 0; PSTR pszPayload = NULL; do { if (bytesRead || !pszPayload) { dwError = VMCAReallocateMemory( (PVOID)pszPayload, (PVOID*)&pszPayload, len + VMCARESTMAXPAYLOADLENGTH + 1); // +1 for NULL char BAIL_ON_VMCA_ERROR(dwError); } bytesRead = 0; dwError = VmRESTGetData( pRESTHandle, pRESTRequest, pszPayload + len, &bytesRead); len += bytesRead; } while (dwError == REST_ENGINE_MORE_IO_REQUIRED); BAIL_ON_VMCA_ERROR(dwError); pszPayload[len] = 0; pVMCARequest->pszPayload = pszPayload; pszPayload = NULL; cleanup: VMCA_SAFE_FREE_MEMORY(pszPayload); return dwError; error: goto cleanup; }
static VOID VMCAPolicySNOperationArrayFree( PVMCA_SNPOLICY_OPERATION *ppOperations, DWORD dwArrayLen ) { DWORD dwIdx = 0; if (ppOperations) { if (dwArrayLen > 0) { for (; dwIdx < dwArrayLen; ++dwIdx) { VMCAPolicySNOperationFree(ppOperations[dwIdx]); } } VMCA_SAFE_FREE_MEMORY(ppOperations); } }
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; }
unsigned int RpcVMCAGetCRL( handle_t IDL_handle, unsigned char *pszClientCachedCRLID, unsigned int dwFileOffset, unsigned int dwSize, VMCA_FILE_BUFFER **ppCRLData ) { DWORD dwError = 0; VMCA_FILE_BUFFER* pTempCRLData = NULL; VMCA_FILE_BUFFER* pCRLData = NULL; VMCA_LOG_DEBUG("Entering %s", __FUNCTION__); if(ppCRLData == NULL) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMCA_ERROR(dwError); } dwError = VMCACheckAccess(IDL_handle, FALSE); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCAGetCRL( dwFileOffset, dwSize, &pTempCRLData); BAIL_ON_VMCA_ERROR(dwError); dwError = VMCARpcAllocateMemory ( sizeof(pCRLData), (PVOID*) &pCRLData ); BAIL_ON_VMCA_ERROR(dwError); pCRLData->dwCount = pTempCRLData->dwCount; if(pCRLData->dwCount > 0) { dwError = VMCARpcAllocateMemory( pCRLData->dwCount * sizeof(unsigned char), (PVOID*) &pCRLData->buffer); BAIL_ON_VMCA_ERROR(dwError); memcpy( (PVOID*) pCRLData->buffer, pTempCRLData->buffer, (size_t) pCRLData->dwCount); } *ppCRLData = pCRLData; pTempCRLData = NULL; cleanup: if ( pTempCRLData ) { VMCA_SAFE_FREE_MEMORY(pTempCRLData->buffer); VMCA_SAFE_FREE_MEMORY(pTempCRLData); } VMCA_LOG_DEBUG("Exiting %s, Status = %d", __FUNCTION__, dwError); return dwError; error: if (ppCRLData) { *ppCRLData = NULL; } if(pCRLData) { if(pCRLData->buffer) { VMCARpcFreeMemory((PVOID) pCRLData->buffer); } VMCARpcFreeMemory((PVOID)pCRLData); } goto cleanup; }
DWORD VMCALdapGetMemberships( PVMCA_LDAP_CONTEXT pConnection, PCSTR pszUPNName, PSTR **pppszMemberships, PDWORD pdwMemberships ) { DWORD dwError = 0; PSTR pszFilter = NULL; PSTR pszAttrMemberOf = ATTR_MEMBEROF; // memberOf PSTR ppszAttrs[] = { pszAttrMemberOf, NULL}; DWORD dwCount = 0; LDAPMessage *pResult = NULL; LDAPMessage *pEntry = NULL; struct berval** ppValues = NULL; PSTR *ppszMemberships = NULL; DWORD dwMemberships = 0; DWORD i = 0; LDAP *pLd = NULL; if (pConnection == NULL || pConnection->pConnection == NULL || IsNullOrEmptyString(pszUPNName) || pppszMemberships == NULL || pdwMemberships == NULL) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMCA_ERROR(dwError); } pLd = pConnection->pConnection; dwError = VMCAAllocateStringPrintfA(&pszFilter, "(%s=%s)", ATTR_KRB_UPN, pszUPNName); // userPrincipalName BAIL_ON_VMCA_ERROR(dwError); dwError = ldap_search_ext_s( pLd, "", LDAP_SCOPE_SUBTREE, pszFilter, (PSTR*)ppszAttrs, 0, NULL, NULL, NULL, -1, &pResult); BAIL_ON_VMCA_ERROR(dwError); dwCount = ldap_count_entries(pLd, pResult); if (dwCount == 0) { dwError = LDAP_NO_SUCH_OBJECT; BAIL_ON_VMCA_ERROR(dwError); } else if (dwCount > 1) { dwError = LDAP_OPERATIONS_ERROR; BAIL_ON_VMCA_ERROR(dwError); } pEntry = ldap_first_entry(pLd, pResult); if (!pEntry) { dwError = LDAP_NO_SUCH_OBJECT; BAIL_ON_VMCA_ERROR(dwError); } ppValues = ldap_get_values_len(pLd, pEntry, pszAttrMemberOf); if (!ppValues) { dwMemberships = 0; } else { dwMemberships = ldap_count_values_len(ppValues); } if (dwMemberships) { dwError = VMCAAllocateMemory(dwMemberships * sizeof(PSTR), (PVOID*)&ppszMemberships); BAIL_ON_VMCA_ERROR(dwError); for (i = 0; ppValues[i] != NULL; i++) { PCSTR pszMemberOf = ppValues[i]->bv_val; dwError = VMCAAllocateStringA(pszMemberOf, &ppszMemberships[i]); BAIL_ON_VMCA_ERROR(dwError); } } *pppszMemberships = ppszMemberships; *pdwMemberships = dwMemberships; cleanup: if(ppValues) { ldap_value_free_len(ppValues); } if (pResult) { ldap_msgfree(pResult); } VMCA_SAFE_FREE_MEMORY(pszFilter); return dwError; error: if (ppszMemberships != NULL && dwMemberships > 0) { for (i = 0; i < dwMemberships; i++) { VMCA_SAFE_FREE_STRINGA(ppszMemberships[i]); } VMCA_SAFE_FREE_MEMORY(ppszMemberships); } 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; }
DWORD VMCARESTVerifyKrbAuth( PVMCA_AUTHORIZATION_PARAM pAuthorization, PVMCA_ACCESS_TOKEN* ppAccessToken ) { DWORD dwError = 0; PSTR pszNegotiate = NULL; PSTR pszDecode = NULL; PSTR pszUser = NULL; char *pszToken = NULL; int nLength = 0; OM_uint32 major_status; OM_uint32 minor_status; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc display_name = GSS_C_EMPTY_BUFFER; gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; gss_name_t client_name = GSS_C_NO_NAME; static gss_OID_desc gss_spnego_mech_oid_desc = {6, (void *)"\x2b\x06\x01\x05\x05\x02"}; static gss_OID gss_spnego_mech_oid = &gss_spnego_mech_oid_desc; gss_cred_id_t server_creds; pszNegotiate = pAuthorization->pszAuthorizationToken; if ( IsNullOrEmptyString(pszNegotiate) ) { dwError = EACCES; BAIL_ON_VMREST_ERROR(dwError); } if (!strcmp(pszNegotiate,"testing")) // TODO: REMOVE // TODO: DO NOT CHECK IN {// Kerberos backdoor for testing dwError = VMCARESTMakeKrbAccessToken(ppAccessToken); BAIL_ON_VMREST_ERROR(dwError); goto cleanup; } dwError = base64_decode( pszNegotiate, &pszDecode, &nLength ); BAIL_ON_VMREST_ERROR(dwError); dwError = server_acquire_creds( "HTTP", &gss_spnego_mech_oid_desc, &server_creds ); BAIL_ON_VMREST_ERROR(dwError); input_token.length = nLength; input_token.value = pszDecode; major_status = gss_accept_sec_context( &minor_status, &gss_context, server_creds, &input_token, GSS_C_NO_CHANNEL_BINDINGS, &client_name, &gss_spnego_mech_oid, &output_token, NULL, NULL, NULL ); if (GSS_ERROR(major_status) ) { //TODO: insert show error dwError = EACCES; BAIL_ON_VMREST_ERROR(dwError); } if (output_token.length) { dwError = make_negotiate_token(&output_token, &pszToken); BAIL_ON_VMREST_ERROR(dwError); } if (major_status == GSS_S_CONTINUE_NEEDED) { OM_uint32 min2; gss_buffer_desc mech_msg = GSS_C_EMPTY_BUFFER; gss_buffer_desc gss_msg = GSS_C_EMPTY_BUFFER; gss_buffer_desc minor_msg = GSS_C_EMPTY_BUFFER; OM_uint32 msg_ctx = 0; PSTR pszError = NULL; gss_oid_to_str(&min2, gss_spnego_mech_oid, &mech_msg); gss_display_status(&min2, major_status, GSS_C_GSS_CODE, gss_spnego_mech_oid, &msg_ctx, &gss_msg); gss_display_status(&min2, minor_status, GSS_C_MECH_CODE, gss_spnego_mech_oid, &msg_ctx, &minor_msg); VMCAAllocateStringPrintfA(&pszError, "gss_rc[%d:%*s] mech[%*s] minor[%u:%*s]", major_status, (int)gss_msg.length, (const char *)(gss_msg.value?gss_msg.value:""), (int)mech_msg.length, (const char *)(mech_msg.value?mech_msg.value:""), minor_status, (int)minor_msg.length, (const char *)(minor_msg.value?minor_msg.value:"")); gss_release_buffer(&min2, &mech_msg); gss_release_buffer(&min2, &gss_msg); gss_release_buffer(&min2, &minor_msg); } if (major_status == GSS_S_COMPLETE) { gss_display_name(&minor_status, client_name, &display_name, NULL); dwError = VMCAAllocateStringA(display_name.value, &pszUser); BAIL_ON_VMREST_ERROR(dwError); } dwError = VMCARESTMakeKrbAccessToken(ppAccessToken); BAIL_ON_VMREST_ERROR(dwError); cleanup: if (pszUser) { VMCA_SAFE_FREE_MEMORY(pszUser); } return dwError; error: 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; }
static DWORD VMCAGenerateCACNForLdap( X509* pCertificate, PSTR* ppszCACN ) { DWORD dwError = ERROR_SUCCESS; int length = 0; unsigned char* pEncodedKey = NULL; unsigned char* pKey = NULL; unsigned char md[SHA_DIGEST_LENGTH]; EVP_PKEY* pPubKey = NULL; PSTR pszCACN = NULL; ASN1_OCTET_STRING* pSid = NULL; if (pCertificate == NULL || ppszCACN == NULL) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_ERROR(dwError); } pSid = (ASN1_OCTET_STRING*)X509_get_ext_d2i(pCertificate, NID_subject_key_identifier, NULL, NULL); if (pSid) { dwError = VMCAKeyIdToHexString(pSid, &pszCACN); BAIL_ON_ERROR(dwError); } if (IsNullOrEmptyString(pszCACN)) { pPubKey = X509_get_pubkey(pCertificate); length = i2d_PUBKEY(pPubKey, NULL); dwError = VMCAAllocateMemory(length, (PVOID*)&pEncodedKey); BAIL_ON_ERROR(dwError); pKey = pEncodedKey; length = i2d_PUBKEY(pPubKey, &pKey); SHA1(pEncodedKey, length, md); dwError = VMCABytesToHexString((PUCHAR)md, SHA_DIGEST_LENGTH, &pszCACN, FALSE); BAIL_ON_ERROR(dwError); } *ppszCACN = pszCACN; cleanup: VMCA_SAFE_FREE_MEMORY(pEncodedKey); if (pPubKey) { EVP_PKEY_free(pPubKey); } if (pSid) { ASN1_OCTET_STRING_free(pSid); } return dwError; error: if (*ppszCACN) { *ppszCACN = NULL; } VMCA_SAFE_FREE_MEMORY(pszCACN); goto cleanup; }
DWORD VMCAPrintCRLPrivate( PSTR pszFileName, PSTR *ppszCRLString ) { DWORD dwError = 0; X509_CRL *pCrl = NULL; BIO *pBioMem = NULL; BUF_MEM *pBuffMem = NULL; PSTR pszTempCrl = NULL; PSTR pTempCrl = NULL; if(IsNullOrEmptyString(pszFileName)){ dwError = ERROR_INVALID_PARAMETER; BAIL_ON_ERROR(dwError); } pBioMem = BIO_new(BIO_s_mem()); if (pBioMem == NULL) { dwError = VMCA_OUT_MEMORY_ERR; BAIL_ON_ERROR(dwError); } dwError = VMCAReadCRLFromFile(pszFileName, &pCrl); BAIL_ON_ERROR(dwError); dwError = X509_CRL_print(pBioMem, pCrl); BAIL_ON_SSL_ERROR(dwError, VMCA_CRL_DECODE_ERROR); BIO_get_mem_ptr(pBioMem, &pBuffMem); dwError = VMCAAllocateMemory((DWORD)pBuffMem->length, (PVOID*)&pTempCrl); BAIL_ON_ERROR(dwError); memcpy(pTempCrl, pBuffMem->data, pBuffMem->length - 1); dwError = VMCAAllocateStringA(pTempCrl, &pszTempCrl); BAIL_ON_ERROR(dwError); *ppszCRLString = pszTempCrl; pszTempCrl = NULL; cleanup: if (pCrl) { VMCACrlFree(pCrl); } if (pBioMem != NULL) { BIO_free(pBioMem); } VMCA_SAFE_FREE_MEMORY(pTempCrl); return dwError; error : VMCA_SAFE_FREE_STRINGA(pszTempCrl); 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; }
DWORD SetSrpAuthenticationInfo() { DWORD dwError = ERROR_SUCCESS; PSTR pszAccount = NULL; PSTR pszPassword = NULL; PSTR pszUpn = NULL; if (!argSrpUpn.empty() && argSrpPwd.empty()) { PSTR pszTempPassword = NULL; dwError = VMCAReadPassword( argSrpUpn.c_str(), NULL, &pszTempPassword ); if (dwError == ERROR_SUCCESS) { argSrpPwd = pszTempPassword; VMCA_SAFE_FREE_MEMORY(pszTempPassword); } else { std::cout << "Error : Invalid password\n"; dwError = VMCA_ARGUMENT_ERROR; BAIL_ON_ERROR(dwError); } } if (argSrpUpn.empty()) { // TEMP hack untill every one started using command line options dwError = VMCAGetMachineAccountInfoA( &pszAccount, &pszPassword); if (dwError == ERROR_SUCCESS) { dwError = VMCAAccountDnToUpn(pszAccount, &pszUpn); if (dwError != ERROR_SUCCESS) { /* Don't use registry entries if UPN conversion fails */ VMCA_SAFE_FREE_MEMORY(pszAccount); VMCA_SAFE_FREE_MEMORY(pszUpn); } } /* Command line upn/pwd has precedence */ if (pszUpn && argSrpUpn.length() == 0) { argSrpUpn = pszUpn; argSrpPwd = pszPassword; } else { // Try with no authentication dwError = ERROR_SUCCESS; } } error: VMCA_SAFE_FREE_MEMORY(pszAccount); VMCA_SAFE_FREE_MEMORY(pszUpn); VMCA_SAFE_FREE_MEMORY(pszPassword); return dwError; }
static DWORD VMCAGetX509Name( X509_NAME* pCertName, DWORD dwFlags, PSTR* ppszSubjectName ) { DWORD dwError = 0; int length = 0; BIO* pBioMem = NULL; PSTR pszSubjectName = NULL; pBioMem = BIO_new(BIO_s_mem()); if (!pBioMem) { dwError = ERROR_OUTOFMEMORY; BAIL_ON_ERROR(dwError); } X509_NAME_print_ex(pBioMem, pCertName, 0, dwFlags); length = BIO_pending(pBioMem); if (length <= 0) { dwError = ERROR_INVALID_DATA; BAIL_ON_ERROR(dwError); } dwError = VMCAAllocateMemory((DWORD)(length + 1), (PVOID*)&pszSubjectName); BAIL_ON_ERROR(dwError); if (BIO_read(pBioMem, pszSubjectName, length) != length) { dwError = ERROR_INVALID_STATE; BAIL_ON_ERROR(dwError); } *ppszSubjectName = pszSubjectName; cleanup: if (pBioMem) { BIO_free(pBioMem); } return dwError; error: if (ppszSubjectName) { *ppszSubjectName = NULL; } VMCA_SAFE_FREE_MEMORY(pszSubjectName); goto cleanup; }