Source code of Windows XP (NT5)
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.

343 lines
8.6 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // action.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // Defines the class Action.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 02/01/2000 Original version.
  16. //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #include <ias.h>
  19. #include <attrcvt.h>
  20. #include <sdoias.h>
  21. #include <action.h>
  22. _COM_SMARTPTR_TYPEDEF(ISdo, __uuidof(ISdo));
  23. _COM_SMARTPTR_TYPEDEF(ISdoCollection, __uuidof(ISdoCollection));
  24. Action::Action(
  25. PCWSTR name,
  26. DWORD nameAttr,
  27. _variant_t& action
  28. )
  29. : attributes(4),
  30. realmsTarget(RADIUS_ATTRIBUTE_USER_NAME)
  31. {
  32. using _com_util::CheckError;
  33. //////////
  34. // Add the policy name attribute.
  35. //////////
  36. IASAttribute policyName(true);
  37. policyName->dwId = nameAttr;
  38. policyName.setString(name);
  39. policyName.setFlag(IAS_INCLUDE_IN_RESPONSE);
  40. attributes.push_back(policyName);
  41. //////////
  42. // Get an enumerator for the attributes collection.
  43. //////////
  44. ISdoCollectionPtr profile(action);
  45. IUnknownPtr unk;
  46. CheckError(profile->get__NewEnum(&unk));
  47. IEnumVARIANTPtr iter(unk);
  48. //////////
  49. // Iterate through the attributes.
  50. //////////
  51. _variant_t element;
  52. unsigned long fetched;
  53. while (iter->Next(1, &element, &fetched) == S_OK && fetched == 1)
  54. {
  55. // Convert to an SDO.
  56. ISdoPtr attribute(element);
  57. element.Clear();
  58. // Get the necessary properties.
  59. _variant_t id, value, syntax;
  60. CheckError(attribute->GetProperty(PROPERTY_ATTRIBUTE_ID, &id));
  61. CheckError(attribute->GetProperty(PROPERTY_ATTRIBUTE_VALUE, &value));
  62. CheckError(attribute->GetProperty(PROPERTY_ATTRIBUTE_SYNTAX, &syntax));
  63. // Attribute-Manipulation-Rule gets processed 'as is'.
  64. if (V_I4(&id) == IAS_ATTRIBUTE_MANIPULATION_RULE)
  65. {
  66. realms.setRealms(&value);
  67. continue;
  68. }
  69. // For everything else we process the VARIANTs one at a time.
  70. VARIANT *begin, *end;
  71. if (V_VT(&value) == (VT_VARIANT | VT_ARRAY))
  72. {
  73. begin = (VARIANT*)V_ARRAY(&value)->pvData;
  74. end = begin + V_ARRAY(&value)->rgsabound[0].cElements;
  75. }
  76. else
  77. {
  78. begin = &value;
  79. end = begin + 1;
  80. }
  81. // Iterate through each value.
  82. for (VARIANT* v = begin; v != end; ++v)
  83. {
  84. // Process based on the attribute ID.
  85. switch (V_I4(&id))
  86. {
  87. case IAS_ATTRIBUTE_MANIPULATION_TARGET:
  88. {
  89. realmsTarget = V_I4(v);
  90. break;
  91. }
  92. case IAS_ATTRIBUTE_AUTH_PROVIDER_TYPE:
  93. {
  94. IASAttribute type(true);
  95. type->dwId = IAS_ATTRIBUTE_PROVIDER_TYPE;
  96. type->Value.itType = IASTYPE_ENUM;
  97. type->Value.Integer = V_I4(v);
  98. authProvider.push_back(type);
  99. break;
  100. }
  101. case IAS_ATTRIBUTE_AUTH_PROVIDER_NAME:
  102. {
  103. IASAttribute name(true);
  104. name->dwId = IAS_ATTRIBUTE_PROVIDER_NAME;
  105. name.setString(V_BSTR(v));
  106. authProvider.push_back(name);
  107. break;
  108. }
  109. case IAS_ATTRIBUTE_ACCT_PROVIDER_TYPE:
  110. {
  111. IASAttribute type(true);
  112. type->dwId = IAS_ATTRIBUTE_PROVIDER_TYPE;
  113. type->Value.itType = IASTYPE_ENUM;
  114. type->Value.Integer = V_I4(v);
  115. acctProvider.push_back(type);
  116. break;
  117. }
  118. case IAS_ATTRIBUTE_ACCT_PROVIDER_NAME:
  119. {
  120. IASAttribute name(true);
  121. name->dwId = IAS_ATTRIBUTE_PROVIDER_NAME;
  122. name.setString(V_BSTR(v));
  123. acctProvider.push_back(name);
  124. break;
  125. }
  126. case RADIUS_ATTRIBUTE_VENDOR_SPECIFIC:
  127. {
  128. IASAttribute attr(VSAFromString(V_BSTR(v)), FALSE);
  129. attr->dwId = RADIUS_ATTRIBUTE_VENDOR_SPECIFIC;
  130. attr.setFlag(IAS_INCLUDE_IN_ACCEPT);
  131. attributes.push_back(attr);
  132. break;
  133. }
  134. default:
  135. {
  136. IASTYPEENUM type = (IASTYPEENUM)V_I4(&syntax);
  137. IASAttribute attr(IASAttributeFromVariant(v, type), false);
  138. attr->dwId = V_I4(&id);
  139. attr.setFlag(IAS_INCLUDE_IN_ACCEPT);
  140. attributes.push_back(attr);
  141. }
  142. }
  143. }
  144. }
  145. }
  146. void Action::doAction(IASRequest& request) const
  147. {
  148. // Populate the provider information:
  149. switch (request.get_Request())
  150. {
  151. case IAS_REQUEST_ACCESS_REQUEST:
  152. authProvider.store(request);
  153. break;
  154. case IAS_REQUEST_ACCOUNTING:
  155. acctProvider.store(request);
  156. break;
  157. }
  158. // Perform attribute manipulation.
  159. if (!realms.empty())
  160. {
  161. IASAttribute attr;
  162. attr.load(request, realmsTarget, IASTYPE_OCTET_STRING);
  163. if (attr)
  164. {
  165. CComBSTR newVal;
  166. realms.process(IAS_OCT2WIDE(attr->Value.OctetString), &newVal);
  167. if (newVal)
  168. {
  169. if (realmsTarget == RADIUS_ATTRIBUTE_USER_NAME)
  170. {
  171. IASAttribute userName(true);
  172. userName->dwId = RADIUS_ATTRIBUTE_USER_NAME;
  173. userName->dwFlags = attr->dwFlags;
  174. userName.setOctetString(newVal);
  175. userName.store(request);
  176. // Now that the new User-Name is safely stored, we can rename
  177. // the old User-Name.
  178. attr->dwId = IAS_ATTRIBUTE_ORIGINAL_USER_NAME;
  179. }
  180. else
  181. {
  182. // No need to save the old, so modify in place.
  183. attr.setOctetString(newVal);
  184. }
  185. }
  186. }
  187. }
  188. // Store the profile attributes.
  189. attributes.store(request);
  190. }
  191. /////////
  192. // Various formats of VSA strings.
  193. /////////
  194. enum Format
  195. {
  196. FORMAT_RAW_HEX,
  197. FORMAT_STRING,
  198. FORMAT_INTEGER,
  199. FORMAT_HEX,
  200. FORMAT_INET_ADDR
  201. };
  202. /////////
  203. // Layout of the VSA strings.
  204. /////////
  205. struct VSAFormat
  206. {
  207. WCHAR format[2];
  208. WCHAR vendorID[8];
  209. union
  210. {
  211. WCHAR rawValue[1];
  212. struct
  213. {
  214. WCHAR vendorType[2];
  215. WCHAR vendorLength[2];
  216. WCHAR value[1];
  217. };
  218. };
  219. };
  220. //////////
  221. // Convert a hex digit to the number it represents.
  222. //////////
  223. inline BYTE digit2Num(WCHAR digit) throw ()
  224. {
  225. return (digit >= L'0' && digit <= L'9') ? digit - L'0'
  226. : digit - (L'A' - 10);
  227. }
  228. //////////
  229. // Pack a hex digit into a byte stream.
  230. //////////
  231. PBYTE packHex(PCWSTR src, ULONG srclen, PBYTE dst) throw ()
  232. {
  233. for (ULONG dstlen = srclen / 2; dstlen; --dstlen)
  234. {
  235. *dst = digit2Num(*src++) << 4;
  236. *dst++ |= digit2Num(*src++);
  237. }
  238. return dst;
  239. }
  240. //////////
  241. // Convert a string describing a VSA into an IASATTRIBUTE.
  242. //////////
  243. PIASATTRIBUTE Action::VSAFromString(PCWSTR string)
  244. {
  245. // Number of characters to process.
  246. SIZE_T len = wcslen(string);
  247. // Overlay the layout struct.
  248. VSAFormat* vsa = (VSAFormat*)string;
  249. // Get the string format.
  250. ULONG format = digit2Num(vsa->format[0]);
  251. format <<= 8;
  252. format |= digit2Num(vsa->format[1]);
  253. // Temporary buffer used for formatting the VSA.
  254. BYTE buffer[253], *dst = buffer;
  255. // Pack the Vendor-ID.
  256. dst = packHex(vsa->vendorID, 8, dst);
  257. // Pack the Vendor-Type and Vendor-Length for conformant VSAs.
  258. if (format != FORMAT_RAW_HEX)
  259. {
  260. dst = packHex(vsa->vendorType, 2, dst);
  261. dst = packHex(vsa->vendorLength, 2, dst);
  262. }
  263. // Pack the value.
  264. switch (format)
  265. {
  266. case FORMAT_RAW_HEX:
  267. {
  268. dst = packHex(
  269. vsa->rawValue,
  270. len - 10,
  271. dst
  272. );
  273. break;
  274. }
  275. case FORMAT_INTEGER:
  276. case FORMAT_HEX:
  277. case FORMAT_INET_ADDR:
  278. {
  279. dst = packHex(
  280. vsa->value,
  281. len - 14,
  282. dst
  283. );
  284. break;
  285. }
  286. case FORMAT_STRING:
  287. {
  288. int nchar = WideCharToMultiByte(
  289. CP_ACP,
  290. 0,
  291. vsa->value,
  292. len - 14,
  293. (PSTR)dst,
  294. sizeof(buffer) - 6,
  295. NULL,
  296. NULL
  297. );
  298. dst += nchar;
  299. break;
  300. }
  301. }
  302. // Store the temporary buffer in an attribute ...
  303. IASAttribute attr(true);
  304. attr.setOctetString(dst - buffer, buffer);
  305. // ... and return.
  306. return attr.detach();
  307. }