471 lines
11 KiB
C++
471 lines
11 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1998 - 1998
|
|
//
|
|
// File: radbal.cpp
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
// **********************************************************************
|
|
// Load balancing code for RADIUS Servers.
|
|
// **********************************************************************
|
|
#include <stdafx.h>
|
|
#include <assert.h>
|
|
|
|
#include "radcfg.h"
|
|
//nclude "radclnt.h"
|
|
#include "radbal.h"
|
|
|
|
// ======================== CRadiusServers ==============================
|
|
|
|
CRadiusServers::CRadiusServers()
|
|
{
|
|
m_pServerList = NULL;
|
|
m_pCurrentServer = NULL;
|
|
m_pDeletedServers = NULL;
|
|
m_dwUnique = 1;
|
|
InitializeCriticalSection(&m_cs);
|
|
} // CRadiusServers()
|
|
|
|
|
|
// ========================= ~CRadiusServers =============================
|
|
|
|
CRadiusServers::~CRadiusServers()
|
|
{
|
|
RADIUSSERVER *pServer;
|
|
|
|
EnterCriticalSection(&m_cs);
|
|
{ // free all items in linked list
|
|
pServer = m_pServerList;
|
|
while (pServer != NULL)
|
|
{
|
|
m_pServerList = pServer->pNext;
|
|
|
|
// Ensure that the password is zeroed
|
|
ZeroMemory(pServer, sizeof(*pServer));
|
|
|
|
LocalFree(pServer);
|
|
pServer = m_pServerList;
|
|
}
|
|
}
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
assert(m_pServerList == NULL);
|
|
DeleteCriticalSection(&m_cs);
|
|
} // ~CRadiusServers()
|
|
|
|
|
|
// ========================= AddServer ==================================
|
|
// Adds a RADIUS server node into the linked list of avialable servers.
|
|
// INPUT:
|
|
// pRadiusServer - struct defining attributes for RADIUS server.
|
|
// dwUnique - insert before server with this dwUnique value
|
|
// dwUnique = 0, means add to head
|
|
// dwUnique = -1, means add to tail
|
|
// RETURN:
|
|
// ERROR_SUCCESS - Server Node added successfully
|
|
// Win32 error code - unsuccessfully in adding server node.
|
|
|
|
DWORD CRadiusServers::AddServer(RADIUSSERVER *pRadiusServer,
|
|
LONG_PTR dwUnique)
|
|
{
|
|
__try
|
|
{
|
|
RADIUSSERVER *pNewServer;
|
|
RADIUSSERVER *pServer;
|
|
RADIUSSERVER *pPrevServer;
|
|
|
|
m_dwUnique++;
|
|
|
|
assert(pRadiusServer != NULL);
|
|
// Allocate space for node
|
|
pNewServer = (RADIUSSERVER *) LocalAlloc(LPTR, sizeof(RADIUSSERVER));
|
|
if (pNewServer == NULL)
|
|
__leave;
|
|
|
|
// Set the unqiue value (this will be used to index this server
|
|
// by the UI).
|
|
pRadiusServer->dwUnique = m_dwUnique;
|
|
|
|
// Copy server data
|
|
*pNewServer = *pRadiusServer;
|
|
|
|
EnterCriticalSection(&m_cs);
|
|
{
|
|
// Find location to insert at
|
|
if (dwUnique == 0)
|
|
{
|
|
pServer = m_pServerList;
|
|
pPrevServer = NULL;
|
|
}
|
|
else
|
|
{
|
|
pServer = m_pServerList;
|
|
pPrevServer = NULL;
|
|
|
|
while (pServer)
|
|
{
|
|
if (pServer->dwUnique == (DWORD) dwUnique)
|
|
break;
|
|
|
|
pPrevServer = pServer;
|
|
pServer = pServer->pNext;
|
|
}
|
|
|
|
// If not found, add to the head of the list
|
|
if (!pServer)
|
|
{
|
|
pServer = m_pServerList;
|
|
pPrevServer = NULL;
|
|
}
|
|
}
|
|
|
|
// Add node to linked list
|
|
if (pPrevServer)
|
|
pPrevServer->pNext = pNewServer;
|
|
|
|
if (pServer == m_pServerList)
|
|
{
|
|
Assert(!pPrevServer);
|
|
m_pServerList = pNewServer;
|
|
}
|
|
|
|
pNewServer->pNext = pServer;
|
|
}
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
SetLastError(ERROR_SUCCESS);
|
|
} // __try
|
|
|
|
__finally
|
|
{
|
|
} // __finally
|
|
|
|
return (GetLastError());
|
|
} // AddServer()
|
|
|
|
// ========================= ValidateServer =================================
|
|
// Used to update the status of the RADIUS servers.
|
|
// All servers start with a score of MAXSCORE
|
|
// Every time a server responding the score is increased by INCSCORE to a max of MAXSCORE
|
|
// Every time a server fails to respond the score is decreased by DECSCORE to a min of MINSCORE
|
|
// Servers with the highest score are selected in a roundrobin method for servers with equal score
|
|
//
|
|
// INPUT:
|
|
// fResponding - Indicates if the server is responding or not
|
|
// OUTPUT:
|
|
//
|
|
|
|
VOID CRadiusServers::ValidateServer(RADIUSSERVER *pServer, BOOL fResponding)
|
|
{
|
|
assert(pServer != NULL && (fResponding == TRUE || fResponding == FALSE));
|
|
|
|
EnterCriticalSection(&m_cs);
|
|
{
|
|
// pNext point to to real pointer of this node in the linked list
|
|
pServer = pServer->pNext;
|
|
assert(pServer);
|
|
|
|
if (fResponding)
|
|
{
|
|
pServer->cScore = min(MAXSCORE, pServer->cScore + INCSCORE);
|
|
}
|
|
else
|
|
{
|
|
pServer->cScore = max(MINSCORE, pServer->cScore - DECSCORE);
|
|
}
|
|
}
|
|
LeaveCriticalSection(&m_cs);
|
|
} // ValidateServer()
|
|
|
|
// ======================== GetNextServer ======================================
|
|
// Used to cycle thru all the RADIUS servers.
|
|
// INPUT:
|
|
// fFirst - TRUE if u want to get the root node.
|
|
// OUTPUT:
|
|
// pointer to next RADIUS server descriptor.
|
|
|
|
RADIUSSERVER *CRadiusServers::GetNextServer(BOOL fFirst)
|
|
{
|
|
RADIUSSERVER *pServer = NULL;
|
|
|
|
assert(fFirst == TRUE || fFirst == FALSE);
|
|
|
|
EnterCriticalSection(&m_cs);
|
|
{
|
|
if (fFirst == TRUE)
|
|
m_pCurrentServer = m_pServerList;
|
|
else
|
|
{
|
|
assert(m_pCurrentServer);
|
|
m_pCurrentServer = m_pCurrentServer->pNext;
|
|
}
|
|
|
|
// Increment unique packet id counter
|
|
if (m_pCurrentServer != NULL)
|
|
m_pCurrentServer->bIdentifier ++;
|
|
|
|
pServer = m_pCurrentServer;
|
|
}
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return (pServer);
|
|
} // GetNextServer()
|
|
|
|
VOID CRadiusServers::MoveServer(LONG_PTR dwUnique, BOOL fUp)
|
|
{
|
|
RADIUSSERVER *pServerTemp = NULL;
|
|
RADIUSSERVER *pServer;
|
|
RADIUSSERVER *pPrevServer;
|
|
RADIUSSERVER *pPrevPrevServer;
|
|
|
|
Assert(dwUnique);
|
|
|
|
if (m_pServerList == NULL)
|
|
return;
|
|
|
|
EnterCriticalSection(&m_cs);
|
|
{
|
|
if (m_pServerList->dwUnique == (DWORD) dwUnique)
|
|
{
|
|
pPrevPrevServer = NULL;
|
|
pPrevServer = NULL;
|
|
pServer = m_pServerList;
|
|
}
|
|
else
|
|
{
|
|
pPrevPrevServer = NULL;
|
|
pPrevServer = m_pServerList;
|
|
pServer = pPrevServer->pNext;
|
|
|
|
while (pServer)
|
|
{
|
|
if (pServer->dwUnique == (DWORD) dwUnique)
|
|
break;
|
|
|
|
pPrevPrevServer = pPrevServer;
|
|
pPrevServer = pServer;
|
|
pServer = pServer->pNext;
|
|
}
|
|
}
|
|
|
|
if (pServer)
|
|
{
|
|
if (fUp)
|
|
{
|
|
if (m_pServerList == pPrevServer)
|
|
m_pServerList = pServer;
|
|
|
|
if (pPrevServer)
|
|
pPrevServer->pNext = pServer->pNext;
|
|
|
|
pServer->pNext = pPrevServer;
|
|
|
|
if (pPrevPrevServer)
|
|
pPrevPrevServer->pNext = pServer;
|
|
}
|
|
else
|
|
{
|
|
if (pPrevServer)
|
|
pPrevServer->pNext = pServer->pNext;
|
|
if (pServer->pNext)
|
|
{
|
|
if (m_pServerList == pServer)
|
|
m_pServerList = pServer->pNext;
|
|
|
|
pServerTemp = pServer->pNext->pNext;
|
|
pServer->pNext->pNext = pServer;
|
|
pServer->pNext = pServerTemp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
}
|
|
|
|
|
|
DWORD CRadiusServers::DeleteServer(LONG_PTR dwUnique, BOOL fRemoveLSAEntry)
|
|
{
|
|
RADIUSSERVER * pServer = m_pServerList;
|
|
RADIUSSERVER * pDeadServer;
|
|
|
|
if (pServer == NULL)
|
|
return 0;
|
|
|
|
// check the first one
|
|
if (pServer->dwUnique == (DWORD) dwUnique)
|
|
{
|
|
m_pServerList = pServer->pNext;
|
|
|
|
if (fRemoveLSAEntry)
|
|
{
|
|
AddToDeletedServerList(pServer);
|
|
}
|
|
else
|
|
{
|
|
// Ensure that the password is zeroed
|
|
ZeroMemory(pServer, sizeof(*pServer));
|
|
LocalFree(pServer);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
for (pServer = m_pServerList; pServer->pNext; pServer=pServer->pNext)
|
|
{
|
|
if (pServer->pNext->dwUnique == (DWORD) dwUnique)
|
|
{
|
|
pDeadServer = pServer->pNext;
|
|
pServer->pNext = pServer->pNext->pNext;
|
|
|
|
if (fRemoveLSAEntry)
|
|
{
|
|
AddToDeletedServerList(pDeadServer);
|
|
}
|
|
else
|
|
{
|
|
ZeroMemory(pDeadServer, sizeof(*pDeadServer));
|
|
LocalFree(pDeadServer);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
CRadiusServers::AddToDeletedServerList
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void CRadiusServers::AddToDeletedServerList(RADIUSSERVER *pServer)
|
|
{
|
|
Assert(pServer);
|
|
|
|
// Add this server to the head of our list
|
|
pServer->pNext = m_pDeletedServers;
|
|
m_pDeletedServers = pServer;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
CRadiusServers::ClearDeletedServerList
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void CRadiusServers::ClearDeletedServerList(LPCTSTR pszServerName)
|
|
{
|
|
RADIUSSERVER * pDeadServer;
|
|
RADIUSSERVER * pNextServer;
|
|
|
|
// Remove the appropriate RADIUS servers from the LSA policy
|
|
DeleteRadiusServers(pszServerName, GetFirstDeletedServer());
|
|
|
|
// Clear out the server list
|
|
for (pDeadServer=GetFirstDeletedServer();
|
|
pDeadServer;
|
|
)
|
|
{
|
|
pNextServer = pDeadServer->pNext;
|
|
|
|
// Remove the entry from the list
|
|
// Ensure that the password is zeroed
|
|
ZeroMemory(pDeadServer, sizeof(*pDeadServer));
|
|
LocalFree(pDeadServer);
|
|
|
|
pDeadServer = pNextServer;
|
|
}
|
|
|
|
// ok, there is nothing left to point to
|
|
m_pDeletedServers = NULL;
|
|
}
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
CRadiusServers::FreeAllServers
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void CRadiusServers::FreeAllServers()
|
|
{
|
|
RADIUSSERVER * pServer = NULL;
|
|
RADIUSSERVER * pNextServer = NULL;
|
|
|
|
for (pServer = m_pServerList;
|
|
pServer;
|
|
)
|
|
{
|
|
pNextServer = pServer->pNext;
|
|
|
|
ZeroMemory(pServer, sizeof(*pServer));
|
|
LocalFree(pServer);
|
|
|
|
pServer = pNextServer;
|
|
}
|
|
|
|
m_pServerList = NULL;
|
|
}
|
|
|
|
BOOL CRadiusServers::FindServer(DWORD dwUnique, RADIUSSERVER **ppServer)
|
|
{
|
|
RADIUSSERVER * pServer = m_pServerList;
|
|
|
|
while (pServer)
|
|
{
|
|
if (pServer->dwUnique == dwUnique)
|
|
{
|
|
if (ppServer)
|
|
*ppServer = pServer;
|
|
return TRUE;
|
|
}
|
|
pServer = pServer->pNext;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CRadiusServers::FindServer(LPCTSTR pszName, RADIUSSERVER **ppServer)
|
|
{
|
|
RADIUSSERVER * pServer = m_pServerList;
|
|
|
|
while (pServer)
|
|
{
|
|
if (StrCmp(pServer->szName, pszName) == 0)
|
|
{
|
|
if (ppServer)
|
|
*ppServer = pServer;
|
|
return TRUE;
|
|
}
|
|
pServer = pServer->pNext;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
void RadiusServer::UseDefaults()
|
|
{
|
|
szName[0] = 0;
|
|
wszSecret[0] = 0;
|
|
cchSecret = 0;
|
|
|
|
Timeout.tv_sec = DEFTIMEOUT;
|
|
cRetries = 0;
|
|
cScore = MAXSCORE;
|
|
|
|
AuthPort = DEFAUTHPORT;
|
|
AcctPort = DEFACCTPORT;
|
|
|
|
IPAddress.sin_family = AF_INET;
|
|
IPAddress.sin_port = htons((SHORT) AuthPort);
|
|
IPAddress.sin_addr.s_addr = 0;
|
|
|
|
fAccountingOnOff = FALSE;
|
|
bIdentifier = 0;
|
|
lPacketID = 0;
|
|
fUseDigitalSignatures = FALSE;
|
|
|
|
fPersisted = FALSE;
|
|
}
|
|
|