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.

291 lines
6.5 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1991 - 1992
  6. //
  7. // File: utils.cxx
  8. //
  9. // Contents: utilities
  10. //
  11. // History: LZhu Feb 1, 2002 Created
  12. //
  13. // Notes:
  14. //
  15. //--------------------------------------------------------------------------
  16. #ifdef WIN32_CHICAGO
  17. #include<kerb.hxx>
  18. #include<kerbp.h>
  19. #endif // WIN32_CHICAGO
  20. extern "C"
  21. {
  22. #include <nt.h>
  23. #include <ntrtl.h>
  24. #include <nturtl.h>
  25. #include <windows.h>
  26. #include <ntlsa.h>
  27. #include <samrpc.h>
  28. #include <samisrv.h>
  29. #include <lsarpc.h>
  30. #include <lsaisrv.h>
  31. #include <lsaitf.h>
  32. #include <wincrypt.h>
  33. }
  34. #include <kerbcomm.h>
  35. #include <kerberr.h>
  36. #include <kerbcon.h>
  37. #include <midles.h>
  38. #include <authen.hxx>
  39. #include <tostring.hxx>
  40. #include <kerberos.h>
  41. #include "debug.h"
  42. #include <fileno.h>
  43. #include <pac.hxx>
  44. #include <utils.hxx>
  45. #define FILENO FILENO_COMMON_UTILS
  46. //+-------------------------------------------------------------------------
  47. //
  48. // Function: KerbUnpackErrorData
  49. //
  50. // Synopsis: This routine unpacks error information from a KERB_ERROR message
  51. //
  52. // Effects:
  53. //
  54. // Arguments: Unpacked error data. Returns extended error to
  55. // be freed using KerbFreeData with KERB_EXT_ERROR_PDU
  56. //
  57. // Requires:
  58. //
  59. // Returns: KERB_ERROR
  60. //
  61. // Notes:
  62. //
  63. //
  64. //--------------------------------------------------------------------------
  65. KERBERR
  66. KerbUnpackErrorData(
  67. IN OUT PKERB_ERROR ErrorMessage,
  68. IN OUT PKERB_EXT_ERROR * ExtendedError
  69. )
  70. {
  71. KERBERR KerbErr = KDC_ERR_NONE;
  72. TYPED_DATA_Element* TypedDataElem = NULL;
  73. TYPED_DATA_Element* ErrorData = NULL;
  74. KERB_ERROR_METHOD_DATA* ErrorMethodData = NULL;
  75. UCHAR* ExtErrTemp = NULL; // need to free it
  76. UCHAR* ExtErr = NULL;
  77. ULONG ExtErrSize = 0;
  78. *ExtendedError = NULL;
  79. if ((ErrorMessage->bit_mask & error_data_present) == 0)
  80. {
  81. KerbErr = (KRB_ERR_GENERIC);
  82. goto Cleanup;
  83. }
  84. KerbErr = KerbUnpackData(
  85. ErrorMessage->error_data.value,
  86. ErrorMessage->error_data.length,
  87. TYPED_DATA_PDU,
  88. (VOID**) &ErrorData
  89. );
  90. if (!KERB_SUCCESS(KerbErr))
  91. {
  92. //
  93. // we do not use error method data from kdc any more, but need to watch
  94. // for those slipped into clients with ServicePacks
  95. //
  96. DebugLog((DEB_WARN, "KerbUnpackData failed to unpack typed data, trying error method data\n"));
  97. KerbErr = KerbUnpackData(
  98. ErrorMessage->error_data.value,
  99. ErrorMessage->error_data.length,
  100. KERB_ERROR_METHOD_DATA_PDU,
  101. (VOID**) &ErrorMethodData
  102. );
  103. if (!KERB_SUCCESS(KerbErr))
  104. {
  105. goto Cleanup;
  106. }
  107. if ((ErrorMethodData->bit_mask & data_value_present)
  108. && (KERB_ERR_TYPE_EXTENDED == ErrorMethodData->data_type)
  109. && ErrorMethodData->data_value.length >= sizeof(KERB_EXT_ERROR))
  110. {
  111. //
  112. // pack the raw data
  113. //
  114. KerbErr = KerbPackData(
  115. ErrorMethodData->data_value.value,
  116. KERB_EXT_ERROR_PDU,
  117. &ExtErrSize,
  118. &ExtErrTemp
  119. );
  120. if (!KERB_SUCCESS(KerbErr))
  121. {
  122. goto Cleanup;
  123. }
  124. ExtErr = ExtErrTemp;
  125. }
  126. }
  127. else
  128. {
  129. TypedDataElem = TypedDataListFind(ErrorData, TD_EXTENDED_ERROR);
  130. if (TypedDataElem)
  131. {
  132. ExtErrSize = TypedDataElem->value.data_value.length;
  133. ExtErr = TypedDataElem->value.data_value.value;
  134. }
  135. if ((KDC_ERR_S_PRINCIPAL_UNKNOWN == ErrorMessage->error_code)
  136. && (NULL != TypedDataListFind(ErrorData, TD_MUST_USE_USER2USER)))
  137. {
  138. DebugLog((DEB_WARN, "KerbUnpackData remap KDC_ERR_S_PRINCIPAL_UNKNOWN to KDC_ERR_MUST_USE_USER2USER\n"));
  139. ErrorMessage->error_code = KDC_ERR_MUST_USE_USER2USER;
  140. }
  141. }
  142. if (ExtErr && ExtErrSize)
  143. {
  144. KerbErr = KerbUnpackData(
  145. ExtErr,
  146. ExtErrSize,
  147. KERB_EXT_ERROR_PDU,
  148. (VOID**)ExtendedError
  149. );
  150. if (!KERB_SUCCESS(KerbErr))
  151. {
  152. goto Cleanup;
  153. }
  154. }
  155. if (*ExtendedError)
  156. {
  157. DebugLog((DEB_ERROR, "KerbUnpackErrorData received failure from kdc %#x KLIN(%#x) NTSTATUS(%#x)\n",
  158. ErrorMessage->error_code, (*ExtendedError)->klininfo, (*ExtendedError)->status));
  159. }
  160. Cleanup:
  161. if (NULL != ErrorMethodData)
  162. {
  163. KerbFreeData(KERB_ERROR_METHOD_DATA_PDU, ErrorMethodData);
  164. }
  165. if (NULL != ErrorData)
  166. {
  167. KerbFreeData(TYPED_DATA_PDU, ErrorData);
  168. }
  169. if (NULL != ExtErrTemp)
  170. {
  171. MIDL_user_free(ExtErrTemp);
  172. }
  173. return (KerbErr);
  174. }
  175. //+-------------------------------------------------------------------------
  176. //
  177. // Function: TypedDataListFind
  178. //
  179. // Synopsis: find a kerb typed data from a type data list
  180. //
  181. // Effects: none
  182. //
  183. // Arguments:
  184. //
  185. // Requires:
  186. //
  187. // Returns: TYPED_DATA_Element that is found, NULL otherwise
  188. //
  189. // Notes:
  190. //
  191. //
  192. //--------------------------------------------------------------------------
  193. TYPED_DATA_Element*
  194. TypedDataListFind(
  195. IN OPTIONAL TYPED_DATA_Element* InputDataList,
  196. IN LONG Type
  197. )
  198. {
  199. for (TYPED_DATA_Element* p = InputDataList; p != NULL; p = p->next)
  200. {
  201. if (p->value.data_type == Type)
  202. {
  203. return p;
  204. }
  205. }
  206. return NULL;
  207. }
  208. //+-------------------------------------------------------------------------
  209. //
  210. // Function: TypedDataListPushFront
  211. //
  212. // Synopsis: Insert a kerb typed data to a type data list
  213. //
  214. // Effects: none
  215. //
  216. // Arguments:
  217. //
  218. // Requires:
  219. //
  220. // Returns: KERBERR
  221. //
  222. // Notes:
  223. //
  224. //
  225. //--------------------------------------------------------------------------
  226. KERBERR
  227. TypedDataListPushFront(
  228. IN OPTIONAL TYPED_DATA_Element* InputDataList,
  229. IN KERB_TYPED_DATA* Data,
  230. OUT ULONG* OutputDataListSize,
  231. OUT UCHAR** OutputDataList
  232. )
  233. {
  234. KERBERR KerbErr = KDC_ERR_NONE;
  235. TYPED_DATA_Element TypedDataElem = {0};
  236. TYPED_DATA_Element* TypedDataList = &TypedDataElem;
  237. TypedDataElem.value = *Data;
  238. TypedDataElem.next = InputDataList;
  239. KerbErr = KerbPackData(
  240. &TypedDataList,
  241. TYPED_DATA_PDU,
  242. OutputDataListSize,
  243. OutputDataList
  244. );
  245. if (!KERB_SUCCESS(KerbErr))
  246. {
  247. D_DebugLog((DEB_ERROR, "KdcGetTicket faild to pack error data as typed data\n", KLIN(FILENO, __LINE__)));
  248. goto Cleanup;
  249. }
  250. Cleanup:
  251. return KerbErr;
  252. }