VOID VmDnsTrimDomainNameSuffix( PSTR pszName, PCSTR pcszDomainName ) { PSTR pszTail = NULL; if (IsNullOrEmptyString(pszName) || IsNullOrEmptyString(pcszDomainName)) { return; } if (VmDnsStringLenA(pszName) <= VmDnsStringLenA(pcszDomainName)) { return; } if (!VmDnsAllocateStringPrintfA(&pszTail, ".%s.", pcszDomainName)) { VmDnsStringTrimA(pszName, pszTail, FALSE); VMDNS_SAFE_FREE_STRINGA(pszTail); } if (!VmDnsAllocateStringPrintfA(&pszTail, ".%s", pcszDomainName)) { VmDnsStringTrimA(pszName, pszTail, FALSE); VMDNS_SAFE_FREE_STRINGA(pszTail); } }
VOID VmDnsClearSrvRecord( PVMDNS_RECORD pRecord ) { if (pRecord) { VMDNS_SAFE_FREE_STRINGA(pRecord->pszName); VMDNS_SAFE_FREE_STRINGA(pRecord->Data.SRV.pNameTarget); } }
VOID VmDnsClearZoneInfo( PVMDNS_ZONE_INFO pZoneInfo ) { if (pZoneInfo) { VMDNS_SAFE_FREE_STRINGA(pZoneInfo->pszName); VMDNS_SAFE_FREE_STRINGA(pZoneInfo->pszPrimaryDnsSrvName); VMDNS_SAFE_FREE_STRINGA(pZoneInfo->pszRName); } }
VOID VmDnsClearPtrRecord( PVMDNS_RECORD pRecord ) { if (pRecord) { VMDNS_SAFE_FREE_STRINGA(pRecord->pszName); VMDNS_SAFE_FREE_MEMORY(pRecord->Data.PTR.pNameHost); } }
static VOID VmDnsFreeForwarderEntry( PVMDNS_FORWARDER_ENTRY pForwarderEntry ) { if (pForwarderEntry) { (void) VmDnsForwarderMetricsDelete(pForwarderEntry); VMDNS_SAFE_FREE_STRINGA(pForwarderEntry->pszForwarder); VMDNS_SAFE_FREE_MEMORY(pForwarderEntry); } }
static VOID VmDnsFreeMemberShips( PSTR* ppszMemberships, DWORD dwMemberships ) { DWORD i = 0; for(i = 0; i < dwMemberships; ++i) { VMDNS_SAFE_FREE_STRINGA(ppszMemberships[i]); } VMDNS_SAFE_FREE_MEMORY(ppszMemberships); }
static VOID VmDnsCliPrintRecord( PVMDNS_RECORD pRecord ) { PSTR pszRecord = NULL; if (pRecord) { if (!VmDnsRecordToString(pRecord, &pszRecord)) { printf("%s\n", pszRecord); VMDNS_SAFE_FREE_STRINGA(pszRecord); } } }
DWORD VmDnsGetForwarderAtIndex( PVMDNS_FORWARDER_CONTEXT pForwarder, DWORD dwIndex, PSTR* ppszForwarder ) { DWORD dwError = 0; PSTR pszForwarder = NULL; BOOL bLocked = FALSE; BAIL_ON_VMDNS_INVALID_POINTER(pForwarder, dwError); BAIL_ON_VMDNS_INVALID_POINTER(ppszForwarder, dwError); VMDNS_LOCKREAD(pForwarder->pLock); bLocked = TRUE; if (dwIndex >= pForwarder->dwCount) { dwError = ERROR_INVALID_INDEX; BAIL_ON_VMDNS_ERROR(dwError); } dwError = VmDnsAllocateStringA( pForwarder->pForwarderEntries[dwIndex]->pszForwarder, &pszForwarder ); BAIL_ON_VMDNS_ERROR(dwError); *ppszForwarder = pszForwarder; cleanup: if (bLocked) { VMDNS_UNLOCKREAD(pForwarder->pLock); } return dwError; error: if (ppszForwarder) { *ppszForwarder = NULL; } VMDNS_SAFE_FREE_STRINGA(pszForwarder); goto cleanup; }
DWORD VmDnsForwarderAppend( PVMDNS_FORWARDER_CONTEXT pForwarder, PCSTR pszForwarder ) { DWORD dwError = ERROR_SUCCESS; PSTR szForwarderCopy = NULL; DWORD dwCount = pForwarder->dwCount; if (dwCount >= VMDNS_MAX_NUM_FORWARDS) { dwError = ERROR_OUT_OF_RANGE; BAIL_ON_VMDNS_ERROR(dwError); } dwError = VmDnsAllocateStringA(pszForwarder, &szForwarderCopy); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsAllocateMemory( sizeof(VMDNS_FORWARDER_ENTRY), (void**)&pForwarder->pForwarderEntries[dwCount]); BAIL_ON_VMDNS_ERROR(dwError); pForwarder->pForwarderEntries[dwCount]->pszForwarder = szForwarderCopy; szForwarderCopy = NULL; dwError = VmDnsForwarderMetricsInit(pForwarder->pForwarderEntries[dwCount]); BAIL_ON_VMDNS_ERROR(dwError); pForwarder->dwCount++; cleanup: return dwError; error: if (dwCount < VMDNS_MAX_NUM_FORWARDS && pForwarder->pForwarderEntries[dwCount]) { VmDnsFreeForwarderEntry(pForwarder->pForwarderEntries[dwCount]); } VMDNS_SAFE_FREE_STRINGA(szForwarderCopy); goto cleanup; }
DWORD VmDnsSrvRecordGetCN( PVMDNS_RECORD pRecord, PSTR* ppStr ) { DWORD dwError = ERROR_SUCCESS; PSTR pStr = NULL; dwError = VmDnsAllocateStringA(pRecord->pszName, &pStr); BAIL_ON_VMDNS_ERROR(dwError); *ppStr = pStr; cleanup: return dwError; error: VMDNS_SAFE_FREE_STRINGA(pStr); goto cleanup; }
DWORD VmDnsSrvRecordToString( PVMDNS_RECORD pRecord, PSTR* ppStr ) { DWORD dwError = ERROR_SUCCESS; PSTR pStr = NULL; PCSTR pszType = NULL; dwError = VmDnsRecordTypeToString(pRecord->dwType, &pszType); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsAllocateStringPrintfA( &pStr, "Type: %s, " "Name: %s, " "Target: %s, " "Port: %hu, " "Priority: %hu, " "Weight: %hu", pszType, pRecord->pszName, pRecord->Data.SRV.pNameTarget, pRecord->Data.SRV.wPort, pRecord->Data.SRV.wPriority, pRecord->Data.SRV.wWeight ); *ppStr = pStr; BAIL_ON_VMDNS_ERROR(dwError); cleanup: return dwError; error: VMDNS_SAFE_FREE_STRINGA(pStr); goto cleanup; }
DWORD VmDnsPtrRecordToString( PVMDNS_RECORD pRecord, PSTR* ppStr ) { DWORD dwError = ERROR_SUCCESS; PSTR pStr = NULL; PCSTR pszType = NULL; dwError = VmDnsRecordTypeToString(pRecord->dwType, &pszType); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsAllocateStringPrintfA( &pStr, "Type: %s\n" "Name: %s\n" "Class: %hu\n" "TTL: %u\n" "Server: %s\n", pszType, pRecord->pszName, pRecord->iClass, pRecord->dwTtl, pRecord->Data.PTR.pNameHost ); BAIL_ON_VMDNS_ERROR(dwError); *ppStr = pStr; cleanup: return dwError; error: VMDNS_SAFE_FREE_STRINGA(pStr); goto cleanup; }
DWORD VmDnsConfigGetStringA( PCSTR pcszKeyPath, PCSTR pcszValueName, PSTR* ppszOutput ) { DWORD dwError = 0; PSTR pszValue = 0; PVMDNS_CFG_CONNECTION pConnection = NULL; PVMDNS_CFG_KEY pRootKey = NULL; PVMDNS_CFG_KEY pParamsKey = NULL; dwError = VmDnsConfigOpenConnection(&pConnection); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsConfigOpenRootKey( pConnection, "HKEY_LOCAL_MACHINE", 0, KEY_READ, &pRootKey); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsConfigOpenKey( pConnection, pRootKey, pcszKeyPath, 0, KEY_READ, &pParamsKey); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsConfigReadStringValue( pParamsKey, NULL, pcszValueName, &pszValue); BAIL_ON_VMDNS_ERROR(dwError); *ppszOutput = pszValue; cleanup: if (pParamsKey) { VmDnsConfigCloseKey(pParamsKey); } if (pRootKey) { VmDnsConfigCloseKey(pRootKey); } if (pConnection) { VmDnsConfigCloseConnection(pConnection); } return dwError; error: VMDNS_SAFE_FREE_STRINGA(pszValue); goto cleanup; }
DWORD VmDnsReadDomainNameFromBuffer( PVMDNS_MESSAGE_BUFFER pVmDnsBuffer, PSTR *ppszDomainName ) { DWORD dwError = 0; DWORD dwTotalStringLength = 0; DWORD dwLabelLength = 0; PSTR pszTempString = NULL; PSTR pszTempStringCursor = NULL; PSTR pszLabels = NULL; PSTR pszDomainName = NULL; if (!pVmDnsBuffer|| !ppszDomainName ) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDNS_ERROR(dwError); } dwError = VmDnsAllocateMemory( 256, (PVOID *)&pszTempString ); BAIL_ON_VMDNS_ERROR(dwError); pszTempStringCursor = pszTempString; do { dwError = VmDnsReadStringFromBuffer( pVmDnsBuffer, &pszLabels, &dwLabelLength ); BAIL_ON_VMDNS_ERROR(dwError); if (dwLabelLength) { dwError = VmDnsCopyMemory( pszTempStringCursor, 255 - dwTotalStringLength, pszLabels, dwLabelLength ); BAIL_ON_VMDNS_ERROR(dwError); pszTempStringCursor[dwLabelLength]='.'; dwLabelLength++; } pszTempStringCursor = &pszTempStringCursor[dwLabelLength]; VMDNS_SAFE_FREE_STRINGA(pszLabels); dwTotalStringLength += dwLabelLength; if (dwTotalStringLength > 255) { dwError = ERROR_LABEL_TOO_LONG; BAIL_ON_VMDNS_ERROR(dwError); } }while(dwLabelLength); if (dwTotalStringLength > 0) { pszTempString[dwTotalStringLength - 1] = 0; } dwError = VmDnsAllocateStringA( pszTempString, &pszDomainName ); BAIL_ON_VMDNS_ERROR(dwError); *ppszDomainName = pszDomainName; cleanup: VMDNS_SAFE_FREE_STRINGA(pszTempString); VMDNS_SAFE_FREE_STRINGA(pszLabels); return dwError; error: if (ppszDomainName) { *ppszDomainName = NULL; } goto cleanup; }
DWORD VmDnsWriteDomainNameLabelsToBuffer( PSTR pszDomainName, PVMDNS_MESSAGE_BUFFER pVmDnsBuffer ) { DWORD dwError = 0; PSTR pszTempString = NULL; PSTR pToken = NULL; PSTR pNextToken = NULL; DWORD dwTotalStringLength = 0; if (!pszDomainName || !pVmDnsBuffer ) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDNS_ERROR(dwError); } dwError = VmDnsAllocateStringA( pszDomainName, &pszTempString ); BAIL_ON_VMDNS_ERROR(dwError); pToken = VmDnsStringTokA( pszTempString, ".", &pNextToken ); while(pToken) { DWORD dwStringLength = 0; dwStringLength = VmDnsStringLenA(pToken); if (dwStringLength > VMDNS_LABEL_LENGTH_MAX) { dwError = ERROR_LABEL_TOO_LONG; BAIL_ON_VMDNS_ERROR(dwError); } dwError = VmDnsWriteStringToBuffer( pToken, dwStringLength, pVmDnsBuffer ); BAIL_ON_VMDNS_ERROR(dwError); dwTotalStringLength += dwStringLength+1; if (dwTotalStringLength > VMDNS_NAME_LENGTH_MAX) { dwError = ERROR_LABEL_TOO_LONG; BAIL_ON_VMDNS_ERROR(dwError); } pToken = VmDnsStringTokA( NULL, ".", &pNextToken ); } if (++dwTotalStringLength > VMDNS_NAME_LENGTH_MAX) { dwError = ERROR_LABEL_TOO_LONG; BAIL_ON_VMDNS_ERROR(dwError); } dwError = VmDnsWriteCharToBuffer( 0, pVmDnsBuffer ); BAIL_ON_VMDNS_ERROR(dwError); cleanup: VMDNS_SAFE_FREE_STRINGA(pszTempString); return dwError; error: goto cleanup; }
DWORD VmDnsGetDomainNameLength( PSTR pszDomainName, PUINT16 puSize, BOOL bTokenizeDomainName ) { DWORD dwError = 0; PSTR pszTempString = NULL; PSTR pToken = NULL; PSTR pNextToken = NULL; UINT16 uTotalStringLength = 0; if (!puSize) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDNS_ERROR(dwError); } if (bTokenizeDomainName) { dwError = VmDnsAllocateStringA( pszDomainName, &pszTempString ); BAIL_ON_VMDNS_ERROR(dwError); pToken = VmDnsStringTokA( pszTempString, ".", &pNextToken ); while(++uTotalStringLength && pToken) { UINT16 uStringLength = 0; uStringLength = VmDnsStringLenA(pToken); uTotalStringLength += uStringLength; pToken = VmDnsStringTokA( NULL, ".", &pNextToken ); } } else { uTotalStringLength = VmDnsStringLenA(pszDomainName) + 1; } *puSize = uTotalStringLength; cleanup: VMDNS_SAFE_FREE_STRINGA(pszTempString); return dwError; error: if (puSize) { *puSize = 0; } goto cleanup; }
static DWORD VmDnsCliValidateAndCompleteRecord( PVM_DNS_CLI_CONTEXT pContext ) { DWORD dwError = 0; PSTR pszTargetFQDN = NULL; pContext->record.iClass = VMDNS_CLASS_IN; pContext->record.dwTtl = VMDNS_DEFAULT_TTL; dwError = VmDnsCliValidateRecordInput(pContext); BAIL_ON_VMDNS_ERROR(dwError); switch (pContext->record.dwType) { case VMDNS_RR_TYPE_A: case VMDNS_RR_TYPE_AAAA: dwError = VmDnsMakeFQDN( pContext->record.pszName, pContext->pszZone, &pszTargetFQDN); BAIL_ON_VMDNS_ERROR(dwError); if (pszTargetFQDN) { VMDNS_SAFE_FREE_STRINGA(pContext->record.pszName); pContext->record.pszName = pszTargetFQDN; pszTargetFQDN = NULL; } break; case VMDNS_RR_TYPE_SRV: dwError = VmDnsAllocateStringPrintfA(&pContext->record.pszName, "%s.%s.%s", pContext->pszService, pContext->pszProtocol, pContext->pszZone); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsMakeFQDN(pContext->record.Data.SRV.pNameTarget, pContext->pszZone, &pszTargetFQDN); BAIL_ON_VMDNS_ERROR(dwError); if (pszTargetFQDN) { VMDNS_SAFE_FREE_STRINGA(pContext->record.Data.SRV.pNameTarget); pContext->record.Data.SRV.pNameTarget = pszTargetFQDN; pszTargetFQDN = NULL; } break; case VMDNS_RR_TYPE_NS: dwError = VmDnsMakeFQDN(pContext->record.Data.NS.pNameHost, pContext->pszZone, &pszTargetFQDN); BAIL_ON_VMDNS_ERROR(dwError); if (pszTargetFQDN) { VMDNS_SAFE_FREE_STRINGA(pContext->record.Data.NS.pNameHost); pContext->record.Data.NS.pNameHost = pszTargetFQDN; pszTargetFQDN = NULL; } DWORD dwNameLen = strlen(pContext->record.pszName); if (pContext->record.pszName[dwNameLen -1] != '.') { dwError = VmDnsAllocateStringPrintfA(&pszTargetFQDN, "%s.", pContext->record.pszName); BAIL_ON_VMDNS_ERROR(dwError); if (pszTargetFQDN) { VMDNS_SAFE_FREE_STRINGA(pContext->record.pszName); pContext->record.pszName = pszTargetFQDN; pszTargetFQDN = NULL; } } break; case VMDNS_RR_TYPE_PTR: if (!VmDnsStringStrA(pContext->record.pszName, pContext->pszZone)) { fprintf(stderr, "Error: IP address doesn't belong to " "the given reverse zone.\n"); dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDNS_ERROR(dwError); } dwError = VmDnsMakeFQDN( pContext->record.pszName, pContext->pszZone, &pszTargetFQDN); BAIL_ON_VMDNS_ERROR(dwError); if (pszTargetFQDN) { VMDNS_SAFE_FREE_STRINGA(pContext->record.pszName); pContext->record.pszName = pszTargetFQDN; pszTargetFQDN = NULL; } break; case VMDNS_RR_TYPE_CNAME: dwError = VmDnsMakeFQDN(pContext->record.Data.CNAME.pNameHost, pContext->pszZone, &pszTargetFQDN); BAIL_ON_VMDNS_ERROR(dwError); if (pszTargetFQDN) { VMDNS_SAFE_FREE_STRINGA(pContext->record.Data.CNAME.pNameHost); pContext->record.Data.NS.pNameHost = pszTargetFQDN; pszTargetFQDN = NULL; } dwError = VmDnsMakeFQDN( pContext->record.pszName, pContext->pszZone, &pszTargetFQDN); BAIL_ON_VMDNS_ERROR(dwError); if (pszTargetFQDN) { VMDNS_SAFE_FREE_STRINGA(pContext->record.pszName); pContext->record.pszName = pszTargetFQDN; pszTargetFQDN = NULL; } break; default: dwError = ERROR_NOT_SUPPORTED; break; } if (IsNullOrEmptyString(pContext->record.pszName)) { fprintf(stderr, "Error: DNS Record name is not specified\n"); dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDNS_ERROR(dwError); } cleanup: return dwError; error: goto cleanup; }
static DWORD VmDnsCliDelRecord( PVM_DNS_CLI_CONTEXT pContext ) { DWORD dwError = 0; DWORD idx = 0; PVMDNS_RECORD_ARRAY pRecordArray = NULL; BOOL bFound = FALSE; PSTR pszTargetFQDN = NULL; if (pContext->record.dwType == VMDNS_RR_TYPE_SOA) { fprintf(stdout, "SOA record cannot be deleted.\n"); dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDNS_ERROR(dwError); } dwError = VmDnsCliValidateAndCompleteRecord(pContext); BAIL_ON_VMDNS_ERROR(dwError); if (pContext->record.dwType == VMDNS_RR_TYPE_SRV) { dwError = VmDnsMakeFQDN(pContext->record.Data.SRV.pNameTarget, pContext->pszZone, &pszTargetFQDN); BAIL_ON_VMDNS_ERROR(dwError); if (pszTargetFQDN) { VMDNS_SAFE_FREE_STRINGA(pContext->record.Data.SRV.pNameTarget); pContext->record.Data.SRV.pNameTarget = pszTargetFQDN; pszTargetFQDN = NULL; } } if (pContext->record.dwType == VMDNS_RR_TYPE_NS) { dwError = VmDnsMakeFQDN(pContext->record.Data.NS.pNameHost, pContext->pszZone, &pszTargetFQDN); BAIL_ON_VMDNS_ERROR(dwError); if (pszTargetFQDN) { VMDNS_SAFE_FREE_STRINGA(pContext->record.Data.NS.pNameHost); pContext->record.Data.NS.pNameHost = pszTargetFQDN; pszTargetFQDN = NULL; } DWORD dwNameLen = strlen(pContext->record.pszName); if (pContext->record.pszName[dwNameLen -1] != '.') { VmDnsAllocateStringPrintfA(&pszTargetFQDN, "%s.", pContext->record.pszName); VMDNS_SAFE_FREE_STRINGA(pContext->record.pszName); pContext->record.pszName = pszTargetFQDN; pszTargetFQDN = NULL; } } if (pContext->record.dwType == VMDNS_RR_TYPE_PTR) { dwError = VmDnsMakeFQDN( pContext->record.pszName, pContext->pszZone, &pszTargetFQDN); BAIL_ON_VMDNS_ERROR(dwError); if (pszTargetFQDN) { VMDNS_SAFE_FREE_STRINGA(pContext->record.pszName); pContext->record.pszName = pszTargetFQDN; pszTargetFQDN = NULL; } } else { VmDnsTrimDomainNameSuffix(pContext->record.pszName, pContext->pszZone); dwError = VmDnsMakeFQDN( pContext->record.pszName, pContext->pszZone, &pszTargetFQDN); BAIL_ON_VMDNS_ERROR(dwError); if (pszTargetFQDN) { VMDNS_SAFE_FREE_STRINGA(pContext->record.pszName); pContext->record.pszName = pszTargetFQDN; pszTargetFQDN = NULL; } } dwError = VmDnsQueryRecordsA( pContext->pServerContext, pContext->pszZone, pContext->record.pszName, pContext->record.dwType, 0, &pRecordArray); BAIL_ON_VMDNS_ERROR(dwError); for (; idx < pRecordArray->dwCount; ++idx) { if (VmDnsMatchRecord(&pRecordArray->Records[idx], &pContext->record)) { dwError = VmDnsDeleteRecordA( pContext->pServerContext, pContext->pszZone, &pRecordArray->Records[idx] ); BAIL_ON_VMDNS_ERROR(dwError); bFound = TRUE; } } error: if (!bFound) { fprintf(stderr, "Error: no matching record found.\n"); } VMDNS_SAFE_FREE_STRINGA(pszTargetFQDN); VmDnsFreeRecordArray(pRecordArray); return dwError; }
DWORD VmDnsLdapAccessCheck( PCSTR szAuthPrinc, VMDNS_USER_TYPE userType ) { DWORD dwError = ERROR_SUCCESS; PVMDNS_DIR_CONTEXT pLd = NULL; PSTR* ppszMemberships = NULL; PSTR szGroupName = NULL; PSTR pszDomainName = NULL; DWORD dwMemberships = 0; if (IsNullOrEmptyString(szAuthPrinc) || (userType != VMDNS_ADMINISTRATORS)) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDNS_ERROR(dwError); } dwError = VmDnsDirConnect("localhost", &pLd); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsLdapGetMemberships( pLd, szAuthPrinc, &ppszMemberships, &dwMemberships ); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsGetDefaultDomainName(pLd, &pszDomainName); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsAllocateStringPrintfA( &szGroupName, "%s,%s", VMDNS_ADMINISTRATORS_GROUP, pszDomainName); BAIL_ON_VMDNS_ERROR(dwError); VMDNS_LOG_INFO("Checking upn: %s against DNS admin group: %s ", szGroupName, szAuthPrinc); if (!VmDnsIsMemberOf( ppszMemberships, dwMemberships, szGroupName )) { dwError = ERROR_ACCESS_DENIED; BAIL_ON_VMDNS_ERROR(dwError); } cleanup: VMDNS_SAFE_FREE_STRINGA(pszDomainName); VMDNS_SAFE_FREE_STRINGA(szGroupName); if (ppszMemberships) { VmDnsFreeMemberShips(ppszMemberships, dwMemberships); ppszMemberships = NULL; } if (pLd) { VmDnsDirClose(pLd); pLd = NULL; } return dwError; error: goto cleanup; }