Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3431 lines
85 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1991 - 1992
  6. //
  7. // File: Logons.c
  8. //
  9. // Contents: Logon Session lists and so forth
  10. //
  11. // Functions InitLogonSessions
  12. // AddLogonSession
  13. // LocateLogonSession
  14. //
  15. //
  16. // History: 27 Oct 92 RichardW Created
  17. //
  18. //------------------------------------------------------------------------
  19. #include <lsapch.hxx>
  20. extern "C"
  21. {
  22. #include <ntrmlsa.h>
  23. #include "sidcache.h"
  24. #include <adtp.h>
  25. #include <secext.h>
  26. #include <lm.h> // NetApiBufferFree
  27. NTSTATUS LsapInitializeCredentials();
  28. }
  29. #define THIRTY_MIN { 0x30E23400, 0x00000004 }
  30. #define NEVER_MIN { 0xFFFFFFFF, 0x7FFFFFFF }
  31. RTL_CRITICAL_SECTION LogonSessionListLock ;
  32. PVOID LogonSessionTable ;
  33. PHANDLE_PACKAGE LogonSessionPackage ;
  34. LIST_ENTRY LogonSessionList ;
  35. ULONG LogonSessionCount ;
  36. PLSAP_DS_NAME_MAP LocalSystemNameMap ;
  37. // #define LOGON_SESSION_TRACK 1
  38. #ifdef LOGON_SESSION_TRACK
  39. HANDLE LogonSessionLog ;
  40. #endif
  41. extern "C"
  42. VOID LogonSessionLogWrite( PCHAR Format, ... );
  43. #ifdef LOGON_SESSION_TRACK
  44. #define LSLog( x ) LogonSessionLogWrite x
  45. #else
  46. #define LSLog( x )
  47. #endif
  48. LARGE_INTEGER LsapNameLifespans[ LSAP_MAX_DS_NAMES ] =
  49. {
  50. THIRTY_MIN, // Unknown
  51. THIRTY_MIN, // FQDN (CN=yada, DC=yada)
  52. NEVER_MIN, // SAM Compatible
  53. THIRTY_MIN, // Display (Fred Smith)
  54. THIRTY_MIN, // unused
  55. THIRTY_MIN, // unused
  56. NEVER_MIN, // GUID
  57. THIRTY_MIN, // Canonical
  58. THIRTY_MIN, // UPN
  59. THIRTY_MIN, // Canonical Ex
  60. THIRTY_MIN, // SPN
  61. NEVER_MIN, // unused (by GetUserNameEx)
  62. NEVER_MIN // DNS domain name
  63. };
  64. BOOL
  65. LsapSetSamAccountNameForLogonSession(
  66. PLSAP_LOGON_SESSION LogonSession
  67. );
  68. NTSTATUS
  69. LsapGetFormatsForLogon(
  70. PLSAP_LOGON_SESSION LogonSession,
  71. IN LPWSTR Domain,
  72. IN LPWSTR Name,
  73. IN ULONG NameType,
  74. OUT PLSAP_DS_NAME_MAP * Map
  75. );
  76. NTSTATUS
  77. LsapCreateDnsNameFromCanonicalName(
  78. IN PLSAP_LOGON_SESSION LogonSession,
  79. IN ULONG NameType,
  80. OUT PLSAP_DS_NAME_MAP * Map
  81. );
  82. #ifdef LOGON_SESSION_TRACK
  83. VOID
  84. LogonSessionLogWrite(
  85. PCHAR Format,
  86. ...
  87. )
  88. {
  89. CHAR Buffer[ 256 ];
  90. va_list ArgList ;
  91. int TotalSize ;
  92. ULONG SizeWritten ;
  93. if ( LogonSessionLog == NULL )
  94. {
  95. return;
  96. }
  97. va_start( ArgList, Format );
  98. if ((TotalSize = _vsnprintf(Buffer,
  99. sizeof(Buffer),
  100. Format, ArgList)) < 0)
  101. {
  102. return;
  103. }
  104. WriteFile( LogonSessionLog, Buffer, TotalSize, &SizeWritten, NULL );
  105. }
  106. VOID
  107. LsapInitLogonSessionLog(
  108. VOID
  109. )
  110. {
  111. WCHAR Path[ MAX_PATH ];
  112. ExpandEnvironmentStrings(L"%SystemRoot%\\Debug\\logonsession.log", Path, MAX_PATH );
  113. LogonSessionLog = CreateFile( Path, GENERIC_WRITE, FILE_SHARE_READ,
  114. NULL, CREATE_ALWAYS, 0, NULL );
  115. if ( LogonSessionLog == INVALID_HANDLE_VALUE )
  116. {
  117. LogonSessionLog = NULL ;
  118. return ;
  119. }
  120. LogonSessionLogWrite( "New LogonSession log created\n" );
  121. }
  122. #endif
  123. ULONG LogonFormats[] =
  124. {
  125. NameFullyQualifiedDN, // needed for GPO
  126. // NameSamCompatible, // needed for GPO but always have locally
  127. NameUniqueId // needed for GPO
  128. };
  129. BOOLEAN
  130. LsapIsNameFormatUsedForLogon(
  131. IN ULONG NameType
  132. )
  133. {
  134. ULONG i;
  135. for ( i = 0; i < (sizeof(LogonFormats)/sizeof(LogonFormats[0])); i++) {
  136. if ( NameType == LogonFormats[i] ) {
  137. return TRUE;
  138. }
  139. }
  140. return FALSE;
  141. }
  142. VOID
  143. LsapDerefDsNameMap(
  144. PLSAP_DS_NAME_MAP Map
  145. )
  146. {
  147. BOOLEAN FreeMap = FALSE;
  148. RtlEnterCriticalSection( &LogonSessionListLock );
  149. Map->RefCount-- ;
  150. if ( Map->RefCount == 0 )
  151. {
  152. FreeMap = TRUE;
  153. }
  154. RtlLeaveCriticalSection( &LogonSessionListLock );
  155. if( FreeMap )
  156. {
  157. LsapFreePrivateHeap( Map );
  158. }
  159. }
  160. PLSAP_DS_NAME_MAP
  161. LsapCreateDsNameMap(
  162. PUNICODE_STRING Name,
  163. ULONG NameType
  164. )
  165. {
  166. LSAP_DS_NAME_MAP * Map ;
  167. LARGE_INTEGER Now ;
  168. PLARGE_INTEGER Lifespan ;
  169. Map = (PLSAP_DS_NAME_MAP) LsapAllocatePrivateHeap(
  170. sizeof( LSAP_DS_NAME_MAP ) + Name->Length + sizeof(WCHAR) );
  171. if ( Map )
  172. {
  173. Lifespan = &LsapNameLifespans[ NameType ];
  174. if ( Lifespan->QuadPart != 0x7FFFFFFFFFFFFFFF )
  175. {
  176. GetSystemTimeAsFileTime( (LPFILETIME) &Now );
  177. Map->ExpirationTime.QuadPart = Now.QuadPart + Lifespan->QuadPart ;
  178. }
  179. else
  180. {
  181. Map->ExpirationTime.QuadPart = Lifespan->QuadPart ;
  182. }
  183. Map->RefCount = 1 ;
  184. Map->Name.Buffer = (PWSTR) ( Map + 1 );
  185. Map->Name.MaximumLength = (USHORT) ( Name->Length + sizeof(WCHAR) );
  186. Map->Name.Length = Name->Length ;
  187. RtlCopyMemory( Map->Name.Buffer,
  188. Name->Buffer,
  189. Name->Length );
  190. Map->Name.Buffer[ Map->Name.Length / sizeof( WCHAR )] = L'\0';
  191. }
  192. return Map ;
  193. }
  194. //+---------------------------------------------------------------------------
  195. //
  196. // Function: LsapLogonSessionDelete
  197. //
  198. // Synopsis: Callback invoked when record is to be deleted.
  199. //
  200. // Arguments: [Handle] --
  201. // [Context] --
  202. //
  203. // History: 8-17-98 RichardW Created
  204. //
  205. // Notes:
  206. //
  207. //----------------------------------------------------------------------------
  208. VOID
  209. LsapLogonSessionDelete(
  210. PSecHandle Handle,
  211. PVOID Context,
  212. ULONG RefCount
  213. )
  214. {
  215. PLSAP_LOGON_SESSION LogonSession ;
  216. ULONG i;
  217. LogonSession = (PLSAP_LOGON_SESSION) Context ;
  218. if (LsapAuditSuccessfulLogons && (LogonSession->UserSid != NULL))
  219. {
  220. LsapAdtAuditLogoff( LogonSession );
  221. }
  222. RtlEnterCriticalSection( &LogonSessionListLock );
  223. RemoveEntryList( &LogonSession->List );
  224. LogonSessionCount-- ;
  225. RtlLeaveCriticalSection( &LogonSessionListLock );
  226. LSLog(( "Deleting logon session %x:%x\n",
  227. LogonSession->LogonId.HighPart,
  228. LogonSession->LogonId.LowPart ));
  229. for ( i = 0 ; i < LSAP_MAX_DS_NAMES ; i++ )
  230. {
  231. if ( LogonSession->DsNames[ i ] )
  232. {
  233. LsapDerefDsNameMap( LogonSession->DsNames[ i ] );
  234. LogonSession->DsNames[ i ] = NULL ;
  235. }
  236. }
  237. LsapAuLogonTerminatedPackages( &LogonSession->LogonId );
  238. if ( LogonSession->Packages )
  239. {
  240. LsapFreePackageCredentialList( LogonSession->Packages );
  241. }
  242. if ( LogonSession->UserSid )
  243. {
  244. LsapDbReleaseLogonNameFromCache( LogonSession->UserSid );
  245. LsapFreeLsaHeap( LogonSession->UserSid );
  246. }
  247. if ( LogonSession->ProfilePath.Buffer )
  248. {
  249. LsapFreeLsaHeap( LogonSession->ProfilePath.Buffer );
  250. }
  251. if ( LogonSession->AuthorityName.Buffer )
  252. {
  253. LsapFreeLsaHeap( LogonSession->AuthorityName.Buffer );
  254. }
  255. if ( LogonSession->AccountName.Buffer )
  256. {
  257. LsapFreeLsaHeap( LogonSession->AccountName.Buffer );
  258. }
  259. if( LogonSession->LogonServer.Buffer )
  260. {
  261. LsapFreePrivateHeap( LogonSession->LogonServer.Buffer );
  262. }
  263. if ( LogonSession->TokenHandle != NULL )
  264. {
  265. NtClose( LogonSession->TokenHandle );
  266. }
  267. if ( LogonSession->LicenseHandle != INVALID_HANDLE_VALUE )
  268. {
  269. LsaFreeLicenseHandle( LogonSession->LicenseHandle );
  270. }
  271. CredpDereferenceCredSets( &LogonSession->CredentialSets );
  272. LsapFreePrivateHeap( Context );
  273. }
  274. NTSTATUS
  275. LsapCreateLsaLogonSession(
  276. IN PLUID Luid,
  277. OUT PLSAP_LOGON_SESSION * pLogonSession
  278. )
  279. {
  280. PLSAP_LOGON_SESSION LogonSession ;
  281. SecHandle Handle ;
  282. LogonSession = (PLSAP_LOGON_SESSION) LsapAllocatePrivateHeap(
  283. sizeof( LSAP_LOGON_SESSION ) );
  284. *pLogonSession = LogonSession ;
  285. if ( LogonSession )
  286. {
  287. LSLog(( "Creating logon session %x:%x\n",
  288. Luid->HighPart, Luid->LowPart ));
  289. RtlZeroMemory( LogonSession, sizeof( LSAP_LOGON_SESSION ) );
  290. LogonSession->LogonId = *Luid ;
  291. GetSystemTimeAsFileTime( (LPFILETIME) &LogonSession->LogonTime );
  292. LsapConvertLuidToSecHandle( Luid, &Handle );
  293. if ( LogonSessionPackage->AddHandle(
  294. LogonSessionTable,
  295. &Handle,
  296. LogonSession,
  297. 0 ) )
  298. {
  299. RtlEnterCriticalSection( &LogonSessionListLock );
  300. InsertHeadList( &LogonSessionList, &LogonSession->List );
  301. LogonSessionCount++ ;
  302. RtlLeaveCriticalSection( &LogonSessionListLock );
  303. return STATUS_SUCCESS ;
  304. }
  305. else
  306. {
  307. LsapFreePrivateHeap( LogonSession );
  308. }
  309. return STATUS_UNSUCCESSFUL ;
  310. }
  311. return STATUS_NO_MEMORY ;
  312. }
  313. BOOLEAN
  314. LsapLogonSessionInitialize(
  315. VOID
  316. )
  317. {
  318. LUID LocalSystem = SYSTEM_LUID ;
  319. PLSAP_LOGON_SESSION LogonSession ;
  320. PLSAPR_POLICY_DNS_DOMAIN_INFO DnsDomainInfo = NULL;
  321. PLSAP_DS_NAME_MAP NameMap = NULL;
  322. NTSTATUS Status ;
  323. HANDLE ProcessToken;
  324. Status = LsapInitializeCredentials();
  325. if (!NT_SUCCESS(Status))
  326. {
  327. return FALSE;
  328. }
  329. Status = RtlInitializeCriticalSection( &LogonSessionListLock );
  330. if (!NT_SUCCESS(Status))
  331. {
  332. return FALSE;
  333. }
  334. InitializeListHead( &LogonSessionList );
  335. if ( LsaTuningParameters.Options & TUNE_SRV_HIGH_PRIORITY )
  336. {
  337. LogonSessionPackage = &LargeHandlePackage ;
  338. }
  339. else
  340. {
  341. LogonSessionPackage = &SmallHandlePackage ;
  342. }
  343. #ifdef LOGON_SESSION_TRACK
  344. LsapInitLogonSessionLog();
  345. LogonSessionPackage = &LargeHandlePackage ;
  346. #endif
  347. if ( LogonSessionPackage->Initialize() )
  348. {
  349. LogonSessionTable = LogonSessionPackage->Create(
  350. HANDLE_PACKAGE_CALLBACK_ON_DELETE |
  351. HANDLE_PACKAGE_REQUIRE_UNIQUE,
  352. NULL,
  353. LsapLogonSessionDelete );
  354. if ( LogonSessionTable == NULL )
  355. {
  356. return FALSE ;
  357. }
  358. }
  359. else
  360. {
  361. return FALSE ;
  362. }
  363. //
  364. // Now, create the initial logon session for local system:
  365. //
  366. Status = LsapCreateLsaLogonSession(
  367. &LocalSystem,
  368. &LogonSession );
  369. if ( !NT_SUCCESS( Status ) )
  370. {
  371. return FALSE ;
  372. }
  373. Status = LsapDuplicateString(
  374. &LogonSession->AccountName,
  375. LsapDbWellKnownSidName(LsapLocalSystemSidIndex) );
  376. if ( !NT_SUCCESS( Status ) )
  377. {
  378. return FALSE ;
  379. }
  380. Status = LsapDuplicateString(
  381. &LogonSession->AuthorityName,
  382. LsapDbWellKnownSidDescription(LsapLocalSystemSidIndex) );
  383. if ( !NT_SUCCESS( Status ) )
  384. {
  385. return FALSE ;
  386. }
  387. Status = LsapDuplicateSid(
  388. &LogonSession->UserSid,
  389. LsapLocalSystemSid );
  390. if ( !NT_SUCCESS( Status ) )
  391. {
  392. return FALSE ;
  393. }
  394. LogonSession->LogonType = (SECURITY_LOGON_TYPE) 0 ;
  395. LogonSession->LicenseHandle = INVALID_HANDLE_VALUE ;
  396. //
  397. // Store the NT4 name away separately:
  398. //
  399. LsapSetSamAccountNameForLogonSession( LogonSession );
  400. if ( LogonSession->DsNames[ NameSamCompatible ] )
  401. {
  402. LocalSystemNameMap = LogonSession->DsNames[ NameSamCompatible ];
  403. LogonSession->DsNames[ NameSamCompatible ] = NULL ;
  404. }
  405. //
  406. // Add the DNS domain name for the machine account
  407. //
  408. Status = LsaIQueryInformationPolicyTrusted(PolicyDnsDomainInformation,
  409. (PLSAPR_POLICY_INFORMATION *) &DnsDomainInfo);
  410. if (NT_SUCCESS(Status))
  411. {
  412. //
  413. // No other threads around -- just jam the name in the logon session directly
  414. //
  415. NameMap = LsapCreateDsNameMap( (PUNICODE_STRING) &DnsDomainInfo->DnsDomainName,
  416. NameDnsDomain );
  417. LogonSession->DsNames[ NameDnsDomain ] = NameMap;
  418. //
  419. // Free the primary domain info
  420. //
  421. LsaIFree_LSAPR_POLICY_INFORMATION(PolicyDnsDomainInformation,
  422. (PLSAPR_POLICY_INFORMATION) DnsDomainInfo);
  423. }
  424. //
  425. // Grab a token handle for the logon session
  426. //
  427. Status = NtOpenProcessToken(
  428. NtCurrentProcess(),
  429. TOKEN_DUPLICATE|TOKEN_QUERY,
  430. &ProcessToken );
  431. if (NT_SUCCESS( Status )) {
  432. Status = LsapSetSessionToken( ProcessToken, &LocalSystem );
  433. NtClose( ProcessToken );
  434. if ( !NT_SUCCESS( Status ) ) {
  435. return FALSE ;
  436. }
  437. }
  438. //
  439. // Init System Logon will update the names appropriately.
  440. //
  441. return TRUE ;
  442. }
  443. NTSTATUS
  444. LsapCreateLogonSession(
  445. IN OUT PLUID LogonId
  446. )
  447. /*++
  448. Routine Description:
  449. This function adds a new logon session to the list of logon sessions.
  450. This service acquires the AuLock.
  451. Arguments:
  452. LogonId - The ID to assign to the new logon session. If it is zero,
  453. a new logon ID will be created.
  454. Return Value:
  455. STATUS_SUCCESS - The logon session has been successfully deleted.
  456. STATUS_LOGON_SESSION_COLLISION - The specified Logon ID is already in
  457. use by another logon session.
  458. STATUS_QUOTA_EXCEEDED - The request could not be fulfilled due to
  459. memory quota limitations.
  460. --*/
  461. {
  462. NTSTATUS Status;
  463. PLSAP_LOGON_SESSION NewSession;
  464. PLSA_CALL_INFO CallInfo ;
  465. SecHandle Handle ;
  466. //
  467. // Create a logon Id if it has not already been don
  468. //
  469. if (LogonId->LowPart == 0 && LogonId->HighPart == 0)
  470. {
  471. Status = NtAllocateLocallyUniqueId(LogonId);
  472. ASSERT(NT_SUCCESS(Status));
  473. }
  474. Status = LsapCreateLsaLogonSession(
  475. LogonId,
  476. &NewSession );
  477. if ( !NT_SUCCESS( Status ) )
  478. {
  479. return Status ;
  480. }
  481. NewSession->CreatingPackage = GetCurrentPackageId();
  482. RtlCopyLuid( &NewSession->LogonId, LogonId );
  483. CallInfo = LsapGetCurrentCall();
  484. if (CallInfo != NULL)
  485. {
  486. NewSession->Process = CallInfo->CallInfo.ProcessId ;
  487. if ( CallInfo->Message->ApiMessage.dwAPI == SPMAPI_AcceptContext )
  488. {
  489. NewSession->ContextAttr = CallInfo->Message->ApiMessage.Args.SpmArguments.API.AcceptContext.fContextReq ;
  490. }
  491. }
  492. //
  493. // Tell the reference monitor about the logon session...
  494. //
  495. Status = LsapCallRm(
  496. RmCreateLogonSession,
  497. (PVOID)LogonId,
  498. (ULONG)sizeof(LUID),
  499. NULL,
  500. 0
  501. );
  502. if ( !NT_SUCCESS(Status) ) {
  503. LsapConvertLuidToSecHandle( LogonId, &Handle );
  504. LogonSessionPackage->DeleteHandle(
  505. LogonSessionTable,
  506. &Handle,
  507. FALSE );
  508. return Status;
  509. }
  510. return STATUS_SUCCESS;
  511. }
  512. NTSTATUS
  513. LsapGetLogonSessionAccountInfo (
  514. IN PLUID LogonId,
  515. OUT PUNICODE_STRING AccountName,
  516. OUT PUNICODE_STRING AuthorityName
  517. )
  518. /*++
  519. Routine Description:
  520. This function retrieves username and authentication domain information
  521. for a specified logon session.
  522. Arguments:
  523. LogonId - The ID of the logon session to set.
  524. AccountName - points to a unicode string with no buffer. A buffer
  525. containing the account name will be allocated and returned
  526. using the PROCESS HEAP - NOT THE LSA HEAP.
  527. AuthorityName - points to a unicode string with no buffer. A buffer
  528. containing the authority name will be allocated and returned
  529. using the PROCESS HEAP - NOT THE LSA HEAP.
  530. Return Value:
  531. STATUS_NO_SUCH_LOGON_SESSION - The specified logon session does
  532. not currently exist.
  533. STATUS_NO_MEMORY - Could not allocate enough process heap.
  534. --*/
  535. {
  536. NTSTATUS Status;
  537. PLSAP_LOGON_SESSION LogonSession;
  538. SecHandle Handle ;
  539. AccountName->Length = 0;
  540. AccountName->Buffer = NULL;
  541. AccountName->MaximumLength = 0;
  542. AuthorityName->Length = 0;
  543. AuthorityName->Buffer = NULL;
  544. AuthorityName->MaximumLength = 0;
  545. LsapConvertLuidToSecHandle( LogonId, &Handle );
  546. LogonSession = (PLSAP_LOGON_SESSION) LogonSessionPackage->GetHandleContext(
  547. LogonSessionTable,
  548. &Handle );
  549. if ( !LogonSession )
  550. {
  551. return STATUS_NO_SUCH_LOGON_SESSION ;
  552. }
  553. Status = STATUS_SUCCESS ;
  554. if ( LogonSession->AccountName.Buffer )
  555. {
  556. Status = LsapDuplicateString( AccountName, &LogonSession->AccountName );
  557. }
  558. if ( LogonSession->AuthorityName.Buffer )
  559. {
  560. Status = LsapDuplicateString( AuthorityName, &LogonSession->AuthorityName );
  561. }
  562. LogonSessionPackage->ReleaseContext(
  563. LogonSessionTable,
  564. &Handle );
  565. return(Status);
  566. }
  567. BOOL
  568. LsapSetSamAccountNameForLogonSession(
  569. PLSAP_LOGON_SESSION LogonSession
  570. )
  571. {
  572. UNICODE_STRING CombinedName ;
  573. if ( LogonSession->AccountName.Buffer &&
  574. LogonSession->AuthorityName.Buffer )
  575. {
  576. CombinedName.Buffer = (PWSTR) LsapAllocatePrivateHeap(
  577. LogonSession->AccountName.Length +
  578. LogonSession->AuthorityName.Length +
  579. sizeof( WCHAR ) * 2 );
  580. if ( CombinedName.Buffer )
  581. {
  582. CombinedName.MaximumLength = LogonSession->AccountName.Length +
  583. LogonSession->AuthorityName.Length +
  584. sizeof( WCHAR ) * 2 ;
  585. CombinedName.Length = CombinedName.MaximumLength - 2 ;
  586. RtlCopyMemory( CombinedName.Buffer,
  587. LogonSession->AuthorityName.Buffer,
  588. LogonSession->AuthorityName.Length );
  589. CombinedName.Buffer[ LogonSession->AuthorityName.Length / sizeof(WCHAR) ] = L'\\';
  590. RtlCopyMemory( &CombinedName.Buffer[ LogonSession->AuthorityName.Length / sizeof( WCHAR ) + 1],
  591. LogonSession->AccountName.Buffer,
  592. LogonSession->AccountName.Length );
  593. CombinedName.Buffer[ CombinedName.Length / sizeof(WCHAR) ] = L'\0';
  594. LogonSession->DsNames[ NameSamCompatible ] =
  595. LsapCreateDsNameMap(
  596. &CombinedName,
  597. NameSamCompatible );
  598. LsapFreePrivateHeap( CombinedName.Buffer );
  599. }
  600. }
  601. return ( LogonSession->DsNames[ NameSamCompatible ] != NULL );
  602. }
  603. NTSTATUS
  604. LsapSetLogonSessionAccountInfo (
  605. IN PLUID LogonId,
  606. IN PUNICODE_STRING AccountName,
  607. IN PUNICODE_STRING AuthorityName,
  608. IN OPTIONAL PUNICODE_STRING ProfilePath,
  609. IN PSID * pUserSid,
  610. IN SECURITY_LOGON_TYPE LogonType,
  611. IN PSECPKG_PRIMARY_CRED PrimaryCredentials OPTIONAL
  612. )
  613. /*++
  614. Routine Description:
  615. This function sets username and authentication domain information
  616. for a specified logon session.
  617. The current account name and authority name, if any, will be freed.
  618. However, if this is the system logon session the information won't
  619. be set.
  620. Arguments:
  621. LogonId - The ID of the logon session to set.
  622. AccountName - points to a unicode string containing the account name
  623. to be assigned to the logon session. Both the UNICODE_STRING
  624. structure and the buffer pointed to by that structure are expected
  625. to be allocated from lsa heap, and they will eventually be freed
  626. to that heap when no longer needed.
  627. AuthorityName - points to a unicode string containing the name of the
  628. authenticating authority of the logon session. Both the
  629. UNICODE_STRING structure and the buffer pointed to by that structure
  630. are expected to be allocated from lsa heap, and they will eventually
  631. be freed to that heap when no longer needed.
  632. ProfilePath - points to a unicode string containing the path to the
  633. user's profile. The structure & buffer need to be freed.
  634. Return Value:
  635. STATUS_NO_SUCH_LOGON_SESSION - The specified logon session does
  636. not currently exist.
  637. --*/
  638. {
  639. NTSTATUS Status;
  640. PLSAP_LOGON_SESSION LogonSession;
  641. SecHandle Handle ;
  642. UNICODE_STRING NullString = { 0 };
  643. ULONG i ;
  644. UNICODE_STRING CombinedName ;
  645. PWSTR OldAccountName = NULL;
  646. PWSTR OldProfilePath = NULL;
  647. PWSTR OldAuthorityName = NULL;
  648. PSID OldUserSid = NULL;
  649. PWSTR OldLogonServer = NULL;
  650. UNICODE_STRING LogonServer;
  651. BOOL fAccountNameChanged = TRUE;
  652. BOOL fAuthorityNameChanged = TRUE;
  653. BOOL fUserSidChanged = TRUE;
  654. LogonServer.Buffer = NULL;
  655. Status = STATUS_NO_SUCH_LOGON_SESSION;
  656. ASSERT( pUserSid );
  657. LsapConvertLuidToSecHandle( LogonId, &Handle );
  658. LogonSession = (PLSAP_LOGON_SESSION) LogonSessionPackage->GetHandleContext(
  659. LogonSessionTable,
  660. &Handle );
  661. if ( !LogonSession )
  662. {
  663. return STATUS_NO_SUCH_LOGON_SESSION ;
  664. }
  665. //
  666. // Get a Credential Set for this session.
  667. //
  668. if ( ( ( LogonType == Interactive ) ||
  669. ( LogonType == Batch ) ||
  670. ( LogonType == Service ) ||
  671. ( LogonType == CachedInteractive ) ||
  672. ( LogonType == RemoteInteractive ) ) &&
  673. ( *pUserSid != NULL ) ) {
  674. Status = CredpCreateCredSets( *pUserSid,
  675. AuthorityName,
  676. &LogonSession->CredentialSets );
  677. if ( !NT_SUCCESS(Status) ) {
  678. LogonSessionPackage->ReleaseContext(
  679. LogonSessionTable,
  680. &Handle );
  681. return Status;
  682. }
  683. }
  684. Status = STATUS_SUCCESS;
  685. if( PrimaryCredentials != NULL )
  686. {
  687. if( PrimaryCredentials->LogonServer.Buffer )
  688. {
  689. LogonServer.Buffer = (PWSTR)LsapAllocatePrivateHeap( PrimaryCredentials->LogonServer.Length );
  690. if( LogonServer.Buffer != NULL )
  691. {
  692. CopyMemory( LogonServer.Buffer,
  693. PrimaryCredentials->LogonServer.Buffer,
  694. PrimaryCredentials->LogonServer.Length
  695. );
  696. LogonServer.Length = PrimaryCredentials->LogonServer.Length;
  697. LogonServer.MaximumLength = LogonServer.Length;
  698. }
  699. }
  700. }
  701. RtlEnterCriticalSection( &LogonSessionListLock );
  702. for ( i = 0 ; i < LSAP_MAX_DS_NAMES ; i++ )
  703. {
  704. //
  705. // Save the names that were prepopulated by the auth package.
  706. // SAM name is restored further down.
  707. //
  708. if ( LogonSession->DsNames[ i ]
  709. &&
  710. (i != NameDisplay)
  711. &&
  712. (i != NameUserPrincipal)
  713. &&
  714. (i != NameDnsDomain))
  715. {
  716. LsapDerefDsNameMap( LogonSession->DsNames[ i ] );
  717. LogonSession->DsNames[ i ] = NULL ;
  718. }
  719. }
  720. //
  721. // Free current names if necessary. Since LsapDbAddLogonNameToCache is
  722. // called outside the scope of the LogonSessionListLock, there's a potential
  723. // race condition when multiple threads call LsaLogonUser for LocalService
  724. // or NetworkService (since they always use the same logon session). To
  725. // avoid this, don't update the parameters in the logon session unless
  726. // the incoming parameters are different from those already in the session.
  727. // Do this only for the parameters LsapDbAddLogonNameToCache uses (account
  728. // name, authority name, and user SID).
  729. //
  730. if (LogonSession->AccountName.Buffer != NULL)
  731. {
  732. if (RtlCompareUnicodeString(&LogonSession->AccountName,
  733. AccountName,
  734. TRUE) == 0)
  735. {
  736. fAccountNameChanged = FALSE;
  737. OldAccountName = AccountName->Buffer;
  738. //
  739. // Caller will try to free the buffer again if non-NULL
  740. //
  741. AccountName->Buffer = NULL;
  742. }
  743. else
  744. {
  745. OldAccountName = LogonSession->AccountName.Buffer;
  746. }
  747. }
  748. if (LogonSession->AuthorityName.Buffer != NULL)
  749. {
  750. if (RtlCompareUnicodeString(&LogonSession->AuthorityName,
  751. AuthorityName,
  752. TRUE) == 0)
  753. {
  754. fAuthorityNameChanged = FALSE;
  755. OldAuthorityName = AuthorityName->Buffer;
  756. //
  757. // Caller will try to free the buffer again if non-NULL
  758. //
  759. AuthorityName->Buffer = NULL;
  760. }
  761. else
  762. {
  763. OldAuthorityName = LogonSession->AuthorityName.Buffer;
  764. }
  765. }
  766. if (LogonSession->ProfilePath.Buffer != NULL)
  767. {
  768. OldProfilePath = LogonSession->ProfilePath.Buffer;
  769. }
  770. if (LogonSession->UserSid != NULL)
  771. {
  772. if (RtlEqualSid(LogonSession->UserSid,
  773. *pUserSid))
  774. {
  775. fUserSidChanged = FALSE;
  776. OldUserSid = *pUserSid;
  777. //
  778. // NULL out to make sure UserSid isn't
  779. // used again down below.
  780. //
  781. *pUserSid = NULL;
  782. }
  783. else
  784. {
  785. OldUserSid = LogonSession->UserSid;
  786. }
  787. }
  788. //
  789. // Assign the new names - they may be null
  790. //
  791. if (fAccountNameChanged)
  792. {
  793. if ( AccountName )
  794. {
  795. LogonSession->AccountName = *AccountName;
  796. }
  797. else
  798. {
  799. LogonSession->AccountName = NullString ;
  800. }
  801. }
  802. if (fAuthorityNameChanged)
  803. {
  804. if ( AuthorityName )
  805. {
  806. LogonSession->AuthorityName = *AuthorityName;
  807. }
  808. else
  809. {
  810. LogonSession->AuthorityName = NullString ;
  811. }
  812. }
  813. if ( ProfilePath )
  814. {
  815. LogonSession->ProfilePath = *ProfilePath;
  816. }
  817. else
  818. {
  819. LogonSession->ProfilePath = NullString ;
  820. }
  821. if (fUserSidChanged)
  822. {
  823. LogonSession->UserSid = *pUserSid;
  824. *pUserSid = NULL;
  825. }
  826. LogonSession->LogonType = LogonType;
  827. if( LogonServer.Buffer )
  828. {
  829. OldLogonServer = LogonSession->LogonServer.Buffer;
  830. LogonSession->LogonServer = LogonServer;
  831. }
  832. LsapSetSamAccountNameForLogonSession( LogonSession );
  833. RtlLeaveCriticalSection( &LogonSessionListLock );
  834. if ( LogonSession->UserSid &&
  835. LogonSession->AccountName.Buffer &&
  836. LogonSession->AuthorityName.Buffer )
  837. {
  838. LsapDbAddLogonNameToCache(
  839. &LogonSession->AccountName,
  840. &LogonSession->AuthorityName,
  841. LogonSession->UserSid );
  842. }
  843. LogonSessionPackage->ReleaseContext(
  844. LogonSessionTable,
  845. &Handle );
  846. if( OldAccountName )
  847. {
  848. LsapFreeLsaHeap( OldAccountName );
  849. }
  850. if( OldAuthorityName )
  851. {
  852. LsapFreeLsaHeap( OldAuthorityName );
  853. }
  854. if( OldProfilePath )
  855. {
  856. LsapFreeLsaHeap( OldProfilePath );
  857. }
  858. if( OldUserSid )
  859. {
  860. LsapFreeLsaHeap( OldUserSid );
  861. }
  862. if( OldLogonServer )
  863. {
  864. LsapFreePrivateHeap( OldLogonServer );
  865. }
  866. return(Status);
  867. }
  868. NTSTATUS
  869. LsapLogonSessionDeletedWrkr(
  870. IN PLSA_COMMAND_MESSAGE CommandMessage,
  871. OUT PLSA_REPLY_MESSAGE ReplyMessage
  872. )
  873. /*++
  874. Routine Description:
  875. This function is called by the reference monitor (via LPC) when the
  876. reference count on a logon session drops to zero. This indicates that
  877. the logon session is no longer needed. This is technically when the
  878. user is considered (from a security standpoint) to be logged out.
  879. Arguments:
  880. CommandMessage - Pointer to structure containing LSA command message
  881. information consisting of an LPC PORT_MESSAGE structure followed
  882. by the command number (LsapComponentTestCommand).
  883. The command-specific portion of this parameter contains the
  884. LogonId (LUID) of the logon session whose reference count
  885. has dropped to zero.
  886. ReplyMessage - Pointer to structure containing LSA reply message
  887. information consisting of an LPC PORT_MESSAGE structure followed
  888. by the command ReturnedStatus field in which a status code from the
  889. command will be returned.
  890. Return Value:
  891. None.
  892. --*/
  893. {
  894. NTSTATUS Status;
  895. LUID LogonId;
  896. SecHandle Handle ;
  897. //
  898. // Check that command is expected type
  899. //
  900. ASSERT( CommandMessage->CommandNumber == LsapLogonSessionDeletedCommand );
  901. //
  902. // Typecast the command parameter to what we expect.
  903. //
  904. LogonId = *((LUID *) CommandMessage->CommandParams);
  905. LsapConvertLuidToSecHandle( &LogonId, &Handle );
  906. LogonSessionPackage->DeleteHandle(
  907. LogonSessionTable,
  908. &Handle,
  909. FALSE );
  910. UNREFERENCED_PARAMETER(ReplyMessage); // Intentionally not referenced
  911. return( STATUS_SUCCESS );
  912. }
  913. PLSAP_LOGON_SESSION
  914. LsapLocateLogonSession(
  915. PLUID LogonId
  916. )
  917. {
  918. SecHandle Handle ;
  919. PLSAP_LOGON_SESSION LogonSession ;
  920. LsapConvertLuidToSecHandle( LogonId, &Handle );
  921. LogonSession = (PLSAP_LOGON_SESSION) LogonSessionPackage->GetHandleContext(
  922. LogonSessionTable,
  923. &Handle );
  924. return LogonSession ;
  925. }
  926. VOID
  927. LsapReleaseLogonSession(
  928. PLSAP_LOGON_SESSION LogonSession
  929. )
  930. {
  931. SecHandle Handle ;
  932. LsapConvertLuidToSecHandle( &LogonSession->LogonId, &Handle );
  933. LogonSessionPackage->ReleaseContext(
  934. LogonSessionTable,
  935. &Handle );
  936. }
  937. NTSTATUS
  938. LsapDeleteLogonSession (
  939. IN PLUID LogonId
  940. )
  941. /*++
  942. Routine Description:
  943. This function deletes a logon session context record. It is expected
  944. that no TOKEN objects were ever created within this logon session.
  945. This means we must inform the Reference Monitor to clean up its
  946. information on the logon session.
  947. If TOKEN objecs were created within this logon session, then deletion
  948. of those tokens will cause the logon session to be deleted.
  949. This service acquires the AuLock.
  950. Arguments:
  951. LogonId - The ID of the logon session to delete.
  952. Return Value:
  953. STATUS_SUCCESS - The logon session has been successfully deleted.
  954. STATUS_NO_SUCH_LOGON_SESSION - The specified logon session doesn't
  955. exist.
  956. STATUS_BAD_LOGON_SESSION_STATE - The logon session is not in a state
  957. that allows it to be deleted. This is typically an indication
  958. that the logon session has had a token created within it, and it
  959. may no longer be explicitly deleted.
  960. --*/
  961. {
  962. PLSAP_LOGON_SESSION LogonSession ;
  963. SecHandle Handle;
  964. NTSTATUS Status ;
  965. Status = LsapCallRm(
  966. RmDeleteLogonSession,
  967. (PVOID)LogonId,
  968. (ULONG)sizeof(LUID),
  969. NULL,
  970. 0
  971. );
  972. if ( !NT_SUCCESS(Status)) {
  973. DebugLog(( DEB_ERROR, "LSA/RM DeleteLogonSession failed, %x\n", Status ));
  974. }
  975. LsapConvertLuidToSecHandle( LogonId, &Handle );
  976. LogonSessionPackage->DeleteHandle(
  977. LogonSessionTable,
  978. &Handle,
  979. FALSE );
  980. return STATUS_SUCCESS ;
  981. }
  982. PLSAP_DS_NAME_MAP
  983. LsapGetNameForLocalSystem(
  984. VOID
  985. )
  986. {
  987. PLSAP_DS_NAME_MAP Map ;
  988. RtlEnterCriticalSection( &LogonSessionListLock );
  989. Map = LocalSystemNameMap ;
  990. LocalSystemNameMap->RefCount++ ;
  991. RtlLeaveCriticalSection( &LogonSessionListLock );
  992. return Map ;
  993. }
  994. NTSTATUS
  995. LsapGetNameForLogonSession(
  996. PLSAP_LOGON_SESSION LogonSession,
  997. ULONG NameType,
  998. PLSAP_DS_NAME_MAP * Map,
  999. BOOL LocalOnly
  1000. )
  1001. {
  1002. NTSTATUS Status ;
  1003. PLSAP_DS_NAME_MAP NameMap ;
  1004. LARGE_INTEGER Now ;
  1005. WCHAR TranslatedNameBuffer[ MAX_PATH ];
  1006. ULONG TranslatedNameLength ;
  1007. PWSTR TranslatedName = NULL ;
  1008. UNICODE_STRING TransName ;
  1009. PLSAP_DS_NAME_MAP SamMap ;
  1010. BOOL TranslateStatus;
  1011. BOOL Flush = FALSE ;
  1012. DWORD Options ;
  1013. WCHAR * AuthorityName = NULL;
  1014. WCHAR * SamMapName = NULL;
  1015. BOOLEAN NeedToImpersonate = TRUE;
  1016. BOOL NeedDnsDomainName = FALSE;
  1017. BOOL GotComputerName = FALSE;
  1018. *Map = NULL ;
  1019. Options = NameType & SPM_NAME_OPTION_MASK ;
  1020. NameType &= (~SPM_NAME_OPTION_MASK );
  1021. if ( Options & SPM_NAME_OPTION_FLUSH )
  1022. {
  1023. Flush = TRUE ;
  1024. }
  1025. if ( NameType >= LSAP_MAX_DS_NAMES )
  1026. {
  1027. return STATUS_INVALID_PARAMETER ;
  1028. }
  1029. GetSystemTimeAsFileTime( (LPFILETIME) &Now );
  1030. //
  1031. // Check for format/account combinations that have no chance
  1032. // of succeeding (e.g., DS formats for local-only accounts)
  1033. // to avoid hitting the network. Do this outside of the
  1034. // critical region since the LUID is a read-only field.
  1035. //
  1036. if (NameType == NameUniqueId)
  1037. {
  1038. LUID LocalServiceLuid = LOCALSERVICE_LUID;
  1039. LUID NetworkServiceLuid = NETWORKSERVICE_LUID;
  1040. if (RtlEqualLuid(&LogonSession->LogonId,
  1041. &LocalServiceLuid)
  1042. ||
  1043. RtlEqualLuid(&LogonSession->LogonId,
  1044. &NetworkServiceLuid))
  1045. {
  1046. return STATUS_NO_SUCH_DOMAIN;
  1047. }
  1048. }
  1049. RtlEnterCriticalSection( &LogonSessionListLock );
  1050. if ( LogonSession->DsNames[ NameType ] )
  1051. {
  1052. NameMap = LogonSession->DsNames[ NameType ];
  1053. if ( ( NameMap->ExpirationTime.QuadPart >= Now.QuadPart ) &&
  1054. ( !Flush ) )
  1055. {
  1056. //
  1057. // Valid entry, bump the ref count and return it
  1058. //
  1059. NameMap->RefCount++ ;
  1060. RtlLeaveCriticalSection( &LogonSessionListLock );
  1061. *Map = NameMap ;
  1062. return STATUS_SUCCESS ;
  1063. }
  1064. //
  1065. // Entry has expired. Remove it, crack the name anew
  1066. //
  1067. LsapDerefDsNameMap( NameMap );
  1068. LogonSession->DsNames[ NameType ] = NULL ;
  1069. }
  1070. SamMap = LogonSession->DsNames[ NameSamCompatible ];
  1071. if ( SamMap == NULL )
  1072. {
  1073. LsapSetSamAccountNameForLogonSession( LogonSession );
  1074. SamMap = LogonSession->DsNames[ NameSamCompatible ] ;
  1075. if ( SamMap == NULL )
  1076. {
  1077. RtlLeaveCriticalSection( &LogonSessionListLock );
  1078. return STATUS_NO_MEMORY ;
  1079. }
  1080. }
  1081. //
  1082. // Not present, or it had expired. Crack from the beginning:
  1083. //
  1084. if ( NameType == NameSamCompatible )
  1085. {
  1086. *Map = SamMap ;
  1087. SamMap->RefCount++ ;
  1088. RtlLeaveCriticalSection( &LogonSessionListLock );
  1089. return STATUS_SUCCESS ;
  1090. }
  1091. else if ( NameType == NameDnsDomain )
  1092. {
  1093. //
  1094. // See if we're dealing with an NT4 domain, in which case we won't
  1095. // have a DNS domain name. If so, return ERROR_NONE_MAPPED for
  1096. // consistency and a way for the caller to know the DC is NT4.
  1097. //
  1098. if (!LocalOnly)
  1099. {
  1100. DWORD dwError;
  1101. PDOMAIN_CONTROLLER_INFO pDcInfo = NULL;
  1102. TranslatedNameLength = MAX_PATH ;
  1103. TranslatedName = TranslatedNameBuffer ;
  1104. GetComputerNameW( TranslatedName, &TranslatedNameLength );
  1105. RtlInitUnicodeString( &TransName, TranslatedName );
  1106. GotComputerName = TRUE;
  1107. //
  1108. // Don't hit the network for local logons.
  1109. //
  1110. if ( !RtlEqualUnicodeString( &LogonSession->AuthorityName,
  1111. &TransName,
  1112. TRUE ) )
  1113. {
  1114. if (LogonSession->AuthorityName.MaximumLength <= LogonSession->AuthorityName.Length ||
  1115. LogonSession->AuthorityName.Buffer[LogonSession->AuthorityName.Length / sizeof(WCHAR)] != L'\0')
  1116. {
  1117. AuthorityName = (LPWSTR) LsapAllocatePrivateHeap(LogonSession->AuthorityName.Length + sizeof( WCHAR ));
  1118. if (AuthorityName == NULL)
  1119. {
  1120. RtlLeaveCriticalSection( &LogonSessionListLock );
  1121. return STATUS_INSUFFICIENT_RESOURCES;
  1122. }
  1123. RtlCopyMemory(AuthorityName,
  1124. LogonSession->AuthorityName.Buffer,
  1125. LogonSession->AuthorityName.Length);
  1126. AuthorityName[LogonSession->AuthorityName.Length / sizeof( WCHAR )] = L'\0';
  1127. }
  1128. else
  1129. {
  1130. AuthorityName = LogonSession->AuthorityName.Buffer;
  1131. }
  1132. //
  1133. // Note that this perf hit is negligible for the non-NT4 case as the next call
  1134. // to DsGetDcName (in SecpTranslateName) will be satisfied from the cache. In
  1135. // the NT4 case, we'd otherwise drop into SecpTranslateName and make a failing
  1136. // DsGetDcName call there instead.
  1137. //
  1138. RtlLeaveCriticalSection(&LogonSessionListLock);
  1139. dwError = DsGetDcName(NULL,
  1140. AuthorityName,
  1141. NULL,
  1142. NULL,
  1143. DS_DIRECTORY_SERVICE_PREFERRED,
  1144. &pDcInfo);
  1145. RtlEnterCriticalSection(&LogonSessionListLock);
  1146. if (AuthorityName != LogonSession->AuthorityName.Buffer)
  1147. {
  1148. LsapFreePrivateHeap( AuthorityName );
  1149. }
  1150. AuthorityName = NULL;
  1151. //
  1152. // Recheck the name in case it was filled in while we
  1153. // were hitting the network.
  1154. //
  1155. if ( LogonSession->DsNames[ NameType ] )
  1156. {
  1157. NameMap = LogonSession->DsNames[ NameType ];
  1158. if ( ( NameMap->ExpirationTime.QuadPart >= Now.QuadPart ) &&
  1159. ( !Flush ) )
  1160. {
  1161. //
  1162. // Valid entry, bump the ref count and return it
  1163. //
  1164. NameMap->RefCount++ ;
  1165. RtlLeaveCriticalSection( &LogonSessionListLock );
  1166. *Map = NameMap ;
  1167. return STATUS_SUCCESS ;
  1168. }
  1169. //
  1170. // Entry has expired. Remove it, crack the name anew
  1171. //
  1172. LsapDerefDsNameMap( NameMap );
  1173. LogonSession->DsNames[ NameType ] = NULL ;
  1174. }
  1175. if (dwError != NO_ERROR)
  1176. {
  1177. RtlLeaveCriticalSection(&LogonSessionListLock);
  1178. //
  1179. // DsGetDcName doesn't set the last error. Set it now along
  1180. // with the last status value (first SetLastError sets the
  1181. // status value via RtlNtStatusToDosError).
  1182. //
  1183. SetLastError(RtlNtStatusToDosError(STATUS_UNSUCCESSFUL));
  1184. SetLastError(dwError);
  1185. return NtCurrentTeb()->LastStatusValue;
  1186. }
  1187. if (!(pDcInfo->Flags & DS_DS_FLAG))
  1188. {
  1189. //
  1190. // NT4 DC
  1191. //
  1192. RtlLeaveCriticalSection(&LogonSessionListLock);
  1193. NetApiBufferFree(pDcInfo);
  1194. return STATUS_NONE_MAPPED;
  1195. }
  1196. NetApiBufferFree(pDcInfo);
  1197. }
  1198. }
  1199. //
  1200. // Since NameDnsDomain is a GetUserNameEx construct, calling
  1201. // the DS for it will directly will fail. Ask the DS for the
  1202. // canonical name and on success, extract the DNS name below.
  1203. //
  1204. NeedDnsDomainName = TRUE;
  1205. NameType = NameCanonical;
  1206. //
  1207. // If the canonical name is already there, we don't
  1208. // need to hit the DS below.
  1209. //
  1210. if (LogonSession->DsNames[NameType])
  1211. {
  1212. Status = LsapCreateDnsNameFromCanonicalName(LogonSession, NameType, Map);
  1213. RtlLeaveCriticalSection(&LogonSessionListLock);
  1214. return Status;
  1215. }
  1216. //
  1217. // We may have the CanonicalEx name and not Canonical -- try that one too.
  1218. //
  1219. NameType = NameCanonicalEx;
  1220. if (LogonSession->DsNames[NameType])
  1221. {
  1222. Status = LsapCreateDnsNameFromCanonicalName(LogonSession, NameType, Map);
  1223. RtlLeaveCriticalSection(&LogonSessionListLock);
  1224. return Status;
  1225. }
  1226. //
  1227. // Otherwise fall through and hit the DS for the canonical name if allowed
  1228. //
  1229. if (LocalOnly)
  1230. {
  1231. RtlLeaveCriticalSection( &LogonSessionListLock );
  1232. return STATUS_NONE_MAPPED;
  1233. }
  1234. }
  1235. RtlLeaveCriticalSection( &LogonSessionListLock );
  1236. if (LocalOnly)
  1237. {
  1238. //
  1239. // We got this far and the name's not yet mapped. Since we
  1240. // can't hit the network, fail.
  1241. //
  1242. return STATUS_NONE_MAPPED;
  1243. }
  1244. if (!GotComputerName)
  1245. {
  1246. TranslatedNameLength = MAX_PATH ;
  1247. TranslatedName = TranslatedNameBuffer ;
  1248. GetComputerNameW( TranslatedName, &TranslatedNameLength );
  1249. RtlInitUnicodeString( &TransName, TranslatedName );
  1250. }
  1251. if ( RtlEqualUnicodeString( &LogonSession->AuthorityName,
  1252. &TransName,
  1253. TRUE ) )
  1254. {
  1255. //
  1256. // Local Logons don't get mapped names.
  1257. //
  1258. return STATUS_NONE_MAPPED ;
  1259. }
  1260. //
  1261. // Make sure AuthorityName and SamMapName are NULL-terminated.
  1262. // Create dynamically allocated copies if necessary.
  1263. //
  1264. if ( LogonSession->AuthorityName.MaximumLength <= LogonSession->AuthorityName.Length ||
  1265. LogonSession->AuthorityName.Buffer[LogonSession->AuthorityName.Length / sizeof(WCHAR)] != L'\0' ) {
  1266. AuthorityName = ( WCHAR * )LsapAllocatePrivateHeap( LogonSession->AuthorityName.Length + sizeof( WCHAR ));
  1267. if ( AuthorityName == NULL ) {
  1268. return STATUS_INSUFFICIENT_RESOURCES;
  1269. }
  1270. RtlCopyMemory( AuthorityName, LogonSession->AuthorityName.Buffer, LogonSession->AuthorityName.Length );
  1271. AuthorityName[LogonSession->AuthorityName.Length / sizeof( WCHAR )] = L'\0';
  1272. } else {
  1273. AuthorityName = LogonSession->AuthorityName.Buffer;
  1274. }
  1275. if ( SamMap->Name.MaximumLength <= SamMap->Name.Length ||
  1276. SamMap->Name.Buffer[SamMap->Name.Length / sizeof(WCHAR)] != L'\0' ) {
  1277. SamMapName = ( WCHAR * )LsapAllocatePrivateHeap( SamMap->Name.Length + sizeof( WCHAR ));
  1278. if ( SamMapName == NULL ) {
  1279. if ( AuthorityName != LogonSession->AuthorityName.Buffer ) {
  1280. LsapFreePrivateHeap( AuthorityName );
  1281. }
  1282. return STATUS_INSUFFICIENT_RESOURCES;
  1283. }
  1284. RtlCopyMemory( SamMapName, SamMap->Name.Buffer, SamMap->Name.Length );
  1285. SamMapName[SamMap->Name.Length / sizeof( WCHAR )] = L'\0';
  1286. } else {
  1287. SamMapName = SamMap->Name.Buffer;
  1288. }
  1289. //
  1290. // We are going to be hitting the wire; if this is a special
  1291. // known format, then optimize by calling DsCrackName to return
  1292. // the other popular formats. The cache will be seeded with
  1293. // the results and hence avoid calls in the future. This is
  1294. // done to improve logon performance.
  1295. //
  1296. if ( LsapIsNameFormatUsedForLogon( NameType ) ) {
  1297. Status = LsapGetFormatsForLogon( LogonSession,
  1298. AuthorityName,
  1299. SamMapName,
  1300. NameType,
  1301. Map );
  1302. if ( NT_SUCCESS( Status ) ) {
  1303. // we are done!
  1304. goto Exit;
  1305. } else {
  1306. // Ok -- go the slow way
  1307. Status = STATUS_SUCCESS;
  1308. }
  1309. }
  1310. Retry:
  1311. //
  1312. // Translate the name, in the caller's context
  1313. //
  1314. if ( NeedToImpersonate ) {
  1315. Status = LsapImpersonateClient();
  1316. if ( !NT_SUCCESS(Status) ) {
  1317. goto Exit;
  1318. }
  1319. }
  1320. TranslatedNameLength = MAX_PATH ;
  1321. TranslatedName = TranslatedNameBuffer ;
  1322. TranslateStatus = SecpTranslateName(
  1323. AuthorityName,
  1324. SamMapName,
  1325. NameSamCompatible,
  1326. (EXTENDED_NAME_FORMAT) NameType,
  1327. TranslatedName,
  1328. &TranslatedNameLength );
  1329. if ( !TranslateStatus )
  1330. {
  1331. Status = NtCurrentTeb()->LastStatusValue ;
  1332. if ( Status == STATUS_BUFFER_TOO_SMALL )
  1333. {
  1334. TranslatedName = (PWSTR) LsapAllocatePrivateHeap( TranslatedNameLength * sizeof( WCHAR ) );
  1335. if ( TranslatedName )
  1336. {
  1337. TranslateStatus = SecpTranslateName(
  1338. AuthorityName,
  1339. SamMapName,
  1340. NameSamCompatible,
  1341. (EXTENDED_NAME_FORMAT) NameType,
  1342. TranslatedName,
  1343. &TranslatedNameLength );
  1344. }
  1345. } else if ( NeedToImpersonate &&
  1346. NtCurrentTeb()->LastErrorValue == ERROR_ACCESS_DENIED ) {
  1347. //
  1348. // Fall back to machine creds and try again
  1349. //
  1350. RevertToSelf();
  1351. NeedToImpersonate = FALSE;
  1352. goto Retry;
  1353. }
  1354. }
  1355. if ( NeedToImpersonate ) {
  1356. RevertToSelf();
  1357. }
  1358. if ( TranslateStatus )
  1359. {
  1360. RtlEnterCriticalSection( &LogonSessionListLock );
  1361. if ( LogonSession->DsNames[ NameType ] )
  1362. {
  1363. //
  1364. // Someone else filled it in while we were out cracking
  1365. // it as well. Use theirs, discard ours:
  1366. //
  1367. NameMap = LogonSession->DsNames[ NameType ];
  1368. NameMap->RefCount++ ;
  1369. RtlLeaveCriticalSection( &LogonSessionListLock );
  1370. *Map = NameMap ;
  1371. if ( TranslatedName != TranslatedNameBuffer )
  1372. {
  1373. LsapFreePrivateHeap( TranslatedName );
  1374. }
  1375. Status = STATUS_SUCCESS;
  1376. goto Exit;
  1377. }
  1378. //
  1379. // SecpTranslateName returns length including the terminating NULL,
  1380. // so correct for that here
  1381. //
  1382. TransName.Buffer = TranslatedName ;
  1383. TransName.Length = (USHORT) (( TranslatedNameLength - 1 ) * sizeof(WCHAR));
  1384. TransName.MaximumLength = TransName.Length + sizeof( WCHAR );
  1385. NameMap = LsapCreateDsNameMap(
  1386. &TransName,
  1387. NameType );
  1388. if ( NameMap )
  1389. {
  1390. LogonSession->DsNames[ NameType ] = NameMap ;
  1391. NameMap->RefCount++ ;
  1392. RtlLeaveCriticalSection( &LogonSessionListLock );
  1393. *Map = NameMap ;
  1394. if ( TranslatedName != TranslatedNameBuffer )
  1395. {
  1396. LsapFreePrivateHeap( TranslatedName );
  1397. }
  1398. Status = STATUS_SUCCESS;
  1399. goto Exit;
  1400. }
  1401. else
  1402. {
  1403. RtlLeaveCriticalSection( &LogonSessionListLock );
  1404. Status = STATUS_NO_MEMORY ;
  1405. }
  1406. }
  1407. else
  1408. {
  1409. Status = NtCurrentTeb()->LastStatusValue ;
  1410. }
  1411. //
  1412. // If the DS couldn't map the UPN (e.g., the account has a default UPN), we can
  1413. // still potentially cruft up a UPN using <SAM account name>@<DNS domain name>
  1414. //
  1415. if (Status == STATUS_NONE_MAPPED && NameType == NameUserPrincipal)
  1416. {
  1417. RtlEnterCriticalSection( &LogonSessionListLock );
  1418. PLSAP_DS_NAME_MAP UsernameMap = LogonSession->DsNames[NameSamCompatible];
  1419. PLSAP_DS_NAME_MAP DnsNameMap = LogonSession->DsNames[NameDnsDomain];
  1420. if (UsernameMap != NULL && DnsNameMap != NULL)
  1421. {
  1422. UsernameMap->RefCount++;
  1423. DnsNameMap->RefCount++;
  1424. RtlLeaveCriticalSection( &LogonSessionListLock );
  1425. LPWSTR Upn;
  1426. LPWSTR Scan = wcschr(UsernameMap->Name.Buffer, L'\\');
  1427. ULONG Index;
  1428. if (Scan != NULL)
  1429. {
  1430. Scan++;
  1431. }
  1432. else
  1433. {
  1434. Scan = UsernameMap->Name.Buffer;
  1435. }
  1436. //
  1437. // SAM name is always NULL-terminated
  1438. //
  1439. Index = wcslen(Scan);
  1440. Upn = (LPWSTR) LsapAllocatePrivateHeap(Index * sizeof(WCHAR)
  1441. + DnsNameMap->Name.Length
  1442. + 2 * sizeof(WCHAR));
  1443. if (Upn != NULL)
  1444. {
  1445. UNICODE_STRING String;
  1446. wcsncpy(Upn, Scan, Index);
  1447. Upn[Index++] = L'@';
  1448. RtlCopyMemory(Upn + Index, DnsNameMap->Name.Buffer, DnsNameMap->Name.Length);
  1449. LsapDerefDsNameMap(UsernameMap);
  1450. LsapDerefDsNameMap(DnsNameMap);
  1451. RtlInitUnicodeString(&String, Upn);
  1452. *Map = LsapCreateDsNameMap(&String, NameType);
  1453. Status = (*Map == NULL ? STATUS_NO_MEMORY : STATUS_SUCCESS);
  1454. LsapFreePrivateHeap(Upn);
  1455. }
  1456. else
  1457. {
  1458. LsapDerefDsNameMap(UsernameMap);
  1459. LsapDerefDsNameMap(DnsNameMap);
  1460. Status = STATUS_NO_MEMORY;
  1461. }
  1462. }
  1463. else
  1464. {
  1465. RtlLeaveCriticalSection( &LogonSessionListLock );
  1466. }
  1467. }
  1468. if ( TranslatedName != TranslatedNameBuffer )
  1469. {
  1470. LsapFreePrivateHeap( TranslatedName );
  1471. }
  1472. Exit:
  1473. if (NeedDnsDomainName && NT_SUCCESS(Status))
  1474. {
  1475. //
  1476. // We successfully retrieved the canonical name but what we really
  1477. // want is the DnsDomainName -- extract it and add it to the session.
  1478. //
  1479. RtlEnterCriticalSection( &LogonSessionListLock );
  1480. //
  1481. // Another thread may have cracked the name before we got here.
  1482. //
  1483. NameMap = LogonSession->DsNames[ NameDnsDomain ];
  1484. if ( NameMap )
  1485. {
  1486. if ( ( NameMap->ExpirationTime.QuadPart >= Now.QuadPart ) &&
  1487. ( !Flush ) )
  1488. {
  1489. //
  1490. // Valid entry, bump the ref count and return it
  1491. //
  1492. NameMap->RefCount++ ;
  1493. *Map = NameMap ;
  1494. NeedDnsDomainName = FALSE ;
  1495. Status = STATUS_SUCCESS;
  1496. }
  1497. else
  1498. {
  1499. //
  1500. // Entry has expired. Remove it, crack the name anew
  1501. //
  1502. LsapDerefDsNameMap( NameMap );
  1503. LogonSession->DsNames[ NameDnsDomain ] = NULL ;
  1504. }
  1505. }
  1506. if (NeedDnsDomainName)
  1507. {
  1508. Status = LsapCreateDnsNameFromCanonicalName(LogonSession, NameType, Map);
  1509. //
  1510. // Since we just successfully created the canonical name map, its refcount
  1511. // has been bumped up. Undo that since we're really after the DnsDomainName
  1512. // (whose refcount was bumped up in LsapCreateDnsNameFromCanonicalName).
  1513. //
  1514. LogonSession->DsNames[NameType]->RefCount--;
  1515. }
  1516. RtlLeaveCriticalSection( &LogonSessionListLock );
  1517. NameType = NameDnsDomain;
  1518. }
  1519. if ( AuthorityName != LogonSession->AuthorityName.Buffer )
  1520. {
  1521. LsapFreePrivateHeap( AuthorityName );
  1522. }
  1523. if ( SamMap != NULL &&
  1524. SamMapName != SamMap->Name.Buffer )
  1525. {
  1526. LsapFreePrivateHeap( SamMapName );
  1527. }
  1528. return Status ;
  1529. }
  1530. NTSTATUS
  1531. WLsaEnumerateLogonSession(
  1532. PULONG Count,
  1533. PLUID * Sessions
  1534. )
  1535. {
  1536. PLUID Logons ;
  1537. PVOID LocalCopy ;
  1538. PLIST_ENTRY Scan ;
  1539. PLSAP_LOGON_SESSION LogonSession ;
  1540. PVOID ClientMemory ;
  1541. NTSTATUS Status ;
  1542. RtlEnterCriticalSection( &LogonSessionListLock );
  1543. Logons = (PLUID) LsapAllocatePrivateHeap( LogonSessionCount * sizeof( LUID ) );
  1544. if ( !Logons )
  1545. {
  1546. RtlLeaveCriticalSection( &LogonSessionListLock );
  1547. return STATUS_NO_MEMORY ;
  1548. }
  1549. *Count = LogonSessionCount ;
  1550. LocalCopy = Logons ;
  1551. Scan = LogonSessionList.Flink ;
  1552. while ( Scan != &LogonSessionList )
  1553. {
  1554. LogonSession = CONTAINING_RECORD( Scan, LSAP_LOGON_SESSION, List );
  1555. *Logons++ = LogonSession->LogonId ;
  1556. Scan = Scan->Flink ;
  1557. }
  1558. RtlLeaveCriticalSection( &LogonSessionListLock );
  1559. ClientMemory = LsapClientAllocate( *Count * sizeof( LUID ) );
  1560. if ( ClientMemory )
  1561. {
  1562. Status = LsapCopyToClient( LocalCopy,
  1563. ClientMemory,
  1564. *Count * sizeof( LUID ) );
  1565. *Sessions = (PLUID) ClientMemory ;
  1566. }
  1567. else
  1568. {
  1569. Status = STATUS_NO_MEMORY ;
  1570. }
  1571. LsapFreePrivateHeap( LocalCopy );
  1572. return Status ;
  1573. }
  1574. NTSTATUS
  1575. LsaIGetNbAndDnsDomainNames(
  1576. IN PUNICODE_STRING DomainName,
  1577. OUT PUNICODE_STRING DnsDomainName,
  1578. OUT PUNICODE_STRING NetbiosDomainName
  1579. )
  1580. /*++
  1581. Routine Description:
  1582. Get both the Netbios name and DNS name of a domain. DomainName must correspond to
  1583. the account domain of some user that is currently logged onto the system.
  1584. Arguments:
  1585. DomainName - Name of the Netbios or DNS domain to query.
  1586. DnsDomainName - Returns the DnsDomainName of the domain if DomainName is trusted.
  1587. DnsDomainName->Buffer will be zero terminated.
  1588. DnsDomainName->Buffer must be freed using LsaIFreeHeap.
  1589. NetbiosDomainName - Returns the Netbios domain name of the domain if DomainName is trusted.
  1590. NetbiosDomainName->Buffer will be zero terminated.
  1591. NetbiosDomainName->Buffer must be freed using LsaIFreeHeap.
  1592. Return Value:
  1593. STATUS_SUCCESS: The routine functioned properly.
  1594. DnsDomainName->Buffer and NetbiosDomainName->Buffer will return null if
  1595. the mapping isn't known.
  1596. --*/
  1597. {
  1598. PLUID Logons ;
  1599. PVOID LocalCopy ;
  1600. PLIST_ENTRY Scan ;
  1601. PLSAP_LOGON_SESSION LogonSession ;
  1602. PVOID ClientMemory ;
  1603. NTSTATUS Status ;
  1604. PUNICODE_STRING LocalDnsDomainName;
  1605. //
  1606. // Initialization
  1607. //
  1608. RtlInitUnicodeString( DnsDomainName, NULL );
  1609. RtlInitUnicodeString( NetbiosDomainName, NULL );
  1610. //
  1611. // Loop through the logon session list trying to find a match
  1612. //
  1613. Status = STATUS_SUCCESS;
  1614. RtlEnterCriticalSection( &LogonSessionListLock );
  1615. for ( Scan = LogonSessionList.Flink; Scan != &LogonSessionList; Scan = Scan->Flink ) {
  1616. LogonSession = CONTAINING_RECORD( Scan, LSAP_LOGON_SESSION, List );
  1617. //
  1618. // Ignore this entry unless both names are known
  1619. //
  1620. if (LogonSession->DsNames[NameDnsDomain] == NULL)
  1621. {
  1622. continue;
  1623. }
  1624. LocalDnsDomainName = &LogonSession->DsNames[NameDnsDomain]->Name;
  1625. if ( LocalDnsDomainName->Length == 0 ||
  1626. LogonSession->AuthorityName.Length == 0 )
  1627. {
  1628. continue;
  1629. }
  1630. //
  1631. // Compare the passed in name with the Netbios and DNS name on the entry
  1632. //
  1633. if ( (DomainName->Length == LogonSession->AuthorityName.Length &&
  1634. RtlEqualUnicodeString( DomainName,
  1635. &LogonSession->AuthorityName,
  1636. TRUE ) ) ||
  1637. (DomainName->Length == LocalDnsDomainName->Length &&
  1638. RtlEqualUnicodeString( DomainName,
  1639. LocalDnsDomainName,
  1640. TRUE ) ) ) {
  1641. //
  1642. // Grab the Dns domain name
  1643. //
  1644. DnsDomainName->Buffer = (LPWSTR) LsapAllocatePrivateHeapNoZero(
  1645. LocalDnsDomainName->Length +
  1646. sizeof(WCHAR) );
  1647. if ( DnsDomainName->Buffer == NULL ) {
  1648. Status = STATUS_INSUFFICIENT_RESOURCES;
  1649. break;
  1650. }
  1651. RtlCopyMemory( DnsDomainName->Buffer,
  1652. LocalDnsDomainName->Buffer,
  1653. LocalDnsDomainName->Length );
  1654. DnsDomainName->Buffer[LocalDnsDomainName->Length/sizeof(WCHAR)] = L'\0';
  1655. DnsDomainName->Length = LocalDnsDomainName->Length;
  1656. DnsDomainName->MaximumLength = LocalDnsDomainName->Length + sizeof(WCHAR);
  1657. //
  1658. // Grab the netbios domain name
  1659. //
  1660. NetbiosDomainName->Buffer = (LPWSTR) LsapAllocatePrivateHeapNoZero(
  1661. LogonSession->AuthorityName.Length +
  1662. sizeof(WCHAR) );
  1663. if ( NetbiosDomainName->Buffer == NULL ) {
  1664. LsapFreePrivateHeap( DnsDomainName->Buffer );
  1665. DnsDomainName->Buffer = NULL;
  1666. Status = STATUS_INSUFFICIENT_RESOURCES;
  1667. break;
  1668. }
  1669. RtlCopyMemory( NetbiosDomainName->Buffer,
  1670. LogonSession->AuthorityName.Buffer,
  1671. LogonSession->AuthorityName.Length );
  1672. NetbiosDomainName->Buffer[LogonSession->AuthorityName.Length/sizeof(WCHAR)] = L'\0';
  1673. NetbiosDomainName->Length = LogonSession->AuthorityName.Length;
  1674. NetbiosDomainName->MaximumLength = LogonSession->AuthorityName.Length + sizeof(WCHAR);
  1675. Status = STATUS_SUCCESS;
  1676. break;
  1677. }
  1678. }
  1679. RtlLeaveCriticalSection( &LogonSessionListLock );
  1680. return Status;
  1681. }
  1682. NTSTATUS
  1683. WLsaGetLogonSessionData(
  1684. PLUID LogonId,
  1685. PVOID * LogonData
  1686. )
  1687. {
  1688. PLSAP_LOGON_SESSION LogonSession;
  1689. ULONG Size ;
  1690. PVOID ClientBuffer ;
  1691. PUCHAR Offset ;
  1692. PUCHAR LocalOffset ;
  1693. NTSTATUS Status ;
  1694. PSECURITY_LOGON_SESSION_DATA Data = NULL;
  1695. PLSAP_SECURITY_PACKAGE Package ;
  1696. HANDLE Token ;
  1697. BOOL OkayToQuery = FALSE ;
  1698. PLSAP_DS_NAME_MAP DnsMap = NULL;
  1699. PLSAP_DS_NAME_MAP UpnMap = NULL;
  1700. LogonSession = LsapLocateLogonSession( LogonId );
  1701. if ( !LogonSession )
  1702. {
  1703. return STATUS_NO_SUCH_LOGON_SESSION ;
  1704. }
  1705. Status = LsapImpersonateClient();
  1706. if ( NT_SUCCESS( Status ) )
  1707. {
  1708. if ( LogonSession->UserSid == NULL ||
  1709. !CheckTokenMembership( NULL,
  1710. LogonSession->UserSid,
  1711. &OkayToQuery ) )
  1712. {
  1713. OkayToQuery = FALSE ;
  1714. }
  1715. if ( !OkayToQuery )
  1716. {
  1717. if ( !CheckTokenMembership( NULL,
  1718. LsapAliasAdminsSid,
  1719. &OkayToQuery ) )
  1720. {
  1721. OkayToQuery = FALSE ;
  1722. }
  1723. }
  1724. RevertToSelf();
  1725. }
  1726. if ( !OkayToQuery )
  1727. {
  1728. Status = STATUS_ACCESS_DENIED ;
  1729. }
  1730. if ( !NT_SUCCESS( Status ) )
  1731. {
  1732. LsapReleaseLogonSession( LogonSession );
  1733. return Status ;
  1734. }
  1735. Package = SpmpLocatePackage( LogonSession->CreatingPackage );
  1736. if ( !Package )
  1737. {
  1738. LsapReleaseLogonSession( LogonSession );
  1739. return STATUS_NO_SUCH_LOGON_SESSION ;
  1740. }
  1741. RtlEnterCriticalSection( &LogonSessionListLock );
  1742. UpnMap = LogonSession->DsNames[NameUserPrincipal];
  1743. if (UpnMap != NULL)
  1744. {
  1745. UpnMap->RefCount++;
  1746. }
  1747. DnsMap = LogonSession->DsNames[NameDnsDomain];
  1748. if (DnsMap != NULL)
  1749. {
  1750. DnsMap->RefCount++;
  1751. }
  1752. RtlLeaveCriticalSection( &LogonSessionListLock );
  1753. Size = sizeof( SECURITY_LOGON_SESSION_DATA ) +
  1754. LogonSession->AccountName.Length + sizeof( WCHAR ) +
  1755. LogonSession->AuthorityName.Length + sizeof( WCHAR ) +
  1756. Package->Name.Length + sizeof( WCHAR ) +
  1757. LogonSession->LogonServer.Length + sizeof(WCHAR) +
  1758. sizeof(WCHAR) + // DnsMap
  1759. sizeof(WCHAR) ; // UpnMap
  1760. if( DnsMap != NULL )
  1761. {
  1762. Size += DnsMap->Name.Length;
  1763. }
  1764. if( UpnMap != NULL )
  1765. {
  1766. Size += UpnMap->Name.Length;
  1767. }
  1768. if ( LogonSession->UserSid )
  1769. {
  1770. Size += RtlLengthSid( LogonSession->UserSid );
  1771. }
  1772. Data = (PSECURITY_LOGON_SESSION_DATA) LsapAllocatePrivateHeap( Size );
  1773. if ( !Data )
  1774. {
  1775. Status = STATUS_NO_MEMORY ;
  1776. goto Cleanup;
  1777. }
  1778. ClientBuffer = LsapClientAllocate( Size );
  1779. if ( !ClientBuffer )
  1780. {
  1781. Status = STATUS_NO_MEMORY ;
  1782. goto Cleanup;
  1783. }
  1784. Offset = (PUCHAR) ClientBuffer + sizeof( SECURITY_LOGON_SESSION_DATA );
  1785. LocalOffset = (PUCHAR) ( Data + 1 );
  1786. Data->Size = sizeof( SECURITY_LOGON_SESSION_DATA );
  1787. Data->LogonId = LogonSession->LogonId ;
  1788. Data->LogonType = (ULONG) LogonSession->LogonType ;
  1789. Data->Session = LogonSession->Session ;
  1790. Data->LogonTime = LogonSession->LogonTime ;
  1791. //
  1792. // do the UserSid first since it needs to be 4-byte aligned
  1793. //
  1794. if ( LogonSession->UserSid )
  1795. {
  1796. ULONG ulSidLength = RtlLengthSid( LogonSession->UserSid );
  1797. Data->Sid = (PSID) Offset ;
  1798. RtlCopyMemory( LocalOffset,
  1799. LogonSession->UserSid,
  1800. ulSidLength );
  1801. Offset += ulSidLength;
  1802. LocalOffset += ulSidLength;
  1803. }
  1804. else
  1805. {
  1806. Data->Sid = (PSID) NULL ;
  1807. }
  1808. Data->UserName.Length = LogonSession->AccountName.Length ;
  1809. Data->UserName.MaximumLength = Data->UserName.Length + sizeof( WCHAR );
  1810. Data->UserName.Buffer = (PWSTR) Offset ;
  1811. RtlCopyMemory( LocalOffset,
  1812. LogonSession->AccountName.Buffer,
  1813. LogonSession->AccountName.Length );
  1814. LocalOffset += LogonSession->AccountName.Length ;
  1815. *LocalOffset++ = '\0';
  1816. *LocalOffset++ = '\0';
  1817. Offset += Data->UserName.MaximumLength ;
  1818. Data->LogonDomain.Length = LogonSession->AuthorityName.Length ;
  1819. Data->LogonDomain.MaximumLength = Data->LogonDomain.Length + sizeof( WCHAR );
  1820. Data->LogonDomain.Buffer = (PWSTR) Offset ;
  1821. RtlCopyMemory( LocalOffset,
  1822. LogonSession->AuthorityName.Buffer,
  1823. LogonSession->AuthorityName.Length );
  1824. LocalOffset += LogonSession->AuthorityName.Length ;
  1825. *LocalOffset++ = '\0';
  1826. *LocalOffset++ = '\0';
  1827. Offset += Data->LogonDomain.MaximumLength ;
  1828. Data->AuthenticationPackage.Length = Package->Name.Length ;
  1829. Data->AuthenticationPackage.MaximumLength = Data->AuthenticationPackage.Length + sizeof( WCHAR );
  1830. Data->AuthenticationPackage.Buffer = (PWSTR) Offset ;
  1831. RtlCopyMemory( LocalOffset,
  1832. Package->Name.Buffer,
  1833. Package->Name.Length );
  1834. LocalOffset += Package->Name.Length ;
  1835. *LocalOffset++ = '\0';
  1836. *LocalOffset++ = '\0';
  1837. Offset += Data->AuthenticationPackage.MaximumLength ;
  1838. //
  1839. // do the LogonServer
  1840. //
  1841. Data->LogonServer.Length = LogonSession->LogonServer.Length ;
  1842. Data->LogonServer.MaximumLength = Data->LogonServer.Length + sizeof( WCHAR );
  1843. Data->LogonServer.Buffer = (PWSTR) Offset ;
  1844. RtlCopyMemory( LocalOffset,
  1845. LogonSession->LogonServer.Buffer,
  1846. LogonSession->LogonServer.Length );
  1847. LocalOffset += LogonSession->LogonServer.Length ;
  1848. *LocalOffset++ = '\0';
  1849. *LocalOffset++ = '\0';
  1850. Offset += Data->LogonServer.MaximumLength ;
  1851. //
  1852. // do the DnsDomainName
  1853. //
  1854. if (DnsMap != NULL)
  1855. {
  1856. Data->DnsDomainName.Length = DnsMap->Name.Length;
  1857. Data->DnsDomainName.MaximumLength = Data->DnsDomainName.Length + sizeof( WCHAR );
  1858. Data->DnsDomainName.Buffer = (PWSTR) Offset ;
  1859. RtlCopyMemory( LocalOffset,
  1860. DnsMap->Name.Buffer,
  1861. DnsMap->Name.Length );
  1862. LocalOffset += DnsMap->Name.Length ;
  1863. *LocalOffset++ = '\0';
  1864. *LocalOffset++ = '\0';
  1865. Offset += Data->DnsDomainName.MaximumLength ;
  1866. }
  1867. else
  1868. {
  1869. Data->DnsDomainName.Length = Data->DnsDomainName.MaximumLength = 0;
  1870. Data->DnsDomainName.Buffer = (PWSTR) Offset;
  1871. *LocalOffset++ = '\0';
  1872. *LocalOffset++ = '\0';
  1873. }
  1874. //
  1875. // do the Upn
  1876. //
  1877. if (UpnMap != NULL)
  1878. {
  1879. Data->Upn.Length = UpnMap->Name.Length ;
  1880. Data->Upn.MaximumLength = Data->Upn.Length + sizeof( WCHAR );
  1881. Data->Upn.Buffer = (PWSTR) Offset ;
  1882. RtlCopyMemory( LocalOffset,
  1883. UpnMap->Name.Buffer,
  1884. UpnMap->Name.Length );
  1885. LocalOffset += UpnMap->Name.Length ;
  1886. *LocalOffset++ = '\0';
  1887. *LocalOffset++ = '\0';
  1888. Offset += Data->Upn.MaximumLength ;
  1889. }
  1890. else
  1891. {
  1892. Data->Upn.Length = Data->Upn.MaximumLength = 0;
  1893. Data->Upn.Buffer = (PWSTR) Offset;
  1894. *LocalOffset++ = '\0';
  1895. *LocalOffset++ = '\0';
  1896. }
  1897. Status = LsapCopyToClient( Data,
  1898. ClientBuffer,
  1899. Size );
  1900. *LogonData = ClientBuffer ;
  1901. Cleanup:
  1902. if (DnsMap != NULL)
  1903. {
  1904. LsapDerefDsNameMap(DnsMap);
  1905. }
  1906. if (UpnMap != NULL)
  1907. {
  1908. LsapDerefDsNameMap(UpnMap);
  1909. }
  1910. LsapReleaseLogonSession( LogonSession );
  1911. if( Data != NULL )
  1912. {
  1913. LsapFreePrivateHeap( Data );
  1914. }
  1915. return Status ;
  1916. }
  1917. NTSTATUS
  1918. LsapGetFormatsForLogon(
  1919. IN PLSAP_LOGON_SESSION LogonSession,
  1920. IN LPWSTR Domain,
  1921. IN LPWSTR Name,
  1922. IN ULONG DesiredNameType,
  1923. OUT PLSAP_DS_NAME_MAP * Map
  1924. )
  1925. {
  1926. NTSTATUS Status = STATUS_SUCCESS;
  1927. LPWSTR *TranslatedNames = NULL;
  1928. BOOL TranslateStatus;
  1929. PLSAP_DS_NAME_MAP NameMap;
  1930. UNICODE_STRING TransName;
  1931. ULONG i;
  1932. BOOLEAN NeedToImpersonate = TRUE;
  1933. Retry:
  1934. if ( NeedToImpersonate ) {
  1935. Status = LsapImpersonateClient();
  1936. if ( !NT_SUCCESS(Status) &&
  1937. ( Status != STATUS_BAD_IMPERSONATION_LEVEL ) ) {
  1938. return Status;
  1939. }
  1940. }
  1941. //
  1942. // If the client thread is using an identify or anonymous level token,
  1943. // do the translation in system context.
  1944. //
  1945. TranslateStatus = SecpTranslateNameEx( Domain,
  1946. Name,
  1947. NameSamCompatible,
  1948. (EXTENDED_NAME_FORMAT*) LogonFormats,
  1949. sizeof(LogonFormats)/sizeof(LogonFormats[0]),
  1950. &TranslatedNames );
  1951. //
  1952. // If we successfully impersonated above, revert now.
  1953. //
  1954. if ( NT_SUCCESS( Status ) && NeedToImpersonate )
  1955. {
  1956. RevertToSelf();
  1957. }
  1958. if ( !TranslateStatus ) {
  1959. if ( NeedToImpersonate &&
  1960. NtCurrentTeb()->LastErrorValue == ERROR_ACCESS_DENIED ) {
  1961. //
  1962. // Fall back to machine creds and try again
  1963. //
  1964. NeedToImpersonate = FALSE;
  1965. goto Retry;
  1966. }
  1967. Status = STATUS_UNSUCCESSFUL;
  1968. } else {
  1969. ULONG i;
  1970. RtlEnterCriticalSection( &LogonSessionListLock );
  1971. for (i = 0; i < sizeof(LogonFormats)/sizeof(LogonFormats[0]); i++ ) {
  1972. ULONG NameFormat = LogonFormats[i];
  1973. if ( LogonSession->DsNames[ NameFormat ] ) {
  1974. //
  1975. // Someone else filled it in while we were out cracking
  1976. // it as well. Use theirs, discard ours:
  1977. //
  1978. NameMap = LogonSession->DsNames[ NameFormat ];
  1979. } else {
  1980. //
  1981. // Still no entry -- create one
  1982. //
  1983. TransName.Buffer = TranslatedNames[i] ;
  1984. TransName.Length = (USHORT) (wcslen(TranslatedNames[i]) * sizeof(WCHAR));
  1985. TransName.MaximumLength = TransName.Length + sizeof( WCHAR );
  1986. NameMap = LsapCreateDsNameMap(
  1987. &TransName,
  1988. NameFormat );
  1989. if ( NameMap )
  1990. {
  1991. LogonSession->DsNames[ NameFormat ] = NameMap ;
  1992. }
  1993. else
  1994. {
  1995. RtlLeaveCriticalSection( &LogonSessionListLock );
  1996. Status = STATUS_NO_MEMORY ;
  1997. goto Exit;
  1998. }
  1999. }
  2000. if ( NameFormat == DesiredNameType ) {
  2001. NameMap->RefCount++ ;
  2002. *Map = NameMap ;
  2003. }
  2004. }
  2005. //
  2006. // Should have found a match
  2007. //
  2008. ASSERT( *Map );
  2009. RtlLeaveCriticalSection( &LogonSessionListLock );
  2010. }
  2011. Exit:
  2012. if ( TranslatedNames ) {
  2013. for ( i = 0; i < sizeof(LogonFormats)/sizeof(LogonFormats[0]); i++ ) {
  2014. if ( TranslatedNames[i] ) {
  2015. SecpFreeMemory( TranslatedNames[i] );
  2016. }
  2017. }
  2018. SecpFreeMemory( TranslatedNames );
  2019. }
  2020. return Status;
  2021. }
  2022. NTSTATUS
  2023. LsapSetSessionToken(
  2024. IN HANDLE InputTokenHandle,
  2025. IN PLUID LogonId
  2026. )
  2027. /*++
  2028. Routine Description:
  2029. This routine duplicates the InputTokenHandle and sets that duplicated handle on the
  2030. LogonSession identified by the LogonId.
  2031. The duplicated handle is available for subsequent callers of LsapOpenTokenByLogonId.
  2032. Arguments:
  2033. InputTokenHandle - A handle to a token for the logon session
  2034. LogonId - The logon id of the session
  2035. Return Values:
  2036. Status of the operation.
  2037. --*/
  2038. {
  2039. NTSTATUS Status;
  2040. OBJECT_ATTRIBUTES ObjAttrs;
  2041. SECURITY_QUALITY_OF_SERVICE SecurityQofS;
  2042. HANDLE TokenHandle = NULL;
  2043. ULONG TokenIsReferenced;
  2044. ULONG StatsSize ;
  2045. TOKEN_STATISTICS TokenStats ;
  2046. PLSAP_LOGON_SESSION LogonSession = NULL;
  2047. //
  2048. // Get the credential set from the logon session.
  2049. //
  2050. LogonSession = LsapLocateLogonSession( LogonId );
  2051. if ( LogonSession == NULL ) {
  2052. ASSERT( LogonSession != NULL );
  2053. // This isn't fatal.
  2054. Status = STATUS_SUCCESS;
  2055. goto Cleanup;
  2056. }
  2057. //
  2058. // Ensure there isn't already a token for this session.
  2059. //
  2060. if ( LogonSession->TokenHandle != NULL ) {
  2061. // This can happen for "local service" and "network service"
  2062. // This isn't fatal.
  2063. Status = STATUS_SUCCESS;
  2064. goto Cleanup;
  2065. }
  2066. //
  2067. // Duplicate the token
  2068. //
  2069. Status = NtQueryInformationToken(
  2070. InputTokenHandle,
  2071. TokenStatistics,
  2072. &TokenStats,
  2073. sizeof( TokenStats ),
  2074. &StatsSize );
  2075. if ( !NT_SUCCESS( Status ) ) {
  2076. // This isn't fatal.
  2077. Status = STATUS_SUCCESS;
  2078. goto Cleanup;
  2079. }
  2080. //
  2081. // if primary token handed in (eg: system process), over-ride to SecurityImpersonation from SecurityAnonymous
  2082. //
  2083. if(TokenStats.TokenType == TokenPrimary)
  2084. {
  2085. TokenStats.ImpersonationLevel = SecurityImpersonation;
  2086. }
  2087. InitializeObjectAttributes( &ObjAttrs, NULL, 0L, NULL, NULL );
  2088. SecurityQofS.Length = sizeof( SECURITY_QUALITY_OF_SERVICE );
  2089. SecurityQofS.ImpersonationLevel = min( SecurityImpersonation, TokenStats.ImpersonationLevel );
  2090. SecurityQofS.ContextTrackingMode = FALSE; // Snapshot client context
  2091. SecurityQofS.EffectiveOnly = FALSE;
  2092. ObjAttrs.SecurityQualityOfService = &SecurityQofS;
  2093. Status = NtDuplicateToken( InputTokenHandle,
  2094. TOKEN_ALL_ACCESS,
  2095. &ObjAttrs,
  2096. FALSE,
  2097. TokenImpersonation,
  2098. &TokenHandle );
  2099. if ( !NT_SUCCESS(Status) ) {
  2100. goto Cleanup;
  2101. }
  2102. //
  2103. // Make this token not reference the logon session.
  2104. // (Otherwise, the existence of this token reference would prevent the reference monitor
  2105. // from detecting the last reference to the logon session.)
  2106. //
  2107. TokenIsReferenced = FALSE;
  2108. Status = NtSetInformationToken( TokenHandle,
  2109. TokenSessionReference,
  2110. &TokenIsReferenced,
  2111. sizeof(TokenIsReferenced) );
  2112. if ( !NT_SUCCESS(Status) ) {
  2113. goto Cleanup;
  2114. }
  2115. if( InterlockedCompareExchangePointer(
  2116. &LogonSession->TokenHandle,
  2117. TokenHandle,
  2118. NULL
  2119. ) == NULL)
  2120. {
  2121. //
  2122. // if the value was NULL initially, then we updated it with the new token
  2123. // set the new token NULL so we don't free it.
  2124. //
  2125. TokenHandle = NULL;
  2126. }
  2127. Status = STATUS_SUCCESS;
  2128. Cleanup:
  2129. if ( TokenHandle != NULL ) {
  2130. NtClose( TokenHandle );
  2131. }
  2132. if ( LogonSession != NULL ) {
  2133. LsapReleaseLogonSession( LogonSession );
  2134. }
  2135. return Status;
  2136. }
  2137. NTSTATUS
  2138. LsapOpenTokenByLogonId(
  2139. IN PLUID LogonId,
  2140. OUT HANDLE *RetTokenHandle
  2141. )
  2142. /*++
  2143. Routine Description:
  2144. This routine open a token by LogonId. It is only valid for LogonIds where all of the
  2145. following are true:
  2146. * A logon session has been create via LsapCreateLogonSession, AND
  2147. * A token has been created via LsapCreateToken or by the LSA after an authentication package
  2148. returns successfully from LsaApLogonUser(Ex)(2).
  2149. Arguments:
  2150. LogonId - The logon id of the session
  2151. RetTokenHandle - Returns a handle to the token. The token is an impersonation token,
  2152. is granted TOKEN_ALL_ACCESS, and should be closed via NtClose.
  2153. Return Values:
  2154. Status of the operation.
  2155. STATUS_NO_SUCH_LOGON_SESSION - The logon session does not exist.
  2156. STATUS_NO_TOKEN - There is no token for this logon session.
  2157. --*/
  2158. {
  2159. NTSTATUS Status;
  2160. OBJECT_ATTRIBUTES ObjAttrs;
  2161. SECURITY_QUALITY_OF_SERVICE SecurityQofS;
  2162. HANDLE TokenHandle = NULL;
  2163. PLSAP_LOGON_SESSION LogonSession = NULL;
  2164. //
  2165. // Get the credential set from the logon session.
  2166. //
  2167. LogonSession = LsapLocateLogonSession( LogonId );
  2168. if ( LogonSession == NULL ) {
  2169. // ASSERT( LogonSession != NULL );
  2170. //
  2171. // If this is the anonymous logon id,
  2172. // create a token.
  2173. //
  2174. if ( RtlEqualLuid( LogonId,
  2175. &LsapAnonymousLogonId ) ) {
  2176. LSA_TOKEN_INFORMATION_NULL VNull;
  2177. TOKEN_SOURCE NullTokenSource = {"*LAnon*", 0};
  2178. HANDLE ImpersonatedToken = NULL;
  2179. VNull.Groups = NULL;
  2180. VNull.ExpirationTime.HighPart = 0x7FFFFFFF;
  2181. VNull.ExpirationTime.LowPart = 0xFFFFFFFF;
  2182. //
  2183. // insure we aren't impersonating a client when we try to create the token
  2184. // this is relevant for inproc security package consumers.
  2185. // BLACKCOMBE: Duplicate a cached anonymous token instead.
  2186. //
  2187. Status = NtOpenThreadToken(
  2188. NtCurrentThread(),
  2189. TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE,
  2190. TRUE,
  2191. &ImpersonatedToken
  2192. );
  2193. if (!NT_SUCCESS(Status))
  2194. {
  2195. if (Status != STATUS_NO_TOKEN)
  2196. {
  2197. goto Cleanup;
  2198. }
  2199. ImpersonatedToken = NULL ;
  2200. }
  2201. Status = LsapCreateNullToken( LogonId,
  2202. &NullTokenSource,
  2203. &VNull,
  2204. RetTokenHandle );
  2205. if( ImpersonatedToken )
  2206. {
  2207. NtSetInformationThread(
  2208. NtCurrentThread(),
  2209. ThreadImpersonationToken,
  2210. &ImpersonatedToken,
  2211. sizeof(HANDLE)
  2212. );
  2213. }
  2214. goto Cleanup;
  2215. }
  2216. Status = STATUS_NO_SUCH_LOGON_SESSION;
  2217. goto Cleanup;
  2218. }
  2219. //
  2220. // Ensure there is a token for this session.
  2221. //
  2222. RtlEnterCriticalSection( &LogonSessionListLock );
  2223. if ( LogonSession->TokenHandle == NULL ) {
  2224. RtlLeaveCriticalSection( &LogonSessionListLock );
  2225. Status = STATUS_NO_TOKEN;
  2226. goto Cleanup;
  2227. }
  2228. //
  2229. // Duplicate the token
  2230. //
  2231. InitializeObjectAttributes( &ObjAttrs, NULL, 0L, NULL, NULL );
  2232. SecurityQofS.Length = sizeof( SECURITY_QUALITY_OF_SERVICE );
  2233. SecurityQofS.ImpersonationLevel = SecurityImpersonation;
  2234. SecurityQofS.ContextTrackingMode = FALSE; // Snapshot client context
  2235. SecurityQofS.EffectiveOnly = FALSE;
  2236. ObjAttrs.SecurityQualityOfService = &SecurityQofS;
  2237. Status = NtDuplicateToken( LogonSession->TokenHandle,
  2238. TOKEN_ALL_ACCESS,
  2239. &ObjAttrs,
  2240. FALSE,
  2241. TokenImpersonation,
  2242. &TokenHandle );
  2243. if ( !NT_SUCCESS(Status) ) {
  2244. RtlLeaveCriticalSection( &LogonSessionListLock );
  2245. goto Cleanup;
  2246. }
  2247. *RetTokenHandle = TokenHandle;
  2248. TokenHandle = NULL;
  2249. RtlLeaveCriticalSection( &LogonSessionListLock );
  2250. Status = STATUS_SUCCESS;
  2251. Cleanup:
  2252. if ( TokenHandle != NULL ) {
  2253. NtClose( TokenHandle );
  2254. }
  2255. if ( LogonSession != NULL ) {
  2256. LsapReleaseLogonSession( LogonSession );
  2257. }
  2258. return Status;
  2259. }
  2260. NTSTATUS
  2261. LsapDomainRenameHandlerForLogonSessions(
  2262. IN PUNICODE_STRING OldNetbiosName,
  2263. IN PUNICODE_STRING OldDnsName,
  2264. IN PUNICODE_STRING NewNetbiosName,
  2265. IN PUNICODE_STRING NewDnsName
  2266. )
  2267. /*++
  2268. Routine Description:
  2269. Walks the logon sessions list and renames the logon sessions with the given
  2270. new netbios and DNS domain names
  2271. Arguments:
  2272. OldNetbiosName old netbios name of the domain
  2273. OldDnsName old DNS name of the domain
  2274. NewNetbiosName new netbios name of the domain
  2275. NewDnsName new DNS name of the domain
  2276. Returns:
  2277. STATUS_ error code
  2278. --*/
  2279. {
  2280. NTSTATUS Status = STATUS_SUCCESS;
  2281. ASSERT( OldNetbiosName );
  2282. ASSERT( OldDnsName );
  2283. ASSERT( NewNetbiosName );
  2284. ASSERT( NewDnsName );
  2285. RtlEnterCriticalSection( &LogonSessionListLock );
  2286. for ( PLIST_ENTRY Scan = LogonSessionList.Flink;
  2287. Scan != &LogonSessionList;
  2288. Scan = Scan->Flink ) {
  2289. UNICODE_STRING NetbiosName = {0};
  2290. UNICODE_STRING DnsName = {0};
  2291. PLSAP_LOGON_SESSION LogonSession = CONTAINING_RECORD( Scan, LSAP_LOGON_SESSION, List );
  2292. PLSAP_DS_NAME_MAP SamMap = LogonSession->DsNames[ NameSamCompatible ];
  2293. PLSAP_DS_NAME_MAP DnsMap = LogonSession->DsNames[ NameDnsDomain ];
  2294. Status = STATUS_SUCCESS;
  2295. if ( NT_SUCCESS( Status ) &&
  2296. RtlEqualUnicodeString(
  2297. OldNetbiosName,
  2298. &LogonSession->AuthorityName,
  2299. TRUE )) {
  2300. Status = LsapDuplicateString( // Use LsapAllocateLsaHeap
  2301. &NetbiosName,
  2302. NewNetbiosName
  2303. );
  2304. }
  2305. if ( NT_SUCCESS( Status ) &&
  2306. DnsMap &&
  2307. RtlEqualUnicodeString(
  2308. OldDnsName,
  2309. &DnsMap->Name,
  2310. TRUE )) {
  2311. Status = LsapDuplicateString2( // Use LsapAllocatePrivateHeap
  2312. &DnsName,
  2313. NewDnsName
  2314. );
  2315. }
  2316. if ( !NT_SUCCESS( Status )) {
  2317. LsapFreeLsaHeap( NetbiosName.Buffer );
  2318. LsapFreePrivateHeap( DnsName.Buffer );
  2319. break;
  2320. }
  2321. if ( NetbiosName.Buffer ) {
  2322. LsapFreeLsaHeap( LogonSession->AuthorityName.Buffer );
  2323. LogonSession->AuthorityName = NetbiosName;
  2324. }
  2325. if ( DnsMap && DnsName.Buffer )
  2326. {
  2327. LsapDerefDsNameMap(DnsMap);
  2328. LogonSession->DsNames[NameDnsDomain] = LsapCreateDsNameMap(&DnsName, NameDnsDomain);
  2329. }
  2330. if ( SamMap &&
  2331. SamMap->Name.Length > OldNetbiosName->Length &&
  2332. 0 == _wcsnicmp(
  2333. SamMap->Name.Buffer,
  2334. OldNetbiosName->Buffer,
  2335. OldNetbiosName->Length / sizeof( WCHAR )) &&
  2336. SamMap->Name.Buffer[ OldNetbiosName->Length / sizeof( WCHAR )] == L'\\' ) {
  2337. LsapDerefDsNameMap( SamMap );
  2338. if ( FALSE == LsapSetSamAccountNameForLogonSession( LogonSession )) {
  2339. Status = STATUS_INSUFFICIENT_RESOURCES;
  2340. break;
  2341. }
  2342. }
  2343. }
  2344. RtlLeaveCriticalSection( &LogonSessionListLock );
  2345. return Status;
  2346. }
  2347. NTSTATUS
  2348. LsapCreateDnsNameFromCanonicalName(
  2349. IN PLSAP_LOGON_SESSION LogonSession,
  2350. IN ULONG NameType,
  2351. OUT PLSAP_DS_NAME_MAP * Map
  2352. )
  2353. /*++
  2354. Routine Description:
  2355. Internal routine used to extract the DnsDomainName given the canonical name
  2356. Arguments:
  2357. LogonSession - The logon session in question
  2358. Map - Pointer that receives the allocated/refcounted name map on success
  2359. Return Values:
  2360. Status of the operation.
  2361. Notes:
  2362. The LogonSessionListLock MUST be held when this routine is called
  2363. --*/
  2364. {
  2365. PLSAP_DS_NAME_MAP CanonicalNameMap = LogonSession->DsNames[NameType];
  2366. UNICODE_STRING DnsDomainName;
  2367. LPWSTR lpSlash;
  2368. USHORT i;
  2369. ASSERT(CanonicalNameMap != NULL);
  2370. ASSERT(LogonSession->DsNames[NameDnsDomain] == NULL);
  2371. //
  2372. // Find the first forward slash in the canonical name. No guarantees on
  2373. // NULL-termination in a UNICODE_STRING.
  2374. //
  2375. lpSlash = NULL;
  2376. for (i = 0; i < CanonicalNameMap->Name.Length; i++)
  2377. {
  2378. if (CanonicalNameMap->Name.Buffer[i] == L'/')
  2379. {
  2380. lpSlash = &CanonicalNameMap->Name.Buffer[i];
  2381. break;
  2382. }
  2383. }
  2384. if (lpSlash == NULL)
  2385. {
  2386. //
  2387. // The canonical name is bad -- bail.
  2388. //
  2389. ASSERT(lpSlash != NULL);
  2390. return STATUS_NONE_MAPPED;
  2391. }
  2392. RtlInitUnicodeString(&DnsDomainName, CanonicalNameMap->Name.Buffer);
  2393. DnsDomainName.Length = (USHORT) (lpSlash - CanonicalNameMap->Name.Buffer) * sizeof(WCHAR);
  2394. *Map = LsapCreateDsNameMap(&DnsDomainName, NameDnsDomain);
  2395. if (*Map == NULL)
  2396. {
  2397. return STATUS_NO_MEMORY;
  2398. }
  2399. LogonSession->DsNames[NameDnsDomain] = *Map;
  2400. (*Map)->RefCount++;
  2401. return STATUS_SUCCESS;
  2402. }
  2403. NTSTATUS
  2404. LsaIAddNameToLogonSession(
  2405. IN PLUID LogonId,
  2406. IN ULONG NameFormat,
  2407. IN PUNICODE_STRING Name
  2408. )
  2409. /*++
  2410. Routine Description:
  2411. Internal routine for the auth packages to call to add names to the cache in the
  2412. logon session
  2413. Arguments:
  2414. LogonId - The logon id of the session
  2415. NameFormat - The EXTENDED_NAME_FORMAT for the name in question (from secext.h)
  2416. Name - The name itself
  2417. Return Values:
  2418. Status of the operation.
  2419. STATUS_NO_SUCH_LOGON_SESSION - The logon session does not exist.
  2420. --*/
  2421. {
  2422. PLSAP_LOGON_SESSION LogonSession;
  2423. PLSAP_DS_NAME_MAP NameMap;
  2424. BOOL fDeleteMap = FALSE;
  2425. //
  2426. // We trust the auth package to be passing in valid parameters
  2427. // session so assert on all invalid parameter errors.
  2428. //
  2429. if (Name == NULL)
  2430. {
  2431. //
  2432. // Package doesn't have this info -- ignore it
  2433. //
  2434. return STATUS_SUCCESS;
  2435. }
  2436. LogonSession = LsapLocateLogonSession(LogonId);
  2437. if (LogonSession == NULL)
  2438. {
  2439. ASSERT(LogonSession != NULL);
  2440. return STATUS_NO_SUCH_LOGON_SESSION;
  2441. }
  2442. ASSERT(NameFormat < LSAP_MAX_DS_NAMES && NameFormat != NameSamCompatible);
  2443. NameMap = LsapCreateDsNameMap(Name, NameFormat);
  2444. if (NameMap == NULL)
  2445. {
  2446. LsapReleaseLogonSession(LogonSession);
  2447. return STATUS_NO_MEMORY;
  2448. }
  2449. //
  2450. // Update the logon session.
  2451. //
  2452. RtlEnterCriticalSection(&LogonSessionListLock);
  2453. if (LogonSession->DsNames[NameFormat] == NULL)
  2454. {
  2455. LogonSession->DsNames[NameFormat] = NameMap;
  2456. }
  2457. else
  2458. {
  2459. //
  2460. // Another thread beat us to it -- keep the name in the session
  2461. //
  2462. fDeleteMap = TRUE;
  2463. }
  2464. RtlLeaveCriticalSection(&LogonSessionListLock);
  2465. if (fDeleteMap)
  2466. {
  2467. LsapDerefDsNameMap(NameMap);
  2468. }
  2469. LsapReleaseLogonSession(LogonSession);
  2470. return STATUS_SUCCESS;
  2471. }
  2472. NTSTATUS
  2473. LsaISetLogonGuidInLogonSession(
  2474. IN PLUID LogonId,
  2475. IN LPGUID LogonGuid
  2476. )
  2477. /*++
  2478. Routine Description:
  2479. Internal routine for the auth packages (currently only kerberos)
  2480. to set the logon GUID in the logon session
  2481. Arguments:
  2482. LogonId - The logon id of the session
  2483. LogonGuid - The logon GUID of the session
  2484. Return Values:
  2485. Status of the operation.
  2486. STATUS_NO_SUCH_LOGON_SESSION - The logon session does not exist.
  2487. --*/
  2488. {
  2489. PLSAP_LOGON_SESSION LogonSession = NULL;
  2490. NTSTATUS Status = STATUS_SUCCESS;
  2491. GUID ZeroGuid = { 0 };
  2492. //
  2493. // We trust the auth package to be passing in valid parameters
  2494. // session so assert on all invalid parameter errors.
  2495. //
  2496. LogonSession = LsapLocateLogonSession(LogonId);
  2497. if (LogonSession == NULL)
  2498. {
  2499. Status = STATUS_NO_SUCH_LOGON_SESSION;
  2500. goto Cleanup;
  2501. }
  2502. //
  2503. // Update the logon session.
  2504. //
  2505. Status = RtlEnterCriticalSection(&LogonSessionListLock);
  2506. if ( NT_SUCCESS(Status) )
  2507. {
  2508. if ( LogonGuid )
  2509. {
  2510. RtlCopyMemory( &LogonSession->LogonGuid, LogonGuid, sizeof(GUID) );
  2511. }
  2512. else
  2513. {
  2514. RtlCopyMemory( &LogonSession->LogonGuid, &ZeroGuid, sizeof(GUID) );
  2515. }
  2516. RtlLeaveCriticalSection(&LogonSessionListLock);
  2517. }
  2518. Cleanup:
  2519. if ( LogonSession )
  2520. {
  2521. LsapReleaseLogonSession(LogonSession);
  2522. }
  2523. return STATUS_SUCCESS;
  2524. }