|
|
//----------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 2000.
//
// File: isakmp-r.c
//
// Contents: ISAKMP management for registry.
//
//
// History: KrishnaG.
// AbhisheV.
//
//----------------------------------------------------------------------------
#include "precomp.h"
extern LPWSTR ISAKMPDNAttributes[];
DWORD RegEnumISAKMPData( HKEY hRegistryKey, LPWSTR pszIpsecRootContainer, PIPSEC_ISAKMP_DATA ** pppIpsecISAKMPData, PDWORD pdwNumISAKMPObjects ) { DWORD dwError = 0; PIPSEC_ISAKMP_OBJECT * ppIpsecISAKMPObjects = NULL; PIPSEC_ISAKMP_DATA pIpsecISAKMPData = NULL; PIPSEC_ISAKMP_DATA * ppIpsecISAKMPData = NULL; DWORD dwNumISAKMPObjects = 0; DWORD i = 0; DWORD j = 0;
dwError = RegEnumISAKMPObjects( hRegistryKey, pszIpsecRootContainer, &ppIpsecISAKMPObjects, &dwNumISAKMPObjects ); BAIL_ON_WIN32_ERROR(dwError);
if (dwNumISAKMPObjects) { ppIpsecISAKMPData = (PIPSEC_ISAKMP_DATA *) AllocPolMem( dwNumISAKMPObjects*sizeof(PIPSEC_ISAKMP_DATA)); if (!ppIpsecISAKMPData) { dwError = ERROR_OUTOFMEMORY; BAIL_ON_WIN32_ERROR(dwError); } }
for (i = 0; i < dwNumISAKMPObjects; i++) {
dwError = RegUnmarshallISAKMPData( *(ppIpsecISAKMPObjects + i), &pIpsecISAKMPData ); if (!dwError) { *(ppIpsecISAKMPData + j) = pIpsecISAKMPData; j++; } }
if (j == 0) { if (ppIpsecISAKMPData) { FreePolMem(ppIpsecISAKMPData); ppIpsecISAKMPData = NULL; } }
*pppIpsecISAKMPData = ppIpsecISAKMPData; *pdwNumISAKMPObjects = j;
dwError = ERROR_SUCCESS;
cleanup:
if (ppIpsecISAKMPObjects) { FreeIpsecISAKMPObjects( ppIpsecISAKMPObjects, dwNumISAKMPObjects ); }
return(dwError);
error:
if (ppIpsecISAKMPData) { FreeMulIpsecISAKMPData( ppIpsecISAKMPData, i ); }
*pppIpsecISAKMPData = NULL; *pdwNumISAKMPObjects = 0;
goto cleanup; }
DWORD RegEnumISAKMPObjects( HKEY hRegistryKey, LPWSTR pszIpsecRootContainer, PIPSEC_ISAKMP_OBJECT ** pppIpsecISAKMPObjects, PDWORD pdwNumISAKMPObjects ) {
DWORD dwError = 0; DWORD i = 0; DWORD dwCount = 0; PIPSEC_ISAKMP_OBJECT pIpsecISAKMPObject = NULL; PIPSEC_ISAKMP_OBJECT * ppIpsecISAKMPObjects = NULL;
DWORD dwNumISAKMPObjectsReturned = 0; DWORD dwIndex = 0; WCHAR szISAKMPName[MAX_PATH]; DWORD dwSize = 0; DWORD dwReserved = 0;
*pppIpsecISAKMPObjects = NULL; *pdwNumISAKMPObjects = 0;
while (1) {
dwSize = MAX_PATH; dwReserved = 0; szISAKMPName[0] = L'\0';
dwError = RegEnumKeyExW( hRegistryKey, dwIndex, szISAKMPName, &dwSize, NULL, NULL, 0, 0 ); if (dwError == ERROR_NO_MORE_ITEMS) { break; } BAIL_ON_WIN32_ERROR(dwError);
if (!wcsstr(szISAKMPName, L"ipsecISAKMPPolicy")) { dwIndex++; continue; }
pIpsecISAKMPObject = NULL;
dwError =UnMarshallRegistryISAKMPObject( hRegistryKey, pszIpsecRootContainer, szISAKMPName, REG_RELATIVE_NAME, &pIpsecISAKMPObject ); if (dwError == ERROR_SUCCESS) {
dwError = ReallocatePolMem( (LPVOID *) &ppIpsecISAKMPObjects, sizeof(PIPSEC_ISAKMP_OBJECT)*(dwNumISAKMPObjectsReturned), sizeof(PIPSEC_ISAKMP_OBJECT)*(dwNumISAKMPObjectsReturned + 1) ); BAIL_ON_WIN32_ERROR(dwError);
*(ppIpsecISAKMPObjects + dwNumISAKMPObjectsReturned) = pIpsecISAKMPObject;
dwNumISAKMPObjectsReturned++;
}
dwIndex++;
}
*pppIpsecISAKMPObjects = ppIpsecISAKMPObjects; *pdwNumISAKMPObjects = dwNumISAKMPObjectsReturned;
dwError = ERROR_SUCCESS;
return(dwError);
error:
if (ppIpsecISAKMPObjects) { FreeIpsecISAKMPObjects( ppIpsecISAKMPObjects, dwNumISAKMPObjectsReturned ); }
if (pIpsecISAKMPObject) { FreeIpsecISAKMPObject( pIpsecISAKMPObject ); }
*pppIpsecISAKMPObjects = NULL; *pdwNumISAKMPObjects = 0;
return(dwError); }
DWORD RegSetISAKMPData( HKEY hRegistryKey, LPWSTR pszIpsecRootContainer, LPWSTR pszLocationName, PIPSEC_ISAKMP_DATA pIpsecISAKMPData ) { DWORD dwError = 0; PIPSEC_ISAKMP_OBJECT pIpsecISAKMPObject = NULL;
dwError = RegMarshallISAKMPObject( pIpsecISAKMPData, &pIpsecISAKMPObject ); BAIL_ON_WIN32_ERROR(dwError);
dwError = RegSetISAKMPObject( hRegistryKey, pszIpsecRootContainer, pIpsecISAKMPObject ); BAIL_ON_WIN32_ERROR(dwError);
dwError = RegBackPropIncChangesForISAKMPToPolicy( hRegistryKey, pszIpsecRootContainer, pszLocationName, pIpsecISAKMPObject ); BAIL_ON_WIN32_ERROR(dwError);
error:
if (pIpsecISAKMPObject) { FreeIpsecISAKMPObject(pIpsecISAKMPObject); }
return(dwError); }
DWORD RegSetISAKMPObject( HKEY hRegistryKey, LPWSTR pszIpsecRootContainer, PIPSEC_ISAKMP_OBJECT pIpsecISAKMPObject ) { DWORD dwError = 0;
dwError = PersistISAKMPObject( hRegistryKey, pIpsecISAKMPObject ); BAIL_ON_WIN32_ERROR(dwError);
error:
return(dwError); }
DWORD RegCreateISAKMPData( HKEY hRegistryKey, LPWSTR pszIpsecRootContainer, PIPSEC_ISAKMP_DATA pIpsecISAKMPData ) { DWORD dwError = 0; PIPSEC_ISAKMP_OBJECT pIpsecISAKMPObject = NULL;
dwError = RegMarshallISAKMPObject( pIpsecISAKMPData, &pIpsecISAKMPObject ); BAIL_ON_WIN32_ERROR(dwError);
dwError = RegCreateISAKMPObject( hRegistryKey, pszIpsecRootContainer, pIpsecISAKMPObject ); BAIL_ON_WIN32_ERROR(dwError);
error:
if (pIpsecISAKMPObject) { FreeIpsecISAKMPObject( pIpsecISAKMPObject ); }
return(dwError); }
DWORD RegCreateISAKMPObject( HKEY hRegistryKey, LPWSTR pszIpsecRootContainer, PIPSEC_ISAKMP_OBJECT pIpsecISAKMPObject ) {
DWORD dwError = 0;
dwError = PersistISAKMPObject( hRegistryKey, pIpsecISAKMPObject ); BAIL_ON_WIN32_ERROR(dwError);
error:
return(dwError); }
DWORD RegDeleteISAKMPData( HKEY hRegistryKey, LPWSTR pszIpsecRootContainer, GUID ISAKMPIdentifier ) { DWORD dwError = ERROR_SUCCESS; WCHAR szGuid[MAX_PATH]; WCHAR szDistinguishedName[MAX_PATH]; LPWSTR pszStringUuid = NULL;
szGuid[0] = L'\0'; szDistinguishedName[0] = L'\0';
dwError = UuidToString( &ISAKMPIdentifier, &pszStringUuid ); BAIL_ON_WIN32_ERROR(dwError); wcscpy(szGuid, L"{"); wcscat(szGuid, pszStringUuid); wcscat(szGuid, L"}");
wcscpy(szDistinguishedName,L"ipsecISAKMPPolicy"); wcscat(szDistinguishedName, szGuid);
dwError = RegDeleteKeyW( hRegistryKey, szDistinguishedName ); BAIL_ON_WIN32_ERROR(dwError);
error:
if (pszStringUuid) { RpcStringFree(&pszStringUuid); }
return(dwError); }
DWORD RegUnmarshallISAKMPData( PIPSEC_ISAKMP_OBJECT pIpsecISAKMPObject, PIPSEC_ISAKMP_DATA * ppIpsecISAKMPData ) { DWORD dwError = 0;
dwError = UnmarshallISAKMPObject( pIpsecISAKMPObject, ppIpsecISAKMPData );
return(dwError); }
DWORD RegMarshallISAKMPObject( PIPSEC_ISAKMP_DATA pIpsecISAKMPData, PIPSEC_ISAKMP_OBJECT * ppIpsecISAKMPObject ) { DWORD dwError = 0; PIPSEC_ISAKMP_OBJECT pIpsecISAKMPObject = NULL; WCHAR szGuid[MAX_PATH]; WCHAR szDistinguishedName[MAX_PATH]; LPBYTE pBuffer = NULL; DWORD dwBufferLen = 0; LPWSTR pszStringUuid = NULL; time_t PresentTime;
szGuid[0] = L'\0'; szDistinguishedName[0] = L'\0'; pIpsecISAKMPObject = (PIPSEC_ISAKMP_OBJECT)AllocPolMem( sizeof(IPSEC_ISAKMP_OBJECT) ); if (!pIpsecISAKMPObject) { dwError = ERROR_OUTOFMEMORY; BAIL_ON_WIN32_ERROR(dwError); }
dwError = UuidToString( &pIpsecISAKMPData->ISAKMPIdentifier, &pszStringUuid ); BAIL_ON_WIN32_ERROR(dwError); wcscpy(szGuid, L"{"); wcscat(szGuid, pszStringUuid); wcscat(szGuid, L"}");
//
// Fill in the distinguishedName
//
wcscpy(szDistinguishedName,L"ipsecISAKMPPolicy"); wcscat(szDistinguishedName, szGuid); pIpsecISAKMPObject->pszDistinguishedName = AllocPolStr( szDistinguishedName ); if (!pIpsecISAKMPObject->pszDistinguishedName) { dwError = ERROR_OUTOFMEMORY; BAIL_ON_WIN32_ERROR(dwError); }
//
// Fill in the ipsecName.
// ISAKMPData doesn't have a name.
//
pIpsecISAKMPObject->pszIpsecName = NULL;
/*
if (pIpsecISAKMPData->pszIpsecName && *pIpsecISAKMPData->pszIpsecName) { pIpsecISAKMPObject->pszIpsecName = AllocPolStr( pIpsecISAKMPData->pszIpsecName ); if (!pIpsecISAKMPObject->pszIpsecName) { dwError = ERROR_OUTOFMEMORY; BAIL_ON_WIN32_ERROR(dwError); } } */
//
// Fill in the ipsecID
//
pIpsecISAKMPObject->pszIpsecID = AllocPolStr( szGuid ); if (!pIpsecISAKMPObject->pszIpsecID) { dwError = ERROR_OUTOFMEMORY; BAIL_ON_WIN32_ERROR(dwError); }
//
// Fill in the ipsecDataType
//
pIpsecISAKMPObject->dwIpsecDataType = 0x100;
//
// Marshall the pIpsecDataBuffer and the Length
//
dwError = MarshallISAKMPBuffer( pIpsecISAKMPData, &pBuffer, &dwBufferLen ); BAIL_ON_WIN32_ERROR(dwError);
pIpsecISAKMPObject->pIpsecData = pBuffer;
pIpsecISAKMPObject->dwIpsecDataLen = dwBufferLen;
time(&PresentTime);
pIpsecISAKMPObject->dwWhenChanged = (DWORD) PresentTime;
*ppIpsecISAKMPObject = pIpsecISAKMPObject;
cleanup:
if (pszStringUuid) { RpcStringFree( &pszStringUuid ); }
return(dwError);
error:
if (pIpsecISAKMPObject) { FreeIpsecISAKMPObject( pIpsecISAKMPObject ); }
*ppIpsecISAKMPObject = NULL; goto cleanup; }
DWORD MapBundleToBYTE(PCRYPTO_BUNDLE pBundle, BYTE *pByte) {
if (pBundle->EncryptionAlgorithm.AlgorithmIdentifier == IPSEC_ESP_DES && pBundle->HashAlgorithm.AlgorithmIdentifier == IPSEC_AH_MD5 && pBundle->OakleyGroup == DH_GROUP_2048) { *pByte = BYTE_DES_MD5_2048; }
if (pBundle->EncryptionAlgorithm.AlgorithmIdentifier == IPSEC_ESP_DES && pBundle->HashAlgorithm.AlgorithmIdentifier == IPSEC_AH_SHA && pBundle->OakleyGroup == DH_GROUP_2048) { *pByte = BYTE_DES_SHA_2048; }
if (pBundle->EncryptionAlgorithm.AlgorithmIdentifier == IPSEC_ESP_3_DES && pBundle->HashAlgorithm.AlgorithmIdentifier == IPSEC_AH_MD5 && pBundle->OakleyGroup == DH_GROUP_2048) { *pByte = BYTE_3DES_MD5_2048; }
if (pBundle->EncryptionAlgorithm.AlgorithmIdentifier == IPSEC_ESP_3_DES && pBundle->HashAlgorithm.AlgorithmIdentifier == IPSEC_AH_SHA && pBundle->OakleyGroup == DH_GROUP_2048) { *pByte = BYTE_3DES_SHA_2048; }
return ERROR_SUCCESS;
}
DWORD ConvertCryptoBundle( PCRYPTO_BUNDLE pInBundle, DWORD dwInNumMethods, DWORD *pdwOutNumMethods, PCRYPTO_BUNDLE *pOutBundle, BYTE *bLeadingBundles ) {
DWORD dwError = 0; DWORD i = 0; BOOL bNonExtDHFound=FALSE;
DWORD dwNumExtLeading=0; DWORD dwNumExtInternal=0; DWORD dwNumMethods;
DWORD dwCurIndex=0;
PCRYPTO_BUNDLE pTmpBundle; PCRYPTO_BUNDLE pPrevNonExtBundle=NULL;
for (i=0; i < dwInNumMethods; i++) {
if (pInBundle[i].OakleyGroup != DH_GROUP_2048) { bNonExtDHFound = TRUE; } else { if (dwNumExtLeading >= 4) { // Error. UI should disallow this case
continue; } if (bNonExtDHFound == FALSE) { MapBundleToBYTE(&pInBundle[i], &bLeadingBundles[dwNumExtLeading]); dwNumExtLeading++; } else { dwNumExtInternal++; } } }
dwNumMethods = dwInNumMethods - dwNumExtLeading; pTmpBundle = (CRYPTO_BUNDLE *)AllocPolMem(dwNumMethods * sizeof(CRYPTO_BUNDLE)); if (pTmpBundle == NULL) { dwError = ERROR_OUTOFMEMORY; BAIL_ON_WIN32_ERROR(dwError); }
bNonExtDHFound = FALSE;
for (i=0; i < dwInNumMethods; i++) { if ((pInBundle[i].OakleyGroup == DH_GROUP_2048) && !bNonExtDHFound) { continue; } if (pInBundle[i].OakleyGroup != DH_GROUP_2048) { memcpy(&pTmpBundle[dwCurIndex], &pInBundle[i], sizeof(CRYPTO_BUNDLE)); bNonExtDHFound = TRUE; pPrevNonExtBundle=&pInBundle[i]; dwCurIndex++; } else { memcpy(&pTmpBundle[dwCurIndex], pPrevNonExtBundle, sizeof(CRYPTO_BUNDLE)); MapBundleToBYTE(&pInBundle[i],(BYTE*)&pTmpBundle[dwCurIndex].PseudoRandomFunction.Rounds); dwCurIndex++; } }
*pOutBundle=pTmpBundle; *pdwOutNumMethods = dwNumMethods;
return ERROR_SUCCESS;
error: *pOutBundle= NULL; *pdwOutNumMethods = 0;
if (pTmpBundle) { FreePolMem(pTmpBundle); }
return dwError;
}
DWORD MarshallISAKMPBuffer( PIPSEC_ISAKMP_DATA pIpsecISAKMPData, LPBYTE * ppBuffer, DWORD * pdwBufferLen ) { LPBYTE pCurrentPos = NULL; LPBYTE pBuffer = NULL; DWORD dwSize = 0; DWORD dwError = 0; DWORD i = 0; DWORD dwNumISAKMPSecurityMethods = 0; PCRYPTO_BUNDLE pSecurityMethods = NULL; PCRYPTO_BUNDLE pSecurityMethod = NULL; ISAKMP_POLICY * pISAKMPPolicy = NULL; DWORD dwEffectiveSize = 0; PCRYPTO_BUNDLE pConvertedMethods = NULL; BYTE bLeadingBundleFlags[4];
// {80DC20B8-2EC8-11d1-A89E-00A0248D3021}
static const GUID GUID_IPSEC_ISAKMP_POLICY_BLOB = { 0x80dc20b8, 0x2ec8, 0x11d1, { 0xa8, 0x9e, 0x0, 0xa0, 0x24, 0x8d, 0x30, 0x21 } };
memset(bLeadingBundleFlags,0,sizeof(BYTE)*4);
dwNumISAKMPSecurityMethods =pIpsecISAKMPData->dwNumISAKMPSecurityMethods; pISAKMPPolicy = &(pIpsecISAKMPData->ISAKMPPolicy); pSecurityMethods = pIpsecISAKMPData->pSecurityMethods;
dwError = ConvertCryptoBundle(pSecurityMethods, pIpsecISAKMPData->dwNumISAKMPSecurityMethods, &dwNumISAKMPSecurityMethods, &pConvertedMethods, bLeadingBundleFlags);
BAIL_ON_WIN32_ERROR(dwError);
dwSize += sizeof(GUID);
dwSize += sizeof(DWORD);
dwSize += sizeof(ISAKMP_POLICY);
dwSize += sizeof(DWORD);
dwSize += sizeof(CRYPTO_BUNDLE)*dwNumISAKMPSecurityMethods; dwSize++;
pBuffer = (LPBYTE)AllocPolMem(dwSize); if (!pBuffer) { dwError = ERROR_OUTOFMEMORY; BAIL_ON_WIN32_ERROR(dwError); }
pCurrentPos = pBuffer;
memcpy(pCurrentPos, &GUID_IPSEC_ISAKMP_POLICY_BLOB, sizeof(GUID)); pCurrentPos += sizeof(GUID);
dwEffectiveSize = dwSize - sizeof(GUID) - sizeof(DWORD) - 1;
memcpy(pCurrentPos, &dwEffectiveSize, sizeof(DWORD)); pCurrentPos += sizeof(DWORD);
memcpy(pISAKMPPolicy->bLeadingBundleFlags, bLeadingBundleFlags, sizeof(BYTE)*4);
pISAKMPPolicy->dwQMLimit = pSecurityMethods->QuickModeLimit; pISAKMPPolicy->dwLifetimeSec = pSecurityMethods->Lifetime.Seconds;
memcpy(pCurrentPos, pISAKMPPolicy, sizeof(ISAKMP_POLICY)); pCurrentPos += sizeof(ISAKMP_POLICY);
memcpy(pCurrentPos, &dwNumISAKMPSecurityMethods, sizeof(DWORD)); pCurrentPos += sizeof(DWORD);
for (i = 0; i < dwNumISAKMPSecurityMethods; i++) {
pSecurityMethod = pConvertedMethods + i; memcpy(pCurrentPos, pSecurityMethod, sizeof(CRYPTO_BUNDLE)); pCurrentPos += sizeof(CRYPTO_BUNDLE);
}
*ppBuffer = pBuffer; *pdwBufferLen = dwSize;
if (pConvertedMethods) { FreePolMem(pConvertedMethods); }
return(dwError);
error:
if (pConvertedMethods) { FreePolMem(pConvertedMethods); }
if (pBuffer) { FreePolMem(pBuffer); }
*ppBuffer = NULL; *pdwBufferLen = 0; return(dwError); }
DWORD RegGetISAKMPData( HKEY hRegistryKey, LPWSTR pszIpsecRootContainer, GUID ISAKMPGUID, PIPSEC_ISAKMP_DATA * ppIpsecISAKMPData ) { DWORD dwError = 0; PIPSEC_ISAKMP_OBJECT pIpsecISAKMPObject = NULL; PIPSEC_ISAKMP_DATA pIpsecISAKMPData = NULL; WCHAR szIpsecISAKMPName[MAX_PATH]; LPWSTR pszISAKMPName = NULL;
szIpsecISAKMPName[0] = L'\0'; wcscpy(szIpsecISAKMPName, L"ipsecISAKMPPolicy");
dwError = UuidToString(&ISAKMPGUID, &pszISAKMPName); BAIL_ON_WIN32_ERROR(dwError);
wcscat(szIpsecISAKMPName, L"{"); wcscat(szIpsecISAKMPName, pszISAKMPName); wcscat(szIpsecISAKMPName, L"}");
dwError =UnMarshallRegistryISAKMPObject( hRegistryKey, pszIpsecRootContainer, szIpsecISAKMPName, REG_RELATIVE_NAME, &pIpsecISAKMPObject ); BAIL_ON_WIN32_ERROR(dwError);
dwError = RegUnmarshallISAKMPData( pIpsecISAKMPObject, &pIpsecISAKMPData ); BAIL_ON_WIN32_ERROR(dwError);
error:
if (pIpsecISAKMPObject) { FreeIpsecISAKMPObject( pIpsecISAKMPObject ); }
if (pszISAKMPName) { RpcStringFree(&pszISAKMPName); }
*ppIpsecISAKMPData = pIpsecISAKMPData;
return(dwError); }
|