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.

3138 lines
80 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. // 26-Sep-1998 ChandanS
  14. // Added more debugging support etc.
  15. //
  16. //------------------------------------------------------------------------
  17. #include <kerb.hxx>
  18. #define CTXTMGR_ALLOCATE
  19. #include <kerbp.h>
  20. #include "userapi.h"
  21. #ifdef RETAIL_LOG_SUPPORT
  22. static TCHAR THIS_FILE[]=TEXT(__FILE__);
  23. #endif
  24. ULONG
  25. HandleToListIndex(
  26. ULONG_PTR ContextHandle
  27. );
  28. //+-------------------------------------------------------------------------
  29. //
  30. // Function: KerbInitContextList
  31. //
  32. // Synopsis: Initializes the contexts list
  33. //
  34. // Effects: allocates a resources
  35. //
  36. // Arguments: none
  37. //
  38. // Requires:
  39. //
  40. // Returns: STATUS_SUCCESS on success, other error codes
  41. // on failure
  42. //
  43. // Notes:
  44. //
  45. //
  46. //--------------------------------------------------------------------------
  47. NTSTATUS
  48. KerbInitContextList(
  49. VOID
  50. )
  51. {
  52. NTSTATUS Status = STATUS_SUCCESS;
  53. ULONG Index = 0;
  54. __try {
  55. SafeInitializeResource( &KerbContextResource, CONTEXT_RESOURCE_LOCK_ENUM );
  56. } __except(EXCEPTION_EXECUTE_HANDLER)
  57. {
  58. return STATUS_INSUFFICIENT_RESOURCES;
  59. }
  60. for(Index = 0 ; Index < KERB_USERLIST_COUNT ; Index++)
  61. {
  62. Status = KerbInitializeList( &KerbContextList[Index], CONTEXT_LIST_LOCK_ENUM );
  63. if (!NT_SUCCESS(Status))
  64. {
  65. goto Cleanup;
  66. }
  67. }
  68. KerberosContextsInitialized = TRUE;
  69. Cleanup:
  70. if (!NT_SUCCESS(Status))
  71. {
  72. ULONG i;
  73. SafeDeleteResource( &KerbContextResource );
  74. for( i = 0 ; i < Index ; i++ )
  75. {
  76. KerbFreeList( &KerbContextList[i] );
  77. }
  78. }
  79. return Status;
  80. }
  81. //+-------------------------------------------------------------------------
  82. //
  83. // Function: KerbFreeContextList
  84. //
  85. // Synopsis: Frees the contexts list
  86. //
  87. // Effects:
  88. //
  89. // Arguments: none
  90. //
  91. // Requires:
  92. //
  93. // Returns: none
  94. //
  95. // Notes:
  96. //
  97. //
  98. //--------------------------------------------------------------------------
  99. VOID
  100. KerbFreeContextList(
  101. VOID
  102. )
  103. {
  104. #if 0
  105. PKERB_CONTEXT Context;
  106. if (KerberosContextsInitialized)
  107. {
  108. KerbLockList(&KerbContextList);
  109. //
  110. // Go through the list of logon sessions and dereferences them all
  111. //
  112. while (!IsListEmpty(&KerbContextList.List))
  113. {
  114. Context = CONTAINING_RECORD(
  115. KerbContextList.List.Flink,
  116. KERB_CONTEXT,
  117. ListEntry.Next
  118. );
  119. KerbReferenceListEntry(
  120. &KerbContextList,
  121. &Context->ListEntry,
  122. TRUE
  123. );
  124. KerbDereferenceContext(Context);
  125. }
  126. KerbFreeList(&KerbContextList);
  127. }
  128. #endif
  129. }
  130. //+-------------------------------------------------------------------------
  131. //
  132. // Function: KerbAllocateContext
  133. //
  134. // Synopsis: Allocates a Context structure
  135. //
  136. // Effects: Allocates a Context, but does not add it to the
  137. // list of Contexts
  138. //
  139. // Arguments: NewContext - receives a new Context allocated
  140. // with KerbAllocate
  141. //
  142. // Requires:
  143. //
  144. // Returns: STATUS_SUCCESS on success
  145. // STATUS_INSUFFICIENT_RESOURCES if the allocation fails
  146. //
  147. // Notes:
  148. //
  149. //
  150. //--------------------------------------------------------------------------
  151. NTSTATUS
  152. KerbAllocateContext(
  153. OUT PKERB_CONTEXT * NewContext,
  154. IN BOOLEAN UserMode
  155. )
  156. {
  157. PKERB_CONTEXT Context;
  158. SECPKG_CALL_INFO CallInfo = {0};
  159. //
  160. // Get the client process ID if we are running in the LSA
  161. //
  162. if (!UserMode)
  163. {
  164. if (!LsaFunctions->GetCallInfo(&CallInfo))
  165. {
  166. D_DebugLog((DEB_ERROR,"Failed to get call info\n. %ws, line %d\n",
  167. THIS_FILE, __LINE__));
  168. DsysAssert(FALSE);
  169. return(STATUS_INSUFFICIENT_RESOURCES);
  170. }
  171. }
  172. Context = (PKERB_CONTEXT) KerbAllocate(
  173. sizeof(KERB_CONTEXT) );
  174. if (Context == NULL)
  175. {
  176. return(STATUS_INSUFFICIENT_RESOURCES);
  177. }
  178. Context->ClientProcess = CallInfo.ProcessId;
  179. Context->ContextState = IdleState;
  180. //
  181. // Set the references to 1 since we are returning a pointer to the
  182. // logon session
  183. //
  184. KerbInitializeListEntry(
  185. &Context->ListEntry
  186. );
  187. *NewContext = Context;
  188. return(STATUS_SUCCESS);
  189. }
  190. //+-------------------------------------------------------------------------
  191. //
  192. // Function: KerbInsertContext
  193. //
  194. // Synopsis: Inserts a logon session into the list of logon sessions
  195. //
  196. // Effects: bumps reference count on logon session
  197. //
  198. // Arguments: Context - Context to insert
  199. //
  200. // Requires:
  201. //
  202. // Returns: STATUS_SUCCESS always
  203. //
  204. // Notes:
  205. //
  206. //
  207. //--------------------------------------------------------------------------
  208. NTSTATUS
  209. KerbInsertContext(
  210. IN PKERB_CONTEXT Context
  211. )
  212. {
  213. ULONG ListIndex;
  214. ListIndex = HandleToListIndex( Context->LsaContextHandle );
  215. Context->ContextTag = KERB_CONTEXT_TAG_ACTIVE;
  216. KerbInsertListEntry(
  217. &Context->ListEntry,
  218. &KerbContextList[ListIndex]
  219. );
  220. return(STATUS_SUCCESS);
  221. }
  222. //+-------------------------------------------------------------------------
  223. //
  224. // Function: KerbReferenceContext
  225. //
  226. // Synopsis: Locates a context context handleand references it
  227. //
  228. // Effects: Increments reference count and possible unlinks it from list
  229. //
  230. // Arguments: ContextHandle - Handle of context to reference.
  231. // RemoveFromList - If TRUE, context will be delinked.
  232. //
  233. // Requires:
  234. //
  235. // Returns:
  236. //
  237. // Notes:
  238. //
  239. //
  240. //--------------------------------------------------------------------------
  241. SECURITY_STATUS
  242. KerbReferenceContext(
  243. IN LSA_SEC_HANDLE ContextHandle,
  244. IN BOOLEAN RemoveFromList,
  245. OUT PKERB_CONTEXT * FoundContext
  246. )
  247. {
  248. PKERB_CONTEXT Context = NULL;
  249. BOOLEAN Found = FALSE;
  250. SECPKG_CLIENT_INFO ClientInfo;
  251. NTSTATUS Status = STATUS_SUCCESS;
  252. ULONG ListIndex = 0;
  253. BOOLEAN ListLocked = FALSE;
  254. if (KerberosState == KerberosLsaMode)
  255. {
  256. Status = LsaFunctions->GetClientInfo(&ClientInfo);
  257. if (!NT_SUCCESS(Status))
  258. {
  259. SECPKG_CALL_INFO CallInfo;
  260. //
  261. // Check to see if the call is terminating. If so, give it
  262. // TCB privilege because it is really the LSA doing this.
  263. //
  264. if (LsaFunctions->GetCallInfo(&CallInfo))
  265. {
  266. if ((CallInfo.Attributes & SECPKG_CALL_CLEANUP) != 0)
  267. {
  268. Status = STATUS_SUCCESS;
  269. RtlZeroMemory(
  270. &ClientInfo,
  271. sizeof(SECPKG_CLIENT_INFO)
  272. );
  273. ClientInfo.HasTcbPrivilege = TRUE;
  274. }
  275. }
  276. if (!NT_SUCCESS(Status))
  277. {
  278. D_DebugLog((DEB_ERROR, "Failed to get client info: 0x%x. %ws, line %d\n", Status, THIS_FILE, __LINE__));
  279. *FoundContext = NULL ;
  280. return(Status);
  281. }
  282. }
  283. }
  284. else
  285. {
  286. ClientInfo.HasTcbPrivilege = FALSE ;
  287. ClientInfo.ProcessID = GetCurrentProcessId();
  288. }
  289. //
  290. // Go through the list of logon sessions looking for the correct
  291. // context
  292. //
  293. Context = (PKERB_CONTEXT)ContextHandle;
  294. while ( Context->ContextTag == KERB_CONTEXT_TAG_ACTIVE )
  295. {
  296. ListIndex = HandleToListIndex( Context->LsaContextHandle );
  297. KerbLockList(&KerbContextList[ListIndex]);
  298. ListLocked = TRUE;
  299. //
  300. // Make sure that if we aren't trying to remove it we are
  301. // from the correct process.
  302. //
  303. if (!ClientInfo.HasTcbPrivilege &&
  304. (Context->ClientProcess != ClientInfo.ProcessID) &&
  305. (KerberosState == KerberosLsaMode))
  306. {
  307. D_DebugLog((DEB_ERROR, "Trying to reference a context from another process! %ws, line %d\n", THIS_FILE, __LINE__));
  308. Found = FALSE;
  309. break;
  310. }
  311. //
  312. // If the context is expired, don't allow it to be referenced.
  313. //
  314. if (KerbGlobalEnforceTime && !RemoveFromList)
  315. {
  316. TimeStamp CurrentTime;
  317. TimeStamp ContextExpires;
  318. GetSystemTimeAsFileTime((PFILETIME) &CurrentTime);
  319. ContextExpires = Context->Lifetime;
  320. if (KerbGetTime(ContextExpires) < KerbGetTime(CurrentTime))
  321. {
  322. D_DebugLog((DEB_WARN, "Trying to reference expired context\n"));
  323. Found = FALSE;
  324. Status = SEC_E_CONTEXT_EXPIRED;
  325. break;
  326. }
  327. }
  328. KerbReferenceListEntry(
  329. &KerbContextList[ ListIndex ],
  330. &Context->ListEntry,
  331. RemoveFromList
  332. );
  333. Found = TRUE;
  334. break;
  335. }
  336. if ( ListLocked )
  337. {
  338. KerbUnlockList(&KerbContextList[ListIndex]);
  339. }
  340. if (!Found)
  341. {
  342. Context = NULL;
  343. }
  344. *FoundContext = Context ;
  345. if ( Context )
  346. {
  347. return Status;
  348. }
  349. else if (NT_SUCCESS(Status))
  350. {
  351. return SEC_E_INVALID_HANDLE ;
  352. }
  353. else
  354. {
  355. return Status;
  356. }
  357. }
  358. //+-------------------------------------------------------------------------
  359. //
  360. // Function: KerbReferenceContextByLsaHandle
  361. //
  362. // Synopsis: Locates a context by lsa context handle and references it
  363. //
  364. // Effects: Increments reference count and possible unlinks it from list
  365. //
  366. // Arguments: ContextHandle - Lsa Handle of context to reference.
  367. // RemoveFromList - If TRUE, context will be delinked.
  368. //
  369. // Requires:
  370. //
  371. // Returns:
  372. //
  373. // Notes:
  374. //
  375. //
  376. //--------------------------------------------------------------------------
  377. SECURITY_STATUS
  378. KerbReferenceContextByLsaHandle(
  379. IN LSA_SEC_HANDLE ContextHandle,
  380. IN BOOLEAN RemoveFromList,
  381. OUT PKERB_CONTEXT *FoundContext
  382. )
  383. {
  384. PLIST_ENTRY ListEntry;
  385. PKERB_CONTEXT Context = NULL;
  386. BOOLEAN Found = FALSE;
  387. NTSTATUS Status = STATUS_SUCCESS;
  388. ULONG ListIndex;
  389. ListIndex = HandleToListIndex( ContextHandle );
  390. KerbLockList(&KerbContextList[ListIndex]);
  391. //
  392. // Go through the list of logon sessions looking for the correct
  393. // context
  394. //
  395. for (ListEntry = KerbContextList[ListIndex].List.Flink ;
  396. ListEntry != &KerbContextList[ListIndex].List ;
  397. ListEntry = ListEntry->Flink )
  398. {
  399. Context = CONTAINING_RECORD(ListEntry, KERB_CONTEXT, ListEntry.Next);
  400. if (ContextHandle == Context->LsaContextHandle)
  401. {
  402. //
  403. // Make sure that if we aren't trying to remove it we are
  404. // from the correct process.
  405. //
  406. //
  407. // If the context is expired, don't allow it to be referenced.
  408. //
  409. if (KerbGlobalEnforceTime && !RemoveFromList )
  410. {
  411. TimeStamp CurrentTime;
  412. TimeStamp ContextExpires;
  413. GetSystemTimeAsFileTime((PFILETIME) &CurrentTime );
  414. ContextExpires = Context->Lifetime;
  415. if (KerbGetTime(ContextExpires) < KerbGetTime(CurrentTime))
  416. {
  417. D_DebugLog((DEB_WARN, "Trying to reference expired context\n"));
  418. Found = FALSE;
  419. Status = SEC_E_CONTEXT_EXPIRED;
  420. break;
  421. }
  422. }
  423. KerbReferenceListEntry(
  424. &KerbContextList[ListIndex],
  425. &Context->ListEntry,
  426. RemoveFromList
  427. );
  428. Found = TRUE;
  429. break;
  430. }
  431. }
  432. KerbUnlockList(&KerbContextList[ListIndex]);
  433. if (!Found)
  434. {
  435. Context = NULL;
  436. }
  437. *FoundContext = Context ;
  438. if ( Context )
  439. {
  440. return Status;
  441. }
  442. else if (NT_SUCCESS(Status))
  443. {
  444. return SEC_E_INVALID_HANDLE ;
  445. }
  446. else
  447. {
  448. return Status;
  449. }
  450. }
  451. //+-------------------------------------------------------------------------
  452. //
  453. // Function: KerbReferenceContextByPointer
  454. //
  455. // Synopsis: References a context by the context pointer itself.
  456. //
  457. // Effects: Increments reference count and possible unlinks it from list
  458. //
  459. // Arguments: Context - The context to reference.
  460. // RemoveFromList - If TRUE, context will be delinked
  461. //
  462. // Requires:
  463. //
  464. // Returns:
  465. //
  466. // Notes:
  467. //
  468. //
  469. //--------------------------------------------------------------------------
  470. VOID
  471. KerbReferenceContextByPointer(
  472. IN PKERB_CONTEXT Context,
  473. IN BOOLEAN RemoveFromList
  474. )
  475. {
  476. ULONG ListIndex;
  477. ListIndex = HandleToListIndex( Context->LsaContextHandle );
  478. KerbLockList(&KerbContextList[ListIndex]);
  479. KerbReferenceListEntry(
  480. &KerbContextList[ListIndex],
  481. &Context->ListEntry,
  482. RemoveFromList
  483. );
  484. KerbUnlockList(&KerbContextList[ListIndex]);
  485. }
  486. //+-------------------------------------------------------------------------
  487. //
  488. // Function: KerbFreeContext
  489. //
  490. // Synopsis: Frees a context that is unlinked
  491. //
  492. // Effects: frees all storage associated with the context
  493. //
  494. // Arguments: Context - context to free
  495. //
  496. // Requires:
  497. //
  498. // Returns: none
  499. //
  500. // Notes:
  501. //
  502. //
  503. //--------------------------------------------------------------------------
  504. VOID
  505. KerbFreeContext(
  506. IN PKERB_CONTEXT Context
  507. )
  508. {
  509. #ifndef WIN32_CHICAGO
  510. if (Context->TokenHandle != NULL)
  511. {
  512. NtClose(Context->TokenHandle);
  513. }
  514. #endif // WIN32_CHICAGO
  515. Context->ContextTag = KERB_CONTEXT_TAG_DELETE;
  516. KerbFreeKey(&Context->SessionKey);
  517. KerbFreeKey(&Context->TicketKey);
  518. if (Context->TicketCacheEntry != NULL)
  519. {
  520. KerbDereferenceTicketCacheEntry(Context->TicketCacheEntry);
  521. }
  522. if (Context->UserSid != NULL)
  523. {
  524. KerbFree(Context->UserSid);
  525. }
  526. KerbFreeString(&Context->ClientName);
  527. KerbFreeString(&Context->ClientRealm);
  528. KerbFreeString(&Context->ClientDnsRealm);
  529. KerbFreeString(&Context->ClientPrincipalName);
  530. KerbFreeString(&Context->ServerPrincipalName);
  531. if( Context->pbMarshalledTargetInfo )
  532. {
  533. KerbFree( Context->pbMarshalledTargetInfo );
  534. }
  535. KerbFree(Context);
  536. }
  537. //+-------------------------------------------------------------------------
  538. //
  539. // Function: KerbDereferenceContext
  540. //
  541. // Synopsis: Dereferences a logon session - if reference count goes
  542. // to zero it frees the logon session
  543. //
  544. // Effects: decrements reference count
  545. //
  546. // Arguments: Context - Logon session to dereference
  547. //
  548. // Requires:
  549. //
  550. // Returns: none
  551. //
  552. // Notes:
  553. //
  554. //
  555. //--------------------------------------------------------------------------
  556. VOID
  557. KerbDereferenceContext(
  558. IN PKERB_CONTEXT Context
  559. )
  560. {
  561. ULONG ListIndex;
  562. ListIndex = HandleToListIndex( Context->LsaContextHandle );
  563. if (KerbDereferenceListEntry(
  564. &Context->ListEntry,
  565. &KerbContextList[ListIndex]
  566. ) )
  567. {
  568. KerbFreeContext(Context);
  569. }
  570. }
  571. //+-------------------------------------------------------------------------
  572. //
  573. // Function: KerbCreateEmptyContext
  574. //
  575. // Synopsis: Creates a context for the server of a datagram authentication
  576. // session. Since there is no input message, all the fields
  577. // are initialized to zero.
  578. //
  579. // Effects: Allocates and links a context.
  580. //
  581. // Arguments: Credential - Credential to hang this context off of
  582. // ContextFlags - Flags for the context
  583. // LogonId = LogonId of the creating logon session
  584. // NewContext - receives referenced context pointer,
  585. // ContextLifetime - Lifetime for the context.
  586. //
  587. // Requires:
  588. //
  589. // Returns: NTSTATUS code
  590. //
  591. // Notes:
  592. //
  593. //
  594. //--------------------------------------------------------------------------
  595. NTSTATUS
  596. KerbCreateEmptyContext(
  597. IN PKERB_CREDENTIAL Credential,
  598. IN ULONG ContextFlags,
  599. IN ULONG ContextAttributes,
  600. IN ULONG NegotitationInfo,
  601. IN PLUID LogonId,
  602. OUT PKERB_CONTEXT * NewContext,
  603. OUT PTimeStamp ContextLifetime
  604. )
  605. {
  606. NTSTATUS Status;
  607. PKERB_CONTEXT Context = NULL;
  608. Status = KerbAllocateContext( &Context, FALSE );
  609. if (!NT_SUCCESS(Status))
  610. {
  611. goto Cleanup;
  612. }
  613. Context->CredentialHandle = KerbGetCredentialHandle(Credential);
  614. Context->ContextFlags = ContextFlags;
  615. Context->ContextAttributes = ContextAttributes;
  616. Context->Lifetime = KerbGlobalWillNeverTime;
  617. Context->CredManCredentials = NULL;
  618. Context->NegotiationInfo = NegotitationInfo;
  619. GetSystemTimeAsFileTime((PFILETIME)
  620. &(Context->StartTime)
  621. );
  622. Context->LogonId = *LogonId;
  623. *ContextLifetime = Context->Lifetime;
  624. Status = KerbInsertContext(
  625. Context
  626. );
  627. if (!NT_SUCCESS(Status))
  628. {
  629. D_DebugLog((DEB_ERROR,"Failed to insert context: 0x%x. %ws, line %d\n",Status, THIS_FILE, __LINE__));
  630. goto Cleanup;
  631. }
  632. *NewContext = Context;
  633. Cleanup:
  634. if (!NT_SUCCESS(Status))
  635. {
  636. if (Context != NULL)
  637. {
  638. KerbFreeContext(Context);
  639. }
  640. }
  641. return(Status);
  642. }
  643. //+-------------------------------------------------------------------------
  644. //
  645. // Function: KerbCreateClientContext
  646. //
  647. // Synopsis: Creates a context for the client of an authentication
  648. // session.
  649. //
  650. // Effects: Allocates and links a context.
  651. //
  652. // Arguments: LogonSession - Logon session to lock when accessing the credential
  653. // Credential - Credential to hang this context off of
  654. // TicketCacheEntry - Ticket around which to build this context
  655. // TargetName - target name supplied by client.
  656. // Nonce - Nonce used in AP request
  657. // SubSessionKey - subsession key to use, if present
  658. // ContextFlags - Flags passed in by client for authentication
  659. // options.
  660. // NewContext - receives referenced context pointer,
  661. // ContextLifetime - Lifetime for the context.
  662. //
  663. // Requires:
  664. //
  665. // Returns: NTSTATUS code
  666. //
  667. // Notes:
  668. //
  669. //
  670. //--------------------------------------------------------------------------
  671. NTSTATUS
  672. KerbCreateClientContext(
  673. IN PKERB_LOGON_SESSION LogonSession,
  674. IN PKERB_CREDENTIAL Credential,
  675. IN OPTIONAL PKERB_CREDMAN_CRED CredManCredentials,
  676. IN OPTIONAL PKERB_TICKET_CACHE_ENTRY TicketCacheEntry,
  677. IN OPTIONAL PUNICODE_STRING TargetName,
  678. IN ULONG Nonce,
  679. IN PTimeStamp pAuthenticatorTime,
  680. IN ULONG ContextFlags,
  681. IN ULONG ContextAttributes,
  682. IN OPTIONAL PKERB_ENCRYPTION_KEY SubSessionKey,
  683. OUT PKERB_CONTEXT * NewContext,
  684. OUT PTimeStamp ContextLifetime
  685. )
  686. {
  687. NTSTATUS Status;
  688. PKERB_CONTEXT Context = NULL;
  689. Status = KerbAllocateContext( &Context, FALSE );
  690. if (!NT_SUCCESS(Status))
  691. {
  692. goto Cleanup;
  693. }
  694. if (ARGUMENT_PRESENT(TicketCacheEntry))
  695. {
  696. //
  697. // If we are doing datagram, reference the cache entry and
  698. // store a pointer to it in the context. The ticket cache cannot be
  699. // read locked at this point because the call to acquire a write
  700. // lock will block.
  701. //
  702. if ((ContextFlags & ISC_RET_DATAGRAM) != 0)
  703. {
  704. KerbReferenceTicketCacheEntry(TicketCacheEntry);
  705. Context->TicketCacheEntry = TicketCacheEntry;
  706. }
  707. KerbReadLockTicketCache();
  708. //
  709. // Duplicate the session key into the context
  710. //
  711. if (ARGUMENT_PRESENT(SubSessionKey) && (SubSessionKey->keyvalue.value != NULL))
  712. {
  713. if (!KERB_SUCCESS(KerbDuplicateKey(
  714. &Context->SessionKey,
  715. SubSessionKey
  716. )))
  717. {
  718. KerbUnlockTicketCache();
  719. Status = STATUS_INSUFFICIENT_RESOURCES;
  720. goto Cleanup;
  721. }
  722. }
  723. else
  724. {
  725. //
  726. // For datagram, create a key
  727. //
  728. if ((ContextFlags & ISC_RET_DATAGRAM) != 0)
  729. {
  730. KERBERR KerbErr;
  731. SECPKG_CALL_INFO CallInfo;
  732. if (!LsaFunctions->GetCallInfo(&CallInfo))
  733. {
  734. D_DebugLog((DEB_ERROR,"Failed to get client info: 0x%x. %ws, line %d\n",Status, THIS_FILE, __LINE__));
  735. Status = STATUS_INSUFFICIENT_RESOURCES;
  736. KerbUnlockTicketCache();
  737. goto Cleanup;
  738. }
  739. //
  740. // If we are configured for strong encryption & we have said to
  741. // use it for datagram or this is an inprocess caller, then create
  742. // a strong key.
  743. //
  744. D_DebugLog((DEB_TRACE_CTXT,"Making exportable key for datagram client context\n"));
  745. if ( KerbGlobalUseStrongEncryptionForDatagram ||
  746. (CallInfo.Attributes & SECPKG_CALL_IN_PROC))
  747. {
  748. KerbErr = KerbMakeKey(
  749. TicketCacheEntry->SessionKey.keytype,
  750. &Context->SessionKey
  751. );
  752. }
  753. else
  754. {
  755. KerbErr = KerbMakeExportableKey(
  756. TicketCacheEntry->SessionKey.keytype,
  757. &Context->SessionKey
  758. );
  759. }
  760. if (!KERB_SUCCESS(KerbErr))
  761. {
  762. Status = KerbMapKerbError(KerbErr);
  763. KerbUnlockTicketCache();
  764. goto Cleanup;
  765. }
  766. }
  767. else
  768. {
  769. if (!KERB_SUCCESS(KerbDuplicateKey(
  770. &Context->SessionKey,
  771. &TicketCacheEntry->SessionKey
  772. )))
  773. {
  774. KerbUnlockTicketCache();
  775. Status = STATUS_INSUFFICIENT_RESOURCES;
  776. goto Cleanup;
  777. }
  778. }
  779. }
  780. if (!KERB_SUCCESS(KerbDuplicateKey(
  781. &Context->TicketKey,
  782. &TicketCacheEntry->SessionKey
  783. )))
  784. {
  785. KerbUnlockTicketCache();
  786. Status = STATUS_INSUFFICIENT_RESOURCES;
  787. goto Cleanup;
  788. }
  789. //
  790. // Get the client's realm
  791. //
  792. Status = KerbDuplicateString(
  793. &Context->ClientRealm,
  794. &TicketCacheEntry->DomainName);
  795. if (!NT_SUCCESS(Status))
  796. {
  797. KerbUnlockTicketCache();
  798. goto Cleanup;
  799. }
  800. //
  801. // Get the client's name.
  802. //
  803. if (!KERB_SUCCESS(KerbConvertKdcNameToString(
  804. &Context->ClientName,
  805. TicketCacheEntry->ClientName,
  806. NULL)))
  807. {
  808. Status = STATUS_INSUFFICIENT_RESOURCES;
  809. KerbUnlockTicketCache();
  810. goto Cleanup;
  811. }
  812. Context->Lifetime = TicketCacheEntry->EndTime;
  813. Context->StartTime = TicketCacheEntry->StartTime;
  814. Context->RenewTime = TicketCacheEntry->RenewUntil;
  815. Context->EncryptionType = TicketCacheEntry->Ticket.encrypted_part.encryption_type;
  816. KerbUnlockTicketCache();
  817. }
  818. else
  819. {
  820. Context->Lifetime = KerbGlobalWillNeverTime;
  821. Context->RenewTime = KerbGlobalWillNeverTime;
  822. GetSystemTimeAsFileTime((PFILETIME)
  823. &(Context->StartTime)
  824. );
  825. Context->EncryptionType = KERB_ETYPE_NULL;
  826. }
  827. Context->Nonce = Nonce;
  828. Context->AuthenticatorTime = *pAuthenticatorTime;
  829. //
  830. // For now, until the server sends us a separate nonce, use the one
  831. // we generated for receiving data
  832. //
  833. Context->ReceiveNonce = Nonce;
  834. Context->CredentialHandle = KerbGetCredentialHandle(Credential);
  835. //KerbReadLockLogonSessions(LogonSession); // FESTER: Needed??
  836. if (ARGUMENT_PRESENT(CredManCredentials))
  837. {
  838. Context->ContextAttributes |= KERB_CONTEXT_USING_CREDMAN;
  839. Context->CredManCredentials = CredManCredentials; // don't ref, as we don't use it..
  840. }
  841. else if ((Credential->SuppliedCredentials != NULL))
  842. {
  843. Context->ContextAttributes |= KERB_CONTEXT_USED_SUPPLIED_CREDS;
  844. }
  845. //KerbUnlockLogonSessions(LogonSession);
  846. Context->ContextFlags = ContextFlags;
  847. Context->ContextAttributes = KERB_CONTEXT_OUTBOUND | ContextAttributes;
  848. //
  849. // if the caller supplied a target name, stash it in the context
  850. //
  851. if (ARGUMENT_PRESENT(TargetName))
  852. {
  853. Status = KerbDuplicateString(
  854. &Context->ServerPrincipalName,
  855. TargetName
  856. );
  857. if (!NT_SUCCESS(Status))
  858. {
  859. goto Cleanup;
  860. }
  861. }
  862. *ContextLifetime = Context->Lifetime;
  863. Status = KerbInsertContext(
  864. Context
  865. );
  866. if (!NT_SUCCESS(Status))
  867. {
  868. D_DebugLog((DEB_ERROR,"Failed to insert context: 0x%x. %ws, line %d\n",Status, THIS_FILE, __LINE__));
  869. goto Cleanup;
  870. }
  871. *NewContext = Context;
  872. Cleanup:
  873. if (!NT_SUCCESS(Status))
  874. {
  875. if (Context != NULL)
  876. {
  877. KerbFreeContext(Context);
  878. }
  879. }
  880. return(Status);
  881. }
  882. //+-------------------------------------------------------------------------
  883. //
  884. // Function: KerbUpdateServerContext
  885. //
  886. // Synopsis: Creates a context for the server of an authentication
  887. // session.
  888. //
  889. // Effects: Allocates and links a context.
  890. //
  891. // Arguments: Context - Context to update
  892. // InternalTicket - Ticket used to create this context.
  893. // SessionKey - Session key from the ticket.
  894. // LogonId - Logon ID of the context
  895. // UserSid - User's sid, held onto by context
  896. // ContextFlags - SSPI Flags for this context
  897. // ContextAttributes - Internal attributes of context
  898. // TokenHandle - Handle the token for this context
  899. // ContextLifetime - Lifetime for the context.
  900. //
  901. // Requires:
  902. //
  903. // Returns: NTSTATUS code
  904. //
  905. // Notes:
  906. //
  907. //
  908. //--------------------------------------------------------------------------
  909. NTSTATUS
  910. KerbUpdateServerContext(
  911. IN PKERB_CONTEXT Context,
  912. IN PKERB_ENCRYPTED_TICKET InternalTicket,
  913. IN PKERB_AP_REQUEST ApRequest,
  914. IN PKERB_ENCRYPTION_KEY SessionKey,
  915. IN PLUID LogonId,
  916. IN PSID * UserSid,
  917. IN ULONG ContextFlags,
  918. IN ULONG ContextAttributes,
  919. IN ULONG NegotiationInfo,
  920. IN ULONG Nonce,
  921. IN ULONG ReceiveNonce,
  922. IN OUT PHANDLE TokenHandle,
  923. IN PUNICODE_STRING ClientName,
  924. IN PUNICODE_STRING ClientDomain,
  925. IN PUNICODE_STRING ClientNetbiosDomain,
  926. OUT PTimeStamp ContextLifetime
  927. )
  928. {
  929. NTSTATUS Status = STATUS_SUCCESS;
  930. KerbWriteLockContexts();
  931. if (!KERB_SUCCESS(KerbDuplicateKey(
  932. &Context->SessionKey,
  933. SessionKey
  934. )))
  935. {
  936. Status = STATUS_INSUFFICIENT_RESOURCES;
  937. goto Cleanup;
  938. }
  939. //
  940. // If this was not a null session and there is a ticket available,
  941. // pull interesting information out of the ticket
  942. //
  943. if (ARGUMENT_PRESENT(InternalTicket))
  944. {
  945. KerbConvertGeneralizedTimeToLargeInt(
  946. &Context->Lifetime,
  947. &InternalTicket->endtime,
  948. 0
  949. );
  950. if (InternalTicket->bit_mask & KERB_ENCRYPTED_TICKET_renew_until_present)
  951. {
  952. KerbConvertGeneralizedTimeToLargeInt(
  953. &Context->RenewTime,
  954. &InternalTicket->KERB_ENCRYPTED_TICKET_renew_until,
  955. 0
  956. );
  957. }
  958. //
  959. // Stick the client name in the context
  960. //
  961. Context->ClientName = *ClientName;
  962. RtlInitUnicodeString(
  963. ClientName,
  964. NULL
  965. );
  966. Context->ClientRealm = *ClientNetbiosDomain;
  967. RtlInitUnicodeString(
  968. ClientNetbiosDomain,
  969. NULL
  970. );
  971. Context->ClientDnsRealm = *ClientDomain;
  972. RtlInitUnicodeString(
  973. ClientDomain,
  974. NULL
  975. );
  976. if (!KERB_SUCCESS(KerbDuplicateKey(
  977. &Context->TicketKey,
  978. &InternalTicket->key)))
  979. {
  980. Status = STATUS_INSUFFICIENT_RESOURCES;
  981. goto Cleanup;
  982. }
  983. //
  984. // Copy the principal names from the ticket
  985. //
  986. if (!KERB_SUCCESS(KerbConvertPrincipalNameToFullServiceString(
  987. &Context->ClientPrincipalName,
  988. &InternalTicket->client_name,
  989. InternalTicket->client_realm
  990. )))
  991. {
  992. Status = STATUS_INSUFFICIENT_RESOURCES;
  993. goto Cleanup;
  994. }
  995. if (!KERB_SUCCESS(KerbConvertPrincipalNameToFullServiceString(
  996. &Context->ServerPrincipalName,
  997. &ApRequest->ticket.server_name,
  998. ApRequest->ticket.realm
  999. )))
  1000. {
  1001. Status = STATUS_INSUFFICIENT_RESOURCES;
  1002. goto Cleanup;
  1003. }
  1004. }
  1005. else
  1006. {
  1007. Context->Lifetime = KerbGlobalWillNeverTime;
  1008. Context->RenewTime = KerbGlobalWillNeverTime;
  1009. Context->EncryptionType = KERB_ETYPE_NULL;
  1010. }
  1011. //
  1012. // If we generated a nonce to send to the client, use it. Otherwise use
  1013. // the receive nonce from the AP req.
  1014. //
  1015. if (Nonce != 0)
  1016. {
  1017. Context->Nonce = Nonce;
  1018. }
  1019. else
  1020. {
  1021. Context->Nonce = ReceiveNonce;
  1022. }
  1023. Context->ReceiveNonce = ReceiveNonce;
  1024. Context->LogonId = *LogonId;
  1025. Context->ContextFlags |= ContextFlags;
  1026. Context->TokenHandle = *TokenHandle;
  1027. Context->UserSid = *UserSid;
  1028. //
  1029. // Noted we wipe out the previous ContextAttributes here, not sure why
  1030. //
  1031. D_DebugLog((DEB_TRACE, "KerbUpdateServerContext ContextAttributes was %#x, now %#x\n", Context->ContextAttributes, ContextAttributes | KERB_CONTEXT_INBOUND));
  1032. Context->ContextAttributes = KERB_CONTEXT_INBOUND;
  1033. Context->ContextAttributes |= ContextAttributes;
  1034. Context->NegotiationInfo = NegotiationInfo;
  1035. *ContextLifetime = Context->Lifetime;
  1036. //
  1037. // Null the token handle so the caller does not free it
  1038. //
  1039. *TokenHandle = NULL;
  1040. *UserSid = NULL;
  1041. Cleanup:
  1042. KerbUnlockContexts();
  1043. return (Status);
  1044. }
  1045. //+-------------------------------------------------------------------------
  1046. //
  1047. // Function: KerbCreateServerContext
  1048. //
  1049. // Synopsis: Creates a context for the server of an authentication
  1050. // session.
  1051. //
  1052. // Effects: Allocates and links a context.
  1053. //
  1054. // Arguments: LogonSession - Logon session to lock when accessing the credential
  1055. // Credential - Credential to hang this context off of
  1056. // InternalTicket - Ticket used to create this context.
  1057. // SessionKey - Session key from the ticket.
  1058. // LogonId - Logon ID of the context
  1059. // UserSid - User's SID, held on to in context.
  1060. // ContextFlags - SSPI Flags for this context
  1061. // ContextAttributes - Internal attributes of context
  1062. // TokenHandle - Handle the token for this context
  1063. // NewContext - receives referenced context pointer
  1064. // ContextLifetime - Lifetime for the context.
  1065. //
  1066. // Requires:
  1067. //
  1068. // Returns: NTSTATUS code
  1069. //
  1070. // Notes:
  1071. //
  1072. //
  1073. //--------------------------------------------------------------------------
  1074. NTSTATUS
  1075. KerbCreateServerContext(
  1076. IN PKERB_LOGON_SESSION LogonSession,
  1077. IN PKERB_CREDENTIAL Credential,
  1078. IN OPTIONAL PKERB_ENCRYPTED_TICKET InternalTicket,
  1079. IN PKERB_AP_REQUEST ApRequest,
  1080. IN PKERB_ENCRYPTION_KEY SessionKey,
  1081. IN PLUID LogonId,
  1082. IN PSID * UserSid,
  1083. IN ULONG ContextFlags,
  1084. IN ULONG ContextAttributes,
  1085. IN ULONG NegotiationInfo,
  1086. IN ULONG Nonce,
  1087. IN ULONG ReceiveNonce,
  1088. IN OUT PHANDLE TokenHandle,
  1089. IN PUNICODE_STRING ClientName,
  1090. IN PUNICODE_STRING ClientDomain,
  1091. IN PUNICODE_STRING ClientNetbiosDomain,
  1092. OUT PKERB_CONTEXT * NewContext,
  1093. OUT PTimeStamp ContextLifetime
  1094. )
  1095. {
  1096. NTSTATUS Status;
  1097. PKERB_CONTEXT Context = NULL;
  1098. Status = KerbAllocateContext( &Context, FALSE );
  1099. if (!NT_SUCCESS(Status))
  1100. {
  1101. goto Cleanup;
  1102. }
  1103. if (!KERB_SUCCESS(KerbDuplicateKey(
  1104. &Context->SessionKey,
  1105. SessionKey
  1106. )))
  1107. {
  1108. Status = STATUS_INSUFFICIENT_RESOURCES;
  1109. goto Cleanup;
  1110. }
  1111. //
  1112. // If this wasn't a null session, stick the info from the ticket into
  1113. // the context.
  1114. //
  1115. if (ARGUMENT_PRESENT(InternalTicket))
  1116. {
  1117. KerbConvertGeneralizedTimeToLargeInt(
  1118. &Context->Lifetime,
  1119. &InternalTicket->endtime,
  1120. 0
  1121. );
  1122. if (InternalTicket->bit_mask & KERB_ENCRYPTED_TICKET_renew_until_present)
  1123. {
  1124. KerbConvertGeneralizedTimeToLargeInt(
  1125. &Context->RenewTime,
  1126. &InternalTicket->KERB_ENCRYPTED_TICKET_renew_until,
  1127. 0
  1128. );
  1129. }
  1130. if (InternalTicket->bit_mask & KERB_ENCRYPTED_TICKET_starttime_present)
  1131. {
  1132. KerbConvertGeneralizedTimeToLargeInt(
  1133. &Context->StartTime,
  1134. &InternalTicket->starttime,
  1135. 0
  1136. );
  1137. }
  1138. else // use current time
  1139. {
  1140. GetSystemTimeAsFileTime((PFILETIME)
  1141. &(Context->StartTime)
  1142. );
  1143. }
  1144. Context->ClientName = *ClientName;
  1145. RtlInitUnicodeString(
  1146. ClientName,
  1147. NULL
  1148. );
  1149. Context->ClientRealm = *ClientNetbiosDomain;
  1150. RtlInitUnicodeString(
  1151. ClientNetbiosDomain,
  1152. NULL
  1153. );
  1154. Context->ClientDnsRealm = *ClientDomain;
  1155. RtlInitUnicodeString(
  1156. ClientDomain,
  1157. NULL
  1158. );
  1159. if (!KERB_SUCCESS(KerbDuplicateKey(
  1160. &Context->TicketKey,
  1161. &InternalTicket->key)))
  1162. {
  1163. Status = STATUS_INSUFFICIENT_RESOURCES;
  1164. goto Cleanup;
  1165. }
  1166. //
  1167. // Copy the principal names from the ticket
  1168. //
  1169. if (!KERB_SUCCESS(KerbConvertPrincipalNameToFullServiceString(
  1170. &Context->ClientPrincipalName,
  1171. &InternalTicket->client_name,
  1172. InternalTicket->client_realm
  1173. )))
  1174. {
  1175. Status = STATUS_INSUFFICIENT_RESOURCES;
  1176. goto Cleanup;
  1177. }
  1178. if (!KERB_SUCCESS(KerbConvertPrincipalNameToFullServiceString(
  1179. &Context->ServerPrincipalName,
  1180. &ApRequest->ticket.server_name,
  1181. ApRequest->ticket.realm
  1182. )))
  1183. {
  1184. Status = STATUS_INSUFFICIENT_RESOURCES;
  1185. goto Cleanup;
  1186. }
  1187. }
  1188. else
  1189. {
  1190. Context->Lifetime = KerbGlobalWillNeverTime;
  1191. Context->RenewTime = KerbGlobalWillNeverTime;
  1192. GetSystemTimeAsFileTime((PFILETIME)
  1193. &(Context->StartTime)
  1194. );
  1195. Context->EncryptionType = KERB_ETYPE_NULL;
  1196. }
  1197. //
  1198. // If we generated a nonce to send to the client, use it. Otherwise use
  1199. // the receive nonce from the AP req.
  1200. //
  1201. // if (Nonce != 0)
  1202. // {
  1203. Context->Nonce = Nonce;
  1204. // }
  1205. // else
  1206. // {
  1207. // Context->Nonce = ReceiveNonce;
  1208. // }
  1209. Context->ReceiveNonce = ReceiveNonce;
  1210. Context->CredentialHandle = KerbGetCredentialHandle(Credential);
  1211. Context->LogonId = *LogonId;
  1212. Context->ContextFlags = ContextFlags;
  1213. Context->TokenHandle = *TokenHandle;
  1214. Context->UserSid = *UserSid;
  1215. Context->NegotiationInfo = NegotiationInfo;
  1216. //
  1217. // Null the token handle so the caller does not free it
  1218. //
  1219. *TokenHandle = NULL;
  1220. *UserSid = NULL;
  1221. Context->ContextAttributes = KERB_CONTEXT_INBOUND;
  1222. Context->ContextAttributes |= ContextAttributes;
  1223. KerbReadLockLogonSessions(LogonSession);
  1224. if (Credential->SuppliedCredentials != NULL)
  1225. {
  1226. Context->ContextAttributes |= KERB_CONTEXT_USED_SUPPLIED_CREDS;
  1227. }
  1228. KerbUnlockLogonSessions(LogonSession);
  1229. *ContextLifetime = Context->Lifetime;
  1230. Status = KerbInsertContext(
  1231. Context
  1232. );
  1233. if (!NT_SUCCESS(Status))
  1234. {
  1235. D_DebugLog((DEB_ERROR,"Failed to insert context: 0x%x. %ws, line %d\n",Status, THIS_FILE, __LINE__));
  1236. goto Cleanup;
  1237. }
  1238. *NewContext = Context;
  1239. Cleanup:
  1240. if (!NT_SUCCESS(Status))
  1241. {
  1242. if (Context != NULL)
  1243. {
  1244. KerbFreeContext(Context);
  1245. }
  1246. }
  1247. return(Status);
  1248. }
  1249. //+-------------------------------------------------------------------------
  1250. //
  1251. // Function: KerbMapContext
  1252. //
  1253. // Synopsis: Maps a context to the caller's address space
  1254. //
  1255. // Effects:
  1256. //
  1257. // Arguments: Context - The context to map
  1258. // CopyToken - If TRUE, duplicate token to client
  1259. // MappedContext - Set to TRUE on success
  1260. // ContextData - Receives a buffer in the LSA's address space
  1261. // with the mapped context.
  1262. //
  1263. // Requires:
  1264. //
  1265. // Returns:
  1266. //
  1267. // Notes:
  1268. //
  1269. //
  1270. //--------------------------------------------------------------------------
  1271. NTSTATUS
  1272. KerbMapContext(
  1273. IN PKERB_CONTEXT Context,
  1274. OUT PBOOLEAN MappedContext,
  1275. OUT PSecBuffer ContextData
  1276. )
  1277. {
  1278. NTSTATUS Status ;
  1279. PKERB_PACKED_CONTEXT PackedContext = NULL ;
  1280. ULONG ContextSize ;
  1281. PUCHAR CopyTo ;
  1282. ULONG CurrentOffset ;
  1283. KerbWriteLockContexts();
  1284. //
  1285. // If we already mapped the context don't try to do it again. We may
  1286. // be able to map user-mode contexts multiple times, though.
  1287. //
  1288. if (KerberosState == KerberosLsaMode)
  1289. {
  1290. if ((Context->ContextAttributes & KERB_CONTEXT_MAPPED) != 0)
  1291. {
  1292. KerbUnlockContexts();
  1293. Status = STATUS_SUCCESS;
  1294. goto Cleanup;
  1295. }
  1296. Context->ContextAttributes |= KERB_CONTEXT_MAPPED;
  1297. }
  1298. ContextSize = sizeof(KERB_PACKED_CONTEXT) +
  1299. ROUND_UP_COUNT(Context->ClientName.Length, ALIGN_LPDWORD) +
  1300. ROUND_UP_COUNT(Context->ClientRealm.Length, ALIGN_LPDWORD) +
  1301. ROUND_UP_COUNT(Context->SessionKey.keyvalue.length, ALIGN_LPDWORD) +
  1302. ROUND_UP_COUNT(Context->cbMarshalledTargetInfo, ALIGN_LPDWORD) ;
  1303. PackedContext = (PKERB_PACKED_CONTEXT) KerbAllocate( ContextSize );
  1304. if (PackedContext == NULL)
  1305. {
  1306. Context->ContextAttributes &= ~(KERB_CONTEXT_MAPPED);
  1307. KerbUnlockContexts();
  1308. Status = STATUS_INSUFFICIENT_RESOURCES;
  1309. goto Cleanup;
  1310. }
  1311. CurrentOffset = sizeof( KERB_PACKED_CONTEXT );
  1312. CopyTo = (PUCHAR) ( PackedContext + 1 );
  1313. PackedContext->ContextType = KERB_PACKED_CONTEXT_MAP ;
  1314. PackedContext->Pad = 0 ;
  1315. PackedContext->Lifetime = Context->Lifetime ;
  1316. PackedContext->RenewTime = Context->RenewTime ;
  1317. PackedContext->StartTime = Context->StartTime;
  1318. PackedContext->ClientName.Length = Context->ClientName.Length ;
  1319. PackedContext->ClientName.MaximumLength = Context->ClientName.Length ;
  1320. PackedContext->ClientName.Buffer = CurrentOffset ;
  1321. RtlCopyMemory(
  1322. CopyTo,
  1323. Context->ClientName.Buffer,
  1324. Context->ClientName.Length );
  1325. CurrentOffset += ROUND_UP_COUNT(Context->ClientName.Length, ALIGN_LPDWORD) ;
  1326. CopyTo += ROUND_UP_COUNT(Context->ClientName.Length, ALIGN_LPDWORD) ;
  1327. PackedContext->ClientRealm.Length = Context->ClientRealm.Length ;
  1328. PackedContext->ClientRealm.MaximumLength = Context->ClientRealm.Length ;
  1329. PackedContext->ClientRealm.Buffer = CurrentOffset ;
  1330. RtlCopyMemory(
  1331. CopyTo,
  1332. Context->ClientRealm.Buffer,
  1333. Context->ClientRealm.Length );
  1334. CurrentOffset += ROUND_UP_COUNT(Context->ClientRealm.Length, ALIGN_LPDWORD);
  1335. CopyTo += ROUND_UP_COUNT(Context->ClientRealm.Length, ALIGN_LPDWORD) ;
  1336. PackedContext->LsaContextHandle = (ULONG) Context->LsaContextHandle ;
  1337. PackedContext->LogonId = Context->LogonId ;
  1338. PackedContext->CredentialHandle = 0 ;
  1339. PackedContext->SessionKeyType = Context->SessionKey.keytype ;
  1340. PackedContext->SessionKeyOffset = CurrentOffset ;
  1341. PackedContext->SessionKeyLength = Context->SessionKey.keyvalue.length ;
  1342. RtlCopyMemory(
  1343. CopyTo,
  1344. Context->SessionKey.keyvalue.value,
  1345. Context->SessionKey.keyvalue.length );
  1346. CurrentOffset += ROUND_UP_COUNT(PackedContext->SessionKeyLength, ALIGN_LPDWORD) ;
  1347. CopyTo += ROUND_UP_COUNT(PackedContext->SessionKeyLength, ALIGN_LPDWORD);
  1348. if( Context->pbMarshalledTargetInfo )
  1349. {
  1350. PackedContext->MarshalledTargetInfo = CurrentOffset;
  1351. PackedContext->MarshalledTargetInfoLength = Context->cbMarshalledTargetInfo;
  1352. RtlCopyMemory(
  1353. CopyTo,
  1354. Context->pbMarshalledTargetInfo,
  1355. Context->cbMarshalledTargetInfo );
  1356. CurrentOffset += ROUND_UP_COUNT(PackedContext->MarshalledTargetInfoLength, ALIGN_LPDWORD);
  1357. CopyTo += ROUND_UP_COUNT(PackedContext->MarshalledTargetInfoLength, ALIGN_LPDWORD);
  1358. }
  1359. PackedContext->Nonce = Context->Nonce ;
  1360. PackedContext->ReceiveNonce = Context->ReceiveNonce ;
  1361. PackedContext->ContextFlags = Context->ContextFlags ;
  1362. PackedContext->ContextAttributes = Context->ContextAttributes ;
  1363. PackedContext->EncryptionType = Context->EncryptionType ;
  1364. KerbUnlockContexts();
  1365. //
  1366. // If there is a token in the context, copy it also
  1367. //
  1368. #ifndef WIN32_CHICAGO
  1369. if ((KerberosState == KerberosLsaMode) && (Context->TokenHandle != NULL))
  1370. {
  1371. HANDLE duplicateHandle;
  1372. Status = LsaFunctions->DuplicateHandle(
  1373. Context->TokenHandle,
  1374. &duplicateHandle
  1375. );
  1376. if (!NT_SUCCESS(Status))
  1377. {
  1378. D_DebugLog((DEB_ERROR,"Failed to duplicate handle: 0x%x. %ws, line %d\n",Status, THIS_FILE, __LINE__));
  1379. goto Cleanup;
  1380. }
  1381. PackedContext->TokenHandle = HandleToUlong(duplicateHandle);
  1382. NtClose(Context->TokenHandle);
  1383. Context->TokenHandle = NULL;
  1384. }
  1385. else
  1386. {
  1387. PackedContext->TokenHandle = NULL;
  1388. }
  1389. #endif // WIN32_CHICAGO
  1390. ContextData->pvBuffer = PackedContext;
  1391. ContextData->cbBuffer = ContextSize;
  1392. *MappedContext = TRUE;
  1393. Status = STATUS_SUCCESS;
  1394. Cleanup:
  1395. if (!NT_SUCCESS(Status))
  1396. {
  1397. if (PackedContext != NULL)
  1398. {
  1399. KerbFree(PackedContext);
  1400. }
  1401. }
  1402. return(Status);
  1403. }
  1404. #if 0
  1405. NTSTATUS
  1406. KerbMapContext(
  1407. IN PKERB_CONTEXT Context,
  1408. OUT PBOOLEAN MappedContext,
  1409. OUT PSecBuffer ContextData
  1410. )
  1411. {
  1412. NTSTATUS Status;
  1413. PKERB_CONTEXT PackedContext = NULL;
  1414. ULONG ContextSize;
  1415. KerbWriteLockContexts();
  1416. //
  1417. // If we already mapped the context don't try to do it again. We may
  1418. // be able to map user-mode contexts multiple times, though.
  1419. //
  1420. if (KerberosState == KerberosLsaMode)
  1421. {
  1422. if ((Context->ContextAttributes & KERB_CONTEXT_MAPPED) != 0)
  1423. {
  1424. KerbUnlockContexts();
  1425. Status = STATUS_SUCCESS;
  1426. goto Cleanup;
  1427. }
  1428. Context->ContextAttributes |= KERB_CONTEXT_MAPPED;
  1429. }
  1430. ContextSize = sizeof(KERB_CONTEXT) +
  1431. Context->ClientName.Length +
  1432. Context->ClientRealm.Length +
  1433. Context->SessionKey.keyvalue.length;
  1434. PackedContext = (PKERB_CONTEXT) KerbAllocate(ContextSize);
  1435. if (PackedContext == NULL)
  1436. {
  1437. KerbUnlockContexts();
  1438. Status = STATUS_INSUFFICIENT_RESOURCES;
  1439. goto Cleanup;
  1440. }
  1441. RtlCopyMemory(
  1442. PackedContext,
  1443. Context,
  1444. sizeof(KERB_CONTEXT)
  1445. );
  1446. PackedContext->ClientName.Buffer = (LPWSTR) sizeof(KERB_CONTEXT);
  1447. RtlCopyMemory(
  1448. PackedContext+1,
  1449. Context->ClientName.Buffer,
  1450. Context->ClientName.Length
  1451. );
  1452. PackedContext->ClientName.MaximumLength = PackedContext->ClientName.Length;
  1453. PackedContext->ClientRealm.Buffer = (LPWSTR) (sizeof(KERB_CONTEXT) + PackedContext->ClientName.Length);
  1454. RtlCopyMemory(
  1455. (PUCHAR) PackedContext + (UINT_PTR) PackedContext->ClientRealm.Buffer,
  1456. Context->ClientRealm.Buffer,
  1457. Context->ClientRealm.Length
  1458. );
  1459. PackedContext->ClientRealm.MaximumLength = PackedContext->ClientRealm.Length;
  1460. RtlZeroMemory(
  1461. &PackedContext->TicketKey,
  1462. sizeof(KERB_ENCRYPTION_KEY)
  1463. );
  1464. RtlZeroMemory(
  1465. &PackedContext->ClientPrincipalName,
  1466. sizeof(UNICODE_STRING)
  1467. );
  1468. RtlZeroMemory(
  1469. &PackedContext->ServerPrincipalName,
  1470. sizeof(UNICODE_STRING)
  1471. );
  1472. //
  1473. // Pack in the session key
  1474. //
  1475. PackedContext->SessionKey.keyvalue.value = (PUCHAR) PackedContext->ClientRealm.Buffer + PackedContext->ClientRealm.MaximumLength;
  1476. RtlCopyMemory(
  1477. PackedContext->SessionKey.keyvalue.value + (UINT_PTR) PackedContext,
  1478. Context->SessionKey.keyvalue.value,
  1479. Context->SessionKey.keyvalue.length
  1480. );
  1481. KerbUnlockContexts();
  1482. //
  1483. // If there is a token in the context, copy it also
  1484. //
  1485. #ifndef WIN32_CHICAGO
  1486. if ((KerberosState == KerberosLsaMode) && (Context->TokenHandle != NULL))
  1487. {
  1488. Status = LsaFunctions->DuplicateHandle(
  1489. Context->TokenHandle,
  1490. &PackedContext->TokenHandle
  1491. );
  1492. if (!NT_SUCCESS(Status))
  1493. {
  1494. D_DebugLog((DEB_ERROR,"Failed to duplicate handle: 0x%x. %ws, line %d\n",Status, THIS_FILE, __LINE__));
  1495. goto Cleanup;
  1496. }
  1497. NtClose(Context->TokenHandle);
  1498. Context->TokenHandle = NULL;
  1499. }
  1500. else
  1501. {
  1502. PackedContext->TokenHandle = NULL;
  1503. }
  1504. #endif // WIN32_CHICAGO
  1505. ContextData->pvBuffer = PackedContext;
  1506. ContextData->cbBuffer = ContextSize;
  1507. *MappedContext = TRUE;
  1508. Status = STATUS_SUCCESS;
  1509. Cleanup:
  1510. if (!NT_SUCCESS(Status))
  1511. {
  1512. if (PackedContext != NULL)
  1513. {
  1514. KerbFree(PackedContext);
  1515. }
  1516. }
  1517. return(Status);
  1518. }
  1519. #endif
  1520. #ifndef WIN32_CHICAGO
  1521. //+-------------------------------------------------------------------------
  1522. //
  1523. // Function: KerbGetTokenUser
  1524. //
  1525. // Synopsis: Returns user field from a token
  1526. //
  1527. // Effects: allocates memory with LocalAlloc
  1528. //
  1529. // Arguments:
  1530. //
  1531. // Requires:
  1532. //
  1533. // Returns:
  1534. //
  1535. // Notes:
  1536. //
  1537. //
  1538. //--------------------------------------------------------------------------
  1539. NTSTATUS
  1540. KerbGetTokenUser(
  1541. HANDLE Token,
  1542. PTOKEN_USER * pTokenUser
  1543. )
  1544. {
  1545. PTOKEN_USER LocalTokenUser = NULL;
  1546. NTSTATUS Status;
  1547. ULONG TokenUserSize = 0;
  1548. //
  1549. // Query the token user. First pass in NULL to get back the
  1550. // required size.
  1551. //
  1552. Status = NtQueryInformationToken(
  1553. Token,
  1554. TokenUser,
  1555. NULL,
  1556. 0,
  1557. &TokenUserSize
  1558. );
  1559. if (Status != STATUS_BUFFER_TOO_SMALL)
  1560. {
  1561. DsysAssert(Status != STATUS_SUCCESS);
  1562. return(Status);
  1563. }
  1564. //
  1565. // Now allocate the required ammount of memory and try again.
  1566. //
  1567. LocalTokenUser = (PTOKEN_USER) LocalAlloc(0,TokenUserSize);
  1568. if (LocalTokenUser == NULL)
  1569. {
  1570. return(STATUS_INSUFFICIENT_RESOURCES);
  1571. }
  1572. Status = NtQueryInformationToken(
  1573. Token,
  1574. TokenUser,
  1575. LocalTokenUser,
  1576. TokenUserSize,
  1577. &TokenUserSize
  1578. );
  1579. if (NT_SUCCESS(Status))
  1580. {
  1581. *pTokenUser = LocalTokenUser;
  1582. }
  1583. else
  1584. {
  1585. LocalFree(LocalTokenUser);
  1586. }
  1587. return(Status);
  1588. }
  1589. #endif // WIN32_CHICAGO
  1590. #ifndef WIN32_CHICAGO
  1591. //+-------------------------------------------------------------------------
  1592. //
  1593. // Function: KerbCreateTokenDacl
  1594. //
  1595. // Synopsis: Modifies DACL on the context token to grant access to the
  1596. // the caller.
  1597. //
  1598. // Effects:
  1599. //
  1600. // Arguments: Token - Token to modify
  1601. //
  1602. // Requires:
  1603. //
  1604. // Returns:
  1605. //
  1606. // Notes:
  1607. //
  1608. //
  1609. //--------------------------------------------------------------------------
  1610. NTSTATUS
  1611. KerbCreateTokenDacl(
  1612. HANDLE Token
  1613. )
  1614. {
  1615. NTSTATUS Status;
  1616. PTOKEN_USER ProcessTokenUser = NULL;
  1617. PTOKEN_USER ThreadTokenUser = NULL;
  1618. PTOKEN_USER ImpersonationTokenUser = NULL;
  1619. HANDLE ProcessToken = NULL;
  1620. HANDLE ImpersonationToken = NULL;
  1621. BOOL fInsertImpersonatingUser = FALSE;
  1622. ULONG AclLength;
  1623. PACL NewDacl = NULL;
  1624. SECURITY_DESCRIPTOR SecurityDescriptor;
  1625. //
  1626. // it's possible that the current thread is impersonating a user.
  1627. // if that's the case, get it's token user, and revert to insure we
  1628. // can open the process token.
  1629. //
  1630. Status = NtOpenThreadToken(
  1631. NtCurrentThread(),
  1632. TOKEN_QUERY | TOKEN_IMPERSONATE,
  1633. TRUE,
  1634. &ImpersonationToken
  1635. );
  1636. if( NT_SUCCESS(Status) )
  1637. {
  1638. //
  1639. // stop impersonating.
  1640. //
  1641. RevertToSelf();
  1642. //
  1643. // get the token user for the impersonating user.
  1644. //
  1645. Status = KerbGetTokenUser(
  1646. ImpersonationToken,
  1647. &ImpersonationTokenUser
  1648. );
  1649. if (!NT_SUCCESS(Status))
  1650. {
  1651. goto Cleanup;
  1652. }
  1653. }
  1654. //
  1655. // Open the process token to find out the user sid
  1656. //
  1657. Status = NtOpenProcessToken(
  1658. NtCurrentProcess(),
  1659. TOKEN_QUERY,
  1660. &ProcessToken
  1661. );
  1662. if (!NT_SUCCESS(Status))
  1663. {
  1664. goto Cleanup;
  1665. }
  1666. Status = KerbGetTokenUser(
  1667. ProcessToken,
  1668. &ProcessTokenUser
  1669. );
  1670. if (!NT_SUCCESS(Status))
  1671. {
  1672. goto Cleanup;
  1673. }
  1674. //
  1675. // Now get the token user for the thread.
  1676. //
  1677. Status = KerbGetTokenUser(
  1678. Token,
  1679. &ThreadTokenUser
  1680. );
  1681. if (!NT_SUCCESS(Status))
  1682. {
  1683. goto Cleanup;
  1684. }
  1685. AclLength = 4 * sizeof( ACCESS_ALLOWED_ACE ) - 4 * sizeof( ULONG ) +
  1686. RtlLengthSid( ProcessTokenUser->User.Sid ) +
  1687. RtlLengthSid( ThreadTokenUser->User.Sid ) +
  1688. RtlLengthSid( KerbGlobalLocalSystemSid ) +
  1689. RtlLengthSid( KerbGlobalAliasAdminsSid ) +
  1690. sizeof( ACL );
  1691. //
  1692. // determine if we need to add impersonation token sid onto the token Dacl.
  1693. //
  1694. if( ImpersonationTokenUser &&
  1695. !RtlEqualSid( ImpersonationTokenUser->User.Sid, ProcessTokenUser->User.Sid ) &&
  1696. !RtlEqualSid( ImpersonationTokenUser->User.Sid, ThreadTokenUser->User.Sid )
  1697. )
  1698. {
  1699. AclLength += (sizeof(ACCESS_ALLOWED_ACE) - sizeof( ULONG )) +
  1700. RtlLengthSid( ImpersonationTokenUser->User.Sid );
  1701. fInsertImpersonatingUser = TRUE;
  1702. }
  1703. NewDacl = (PACL) LocalAlloc(0, AclLength );
  1704. if (NewDacl == NULL) {
  1705. Status = STATUS_INSUFFICIENT_RESOURCES;
  1706. goto Cleanup;
  1707. }
  1708. Status = RtlCreateAcl( NewDacl, AclLength, ACL_REVISION2 );
  1709. DsysAssert(NT_SUCCESS( Status ));
  1710. Status = RtlAddAccessAllowedAce (
  1711. NewDacl,
  1712. ACL_REVISION2,
  1713. TOKEN_ALL_ACCESS,
  1714. ProcessTokenUser->User.Sid
  1715. );
  1716. DsysAssert( NT_SUCCESS( Status ));
  1717. Status = RtlAddAccessAllowedAce (
  1718. NewDacl,
  1719. ACL_REVISION2,
  1720. TOKEN_ALL_ACCESS,
  1721. ThreadTokenUser->User.Sid
  1722. );
  1723. DsysAssert( NT_SUCCESS( Status ));
  1724. if( fInsertImpersonatingUser )
  1725. {
  1726. Status = RtlAddAccessAllowedAce (
  1727. NewDacl,
  1728. ACL_REVISION2,
  1729. TOKEN_ALL_ACCESS,
  1730. ImpersonationTokenUser->User.Sid
  1731. );
  1732. DsysAssert( NT_SUCCESS( Status ));
  1733. }
  1734. Status = RtlAddAccessAllowedAce (
  1735. NewDacl,
  1736. ACL_REVISION2,
  1737. TOKEN_ALL_ACCESS,
  1738. KerbGlobalAliasAdminsSid
  1739. );
  1740. DsysAssert( NT_SUCCESS( Status ));
  1741. Status = RtlAddAccessAllowedAce (
  1742. NewDacl,
  1743. ACL_REVISION2,
  1744. TOKEN_ALL_ACCESS,
  1745. KerbGlobalLocalSystemSid
  1746. );
  1747. DsysAssert( NT_SUCCESS( Status ));
  1748. Status = RtlCreateSecurityDescriptor (
  1749. &SecurityDescriptor,
  1750. SECURITY_DESCRIPTOR_REVISION
  1751. );
  1752. DsysAssert( NT_SUCCESS( Status ));
  1753. Status = RtlSetDaclSecurityDescriptor(
  1754. &SecurityDescriptor,
  1755. TRUE,
  1756. NewDacl,
  1757. FALSE
  1758. );
  1759. DsysAssert( NT_SUCCESS( Status ));
  1760. Status = NtSetSecurityObject(
  1761. Token,
  1762. DACL_SECURITY_INFORMATION,
  1763. &SecurityDescriptor
  1764. );
  1765. DsysAssert( NT_SUCCESS( Status ));
  1766. Cleanup:
  1767. if( ImpersonationToken != NULL ) {
  1768. //
  1769. // put the thread token back if we were impersonating.
  1770. //
  1771. SetThreadToken( NULL, ImpersonationToken );
  1772. NtClose( ImpersonationToken );
  1773. }
  1774. if (ThreadTokenUser != NULL) {
  1775. LocalFree( ThreadTokenUser );
  1776. }
  1777. if (ProcessTokenUser != NULL) {
  1778. LocalFree( ProcessTokenUser );
  1779. }
  1780. if (ImpersonationTokenUser != NULL) {
  1781. LocalFree( ImpersonationTokenUser );
  1782. }
  1783. if (NewDacl != NULL) {
  1784. LocalFree( NewDacl );
  1785. }
  1786. if (ProcessToken != NULL)
  1787. {
  1788. NtClose(ProcessToken);
  1789. }
  1790. return( Status );
  1791. }
  1792. #endif // WIN32_CHICAGO
  1793. //+-------------------------------------------------------------------------
  1794. //
  1795. // Function: KerbCreateUserModeContext
  1796. //
  1797. // Synopsis: Creates a user-mode context to support impersonation and
  1798. // message integrity and privacy
  1799. //
  1800. // Effects:
  1801. //
  1802. // Arguments:
  1803. //
  1804. // Requires:
  1805. //
  1806. // Returns:
  1807. //
  1808. // Notes:
  1809. //
  1810. //
  1811. //--------------------------------------------------------------------------
  1812. NTSTATUS
  1813. KerbCreateUserModeContext(
  1814. IN LSA_SEC_HANDLE ContextHandle,
  1815. IN PSecBuffer MarshalledContext,
  1816. OUT PKERB_CONTEXT * NewContext
  1817. )
  1818. {
  1819. NTSTATUS Status;
  1820. PKERB_CONTEXT Context = NULL;
  1821. PKERB_PACKED_CONTEXT PackedContext ;
  1822. UNICODE_STRING String ;
  1823. KERB_ENCRYPTION_KEY Key ;
  1824. if (MarshalledContext->cbBuffer < sizeof(KERB_PACKED_CONTEXT))
  1825. {
  1826. D_DebugLog((DEB_ERROR,"Invalid buffer size for marshalled context: was 0x%x, needed 0x%x. %ws, line %d\n",
  1827. MarshalledContext->cbBuffer, sizeof(KERB_CONTEXT), THIS_FILE, __LINE__));
  1828. return(STATUS_INVALID_PARAMETER);
  1829. }
  1830. PackedContext = (PKERB_PACKED_CONTEXT) MarshalledContext->pvBuffer;
  1831. Status = KerbAllocateContext( &Context, TRUE );
  1832. if (!NT_SUCCESS(Status))
  1833. {
  1834. goto Cleanup;
  1835. }
  1836. Context->Lifetime = PackedContext->Lifetime ;
  1837. Context->RenewTime = PackedContext->RenewTime ;
  1838. Context->StartTime = PackedContext->StartTime;
  1839. String.Length = PackedContext->ClientName.Length ;
  1840. String.MaximumLength = PackedContext->ClientName.MaximumLength ;
  1841. String.Buffer = (PWSTR)((PUCHAR) PackedContext + PackedContext->ClientName.Buffer );
  1842. Status = KerbDuplicateString(
  1843. &Context->ClientName,
  1844. &String );
  1845. if ( !NT_SUCCESS( Status ) )
  1846. {
  1847. goto Cleanup ;
  1848. }
  1849. String.Length = PackedContext->ClientRealm.Length ;
  1850. String.MaximumLength = PackedContext->ClientRealm.MaximumLength ;
  1851. String.Buffer = (PWSTR)((PUCHAR) PackedContext + PackedContext->ClientRealm.Buffer );
  1852. Status = KerbDuplicateString(
  1853. &Context->ClientRealm,
  1854. &String );
  1855. if ( !NT_SUCCESS( Status ) )
  1856. {
  1857. goto Cleanup ;
  1858. }
  1859. Context->LogonId = PackedContext->LogonId ;
  1860. Context->TokenHandle = (HANDLE) ULongToPtr(PackedContext->TokenHandle);
  1861. Context->CredentialHandle = NULL ;
  1862. Context->Nonce = PackedContext->Nonce ;
  1863. Context->ReceiveNonce = PackedContext->ReceiveNonce ;
  1864. Context->ContextFlags = PackedContext->ContextFlags ;
  1865. Context->ContextAttributes = PackedContext->ContextAttributes ;
  1866. Context->EncryptionType = PackedContext->EncryptionType ;
  1867. Key.keytype = PackedContext->SessionKeyType ;
  1868. Key.keyvalue.value = (PUCHAR) ((PUCHAR) PackedContext + PackedContext->SessionKeyOffset );
  1869. Key.keyvalue.length = PackedContext->SessionKeyLength ;
  1870. if (!KERB_SUCCESS(KerbDuplicateKey(
  1871. &Context->SessionKey,
  1872. &Key)))
  1873. {
  1874. Status = STATUS_INSUFFICIENT_RESOURCES;
  1875. goto Cleanup;
  1876. }
  1877. //
  1878. // Null out string buffers that aren't meant to be copied.
  1879. //
  1880. Context->ClientPrincipalName.Buffer = NULL;
  1881. Context->ServerPrincipalName.Buffer = NULL;
  1882. Context->TicketKey.keyvalue.value = NULL;
  1883. Context->UserSid = NULL;
  1884. Context->TicketCacheEntry = NULL;
  1885. //
  1886. // Modify the DACL on the token to grant access to the caller
  1887. //
  1888. #ifndef WIN32_CHICAGO
  1889. if (Context->TokenHandle != NULL)
  1890. {
  1891. Status = KerbCreateTokenDacl(
  1892. Context->TokenHandle
  1893. );
  1894. if (!NT_SUCCESS(Status))
  1895. {
  1896. goto Cleanup;
  1897. }
  1898. }
  1899. #endif // WIN32_CHICAGO
  1900. //
  1901. // We didn't copy the ticket here, so don't store the entry
  1902. //
  1903. Context->TicketCacheEntry = NULL;
  1904. KerbInitializeListEntry(
  1905. &Context->ListEntry
  1906. );
  1907. if ( ContextHandle != 0 )
  1908. {
  1909. Context->LsaContextHandle = ContextHandle;
  1910. } else {
  1911. Context->LsaContextHandle = (ULONG_PTR)Context;
  1912. }
  1913. Context->cbMarshalledTargetInfo = PackedContext->MarshalledTargetInfoLength;
  1914. if (PackedContext->MarshalledTargetInfo)
  1915. {
  1916. Context->pbMarshalledTargetInfo = (PUCHAR) KerbAllocate( Context->cbMarshalledTargetInfo );
  1917. if (Context->pbMarshalledTargetInfo == NULL)
  1918. {
  1919. Status = STATUS_INSUFFICIENT_RESOURCES;
  1920. goto Cleanup;
  1921. }
  1922. RtlCopyMemory(
  1923. Context->pbMarshalledTargetInfo,
  1924. (PUCHAR) PackedContext + PackedContext->MarshalledTargetInfo,
  1925. Context->cbMarshalledTargetInfo
  1926. );
  1927. } else {
  1928. Context->pbMarshalledTargetInfo = NULL;
  1929. }
  1930. Status = KerbInsertContext(
  1931. Context
  1932. );
  1933. if (!NT_SUCCESS(Status))
  1934. {
  1935. D_DebugLog((DEB_ERROR,"Failed to insert context: 0x%x. %ws, line %d\n",Status, THIS_FILE, __LINE__));
  1936. goto Cleanup;
  1937. }
  1938. *NewContext = Context;
  1939. Cleanup:
  1940. if (!NT_SUCCESS(Status))
  1941. {
  1942. if (Context != NULL)
  1943. {
  1944. KerbFreeContext(Context);
  1945. }
  1946. }
  1947. return(Status);
  1948. }
  1949. #if 0
  1950. NTSTATUS
  1951. KerbCreateUserModeContext(
  1952. IN LSA_SEC_HANDLE ContextHandle,
  1953. IN PSecBuffer MarshalledContext,
  1954. OUT PKERB_CONTEXT * NewContext
  1955. )
  1956. {
  1957. NTSTATUS Status;
  1958. PKERB_CONTEXT Context = NULL;
  1959. PKERB_CONTEXT LsaContext;
  1960. if (MarshalledContext->cbBuffer < sizeof(KERB_CONTEXT))
  1961. {
  1962. D_DebugLog((DEB_ERROR,"Invalid buffer size for marshalled context: was 0x%x, needed 0x%x. %ws, line %d\n",
  1963. MarshalledContext->cbBuffer, sizeof(KERB_CONTEXT), THIS_FILE, __LINE__));
  1964. return(STATUS_INVALID_PARAMETER);
  1965. }
  1966. LsaContext = (PKERB_CONTEXT) MarshalledContext->pvBuffer;
  1967. //
  1968. // Normalize the client name.
  1969. //
  1970. LsaContext->ClientName.Buffer = (LPWSTR) ((PUCHAR) LsaContext->ClientName.Buffer + (UINT_PTR) LsaContext);
  1971. LsaContext->ClientRealm.Buffer = (LPWSTR) ((PUCHAR) LsaContext->ClientRealm.Buffer + (UINT_PTR) LsaContext);
  1972. LsaContext->SessionKey.keyvalue.value = (PUCHAR) LsaContext->SessionKey.keyvalue.value + (UINT_PTR) LsaContext;
  1973. Status = KerbAllocateContext( &Context, TRUE );
  1974. if (!NT_SUCCESS(Status))
  1975. {
  1976. goto Cleanup;
  1977. }
  1978. *Context = *LsaContext;
  1979. //
  1980. // Null out string buffers that aren't meant to be copied.
  1981. //
  1982. Context->ClientName.Buffer = NULL;
  1983. Context->ClientRealm.Buffer = NULL;
  1984. Context->SessionKey.keyvalue.value = NULL;
  1985. Context->UserSid = NULL;
  1986. Context->TicketCacheEntry = NULL;
  1987. //
  1988. // Modify the DACL on the token to grant access to the caller
  1989. //
  1990. #ifndef WIN32_CHICAGO
  1991. if (Context->TokenHandle != NULL)
  1992. {
  1993. Status = KerbCreateTokenDacl(
  1994. Context->TokenHandle
  1995. );
  1996. if (!NT_SUCCESS(Status))
  1997. {
  1998. goto Cleanup;
  1999. }
  2000. }
  2001. #endif // WIN32_CHICAGO
  2002. //
  2003. // We didn't copy the ticket here, so don't store the entry
  2004. //
  2005. Context->TicketCacheEntry = NULL;
  2006. KerbInitializeListEntry(
  2007. &Context->ListEntry
  2008. );
  2009. Context->LsaContextHandle = ContextHandle;
  2010. Status = KerbDuplicateString(
  2011. &Context->ClientName,
  2012. &LsaContext->ClientName
  2013. );
  2014. if (!NT_SUCCESS(Status))
  2015. {
  2016. goto Cleanup;
  2017. }
  2018. Status = KerbDuplicateString(
  2019. &Context->ClientRealm,
  2020. &LsaContext->ClientRealm
  2021. );
  2022. if (!NT_SUCCESS(Status))
  2023. {
  2024. goto Cleanup;
  2025. }
  2026. if (!KERB_SUCCESS(KerbDuplicateKey(
  2027. &Context->SessionKey,
  2028. &LsaContext->SessionKey)))
  2029. {
  2030. Status = STATUS_INSUFFICIENT_RESOURCES;
  2031. goto Cleanup;
  2032. }
  2033. Status = KerbInsertContext(
  2034. Context
  2035. );
  2036. if (!NT_SUCCESS(Status))
  2037. {
  2038. D_DebugLog((DEB_ERROR,"Failed to insert context: 0x%x. %ws, line %d\n",Status, THIS_FILE, __LINE__));
  2039. goto Cleanup;
  2040. }
  2041. *NewContext = Context;
  2042. Cleanup:
  2043. if (!NT_SUCCESS(Status))
  2044. {
  2045. if (Context != NULL)
  2046. {
  2047. KerbFreeContext(Context);
  2048. }
  2049. }
  2050. return(Status);
  2051. }
  2052. #endif
  2053. //+-------------------------------------------------------------------------
  2054. //
  2055. // Function: KerbUpdateClientContext
  2056. //
  2057. // Synopsis: updates context with latest info
  2058. //
  2059. // Effects:
  2060. //
  2061. // Arguments:
  2062. //
  2063. // Requires:
  2064. //
  2065. // Returns:
  2066. //
  2067. // Notes:
  2068. //
  2069. //
  2070. //--------------------------------------------------------------------------
  2071. NTSTATUS
  2072. KerbUpdateClientContext(
  2073. IN PKERB_CONTEXT Context,
  2074. IN OPTIONAL PKERB_TICKET_CACHE_ENTRY TicketCacheEntry,
  2075. IN ULONG Nonce,
  2076. IN PTimeStamp pAuthenticatorTime,
  2077. IN ULONG ReceiveNonce,
  2078. IN ULONG ContextFlags,
  2079. IN ULONG ContextAttributes,
  2080. IN OPTIONAL PKERB_ENCRYPTION_KEY SubSessionKey,
  2081. OUT PTimeStamp ContextLifetime
  2082. )
  2083. {
  2084. NTSTATUS Status = STATUS_SUCCESS;
  2085. if (ARGUMENT_PRESENT(TicketCacheEntry))
  2086. {
  2087. KerbReadLockTicketCache();
  2088. }
  2089. KerbWriteLockContexts();
  2090. if (ARGUMENT_PRESENT(TicketCacheEntry))
  2091. {
  2092. //
  2093. // Duplicate the session key into the context
  2094. //
  2095. KerbFreeKey(
  2096. &Context->SessionKey
  2097. );
  2098. if (ARGUMENT_PRESENT(SubSessionKey) && (SubSessionKey->keyvalue.value != NULL))
  2099. {
  2100. if (!KERB_SUCCESS(KerbDuplicateKey(
  2101. &Context->SessionKey,
  2102. SubSessionKey
  2103. )))
  2104. {
  2105. KerbUnlockTicketCache();
  2106. Status = STATUS_INSUFFICIENT_RESOURCES;
  2107. goto Cleanup;
  2108. }
  2109. }
  2110. else
  2111. {
  2112. if (!KERB_SUCCESS(KerbDuplicateKey(
  2113. &Context->SessionKey,
  2114. &TicketCacheEntry->SessionKey
  2115. )))
  2116. {
  2117. KerbUnlockTicketCache();
  2118. Status = STATUS_INSUFFICIENT_RESOURCES;
  2119. goto Cleanup;
  2120. }
  2121. }
  2122. KerbFreeKey(
  2123. &Context->TicketKey
  2124. );
  2125. if (!KERB_SUCCESS(KerbDuplicateKey(
  2126. &Context->TicketKey,
  2127. &TicketCacheEntry->SessionKey
  2128. )))
  2129. {
  2130. KerbUnlockTicketCache();
  2131. Status = STATUS_INSUFFICIENT_RESOURCES;
  2132. goto Cleanup;
  2133. }
  2134. Context->Lifetime = TicketCacheEntry->EndTime;
  2135. Context->RenewTime = TicketCacheEntry->RenewUntil;
  2136. Context->EncryptionType = TicketCacheEntry->Ticket.encrypted_part.encryption_type;
  2137. KerbUnlockTicketCache();
  2138. }
  2139. else
  2140. {
  2141. Context->Lifetime = KerbGlobalWillNeverTime;
  2142. Context->RenewTime = KerbGlobalWillNeverTime;
  2143. Context->EncryptionType = KERB_ETYPE_NULL;
  2144. }
  2145. Context->Nonce = Nonce;
  2146. Context->AuthenticatorTime = *pAuthenticatorTime;
  2147. //
  2148. // If the server sent us a nonce for receiving data, use it. Otherwise use
  2149. // the nonce we generated.
  2150. //
  2151. // if (ReceiveNonce != 0)
  2152. // {
  2153. Context->ReceiveNonce = ReceiveNonce;
  2154. // }
  2155. // else
  2156. // {
  2157. // Context->ReceiveNonce = Nonce;
  2158. // }
  2159. //
  2160. // delegation flags are not additive, turn it off before updating it
  2161. //
  2162. Context->ContextFlags &= ~(ISC_RET_DELEGATE_IF_SAFE | ISC_RET_DELEGATE);
  2163. Context->ContextFlags |= ContextFlags;
  2164. Context->ContextAttributes |= KERB_CONTEXT_OUTBOUND | ContextAttributes;
  2165. *ContextLifetime = Context->Lifetime;
  2166. Cleanup:
  2167. KerbUnlockContexts();
  2168. return(Status);
  2169. }
  2170. //+-------------------------------------------------------------------------
  2171. //
  2172. // Function: KerbCreateSKeyEntry
  2173. //
  2174. // Synopsis: Create a session key entry
  2175. //
  2176. // Effects:
  2177. //
  2178. // Arguments: pSessionKey - session key that is used, mostly SubKey
  2179. // pExpireTime - time that the session key expires
  2180. //
  2181. // Requires: Memory allocator must zero out memory because KerbFreeSKeyEntry
  2182. // relies on that behavior
  2183. //
  2184. // Returns:
  2185. //
  2186. // Notes:
  2187. //
  2188. //
  2189. //--------------------------------------------------------------------------
  2190. NTSTATUS
  2191. KerbCreateSKeyEntry(
  2192. IN KERB_ENCRYPTION_KEY* pSessionKey,
  2193. IN FILETIME* pExpireTime
  2194. )
  2195. {
  2196. NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
  2197. KERB_SESSION_KEY_ENTRY* pSessionKeyEntry = NULL;
  2198. if (!pSessionKey || !pExpireTime)
  2199. {
  2200. return STATUS_INVALID_PARAMETER;
  2201. }
  2202. pSessionKeyEntry = (KERB_SESSION_KEY_ENTRY*) KerbAllocate(sizeof(KERB_SESSION_KEY_ENTRY));
  2203. if (!pSessionKeyEntry)
  2204. {
  2205. return STATUS_NO_MEMORY;
  2206. }
  2207. pSessionKeyEntry->ExpireTime = *pExpireTime;
  2208. InitializeListHead(&pSessionKeyEntry->ListEntry); // so that un-linking always works
  2209. NtStatus = KerbMapKerbError(
  2210. KerbDuplicateKey(
  2211. &pSessionKeyEntry->SessionKey,
  2212. pSessionKey
  2213. ));
  2214. if (NT_SUCCESS(NtStatus))
  2215. {
  2216. if (SafeAcquireResourceExclusive(&KerbSKeyLock, TRUE))
  2217. {
  2218. #if DBG
  2219. ULONG cSKeyEntries = 0;
  2220. if (NT_SUCCESS(NtStatus))
  2221. {
  2222. cSKeyEntries = InterlockedIncrement(&KerbcSKeyEntries);
  2223. }
  2224. DebugLog((DEB_TRACE_LOOPBACK,
  2225. "KerbInsertSKey, status 0x%x, keyexpire %#x:%#x, total %d keys\n",
  2226. NtStatus,
  2227. pSessionKeyEntry->ExpireTime.dwHighDateTime,
  2228. pSessionKeyEntry->ExpireTime.dwLowDateTime,
  2229. cSKeyEntries));
  2230. #endif
  2231. InsertHeadList(&KerbSKeyList, &pSessionKeyEntry->ListEntry);
  2232. pSessionKeyEntry = NULL;
  2233. SafeReleaseResource(&KerbSKeyLock);
  2234. }
  2235. else
  2236. {
  2237. NtStatus = STATUS_UNSUCCESSFUL;
  2238. }
  2239. }
  2240. if (pSessionKeyEntry)
  2241. {
  2242. KerbFreeSKeyEntry(pSessionKeyEntry);
  2243. }
  2244. return NtStatus;
  2245. }
  2246. //+-------------------------------------------------------------------------
  2247. //
  2248. // Function: KerbDoesSKeyExist
  2249. //
  2250. // Synopsis: check whether a session key entry exists the session key list
  2251. //
  2252. // Effects:
  2253. //
  2254. // Arguments: pKey - key to be located
  2255. // pbExist - whether session key entry exists
  2256. //
  2257. // Requires:
  2258. //
  2259. // Returns: If an entry is found, ppSKeyEntry points to the entry
  2260. // that contains pKey hence should be non null
  2261. //
  2262. // Notes:
  2263. //
  2264. //
  2265. //--------------------------------------------------------------------------
  2266. NTSTATUS
  2267. KerbDoesSKeyExist(
  2268. IN KERB_ENCRYPTION_KEY* pKey,
  2269. OUT BOOLEAN* pbExist
  2270. )
  2271. {
  2272. FILETIME CurrentTime = {0};
  2273. NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
  2274. if (!pKey || !pbExist)
  2275. {
  2276. return STATUS_INVALID_PARAMETER;
  2277. }
  2278. *pbExist = FALSE;
  2279. GetSystemTimeAsFileTime(&CurrentTime);
  2280. DebugLog((DEB_TRACE_LOOPBACK, "KerbDoesSKeyExist, curtime %#x:%#x\n", CurrentTime.dwHighDateTime, CurrentTime.dwLowDateTime));
  2281. if (SafeAcquireResourceShared(&KerbSKeyLock, TRUE))
  2282. {
  2283. NtStatus = STATUS_SUCCESS;
  2284. for (LIST_ENTRY* pListEntry = KerbSKeyList.Flink;
  2285. NT_SUCCESS(NtStatus) && pListEntry != &KerbSKeyList;
  2286. pListEntry = pListEntry->Flink)
  2287. {
  2288. KERB_SESSION_KEY_ENTRY* pSKeyEntry = CONTAINING_RECORD(pListEntry, KERB_SESSION_KEY_ENTRY, ListEntry);
  2289. //
  2290. // only keys that have not expired are checked
  2291. //
  2292. if (KerbGetTime(* (TimeStamp*)&pSKeyEntry->ExpireTime) > KerbGetTime(* (TimeStamp*)&CurrentTime))
  2293. {
  2294. BOOLEAN bEqual = FALSE;
  2295. NtStatus = KerbEqualKey(&pSKeyEntry->SessionKey, pKey, &bEqual);
  2296. if (NT_SUCCESS(NtStatus) && bEqual)
  2297. {
  2298. //
  2299. // found it
  2300. //
  2301. DebugLog((DEB_TRACE_LOOPBACK, "KerbDoesSKeyExist, keyexpire %#x:%#x found\n", pSKeyEntry->ExpireTime.dwHighDateTime, pSKeyEntry->ExpireTime.dwLowDateTime));
  2302. *pbExist = TRUE;
  2303. break;
  2304. }
  2305. }
  2306. }
  2307. SafeReleaseResource(&KerbSKeyLock);
  2308. }
  2309. return NtStatus;
  2310. }
  2311. //+-------------------------------------------------------------------------
  2312. //
  2313. // Function: KerbDeleteSKeyEntry
  2314. //
  2315. // Synopsis: remove a session key entry if it exists
  2316. //
  2317. // Effects:
  2318. //
  2319. // Arguments: pKey - key to be delete
  2320. //
  2321. // Requires:
  2322. //
  2323. // Returns: None
  2324. //
  2325. // Notes:
  2326. //
  2327. //
  2328. //--------------------------------------------------------------------------
  2329. VOID
  2330. KerbDeleteSKeyEntry(
  2331. IN OPTIONAL KERB_ENCRYPTION_KEY* pKey
  2332. )
  2333. {
  2334. if (pKey)
  2335. {
  2336. if (SafeAcquireResourceExclusive(&KerbSKeyLock, TRUE))
  2337. {
  2338. NTSTATUS NtStatus = STATUS_SUCCESS;
  2339. for (LIST_ENTRY* pListEntry = KerbSKeyList.Flink;
  2340. NT_SUCCESS(NtStatus) && pListEntry != &KerbSKeyList;
  2341. pListEntry = pListEntry->Flink)
  2342. {
  2343. BOOLEAN bEqual = FALSE;
  2344. KERB_SESSION_KEY_ENTRY* pSKeyEntry = CONTAINING_RECORD(pListEntry, KERB_SESSION_KEY_ENTRY, ListEntry);
  2345. NtStatus = KerbEqualKey(&pSKeyEntry->SessionKey, pKey, &bEqual);
  2346. if (NT_SUCCESS(NtStatus) && bEqual)
  2347. {
  2348. KerbFreeSKeyEntry(pSKeyEntry);
  2349. break;
  2350. }
  2351. }
  2352. SafeReleaseResource(&KerbSKeyLock);
  2353. }
  2354. }
  2355. }
  2356. //+-----------------------------------------------------------------------
  2357. //
  2358. // Function: KerbEqualKey
  2359. //
  2360. // Synopsis: Compare two keys
  2361. //
  2362. // Effects:
  2363. //
  2364. // Arguments: pKeyFoo - one key
  2365. // pKeyBar - the other key
  2366. //
  2367. // Returns: NTSTATUS
  2368. //
  2369. // History:
  2370. //
  2371. //------------------------------------------------------------------------
  2372. NTSTATUS
  2373. KerbEqualKey(
  2374. IN KERB_ENCRYPTION_KEY* pKeyFoo,
  2375. IN KERB_ENCRYPTION_KEY* pKeyBar,
  2376. OUT BOOLEAN* pbEqual
  2377. )
  2378. {
  2379. if (!pKeyFoo || !pKeyBar || !pbEqual)
  2380. {
  2381. return STATUS_INVALID_PARAMETER;
  2382. }
  2383. *pbEqual = (pKeyFoo->keytype == pKeyBar->keytype) &&
  2384. (pKeyFoo->keyvalue.length == pKeyBar->keyvalue.length) &&
  2385. (pKeyFoo->keyvalue.length == RtlCompareMemory(pKeyFoo->keyvalue.value, pKeyBar->keyvalue.value, pKeyFoo->keyvalue.length));
  2386. return STATUS_SUCCESS;
  2387. }
  2388. //+-------------------------------------------------------------------------
  2389. //
  2390. // Function: KerbTrimSKeyList
  2391. //
  2392. // Synopsis: Release session key entries that have expired
  2393. //
  2394. // Effects:
  2395. //
  2396. // Arguments:
  2397. //
  2398. // Requires:
  2399. //
  2400. // Returns:
  2401. //
  2402. // Notes:
  2403. //
  2404. //
  2405. //--------------------------------------------------------------------------
  2406. VOID
  2407. KerbTrimSKeyList(
  2408. VOID
  2409. )
  2410. {
  2411. FILETIME CurrentTime = {0};
  2412. BOOLEAN bCleanUpNeeded = FALSE;
  2413. GetSystemTimeAsFileTime(&CurrentTime);
  2414. DebugLog((DEB_TRACE_LOOPBACK, "KerbTrimSKeyList, curtime %#x:%#x\n", CurrentTime.dwHighDateTime, CurrentTime.dwLowDateTime));
  2415. if (SafeAcquireResourceShared(&KerbSKeyLock, TRUE))
  2416. {
  2417. for (LIST_ENTRY* pListEntry = KerbSKeyList.Flink;
  2418. pListEntry != &KerbSKeyList;
  2419. pListEntry = pListEntry->Flink)
  2420. {
  2421. KERB_SESSION_KEY_ENTRY* pSKeyEntry = CONTAINING_RECORD(pListEntry, KERB_SESSION_KEY_ENTRY, ListEntry);
  2422. if (KerbGetTime(* (TimeStamp*)&pSKeyEntry->ExpireTime) <= KerbGetTime(* (TimeStamp*)&CurrentTime))
  2423. {
  2424. bCleanUpNeeded = TRUE;
  2425. break;
  2426. }
  2427. }
  2428. if (bCleanUpNeeded)
  2429. {
  2430. SafeConvertSharedToExclusive(&KerbSKeyLock);
  2431. for (LIST_ENTRY* pListEntry = KerbSKeyList.Flink;
  2432. pListEntry != &KerbSKeyList;
  2433. /* updating pListEntry inside the loop */)
  2434. {
  2435. KERB_SESSION_KEY_ENTRY* pSKeyEntry = CONTAINING_RECORD(pListEntry, KERB_SESSION_KEY_ENTRY, ListEntry);
  2436. //
  2437. // Update next link before pListEntry is deleted
  2438. //
  2439. pListEntry = pListEntry->Flink;
  2440. //
  2441. // only delete keys that expired
  2442. //
  2443. if (KerbGetTime(* (TimeStamp*)&pSKeyEntry->ExpireTime) <= KerbGetTime(* (TimeStamp*)&CurrentTime))
  2444. {
  2445. KerbFreeSKeyEntry(pSKeyEntry);
  2446. }
  2447. }
  2448. }
  2449. SafeReleaseResource(&KerbSKeyLock);
  2450. }
  2451. }
  2452. //+-------------------------------------------------------------------------
  2453. //
  2454. // Function: KerbSKeyListCleanupCallback
  2455. //
  2456. // Synopsis: Clean up network service session key list
  2457. //
  2458. // Effects:
  2459. //
  2460. // Arguments: pContext - the context parameter, see RtlCreateTimer
  2461. // bTimeOut - whether a timeout has occurred
  2462. //
  2463. // Requires:
  2464. //
  2465. // Returns:
  2466. //
  2467. // Notes:
  2468. //
  2469. //
  2470. //--------------------------------------------------------------------------
  2471. VOID
  2472. KerbSKeyListCleanupCallback(
  2473. IN VOID* pContext,
  2474. IN BOOLEAN bTimeOut
  2475. )
  2476. {
  2477. DebugLog((DEB_TRACE_LOOPBACK, "KerbSKeyListCleanupCallback is called\n"));
  2478. KerbTrimSKeyList();
  2479. }
  2480. //+-------------------------------------------------------------------------
  2481. //
  2482. // Function: KerbFreeSKeyEntry
  2483. //
  2484. // Synopsis: Free a session key entry
  2485. //
  2486. // Effects:
  2487. //
  2488. // Arguments: pSKeyEntry - session key entry to free
  2489. //
  2490. // Requires: pSKeyEntry->ListEntry must have been initialized properly
  2491. //
  2492. // Returns:
  2493. //
  2494. // Notes:
  2495. //
  2496. //
  2497. //--------------------------------------------------------------------------
  2498. VOID
  2499. KerbFreeSKeyEntry(
  2500. IN KERB_SESSION_KEY_ENTRY* pSKeyEntry
  2501. )
  2502. {
  2503. if (pSKeyEntry)
  2504. {
  2505. if (!IsListEmpty(&pSKeyEntry->ListEntry)) // make sure this entry has been linked
  2506. {
  2507. RemoveEntryList(&pSKeyEntry->ListEntry);
  2508. #if DBG
  2509. LONG cSKeyEntries = 0;
  2510. cSKeyEntries = InterlockedDecrement(&KerbcSKeyEntries);
  2511. DebugLog((DEB_TRACE_LOOPBACK, "KerbFreeSKeyEntry, keyexpire %#x:%#x, %d keys left\n",
  2512. pSKeyEntry->ExpireTime.dwHighDateTime,
  2513. pSKeyEntry->ExpireTime.dwLowDateTime,
  2514. cSKeyEntries));
  2515. #endif
  2516. }
  2517. KerbFreeKey(&pSKeyEntry->SessionKey);
  2518. KerbFree(pSKeyEntry);
  2519. }
  2520. }
  2521. //+-------------------------------------------------------------------------
  2522. //
  2523. // Function: KerbCreateSKeyTimer
  2524. //
  2525. // Synopsis: Create a timer and set the callback to clean up the session
  2526. // key list
  2527. //
  2528. // Effects:
  2529. //
  2530. // Arguments:
  2531. //
  2532. // Requires:
  2533. //
  2534. // Returns:
  2535. //
  2536. // Notes:
  2537. //
  2538. //
  2539. //--------------------------------------------------------------------------
  2540. NTSTATUS
  2541. KerbCreateSKeyTimer(
  2542. VOID
  2543. )
  2544. {
  2545. NTSTATUS NtStatus;
  2546. HANDLE hTimer = NULL;
  2547. KerbhSKeyTimerQueue = NULL;
  2548. NtStatus = RtlCreateTimerQueue(&KerbhSKeyTimerQueue);
  2549. if (NT_SUCCESS(NtStatus))
  2550. {
  2551. NtStatus = RtlCreateTimer(
  2552. KerbhSKeyTimerQueue,
  2553. &hTimer,
  2554. KerbSKeyListCleanupCallback,
  2555. NULL, // no context
  2556. KERB_DEFAULT_SKEWTIME * 60 * 1000, // 5 min
  2557. KERB_DEFAULT_SKEWTIME * KERB_SKLIST_CALLBACK_FEQ * 60 * 1000, // 50 min
  2558. 0
  2559. );
  2560. }
  2561. return NtStatus;
  2562. }
  2563. //+-------------------------------------------------------------------------
  2564. //
  2565. // Function: KerbFreeSKeyTimer
  2566. //
  2567. // Synopsis: Free network service key list timer queue
  2568. //
  2569. // Effects:
  2570. //
  2571. // Arguments:
  2572. //
  2573. // Requires:
  2574. //
  2575. // Returns:
  2576. //
  2577. // Notes:
  2578. //
  2579. //
  2580. //--------------------------------------------------------------------------
  2581. VOID
  2582. KerbFreeSKeyTimer(
  2583. VOID
  2584. )
  2585. {
  2586. if (KerbhSKeyTimerQueue)
  2587. {
  2588. RtlDeleteTimerQueue(KerbhSKeyTimerQueue);
  2589. KerbhSKeyTimerQueue = NULL;
  2590. }
  2591. }
  2592. ULONG
  2593. HandleToListIndex(
  2594. ULONG_PTR ContextHandle
  2595. )
  2596. {
  2597. ASSERT( (KERB_USERLIST_COUNT != 0) );
  2598. ASSERT( (KERB_USERLIST_COUNT & 1) == 0 );
  2599. ULONG Number ;
  2600. ULONG Hash;
  2601. ULONG HashFinal;
  2602. Number = (ULONG)ContextHandle;
  2603. Hash = Number;
  2604. Hash += Number >> 8;
  2605. Hash += Number >> 16;
  2606. Hash += Number >> 24;
  2607. HashFinal = Hash;
  2608. HashFinal += Hash >> 4;
  2609. //
  2610. // insure power of two if not one.
  2611. //
  2612. return ( HashFinal & (KERB_USERLIST_COUNT-1) ) ;
  2613. }