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.

239 lines
6.1 KiB

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