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.

389 lines
10 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) Microsoft Corporation
  4. //
  5. // SYNOPSIS
  6. //
  7. // Defines the class RadiusExtension
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #include "Precompiled.h"
  11. #include "ias.h"
  12. #include "new"
  13. #include "extension.h"
  14. RadiusExtension::RadiusExtension() throw ()
  15. : name(0),
  16. module(0),
  17. initialized(false),
  18. RadiusExtensionInit(0),
  19. RadiusExtensionTerm(0),
  20. RadiusExtensionProcess(0),
  21. RadiusExtensionProcessEx(0),
  22. RadiusExtensionFreeAttributes(0),
  23. RadiusExtensionProcess2(0)
  24. {
  25. }
  26. RadiusExtension::~RadiusExtension() throw ()
  27. {
  28. if (initialized && (RadiusExtensionTerm != 0))
  29. {
  30. RadiusExtensionTerm();
  31. }
  32. if (module != 0)
  33. {
  34. FreeLibrary(module);
  35. }
  36. delete[] name;
  37. }
  38. // Load the extension DLL.
  39. DWORD RadiusExtension::Load(const wchar_t* dllPath) throw ()
  40. {
  41. IASTracePrintf("Loading extension %S", dllPath);
  42. // Save the name of the module.
  43. const wchar_t* fileName = ExtractFileNameFromPath(dllPath);
  44. name = new (std::nothrow) wchar_t[wcslen(fileName) + 1];
  45. if (name == 0)
  46. {
  47. return ERROR_NOT_ENOUGH_MEMORY;
  48. }
  49. wcscpy(name, fileName);
  50. // Load the extension DLL.
  51. module = LoadLibraryW(dllPath);
  52. if (module == 0)
  53. {
  54. DWORD error = GetLastError();
  55. IASTraceFailure("LoadLibraryW", error);
  56. return error;
  57. }
  58. // Look-up the entry points.
  59. RadiusExtensionInit =
  60. reinterpret_cast<PRADIUS_EXTENSION_INIT>(
  61. GetProcAddress(
  62. module,
  63. RADIUS_EXTENSION_INIT
  64. )
  65. );
  66. RadiusExtensionTerm =
  67. reinterpret_cast<PRADIUS_EXTENSION_TERM>(
  68. GetProcAddress(
  69. module,
  70. RADIUS_EXTENSION_TERM
  71. )
  72. );
  73. RadiusExtensionProcess =
  74. reinterpret_cast<PRADIUS_EXTENSION_PROCESS>(
  75. GetProcAddress(
  76. module,
  77. RADIUS_EXTENSION_PROCESS
  78. )
  79. );
  80. RadiusExtensionProcessEx =
  81. reinterpret_cast<PRADIUS_EXTENSION_PROCESS_EX>(
  82. GetProcAddress(
  83. module,
  84. RADIUS_EXTENSION_PROCESS_EX
  85. )
  86. );
  87. RadiusExtensionFreeAttributes =
  88. reinterpret_cast<PRADIUS_EXTENSION_FREE_ATTRIBUTES>(
  89. GetProcAddress(
  90. module,
  91. RADIUS_EXTENSION_FREE_ATTRIBUTES
  92. )
  93. );
  94. RadiusExtensionProcess2 =
  95. reinterpret_cast<PRADIUS_EXTENSION_PROCESS_2>(
  96. GetProcAddress(
  97. module,
  98. RADIUS_EXTENSION_PROCESS2
  99. )
  100. );
  101. // Validate the entry points.
  102. if ((RadiusExtensionProcess == 0) &&
  103. (RadiusExtensionProcessEx == 0) &&
  104. (RadiusExtensionProcess2 == 0))
  105. {
  106. IASTraceString(
  107. "Either RadiusExtensionProcess, RadiusExtensionProcessEx, or "
  108. "RadiusExtensionProcess2 must be defined."
  109. );
  110. return ERROR_PROC_NOT_FOUND;
  111. }
  112. if ((RadiusExtensionProcessEx != 0) && (RadiusExtensionFreeAttributes == 0))
  113. {
  114. IASTraceString(
  115. "RadiusExtensionFreeAttributes must be defined if "
  116. "RadiusExtensionProcessEx is defined."
  117. );
  118. return ERROR_PROC_NOT_FOUND;
  119. }
  120. // Initialize the DLL.
  121. if (RadiusExtensionInit != 0)
  122. {
  123. DWORD error = RadiusExtensionInit();
  124. if (error != NO_ERROR)
  125. {
  126. IASTraceFailure("RadiusExtensionInit", error);
  127. return error;
  128. }
  129. }
  130. initialized = true;
  131. return NO_ERROR;
  132. }
  133. DWORD RadiusExtension::Process(
  134. RADIUS_EXTENSION_CONTROL_BLOCK* ecb
  135. ) const throw ()
  136. {
  137. IASTracePrintf("Invoking extension %S", name);
  138. DWORD retval;
  139. if (RadiusExtensionProcess2 != 0)
  140. {
  141. retval = RadiusExtensionProcess2(ecb);
  142. IASTracePrintf("RadiusExtensionProcess2 returned %lu", retval);
  143. return retval;
  144. }
  145. // Determine the allowed actions and attributes for an old-style extension.
  146. unsigned allowedActions = 0;
  147. RADIUS_ATTRIBUTE* inAttrs = 0;
  148. switch (MAKELONG(ecb->repPoint, ecb->rcResponseType))
  149. {
  150. case MAKELONG(repAuthentication, rcUnknown):
  151. {
  152. allowedActions = (acceptAllowed | rejectAllowed);
  153. inAttrs = CreateExtensionAttributes(ecb);
  154. break;
  155. }
  156. case MAKELONG(repAuthorization, rcAccessAccept):
  157. {
  158. allowedActions = rejectAllowed;
  159. inAttrs = CreateAuthorizationAttributes(ecb);
  160. break;
  161. }
  162. case MAKELONG(repAuthentication, rcAccountingResponse):
  163. {
  164. inAttrs = CreateExtensionAttributes(ecb);
  165. break;
  166. }
  167. case MAKELONG(repAuthorization, rcAccountingResponse):
  168. {
  169. inAttrs = CreateAuthorizationAttributes(ecb);
  170. break;
  171. }
  172. case MAKELONG(repAuthorization, rcUnknown):
  173. {
  174. ecb->SetResponseType(ecb, rcAccountingResponse);
  175. inAttrs = CreateAuthorizationAttributes(ecb);
  176. break;
  177. }
  178. default:
  179. {
  180. // This is one of the combinations that doesn't get sent to old-style
  181. // extensions.
  182. // old-style Authorization dlls are called only when the return
  183. // type is known
  184. return NO_ERROR;
  185. }
  186. }
  187. if (inAttrs == 0)
  188. {
  189. return ERROR_NOT_ENOUGH_MEMORY;
  190. }
  191. RADIUS_ATTRIBUTE* outAttrs = 0;
  192. RADIUS_ACTION action = raContinue;
  193. RADIUS_ACTION* pAction = (allowedActions != 0) ? &action : 0;
  194. if (RadiusExtensionProcessEx != 0)
  195. {
  196. retval = RadiusExtensionProcessEx(inAttrs, &outAttrs, pAction);
  197. IASTracePrintf("RadiusExtensionProcessEx returned %lu", retval);
  198. }
  199. else
  200. {
  201. retval = RadiusExtensionProcess(inAttrs, pAction);
  202. IASTracePrintf("RadiusExtensionProcess returned %lu", retval);
  203. }
  204. delete[] inAttrs;
  205. if (retval != NO_ERROR)
  206. {
  207. return retval;
  208. }
  209. // Process the action code.
  210. RADIUS_CODE outAttrDst;
  211. if ((action == raAccept) && ((allowedActions & acceptAllowed) != 0))
  212. {
  213. ecb->SetResponseType(ecb, rcAccessAccept);
  214. outAttrDst = rcAccessAccept;
  215. }
  216. else if ((action == raReject) && ((allowedActions & rejectAllowed) != 0))
  217. {
  218. ecb->SetResponseType(ecb, rcAccessReject);
  219. outAttrDst = rcAccessReject;
  220. }
  221. else
  222. {
  223. outAttrDst = rcAccessAccept;
  224. }
  225. // Insert the returned attributes.
  226. if (outAttrs != 0)
  227. {
  228. RADIUS_ATTRIBUTE_ARRAY* array = ecb->GetResponse(ecb, outAttrDst);
  229. for (RADIUS_ATTRIBUTE* outAttrsIter = outAttrs;
  230. outAttrsIter->dwAttrType != ratMinimum;
  231. ++outAttrsIter)
  232. {
  233. retval = array->Add(array, outAttrsIter);
  234. if (retval != NO_ERROR)
  235. {
  236. break;
  237. }
  238. }
  239. RadiusExtensionFreeAttributes(outAttrs);
  240. }
  241. return retval;
  242. }
  243. RADIUS_ATTRIBUTE* RadiusExtension::CreateExtensionAttributes(
  244. RADIUS_EXTENSION_CONTROL_BLOCK* ecb
  245. ) throw ()
  246. {
  247. // ExtensionDLLs just get incoming attributes.
  248. RADIUS_ATTRIBUTE_ARRAY* request = ecb->GetRequest(ecb);
  249. size_t numRequestAttrs = request->GetSize(request);
  250. // Allocate extra space for ratCode and the array terminator.
  251. size_t numAttrs = numRequestAttrs + 2;
  252. RADIUS_ATTRIBUTE* attrs = new (std::nothrow) RADIUS_ATTRIBUTE[numAttrs];
  253. if (attrs == 0)
  254. {
  255. return 0;
  256. }
  257. RADIUS_ATTRIBUTE* dst = attrs;
  258. // New style extensions don't use ratCode, so we have to add it ourself.
  259. dst->dwAttrType = ratCode;
  260. dst->fDataType = rdtInteger;
  261. dst->cbDataLength = sizeof(DWORD);
  262. dst->dwValue = ecb->rcRequestType;
  263. ++dst;
  264. // Now add the rest of the incoming attributes.
  265. for (size_t i = 0; i < numRequestAttrs; ++i)
  266. {
  267. *dst = *(request->AttributeAt(request, i));
  268. ++dst;
  269. }
  270. // Finally, add the array terminator.
  271. dst->dwAttrType = ratMinimum;
  272. return attrs;
  273. }
  274. RADIUS_ATTRIBUTE* RadiusExtension::CreateAuthorizationAttributes(
  275. RADIUS_EXTENSION_CONTROL_BLOCK* ecb
  276. ) throw ()
  277. {
  278. // AuthorizationDLLs get internal attributes from the request ...
  279. RADIUS_ATTRIBUTE_ARRAY* request = ecb->GetRequest(ecb);
  280. // We're not going to use all the request attributes, but it's easier to
  281. // just allocate the extra space, rather than looping through the attributes
  282. // to determine how many we will really use.
  283. size_t numRequestAttrs = request->GetSize(request);
  284. // ... and any outgoing attributes.
  285. RADIUS_ATTRIBUTE_ARRAY* response = ecb->GetResponse(
  286. ecb,
  287. ecb->rcResponseType
  288. );
  289. // passed a valid type, shoude get an array back
  290. _ASSERT(response);
  291. size_t numResponseAttrs = response->GetSize(response);
  292. // Save space for ratCode and the array terminator.
  293. size_t numAttrs = numRequestAttrs + numResponseAttrs + 2;
  294. RADIUS_ATTRIBUTE* attrs = new (std::nothrow) RADIUS_ATTRIBUTE[numAttrs];
  295. if (attrs == 0)
  296. {
  297. return 0;
  298. }
  299. RADIUS_ATTRIBUTE* dst = attrs;
  300. // New style extensions don't use ratCode, so we have to add it ourself.
  301. dst->dwAttrType = ratCode;
  302. dst->fDataType = rdtInteger;
  303. dst->cbDataLength = sizeof(DWORD);
  304. dst->dwValue = ecb->rcResponseType;
  305. ++dst;
  306. // Add internal attributes from the request.
  307. for (size_t i = 0; i < numRequestAttrs; ++i)
  308. {
  309. const RADIUS_ATTRIBUTE* attr = request->AttributeAt(request, i);
  310. if (attr->dwAttrType > 255)
  311. {
  312. *dst = *attr;
  313. ++dst;
  314. }
  315. }
  316. // Add response attributes.
  317. for (size_t i = 0; i < numResponseAttrs; ++i)
  318. {
  319. *dst = *(response->AttributeAt(response, i));
  320. ++dst;
  321. }
  322. // Finally, add the array terminator.
  323. dst->dwAttrType = ratMinimum;
  324. return attrs;
  325. }
  326. const wchar_t* ExtractFileNameFromPath(const wchar_t* path) throw ()
  327. {
  328. const wchar_t* lastSlash = wcsrchr(path, L'\\');
  329. return (lastSlash == 0) ? path : (lastSlash + 1);
  330. }