Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

470 lines
11 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1998
  6. //
  7. // File: radbal.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // **********************************************************************
  11. // Load balancing code for RADIUS Servers.
  12. // **********************************************************************
  13. #include <stdafx.h>
  14. #include <assert.h>
  15. #include "radcfg.h"
  16. //nclude "radclnt.h"
  17. #include "radbal.h"
  18. // ======================== CRadiusServers ==============================
  19. CRadiusServers::CRadiusServers()
  20. {
  21. m_pServerList = NULL;
  22. m_pCurrentServer = NULL;
  23. m_pDeletedServers = NULL;
  24. m_dwUnique = 1;
  25. InitializeCriticalSection(&m_cs);
  26. } // CRadiusServers()
  27. // ========================= ~CRadiusServers =============================
  28. CRadiusServers::~CRadiusServers()
  29. {
  30. RADIUSSERVER *pServer;
  31. EnterCriticalSection(&m_cs);
  32. { // free all items in linked list
  33. pServer = m_pServerList;
  34. while (pServer != NULL)
  35. {
  36. m_pServerList = pServer->pNext;
  37. // Ensure that the password is zeroed
  38. ZeroMemory(pServer, sizeof(*pServer));
  39. LocalFree(pServer);
  40. pServer = m_pServerList;
  41. }
  42. }
  43. LeaveCriticalSection(&m_cs);
  44. assert(m_pServerList == NULL);
  45. DeleteCriticalSection(&m_cs);
  46. } // ~CRadiusServers()
  47. // ========================= AddServer ==================================
  48. // Adds a RADIUS server node into the linked list of avialable servers.
  49. // INPUT:
  50. // pRadiusServer - struct defining attributes for RADIUS server.
  51. // dwUnique - insert before server with this dwUnique value
  52. // dwUnique = 0, means add to head
  53. // dwUnique = -1, means add to tail
  54. // RETURN:
  55. // ERROR_SUCCESS - Server Node added successfully
  56. // Win32 error code - unsuccessfully in adding server node.
  57. DWORD CRadiusServers::AddServer(RADIUSSERVER *pRadiusServer,
  58. LONG_PTR dwUnique)
  59. {
  60. __try
  61. {
  62. RADIUSSERVER *pNewServer;
  63. RADIUSSERVER *pServer;
  64. RADIUSSERVER *pPrevServer;
  65. m_dwUnique++;
  66. assert(pRadiusServer != NULL);
  67. // Allocate space for node
  68. pNewServer = (RADIUSSERVER *) LocalAlloc(LPTR, sizeof(RADIUSSERVER));
  69. if (pNewServer == NULL)
  70. __leave;
  71. // Set the unqiue value (this will be used to index this server
  72. // by the UI).
  73. pRadiusServer->dwUnique = m_dwUnique;
  74. // Copy server data
  75. *pNewServer = *pRadiusServer;
  76. EnterCriticalSection(&m_cs);
  77. {
  78. // Find location to insert at
  79. if (dwUnique == 0)
  80. {
  81. pServer = m_pServerList;
  82. pPrevServer = NULL;
  83. }
  84. else
  85. {
  86. pServer = m_pServerList;
  87. pPrevServer = NULL;
  88. while (pServer)
  89. {
  90. if (pServer->dwUnique == (DWORD) dwUnique)
  91. break;
  92. pPrevServer = pServer;
  93. pServer = pServer->pNext;
  94. }
  95. // If not found, add to the head of the list
  96. if (!pServer)
  97. {
  98. pServer = m_pServerList;
  99. pPrevServer = NULL;
  100. }
  101. }
  102. // Add node to linked list
  103. if (pPrevServer)
  104. pPrevServer->pNext = pNewServer;
  105. if (pServer == m_pServerList)
  106. {
  107. Assert(!pPrevServer);
  108. m_pServerList = pNewServer;
  109. }
  110. pNewServer->pNext = pServer;
  111. }
  112. LeaveCriticalSection(&m_cs);
  113. SetLastError(ERROR_SUCCESS);
  114. } // __try
  115. __finally
  116. {
  117. } // __finally
  118. return (GetLastError());
  119. } // AddServer()
  120. // ========================= ValidateServer =================================
  121. // Used to update the status of the RADIUS servers.
  122. // All servers start with a score of MAXSCORE
  123. // Every time a server responding the score is increased by INCSCORE to a max of MAXSCORE
  124. // Every time a server fails to respond the score is decreased by DECSCORE to a min of MINSCORE
  125. // Servers with the highest score are selected in a roundrobin method for servers with equal score
  126. //
  127. // INPUT:
  128. // fResponding - Indicates if the server is responding or not
  129. // OUTPUT:
  130. //
  131. VOID CRadiusServers::ValidateServer(RADIUSSERVER *pServer, BOOL fResponding)
  132. {
  133. assert(pServer != NULL && (fResponding == TRUE || fResponding == FALSE));
  134. EnterCriticalSection(&m_cs);
  135. {
  136. // pNext point to to real pointer of this node in the linked list
  137. pServer = pServer->pNext;
  138. assert(pServer);
  139. if (fResponding)
  140. {
  141. pServer->cScore = min(MAXSCORE, pServer->cScore + INCSCORE);
  142. }
  143. else
  144. {
  145. pServer->cScore = max(MINSCORE, pServer->cScore - DECSCORE);
  146. }
  147. }
  148. LeaveCriticalSection(&m_cs);
  149. } // ValidateServer()
  150. // ======================== GetNextServer ======================================
  151. // Used to cycle thru all the RADIUS servers.
  152. // INPUT:
  153. // fFirst - TRUE if u want to get the root node.
  154. // OUTPUT:
  155. // pointer to next RADIUS server descriptor.
  156. RADIUSSERVER *CRadiusServers::GetNextServer(BOOL fFirst)
  157. {
  158. RADIUSSERVER *pServer = NULL;
  159. assert(fFirst == TRUE || fFirst == FALSE);
  160. EnterCriticalSection(&m_cs);
  161. {
  162. if (fFirst == TRUE)
  163. m_pCurrentServer = m_pServerList;
  164. else
  165. {
  166. assert(m_pCurrentServer);
  167. m_pCurrentServer = m_pCurrentServer->pNext;
  168. }
  169. // Increment unique packet id counter
  170. if (m_pCurrentServer != NULL)
  171. m_pCurrentServer->bIdentifier ++;
  172. pServer = m_pCurrentServer;
  173. }
  174. LeaveCriticalSection(&m_cs);
  175. return (pServer);
  176. } // GetNextServer()
  177. VOID CRadiusServers::MoveServer(LONG_PTR dwUnique, BOOL fUp)
  178. {
  179. RADIUSSERVER *pServerTemp = NULL;
  180. RADIUSSERVER *pServer;
  181. RADIUSSERVER *pPrevServer;
  182. RADIUSSERVER *pPrevPrevServer;
  183. Assert(dwUnique);
  184. if (m_pServerList == NULL)
  185. return;
  186. EnterCriticalSection(&m_cs);
  187. {
  188. if (m_pServerList->dwUnique == (DWORD) dwUnique)
  189. {
  190. pPrevPrevServer = NULL;
  191. pPrevServer = NULL;
  192. pServer = m_pServerList;
  193. }
  194. else
  195. {
  196. pPrevPrevServer = NULL;
  197. pPrevServer = m_pServerList;
  198. pServer = pPrevServer->pNext;
  199. while (pServer)
  200. {
  201. if (pServer->dwUnique == (DWORD) dwUnique)
  202. break;
  203. pPrevPrevServer = pPrevServer;
  204. pPrevServer = pServer;
  205. pServer = pServer->pNext;
  206. }
  207. }
  208. if (pServer)
  209. {
  210. if (fUp)
  211. {
  212. if (m_pServerList == pPrevServer)
  213. m_pServerList = pServer;
  214. if (pPrevServer)
  215. pPrevServer->pNext = pServer->pNext;
  216. pServer->pNext = pPrevServer;
  217. if (pPrevPrevServer)
  218. pPrevPrevServer->pNext = pServer;
  219. }
  220. else
  221. {
  222. if (pPrevServer)
  223. pPrevServer->pNext = pServer->pNext;
  224. if (pServer->pNext)
  225. {
  226. if (m_pServerList == pServer)
  227. m_pServerList = pServer->pNext;
  228. pServerTemp = pServer->pNext->pNext;
  229. pServer->pNext->pNext = pServer;
  230. pServer->pNext = pServerTemp;
  231. }
  232. }
  233. }
  234. }
  235. LeaveCriticalSection(&m_cs);
  236. }
  237. DWORD CRadiusServers::DeleteServer(LONG_PTR dwUnique, BOOL fRemoveLSAEntry)
  238. {
  239. RADIUSSERVER * pServer = m_pServerList;
  240. RADIUSSERVER * pDeadServer;
  241. if (pServer == NULL)
  242. return 0;
  243. // check the first one
  244. if (pServer->dwUnique == (DWORD) dwUnique)
  245. {
  246. m_pServerList = pServer->pNext;
  247. if (fRemoveLSAEntry)
  248. {
  249. AddToDeletedServerList(pServer);
  250. }
  251. else
  252. {
  253. // Ensure that the password is zeroed
  254. ZeroMemory(pServer, sizeof(*pServer));
  255. LocalFree(pServer);
  256. }
  257. return 0;
  258. }
  259. for (pServer = m_pServerList; pServer->pNext; pServer=pServer->pNext)
  260. {
  261. if (pServer->pNext->dwUnique == (DWORD) dwUnique)
  262. {
  263. pDeadServer = pServer->pNext;
  264. pServer->pNext = pServer->pNext->pNext;
  265. if (fRemoveLSAEntry)
  266. {
  267. AddToDeletedServerList(pDeadServer);
  268. }
  269. else
  270. {
  271. ZeroMemory(pDeadServer, sizeof(*pDeadServer));
  272. LocalFree(pDeadServer);
  273. }
  274. break;
  275. }
  276. }
  277. return 0;
  278. }
  279. /*!--------------------------------------------------------------------------
  280. CRadiusServers::AddToDeletedServerList
  281. -
  282. Author: KennT
  283. ---------------------------------------------------------------------------*/
  284. void CRadiusServers::AddToDeletedServerList(RADIUSSERVER *pServer)
  285. {
  286. Assert(pServer);
  287. // Add this server to the head of our list
  288. pServer->pNext = m_pDeletedServers;
  289. m_pDeletedServers = pServer;
  290. }
  291. /*!--------------------------------------------------------------------------
  292. CRadiusServers::ClearDeletedServerList
  293. -
  294. Author: KennT
  295. ---------------------------------------------------------------------------*/
  296. void CRadiusServers::ClearDeletedServerList(LPCTSTR pszServerName)
  297. {
  298. RADIUSSERVER * pDeadServer;
  299. RADIUSSERVER * pNextServer;
  300. // Remove the appropriate RADIUS servers from the LSA policy
  301. DeleteRadiusServers(pszServerName, GetFirstDeletedServer());
  302. // Clear out the server list
  303. for (pDeadServer=GetFirstDeletedServer();
  304. pDeadServer;
  305. )
  306. {
  307. pNextServer = pDeadServer->pNext;
  308. // Remove the entry from the list
  309. // Ensure that the password is zeroed
  310. ZeroMemory(pDeadServer, sizeof(*pDeadServer));
  311. LocalFree(pDeadServer);
  312. pDeadServer = pNextServer;
  313. }
  314. // ok, there is nothing left to point to
  315. m_pDeletedServers = NULL;
  316. }
  317. /*!--------------------------------------------------------------------------
  318. CRadiusServers::FreeAllServers
  319. -
  320. Author: KennT
  321. ---------------------------------------------------------------------------*/
  322. void CRadiusServers::FreeAllServers()
  323. {
  324. RADIUSSERVER * pServer = NULL;
  325. RADIUSSERVER * pNextServer = NULL;
  326. for (pServer = m_pServerList;
  327. pServer;
  328. )
  329. {
  330. pNextServer = pServer->pNext;
  331. ZeroMemory(pServer, sizeof(*pServer));
  332. LocalFree(pServer);
  333. pServer = pNextServer;
  334. }
  335. m_pServerList = NULL;
  336. }
  337. BOOL CRadiusServers::FindServer(DWORD dwUnique, RADIUSSERVER **ppServer)
  338. {
  339. RADIUSSERVER * pServer = m_pServerList;
  340. while (pServer)
  341. {
  342. if (pServer->dwUnique == dwUnique)
  343. {
  344. if (ppServer)
  345. *ppServer = pServer;
  346. return TRUE;
  347. }
  348. pServer = pServer->pNext;
  349. }
  350. return FALSE;
  351. }
  352. BOOL CRadiusServers::FindServer(LPCTSTR pszName, RADIUSSERVER **ppServer)
  353. {
  354. RADIUSSERVER * pServer = m_pServerList;
  355. while (pServer)
  356. {
  357. if (StrCmp(pServer->szName, pszName) == 0)
  358. {
  359. if (ppServer)
  360. *ppServer = pServer;
  361. return TRUE;
  362. }
  363. pServer = pServer->pNext;
  364. }
  365. return FALSE;
  366. }
  367. void RadiusServer::UseDefaults()
  368. {
  369. szName[0] = 0;
  370. wszSecret[0] = 0;
  371. cchSecret = 0;
  372. Timeout.tv_sec = DEFTIMEOUT;
  373. cRetries = 0;
  374. cScore = MAXSCORE;
  375. AuthPort = DEFAUTHPORT;
  376. AcctPort = DEFACCTPORT;
  377. IPAddress.sin_family = AF_INET;
  378. IPAddress.sin_port = htons((SHORT) AuthPort);
  379. IPAddress.sin_addr.s_addr = 0;
  380. fAccountingOnOff = FALSE;
  381. bIdentifier = 0;
  382. lPacketID = 0;
  383. fUseDigitalSignatures = FALSE;
  384. fPersisted = FALSE;
  385. }