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.

240 lines
5.8 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // radutil.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // This file defines methods for converting attributes to and from
  12. // RADIUS wire format.
  13. //
  14. // MODIFICATION HISTORY
  15. //
  16. // 03/08/1998 Original version.
  17. // 08/11/1998 Packing functions moved to iasutil.
  18. // Set pszWide to NULL when initializing IASTYPE_STRING.
  19. //
  20. ///////////////////////////////////////////////////////////////////////////////
  21. #include <radcommon.h>
  22. #include <iasutil.h>
  23. #include <iastlutl.h>
  24. #include <radutil.h>
  25. //////////
  26. // The offset between the UNIX and NT epochs.
  27. //////////
  28. const DWORDLONG UNIX_EPOCH = 116444736000000000ui64;
  29. ///////////////////////////////////////////////////////////////////////////////
  30. //
  31. // METHOD
  32. //
  33. // RadiusUtil::decode
  34. //
  35. // DESCRIPTION
  36. //
  37. // Decodes an octet string into a newly-allocated IAS Attribute of the
  38. // specified type.
  39. //
  40. ///////////////////////////////////////////////////////////////////////////////
  41. PIASATTRIBUTE RadiusUtil::decode(
  42. IASTYPE dstType,
  43. PBYTE src,
  44. ULONG srclen
  45. )
  46. {
  47. // Allocate an attribute to hold the decoded value.
  48. IASTL::IASAttribute dst(true);
  49. // Switch based on the destination type.
  50. switch (dstType)
  51. {
  52. case IASTYPE_BOOLEAN:
  53. {
  54. if (srclen != 4) { _com_issue_error(E_INVALIDARG); }
  55. dst->Value.Boolean = IASExtractDWORD(src) ? TRUE : FALSE;
  56. break;
  57. }
  58. case IASTYPE_INTEGER:
  59. case IASTYPE_ENUM:
  60. case IASTYPE_INET_ADDR:
  61. {
  62. if (srclen != 4) { _com_issue_error(E_INVALIDARG); }
  63. dst->Value.Integer = IASExtractDWORD(src);
  64. break;
  65. }
  66. case IASTYPE_UTC_TIME:
  67. {
  68. if (srclen != 4) { _com_issue_error(E_INVALIDARG); }
  69. DWORDLONG val;
  70. // Extract the UNIX time.
  71. val = IASExtractDWORD(src);
  72. // Convert from seconds to 100 nsec intervals.
  73. val *= 10000000;
  74. // Shift to the NT epoch.
  75. val += 116444736000000000ui64;
  76. // Split into the high and low DWORDs.
  77. dst->Value.UTCTime.dwLowDateTime = (DWORD)val;
  78. dst->Value.UTCTime.dwHighDateTime = (DWORD)(val >> 32);
  79. break;
  80. }
  81. case IASTYPE_STRING:
  82. {
  83. dst.setString(srclen, src);
  84. break;
  85. }
  86. case IASTYPE_OCTET_STRING:
  87. case IASTYPE_PROV_SPECIFIC:
  88. {
  89. dst.setOctetString(srclen, src);
  90. break;
  91. }
  92. }
  93. // All went well, so set type attribute type ...
  94. dst->Value.itType = dstType;
  95. // ... and return.
  96. return dst.detach();
  97. }
  98. ///////////////////////////////////////////////////////////////////////////////
  99. //
  100. // METHOD
  101. //
  102. // RadiusUtil::getEncodedSize
  103. //
  104. // DESCRIPTION
  105. //
  106. // Returns the size in bytes of the IASATTRIBUTE when converted to RADIUS
  107. // wire format. This does NOT include the attribute header.
  108. //
  109. ///////////////////////////////////////////////////////////////////////////////
  110. ULONG RadiusUtil::getEncodedSize(
  111. const IASATTRIBUTE& src
  112. ) throw ()
  113. {
  114. switch (src.Value.itType)
  115. {
  116. case IASTYPE_BOOLEAN:
  117. case IASTYPE_INTEGER:
  118. case IASTYPE_ENUM:
  119. case IASTYPE_INET_ADDR:
  120. case IASTYPE_UTC_TIME:
  121. {
  122. return 4;
  123. }
  124. case IASTYPE_STRING:
  125. {
  126. // Convert the string to ANSI so we can count octets.
  127. IASAttributeAnsiAlloc(const_cast<PIASATTRIBUTE>(&src));
  128. // Allow for NULL strings and don't count the terminator.
  129. return src.Value.String.pszAnsi ? strlen(src.Value.String.pszAnsi)
  130. : 0;
  131. }
  132. case IASTYPE_OCTET_STRING:
  133. case IASTYPE_PROV_SPECIFIC:
  134. {
  135. return src.Value.OctetString.dwLength;
  136. }
  137. }
  138. // All other types have no wire representation.
  139. return 0;
  140. }
  141. ///////////////////////////////////////////////////////////////////////////////
  142. //
  143. // METHOD
  144. //
  145. // RadiusUtil::encode
  146. //
  147. // DESCRIPTION
  148. //
  149. // Encodes the IASATTRIBUTE into RADIUS wire format and copies the value
  150. // to the buffer pointed to by 'dst'. The caller should ensure that the
  151. // destination buffer is large enough by first calling getEncodedSize.
  152. // This method only encodes the attribute value, not the header.
  153. //
  154. ///////////////////////////////////////////////////////////////////////////////
  155. void RadiusUtil::encode(
  156. PBYTE dst,
  157. const IASATTRIBUTE& src
  158. ) throw ()
  159. {
  160. // Switch based on the source's type.
  161. switch (src.Value.itType)
  162. {
  163. case IASTYPE_BOOLEAN:
  164. {
  165. IASInsertDWORD(dst, (src.Value.Boolean ? 1 : 0));
  166. break;
  167. }
  168. case IASTYPE_INTEGER:
  169. case IASTYPE_ENUM:
  170. case IASTYPE_INET_ADDR:
  171. {
  172. IASInsertDWORD(dst, src.Value.Integer);
  173. break;
  174. }
  175. case IASTYPE_UTC_TIME:
  176. {
  177. DWORDLONG val;
  178. // Move in the high DWORD.
  179. val = src.Value.UTCTime.dwHighDateTime;
  180. val <<= 32;
  181. // Move in the low DWORD.
  182. val |= src.Value.UTCTime.dwLowDateTime;
  183. // Convert to the UNIX epoch.
  184. val -= UNIX_EPOCH;
  185. // Convert to seconds.
  186. val /= 10000000;
  187. IASInsertDWORD(dst, (DWORD)val);
  188. break;
  189. }
  190. case IASTYPE_STRING:
  191. {
  192. const BYTE* p = (const BYTE*)src.Value.String.pszAnsi;
  193. // Don't use strcpy since we don't want the null terminator.
  194. if (p) while (*p) *dst++ = *p++;
  195. break;
  196. }
  197. case IASTYPE_OCTET_STRING:
  198. case IASTYPE_PROV_SPECIFIC:
  199. {
  200. memcpy(dst,
  201. src.Value.OctetString.lpValue,
  202. src.Value.OctetString.dwLength);
  203. }
  204. }
  205. }