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.

462 lines
14 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // logresult.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // Defines the function IASRadiusLogResult.
  12. //
  13. ///////////////////////////////////////////////////////////////////////////////
  14. #include <radcommon.h>
  15. #include <iastlutl.h>
  16. #include <iasutil.h>
  17. #include <logresult.h>
  18. // Dummy attribute ID for the stringized reason code.
  19. const DWORD IAS_ATTRIBUTE_REASON_STRING = 0xBADF00D;
  20. // An empty string.
  21. WCHAR emptyString[1];
  22. // Create a newly-allocated copy of a string.
  23. PWSTR copyString(PCWSTR sz) throw ()
  24. {
  25. if (sz)
  26. {
  27. // Calculate the number of bytes.
  28. size_t nbyte = (wcslen(sz) + 1) * sizeof(WCHAR);
  29. // Allocate the memory.
  30. PVOID p = LocalAlloc(LMEM_FIXED, nbyte);
  31. if (p)
  32. {
  33. // Copy the string and return.
  34. return (PWSTR)memcpy(p, sz, nbyte);
  35. }
  36. }
  37. // If anything went wrong, return an empty string.
  38. return emptyString;
  39. }
  40. // Frees a string returned by copyString.
  41. void freeString(PWSTR sz) throw ()
  42. {
  43. if (sz != emptyString) { LocalFree(sz); }
  44. }
  45. // Format an integer value.
  46. PWSTR formatInteger(DWORD value) throw ()
  47. {
  48. WCHAR buffer[11], *p = buffer + 10;
  49. *p = L'\0';
  50. do { *--p = L'0' + (WCHAR)(value % 10); } while (value /= 10);
  51. return copyString(p);
  52. }
  53. // Format a parameter value.
  54. PWSTR formatParameter(DWORD value) throw ()
  55. {
  56. WCHAR buffer[13], *p = buffer + 12;
  57. *p = L'\0';
  58. do { *--p = L'0' + (WCHAR)(value % 10); } while (value /= 10);
  59. *--p = L'%';
  60. *--p = L'%';
  61. return copyString(p);
  62. }
  63. // Format the IAS_ATTRIBUTE_PROVIDER_TYPE value.
  64. PWSTR formatProviderType(DWORD type) throw ()
  65. {
  66. switch (type)
  67. {
  68. case IAS_PROVIDER_WINDOWS:
  69. return formatParameter(IASP_PROVIDER_WINDOWS);
  70. case IAS_PROVIDER_RADIUS_PROXY:
  71. return formatParameter(IASP_PROVIDER_RADIUS_PROXY);
  72. case IAS_PROVIDER_EXTERNAL_AUTH:
  73. return formatParameter(IASP_PROVIDER_EXTERNAL_AUTH);
  74. default:
  75. return formatParameter(IASP_NONE);
  76. }
  77. }
  78. // Format the IAS_ATTRIBUTE_AUTHENTICATION_TYPE value.
  79. PWSTR formatAuthType(DWORD type) throw ()
  80. {
  81. switch (type)
  82. {
  83. case IAS_AUTH_PAP:
  84. return copyString(L"PAP");
  85. case IAS_AUTH_MD5CHAP:
  86. return copyString(L"MD5-CHAP");
  87. case IAS_AUTH_MSCHAP:
  88. return copyString(L"MS-CHAPv1");
  89. case IAS_AUTH_MSCHAP2:
  90. return copyString(L"MS-CHAPv2");
  91. case IAS_AUTH_EAP:
  92. return copyString(L"EAP");
  93. case IAS_AUTH_ARAP:
  94. return copyString(L"ARAP");
  95. case IAS_AUTH_NONE:
  96. return copyString(L"Unauthenticated");
  97. case IAS_AUTH_CUSTOM:
  98. return copyString(L"Extension");
  99. case IAS_AUTH_MSCHAP_CPW:
  100. return copyString(L"MS-CHAPv1 CPW");
  101. case IAS_AUTH_MSCHAP2_CPW:
  102. return copyString(L"MS-CHAPv2 CPW");
  103. case IAS_AUTH_PEAP:
  104. return copyString(L"PEAP");
  105. default:
  106. return formatInteger(type);
  107. }
  108. }
  109. // Format the NAS-Port-Type value.
  110. PWSTR formatPortType(DWORD type) throw ()
  111. {
  112. switch (type)
  113. {
  114. case 0:
  115. return copyString(L"Async");
  116. case 1:
  117. return copyString(L"Sync");
  118. case 2:
  119. return copyString(L"ISDN Sync");
  120. case 3:
  121. return copyString(L"ISDN Async V.120");
  122. case 4:
  123. return copyString(L"ISDN Async V.110");
  124. case 5:
  125. return copyString(L"Virtual");
  126. case 6:
  127. return copyString(L"PIAFS");
  128. case 7:
  129. return copyString(L"HDLC Clear Channel");
  130. case 8:
  131. return copyString(L"X.25");
  132. case 9:
  133. return copyString(L"X.75");
  134. case 10:
  135. return copyString(L"G.3 Fax");
  136. case 11:
  137. return copyString(L"SDSL");
  138. case 12:
  139. return copyString(L"ADSL-CAP");
  140. case 13:
  141. return copyString(L"ADSL-DMT");
  142. case 14:
  143. return copyString(L"IDSL");
  144. case 15:
  145. return copyString(L"Ethernet");
  146. case 16:
  147. return copyString(L"xDSL");
  148. case 17:
  149. return copyString(L"Cable");
  150. case 18:
  151. return copyString(L"Wireless - Other");
  152. case 19:
  153. return copyString(L"Wireless - IEEE 802.11");
  154. default:
  155. return formatInteger(type);
  156. }
  157. }
  158. PWSTR formatAttribute(
  159. IRequest* request,
  160. IAttributesRaw* raw,
  161. DWORD dwId,
  162. DWORD defaultValue
  163. ) throw ()
  164. {
  165. // Is this one of the 'special' attributes ?
  166. switch (dwId)
  167. {
  168. case IAS_ATTRIBUTE_REASON_CODE:
  169. {
  170. LONG reason = 0;
  171. request->get_Reason(&reason);
  172. if (reason >= IAS_MAX_REASON_CODE)
  173. {
  174. reason = IAS_INTERNAL_ERROR;
  175. }
  176. return formatInteger(reason);
  177. }
  178. case IAS_ATTRIBUTE_REASON_STRING:
  179. {
  180. LONG reason;
  181. request->get_Reason(&reason);
  182. if (reason >= IAS_MAX_REASON_CODE)
  183. {
  184. reason = IAS_INTERNAL_ERROR;
  185. }
  186. return formatParameter(reason + 0x1000);
  187. }
  188. }
  189. // Get a single attribute with the give ID.
  190. DWORD posCount = 1;
  191. ATTRIBUTEPOSITION pos;
  192. raw->GetAttributes(&posCount, &pos, 1, &dwId);
  193. // If it's not present, use the defaultValue parameter.
  194. if (!posCount) { return formatParameter(defaultValue); }
  195. // Otherwise, save and release.
  196. const IASVALUE& val = pos.pAttribute->Value;
  197. IASAttributeRelease(pos.pAttribute);
  198. // Format the value.
  199. switch (val.itType)
  200. {
  201. case IASTYPE_ENUM:
  202. case IASTYPE_INTEGER:
  203. {
  204. switch (dwId)
  205. {
  206. case RADIUS_ATTRIBUTE_NAS_PORT_TYPE:
  207. return formatPortType(val.Enumerator);
  208. case IAS_ATTRIBUTE_PROVIDER_TYPE:
  209. return formatProviderType(val.Enumerator);
  210. case IAS_ATTRIBUTE_AUTHENTICATION_TYPE:
  211. return formatAuthType(val.Enumerator);
  212. // Fall through.
  213. }
  214. return formatInteger(val.Integer);
  215. }
  216. case IASTYPE_INET_ADDR:
  217. {
  218. WCHAR buffer[16];
  219. return copyString(ias_inet_htow(val.InetAddr, buffer));
  220. }
  221. case IASTYPE_STRING:
  222. {
  223. if (val.String.pszWide)
  224. {
  225. return copyString(val.String.pszWide);
  226. }
  227. else
  228. {
  229. USES_CONVERSION;
  230. return copyString(A2W(val.String.pszAnsi));
  231. }
  232. }
  233. case IASTYPE_OCTET_STRING:
  234. {
  235. return copyString(IAS_OCT2WIDE(val.OctetString));
  236. }
  237. }
  238. return emptyString;
  239. }
  240. ///////
  241. // An InsertionString definition consists of the attribute ID and a
  242. // defaultValue to be used if the attribute isn't present.
  243. ///////
  244. struct InsertionString
  245. {
  246. DWORD attrID;
  247. DWORD defaultValue;
  248. };
  249. // Insertion strings for an Access-Accept.
  250. const InsertionString ACCEPT_ATTRS[] =
  251. {
  252. { RADIUS_ATTRIBUTE_USER_NAME, IASP_NOT_PRESENT },
  253. { IAS_ATTRIBUTE_FULLY_QUALIFIED_USER_NAME, IASP_UNDETERMINED },
  254. { RADIUS_ATTRIBUTE_NAS_IP_ADDRESS, IASP_NOT_PRESENT },
  255. { RADIUS_ATTRIBUTE_NAS_IDENTIFIER, IASP_NOT_PRESENT },
  256. { IAS_ATTRIBUTE_CLIENT_NAME, IASP_NOT_PRESENT },
  257. { IAS_ATTRIBUTE_CLIENT_IP_ADDRESS, IASP_NOT_PRESENT },
  258. { RADIUS_ATTRIBUTE_CALLING_STATION_ID, IASP_NOT_PRESENT },
  259. { RADIUS_ATTRIBUTE_NAS_PORT_TYPE, IASP_NOT_PRESENT },
  260. { RADIUS_ATTRIBUTE_NAS_PORT, IASP_NOT_PRESENT },
  261. { IAS_ATTRIBUTE_PROXY_POLICY_NAME, IASP_NONE },
  262. { IAS_ATTRIBUTE_PROVIDER_TYPE, IASP_UNDETERMINED },
  263. { IAS_ATTRIBUTE_REMOTE_SERVER_ADDRESS, IASP_UNDETERMINED },
  264. { IAS_ATTRIBUTE_NP_NAME, IASP_UNDETERMINED },
  265. { IAS_ATTRIBUTE_AUTHENTICATION_TYPE, IASP_UNDETERMINED },
  266. { IAS_ATTRIBUTE_EAP_FRIENDLY_NAME, IASP_UNDETERMINED },
  267. { ATTRIBUTE_UNDEFINED, IASP_UNDETERMINED }
  268. };
  269. // Insertion strings for an Access-Reject.
  270. const InsertionString REJECT_ATTRS[] =
  271. {
  272. { RADIUS_ATTRIBUTE_USER_NAME, IASP_NOT_PRESENT },
  273. { IAS_ATTRIBUTE_FULLY_QUALIFIED_USER_NAME, IASP_UNDETERMINED },
  274. { RADIUS_ATTRIBUTE_NAS_IP_ADDRESS, IASP_NOT_PRESENT },
  275. { RADIUS_ATTRIBUTE_NAS_IDENTIFIER, IASP_NOT_PRESENT },
  276. { RADIUS_ATTRIBUTE_CALLED_STATION_ID, IASP_NOT_PRESENT },
  277. { RADIUS_ATTRIBUTE_CALLING_STATION_ID, IASP_NOT_PRESENT },
  278. { IAS_ATTRIBUTE_CLIENT_NAME, IASP_NOT_PRESENT },
  279. { IAS_ATTRIBUTE_CLIENT_IP_ADDRESS, IASP_NOT_PRESENT },
  280. { RADIUS_ATTRIBUTE_NAS_PORT_TYPE, IASP_NOT_PRESENT },
  281. { RADIUS_ATTRIBUTE_NAS_PORT, IASP_NOT_PRESENT },
  282. { IAS_ATTRIBUTE_PROXY_POLICY_NAME, IASP_NONE },
  283. { IAS_ATTRIBUTE_PROVIDER_TYPE, IASP_UNDETERMINED },
  284. { IAS_ATTRIBUTE_REMOTE_SERVER_ADDRESS, IASP_UNDETERMINED },
  285. { IAS_ATTRIBUTE_NP_NAME, IASP_UNDETERMINED },
  286. { IAS_ATTRIBUTE_AUTHENTICATION_TYPE, IASP_UNDETERMINED },
  287. { IAS_ATTRIBUTE_EAP_FRIENDLY_NAME, IASP_UNDETERMINED },
  288. { IAS_ATTRIBUTE_REASON_CODE, IASP_UNDETERMINED },
  289. { IAS_ATTRIBUTE_REASON_STRING, IASP_UNDETERMINED },
  290. { ATTRIBUTE_UNDEFINED, IASP_UNDETERMINED }
  291. };
  292. // Insertion strings for a discarded request.
  293. const InsertionString DISCARD_ATTRS[] =
  294. {
  295. { RADIUS_ATTRIBUTE_USER_NAME, IASP_NOT_PRESENT },
  296. { IAS_ATTRIBUTE_FULLY_QUALIFIED_USER_NAME, IASP_UNDETERMINED },
  297. { RADIUS_ATTRIBUTE_NAS_IP_ADDRESS, IASP_NOT_PRESENT },
  298. { RADIUS_ATTRIBUTE_NAS_IDENTIFIER, IASP_NOT_PRESENT },
  299. { RADIUS_ATTRIBUTE_CALLED_STATION_ID, IASP_NOT_PRESENT },
  300. { RADIUS_ATTRIBUTE_CALLING_STATION_ID, IASP_NOT_PRESENT },
  301. { IAS_ATTRIBUTE_CLIENT_NAME, IASP_NOT_PRESENT },
  302. { IAS_ATTRIBUTE_CLIENT_IP_ADDRESS, IASP_NOT_PRESENT },
  303. { RADIUS_ATTRIBUTE_NAS_PORT_TYPE, IASP_NOT_PRESENT },
  304. { RADIUS_ATTRIBUTE_NAS_PORT, IASP_NOT_PRESENT },
  305. { IAS_ATTRIBUTE_PROXY_POLICY_NAME, IASP_NONE },
  306. { IAS_ATTRIBUTE_PROVIDER_TYPE, IASP_UNDETERMINED },
  307. { IAS_ATTRIBUTE_REMOTE_SERVER_ADDRESS, IASP_UNDETERMINED },
  308. { IAS_ATTRIBUTE_REASON_CODE, IASP_UNDETERMINED },
  309. { IAS_ATTRIBUTE_REASON_STRING, IASP_UNDETERMINED },
  310. { ATTRIBUTE_UNDEFINED, IASP_UNDETERMINED }
  311. };
  312. // Insertion strings for a discarded accounting request.
  313. const InsertionString ACCT_DISCARD_ATTRS[] =
  314. {
  315. { RADIUS_ATTRIBUTE_USER_NAME, IASP_NOT_PRESENT },
  316. { IAS_ATTRIBUTE_FULLY_QUALIFIED_USER_NAME, IASP_UNDETERMINED },
  317. { RADIUS_ATTRIBUTE_NAS_IP_ADDRESS, IASP_NOT_PRESENT },
  318. { RADIUS_ATTRIBUTE_NAS_IDENTIFIER, IASP_NOT_PRESENT },
  319. { RADIUS_ATTRIBUTE_CALLED_STATION_ID, IASP_NOT_PRESENT },
  320. { RADIUS_ATTRIBUTE_CALLING_STATION_ID, IASP_NOT_PRESENT },
  321. { IAS_ATTRIBUTE_CLIENT_NAME, IASP_NOT_PRESENT },
  322. { IAS_ATTRIBUTE_CLIENT_IP_ADDRESS, IASP_NOT_PRESENT },
  323. { RADIUS_ATTRIBUTE_NAS_PORT_TYPE, IASP_NOT_PRESENT },
  324. { RADIUS_ATTRIBUTE_NAS_PORT, IASP_NOT_PRESENT },
  325. { IAS_ATTRIBUTE_PROXY_POLICY_NAME, IASP_NONE },
  326. { IAS_ATTRIBUTE_PROVIDER_TYPE, IASP_UNDETERMINED },
  327. { IAS_ATTRIBUTE_REMOTE_SERVER_ADDRESS, IASP_UNDETERMINED },
  328. { IAS_ATTRIBUTE_REASON_CODE, IASP_UNDETERMINED },
  329. { IAS_ATTRIBUTE_REASON_STRING, IASP_UNDETERMINED },
  330. { ATTRIBUTE_UNDEFINED, IASP_UNDETERMINED }
  331. };
  332. VOID
  333. WINAPI
  334. IASRadiusLogResult(
  335. IRequest* request,
  336. IAttributesRaw* raw
  337. )
  338. {
  339. // Determine which response type this is.
  340. LONG type;
  341. HRESULT hr = request->get_Response(&type);
  342. if (FAILED(hr))
  343. {
  344. return;
  345. }
  346. DWORD eventID;
  347. const InsertionString* attrs;
  348. switch (type)
  349. {
  350. case IAS_RESPONSE_ACCESS_ACCEPT:
  351. {
  352. eventID = IAS_RESPONSE_ACCEPT;
  353. attrs = ACCEPT_ATTRS;
  354. break;
  355. }
  356. case IAS_RESPONSE_ACCESS_REJECT:
  357. {
  358. eventID = IAS_RESPONSE_REJECT;
  359. attrs = REJECT_ATTRS;
  360. break;
  361. }
  362. case IAS_RESPONSE_DISCARD_PACKET:
  363. {
  364. hr = request->get_Request(&type);
  365. if (FAILED(hr))
  366. {
  367. return;
  368. }
  369. switch (type)
  370. {
  371. case IAS_REQUEST_ACCESS_REQUEST:
  372. {
  373. eventID = IAS_RESPONSE_DISCARD;
  374. attrs = DISCARD_ATTRS;
  375. break;
  376. }
  377. case IAS_REQUEST_ACCOUNTING:
  378. {
  379. eventID = IAS_ACCT_RESPONSE_DISCARD;
  380. attrs = ACCT_DISCARD_ATTRS;
  381. break;
  382. }
  383. default:
  384. {
  385. return;
  386. }
  387. }
  388. break;
  389. }
  390. default:
  391. {
  392. return;
  393. }
  394. }
  395. // Format the insertion strings.
  396. PWSTR strings[24];
  397. DWORD numStrings = 0;
  398. for ( ; attrs->attrID != ATTRIBUTE_UNDEFINED; ++attrs, ++numStrings)
  399. {
  400. strings[numStrings] = formatAttribute(
  401. request,
  402. raw,
  403. attrs->attrID,
  404. attrs->defaultValue
  405. );
  406. }
  407. // Report the event.
  408. IASReportEvent(
  409. eventID,
  410. numStrings,
  411. 0,
  412. (PCWSTR*)strings,
  413. NULL
  414. );
  415. // Free the insertion strings.
  416. while (numStrings--)
  417. {
  418. freeString(strings[numStrings]);
  419. }
  420. }