windows-nt/Source/XPSP1/NT/net/rras/upgrade/steelhead2nt5/radius.c
2020-09-26 16:20:57 +08:00

776 lines
17 KiB
C

/*
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(&paramTable[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;
}