|
|
/*
File: radius.c
Upgrades radius configuration from nt4 steelhead to win2k rras.
Paul Mayfield, 2/8/99 */
#include "upgrade.h"
//
// Information describing a radius server
//
typedef struct _RAD_SERVER_NODE { PWCHAR pszName; DWORD dwTimeout; DWORD dwAuthPort; DWORD dwAcctPort; DWORD dwScore; BOOL bEnableAuth; BOOL bEnableAcct; BOOL bAccountingOnOff; struct _RAD_SERVER_NODE * pNext; } RAD_SERVER_NODE;
//
// A radius server list
//
typedef struct _RAD_SERVER_LIST { RAD_SERVER_NODE* pHead; DWORD dwCount; } RAD_SERVER_LIST;
//
// Info used by routines that manipulate the nt5 radius registry hive
//
typedef struct _RAD_CONFIG_INFO { HKEY hkAuthServers; HKEY hkAuthProviders;
HKEY hkAcctServers; HKEY hkAcctProviders; } RAD_CONFIG_INFO;
//
// Registry value names
//
// The all caps ones were taken from nt40 src.
//
static const WCHAR PSZTIMEOUT[] = L"Timeout"; static const WCHAR PSZAUTHPORT[] = L"AuthPort"; static const WCHAR PSZACCTPORT[] = L"AcctPort"; static const WCHAR PSZENABLEACCT[] = L"EnableAccounting"; static const WCHAR PSZENABLEACCTONOFF[] = L"EnableAccountingOnOff"; static const WCHAR PSZENABLEAUTH[] = L"EnableAuthentication"; static const WCHAR PSZSCORE[] = L"Score";
static const WCHAR pszTempRegKey[] = L"Temp"; static const WCHAR pszAccounting[] = L"Accounting\\Providers"; static const WCHAR pszAuthentication[] = L"Authentication\\Providers"; static const WCHAR pszActiveProvider[] = L"ActiveProvider"; static const WCHAR pszRadServersFmt[] = L"%s\\Servers"; static const WCHAR pszServers[] = L"Servers";
static const WCHAR pszGuidRadAuth[] = L"{1AA7F83F-C7F5-11D0-A376-00C04FC9DA04}";
static const WCHAR pszGuidRadAcct[] = L"{1AA7F840-C7F5-11D0-A376-00C04FC9DA04}";
// Defaults
//
#define DEFTIMEOUT 5
#define DEFAUTHPORT 1645
#define DEFACCTPORT 1646
#define MAXSCORE 30
RAD_SERVER_NODE g_DefaultRadNode = { NULL,
DEFTIMEOUT, DEFAUTHPORT, DEFACCTPORT, MAXSCORE, TRUE, TRUE, TRUE,
NULL };
//
// Loads a radius server node's configuration from the registry
// (assumed nt4 format and that defaults are assigned to pNode)
//
DWORD RadNodeLoad( IN HKEY hKey, OUT RAD_SERVER_NODE* pNode) { RTL_QUERY_REGISTRY_TABLE paramTable[8]; BOOL bTrue = TRUE; DWORD i;
// Initialize the table of parameters
RtlZeroMemory(¶mTable[0], sizeof(paramTable)); paramTable[0].Name = (PWCHAR)PSZTIMEOUT; paramTable[0].EntryContext = &(pNode->dwTimeout); paramTable[1].Name = (PWCHAR)PSZAUTHPORT; paramTable[1].EntryContext = &(pNode->dwAuthPort);
paramTable[2].Name = (PWCHAR)PSZACCTPORT; paramTable[2].EntryContext = &(pNode->dwAcctPort);
paramTable[3].Name = (PWCHAR)PSZENABLEAUTH; paramTable[3].EntryContext = &(pNode->bEnableAuth);
paramTable[4].Name = (PWCHAR)PSZENABLEACCT; paramTable[4].EntryContext = &(pNode->bEnableAcct);
paramTable[5].Name = (PWCHAR)PSZENABLEACCTONOFF; paramTable[5].EntryContext = &(pNode->bAccountingOnOff);
paramTable[6].Name = (PWCHAR)PSZSCORE; paramTable[6].EntryContext = &(pNode->dwScore);
// We're reading all dwords, set the types
// accordingly
//
for (i = 0; i < (sizeof(paramTable) / sizeof(*paramTable)) - 1; i++) { paramTable[i].Flags = RTL_QUERY_REGISTRY_DIRECT; paramTable[i].DefaultType = REG_DWORD; paramTable[i].DefaultLength = sizeof(DWORD); paramTable[i].DefaultData = paramTable[i].EntryContext; }
// Read in the values
//
RtlQueryRegistryValues( RTL_REGISTRY_HANDLE, (PWSTR)hKey, paramTable, NULL, NULL);
return NO_ERROR; }
// Add the authentication server node
//
DWORD RadNodeSave( IN HKEY hKey, IN RAD_SERVER_NODE* pNode, IN BOOL bAuth) { DWORD dwErr = NO_ERROR; HKEY hkServer = NULL;
do { // Create the server key in which to store the info
//
dwErr = RegCreateKeyExW( hKey, pNode->pszName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkServer, NULL); if (dwErr != ERROR_SUCCESS) { break; }
if (bAuth) { RegSetValueExW( hkServer, (PWCHAR)PSZAUTHPORT, 0, REG_DWORD, (BYTE*)&pNode->dwAuthPort, sizeof(DWORD));
RegSetValueExW( hkServer, (PWCHAR)PSZSCORE, 0, REG_DWORD, (BYTE*)&pNode->dwScore, sizeof(DWORD));
RegSetValueExW( hkServer, (PWCHAR)PSZTIMEOUT, 0, REG_DWORD, (BYTE*)&pNode->dwTimeout, sizeof(DWORD)); } else { RegSetValueExW( hkServer, (PWCHAR)PSZACCTPORT, 0, REG_DWORD, (BYTE*)&pNode->dwAcctPort, sizeof(DWORD));
RegSetValueExW( hkServer, (PWCHAR)PSZSCORE, 0, REG_DWORD, (BYTE*)&pNode->dwScore, sizeof(DWORD));
RegSetValueExW( hkServer, (PWCHAR)PSZTIMEOUT, 0, REG_DWORD, (BYTE*)&pNode->dwTimeout, sizeof(DWORD));
RegSetValueExW( hkServer, (PWCHAR)PSZENABLEACCTONOFF, 0, REG_DWORD, (BYTE*)&pNode->bAccountingOnOff, sizeof(DWORD)); }
} while (FALSE);
// Cleanup
{ if (hkServer) { RegCloseKey(hkServer); } }
return dwErr; }
//
// Callback from registry key enumerator that adds the server at the given key
// to the list of radius servers.
//
DWORD RadSrvListAddNodeFromKey( IN PWCHAR pszName, // sub key name
IN HKEY hKey, // sub key
IN HANDLE hData) { DWORD dwErr = NO_ERROR; RAD_SERVER_LIST * pList = (RAD_SERVER_LIST*)hData; RAD_SERVER_NODE * pNode = NULL; do { // Initialize the new node
//
pNode = (RAD_SERVER_NODE*) UtlAlloc(sizeof(RAD_SERVER_NODE)); if (pNode == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } CopyMemory(pNode, &g_DefaultRadNode, sizeof(RAD_SERVER_NODE));
// Initialize the name
//
pNode->pszName = UtlDupString(pszName); if (pNode->pszName == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
// Load in the registry settings
//
dwErr = RadNodeLoad(hKey, pNode); if (dwErr != NO_ERROR) { break; }
// Add the node to the list
//
pNode->pNext = pList->pHead; pList->pHead = pNode; pList->dwCount += 1; } while (FALSE);
// Cleanup
{ } return dwErr; }
//
// Generates a RAD_SERVER_LIST based on the configuration (assumed
// nt4 format) in the given registry key
//
DWORD RadSrvListGenerate( IN HKEY hkSettings, OUT RAD_SERVER_LIST** ppList) { RAD_SERVER_LIST* pList = NULL; DWORD dwErr = NO_ERROR;
do { // Alloc/Init the list
pList = (RAD_SERVER_LIST*) UtlAlloc(sizeof(RAD_SERVER_LIST)); if (pList == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } ZeroMemory(pList, sizeof(RAD_SERVER_LIST));
// Build the list
//
dwErr = UtlEnumRegistrySubKeys( hkSettings, NULL, RadSrvListAddNodeFromKey, (HANDLE)pList); if (dwErr != NO_ERROR) { break; }
// Assign the return value
//
*ppList = pList; } while (FALSE);
// Cleanup
{ }
return dwErr; }
//
// Cleans up a radius server list
//
DWORD RadSrvListCleanup( IN RAD_SERVER_LIST* pList) { RAD_SERVER_NODE* pNode = NULL;
if (pList) { for (pNode = pList->pHead; pNode; pNode = pList->pHead) { if (pNode->pszName) { UtlFree(pNode->pszName); } pList->pHead = pNode->pNext; UtlFree(pNode); } UtlFree(pList); }
return NO_ERROR; }
//
// Opens the registry keys required by pNode
//
DWORD RadOpenRegKeys( IN HKEY hkRouter, IN RAD_SERVER_NODE* pNode, IN OUT RAD_CONFIG_INFO* pInfo) { DWORD dwErr = NO_ERROR; WCHAR pszPath[MAX_PATH];
do { // Open the authentication keys as needed
//
if (pNode->bEnableAuth) { if (pInfo->hkAuthProviders == NULL) { // Open the auth providers key
//
dwErr = RegOpenKeyExW( hkRouter, pszAuthentication, 0, KEY_ALL_ACCESS, &pInfo->hkAuthProviders); if (dwErr != NO_ERROR) { break; }
// Generate the servers key name
//
wsprintfW(pszPath, pszRadServersFmt, pszGuidRadAuth); // Open the auth servers key
//
dwErr = RegCreateKeyExW( pInfo->hkAuthProviders, pszPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &pInfo->hkAuthServers, NULL); if (dwErr != NO_ERROR) { break; } } }
// Open the accounting keys
//
if (pNode->bEnableAcct) { if (pInfo->hkAcctProviders == NULL) { // Open the auth providers key
//
dwErr = RegOpenKeyExW( hkRouter, pszAccounting, 0, KEY_ALL_ACCESS, &pInfo->hkAcctProviders); if (dwErr != NO_ERROR) { break; }
// Generate the servers key name
//
wsprintfW(pszPath, pszRadServersFmt, pszGuidRadAcct); // Open the auth servers key
//
dwErr = RegCreateKeyExW( pInfo->hkAcctProviders, pszPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &pInfo->hkAcctServers, NULL); if (dwErr != NO_ERROR) { break; } } }
} while (FALSE);
// Cleanup
{ }
return dwErr; }
//
// Cleans up info from radius installation
//
DWORD RadCloseRegKeys( IN RAD_CONFIG_INFO* pInfo) { if (pInfo) { if (pInfo->hkAuthServers) { RegCloseKey(pInfo->hkAuthServers); pInfo->hkAuthServers = NULL; } if (pInfo->hkAuthProviders) { RegCloseKey(pInfo->hkAuthProviders); pInfo->hkAuthProviders = NULL; }
if (pInfo->hkAcctServers) { RegCloseKey(pInfo->hkAcctServers); pInfo->hkAcctServers = NULL; } if (pInfo->hkAcctProviders) { RegCloseKey(pInfo->hkAcctProviders); pInfo->hkAcctProviders = NULL; } } return NO_ERROR; }
//
// Adds the given server to the win2k section of the registry
//
DWORD RadInstallServer( IN HKEY hkRouter, IN RAD_SERVER_NODE* pNode, IN OUT RAD_CONFIG_INFO* pInfo) { DWORD dwErr = NO_ERROR;
do { // Based on the node, open or create any neccessary
// registry keys.
//
dwErr = RadOpenRegKeys(hkRouter, pNode, pInfo); if (dwErr != NO_ERROR) { break; }
if (pNode->bEnableAuth) { // Add the authentication server node
//
dwErr = RadNodeSave( pInfo->hkAuthServers, pNode, TRUE); if (dwErr != NO_ERROR) { break; }
// Set the active authentication provider
//
dwErr = RegSetValueExW( pInfo->hkAuthProviders, (PWCHAR)pszActiveProvider, 0, REG_SZ, (BYTE*)pszGuidRadAuth, (wcslen(pszGuidRadAuth) + 1) * sizeof(WCHAR)); if (dwErr != NO_ERROR) { break; } } if (pNode->bEnableAcct) { // Add the accounting server node
//
dwErr = RadNodeSave( pInfo->hkAcctServers, pNode, FALSE); if (dwErr != NO_ERROR) { break; }
// Set the active accounting provider
//
dwErr = RegSetValueExW( pInfo->hkAcctProviders, (PWCHAR)pszActiveProvider, 0, REG_SZ, (BYTE*)pszGuidRadAcct, (wcslen(pszGuidRadAcct) + 1) * sizeof(WCHAR)); if (dwErr != NO_ERROR) { break; } }
} while (FALSE);
// Cleanup
{ }
return dwErr; }
//
// Migrates radius settings from the settings key into the
// router key.
//
DWORD RadMigrateSettings( IN HKEY hkRouter, IN HKEY hkSettings) { DWORD dwErr = NO_ERROR; RAD_SERVER_LIST* pList = NULL; RAD_CONFIG_INFO* pInfo = NULL; RAD_SERVER_NODE* pNode = NULL;
do { // Generate the list of servers based on
// the loaded settings
dwErr = RadSrvListGenerate(hkSettings, &pList); if (dwErr != NO_ERROR) { break; }
// If there were no servers, then there's nothing
// to do
//
if (pList->pHead == NULL) { dwErr = NO_ERROR; break; }
// Allocate and init the info blob that will be
// used by the install funcs.
//
pInfo = (RAD_CONFIG_INFO*) UtlAlloc(sizeof(RAD_CONFIG_INFO)); if (pInfo == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } ZeroMemory(pInfo, sizeof(RAD_CONFIG_INFO));
// Install all of the servers
//
for (pNode = pList->pHead; pNode; pNode = pNode->pNext) { RadInstallServer(hkRouter, pNode, pInfo); }
} while (FALSE);
// Cleanup
{ if (pList) { RadSrvListCleanup(pList); } if (pInfo) { RadCloseRegKeys(pInfo); UtlFree(pInfo); } }
return dwErr; }
//
// Performs the upgrade work
//
DWORD RadiusToRouterUpgrade( IN PWCHAR pszFile) { DWORD dwErr = NO_ERROR; HKEY hkRouter = NULL, hkTemp = NULL, hkSettings = NULL;
do { // Get the Router subkey
//
dwErr = UtlAccessRouterKey(&hkRouter); if (dwErr != NO_ERROR) { break; } // Load registry data that has been saved off
//
dwErr = UtlLoadSavedSettings( hkRouter, (PWCHAR)pszTempRegKey, pszFile, &hkTemp); if (dwErr != NO_ERROR) { PrintMessage(L"Unable to load radius settings.\n"); break; }
// Load the settings key
//
dwErr = RegOpenKeyExW( hkTemp, pszServers, 0, KEY_ALL_ACCESS, &hkSettings); if (dwErr != NO_ERROR) { break; }
// Migrate radius information
//
dwErr = RadMigrateSettings(hkRouter, hkSettings); if (dwErr != NO_ERROR) { PrintMessage(L"Unable to migrate radius settings.\n"); break; }
} while (FALSE);
// Cleanup
{ if (hkSettings) { RegCloseKey(hkSettings); } if (hkTemp) { UtlDeleteRegistryTree(hkTemp); RegCloseKey(hkTemp); RegDeleteKey(hkRouter, pszTempRegKey); } if (hkRouter) { RegCloseKey(hkRouter); } }
return dwErr; }
|