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.

507 lines
12 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 <kerberos.h>
  40. #include "debug.h"
  41. #include <fileno.h>
  42. #include <pac.hxx>
  43. #include <utils.hxx>
  44. #define FILENO FILENO_COMMON_UTILS
  45. //+-------------------------------------------------------------------------
  46. //
  47. // Function: KerbUnpackErrorData
  48. //
  49. // Synopsis: This routine unpacks error information from a KERB_ERROR message
  50. //
  51. // Effects:
  52. //
  53. // Arguments: Unpacked error data. Returns extended error to
  54. // be freed using KerbFreeData with KERB_EXT_ERROR_PDU
  55. //
  56. // Requires:
  57. //
  58. // Returns: KERB_ERROR
  59. //
  60. // Notes:
  61. //
  62. //
  63. //--------------------------------------------------------------------------
  64. KERBERR
  65. KerbUnpackErrorData(
  66. IN OUT PKERB_ERROR ErrorMessage,
  67. IN OUT PKERB_EXT_ERROR * ExtendedError
  68. )
  69. {
  70. KERBERR KerbErr = KDC_ERR_NONE;
  71. TYPED_DATA_Element* TypedDataElem = NULL;
  72. TYPED_DATA_Element* ErrorData = NULL;
  73. KERB_ERROR_METHOD_DATA* ErrorMethodData = NULL;
  74. UCHAR* ExtErrTemp = NULL; // need to free it
  75. UCHAR* ExtErr = NULL;
  76. ULONG ExtErrSize = 0;
  77. *ExtendedError = NULL;
  78. if ((ErrorMessage->bit_mask & error_data_present) == 0)
  79. {
  80. KerbErr = (KRB_ERR_GENERIC);
  81. goto Cleanup;
  82. }
  83. KerbErr = KerbUnpackData(
  84. ErrorMessage->error_data.value,
  85. ErrorMessage->error_data.length,
  86. TYPED_DATA_PDU,
  87. (VOID**) &ErrorData
  88. );
  89. if (!KERB_SUCCESS(KerbErr))
  90. {
  91. //
  92. // we do not use error method data from kdc any more, but need to watch
  93. // for those slipped into clients with ServicePacks
  94. //
  95. DebugLog((DEB_WARN, "KerbUnpackData failed to unpack typed data, trying error method data\n"));
  96. KerbErr = KerbUnpackData(
  97. ErrorMessage->error_data.value,
  98. ErrorMessage->error_data.length,
  99. KERB_ERROR_METHOD_DATA_PDU,
  100. (VOID**) &ErrorMethodData
  101. );
  102. if (!KERB_SUCCESS(KerbErr))
  103. {
  104. goto Cleanup;
  105. }
  106. if ((ErrorMethodData->bit_mask & data_value_present)
  107. && (KERB_ERR_TYPE_EXTENDED == ErrorMethodData->data_type)
  108. && ErrorMethodData->data_value.length >= sizeof(KERB_EXT_ERROR))
  109. {
  110. //
  111. // pack the raw data
  112. //
  113. KerbErr = KerbPackData(
  114. ErrorMethodData->data_value.value,
  115. KERB_EXT_ERROR_PDU,
  116. &ExtErrSize,
  117. &ExtErrTemp
  118. );
  119. if (!KERB_SUCCESS(KerbErr))
  120. {
  121. goto Cleanup;
  122. }
  123. ExtErr = ExtErrTemp;
  124. }
  125. }
  126. else
  127. {
  128. TypedDataElem = TypedDataListFind(ErrorData, TD_EXTENDED_ERROR);
  129. if (TypedDataElem)
  130. {
  131. ExtErrSize = TypedDataElem->value.data_value.length;
  132. ExtErr = TypedDataElem->value.data_value.value;
  133. }
  134. if ((KDC_ERR_S_PRINCIPAL_UNKNOWN == ErrorMessage->error_code)
  135. && (NULL != TypedDataListFind(ErrorData, TD_MUST_USE_USER2USER)))
  136. {
  137. DebugLog((DEB_WARN, "KerbUnpackData remap KDC_ERR_S_PRINCIPAL_UNKNOWN to KDC_ERR_MUST_USE_USER2USER\n"));
  138. ErrorMessage->error_code = KDC_ERR_MUST_USE_USER2USER;
  139. }
  140. }
  141. if (ExtErr && ExtErrSize)
  142. {
  143. KerbErr = KerbUnpackData(
  144. ExtErr,
  145. ExtErrSize,
  146. KERB_EXT_ERROR_PDU,
  147. (VOID**)ExtendedError
  148. );
  149. if (!KERB_SUCCESS(KerbErr))
  150. {
  151. goto Cleanup;
  152. }
  153. }
  154. if (*ExtendedError)
  155. {
  156. DebugLog((DEB_ERROR, "KerbUnpackErrorData received failure from kdc %#x KLIN(%#x) NTSTATUS(%#x)\n",
  157. ErrorMessage->error_code, (*ExtendedError)->klininfo, (*ExtendedError)->status));
  158. }
  159. Cleanup:
  160. if (NULL != ErrorMethodData)
  161. {
  162. KerbFreeData(KERB_ERROR_METHOD_DATA_PDU, ErrorMethodData);
  163. }
  164. if (NULL != ErrorData)
  165. {
  166. KerbFreeData(TYPED_DATA_PDU, ErrorData);
  167. }
  168. if (NULL != ExtErrTemp)
  169. {
  170. MIDL_user_free(ExtErrTemp);
  171. }
  172. return (KerbErr);
  173. }
  174. //+-------------------------------------------------------------------------
  175. //
  176. // Function: TypedDataListFind
  177. //
  178. // Synopsis: find a kerb typed data from a type data list
  179. //
  180. // Effects: none
  181. //
  182. // Arguments:
  183. //
  184. // Requires:
  185. //
  186. // Returns: TYPED_DATA_Element that is found, NULL otherwise
  187. //
  188. // Notes:
  189. //
  190. //
  191. //--------------------------------------------------------------------------
  192. TYPED_DATA_Element*
  193. TypedDataListFind(
  194. IN OPTIONAL TYPED_DATA_Element* InputDataList,
  195. IN LONG Type
  196. )
  197. {
  198. for (TYPED_DATA_Element* p = InputDataList; p != NULL; p = p->next)
  199. {
  200. if (p->value.data_type == Type)
  201. {
  202. return p;
  203. }
  204. }
  205. return NULL;
  206. }
  207. //+-------------------------------------------------------------------------
  208. //
  209. // Function: TypedDataListPushFront
  210. //
  211. // Synopsis: Insert a kerb typed data to a type data list
  212. //
  213. // Effects: none
  214. //
  215. // Arguments:
  216. //
  217. // Requires:
  218. //
  219. // Returns: KERBERR
  220. //
  221. // Notes:
  222. //
  223. //
  224. //--------------------------------------------------------------------------
  225. KERBERR
  226. TypedDataListPushFront(
  227. IN OPTIONAL TYPED_DATA_Element* InputDataList,
  228. IN KERB_TYPED_DATA* Data,
  229. OUT ULONG* OutputDataListSize,
  230. OUT UCHAR** OutputDataList
  231. )
  232. {
  233. KERBERR KerbErr = KDC_ERR_NONE;
  234. TYPED_DATA_Element TypedDataElem = {0};
  235. TYPED_DATA_Element* TypedDataList = &TypedDataElem;
  236. TypedDataElem.value = *Data;
  237. TypedDataElem.next = InputDataList;
  238. KerbErr = KerbPackData(
  239. &TypedDataList,
  240. TYPED_DATA_PDU,
  241. OutputDataListSize,
  242. OutputDataList
  243. );
  244. if (!KERB_SUCCESS(KerbErr))
  245. {
  246. D_DebugLog((DEB_ERROR, "KdcGetTicket faild to pack error data as typed data %#x\n", KLIN(FILENO, __LINE__)));
  247. goto Cleanup;
  248. }
  249. Cleanup:
  250. return KerbErr;
  251. }
  252. //+-------------------------------------------------------------------------
  253. //
  254. // Function: PackUnicodeStringAsUnicodeStringZ
  255. //
  256. // Synopsis: Pack a unicode string as null-terminated
  257. //
  258. // Effects:
  259. //
  260. // Arguments:
  261. //
  262. // Requires:
  263. //
  264. // Returns:
  265. //
  266. // Notes:
  267. //
  268. //
  269. //-------------------------------------------------------------------------
  270. VOID
  271. PackUnicodeStringAsUnicodeStringZ(
  272. IN UNICODE_STRING* pString,
  273. IN OUT WCHAR** ppWhere,
  274. OUT UNICODE_STRING* pDestString
  275. )
  276. {
  277. RtlCopyMemory(*ppWhere, pString->Buffer, pString->Length);
  278. pDestString->Buffer = *ppWhere;
  279. pDestString->Length = pString->Length;
  280. pDestString->MaximumLength = pString->Length + sizeof(WCHAR);
  281. *ppWhere += pDestString->MaximumLength / sizeof(WCHAR);
  282. //
  283. // add unicode NULL
  284. //
  285. pDestString->Buffer[(pDestString->MaximumLength / sizeof(WCHAR)) - 1] = UNICODE_NULL;
  286. }
  287. //+-------------------------------------------------------------------------
  288. //
  289. // Function: PackS4UDelegationInformation
  290. //
  291. // Synopsis: Pack S4U DelegationInformation
  292. //
  293. // Effects:
  294. //
  295. // Arguments:
  296. //
  297. // Requires:
  298. //
  299. // Returns:
  300. //
  301. // Notes:
  302. //
  303. //
  304. //-------------------------------------------------------------------------
  305. NTSTATUS
  306. PackS4UDelegationInformation(
  307. IN OPTIONAL PS4U_DELEGATION_INFO DelegationInfo,
  308. OUT PS4U_DELEGATION_INFO* NewDelegationInfo
  309. )
  310. {
  311. ULONG NewDelegationInfoSize = 0;
  312. WCHAR* Where = NULL;
  313. *NewDelegationInfo = NULL;
  314. if (DelegationInfo)
  315. {
  316. NewDelegationInfoSize = ROUND_UP_COUNT(sizeof(S4U_DELEGATION_INFO), ALIGN_QUAD)
  317. + ROUND_UP_COUNT(DelegationInfo->S4U2proxyTarget.Length + sizeof(WCHAR), ALIGN_QUAD);
  318. if (DelegationInfo->TransitedListSize)
  319. {
  320. NewDelegationInfoSize += ROUND_UP_COUNT(NewDelegationInfoSize, ALIGN_QUAD);
  321. for (ULONG i = 0; i < DelegationInfo->TransitedListSize; i++)
  322. {
  323. NewDelegationInfoSize += ROUND_UP_COUNT(sizeof(UNICODE_STRING), ALIGN_QUAD)
  324. + ROUND_UP_COUNT(DelegationInfo->S4UTransitedServices[i].Length + sizeof(WCHAR), ALIGN_QUAD);
  325. }
  326. }
  327. *NewDelegationInfo = (PS4U_DELEGATION_INFO) MIDL_user_allocate(NewDelegationInfoSize);
  328. if (NULL == *NewDelegationInfo)
  329. {
  330. return STATUS_NO_MEMORY;
  331. }
  332. RtlZeroMemory(*NewDelegationInfo, NewDelegationInfoSize);
  333. Where = (WCHAR*) (*NewDelegationInfo + 1);
  334. PackUnicodeStringAsUnicodeStringZ(&DelegationInfo->S4U2proxyTarget, &Where, &(*NewDelegationInfo)->S4U2proxyTarget);
  335. (*NewDelegationInfo)->TransitedListSize = DelegationInfo->TransitedListSize;
  336. (*NewDelegationInfo)->S4UTransitedServices = (UNICODE_STRING*) ROUND_UP_POINTER(Where, ALIGN_QUAD);
  337. Where = (WCHAR*) ((*NewDelegationInfo)->S4UTransitedServices + DelegationInfo->TransitedListSize);
  338. for (ULONG j = 0; j < DelegationInfo->TransitedListSize; j++)
  339. {
  340. PackUnicodeStringAsUnicodeStringZ(
  341. &DelegationInfo->S4UTransitedServices[j],
  342. &Where,
  343. &(*NewDelegationInfo)->S4UTransitedServices[j]
  344. );
  345. }
  346. }
  347. return STATUS_SUCCESS;
  348. }
  349. //+-------------------------------------------------------------------------
  350. //
  351. // Function: PackS4UDelegationInformation
  352. //
  353. // Synopsis: Pack S4U DelegationInformation
  354. //
  355. // Effects:
  356. //
  357. // Arguments:
  358. //
  359. // Requires:
  360. //
  361. // Returns:
  362. //
  363. // Notes:
  364. //
  365. //
  366. //-------------------------------------------------------------------------
  367. NTSTATUS
  368. UnmarshalS4UDelegationInformation(
  369. IN ULONG DelegInfoMarshalledSize,
  370. IN OPTIONAL BYTE* DelegInfoMarshalled,
  371. OUT PS4U_DELEGATION_INFO* S4UDelegationInfo
  372. )
  373. {
  374. NTSTATUS Status;
  375. PS4U_DELEGATION_INFO RawDelegInfo = NULL;
  376. Status = PAC_UnmarshallS4UDelegationInfo(
  377. &RawDelegInfo,
  378. DelegInfoMarshalled,
  379. DelegInfoMarshalledSize
  380. );
  381. if (!NT_SUCCESS(Status))
  382. {
  383. DebugLog((DEB_ERROR, "KdcUpdateAndValidateS4UProxyPAC failed to unmarshall S4U delgation info %#x\n", Status));
  384. goto Cleanup;
  385. }
  386. Status = PackS4UDelegationInformation(
  387. RawDelegInfo,
  388. S4UDelegationInfo
  389. );
  390. if (!NT_SUCCESS( Status ))
  391. {
  392. DebugLog((DEB_ERROR, "KdcUpdateAndValidateS4UProxyPAC: PackS4UDelegationInformation failed - %#x\n", Status));
  393. goto Cleanup;
  394. }
  395. Cleanup:
  396. if (RawDelegInfo != NULL)
  397. {
  398. MIDL_user_free(RawDelegInfo);
  399. }
  400. return Status;
  401. }
  402. //+-------------------------------------------------------------------------
  403. //
  404. // Function: KerbMapStatusToKerbError
  405. //
  406. // Synopsis: Maps an NTSTATUS or SECURITY_STATUS to a KERBERR
  407. //
  408. // Effects:
  409. //
  410. // Arguments:
  411. //
  412. // Requires:
  413. //
  414. // Returns:
  415. //
  416. // Notes:
  417. //
  418. //
  419. //--------------------------------------------------------------------------
  420. KERBERR
  421. KerbMapStatusToKerbError(
  422. IN LONG Status
  423. )
  424. {
  425. KERBERR KerbError = KRB_ERR_GENERIC;
  426. switch (Status) {
  427. case SEC_E_ETYPE_NOT_SUPP:
  428. KerbError = KDC_ERR_ETYPE_NOTSUPP;
  429. break;
  430. case SEC_E_OK:
  431. KerbError = KDC_ERR_NONE;
  432. break;
  433. default:
  434. KerbError = KRB_ERR_GENERIC;
  435. break;
  436. }
  437. return KerbError;
  438. }