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.

2402 lines
60 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1991 - 1992
  6. //
  7. // File: sphelp.c
  8. //
  9. // Contents: Security Package Helper functions (see isecpkg.doc)
  10. //
  11. // Functions LsapUnloadPackage
  12. // LsapAllocate
  13. // LsapFree
  14. // LsapClientAllocate
  15. // LsapCopyToClient
  16. // LsapCopyFromClient
  17. // LsapClientFree
  18. // LsapOpenClientProcess
  19. // LsapOpenClientThread
  20. // LsapDuplicateHandle
  21. // LsapGetWindow
  22. // LsapCreateThread
  23. // LsapMapClientBuffer
  24. //
  25. //
  26. // Notes: By defining TRACK_MEM, we will track all use of memory
  27. // allocated through the LsapAllocate. DBG_MEM will track
  28. // memory leaks.
  29. //
  30. // History: 20 May 92 RichardW Created
  31. //
  32. //------------------------------------------------------------------------
  33. #include <lsapch.hxx>
  34. extern "C"
  35. {
  36. #include "sesmgr.h"
  37. #include "klpcstub.h"
  38. }
  39. typedef struct _LSAP_THREAD_START {
  40. LPTHREAD_START_ROUTINE lpStart;
  41. LPVOID lpParm;
  42. ULONG_PTR dwPackageID;
  43. } LSAP_THREAD_START, *PLSAP_THREAD_START;
  44. extern LSA_CALL_INFO LsapDefaultCallInfo ;
  45. ULONG_PTR LsapUserModeLimit ;
  46. //
  47. // private heaps defines.
  48. //
  49. //
  50. // HEAP_HEADER should always be size even multiple of heap allocation granularity
  51. //
  52. typedef struct {
  53. HANDLE hHeap;
  54. SIZE_T Magic;
  55. } HEAP_HEADER_LSA, *PHEAP_HEADER_LSA;
  56. #define HEAP_COUNT_MAX 32
  57. #define HEAP_MAGIC_TAG 0x66677766
  58. HANDLE gHeaps[ HEAP_COUNT_MAX ];
  59. DWORD gcHeaps;
  60. LSA_SECPKG_FUNCTION_TABLE LsapSecpkgFunctionTable = {
  61. LsapCreateLogonSession,
  62. LsapDeleteLogonSession,
  63. LsapAddCredential,
  64. LsapGetCredentials,
  65. LsapDeleteCredential,
  66. LsapAllocateLsaHeap,
  67. LsapFreeLsaHeap,
  68. LsapAllocateClientBuffer,
  69. LsapFreeClientBuffer,
  70. LsapCopyToClientBuffer,
  71. LsapCopyFromClientBuffer,
  72. LsapImpersonateClient,
  73. LsapUnloadPackage,
  74. LsapDuplicateHandle,
  75. NULL, // LsapSaveSupplementalCredentials,
  76. LsapCreateThread,
  77. LsapGetClientInfo,
  78. LsaIRegisterNotification,
  79. LsaICancelNotification,
  80. LsapMapClientBuffer,
  81. LsapCreateToken,
  82. LsapAuditLogon,
  83. LsaICallPackage,
  84. LsaIFreeReturnBuffer,
  85. LsapGetCallInfo,
  86. LsaICallPackageEx,
  87. LsaCreateSharedMemory,
  88. LsaAllocateSharedMemory,
  89. LsaFreeSharedMemory,
  90. LsaDeleteSharedMemory,
  91. LsaOpenSamUser,
  92. NULL, // LsaGetUserCredentials
  93. LsaGetUserAuthData,
  94. LsaCloseSamUser,
  95. LsaConvertAuthDataToToken,
  96. LsaClientCallback,
  97. LsapUpdateCredentials,
  98. LsaGetAuthDataForUser,
  99. LsaCrackSingleName,
  100. LsaIAuditAccountLogon,
  101. LsaICallPackagePassthrough,
  102. CrediRead,
  103. CrediReadDomainCredentials,
  104. CrediFreeCredentials,
  105. LsaProtectMemory,
  106. LsaUnprotectMemory,
  107. LsapOpenTokenByLogonId,
  108. LsaExpandAuthDataForDomain,
  109. LsapAllocatePrivateHeap,
  110. LsapFreePrivateHeap,
  111. LsapCreateTokenEx,
  112. CrediWrite
  113. };
  114. //+-------------------------------------------------------------------------
  115. //
  116. // Function: LsapOpenCaller
  117. //
  118. // Synopsis: Opens the calling process
  119. //
  120. // Effects:
  121. //
  122. // Arguments: phProcess -- receives handle to process
  123. //
  124. // Requires:
  125. //
  126. // Returns:
  127. //
  128. // Notes:
  129. //
  130. //--------------------------------------------------------------------------
  131. NTSTATUS
  132. LsapOpenCaller(
  133. IN OUT PSession pSession
  134. )
  135. {
  136. HANDLE hProcess;
  137. NTSTATUS Status;
  138. OBJECT_ATTRIBUTES ObjectAttributes;
  139. CLIENT_ID ClientId;
  140. PVOID Ignored ;
  141. ClientId.UniqueThread = NULL;
  142. ClientId.UniqueProcess = (HANDLE) LongToHandle(pSession->dwProcessID);
  143. InitializeObjectAttributes(
  144. &ObjectAttributes,
  145. NULL,
  146. 0,
  147. NULL,
  148. NULL
  149. );
  150. Status = NtOpenProcess(
  151. &hProcess,
  152. PROCESS_DUP_HANDLE | // Duplicate Handles
  153. PROCESS_QUERY_INFORMATION | // Get token
  154. PROCESS_VM_OPERATION | // Allocate
  155. PROCESS_VM_READ | // Read memory
  156. PROCESS_VM_WRITE, // Write memory
  157. &ObjectAttributes,
  158. &ClientId
  159. );
  160. if (!NT_SUCCESS(Status))
  161. {
  162. DebugLog((DEB_ERROR, "Did not open process %08x, error %08x\n",
  163. pSession->dwProcessID, Status));
  164. return( Status );
  165. }
  166. pSession->hProcess = hProcess;
  167. Status = NtQueryInformationProcess(
  168. hProcess,
  169. ProcessSessionInformation,
  170. &pSession->SessionId,
  171. sizeof( ULONG ),
  172. NULL );
  173. #if _WIN64
  174. Status = NtQueryInformationProcess(
  175. hProcess,
  176. ProcessWow64Information,
  177. &Ignored,
  178. sizeof( Ignored ),
  179. NULL );
  180. if ( NT_SUCCESS( Status ) )
  181. {
  182. if ( Ignored != 0 )
  183. {
  184. pSession->fSession |= SESFLAG_WOW_PROCESS ;
  185. }
  186. }
  187. #endif
  188. return( STATUS_SUCCESS );
  189. }
  190. //+-------------------------------------------------------------------------
  191. //
  192. // Function: CheckCaller
  193. //
  194. // Synopsis: Checks if calling process has been opened, opens if it
  195. // hasn't.
  196. //
  197. // Effects:
  198. //
  199. // Arguments: pSession - Current session
  200. //
  201. // Requires:
  202. //
  203. // Returns:
  204. //
  205. // Notes:
  206. //
  207. //--------------------------------------------------------------------------
  208. NTSTATUS
  209. CheckCaller(
  210. IN PSession pSession
  211. )
  212. {
  213. NTSTATUS Status;
  214. if (!pSession->hProcess)
  215. {
  216. Status = LsapOpenCaller(pSession);
  217. if (FAILED(Status))
  218. {
  219. DebugLog((DEB_ERROR, "Could not open client (%x)\n", Status));
  220. return(Status);
  221. }
  222. }
  223. return(STATUS_SUCCESS);
  224. }
  225. //+-------------------------------------------------------------------------
  226. //
  227. // Function: LsapUnloadPackage
  228. //
  229. // Synopsis: Unloads the calling package in case of catastrophic problems
  230. //
  231. // Effects: Unloads the DLL that generated this call.
  232. //
  233. // Arguments:
  234. //
  235. // Requires:
  236. //
  237. // Returns:
  238. //
  239. // Notes: Calling thread is terminated through a special exception.
  240. //
  241. //--------------------------------------------------------------------------
  242. NTSTATUS NTAPI
  243. LsapUnloadPackage(
  244. VOID
  245. )
  246. {
  247. ULONG_PTR PackageId;
  248. PSession pSession = GetCurrentSession();
  249. PackageId = GetCurrentPackageId();
  250. pSession->fSession |= SESFLAG_UNLOADING;
  251. RaiseException((ULONG) SEC_E_BAD_PKGID, 0, 0, NULL);
  252. return(STATUS_SUCCESS);
  253. }
  254. BOOLEAN
  255. LsapHeapInitialize(
  256. IN BOOLEAN Server
  257. )
  258. {
  259. if( !Server )
  260. {
  261. NT_PRODUCT_TYPE ProductType;
  262. if ( RtlGetNtProductType( &ProductType ) &&
  263. (ProductType == NtProductServer || ProductType == NtProductLanManNt)
  264. )
  265. {
  266. Server = TRUE;
  267. }
  268. }
  269. if ( Server )
  270. {
  271. SYSTEM_INFO si;
  272. DWORD Heaps;
  273. DWORD i, cHeapsCreated;
  274. RTL_HEAP_PARAMETERS HeapParameters;
  275. ULONG Value;
  276. GetSystemInfo( &si );
  277. if( si.dwNumberOfProcessors == 0 )
  278. {
  279. Heaps = 1;
  280. }
  281. else if( si.dwNumberOfProcessors > HEAP_COUNT_MAX )
  282. {
  283. Heaps = HEAP_COUNT_MAX;
  284. }
  285. else
  286. {
  287. Heaps = si.dwNumberOfProcessors;
  288. }
  289. ZeroMemory( &HeapParameters, sizeof(HeapParameters) );
  290. HeapParameters.Length = sizeof(HeapParameters);
  291. HeapParameters.DeCommitTotalFreeThreshold = 8 * LsapPageSize ;
  292. cHeapsCreated = 0;
  293. for( i = 0 ; i < Heaps ; i++ )
  294. {
  295. gHeaps[ cHeapsCreated ] = RtlCreateHeap(
  296. HEAP_GROWABLE,
  297. NULL,
  298. 0,
  299. 0,
  300. NULL,
  301. &HeapParameters
  302. );
  303. if( gHeaps[ cHeapsCreated ] != NULL )
  304. {
  305. //
  306. // enable low-frag heap.
  307. //
  308. Value = 2;
  309. HeapSetInformation(
  310. gHeaps[ cHeapsCreated ],
  311. HeapCompatibilityInformation,
  312. &Value,
  313. sizeof(Value)
  314. );
  315. cHeapsCreated++;
  316. }
  317. }
  318. gcHeaps = cHeapsCreated;
  319. //
  320. // enable low-frag heap on process heap.
  321. //
  322. Value = 2;
  323. HeapSetInformation(
  324. GetProcessHeap(),
  325. HeapCompatibilityInformation,
  326. &Value,
  327. sizeof(Value)
  328. );
  329. }
  330. if( gHeaps[ 0 ] == NULL )
  331. {
  332. gHeaps[ 0 ] = RtlProcessHeap();
  333. gcHeaps = 1;
  334. }
  335. return TRUE;
  336. }
  337. //+-------------------------------------------------------------------------
  338. //
  339. // Function: LsapAllocateLsaHeap
  340. //
  341. // Synopsis: Allocates memory on process heap
  342. //
  343. // Effects:
  344. //
  345. // Arguments: cbMemory -- Size of block needed
  346. //
  347. // Requires:
  348. //
  349. // Returns: ptr to memory
  350. //
  351. // Notes: if DBGMEM or TRACK_MEM defined, extra work is done for
  352. // tracking purposes.
  353. //
  354. // Can raise the exception STATUS_NO_MEMORY
  355. //
  356. // Per object reuse rules of C2 and above, we zero any memory
  357. // allocated through this function
  358. //
  359. //--------------------------------------------------------------------------
  360. PVOID NTAPI
  361. LsapAllocateLsaHeap(
  362. IN ULONG cbMemory
  363. )
  364. {
  365. return(RtlAllocateHeap(
  366. RtlProcessHeap(),
  367. HEAP_ZERO_MEMORY,
  368. cbMemory
  369. ));
  370. }
  371. //+-------------------------------------------------------------------------
  372. //
  373. // Function: LsapFreeLsaHeap
  374. //
  375. // Synopsis: Frees memory allocated by LsapAllocateLsaHeap
  376. //
  377. // Effects:
  378. //
  379. // Arguments: pvMemory
  380. //
  381. // Requires:
  382. //
  383. // Returns:
  384. //
  385. // Notes:
  386. //
  387. //--------------------------------------------------------------------------
  388. void NTAPI
  389. LsapFreeLsaHeap(
  390. IN PVOID pvMemory
  391. )
  392. {
  393. RtlFreeHeap(
  394. RtlProcessHeap(),
  395. 0,
  396. pvMemory
  397. );
  398. }
  399. //+-------------------------------------------------------------------------
  400. //
  401. // Function: LsapAllocatePrivateHeap
  402. //
  403. // Synopsis: Allocates memory on private heap(s)
  404. //
  405. // Effects:
  406. //
  407. // Arguments: cbMemory -- Size of block needed
  408. //
  409. // Requires:
  410. //
  411. // Returns: ptr to memory
  412. //
  413. // Per object reuse rules of C2 and above, we zero any memory
  414. // allocated through this function
  415. //
  416. //--------------------------------------------------------------------------
  417. PVOID
  418. NTAPI
  419. LsapAllocatePrivateHeap(
  420. IN SIZE_T cbMemory
  421. )
  422. {
  423. HANDLE hHeap;
  424. PHEAP_HEADER_LSA memory;
  425. hHeap = LsapGetCurrentHeap();
  426. if( hHeap == NULL )
  427. {
  428. static ULONG heapindex;
  429. ULONG LocalHeapIndex;
  430. LocalHeapIndex = (ULONG)InterlockedIncrement( (PLONG)&heapindex );
  431. LocalHeapIndex %= gcHeaps;
  432. hHeap = gHeaps[ LocalHeapIndex ];
  433. LsapSetCurrentHeap( hHeap );
  434. }
  435. memory = (PHEAP_HEADER_LSA)RtlAllocateHeap(
  436. hHeap,
  437. HEAP_ZERO_MEMORY,
  438. cbMemory+sizeof(HEAP_HEADER_LSA)
  439. );
  440. if( memory != NULL )
  441. {
  442. memory->hHeap = hHeap;
  443. memory->Magic = (unsigned char*)HEAP_MAGIC_TAG-(unsigned char*)hHeap;
  444. return ( (unsigned char*)memory+sizeof(HEAP_HEADER_LSA) );
  445. }
  446. DebugLog((DEB_ERROR,"LsapAllocatePrivateHeap: %p failed allocate %lu bytes\n", hHeap, cbMemory));
  447. return NULL;
  448. }
  449. PVOID
  450. NTAPI
  451. LsapAllocatePrivateHeapNoZero(
  452. IN SIZE_T cbMemory
  453. )
  454. {
  455. HANDLE hHeap;
  456. PHEAP_HEADER_LSA memory;
  457. hHeap = LsapGetCurrentHeap();
  458. if( hHeap == NULL )
  459. {
  460. static ULONG heapindex;
  461. ULONG LocalHeapIndex;
  462. LocalHeapIndex = (ULONG)InterlockedIncrement( (PLONG)&heapindex );
  463. LocalHeapIndex %= gcHeaps;
  464. hHeap = gHeaps[ LocalHeapIndex ];
  465. LsapSetCurrentHeap( hHeap );
  466. }
  467. memory = (PHEAP_HEADER_LSA)RtlAllocateHeap(
  468. hHeap,
  469. 0,
  470. cbMemory+sizeof(HEAP_HEADER_LSA)
  471. );
  472. if( memory != NULL )
  473. {
  474. memory->hHeap = hHeap;
  475. memory->Magic = (unsigned char*)HEAP_MAGIC_TAG-(unsigned char*)hHeap;
  476. return ( (unsigned char*)memory+sizeof(HEAP_HEADER_LSA) );
  477. }
  478. DebugLog((DEB_ERROR,"LsapAllocatePrivateHeapNoZero: %p failed allocate %lu bytes\n", hHeap, cbMemory));
  479. return NULL;
  480. }
  481. //+-------------------------------------------------------------------------
  482. //
  483. // Function: LsapFreePrivateHeap
  484. //
  485. // Synopsis: Frees memory allocated by LsapAllocatePrivateHeap
  486. //
  487. // Effects:
  488. //
  489. // Arguments: pvMemory
  490. //
  491. // Requires:
  492. //
  493. // Returns:
  494. //
  495. // Notes:
  496. //
  497. //--------------------------------------------------------------------------
  498. void
  499. NTAPI
  500. LsapFreePrivateHeap(
  501. IN PVOID pvMemory
  502. )
  503. {
  504. PHEAP_HEADER_LSA HeapEntry;
  505. if( pvMemory == NULL )
  506. {
  507. return ;
  508. }
  509. HeapEntry = (PHEAP_HEADER_LSA)((unsigned char*)pvMemory-sizeof(HEAP_HEADER_LSA));
  510. if( HeapEntry->Magic + ((unsigned char*)HeapEntry->hHeap) != (unsigned char*)HEAP_MAGIC_TAG )
  511. {
  512. DebugLog((DEB_ERROR, "LsapFreePrivateHeap tried to free %p from wrong heap\n",
  513. pvMemory));
  514. DsysAssert( pvMemory == NULL );
  515. return;
  516. }
  517. RtlFreeHeap(
  518. HeapEntry->hHeap,
  519. 0,
  520. HeapEntry
  521. );
  522. }
  523. //+-------------------------------------------------------------------------
  524. //
  525. // Function: LsapClientAllocate
  526. //
  527. // Synopsis: Allocates memory in client process
  528. //
  529. // Effects:
  530. //
  531. // Arguments: cbMemory -- Size of block to allocate
  532. //
  533. // Requires:
  534. //
  535. // Returns: pointer to memory in client address space
  536. //
  537. // Notes: pointer is not valid in this process, only in client
  538. //
  539. //--------------------------------------------------------------------------
  540. PVOID NTAPI
  541. LsapClientAllocate(
  542. IN ULONG cbMemory
  543. )
  544. {
  545. NTSTATUS Status;
  546. PSession pSession;
  547. void * pClientMemory = NULL;
  548. SIZE_T cbMem = cbMemory;
  549. PLSA_CALL_INFO CallInfo ;
  550. CallInfo = LsapGetCurrentCall();
  551. pSession = GetCurrentSession() ;
  552. if ( pSession == NULL )
  553. {
  554. pSession = pDefaultSession ;
  555. }
  556. if ( CallInfo == NULL )
  557. {
  558. CallInfo = &LsapDefaultCallInfo ;
  559. }
  560. if (FAILED(CheckCaller(pSession)))
  561. {
  562. return(NULL);
  563. }
  564. //
  565. // If the INPROC flag is set, allocate out of the heap. The copy functions
  566. // will also honor this.
  567. //
  568. if ( pSession->fSession & SESFLAG_INPROC )
  569. {
  570. pClientMemory = LsapAllocateLsaHeap( (ULONG) cbMem );
  571. return( pClientMemory );
  572. }
  573. if ( CallInfo->Flags & CALL_FLAG_KERNEL_POOL )
  574. {
  575. if ( ( CallInfo->Flags & CALL_FLAG_KMAP_USED ) != 0 )
  576. {
  577. pClientMemory = LsapAllocateFromKsecBuffer(
  578. CallInfo->KMap,
  579. (ULONG) cbMem );
  580. DebugLog((DEB_TRACE_HELPERS, "[%x] LsapClientAllocate(%d) = %p in KMap %p\n",
  581. pSession->dwProcessID, cbMem,
  582. pClientMemory, CallInfo->KMap ));
  583. return pClientMemory ;
  584. }
  585. }
  586. Status = NtAllocateVirtualMemory(pSession->hProcess,
  587. &pClientMemory,
  588. 0,
  589. &cbMem,
  590. MEM_COMMIT,
  591. PAGE_READWRITE);
  592. if (!NT_SUCCESS(Status))
  593. {
  594. DebugLog((DEB_ERROR, "[%x] Could not allocate client memory (%x)\n",
  595. pSession->dwProcessID, Status));
  596. pClientMemory = NULL;
  597. }
  598. DebugLog((DEB_TRACE_HELPERS, "[%x] LsapClientAllocate(%d) = %p\n",
  599. pSession->dwProcessID, cbMemory, pClientMemory));
  600. if ( pClientMemory )
  601. {
  602. // Save pointer so that FreeContextBuffer will use
  603. // correct 'free' function.
  604. if(CallInfo->Allocs < MAX_BUFFERS_IN_CALL)
  605. {
  606. CallInfo->Buffers[ CallInfo->Allocs++ ] = pClientMemory ;
  607. }
  608. }
  609. return(pClientMemory);
  610. }
  611. //+-------------------------------------------------------------------------
  612. //
  613. // Function: LsapCopyToClient
  614. //
  615. // Synopsis: Copies data into client process
  616. //
  617. // Effects:
  618. //
  619. // Arguments: pLocalMemory -- pointer to data in this process
  620. // pClientMemory -- pointer to destination in client process
  621. // cbMemory -- how much to copy
  622. //
  623. // Requires:
  624. //
  625. // Returns:
  626. //
  627. // Notes:
  628. //
  629. //--------------------------------------------------------------------------
  630. NTSTATUS NTAPI
  631. LsapCopyToClient(
  632. IN PVOID pLocalMemory,
  633. OUT PVOID pClientMemory,
  634. IN ULONG cbMemory
  635. )
  636. {
  637. NTSTATUS Status;
  638. PSession pSession;
  639. PLSA_CALL_INFO CallInfo;
  640. PKSEC_LSA_MEMORY_HEADER Header ;
  641. ULONG i ;
  642. ULONG_PTR Basis ;
  643. ULONG_PTR Limit ;
  644. BOOL Tried = FALSE ;
  645. if (cbMemory == 0)
  646. {
  647. return(STATUS_SUCCESS);
  648. }
  649. pSession = GetCurrentSession();
  650. if ( !pSession )
  651. {
  652. pSession = pDefaultSession ;
  653. }
  654. CallInfo = LsapGetCurrentCall();
  655. if ( ( pLocalMemory == NULL ) ||
  656. ( pClientMemory == NULL ) )
  657. {
  658. return STATUS_ACCESS_VIOLATION ;
  659. }
  660. if (FAILED(Status = CheckCaller(pSession)))
  661. {
  662. return(Status);
  663. }
  664. //
  665. // Cases for a direct copy:
  666. //
  667. // - The current session is the default session
  668. // - This is an inproc call
  669. // - We're using a KMap buffer
  670. //
  671. if (CallInfo &&
  672. CallInfo->Flags & CALL_FLAG_KERNEL_POOL )
  673. {
  674. Header = CallInfo->KMap ;
  675. if ( (ULONG_PTR) pClientMemory > LsapUserModeLimit )
  676. {
  677. //
  678. // Someone is trying to deal with a pool address directly.
  679. // we can handle this if it was copied into the KMap already
  680. //
  681. for ( i = 0 ; i < Header->MapCount ; i++ )
  682. {
  683. Limit = (ULONG_PTR) Header->PoolMap[ i ].Pool + Header->PoolMap[ i ].Size ;
  684. if ( ((ULONG_PTR) pClientMemory >= (ULONG_PTR) Header->PoolMap[ i ].Pool ) &&
  685. ( (ULONG_PTR) pClientMemory < Limit ) )
  686. {
  687. //
  688. // Found an overlap, this is promising. Check the bounds:
  689. //
  690. Basis = (ULONG_PTR) pClientMemory -
  691. (ULONG_PTR) Header->PoolMap[ i ].Pool ;
  692. if ( Basis + cbMemory <= Header->PoolMap[ i ].Size )
  693. {
  694. //
  695. // Found it!
  696. //
  697. __try
  698. {
  699. RtlCopyMemory(
  700. (PUCHAR) Header +
  701. (Header->PoolMap[ i ].Offset +
  702. Basis),
  703. pLocalMemory,
  704. cbMemory );
  705. Status = STATUS_SUCCESS ;
  706. }
  707. __except (EXCEPTION_EXECUTE_HANDLER)
  708. {
  709. Status = GetExceptionCode();
  710. }
  711. }
  712. Tried = TRUE ;
  713. break;
  714. }
  715. }
  716. if ( !Tried )
  717. {
  718. Status = STATUS_ACCESS_VIOLATION ;
  719. }
  720. }
  721. else if ( LsapIsBlockInKMap( CallInfo->KMap, pClientMemory ) )
  722. {
  723. __try
  724. {
  725. RtlCopyMemory( pClientMemory, pLocalMemory, cbMemory );
  726. Status = STATUS_SUCCESS ;
  727. }
  728. __except (EXCEPTION_EXECUTE_HANDLER)
  729. {
  730. Status = GetExceptionCode();
  731. }
  732. }
  733. else
  734. {
  735. Status = NtWriteVirtualMemory(pSession->hProcess,
  736. pClientMemory,
  737. pLocalMemory,
  738. cbMemory,
  739. NULL);
  740. }
  741. } else if ( (pSession->dwProcessID == pDefaultSession->dwProcessID) ||
  742. (pSession->fSession & SESFLAG_INPROC) ||
  743. (CallInfo->Flags & CALL_FLAG_KMAP_USED ) )
  744. {
  745. __try
  746. {
  747. RtlCopyMemory( pClientMemory, pLocalMemory, cbMemory );
  748. Status = STATUS_SUCCESS ;
  749. }
  750. __except ( EXCEPTION_EXECUTE_HANDLER )
  751. {
  752. Status = GetExceptionCode();
  753. }
  754. }
  755. else
  756. {
  757. Status = NtWriteVirtualMemory( pSession->hProcess,
  758. pClientMemory,
  759. pLocalMemory,
  760. cbMemory,
  761. NULL);
  762. }
  763. DebugLog((DEB_TRACE_HELPERS, "[%x] LsapCopyToClient(%p, %p, %d) = %x\n",
  764. pSession->dwProcessID, pLocalMemory, pClientMemory, cbMemory,
  765. Status ));
  766. return(Status);
  767. }
  768. //+-------------------------------------------------------------------------
  769. //
  770. // Function: LsapCopyFromClient
  771. //
  772. // Synopsis: Copies memory from client to this process
  773. //
  774. // Effects:
  775. //
  776. // Arguments: pClientMemory -- Pointer to data in client space
  777. // pLocalMemory -- Pointer to destination in this process
  778. // cbMemory -- How much
  779. //
  780. // Requires:
  781. //
  782. // Returns:
  783. //
  784. // Notes:
  785. //
  786. //--------------------------------------------------------------------------
  787. NTSTATUS NTAPI
  788. LsapCopyFromClient(
  789. IN PVOID pClientMemory,
  790. OUT PVOID pLocalMemory,
  791. IN ULONG cbMemory
  792. )
  793. {
  794. NTSTATUS Status;
  795. PSession pSession;
  796. PLSA_CALL_INFO CallInfo ;
  797. PKSEC_LSA_MEMORY_HEADER Header ;
  798. ULONG i ;
  799. ULONG_PTR Basis ;
  800. ULONG_PTR Limit ;
  801. BOOL Tried = FALSE ;
  802. if (cbMemory == 0)
  803. {
  804. return(STATUS_SUCCESS);
  805. }
  806. if ( ( pClientMemory == NULL ) ||
  807. ( pLocalMemory == NULL ) )
  808. {
  809. return STATUS_ACCESS_VIOLATION ;
  810. }
  811. pSession = GetCurrentSession();
  812. if ( pSession == NULL )
  813. {
  814. pSession = pDefaultSession ;
  815. }
  816. CallInfo = LsapGetCurrentCall();
  817. if (FAILED(Status = CheckCaller(pSession)))
  818. {
  819. return(Status);
  820. }
  821. if (CallInfo &&
  822. CallInfo->Flags & CALL_FLAG_KERNEL_POOL )
  823. {
  824. Header = CallInfo->KMap ;
  825. if ( (ULONG_PTR) pClientMemory > LsapUserModeLimit )
  826. {
  827. //
  828. // Someone is trying to deal with a pool address directly.
  829. // we can handle this if it was copied into the KMap already
  830. //
  831. for ( i = 0 ; i < Header->MapCount ; i++ )
  832. {
  833. Limit = (ULONG_PTR) Header->PoolMap[ i ].Pool + Header->PoolMap[ i ].Size ;
  834. if ( ((ULONG_PTR) pClientMemory >= (ULONG_PTR) Header->PoolMap[ i ].Pool ) &&
  835. ( (ULONG_PTR) pClientMemory < Limit ) )
  836. {
  837. //
  838. // Found an overlap, this is promising. Check the bounds:
  839. //
  840. Basis = (ULONG_PTR) pClientMemory -
  841. (ULONG_PTR) Header->PoolMap[ i ].Pool ;
  842. if ( Basis + cbMemory <= Header->PoolMap[ i ].Size )
  843. {
  844. //
  845. // Found it!
  846. //
  847. __try
  848. {
  849. RtlCopyMemory(
  850. pLocalMemory,
  851. (PUCHAR) Header +
  852. (Header->PoolMap[ i ].Offset +
  853. Basis),
  854. cbMemory );
  855. Status = STATUS_SUCCESS ;
  856. }
  857. __except (EXCEPTION_EXECUTE_HANDLER)
  858. {
  859. Status = GetExceptionCode();
  860. }
  861. }
  862. Tried = TRUE ;
  863. break;
  864. }
  865. }
  866. if ( !Tried )
  867. {
  868. Status = STATUS_ACCESS_VIOLATION ;
  869. }
  870. }
  871. else if ( LsapIsBlockInKMap( CallInfo->KMap, pClientMemory ) )
  872. {
  873. __try
  874. {
  875. RtlCopyMemory( pLocalMemory, pClientMemory, cbMemory );
  876. Status = STATUS_SUCCESS ;
  877. }
  878. __except (EXCEPTION_EXECUTE_HANDLER)
  879. {
  880. Status = GetExceptionCode();
  881. }
  882. }
  883. else
  884. {
  885. Status = NtReadVirtualMemory(pSession->hProcess,
  886. pClientMemory,
  887. pLocalMemory,
  888. cbMemory,
  889. NULL);
  890. }
  891. }
  892. else if ( (pSession->dwProcessID == pDefaultSession->dwProcessID) ||
  893. (pSession->fSession & SESFLAG_INPROC ) )
  894. {
  895. __try
  896. {
  897. RtlCopyMemory( pLocalMemory, pClientMemory, cbMemory );
  898. Status = STATUS_SUCCESS ;
  899. }
  900. __except (EXCEPTION_EXECUTE_HANDLER)
  901. {
  902. Status = GetExceptionCode();
  903. }
  904. }
  905. else
  906. {
  907. Status = NtReadVirtualMemory(pSession->hProcess,
  908. pClientMemory,
  909. pLocalMemory,
  910. cbMemory,
  911. NULL);
  912. }
  913. DebugLog((DEB_TRACE_HELPERS, "[%x] LsapCopyFromClient(%p, %p, %d) = %x\n",
  914. pSession->dwProcessID, pClientMemory, pLocalMemory, cbMemory,
  915. Status));
  916. return(Status);
  917. }
  918. //+-------------------------------------------------------------------------
  919. //
  920. // Function: LsapClientFree
  921. //
  922. // Synopsis: Frees memory allocated in client space
  923. //
  924. // Effects:
  925. //
  926. // Arguments: pClientMemory -- pointer to memory to free
  927. //
  928. // Requires:
  929. //
  930. // Returns:
  931. //
  932. // Notes:
  933. //
  934. //--------------------------------------------------------------------------
  935. NTSTATUS NTAPI
  936. LsapClientFree(
  937. IN PVOID pClientMemory
  938. )
  939. {
  940. NTSTATUS Status;
  941. SIZE_T cbMem = 0;
  942. PSession pSession;
  943. PLSA_CALL_INFO CallInfo ;
  944. CallInfo = LsapGetCurrentCall();
  945. if ( CallInfo == NULL )
  946. {
  947. CallInfo = &LsapDefaultCallInfo ;
  948. }
  949. if (!pClientMemory)
  950. {
  951. return(STATUS_SUCCESS);
  952. }
  953. pSession = GetCurrentSession();
  954. if ( pSession == NULL )
  955. {
  956. pSession = pDefaultSession ;
  957. }
  958. if (FAILED(Status = CheckCaller(pSession)))
  959. {
  960. return(Status);
  961. }
  962. if ( pSession->fSession & SESFLAG_INPROC )
  963. {
  964. LsapFreeLsaHeap( pClientMemory );
  965. return( STATUS_SUCCESS );
  966. }
  967. #if DBG
  968. if ( pSession->dwProcessID == pDefaultSession->dwProcessID )
  969. {
  970. DebugLog(( DEB_ERROR, "Freeing VM in LSA: %x\n", pClientMemory ));
  971. }
  972. #endif
  973. Status = NtFreeVirtualMemory(pSession->hProcess,
  974. &pClientMemory,
  975. &cbMem,
  976. MEM_RELEASE);
  977. if ( pClientMemory )
  978. {
  979. ULONG i;
  980. // Remove this pointer from our list.
  981. for(i = 0; i < CallInfo->Allocs; i++)
  982. {
  983. if(CallInfo->Buffers[i] == pClientMemory)
  984. {
  985. if(i < CallInfo->Allocs - 1)
  986. {
  987. memcpy(&CallInfo->Buffers[i],
  988. &CallInfo->Buffers[i+1],
  989. sizeof(PVOID) * (CallInfo->Allocs - i - 1));
  990. }
  991. CallInfo->Allocs--;
  992. break;
  993. }
  994. }
  995. }
  996. DebugLog((DEB_TRACE_HELPERS, "[%x] LsapClientFree(%x) == %x\n",
  997. pSession->dwProcessID, pClientMemory, Status));
  998. return(Status);
  999. }
  1000. //+-------------------------------------------------------------------------
  1001. //
  1002. // Function: LsapDuplicateHandle
  1003. //
  1004. // Synopsis: Duplicates a handle to an NT object into the calling process
  1005. //
  1006. // Effects: A new handle is generated, referencing the object
  1007. //
  1008. // Arguments: hObject -- handle to the object
  1009. // hNewObject -- New handle valid in calling process
  1010. //
  1011. // Requires:
  1012. //
  1013. // Returns:
  1014. //
  1015. // Notes:
  1016. //
  1017. //--------------------------------------------------------------------------
  1018. NTSTATUS NTAPI
  1019. LsapDuplicateHandle(
  1020. IN HANDLE hObject,
  1021. OUT PHANDLE phNewObject
  1022. )
  1023. {
  1024. NTSTATUS Status;
  1025. PSession pSession;
  1026. pSession = GetCurrentSession();
  1027. if ( pSession == NULL )
  1028. {
  1029. pSession = pDefaultSession ;
  1030. }
  1031. if (Status = CheckCaller(pSession))
  1032. {
  1033. DebugLog((DEB_ERROR, "CheckCaller returned %d\n", Status));
  1034. return(Status);
  1035. }
  1036. Status = NtDuplicateObject( NtCurrentProcess(),
  1037. hObject,
  1038. pSession->hProcess,
  1039. phNewObject,
  1040. 0,
  1041. 0,
  1042. DUPLICATE_SAME_ACCESS);
  1043. DebugLog((DEB_TRACE_HELPERS, "[%x] LsapDupHandle(%x, %x (@%x)) = %x\n",
  1044. pSession->dwProcessID, hObject, *phNewObject, phNewObject, Status));
  1045. return(Status);
  1046. }
  1047. //+---------------------------------------------------------------------------
  1048. //
  1049. // Function: LsapImpersonateClient
  1050. //
  1051. // Synopsis: Impersonate the client of the API call.
  1052. //
  1053. // Arguments: (none)
  1054. //
  1055. // History: 6-05-95 RichardW Created
  1056. //
  1057. // Notes: Threads should call RevertToSelf() when done.
  1058. //
  1059. //----------------------------------------------------------------------------
  1060. NTSTATUS NTAPI
  1061. LsapImpersonateClient(
  1062. VOID
  1063. )
  1064. {
  1065. PSession pSession;
  1066. PLSA_CALL_INFO CallInfo ;
  1067. PSPM_LPC_MESSAGE pApiMessage;
  1068. NTSTATUS Status;
  1069. CallInfo = LsapGetCurrentCall() ;
  1070. if ( CallInfo->InProcCall )
  1071. {
  1072. if ( CallInfo->InProcToken )
  1073. {
  1074. Status = NtSetInformationThread(
  1075. NtCurrentThread(),
  1076. ThreadImpersonationToken,
  1077. (PVOID) &CallInfo->InProcToken,
  1078. sizeof(HANDLE)
  1079. );
  1080. }
  1081. else
  1082. {
  1083. Status = RtlImpersonateSelf(SecurityImpersonation);
  1084. }
  1085. }
  1086. else
  1087. {
  1088. pSession = GetCurrentSession() ;
  1089. if ( !pSession )
  1090. {
  1091. pSession = pDefaultSession ;
  1092. }
  1093. Status = NtImpersonateClientOfPort(
  1094. pSession->hPort,
  1095. (PPORT_MESSAGE) CallInfo->Message);
  1096. }
  1097. return(Status);
  1098. }
  1099. //+-------------------------------------------------------------------------
  1100. //
  1101. // Function: LsapDuplicateString
  1102. //
  1103. // Synopsis:
  1104. //
  1105. // Effects:
  1106. //
  1107. // Arguments:
  1108. //
  1109. // Requires:
  1110. //
  1111. // Returns:
  1112. //
  1113. // Notes:
  1114. //
  1115. //--------------------------------------------------------------------------
  1116. NTSTATUS
  1117. LsapDuplicateString(
  1118. OUT PUNICODE_STRING pDest,
  1119. IN PUNICODE_STRING pSrc
  1120. )
  1121. {
  1122. pDest->Length = 0;
  1123. if (pSrc == NULL)
  1124. {
  1125. pDest->Buffer = NULL;
  1126. pDest->MaximumLength = 0;
  1127. return(STATUS_SUCCESS);
  1128. }
  1129. pDest->Buffer = (LPWSTR) LsapAllocateLsaHeap(pSrc->Length + sizeof(WCHAR));
  1130. if (pDest->Buffer)
  1131. {
  1132. pDest->MaximumLength = pSrc->Length + sizeof(WCHAR);
  1133. RtlCopyMemory(
  1134. pDest->Buffer,
  1135. pSrc->Buffer,
  1136. pSrc->Length
  1137. );
  1138. pDest->Buffer[pSrc->Length/sizeof(WCHAR)] = L'\0';
  1139. pDest->Length = pSrc->Length;
  1140. return(STATUS_SUCCESS);
  1141. }
  1142. else
  1143. {
  1144. pDest->MaximumLength = 0;
  1145. return(STATUS_INSUFFICIENT_RESOURCES);
  1146. }
  1147. }
  1148. NTSTATUS
  1149. LsapDuplicateString2(
  1150. OUT PUNICODE_STRING pDest,
  1151. IN PUNICODE_STRING pSrc
  1152. )
  1153. /*++
  1154. Same as LsapDuplicateString(), but uses LsapPrivateHeap routines.
  1155. --*/
  1156. {
  1157. pDest->Length = 0;
  1158. if (pSrc == NULL)
  1159. {
  1160. pDest->Buffer = NULL;
  1161. pDest->MaximumLength = 0;
  1162. return(STATUS_SUCCESS);
  1163. }
  1164. pDest->Buffer = (LPWSTR) LsapAllocatePrivateHeap(pSrc->Length + sizeof(WCHAR));
  1165. if (pDest->Buffer)
  1166. {
  1167. pDest->MaximumLength = pSrc->Length + sizeof(WCHAR);
  1168. RtlCopyMemory(
  1169. pDest->Buffer,
  1170. pSrc->Buffer,
  1171. pSrc->Length
  1172. );
  1173. pDest->Buffer[pSrc->Length/sizeof(WCHAR)] = L'\0';
  1174. pDest->Length = pSrc->Length;
  1175. return(STATUS_SUCCESS);
  1176. } else
  1177. {
  1178. pDest->MaximumLength = 0;
  1179. return(STATUS_INSUFFICIENT_RESOURCES);
  1180. }
  1181. }
  1182. //+-------------------------------------------------------------------------
  1183. //
  1184. // Function: LsapFreeString
  1185. //
  1186. // Synopsis: Frees a string allocated by LsapDuplicateString
  1187. //
  1188. // Effects:
  1189. //
  1190. // Arguments: String - Optionally points to a UNICODE_STRING
  1191. //
  1192. // Requires:
  1193. //
  1194. // Returns:
  1195. //
  1196. // Notes:
  1197. //
  1198. //
  1199. //--------------------------------------------------------------------------
  1200. VOID
  1201. LsapFreeString(
  1202. IN OPTIONAL PUNICODE_STRING String
  1203. )
  1204. {
  1205. if (ARGUMENT_PRESENT(String) && String->Buffer != NULL)
  1206. {
  1207. LsapFreeLsaHeap(String->Buffer);
  1208. String->Buffer = NULL;
  1209. }
  1210. }
  1211. //+-------------------------------------------------------------------------
  1212. //
  1213. // Function: LsapThreadBase
  1214. //
  1215. // Synopsis: Thread start routine
  1216. //
  1217. // Effects: Sets up all the TLS data for a thread, then executes
  1218. // the "real" base function.
  1219. //
  1220. // Arguments:
  1221. //
  1222. // Requires:
  1223. //
  1224. // Returns:
  1225. //
  1226. // Notes:
  1227. //
  1228. //--------------------------------------------------------------------------
  1229. void
  1230. LsapThreadBase(
  1231. PLSAP_THREAD_START pThread)
  1232. {
  1233. NTSTATUS Status;
  1234. PSession pSession;
  1235. LSAP_THREAD_START tStart = *pThread;
  1236. LsapFreePrivateHeap(pThread);
  1237. SetCurrentSession( pDefaultSession );
  1238. SpmpReferenceSession( pDefaultSession );
  1239. // Initialize Session information:
  1240. SetCurrentPackageId(tStart.dwPackageID);
  1241. DebugLog((DEB_TRACE, "Thread start @%x\n", tStart.lpStart));
  1242. // If this is a debug build, all threads are started in a protective
  1243. // try-except block. For retail, only threads started by packages
  1244. // will be run this way. Retail builds, we assume that the SPM is
  1245. // debugged and running correctly, and threads started this way can
  1246. // be trusted.
  1247. #if DBG == 0
  1248. if (tStart.dwPackageID != SPMGR_ID)
  1249. #endif
  1250. {
  1251. __try
  1252. {
  1253. tStart.lpStart(tStart.lpParm);
  1254. }
  1255. __except (SP_EXCEPTION)
  1256. {
  1257. Status = GetExceptionCode();
  1258. Status = SPException(Status, tStart.dwPackageID);
  1259. }
  1260. }
  1261. #if DBG == 0
  1262. else
  1263. {
  1264. tStart.lpStart(tStart.lpParm);
  1265. }
  1266. #endif
  1267. pSession = GetCurrentSession();
  1268. SpmpDereferenceSession( pSession );
  1269. if ( pSession != pDefaultSession )
  1270. {
  1271. DebugLog(( DEB_ERROR, "Thread completing in session other than default!\n" ));
  1272. }
  1273. DebugLog((DEB_TRACE, "Thread exit\n" ));
  1274. }
  1275. //+-------------------------------------------------------------------------
  1276. //
  1277. // Function: LsapCreateThread
  1278. //
  1279. // Synopsis: Creates a thread with all the proper Tls stuff
  1280. //
  1281. // Effects:
  1282. //
  1283. // Arguments: same as CreateThread
  1284. //
  1285. // Requires:
  1286. //
  1287. // Returns:
  1288. //
  1289. // Notes:
  1290. //
  1291. //--------------------------------------------------------------------------
  1292. HANDLE NTAPI
  1293. LsapCreateThread(
  1294. IN LPSECURITY_ATTRIBUTES lpSA,
  1295. IN ULONG cbStack,
  1296. IN LPTHREAD_START_ROUTINE lpStart,
  1297. IN LPVOID lpvThreadParm,
  1298. IN ULONG fCreate,
  1299. OUT PULONG lpTID
  1300. )
  1301. {
  1302. PLSAP_THREAD_START pThread;
  1303. HANDLE hThread;
  1304. pThread = (PLSAP_THREAD_START) LsapAllocatePrivateHeap(sizeof(LSAP_THREAD_START));
  1305. if (pThread == NULL)
  1306. {
  1307. DebugLog((DEB_ERROR, "LsapCreateThread, memory allocation failed.\n"));
  1308. SetLastError(ERROR_OUTOFMEMORY);
  1309. return(NULL);
  1310. }
  1311. pThread->lpStart = lpStart;
  1312. pThread->lpParm = lpvThreadParm;
  1313. pThread->dwPackageID = GetCurrentPackageId();
  1314. hThread = CreateThread(
  1315. lpSA,
  1316. cbStack,
  1317. (LPTHREAD_START_ROUTINE) LsapThreadBase,
  1318. pThread,
  1319. fCreate,
  1320. lpTID
  1321. );
  1322. if( hThread == NULL )
  1323. {
  1324. DebugLog((DEB_ERROR, "LsapCreateThread, failed thread creation (%lu)\n", GetLastError()));
  1325. LsapFreePrivateHeap( pThread );
  1326. }
  1327. return hThread;
  1328. }
  1329. //+-------------------------------------------------------------------------
  1330. //
  1331. // Function: LsapGetClientInfo
  1332. //
  1333. // Synopsis:
  1334. //
  1335. // Effects:
  1336. //
  1337. // Arguments:
  1338. //
  1339. // Requires:
  1340. //
  1341. // Returns:
  1342. //
  1343. // Notes:
  1344. //
  1345. //--------------------------------------------------------------------------
  1346. NTSTATUS NTAPI
  1347. LsapGetClientInfo(
  1348. OUT PSECPKG_CLIENT_INFO ClientInfo
  1349. )
  1350. {
  1351. PSession pSession = GetCurrentSession();
  1352. PPORT_MESSAGE pMessage;
  1353. HANDLE ClientToken;
  1354. NTSTATUS Status;
  1355. NTSTATUS ExtraStatus ;
  1356. TOKEN_STATISTICS TokenStats;
  1357. ULONG TokenStatsSize = sizeof(TOKEN_STATISTICS);
  1358. PLSA_CALL_INFO CallInfo ;
  1359. HANDLE Thread = NULL ;
  1360. OBJECT_ATTRIBUTES NullAttributes = { 0 };
  1361. KERNEL_USER_TIMES Times ;
  1362. RtlZeroMemory(
  1363. ClientInfo,
  1364. sizeof(SECPKG_CLIENT_INFO)
  1365. );
  1366. if ( !pSession )
  1367. {
  1368. pSession = pDefaultSession ;
  1369. }
  1370. //
  1371. // First, fill in the easy stuff from the session record. If we are
  1372. // running with the LSA session then we want to ignore the LPC message
  1373. // because it may be referring to somebody elses message (we may be
  1374. // being called on behalf of someone doing authenticated RPC in response
  1375. // to an LPC request)
  1376. //
  1377. CallInfo = LsapGetCurrentCall();
  1378. if ( CallInfo )
  1379. {
  1380. ClientInfo->ProcessID = CallInfo->CallInfo.ProcessId ;
  1381. ClientInfo->ThreadID = CallInfo->CallInfo.ThreadId ;
  1382. if (((pSession->fSession & SESFLAG_TCB_PRIV) != 0) ||
  1383. ((pSession->fSession & SESFLAG_KERNEL) != 0))
  1384. {
  1385. ClientInfo->HasTcbPrivilege = TRUE;
  1386. }
  1387. else
  1388. {
  1389. ClientInfo->HasTcbPrivilege = FALSE;
  1390. }
  1391. if(CallInfo->CachedTokenInfo)
  1392. {
  1393. ClientInfo->LogonId = CallInfo->LogonId;
  1394. ClientInfo->Restricted = CallInfo->Restricted;
  1395. ClientInfo->Impersonating = CallInfo->Impersonating;
  1396. ClientInfo->ImpersonationLevel = CallInfo->ImpersonationLevel;
  1397. return STATUS_SUCCESS;
  1398. }
  1399. Status = LsapImpersonateClient();
  1400. if ( !NT_SUCCESS( Status ) )
  1401. {
  1402. if ( Status == STATUS_BAD_IMPERSONATION_LEVEL )
  1403. {
  1404. Status = NtOpenThread(
  1405. &Thread,
  1406. THREAD_QUERY_INFORMATION,
  1407. &NullAttributes,
  1408. &CallInfo->Message->pmMessage.ClientId );
  1409. }
  1410. else if ( ( Status == STATUS_REPLY_MESSAGE_MISMATCH ) ||
  1411. ( Status == STATUS_INVALID_CID ) ||
  1412. ( Status == STATUS_PORT_DISCONNECTED ) )
  1413. {
  1414. //
  1415. // This is a special status returned by the LPC layer to indicate
  1416. // that the client thread has disappeared, or the process is
  1417. // terminating. Set a flag to indicate this:
  1418. //
  1419. ClientInfo->ClientFlags |= SECPKG_CLIENT_THREAD_TERMINATED ;
  1420. CallInfo->CallInfo.Attributes |= SECPKG_CALL_THREAD_TERM ;
  1421. //
  1422. // Check the process. If the process has started to exit, set that
  1423. // flag as well.
  1424. //
  1425. ExtraStatus = NtQueryInformationProcess(
  1426. pSession->hProcess,
  1427. ProcessTimes,
  1428. &Times,
  1429. sizeof( Times ),
  1430. NULL );
  1431. if ( NT_SUCCESS( ExtraStatus ) )
  1432. {
  1433. if ( Times.ExitTime.QuadPart != 0 )
  1434. {
  1435. ClientInfo->ClientFlags |= SECPKG_CLIENT_PROCESS_TERMINATED ;
  1436. CallInfo->CallInfo.Attributes |= SECPKG_CALL_PROCESS_TERM ;
  1437. }
  1438. }
  1439. DebugLog(( DEB_TRACE, "Client %x.%x has terminated\n",
  1440. ClientInfo->ProcessID, ClientInfo->ThreadID ));
  1441. return STATUS_SUCCESS ;
  1442. }
  1443. }
  1444. else
  1445. {
  1446. Thread = NtCurrentThread();
  1447. }
  1448. if (!NT_SUCCESS(Status))
  1449. {
  1450. DebugLog((DEB_WARN,"Failed to impersonate client: 0x%x\n",Status));
  1451. return(Status);
  1452. }
  1453. Status = NtOpenThreadToken(
  1454. Thread,
  1455. TOKEN_QUERY,
  1456. TRUE, // use LSA security context
  1457. &ClientToken
  1458. );
  1459. if (NT_SUCCESS(Status))
  1460. {
  1461. ClientInfo->Restricted = ( IsTokenRestricted(ClientToken) != 0 );
  1462. Status = NtQueryInformationToken(
  1463. ClientToken,
  1464. TokenStatistics,
  1465. (PVOID) &TokenStats,
  1466. TokenStatsSize,
  1467. &TokenStatsSize
  1468. );
  1469. NtClose(ClientToken);
  1470. if (NT_SUCCESS(Status))
  1471. {
  1472. ClientInfo->LogonId = TokenStats.AuthenticationId;
  1473. ClientInfo->Impersonating = (TokenStats.TokenType == TokenPrimary) ? FALSE : TRUE;
  1474. if( ClientInfo->Impersonating )
  1475. {
  1476. ClientInfo->ImpersonationLevel = TokenStats.ImpersonationLevel;
  1477. } else {
  1478. ClientInfo->ImpersonationLevel = SecurityImpersonation;
  1479. }
  1480. }
  1481. }
  1482. RevertToSelf();
  1483. if ( Thread != NtCurrentThread() )
  1484. {
  1485. NtClose( Thread );
  1486. }
  1487. if(NT_SUCCESS(Status))
  1488. {
  1489. CallInfo->LogonId = ClientInfo->LogonId;
  1490. CallInfo->Restricted = ClientInfo->Restricted;
  1491. CallInfo->Impersonating = ClientInfo->Impersonating;
  1492. CallInfo->ImpersonationLevel = ClientInfo->ImpersonationLevel;
  1493. CallInfo->CachedTokenInfo = TRUE;
  1494. }
  1495. return(Status);
  1496. }
  1497. else
  1498. {
  1499. ClientInfo->ProcessID = GetCurrentProcessId();
  1500. ClientInfo->ThreadID = GetCurrentThreadId();
  1501. ClientInfo->HasTcbPrivilege = TRUE;
  1502. ClientInfo->Impersonating = FALSE;
  1503. ClientInfo->ImpersonationLevel = SecurityImpersonation;
  1504. ClientInfo->LogonId = SystemLogonId;
  1505. return(STATUS_SUCCESS);
  1506. }
  1507. }
  1508. //+---------------------------------------------------------------------------
  1509. //
  1510. // Function: LsapGetCallInfo
  1511. //
  1512. // Synopsis: Gets call information
  1513. //
  1514. // Arguments: [Info] --
  1515. //
  1516. // History: 10-06-96 RichardW Created
  1517. //
  1518. // Notes:
  1519. //
  1520. //----------------------------------------------------------------------------
  1521. BOOLEAN
  1522. LsapGetCallInfo(
  1523. PSECPKG_CALL_INFO Info
  1524. )
  1525. {
  1526. PLSA_CALL_INFO CallInfo ;
  1527. CallInfo = LsapGetCurrentCall() ;
  1528. if ( CallInfo )
  1529. {
  1530. *Info = CallInfo->CallInfo ;
  1531. if ( CallInfo->InProcCall )
  1532. {
  1533. Info->Attributes |= SECPKG_CALL_IN_PROC ;
  1534. }
  1535. return TRUE ;
  1536. } else {
  1537. Info->ProcessId = GetCurrentProcessId();
  1538. Info->ThreadId = GetCurrentThreadId();
  1539. Info->Attributes = SECPKG_CALL_IN_PROC |
  1540. SECPKG_CALL_IS_TCB ;
  1541. Info->CallCount = 0;
  1542. return TRUE;
  1543. }
  1544. }
  1545. //+-------------------------------------------------------------------------
  1546. //
  1547. // Function: LsapMapClientBuffer
  1548. //
  1549. // Synopsis: Maps a client's SecBuffer into the caller's address space
  1550. //
  1551. // Effects: Clears the SECBUFFER_UNMAPPED field of the BufferType of
  1552. // the return SecBuffer
  1553. //
  1554. // Arguments:
  1555. //
  1556. // Requires:
  1557. //
  1558. // Returns:
  1559. //
  1560. // Notes: Doesn't modify pOutput until the end, so it is o.k. to pass
  1561. // the same thing for pInput and pOutput.
  1562. //
  1563. //
  1564. //--------------------------------------------------------------------------
  1565. NTSTATUS
  1566. LsapMapClientBuffer(
  1567. IN PSecBuffer pInput,
  1568. OUT PSecBuffer pOutput
  1569. )
  1570. {
  1571. NTSTATUS Status = STATUS_SUCCESS ;
  1572. SecBuffer Output ;
  1573. Output = *pInput ;
  1574. PLSA_CALL_INFO CallInfo = LsapGetCurrentCall();
  1575. //
  1576. // If the buffer is already mapped or it doesn't exist (is NULL) we
  1577. // are done.
  1578. //
  1579. if (!(pInput->BufferType & SECBUFFER_UNMAPPED) ||
  1580. (!pInput->cbBuffer))
  1581. {
  1582. return( STATUS_SUCCESS );
  1583. }
  1584. else
  1585. {
  1586. Output.BufferType &= ~SECBUFFER_UNMAPPED;
  1587. }
  1588. if ( pInput->BufferType & SECBUFFER_KERNEL_MAP )
  1589. {
  1590. //
  1591. // This one is already in process space
  1592. //
  1593. if ( ( CallInfo->CallInfo.Attributes & SECPKG_CALL_KERNEL_MODE ) == 0 )
  1594. {
  1595. //
  1596. // If this call did not come from kernel mode with
  1597. // the kernel-pool flag set, then this is an attempted
  1598. // hack on the LSA. Reject it.
  1599. //
  1600. Status = STATUS_ACCESS_VIOLATION ;
  1601. }
  1602. else
  1603. {
  1604. //
  1605. // The buffer is already in memory. Mark the call as
  1606. // using kernel-pool memory, so we allocate correctly
  1607. // on the return.
  1608. //
  1609. CallInfo->Flags |= CALL_FLAG_KERNEL_POOL ;
  1610. DebugLog((DEB_TRACE_SPECIAL, "Kernel Pool Map at %p [%x,%x]\n",
  1611. Output.pvBuffer, Output.BufferType, Output.cbBuffer ));
  1612. }
  1613. }
  1614. else
  1615. {
  1616. Output.pvBuffer = LsapAllocateLsaHeap( Output.cbBuffer );
  1617. if ( Output.pvBuffer != NULL )
  1618. {
  1619. Status = LsapCopyFromClient(
  1620. pInput->pvBuffer,
  1621. Output.pvBuffer,
  1622. Output.cbBuffer );
  1623. if ( !NT_SUCCESS( Status ) )
  1624. {
  1625. //
  1626. // STATUS_ACCESS_VIOLATION most likely due to STATUS_INVALID_PARAMETER
  1627. //
  1628. if (STATUS_ACCESS_VIOLATION == Status)
  1629. {
  1630. Status = STATUS_INVALID_PARAMETER;
  1631. }
  1632. LsapFreeLsaHeap(Output.pvBuffer);
  1633. }
  1634. }
  1635. else
  1636. {
  1637. Status = STATUS_NO_MEMORY ;
  1638. }
  1639. }
  1640. if ( NT_SUCCESS( Status ) )
  1641. {
  1642. *pOutput = Output ;
  1643. }
  1644. return( Status );
  1645. }
  1646. //+-------------------------------------------------------------------------
  1647. //
  1648. // Function: LsaICallPackage
  1649. //
  1650. // Synopsis: Function to call another security package
  1651. //
  1652. // Effects:
  1653. //
  1654. // Arguments:
  1655. //
  1656. // Requires:
  1657. //
  1658. // Returns:
  1659. //
  1660. // Notes:
  1661. //
  1662. //
  1663. //--------------------------------------------------------------------------
  1664. extern "C"
  1665. NTSTATUS
  1666. LsaICallPackage(
  1667. IN PUNICODE_STRING AuthenticationPackage,
  1668. IN PVOID ProtocolSubmitBuffer,
  1669. IN ULONG SubmitBufferLength,
  1670. OUT PVOID *ProtocolReturnBuffer,
  1671. OUT PULONG ReturnBufferLength,
  1672. OUT PNTSTATUS ProtocolStatus
  1673. )
  1674. {
  1675. return LsaICallPackageEx( AuthenticationPackage,
  1676. ProtocolSubmitBuffer, // client buffer base is same as local buffer
  1677. ProtocolSubmitBuffer,
  1678. SubmitBufferLength,
  1679. ProtocolReturnBuffer,
  1680. ReturnBufferLength,
  1681. ProtocolStatus );
  1682. }
  1683. //+-------------------------------------------------------------------------
  1684. //
  1685. // Function: LsaICallPackageEx
  1686. //
  1687. // Synopsis: Function to call another security package
  1688. //
  1689. // Effects:
  1690. //
  1691. // Arguments:
  1692. //
  1693. // Requires:
  1694. //
  1695. // Returns:
  1696. //
  1697. // Notes:
  1698. //
  1699. //
  1700. //--------------------------------------------------------------------------
  1701. extern "C"
  1702. NTSTATUS
  1703. LsaICallPackageEx(
  1704. IN PUNICODE_STRING AuthenticationPackage,
  1705. IN PVOID ClientBufferBase,
  1706. IN PVOID ProtocolSubmitBuffer,
  1707. IN ULONG SubmitBufferLength,
  1708. OUT PVOID *ProtocolReturnBuffer,
  1709. OUT PULONG ReturnBufferLength,
  1710. OUT PNTSTATUS ProtocolStatus
  1711. )
  1712. {
  1713. NTSTATUS Status = STATUS_SUCCESS;
  1714. PLSAP_SECURITY_PACKAGE Package;
  1715. PSession OldSession;
  1716. ULONG_PTR OldPackageId;
  1717. Package = SpmpLookupPackageAndRequest(
  1718. AuthenticationPackage,
  1719. SP_ORDINAL_CALLPACKAGE
  1720. );
  1721. if (Package == NULL)
  1722. {
  1723. DebugLog((DEB_WARN,"LsapCallPackage failed: package %wZ not found\n",
  1724. AuthenticationPackage ));
  1725. Status = STATUS_NO_SUCH_PACKAGE;
  1726. goto Cleanup;
  1727. }
  1728. //
  1729. // Set the session to be the LSA's so calls to allocate memory
  1730. // will allocate in the correct process
  1731. //
  1732. OldSession = GetCurrentSession();
  1733. SetCurrentSession( pDefaultSession );
  1734. //
  1735. // Set the package id
  1736. //
  1737. OldPackageId = GetCurrentPackageId();
  1738. SetCurrentPackageId(Package->dwPackageID);
  1739. //
  1740. // Call into the security package.
  1741. //
  1742. Status = Package->FunctionTable.CallPackage(
  1743. NULL,
  1744. ProtocolSubmitBuffer,
  1745. ClientBufferBase,
  1746. SubmitBufferLength,
  1747. ProtocolReturnBuffer,
  1748. ReturnBufferLength,
  1749. ProtocolStatus
  1750. );
  1751. //
  1752. // Restore the original package id
  1753. //
  1754. SetCurrentPackageId(OldPackageId);
  1755. //
  1756. // Restore our original session
  1757. //
  1758. SetCurrentSession( OldSession );
  1759. Cleanup:
  1760. return(Status);
  1761. }
  1762. //+-------------------------------------------------------------------------
  1763. //
  1764. // Function: LsaICallPackagePassthrough
  1765. //
  1766. // Synopsis: Function to call another security package for pass-through request
  1767. //
  1768. // Effects:
  1769. //
  1770. // Arguments:
  1771. //
  1772. // Requires:
  1773. //
  1774. // Returns:
  1775. //
  1776. // Notes:
  1777. //
  1778. //
  1779. //--------------------------------------------------------------------------
  1780. extern "C"
  1781. NTSTATUS
  1782. LsaICallPackagePassthrough(
  1783. IN PUNICODE_STRING AuthenticationPackage,
  1784. IN PVOID ClientBufferBase,
  1785. IN PVOID ProtocolSubmitBuffer,
  1786. IN ULONG SubmitBufferLength,
  1787. OUT PVOID *ProtocolReturnBuffer,
  1788. OUT PULONG ReturnBufferLength,
  1789. OUT PNTSTATUS ProtocolStatus
  1790. )
  1791. {
  1792. NTSTATUS Status = STATUS_SUCCESS;
  1793. PLSAP_SECURITY_PACKAGE Package;
  1794. PSession OldSession;
  1795. Package = SpmpLookupPackageAndRequest(
  1796. AuthenticationPackage,
  1797. SP_ORDINAL_CALLPACKAGE
  1798. );
  1799. if (Package == NULL)
  1800. {
  1801. DebugLog((DEB_WARN,"LsapCallPackage failed: package %wZ not found\n",
  1802. AuthenticationPackage ));
  1803. Status = STATUS_NO_SUCH_PACKAGE;
  1804. goto Cleanup;
  1805. }
  1806. //
  1807. // Set the session to be the LSA's so calls to allocate memory
  1808. // will allocate in the correct process
  1809. //
  1810. OldSession = GetCurrentSession();
  1811. SetCurrentSession( pDefaultSession );
  1812. Status = Package->FunctionTable.CallPackagePassthrough(
  1813. NULL,
  1814. ProtocolSubmitBuffer,
  1815. ClientBufferBase,
  1816. SubmitBufferLength,
  1817. ProtocolReturnBuffer,
  1818. ReturnBufferLength,
  1819. ProtocolStatus
  1820. );
  1821. //
  1822. // Restore our original session
  1823. //
  1824. SetCurrentSession( OldSession );
  1825. Cleanup:
  1826. return(Status);
  1827. }
  1828. extern "C"
  1829. VOID
  1830. LsaIFreeReturnBuffer(
  1831. IN PVOID Buffer
  1832. )
  1833. /*++
  1834. Routine Description:
  1835. Some of the LSA authentication services allocate memory buffers to
  1836. hold returned information. This service is used to free those buffers
  1837. when no longer needed.
  1838. Arguments:
  1839. Buffer - Supplies a pointer to the return buffer to be freed.
  1840. Return Status:
  1841. STATUS_SUCCESS - Indicates the service completed successfully.
  1842. Others - returned by NtFreeVirtualMemory().
  1843. --*/
  1844. {
  1845. SIZE_T Length;
  1846. Length = 0;
  1847. DebugLog(( DEB_TRACE_HELPERS, "LsaIFreeReturnBuffer - freeing VM at %x\n", Buffer ));
  1848. if (((ULONG_PTR) Buffer & 0xfff) != 0)
  1849. {
  1850. DbgPrint("Freeing non-page address: %p\n",Buffer);
  1851. DbgBreakPoint();
  1852. }
  1853. NtFreeVirtualMemory(
  1854. NtCurrentProcess(),
  1855. &Buffer,
  1856. &Length,
  1857. MEM_RELEASE
  1858. );
  1859. }
  1860. NTSTATUS
  1861. LsaClientCallback(
  1862. PCHAR Callback,
  1863. ULONG_PTR Argument1,
  1864. ULONG_PTR Argument2,
  1865. PSecBuffer Input,
  1866. PSecBuffer Output
  1867. )
  1868. {
  1869. PSession Session ;
  1870. ULONG Type ;
  1871. Session = GetCurrentSession();
  1872. if ( !Session )
  1873. {
  1874. Session = pDefaultSession ;
  1875. }
  1876. if ( !Session->hPort &&
  1877. ((Session->fSession & SESFLAG_DEFAULT) == 0) )
  1878. {
  1879. return SEC_E_INVALID_HANDLE ;
  1880. }
  1881. if ( (ULONG_PTR) Callback < 0x00010000 )
  1882. {
  1883. Type = SPM_CALLBACK_PACKAGE ;
  1884. }
  1885. else
  1886. {
  1887. Type = SPM_CALLBACK_EXPORT ;
  1888. }
  1889. return LsapClientCallback( Session,
  1890. Type,
  1891. Callback,
  1892. (PVOID) Argument1,
  1893. (PVOID) Argument2,
  1894. Input,
  1895. Output );
  1896. }
  1897. //+-------------------------------------------------------------------------
  1898. //
  1899. // Function: LsapUpdateCredentials
  1900. //
  1901. // Synopsis: This function provides a mechanism for one package to notify
  1902. // another package that the credentials for a logon session
  1903. // have changed.
  1904. //
  1905. // Effects:
  1906. //
  1907. // Arguments: PrimaryCredentials - Primary information about the user.
  1908. // All fields may be NULL but the LogonId
  1909. // Credentials - Array of credentials for different packages
  1910. //
  1911. // Requires:
  1912. //
  1913. // Returns:
  1914. //
  1915. // Notes:
  1916. //
  1917. //
  1918. //--------------------------------------------------------------------------
  1919. NTSTATUS
  1920. LsapUpdateCredentials(
  1921. IN PSECPKG_PRIMARY_CRED PrimaryCredentials,
  1922. IN OPTIONAL PSECPKG_SUPPLEMENTAL_CRED_ARRAY Credentials
  1923. )
  1924. {
  1925. return(LsapUpdateCredentialsWorker(
  1926. (SECURITY_LOGON_TYPE) 0, // no logon type
  1927. NULL, // no account name
  1928. PrimaryCredentials,
  1929. Credentials ));
  1930. }
  1931. //+-------------------------------------------------------------------------
  1932. //
  1933. // Function: LsapUpdateCredentialsWorker
  1934. //
  1935. // Synopsis: Worker function for updated credentials - calls all package
  1936. // with specified credentials
  1937. //
  1938. // Effects:
  1939. //
  1940. // Arguments:
  1941. //
  1942. // Requires:
  1943. //
  1944. // Returns:
  1945. //
  1946. // Notes:
  1947. //
  1948. //
  1949. //--------------------------------------------------------------------------
  1950. NTSTATUS
  1951. LsapUpdateCredentialsWorker(
  1952. IN SECURITY_LOGON_TYPE LogonType,
  1953. IN PUNICODE_STRING AccountName,
  1954. IN PSECPKG_PRIMARY_CRED PrimaryCredentials,
  1955. IN OPTIONAL PSECPKG_SUPPLEMENTAL_CRED_ARRAY Credentials
  1956. )
  1957. {
  1958. NTSTATUS Status;
  1959. ULONG_PTR CurrentPackageId;
  1960. PLSAP_SECURITY_PACKAGE SupplementalPackage;
  1961. SupplementalPackage = SpmpIteratePackagesByRequest( NULL, SP_ORDINAL_ACCEPTCREDS );
  1962. CurrentPackageId = GetCurrentPackageId();
  1963. while (SupplementalPackage)
  1964. {
  1965. if (SupplementalPackage->dwPackageID != CurrentPackageId)
  1966. {
  1967. ULONG Index;
  1968. PSECPKG_SUPPLEMENTAL_CRED SuppCreds;
  1969. //
  1970. // For all packages, do the accept call so the
  1971. // package can associate the credentials with
  1972. // the logon session.
  1973. //
  1974. DebugLog((DEB_TRACE_WAPI, "Whacking package %ws with %x:%x = %wZ\n",
  1975. SupplementalPackage->Name.Buffer,
  1976. PrimaryCredentials->LogonId.HighPart, PrimaryCredentials->LogonId.LowPart,
  1977. AccountName));
  1978. SetCurrentPackageId( SupplementalPackage->dwPackageID );
  1979. //
  1980. // Find any supplmental credentials
  1981. //
  1982. SuppCreds = NULL;
  1983. if (Credentials != NULL)
  1984. {
  1985. for (Index = 0; Index < Credentials->CredentialCount ; Index++ ) {
  1986. if (RtlEqualUnicodeString(
  1987. &Credentials->Credentials[Index].PackageName,
  1988. &SupplementalPackage->Name,
  1989. TRUE))
  1990. {
  1991. SuppCreds = &Credentials->Credentials[Index];
  1992. break;
  1993. }
  1994. }
  1995. }
  1996. __try
  1997. {
  1998. Status = SupplementalPackage->FunctionTable.AcceptCredentials(
  1999. LogonType,
  2000. AccountName,
  2001. PrimaryCredentials,
  2002. SuppCreds
  2003. );
  2004. }
  2005. __except (SP_EXCEPTION)
  2006. {
  2007. Status = GetExceptionCode();
  2008. Status = SPException(Status, SupplementalPackage->dwPackageID);
  2009. }
  2010. // Note: if an exception occurs, we don't fail the logon, we just
  2011. // do the magic on the package that blew. If the package blows,
  2012. // the other packages may succeed, and so the user may not be able
  2013. // to use that provider.
  2014. }
  2015. SupplementalPackage = SpmpIteratePackagesByRequest(
  2016. SupplementalPackage,
  2017. SP_ORDINAL_ACCEPTCREDS
  2018. );
  2019. }
  2020. return(STATUS_SUCCESS);
  2021. }