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.

491 lines
12 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1992 - 1996
  6. //
  7. // File: ctxtmgr.cxx
  8. //
  9. // Contents: Code for managing contexts list for the Kerberos package
  10. //
  11. //
  12. // History: 17-April-1996 Created MikeSw
  13. //
  14. //------------------------------------------------------------------------
  15. #include "krbprgma.h"
  16. #define CTXTMGR_ALLOCATE
  17. #include <kerbkrnl.h>
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text(PAGE, KerbInitContextList)
  20. #pragma alloc_text(PAGE, KerbFreeContextList)
  21. #pragma alloc_text(PAGEMSG, KerbAllocateContext)
  22. #pragma alloc_text(PAGEMSG, KerbInsertContext)
  23. #pragma alloc_text(PAGEMSG, KerbReferenceContext)
  24. #pragma alloc_text(PAGEMSG, KerbDereferenceContext)
  25. #pragma alloc_text(PAGEMSG, KerbCreateKernelModeContext)
  26. #endif
  27. #define MAYBE_PAGED_CODE() \
  28. if ( KerbPoolType == PagedPool ) \
  29. { \
  30. PAGED_CODE(); \
  31. }
  32. //+-------------------------------------------------------------------------
  33. //
  34. // Function: KerbInitContextList
  35. //
  36. // Synopsis: Initializes the contexts list
  37. //
  38. // Effects: allocates a resources
  39. //
  40. // Arguments: none
  41. //
  42. // Requires:
  43. //
  44. // Returns: STATUS_SUCCESS on success, other error codes
  45. // on failure
  46. //
  47. // Notes:
  48. //
  49. //
  50. //--------------------------------------------------------------------------
  51. NTSTATUS
  52. KerbInitContextList(
  53. VOID
  54. )
  55. {
  56. NTSTATUS Status;
  57. PAGED_CODE();
  58. Status = ExInitializeResourceLite( &KerbContextResource );
  59. if (!NT_SUCCESS(Status))
  60. {
  61. return Status;
  62. }
  63. Status = KerbInitializeList( &KerbContextList );
  64. if (!NT_SUCCESS(Status))
  65. {
  66. ExDeleteResourceLite( &KerbContextResource );
  67. }
  68. return Status;
  69. }
  70. //+-------------------------------------------------------------------------
  71. //
  72. // Function: KerbAllocateContext
  73. //
  74. // Synopsis: Allocates a Context structure
  75. //
  76. // Effects: Allocates a Context, but does not add it to the
  77. // list of Contexts
  78. //
  79. // Arguments: NewContext - receives a new Context allocated
  80. // with KerbAllocate
  81. //
  82. // Requires:
  83. //
  84. // Returns: STATUS_SUCCESS on success
  85. // STATUS_INSUFFICIENT_RESOURCES if the allocation fails
  86. //
  87. // Notes:
  88. //
  89. //
  90. //--------------------------------------------------------------------------
  91. NTSTATUS
  92. KerbAllocateContext(
  93. PKERB_KERNEL_CONTEXT * NewContext
  94. )
  95. {
  96. PKERB_KERNEL_CONTEXT Context;
  97. MAYBE_PAGED_CODE();
  98. //
  99. // Get the client process ID if we are running in the LSA
  100. //
  101. Context = (PKERB_KERNEL_CONTEXT) KerbAllocate(
  102. sizeof(KERB_KERNEL_CONTEXT) );
  103. if (Context == NULL)
  104. {
  105. return(STATUS_INSUFFICIENT_RESOURCES);
  106. }
  107. RtlZeroMemory(
  108. Context,
  109. sizeof(KERB_KERNEL_CONTEXT)
  110. );
  111. KsecInitializeListEntry( &Context->List, KERB_CONTEXT_SIGNATURE );
  112. *NewContext = Context;
  113. return(STATUS_SUCCESS);
  114. }
  115. //+-------------------------------------------------------------------------
  116. //
  117. // Function: KerbInsertContext
  118. //
  119. // Synopsis: Inserts a logon session into the list of logon sessions
  120. //
  121. // Effects: bumps reference count on logon session
  122. //
  123. // Arguments: Context - Context to insert
  124. //
  125. // Requires:
  126. //
  127. // Returns: STATUS_SUCCESS always
  128. //
  129. // Notes:
  130. //
  131. //
  132. //--------------------------------------------------------------------------
  133. NTSTATUS
  134. KerbInsertContext(
  135. IN PKERB_KERNEL_CONTEXT Context
  136. )
  137. {
  138. MAYBE_PAGED_CODE();
  139. KSecInsertListEntry(
  140. KerbActiveList,
  141. (PKSEC_LIST_ENTRY) Context
  142. );
  143. return(STATUS_SUCCESS);
  144. }
  145. //+-------------------------------------------------------------------------
  146. //
  147. // Function: KerbReferenceContext
  148. //
  149. // Synopsis: Locates a context and references it
  150. //
  151. // Effects: Increments reference count and possible unlinks it from list
  152. //
  153. // Arguments: ContextHandle - Lsa Handle of context to reference.
  154. // RemoveFromList - If TRUE, context will be delinked.
  155. //
  156. // Requires:
  157. //
  158. // Returns:
  159. //
  160. // Notes:
  161. //
  162. //
  163. //--------------------------------------------------------------------------
  164. PKERB_KERNEL_CONTEXT
  165. KerbReferenceContext(
  166. IN LSA_SEC_HANDLE ContextHandle,
  167. IN BOOLEAN RemoveFromList
  168. )
  169. {
  170. PKERB_KERNEL_CONTEXT Context = NULL;
  171. NTSTATUS Status;
  172. MAYBE_PAGED_CODE();
  173. Status = KSecReferenceListEntry(
  174. (PKSEC_LIST_ENTRY) ContextHandle,
  175. KERB_CONTEXT_SIGNATURE,
  176. RemoveFromList );
  177. if ( NT_SUCCESS( Status ) )
  178. {
  179. Context = (PKERB_KERNEL_CONTEXT) ContextHandle ;
  180. }
  181. //
  182. // In kernel mode we trust the caller to provide a valid pointer, but
  183. // make sure it is a kernel mode pointer.
  184. //
  185. return(Context);
  186. }
  187. //+-------------------------------------------------------------------------
  188. //
  189. // Function: KerbFreeContext
  190. //
  191. // Synopsis: Frees a context that is unlinked
  192. //
  193. // Effects: frees all storage associated with the context
  194. //
  195. // Arguments: Context - context to free
  196. //
  197. // Requires:
  198. //
  199. // Returns: none
  200. //
  201. // Notes:
  202. //
  203. //
  204. //--------------------------------------------------------------------------
  205. VOID
  206. KerbFreeContext(
  207. IN PKERB_KERNEL_CONTEXT Context
  208. )
  209. {
  210. PAGED_CODE();
  211. if (Context->TokenHandle != NULL)
  212. {
  213. NtClose(Context->TokenHandle);
  214. }
  215. if (Context->AccessToken != NULL)
  216. {
  217. ObDereferenceObject( Context->AccessToken );
  218. }
  219. if (Context->FullName.Buffer != NULL)
  220. {
  221. KerbFree(Context->FullName.Buffer);
  222. }
  223. if (Context->SessionKey.keyvalue.value != NULL)
  224. {
  225. KerbFree(Context->SessionKey.keyvalue.value);
  226. }
  227. if (Context->pbMarshalledTargetInfo != NULL)
  228. {
  229. KerbFree(Context->pbMarshalledTargetInfo);
  230. }
  231. KerbFree(Context);
  232. }
  233. //+-------------------------------------------------------------------------
  234. //
  235. // Function: KerbDereferenceContext
  236. //
  237. // Synopsis: Dereferences a logon session - if reference count goes
  238. // to zero it frees the logon session
  239. //
  240. // Effects: decrements reference count
  241. //
  242. // Arguments: Context - Logon session to dereference
  243. //
  244. // Requires:
  245. //
  246. // Returns: none
  247. //
  248. // Notes:
  249. //
  250. //
  251. //--------------------------------------------------------------------------
  252. VOID
  253. KerbDereferenceContext(
  254. IN PKERB_KERNEL_CONTEXT Context
  255. )
  256. {
  257. BOOLEAN Delete ;
  258. MAYBE_PAGED_CODE();
  259. KSecDereferenceListEntry(
  260. (PKSEC_LIST_ENTRY) Context,
  261. &Delete );
  262. if ( Delete )
  263. {
  264. KerbFreeContext( Context );
  265. }
  266. }
  267. //+-------------------------------------------------------------------------
  268. //
  269. // Function: KerbCreateKernelModeContext
  270. //
  271. // Synopsis: Creates a kernel-mode context to support impersonation and
  272. // message integrity and privacy
  273. //
  274. // Effects:
  275. //
  276. // Arguments:
  277. //
  278. // Requires:
  279. //
  280. // Returns:
  281. //
  282. // Notes:
  283. //
  284. //
  285. //--------------------------------------------------------------------------
  286. NTSTATUS
  287. KerbCreateKernelModeContext(
  288. IN LSA_SEC_HANDLE ContextHandle,
  289. IN PSecBuffer MarshalledContext,
  290. OUT PKERB_KERNEL_CONTEXT * NewContext
  291. )
  292. {
  293. NTSTATUS Status;
  294. PKERB_KERNEL_CONTEXT Context = NULL;
  295. PKERB_PACKED_CONTEXT PackedContext ;
  296. PUCHAR Where;
  297. PAGED_CODE();
  298. if (MarshalledContext->cbBuffer < sizeof(KERB_PACKED_CONTEXT))
  299. {
  300. DebugLog((DEB_ERROR,"Invalid buffer size for marshalled context: was 0x%x, needed 0x%x\n",
  301. MarshalledContext->cbBuffer, sizeof(KERB_CONTEXT)));
  302. return(STATUS_INVALID_PARAMETER);
  303. }
  304. PackedContext = (PKERB_PACKED_CONTEXT) MarshalledContext->pvBuffer;
  305. Status = KerbAllocateContext( &Context );
  306. if (!NT_SUCCESS(Status))
  307. {
  308. goto Cleanup;
  309. }
  310. KsecInitializeListEntry( &Context->List, KERB_CONTEXT_SIGNATURE );
  311. Context->Lifetime = PackedContext->Lifetime;
  312. Context->RenewTime = PackedContext->RenewTime;
  313. Context->Nonce = PackedContext->Nonce;
  314. Context->ReceiveNonce = PackedContext->ReceiveNonce;
  315. Context->ContextFlags = PackedContext->ContextFlags;
  316. Context->ContextAttributes = PackedContext->ContextAttributes;
  317. Context->EncryptionType = PackedContext->EncryptionType;
  318. Context->LsaContextHandle = ContextHandle;
  319. Context->ReceiveNonce = Context->Nonce;
  320. Context->TokenHandle = (HANDLE) ULongToPtr(PackedContext->TokenHandle);
  321. //
  322. // Fill in the full name, which is the concatenation of the client name
  323. // and client realm with a '\\' separator
  324. //
  325. Context->FullName.MaximumLength = PackedContext->ClientName.Length +
  326. PackedContext->ClientRealm.Length +
  327. sizeof(WCHAR);
  328. Context->FullName.Buffer = (LPWSTR) KerbAllocate(Context->FullName.MaximumLength);
  329. if (Context->FullName.Buffer == NULL)
  330. {
  331. Status = STATUS_INSUFFICIENT_RESOURCES;
  332. goto Cleanup;
  333. }
  334. Where = (PUCHAR) Context->FullName.Buffer;
  335. if (PackedContext->ClientRealm.Length != 0)
  336. {
  337. RtlCopyMemory(
  338. Where,
  339. (PUCHAR) PackedContext + (ULONG_PTR) PackedContext->ClientRealm.Buffer,
  340. PackedContext->ClientRealm.Length
  341. );
  342. Where += PackedContext->ClientRealm.Length;
  343. *(LPWSTR) Where = L'\\';
  344. Where += sizeof(WCHAR);
  345. }
  346. if (PackedContext->ClientName.Length != 0)
  347. {
  348. RtlCopyMemory(
  349. Where,
  350. (PUCHAR) PackedContext + (ULONG_PTR) PackedContext->ClientName.Buffer,
  351. PackedContext->ClientName.Length
  352. );
  353. Where += PackedContext->ClientName.Length;
  354. }
  355. Context->FullName.Length = (USHORT) (Where - (PUCHAR) Context->FullName.Buffer);
  356. //
  357. // Copy in the session key
  358. //
  359. Context->SessionKey.keytype = PackedContext->SessionKeyType;
  360. Context->SessionKey.keyvalue.length = PackedContext->SessionKeyLength;
  361. if (Context->SessionKey.keyvalue.length != 0)
  362. {
  363. Context->SessionKey.keyvalue.value = (PUCHAR) KerbAllocate( Context->SessionKey.keyvalue.length );
  364. if (Context->SessionKey.keyvalue.value == NULL)
  365. {
  366. Status = STATUS_INSUFFICIENT_RESOURCES;
  367. goto Cleanup;
  368. }
  369. RtlCopyMemory(
  370. Context->SessionKey.keyvalue.value,
  371. (PUCHAR) PackedContext + PackedContext->SessionKeyOffset,
  372. Context->SessionKey.keyvalue.length
  373. );
  374. }
  375. //
  376. // copy in the marshalled target info.
  377. //
  378. Context->cbMarshalledTargetInfo = PackedContext->MarshalledTargetInfoLength;
  379. if (PackedContext->MarshalledTargetInfo)
  380. {
  381. Context->pbMarshalledTargetInfo = (PUCHAR) KerbAllocate( Context->cbMarshalledTargetInfo );
  382. if (Context->pbMarshalledTargetInfo == NULL)
  383. {
  384. Status = STATUS_INSUFFICIENT_RESOURCES;
  385. goto Cleanup;
  386. }
  387. RtlCopyMemory(
  388. Context->pbMarshalledTargetInfo,
  389. (PUCHAR) PackedContext + PackedContext->MarshalledTargetInfo,
  390. Context->cbMarshalledTargetInfo
  391. );
  392. } else {
  393. Context->pbMarshalledTargetInfo = NULL;
  394. }
  395. Status = KerbInsertContext(
  396. Context
  397. );
  398. if (!NT_SUCCESS(Status))
  399. {
  400. DebugLog((DEB_ERROR,"Failed to insert context: 0x%x\n",Status));
  401. goto Cleanup;
  402. }
  403. *NewContext = Context;
  404. Cleanup:
  405. if (!NT_SUCCESS(Status))
  406. {
  407. if (Context != NULL)
  408. {
  409. KerbFreeContext(Context);
  410. }
  411. }
  412. return(Status);
  413. }