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.

3604 lines
95 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: neglsa.cxx
  7. //
  8. // Contents: General (both win9x and nt) functions
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 02-09-00 RichardW Created - split from negotiat.cxx
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <lsapch.hxx>
  18. extern "C"
  19. {
  20. #include <align.h>
  21. #include <lm.h>
  22. #include <dsgetdc.h>
  23. #include <cryptdll.h>
  24. #include <netlib.h>
  25. #include <spmgr.h>
  26. #include "sesmgr.h"
  27. #include "spinit.h"
  28. }
  29. #include "negotiat.hxx"
  30. #include <stdio.h>
  31. GUID GUID_NULL = {0L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  32. TOKEN_SOURCE LsapTokenSource = {"LSA", 0};
  33. //
  34. // Hardcoded english strings for LocalService and NetworkService
  35. // since the account names may come from the registry (which isn't
  36. // localized).
  37. //
  38. #define LOCALSERVICE_NAME L"LocalService"
  39. #define NETWORKSERVICE_NAME L"NetworkService"
  40. #define NTAUTHORITY_NAME L"NT AUTHORITY"
  41. UNICODE_STRING LocalServiceName = { sizeof(LOCALSERVICE_NAME) - 2,
  42. sizeof(LOCALSERVICE_NAME),
  43. LOCALSERVICE_NAME };
  44. UNICODE_STRING NetworkServiceName = { sizeof(NETWORKSERVICE_NAME) - 2,
  45. sizeof(NETWORKSERVICE_NAME),
  46. NETWORKSERVICE_NAME };
  47. UNICODE_STRING NTAuthorityName = { sizeof(NTAUTHORITY_NAME) - 2,
  48. sizeof(NTAUTHORITY_NAME),
  49. NTAUTHORITY_NAME };
  50. HANDLE NegEventLogHandle = NULL ;
  51. ULONG NegEventLogLevel = 3 ;
  52. EXTERN RTL_CRITICAL_SECTION NegComputerNamesLock;
  53. //
  54. // RELOCATE_ONE - Relocate a single pointer in a client buffer.
  55. //
  56. // Note: this macro is dependent on parameter names as indicated in the
  57. // description below. On error, this macro goes to 'Cleanup' with
  58. // 'Status' set to the NT Status code.
  59. //
  60. // The MaximumLength is forced to be Length.
  61. //
  62. // Define a macro to relocate a pointer in the buffer the client passed in
  63. // to be relative to 'ProtocolSubmitBuffer' rather than being relative to
  64. // 'ClientBufferBase'. The result is checked to ensure the pointer and
  65. // the data pointed to is within the first 'SubmitBufferSize' of the
  66. // 'ProtocolSubmitBuffer'.
  67. //
  68. // The relocated field must be aligned to a WCHAR boundary.
  69. //
  70. // _q - Address of UNICODE_STRING structure which points to data to be
  71. // relocated
  72. //
  73. #define RELOCATE_ONE( _q ) \
  74. { \
  75. ULONG_PTR Offset; \
  76. \
  77. Offset = (((PUCHAR)((_q)->Buffer)) - ((PUCHAR)ClientBufferBase)); \
  78. if ( Offset >= SubmitBufferSize || \
  79. Offset + (_q)->Length > SubmitBufferSize || \
  80. !COUNT_IS_ALIGNED( Offset, ALIGN_WCHAR) ) { \
  81. \
  82. Status = STATUS_INVALID_PARAMETER; \
  83. goto Cleanup; \
  84. } \
  85. \
  86. (_q)->Buffer = (PWSTR)(((PUCHAR)ProtocolSubmitBuffer) + Offset); \
  87. (_q)->MaximumLength = (_q)->Length ; \
  88. }
  89. //
  90. // NULL_RELOCATE_ONE - Relocate a single (possibly NULL) pointer in a client
  91. // buffer.
  92. //
  93. // This macro special cases a NULL pointer then calls RELOCATE_ONE. Hence
  94. // it has all the restrictions of RELOCATE_ONE.
  95. //
  96. //
  97. // _q - Address of UNICODE_STRING structure which points to data to be
  98. // relocated
  99. //
  100. #define NULL_RELOCATE_ONE( _q ) \
  101. { \
  102. if ( (_q)->Buffer == NULL ) { \
  103. if ( (_q)->Length != 0 ) { \
  104. Status = STATUS_INVALID_PARAMETER; \
  105. goto Cleanup; \
  106. } \
  107. } else if ( (_q)->Length == 0 ) { \
  108. (_q)->Buffer = NULL; \
  109. } else { \
  110. RELOCATE_ONE( _q ); \
  111. } \
  112. }
  113. #define MAX_EVENT_STRINGS 8
  114. extern SECPKG_PRIMARY_CRED NegPrimarySystemCredentials;
  115. //
  116. // Local function prototypes
  117. //
  118. NTSTATUS
  119. NegpMakeServiceToken(
  120. IN ULONG ulAccountId,
  121. OUT PLUID pLogonId,
  122. OUT PVOID *ProfileBuffer,
  123. OUT PULONG ProfileBufferLength,
  124. OUT PNTSTATUS ApiSubStatus,
  125. OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
  126. OUT PVOID *TokenInformation,
  127. OUT PUNICODE_STRING *AccountName,
  128. OUT PUNICODE_STRING *AuthenticatingAuthority,
  129. OUT PUNICODE_STRING *MachineName,
  130. OUT PSECPKG_PRIMARY_CRED PrimaryCredentials,
  131. OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY * CachedCredentials
  132. );
  133. BOOL
  134. NegpIsLocalOrNetworkService(
  135. IN PVOID ProtocolSubmitBuffer,
  136. IN PVOID ClientBufferBase,
  137. IN ULONG SubmitBufferSize,
  138. OUT PUNICODE_STRING *AccountName,
  139. OUT PUNICODE_STRING *AuthenticatingAuthority,
  140. OUT PUNICODE_STRING *MachineName,
  141. OUT PULONG pulAccountId
  142. );
  143. #ifdef _WIN64
  144. NTSTATUS
  145. NegpConvertWOWInteractiveLogonBuffer(
  146. IN PVOID ProtocolSubmitBuffer,
  147. IN PVOID ClientBufferBase,
  148. IN OUT PULONG pSubmitBufferSize,
  149. OUT PVOID *ppTempSubmitBuffer
  150. );
  151. #endif // _WIN64
  152. VOID
  153. NegpReportEvent(
  154. IN WORD EventType,
  155. IN DWORD EventId,
  156. IN DWORD Category,
  157. IN NTSTATUS Status,
  158. IN DWORD NumberOfStrings,
  159. ...
  160. )
  161. {
  162. va_list arglist;
  163. ULONG i;
  164. PWSTR Strings[ MAX_EVENT_STRINGS ];
  165. BOOLEAN Allocated[ MAX_EVENT_STRINGS ] = { 0 };
  166. WCHAR StatusString[ MAX_PATH ];
  167. WCHAR FinalStatus[ MAX_PATH ];
  168. HANDLE Dll ;
  169. DWORD rv;
  170. if (NegEventLogHandle == NULL )
  171. {
  172. //
  173. // only log identical event once per hour.
  174. // note that LSA doesn't cleanup this 'handle' during shutdown,
  175. // to avoid preventing log failures during shutdown.
  176. //
  177. NegEventLogHandle = NetpEventlogOpen( L"LSASRV", 60000*60 );
  178. if ( NegEventLogHandle == NULL )
  179. {
  180. return ;
  181. }
  182. }
  183. //
  184. // We're not supposed to be logging this, so nuke it
  185. //
  186. if ((NegEventLogLevel & (1 << EventType)) == 0)
  187. {
  188. return ;
  189. }
  190. //
  191. // Look at the strings, if they were provided
  192. //
  193. va_start( arglist, NumberOfStrings );
  194. if (NumberOfStrings > MAX_EVENT_STRINGS) {
  195. NumberOfStrings = MAX_EVENT_STRINGS;
  196. }
  197. for (i=0; i<NumberOfStrings; i++) {
  198. PUNICODE_STRING String = va_arg( arglist, PUNICODE_STRING );
  199. //
  200. // Make sure strings are NULL-terminated. Do it in place for
  201. // those strings whose buffers can accomodate an additional character,
  202. // and allocate memory for the rest.
  203. //
  204. if ( String->MaximumLength > String->Length ) {
  205. Strings[i] = String->Buffer;
  206. } else {
  207. SafeAllocaAllocate(Strings[i], String->Length + sizeof( WCHAR ));
  208. if ( Strings[i] == NULL ) {
  209. goto Cleanup;
  210. }
  211. Allocated[i] = TRUE;
  212. RtlCopyMemory( Strings[i], String->Buffer, String->Length );
  213. }
  214. Strings[i][String->Length / sizeof( WCHAR )] = L'\0';
  215. }
  216. if ( Status != 0 )
  217. {
  218. static HMODULE NtDll;
  219. static HMODULE Kernel32;
  220. //
  221. // Map the status code:
  222. //
  223. //
  224. // The value "type" is not known. Try and figure out what it
  225. // is.
  226. //
  227. if ( (Status & 0xC0000000) == 0xC0000000 )
  228. {
  229. //
  230. // Easy: NTSTATUS failure case
  231. //
  232. if( NtDll == NULL )
  233. {
  234. NtDll = GetModuleHandleW( L"NTDLL.DLL" );
  235. }
  236. Dll = NtDll;
  237. }
  238. else if ( ( Status & 0xF0000000 ) == 0xD0000000 )
  239. {
  240. //
  241. // HRESULT from NTSTATUS
  242. //
  243. if( NtDll == NULL )
  244. {
  245. NtDll = GetModuleHandleW( L"NTDLL.DLL" );
  246. }
  247. Dll = NtDll;
  248. Status &= 0xCFFFFFFF ;
  249. }
  250. else if ( ( Status & 0x80000000 ) == 0x80000000 )
  251. {
  252. //
  253. // Note, this can overlap with NTSTATUS warning area. In that
  254. // case, force the NTSTATUS.
  255. //
  256. if( Kernel32 == NULL )
  257. {
  258. Kernel32 = GetModuleHandleW( L"KERNEL32.DLL" );
  259. }
  260. Dll = Kernel32;
  261. }
  262. else
  263. {
  264. //
  265. // Sign bit is off. Explore some known ranges:
  266. //
  267. if ( (Status >= WSABASEERR) && (Status <= WSABASEERR + 1000 ))
  268. {
  269. Dll = LoadLibraryExW(L"ws2_32.dll",
  270. NULL,
  271. LOAD_LIBRARY_AS_DATAFILE);
  272. }
  273. else if ( ( Status >= NERR_BASE ) && ( Status <= MAX_NERR ) )
  274. {
  275. Dll = LoadLibraryExW(L"netmsg.dll",
  276. NULL,
  277. LOAD_LIBRARY_AS_DATAFILE);
  278. }
  279. else
  280. {
  281. if( Kernel32 == NULL )
  282. {
  283. Kernel32 = GetModuleHandleW( L"KERNEL32.DLL" );
  284. }
  285. Dll = Kernel32;
  286. }
  287. }
  288. if (!FormatMessage(
  289. FORMAT_MESSAGE_IGNORE_INSERTS |
  290. FORMAT_MESSAGE_FROM_HMODULE,
  291. Dll,
  292. Status,
  293. 0,
  294. StatusString,
  295. MAX_PATH,
  296. NULL ) )
  297. {
  298. StatusString[0] = L' ';
  299. StatusString[1] = L'\0';
  300. }
  301. if ( Status < 0 )
  302. {
  303. _snwprintf( FinalStatus, MAX_PATH, L"\"%ws (%#x)\"", StatusString, Status );
  304. }
  305. else
  306. {
  307. _snwprintf( FinalStatus, MAX_PATH, L"\"%ws (%#x, %d)\"", StatusString, Status, Status );
  308. }
  309. if ( NumberOfStrings < MAX_EVENT_STRINGS )
  310. {
  311. Strings[ NumberOfStrings++ ] = FinalStatus ;
  312. }
  313. }
  314. //
  315. // Report the event to the eventlog service
  316. //
  317. NetpEventlogWriteEx(
  318. NegEventLogHandle,
  319. EventType,
  320. Category,
  321. EventId,
  322. NumberOfStrings,
  323. sizeof(NTSTATUS),
  324. Strings,
  325. &Status
  326. );
  327. Cleanup:
  328. for ( i = 0 ; i < NumberOfStrings ; i++ ) {
  329. if ( Allocated[i] ) {
  330. SafeAllocaFree( Strings[i] );
  331. }
  332. }
  333. }
  334. //+---------------------------------------------------------------------------
  335. //
  336. // Function: NegLsaPolicyChangeCallback
  337. //
  338. // Synopsis: Called by the policy engine in the LSA when local policy changes,
  339. // allowing us to update our state about the machine account, etc.
  340. //
  341. // Arguments: ChangedInfoClass - Class of policy that changed
  342. //
  343. // History: 2-9-00 RichardW Created
  344. //
  345. // Notes:
  346. //
  347. //----------------------------------------------------------------------------
  348. VOID
  349. NTAPI
  350. NegLsaPolicyChangeCallback(
  351. IN POLICY_NOTIFICATION_INFORMATION_CLASS ChangedInfoClass
  352. )
  353. {
  354. PLSAPR_POLICY_INFORMATION Policy = NULL ;
  355. NTSTATUS Status ;
  356. GUID GuidNull = GUID_NULL ;
  357. PLSAP_LOGON_SESSION LogonSession = NULL ;
  358. BOOL Uplevel ;
  359. UNICODE_STRING TmpDomainName = {0};
  360. //
  361. // Right now, only domain information is interesting
  362. //
  363. if ( ChangedInfoClass != PolicyNotifyDnsDomainInformation )
  364. {
  365. return ;
  366. }
  367. DebugLog(( DEB_TRACE_NEG, "Domain change, updating state\n" ));
  368. //
  369. // Reset the trust list. The next time someone asks for the trust
  370. // list, it will have expired and they will get a fresh one.
  371. //
  372. NegTrustTime.QuadPart = 0 ;
  373. //
  374. // Obtain the new policy settings
  375. //
  376. Status = LsaIQueryInformationPolicyTrusted(
  377. PolicyDnsDomainInformation,
  378. &Policy );
  379. if ( NT_SUCCESS( Status ) )
  380. {
  381. //
  382. // If the domain has a GUID, then it is an uplevel domain
  383. //
  384. if ( Policy->PolicyDnsDomainInfo.DomainGuid == GuidNull )
  385. {
  386. Uplevel = FALSE ;
  387. }
  388. else
  389. {
  390. Uplevel = TRUE ;
  391. }
  392. RtlEnterCriticalSection(&NegComputerNamesLock);
  393. Status = LsapDuplicateString(
  394. &TmpDomainName,
  395. (PUNICODE_STRING) &Policy->PolicyDnsDomainInfo.DnsDomainName
  396. );
  397. if (NT_SUCCESS(Status))
  398. {
  399. //
  400. // Time to update the primary system credentials.
  401. //
  402. if ( TmpDomainName.Buffer )
  403. {
  404. LsapFreeString( &NegPrimarySystemCredentials.DnsDomainName );
  405. NegPrimarySystemCredentials.DnsDomainName = TmpDomainName;
  406. TmpDomainName.Buffer = NULL;
  407. }
  408. Status = LsapDuplicateString(
  409. &TmpDomainName,
  410. (PUNICODE_STRING) &Policy->PolicyDnsDomainInfo.Name
  411. );
  412. if (NT_SUCCESS(Status))
  413. {
  414. if ( TmpDomainName.Buffer )
  415. {
  416. LsapFreeString( &NegPrimarySystemCredentials.DomainName );
  417. NegPrimarySystemCredentials.DomainName = TmpDomainName;
  418. TmpDomainName.Buffer = NULL;
  419. }
  420. }
  421. }
  422. RtlLeaveCriticalSection(&NegComputerNamesLock);
  423. //
  424. // Done with the policy info
  425. //
  426. LsaIFree_LSAPR_POLICY_INFORMATION(
  427. PolicyDnsDomainInformation,
  428. Policy
  429. );
  430. NegUplevelDomain = Uplevel ;
  431. //
  432. // Update the package ID for the local system logon session
  433. // Note, any additional special logon sessions will need to be
  434. // updated as well.
  435. //
  436. LogonSession = LsapLocateLogonSession( &SystemLogonId );
  437. if ( LogonSession )
  438. {
  439. if ( Uplevel )
  440. {
  441. LogonSession->CreatingPackage = NegPackageId ;
  442. }
  443. else
  444. {
  445. LogonSession->CreatingPackage = NtlmPackageId ;
  446. }
  447. LsapReleaseLogonSession( LogonSession );
  448. }
  449. }
  450. {
  451. ULONG Size;
  452. static WCHAR NegNetbiosComputerName[ MAX_COMPUTERNAME_LENGTH + 1 ];
  453. static WCHAR NegDnsComputerName[ DNS_MAX_NAME_BUFFER_LENGTH + 1 ];
  454. //
  455. // refresh the computer names.
  456. // note we could avoid taking the lock around these calls if we dyna-alloc'd
  457. // and freed the existing buffers. We don't expect this path to be hit often,
  458. // so avoid the hassle.
  459. //
  460. NegWriteLockComputerNames();
  461. Size = sizeof(NegDnsComputerName) / sizeof(WCHAR);
  462. //
  463. // Note, if this fails, it's ok. We just won't be able to make
  464. // some optimizations later.
  465. //
  466. if(!GetComputerNameExW(
  467. ComputerNamePhysicalDnsFullyQualified,
  468. NegDnsComputerName,
  469. &Size
  470. ))
  471. {
  472. NegDnsComputerName[ 0 ] = L'\0';
  473. }
  474. RtlInitUnicodeString( &NegDnsComputerName_U, NegDnsComputerName );
  475. Size = sizeof(NegNetbiosComputerName) / sizeof(WCHAR);
  476. if(!GetComputerNameExW(
  477. ComputerNamePhysicalNetBIOS,
  478. NegNetbiosComputerName,
  479. &Size
  480. ))
  481. {
  482. NegNetbiosComputerName[ 0 ] = L'\0';
  483. }
  484. RtlInitUnicodeString( &NegNetbiosComputerName_U, NegNetbiosComputerName );
  485. NegUnlockComputerNames();
  486. }
  487. }
  488. //+---------------------------------------------------------------------------
  489. //
  490. // Function: NegParamChange
  491. //
  492. // Synopsis: Called by LSA whenever the LSA registry key changes
  493. //
  494. // Arguments: [p] --
  495. //
  496. // History: 5-11-00 RichardW Created
  497. //
  498. // Notes:
  499. //
  500. //----------------------------------------------------------------------------
  501. DWORD
  502. WINAPI
  503. NegParamChange(
  504. PVOID p
  505. )
  506. {
  507. NTSTATUS Status ;
  508. PSECPKG_EVENT_NOTIFY Notify;
  509. HKEY LsaKey ;
  510. Notify = (PSECPKG_EVENT_NOTIFY) p;
  511. if ( Notify->EventClass != NOTIFY_CLASS_REGISTRY_CHANGE )
  512. {
  513. return( 0 );
  514. }
  515. if ( RegOpenKeyEx(
  516. HKEY_LOCAL_MACHINE,
  517. TEXT("System\\CurrentControlSet\\Control\\Lsa"),
  518. 0,
  519. KEY_READ,
  520. &LsaKey ) == 0 )
  521. {
  522. NegpReadRegistryParameters( LsaKey );
  523. RegCloseKey( LsaKey );
  524. }
  525. return 0 ;
  526. }
  527. //+---------------------------------------------------------------------------
  528. //
  529. // Function: NegEnumPackagePrefixesCall
  530. //
  531. // Synopsis: LsaCallPackage routine to identify the prefxes (or OIDs) for
  532. // all the packages, for SASL support.
  533. //
  534. // Arguments:
  535. //
  536. // History:
  537. //
  538. // Notes:
  539. //
  540. //----------------------------------------------------------------------------
  541. NTSTATUS
  542. NegEnumPackagePrefixesCall(
  543. IN PLSA_CLIENT_REQUEST ClientRequest,
  544. IN PVOID ProtocolSubmitBuffer,
  545. IN PVOID ClientBufferBase,
  546. IN ULONG SubmitBufferLength,
  547. OUT PVOID *ProtocolReturnBuffer,
  548. OUT PULONG ReturnBufferLength,
  549. OUT PNTSTATUS ProtocolStatus
  550. )
  551. {
  552. UCHAR PrefixBuffer[ NEGOTIATE_MAX_PREFIX ];
  553. NTSTATUS Status ;
  554. PNEGOTIATE_PACKAGE_PREFIXES Prefixes ;
  555. PNEGOTIATE_PACKAGE_PREFIX Prefix ;
  556. PNEGOTIATE_PACKAGE_PREFIX_WOW PrefixWow ;
  557. ULONG PackageCount ;
  558. BOOL WowClient = FALSE ;
  559. PNEG_PACKAGE Package ;
  560. PLIST_ENTRY Scan ;
  561. SECPKG_CALL_INFO CallInfo ;
  562. ULONG Size ;
  563. LsapGetCallInfo( &CallInfo );
  564. if ( CallInfo.Attributes & SECPKG_CALL_WOWCLIENT )
  565. {
  566. WowClient = TRUE;
  567. }
  568. NegReadLockList();
  569. Size = sizeof( NEGOTIATE_PACKAGE_PREFIXES ) +
  570. sizeof( NEGOTIATE_PACKAGE_PREFIX ) * ( NegPackageCount + 1 );
  571. SafeAllocaAllocate(Prefixes, Size);
  572. if ( !Prefixes )
  573. {
  574. NegUnlockList();
  575. return SEC_E_INSUFFICIENT_MEMORY ;
  576. }
  577. Prefixes->MessageType = NegEnumPackagePrefixes ;
  578. Prefixes->Offset = sizeof( NEGOTIATE_PACKAGE_PREFIXES );
  579. //
  580. // We're going to do one or the other, but initializing them both
  581. // makes the compiler happier.
  582. //
  583. Prefix = (PNEGOTIATE_PACKAGE_PREFIX) ( Prefixes + 1 );
  584. PrefixWow = (PNEGOTIATE_PACKAGE_PREFIX_WOW) ( Prefixes + 1);
  585. if ( WowClient )
  586. {
  587. PrefixWow->PackageId = (ULONG) NegPackageId ;
  588. PrefixWow->PrefixLen = sizeof( NegSpnegoMechEncodedOid );
  589. PrefixWow->PackageDataA = NULL ;
  590. PrefixWow->PackageDataW = NULL ;
  591. RtlCopyMemory( PrefixWow->Prefix,
  592. NegSpnegoMechEncodedOid,
  593. sizeof( NegSpnegoMechEncodedOid ) );
  594. PrefixWow++ ;
  595. }
  596. else
  597. {
  598. Prefix->PackageId = NegPackageId ;
  599. Prefix->PrefixLen = sizeof( NegSpnegoMechEncodedOid );
  600. Prefix->PackageDataA = NULL ;
  601. Prefix->PackageDataW = NULL ;
  602. RtlCopyMemory( Prefix->Prefix,
  603. NegSpnegoMechEncodedOid,
  604. sizeof( NegSpnegoMechEncodedOid ) );
  605. Prefix++ ;
  606. }
  607. PackageCount = 1 ;
  608. Scan = NegPackageList.Flink ;
  609. while ( Scan != &NegPackageList )
  610. {
  611. Package = CONTAINING_RECORD( Scan, NEG_PACKAGE, List );
  612. if ( !WowClient )
  613. {
  614. Prefix->PackageId = Package->LsaPackage->dwPackageID ;
  615. Prefix->PrefixLen = Package->PrefixLen ;
  616. Prefix->PackageDataA = NULL ;
  617. Prefix->PackageDataW = NULL ;
  618. RtlCopyMemory( Prefix->Prefix,
  619. Package->Prefix,
  620. Package->PrefixLen );
  621. Prefix++ ;
  622. PackageCount++ ;
  623. }
  624. else
  625. {
  626. if ( Package->LsaPackage->fPackage & SP_WOW_SUPPORT )
  627. {
  628. PrefixWow->PackageId = (ULONG) Package->LsaPackage->dwPackageID ;
  629. PrefixWow->PrefixLen = Package->PrefixLen ;
  630. PrefixWow->PackageDataA = NULL ;
  631. PrefixWow->PackageDataW = NULL ;
  632. RtlCopyMemory( PrefixWow->Prefix,
  633. Package->Prefix,
  634. Package->PrefixLen );
  635. PrefixWow++ ;
  636. PackageCount++ ;
  637. }
  638. }
  639. Scan = Scan->Flink ;
  640. }
  641. NegUnlockList();
  642. //
  643. // Set the final count of packages:
  644. //
  645. Prefixes->PrefixCount = PackageCount ;
  646. Status = LsapAllocateClientBuffer(
  647. NULL,
  648. Size,
  649. ProtocolReturnBuffer );
  650. if ( NT_SUCCESS( Status ) )
  651. {
  652. Status = LsapCopyToClient(
  653. Prefixes,
  654. *ProtocolReturnBuffer,
  655. Size );
  656. *ReturnBufferLength = Size ;
  657. }
  658. SafeAllocaFree(Prefixes);
  659. return Status ;
  660. }
  661. NTSTATUS
  662. NegGetCallerNameCall(
  663. IN PLSA_CLIENT_REQUEST ClientRequest,
  664. IN PVOID ProtocolSubmitBuffer,
  665. IN PVOID ClientBufferBase,
  666. IN ULONG SubmitBufferLength,
  667. OUT PVOID *ProtocolReturnBuffer,
  668. OUT PULONG ReturnBufferLength,
  669. OUT PNTSTATUS ProtocolStatus
  670. )
  671. {
  672. PNEGOTIATE_CALLER_NAME_REQUEST Request ;
  673. PNEGOTIATE_CALLER_NAME_RESPONSE Response ;
  674. PNEGOTIATE_CALLER_NAME_RESPONSE_WOW ResponseWow ;
  675. SECPKG_CLIENT_INFO ClientInfo ;
  676. SECPKG_CALL_INFO CallInfo ;
  677. NTSTATUS Status ;
  678. PNEG_LOGON_SESSION LogonSession ;
  679. ULONG ClientSize ;
  680. PUCHAR Where ;
  681. PVOID ClientBuffer ;
  682. BOOL ReCheckAccess = FALSE ;
  683. *ProtocolReturnBuffer = NULL ;
  684. *ReturnBufferLength = 0 ;
  685. *ProtocolStatus = 0 ;
  686. if ( SubmitBufferLength != sizeof( NEGOTIATE_CALLER_NAME_REQUEST ) )
  687. {
  688. return STATUS_INVALID_PARAMETER ;
  689. }
  690. Request = (PNEGOTIATE_CALLER_NAME_REQUEST) ProtocolSubmitBuffer ;
  691. Status = LsapGetClientInfo( &ClientInfo );
  692. if ( !NT_SUCCESS( Status ) )
  693. {
  694. return Status ;
  695. }
  696. LsapGetCallInfo( &CallInfo );
  697. if ( RtlIsZeroLuid( &Request->LogonId ) )
  698. {
  699. Request->LogonId = ClientInfo.LogonId ;
  700. }
  701. else
  702. {
  703. if ( !RtlEqualLuid( &ClientInfo.LogonId, &Request->LogonId ) )
  704. {
  705. ReCheckAccess = TRUE ;
  706. }
  707. }
  708. LogonSession = NegpLocateLogonSession( &Request->LogonId );
  709. if ( LogonSession )
  710. {
  711. if ( ReCheckAccess )
  712. {
  713. if ( !RtlEqualLuid( &ClientInfo.LogonId, &LogonSession->ParentLogonId ) )
  714. {
  715. Status = STATUS_ACCESS_DENIED ;
  716. goto AccessDeniedError ;
  717. }
  718. }
  719. if ( LogonSession->AlternateName.Buffer == NULL )
  720. {
  721. //
  722. // No alternate ID
  723. //
  724. Status = STATUS_NO_SUCH_LOGON_SESSION ;
  725. goto AccessDeniedError ;
  726. }
  727. ClientSize = sizeof( NEGOTIATE_CALLER_NAME_RESPONSE ) +
  728. LogonSession->AlternateName.Length + sizeof( WCHAR );
  729. SafeAllocaAllocate(Response, ClientSize);
  730. if ( Response )
  731. {
  732. RtlZeroMemory(Response, ClientSize);
  733. ClientBuffer = LsapClientAllocate( ClientSize );
  734. if ( ClientBuffer )
  735. {
  736. Where = (PUCHAR) ClientBuffer + sizeof( NEGOTIATE_CALLER_NAME_RESPONSE ) ;
  737. //
  738. // If a WOW client, copy these to the 32bit locations. Note
  739. // that this will leave a "hole," but that's ok.
  740. //
  741. if ( CallInfo.Attributes & SECPKG_CALL_WOWCLIENT )
  742. {
  743. ResponseWow = (PNEGOTIATE_CALLER_NAME_RESPONSE_WOW) Response ;
  744. ResponseWow->MessageType = NegGetCallerName ;
  745. ResponseWow->CallerName = PtrToUlong(Where) ;
  746. }
  747. else
  748. {
  749. Response->MessageType = NegGetCallerName ;
  750. Response->CallerName = (PWSTR) Where ;
  751. }
  752. RtlCopyMemory( (Response + 1),
  753. LogonSession->AlternateName.Buffer,
  754. LogonSession->AlternateName.Length );
  755. *ProtocolReturnBuffer = ClientBuffer ;
  756. *ReturnBufferLength = ClientSize ;
  757. *ProtocolStatus = 0 ;
  758. Status = LsapCopyToClient( Response,
  759. ClientBuffer,
  760. ClientSize ) ;
  761. }
  762. else
  763. {
  764. Status = STATUS_NO_MEMORY ;
  765. }
  766. SafeAllocaFree(Response);
  767. }
  768. AccessDeniedError:
  769. NegpDerefLogonSession( LogonSession );
  770. }
  771. else
  772. {
  773. Status = STATUS_NO_SUCH_LOGON_SESSION ;
  774. }
  775. *ProtocolStatus = Status ;
  776. return STATUS_SUCCESS ;
  777. }
  778. PNEG_LOGON_SESSION
  779. NegpBuildLogonSession(
  780. PLUID LogonId,
  781. ULONG_PTR LogonPackage,
  782. ULONG_PTR DefaultPackage
  783. )
  784. {
  785. PNEG_LOGON_SESSION LogonSession ;
  786. LogonSession = (PNEG_LOGON_SESSION) LsapAllocatePrivateHeap( sizeof( NEG_LOGON_SESSION ) );
  787. if ( LogonSession )
  788. {
  789. LogonSession->LogonId = *LogonId ;
  790. LogonSession->CreatingPackage = LogonPackage ;
  791. LogonSession->DefaultPackage = DefaultPackage ;
  792. LogonSession->RefCount = 2 ;
  793. RtlEnterCriticalSection( &NegLogonSessionListLock );
  794. InsertHeadList( &NegLogonSessionList, &LogonSession->List );
  795. RtlLeaveCriticalSection( &NegLogonSessionListLock );
  796. }
  797. return LogonSession ;
  798. }
  799. VOID
  800. NegpDerefLogonSession(
  801. PNEG_LOGON_SESSION LogonSession
  802. )
  803. {
  804. BOOL FreeIt = FALSE ;
  805. RtlEnterCriticalSection( &NegLogonSessionListLock );
  806. LogonSession->RefCount-- ;
  807. if ( LogonSession->RefCount == 0 )
  808. {
  809. RemoveEntryList( &LogonSession->List );
  810. FreeIt = TRUE ;
  811. }
  812. RtlLeaveCriticalSection( &NegLogonSessionListLock );
  813. if ( FreeIt )
  814. {
  815. if ( LogonSession->AlternateName.Buffer )
  816. {
  817. LsapFreePrivateHeap( LogonSession->AlternateName.Buffer );
  818. }
  819. LsapFreePrivateHeap( LogonSession );
  820. }
  821. }
  822. VOID
  823. NegpDerefLogonSessionById(
  824. PLUID LogonId
  825. )
  826. {
  827. BOOL FreeIt = FALSE ;
  828. PLIST_ENTRY Scan ;
  829. PNEG_LOGON_SESSION LogonSession = NULL;
  830. RtlEnterCriticalSection( &NegLogonSessionListLock );
  831. Scan = NegLogonSessionList.Flink ;
  832. while ( Scan != &NegLogonSessionList )
  833. {
  834. LogonSession = CONTAINING_RECORD( Scan, NEG_LOGON_SESSION, List );
  835. if ( RtlEqualLuid( LogonId, &LogonSession->LogonId ) )
  836. {
  837. LogonSession->RefCount -- ;
  838. if ( LogonSession->RefCount == 0 )
  839. {
  840. RemoveEntryList( &LogonSession->List );
  841. FreeIt = TRUE ;
  842. }
  843. break;
  844. }
  845. LogonSession = NULL ;
  846. Scan = Scan->Flink ;
  847. }
  848. RtlLeaveCriticalSection( &NegLogonSessionListLock );
  849. if ( FreeIt )
  850. {
  851. DsysAssert( LogonSession != NULL );
  852. if ( LogonSession->AlternateName.Buffer )
  853. {
  854. LsapFreePrivateHeap( LogonSession->AlternateName.Buffer );
  855. }
  856. LsapFreePrivateHeap( LogonSession );
  857. }
  858. }
  859. PNEG_LOGON_SESSION
  860. NegpLocateLogonSession(
  861. PLUID LogonId
  862. )
  863. {
  864. PLIST_ENTRY Scan ;
  865. PNEG_LOGON_SESSION LogonSession = NULL;
  866. RtlEnterCriticalSection( &NegLogonSessionListLock );
  867. Scan = NegLogonSessionList.Flink ;
  868. while ( Scan != &NegLogonSessionList )
  869. {
  870. LogonSession = CONTAINING_RECORD( Scan, NEG_LOGON_SESSION, List );
  871. if ( RtlEqualLuid( LogonId, &LogonSession->LogonId ) )
  872. {
  873. break;
  874. }
  875. LogonSession = NULL ;
  876. Scan = Scan->Flink ;
  877. }
  878. if ( LogonSession )
  879. {
  880. LogonSession->RefCount++ ;
  881. }
  882. RtlLeaveCriticalSection( &NegLogonSessionListLock );
  883. return LogonSession ;
  884. }
  885. NTSTATUS
  886. NTAPI
  887. NegpMapLogonRequest(
  888. IN PVOID ProtocolSubmitBuffer,
  889. IN PVOID ClientBufferBase,
  890. IN ULONG SubmitBufferSize,
  891. OUT PMSV1_0_INTERACTIVE_LOGON * LogonInfo
  892. )
  893. {
  894. NTSTATUS Status = STATUS_SUCCESS ;
  895. PMSV1_0_INTERACTIVE_LOGON Authentication = NULL;
  896. PSECURITY_SEED_AND_LENGTH SeedAndLength;
  897. UCHAR Seed;
  898. //
  899. // Ensure this is really an interactive logon.
  900. //
  901. Authentication =
  902. (PMSV1_0_INTERACTIVE_LOGON) ProtocolSubmitBuffer;
  903. if ( Authentication->MessageType != MsV1_0InteractiveLogon ) {
  904. DebugLog(( DEB_ERROR, "Neg: Bad Validation Class %d\n",
  905. Authentication->MessageType));
  906. Status = STATUS_BAD_VALIDATION_CLASS;
  907. goto Cleanup;
  908. }
  909. //
  910. // If the password length is greater than 255 (i.e., the
  911. // upper byte of the length is non-zero) then the password
  912. // has been run-encoded for privacy reasons. Get the
  913. // run-encode seed out of the upper-byte of the length
  914. // for later use.
  915. //
  916. //
  917. SeedAndLength = (PSECURITY_SEED_AND_LENGTH)
  918. &Authentication->Password.Length;
  919. Seed = SeedAndLength->Seed;
  920. SeedAndLength->Seed = 0;
  921. //
  922. // Enforce length restrictions on username and password.
  923. //
  924. if ( Authentication->UserName.Length > UNLEN ||
  925. Authentication->Password.Length > PWLEN ) {
  926. DebugLog(( DEB_ERROR, "Neg: Name or password too long\n"));
  927. Status = STATUS_NAME_TOO_LONG;
  928. goto Cleanup;
  929. }
  930. //
  931. // Relocate any pointers to be relative to 'Authentication'
  932. //
  933. NULL_RELOCATE_ONE( &Authentication->LogonDomainName );
  934. RELOCATE_ONE( &Authentication->UserName );
  935. NULL_RELOCATE_ONE( &Authentication->Password );
  936. //
  937. // Now decode the password, if necessary
  938. //
  939. if (Seed != 0 ) {
  940. __try {
  941. RtlRunDecodeUnicodeString( Seed, &Authentication->Password);
  942. } __except(EXCEPTION_EXECUTE_HANDLER) {
  943. Status = STATUS_ILL_FORMED_PASSWORD;
  944. goto Cleanup;
  945. }
  946. }
  947. *LogonInfo = Authentication ;
  948. Cleanup:
  949. return Status ;
  950. }
  951. VOID
  952. NegpDerefTrustList(
  953. PNEG_TRUST_LIST TrustList
  954. )
  955. {
  956. RtlEnterCriticalSection( &NegTrustListLock );
  957. TrustList->RefCount-- ;
  958. if ( TrustList->RefCount == 0 )
  959. {
  960. if( NegTrustList == TrustList )
  961. {
  962. NegTrustList = NULL;
  963. }
  964. RtlLeaveCriticalSection( &NegTrustListLock );
  965. NetApiBufferFree( TrustList->Trusts );
  966. LsapFreePrivateHeap( TrustList );
  967. return;
  968. }
  969. RtlLeaveCriticalSection( &NegTrustListLock );
  970. }
  971. PNEG_TRUST_LIST
  972. NegpGetTrustList(
  973. VOID
  974. )
  975. {
  976. PDS_DOMAIN_TRUSTS Trusts = NULL;
  977. DWORD TrustCount ;
  978. PNEG_TRUST_LIST TrustList = NULL ;
  979. DWORD NetStatus ;
  980. LARGE_INTEGER Now ;
  981. BOOLEAN TrustListLocked = TRUE;
  982. GetSystemTimeAsFileTime( (LPFILETIME) &Now );
  983. RtlEnterCriticalSection( &NegTrustListLock );
  984. if ( Now.QuadPart > NegTrustTime.QuadPart + FIFTEEN_MINUTES )
  985. {
  986. if( NegTrustList != NULL && NegTrustList->RefCount == 1 )
  987. {
  988. NegpDerefTrustList( NegTrustList );
  989. NegTrustList = NULL;
  990. }
  991. }
  992. if( NegTrustList != NULL )
  993. {
  994. TrustList = NegTrustList ;
  995. TrustList->RefCount++ ;
  996. goto Cleanup;
  997. }
  998. RtlLeaveCriticalSection( &NegTrustListLock );
  999. TrustListLocked = FALSE;
  1000. NetStatus = DsEnumerateDomainTrustsW( NULL,
  1001. DS_DOMAIN_IN_FOREST |
  1002. DS_DOMAIN_PRIMARY,
  1003. &Trusts,
  1004. &TrustCount );
  1005. if ( NetStatus != 0 )
  1006. {
  1007. goto Cleanup;
  1008. }
  1009. TrustList = (PNEG_TRUST_LIST) LsapAllocatePrivateHeap( sizeof( NEG_TRUST_LIST ) );
  1010. if( TrustList == NULL )
  1011. {
  1012. goto Cleanup;
  1013. }
  1014. TrustList->RefCount = 2 ;
  1015. TrustList->TrustCount = TrustCount ;
  1016. TrustList->Trusts = Trusts ;
  1017. RtlEnterCriticalSection( &NegTrustListLock );
  1018. TrustListLocked = TRUE;
  1019. if( NegTrustList != NULL )
  1020. {
  1021. PNEG_TRUST_LIST FreeTrustList = TrustList;
  1022. TrustList = NegTrustList ;
  1023. TrustList->RefCount++ ;
  1024. RtlLeaveCriticalSection( &NegTrustListLock );
  1025. TrustListLocked = FALSE;
  1026. LsapFreePrivateHeap( FreeTrustList );
  1027. goto Cleanup;
  1028. }
  1029. Trusts = NULL;
  1030. NegTrustList = TrustList ;
  1031. NegTrustTime = Now ;
  1032. Cleanup:
  1033. if( TrustListLocked )
  1034. {
  1035. RtlLeaveCriticalSection( &NegTrustListLock );
  1036. }
  1037. if( Trusts != NULL )
  1038. {
  1039. NetApiBufferFree( Trusts );
  1040. }
  1041. return TrustList ;
  1042. }
  1043. NEG_DOMAIN_TYPES
  1044. NegpIsUplevelDomain(
  1045. PLUID LogonId,
  1046. SECURITY_LOGON_TYPE LogonType,
  1047. PUNICODE_STRING Domain
  1048. )
  1049. {
  1050. PNEG_TRUST_LIST TrustList ;
  1051. UNICODE_STRING String ;
  1052. ULONG i ;
  1053. BOOL IsUplevel = FALSE ;
  1054. LONG Error ;
  1055. PDOMAIN_CONTROLLER_INFOW Info ;
  1056. UNREFERENCED_PARAMETER(LogonId);
  1057. //
  1058. // Case #1. Local logons are not uplevel, and should be allowed to
  1059. // use NTLM right off the bat. Therefore, return false
  1060. //
  1061. if ( RtlEqualUnicodeString(
  1062. Domain,
  1063. &MachineName,
  1064. TRUE ) )
  1065. {
  1066. return NegLocalDomain;
  1067. }
  1068. if ( LogonType == CachedInteractive )
  1069. {
  1070. return NegUpLevelDomain;
  1071. }
  1072. //
  1073. // Case #2. We logged on to a domain, but we need to check if it is
  1074. // an uplevel domain in our forest. If it is, then return true, otherwise
  1075. // it's not an uplevel domain and NTLM is acceptable. If we can't obtain the
  1076. // trust list, assume downlevel.
  1077. //
  1078. TrustList = NegpGetTrustList();
  1079. if ( TrustList )
  1080. {
  1081. for ( i = 0 ; i < TrustList->TrustCount ; i++ )
  1082. {
  1083. RtlInitUnicodeString( &String, TrustList->Trusts[i].NetbiosDomainName );
  1084. if ( RtlEqualUnicodeString( Domain,
  1085. &String,
  1086. TRUE ) )
  1087. {
  1088. //
  1089. // Hit, check it
  1090. //
  1091. if ( ( TrustList->Trusts[i].DnsDomainName != NULL ) &&
  1092. ( TrustList->Trusts[i].Flags & DS_DOMAIN_IN_FOREST ) )
  1093. {
  1094. IsUplevel = TRUE ;
  1095. break;
  1096. }
  1097. }
  1098. }
  1099. NegpDerefTrustList( TrustList );
  1100. }
  1101. if ( IsUplevel )
  1102. {
  1103. return NegUpLevelDomain ;
  1104. }
  1105. //
  1106. // Case #3 - if this is an uplevel domain we live in, then the answer returned
  1107. // by netlogon is authoritative:
  1108. //
  1109. if ( NegUplevelDomain )
  1110. {
  1111. return NegDownLevelDomain ;
  1112. }
  1113. //
  1114. // Case #4 - if we are living in a downlevel domain, netlogon won't know if the domain
  1115. // we just talked to is uplevel or downlevel. So, we need to figure out directly.
  1116. //
  1117. Error = DsGetDcNameW(
  1118. NULL,
  1119. Domain->Buffer,
  1120. NULL,
  1121. NULL,
  1122. DS_DIRECTORY_SERVICE_REQUIRED,
  1123. &Info );
  1124. if ( Error == 0 )
  1125. {
  1126. IsUplevel = TRUE ;
  1127. NetApiBufferFree( Info );
  1128. }
  1129. else
  1130. {
  1131. IsUplevel = FALSE ;
  1132. }
  1133. return ( IsUplevel ? NegUpLevelTrustedDomain : NegDownLevelDomain );
  1134. }
  1135. //+-------------------------------------------------------------------------
  1136. //
  1137. // Function: NegpCloneLogonSession
  1138. //
  1139. // Synopsis: Handles a NewCredentials type of logon.
  1140. //
  1141. // Effects:
  1142. //
  1143. // Arguments:
  1144. //
  1145. // Requires:
  1146. //
  1147. // Returns:
  1148. //
  1149. // Notes:
  1150. //
  1151. //
  1152. //--------------------------------------------------------------------------
  1153. NTSTATUS
  1154. NTAPI
  1155. NegpCloneLogonSession(
  1156. IN PVOID ProtocolSubmitBuffer,
  1157. IN PVOID ClientBufferBase,
  1158. IN ULONG SubmitBufferSize,
  1159. OUT PVOID *ProfileBuffer,
  1160. OUT PULONG ProfileBufferLength,
  1161. OUT PLUID NewLogonId,
  1162. OUT PNTSTATUS ApiSubStatus,
  1163. OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
  1164. OUT PVOID *TokenInformation,
  1165. OUT PUNICODE_STRING *AccountName,
  1166. OUT PUNICODE_STRING *AuthenticatingAuthority,
  1167. OUT PUNICODE_STRING *MachineName,
  1168. OUT PSECPKG_PRIMARY_CRED PrimaryCredentials,
  1169. OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY * CachedCredentials
  1170. )
  1171. {
  1172. NTSTATUS Status;
  1173. HANDLE hToken;
  1174. UCHAR SmallBuffer[ 128 ];
  1175. PLSA_TOKEN_INFORMATION_V1 TokenInfo = NULL;
  1176. PTOKEN_USER User = NULL;
  1177. PTOKEN_GROUPS Groups = NULL;
  1178. PTOKEN_GROUPS FinalGroups = NULL;
  1179. PTOKEN_PRIMARY_GROUP PrimaryGroup = NULL;
  1180. TOKEN_STATISTICS TokenStats;
  1181. PLSAP_LOGON_SESSION LogonSession = NULL;
  1182. PNEG_LOGON_SESSION NegLogonSession;
  1183. LUID LogonId;
  1184. LUID LocalServiceLuid = LOCALSERVICE_LUID;
  1185. LUID NetworkServiceLuid = NETWORKSERVICE_LUID;
  1186. LUID LocalSystemLuid = SYSTEM_LUID;
  1187. BOOL fFilterGroups;
  1188. PMSV1_0_INTERACTIVE_LOGON Authentication = NULL;
  1189. DWORD Size;
  1190. ULONG i;
  1191. ULONG j;
  1192. PWSTR AltName, AltNameScan;
  1193. Status = LsapImpersonateClient();
  1194. if ( !NT_SUCCESS( Status ) )
  1195. {
  1196. return Status ;
  1197. }
  1198. //
  1199. // Open the token for the lifetime of this call. This makes sure that the
  1200. // client doesn't die on us, taking out the logon session (potentially).
  1201. //
  1202. Status = NtOpenThreadToken(
  1203. NtCurrentThread(),
  1204. TOKEN_QUERY,
  1205. TRUE,
  1206. &hToken );
  1207. RevertToSelf();
  1208. if ( !NT_SUCCESS( Status ) )
  1209. {
  1210. return Status ;
  1211. }
  1212. //
  1213. // Grovel the token, and build up a list of groups that we will use for
  1214. // the new token. Only non-builtin groups will be used.
  1215. //
  1216. TokenInfo = (PLSA_TOKEN_INFORMATION_V1) LsapAllocateLsaHeap(
  1217. sizeof( LSA_TOKEN_INFORMATION_V1) );
  1218. if ( !TokenInfo )
  1219. {
  1220. Status = STATUS_NO_MEMORY ;
  1221. goto Clone_Exit ;
  1222. }
  1223. Status = NtQueryInformationToken(
  1224. hToken,
  1225. TokenStatistics,
  1226. &TokenStats,
  1227. sizeof( TokenStats ),
  1228. &Size );
  1229. if ( !NT_SUCCESS( Status ) )
  1230. {
  1231. goto Clone_Exit ;
  1232. }
  1233. TokenInfo->ExpirationTime = TokenStats.ExpirationTime ;
  1234. User = (PTOKEN_USER) SmallBuffer ;
  1235. Size = sizeof( SmallBuffer );
  1236. Status = NtQueryInformationToken(
  1237. hToken,
  1238. TokenUser,
  1239. User,
  1240. Size,
  1241. &Size );
  1242. if ( ( Status == STATUS_BUFFER_OVERFLOW ) ||
  1243. ( Status == STATUS_BUFFER_TOO_SMALL ) )
  1244. {
  1245. SafeAllocaAllocate(User, Size);
  1246. if ( User )
  1247. {
  1248. Status = NtQueryInformationToken(
  1249. hToken,
  1250. TokenUser,
  1251. User,
  1252. Size,
  1253. &Size );
  1254. }
  1255. else
  1256. {
  1257. Status = STATUS_NO_MEMORY ;
  1258. }
  1259. }
  1260. if ( !NT_SUCCESS( Status ) )
  1261. {
  1262. goto Clone_Exit ;
  1263. }
  1264. TokenInfo->User.User.Attributes = 0 ;
  1265. TokenInfo->User.User.Sid = LsapAllocateLsaHeap( RtlLengthSid( User->User.Sid ) );
  1266. if ( TokenInfo->User.User.Sid )
  1267. {
  1268. RtlCopyMemory( TokenInfo->User.User.Sid,
  1269. User->User.Sid,
  1270. RtlLengthSid( User->User.Sid ) );
  1271. }
  1272. else
  1273. {
  1274. Status = STATUS_NO_MEMORY ;
  1275. goto Clone_Exit ;
  1276. }
  1277. if ( User != (PTOKEN_USER) SmallBuffer )
  1278. {
  1279. SafeAllocaFree( User );
  1280. }
  1281. User = NULL ;
  1282. Status = NtQueryInformationToken(
  1283. hToken,
  1284. TokenGroups,
  1285. NULL,
  1286. 0,
  1287. &Size );
  1288. if ( ( Status != STATUS_BUFFER_OVERFLOW ) &&
  1289. ( Status != STATUS_BUFFER_TOO_SMALL ) )
  1290. {
  1291. goto Clone_Exit ;
  1292. }
  1293. SafeAllocaAllocate(Groups, Size);
  1294. if ( !Groups )
  1295. {
  1296. Status = STATUS_NO_MEMORY ;
  1297. goto Clone_Exit ;
  1298. }
  1299. Status = NtQueryInformationToken(
  1300. hToken,
  1301. TokenGroups,
  1302. Groups,
  1303. Size,
  1304. &Size );
  1305. if ( !NT_SUCCESS( Status ) )
  1306. {
  1307. goto Clone_Exit ;
  1308. }
  1309. //
  1310. // Grovel through the group list, and ditch those we don't care about.
  1311. // i always travels ahead of j. Skip groups that have one or two RIDs,
  1312. // because those are the builtin ones.
  1313. //
  1314. FinalGroups = (PTOKEN_GROUPS) LsapAllocatePrivateHeap( sizeof( TOKEN_GROUPS ) +
  1315. Groups->GroupCount * sizeof( SID_AND_ATTRIBUTES ) );
  1316. if ( !FinalGroups )
  1317. {
  1318. goto Clone_Exit ;
  1319. }
  1320. //
  1321. // Don't filter out groups for tokens where the LSA has hardcoded info on
  1322. // how to build the token. If we filter in those cases, we strip out SIDs
  1323. // that won't be replaced by the LSA policy/filter routines later on.
  1324. //
  1325. fFilterGroups = !RtlEqualLuid(&TokenStats.AuthenticationId, &LocalSystemLuid) &&
  1326. !RtlEqualLuid(&TokenStats.AuthenticationId, &LocalServiceLuid) &&
  1327. !RtlEqualLuid(&TokenStats.AuthenticationId, &NetworkServiceLuid);
  1328. for ( i = 0, j = 0 ; i < Groups->GroupCount ; i++ )
  1329. {
  1330. if ( !fFilterGroups || *RtlSubAuthorityCountSid( Groups->Groups[ i ].Sid ) > 2 )
  1331. {
  1332. FinalGroups->Groups[ j ].Attributes = Groups->Groups[ i ].Attributes ;
  1333. Status = LsapDuplicateSid2( &FinalGroups->Groups[ j ].Sid,
  1334. Groups->Groups[ i ].Sid );
  1335. j++ ;
  1336. if( !NT_SUCCESS(Status) )
  1337. {
  1338. break;
  1339. }
  1340. }
  1341. }
  1342. FinalGroups->GroupCount = j ;
  1343. if ( !NT_SUCCESS( Status ) )
  1344. {
  1345. goto Clone_Exit ;
  1346. }
  1347. //
  1348. // whew. Set this in the token info, and null out the other pointer
  1349. // so we don't free it inadvertantly.
  1350. //
  1351. TokenInfo->Groups = FinalGroups ;
  1352. FinalGroups = NULL ;
  1353. //
  1354. // Determine the primary group:
  1355. //
  1356. PrimaryGroup = (PTOKEN_PRIMARY_GROUP) SmallBuffer ;
  1357. Size = sizeof( SmallBuffer );
  1358. Status = NtQueryInformationToken(
  1359. hToken,
  1360. TokenPrimaryGroup,
  1361. PrimaryGroup,
  1362. Size,
  1363. &Size );
  1364. if ( ( Status == STATUS_BUFFER_OVERFLOW ) ||
  1365. ( Status == STATUS_BUFFER_TOO_SMALL ) )
  1366. {
  1367. SafeAllocaAllocate(PrimaryGroup, Size);
  1368. Status = NtQueryInformationToken(
  1369. hToken,
  1370. TokenPrimaryGroup,
  1371. PrimaryGroup,
  1372. Size,
  1373. &Size );
  1374. }
  1375. if ( !NT_SUCCESS( Status ) )
  1376. {
  1377. goto Clone_Exit ;
  1378. }
  1379. TokenInfo->PrimaryGroup.PrimaryGroup = LsapAllocateLsaHeap(RtlLengthSid(PrimaryGroup->PrimaryGroup));
  1380. if ( TokenInfo->PrimaryGroup.PrimaryGroup )
  1381. {
  1382. RtlCopyMemory( TokenInfo->PrimaryGroup.PrimaryGroup,
  1383. PrimaryGroup->PrimaryGroup,
  1384. RtlLengthSid( PrimaryGroup->PrimaryGroup ) );
  1385. }
  1386. else
  1387. {
  1388. Status = STATUS_NO_MEMORY ;
  1389. goto Clone_Exit ;
  1390. }
  1391. if ( PrimaryGroup != (PTOKEN_PRIMARY_GROUP) SmallBuffer )
  1392. {
  1393. SafeAllocaFree(PrimaryGroup);
  1394. }
  1395. PrimaryGroup = NULL ;
  1396. //
  1397. // Almost there -- now dupe the privileges.
  1398. //
  1399. TokenInfo->Privileges = NULL ;
  1400. Size = 0;
  1401. Status = NtQueryInformationToken(
  1402. hToken,
  1403. TokenPrivileges,
  1404. TokenInfo->Privileges,
  1405. Size,
  1406. &Size );
  1407. if ( ( Status == STATUS_BUFFER_OVERFLOW ) ||
  1408. ( Status == STATUS_BUFFER_TOO_SMALL ) )
  1409. {
  1410. TokenInfo->Privileges = (PTOKEN_PRIVILEGES) LsapAllocateLsaHeap(Size);
  1411. if (TokenInfo->Privileges == NULL)
  1412. {
  1413. Status = STATUS_NO_MEMORY;
  1414. }
  1415. else
  1416. {
  1417. Status = NtQueryInformationToken(
  1418. hToken,
  1419. TokenPrivileges,
  1420. TokenInfo->Privileges,
  1421. Size,
  1422. &Size);
  1423. }
  1424. }
  1425. if ( !NT_SUCCESS( Status ) )
  1426. {
  1427. goto Clone_Exit ;
  1428. }
  1429. //
  1430. // Ok, we have completed the Token Information. Now, we need to parse
  1431. // the supplied buffer to come up with creds for the other packages, since
  1432. // that's what this is all about
  1433. //
  1434. Status = NegpMapLogonRequest(
  1435. ProtocolSubmitBuffer,
  1436. ClientBufferBase,
  1437. SubmitBufferSize,
  1438. &Authentication );
  1439. if ( !NT_SUCCESS( Status ) )
  1440. {
  1441. goto Clone_Exit ;
  1442. }
  1443. //
  1444. // Stuff the names:
  1445. //
  1446. *AccountName = (PUNICODE_STRING) LsapAllocateLsaHeap( sizeof( UNICODE_STRING ) );
  1447. if ( ! ( *AccountName ) )
  1448. {
  1449. Status = STATUS_NO_MEMORY ;
  1450. goto Clone_Exit ;
  1451. }
  1452. *AuthenticatingAuthority = (PUNICODE_STRING) LsapAllocateLsaHeap( sizeof( UNICODE_STRING ) );
  1453. if ( ! ( *AuthenticatingAuthority ) )
  1454. {
  1455. Status = STATUS_NO_MEMORY ;
  1456. goto Clone_Exit ;
  1457. }
  1458. *MachineName = (PUNICODE_STRING) LsapAllocateLsaHeap( sizeof( UNICODE_STRING ) );
  1459. if ( ! ( *MachineName ) )
  1460. {
  1461. Status = STATUS_NO_MEMORY ;
  1462. goto Clone_Exit ;
  1463. }
  1464. //
  1465. // Tokens that the LSA normally constructs (SYSTEM, LocalService, NetworkService)
  1466. // have special names for returned as part of SID --> name lookups that don't
  1467. // necessarily match what's in the token as the account/authority names. Cruft
  1468. // up the new token with these special names instead of the standard ones.
  1469. //
  1470. if (fFilterGroups)
  1471. {
  1472. Status = LsapGetLogonSessionAccountInfo(
  1473. &TokenStats.AuthenticationId,
  1474. (*AccountName),
  1475. (*AuthenticatingAuthority) );
  1476. }
  1477. else
  1478. {
  1479. LSAP_WELL_KNOWN_SID_INDEX dwIndex = LsapLocalSystemSidIndex;
  1480. if (RtlEqualLuid(&TokenStats.AuthenticationId, &LocalServiceLuid))
  1481. {
  1482. dwIndex = LsapLocalServiceSidIndex;
  1483. }
  1484. else if (RtlEqualLuid(&TokenStats.AuthenticationId, &NetworkServiceLuid))
  1485. {
  1486. dwIndex = LsapNetworkServiceSidIndex;
  1487. }
  1488. Status = LsapDuplicateString(*AccountName,
  1489. LsapDbWellKnownSidName(dwIndex));
  1490. if ( !NT_SUCCESS( Status ) )
  1491. {
  1492. goto Clone_Exit ;
  1493. }
  1494. Status = LsapDuplicateString(*AuthenticatingAuthority,
  1495. LsapDbWellKnownSidDescription(dwIndex));
  1496. }
  1497. if ( !NT_SUCCESS( Status ) )
  1498. {
  1499. goto Clone_Exit ;
  1500. }
  1501. //
  1502. // Construct the credential data to pass on to the other packages:
  1503. //
  1504. Status = LsapDuplicateString( &PrimaryCredentials->DomainName,
  1505. &Authentication->LogonDomainName );
  1506. if ( !NT_SUCCESS( Status ) )
  1507. {
  1508. goto Clone_Exit ;
  1509. }
  1510. Status = LsapDuplicateString( &PrimaryCredentials->DownlevelName,
  1511. &Authentication->UserName );
  1512. if ( !NT_SUCCESS( Status ) )
  1513. {
  1514. goto Clone_Exit ;
  1515. }
  1516. Status = LsapDuplicateString( &PrimaryCredentials->Password,
  1517. &Authentication->Password );
  1518. if ( !NT_SUCCESS( Status ) )
  1519. {
  1520. goto Clone_Exit ;
  1521. }
  1522. Status = LsapDuplicateSid( &PrimaryCredentials->UserSid,
  1523. TokenInfo->User.User.Sid );
  1524. if ( !NT_SUCCESS( Status ) )
  1525. {
  1526. goto Clone_Exit ;
  1527. }
  1528. PrimaryCredentials->Flags = PRIMARY_CRED_CLEAR_PASSWORD ;
  1529. //
  1530. // Let the LSA do the rest:
  1531. //
  1532. NtAllocateLocallyUniqueId( &LogonId );
  1533. Status = LsapCreateLogonSession( &LogonId );
  1534. if ( !NT_SUCCESS( Status ) )
  1535. {
  1536. goto Clone_Exit ;
  1537. }
  1538. //
  1539. // save away username and domainname for auditing
  1540. //
  1541. LogonSession = LsapLocateLogonSession( &LogonId );
  1542. if (LogonSession == NULL)
  1543. {
  1544. ASSERT(LogonSession != NULL);
  1545. Status = STATUS_NO_SUCH_LOGON_SESSION;
  1546. goto Clone_Exit;
  1547. }
  1548. Status = LsapDuplicateString( &LogonSession->NewAuthorityName,
  1549. &Authentication->LogonDomainName );
  1550. if ( !NT_SUCCESS( Status ) )
  1551. {
  1552. goto Clone_Exit ;
  1553. }
  1554. Status = LsapDuplicateString( &LogonSession->NewAccountName,
  1555. &Authentication->UserName );
  1556. if ( !NT_SUCCESS( Status ) )
  1557. {
  1558. goto Clone_Exit ;
  1559. }
  1560. NegLogonSession = NegpBuildLogonSession( &LogonId,
  1561. NegPackageId,
  1562. NegPackageId );
  1563. if ( !NegLogonSession )
  1564. {
  1565. Status = STATUS_NO_MEMORY ;
  1566. goto Clone_Exit;
  1567. }
  1568. AltName = (PWSTR) LsapAllocatePrivateHeap( Authentication->UserName.Length +
  1569. Authentication->LogonDomainName.Length +
  1570. 2 * sizeof( WCHAR ) );
  1571. if ( AltName )
  1572. {
  1573. AltNameScan = AltName ;
  1574. RtlCopyMemory( AltNameScan,
  1575. Authentication->LogonDomainName.Buffer,
  1576. Authentication->LogonDomainName.Length );
  1577. AltNameScan += Authentication->LogonDomainName.Length / sizeof(WCHAR) ;
  1578. *AltNameScan++ = L'\\';
  1579. RtlCopyMemory( AltNameScan,
  1580. Authentication->UserName.Buffer,
  1581. Authentication->UserName.Length );
  1582. AltNameScan += Authentication->UserName.Length / sizeof( WCHAR ) ;
  1583. *AltNameScan++ = L'\0';
  1584. RtlInitUnicodeString( &NegLogonSession->AlternateName, AltName );
  1585. }
  1586. NegLogonSession->ParentLogonId = TokenStats.AuthenticationId ;
  1587. NegpDerefLogonSession( NegLogonSession );
  1588. PrimaryCredentials->LogonId = LogonId ;
  1589. *ProfileBuffer = NULL ;
  1590. *ProfileBufferLength = 0 ;
  1591. *NewLogonId = LogonId ;
  1592. *ApiSubStatus = STATUS_SUCCESS ;
  1593. *TokenInformationType = LsaTokenInformationV1 ;
  1594. *TokenInformation = TokenInfo ;
  1595. TokenInfo = NULL ;
  1596. *CachedCredentials = NULL ;
  1597. Clone_Exit:
  1598. SafeAllocaFree(Groups);
  1599. if ( FinalGroups )
  1600. {
  1601. LsapFreeTokenGroups( FinalGroups );
  1602. }
  1603. if ( TokenInfo )
  1604. {
  1605. if ( TokenInfo->User.User.Sid )
  1606. {
  1607. LsapFreeLsaHeap( TokenInfo->User.User.Sid );
  1608. }
  1609. if ( TokenInfo->Groups )
  1610. {
  1611. LsapFreeTokenGroups( TokenInfo->Groups );
  1612. }
  1613. if ( TokenInfo->Privileges )
  1614. {
  1615. LsapFreeLsaHeap( TokenInfo->Privileges );
  1616. }
  1617. LsapFreeLsaHeap( TokenInfo );
  1618. }
  1619. if (User != (PTOKEN_USER) SmallBuffer)
  1620. {
  1621. SafeAllocaFree(User);
  1622. }
  1623. if ( PrimaryGroup != (PTOKEN_PRIMARY_GROUP) SmallBuffer )
  1624. {
  1625. SafeAllocaFree(PrimaryGroup);
  1626. }
  1627. if ( hToken != NULL )
  1628. {
  1629. NtClose( hToken );
  1630. }
  1631. if ( !NT_SUCCESS( Status ) )
  1632. {
  1633. if ( *AuthenticatingAuthority )
  1634. {
  1635. if ( (*AuthenticatingAuthority)->Buffer )
  1636. {
  1637. LsapFreeLsaHeap( (*AuthenticatingAuthority)->Buffer );
  1638. }
  1639. LsapFreeLsaHeap( *AuthenticatingAuthority );
  1640. *AuthenticatingAuthority = NULL;
  1641. }
  1642. if ( *AccountName )
  1643. {
  1644. if ( (*AccountName)->Buffer )
  1645. {
  1646. LsapFreeLsaHeap( (*AccountName)->Buffer );
  1647. }
  1648. LsapFreeLsaHeap( *AccountName );
  1649. *AccountName = NULL;
  1650. }
  1651. if ( *MachineName )
  1652. {
  1653. if ( (*MachineName)->Buffer )
  1654. {
  1655. LsapFreeLsaHeap( (*MachineName)->Buffer );
  1656. }
  1657. LsapFreeLsaHeap( *MachineName );
  1658. *MachineName = NULL;
  1659. }
  1660. }
  1661. if (LogonSession)
  1662. {
  1663. LsapReleaseLogonSession(LogonSession);
  1664. }
  1665. return Status;
  1666. }
  1667. //+-------------------------------------------------------------------------
  1668. //
  1669. // Function: NegLogonUserEx2
  1670. //
  1671. // Synopsis: Handles service, batch, and interactive logons
  1672. //
  1673. // Effects:
  1674. //
  1675. // Arguments:
  1676. //
  1677. // Requires:
  1678. //
  1679. // Returns:
  1680. //
  1681. // Notes:
  1682. //
  1683. //
  1684. //--------------------------------------------------------------------------
  1685. NTSTATUS
  1686. NTAPI
  1687. NegLogonUserEx2(
  1688. IN PLSA_CLIENT_REQUEST ClientRequest,
  1689. IN SECURITY_LOGON_TYPE LogonType,
  1690. IN PVOID ProtocolSubmitBuffer,
  1691. IN PVOID ClientBufferBase,
  1692. IN ULONG SubmitBufferSize,
  1693. OUT PVOID *ProfileBuffer,
  1694. OUT PULONG ProfileBufferLength,
  1695. OUT PLUID NewLogonId,
  1696. OUT PNTSTATUS ApiSubStatus,
  1697. OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
  1698. OUT PVOID *TokenInformation,
  1699. OUT PUNICODE_STRING *AccountName,
  1700. OUT PUNICODE_STRING *AuthenticatingAuthority,
  1701. OUT PUNICODE_STRING *MachineName,
  1702. OUT PSECPKG_PRIMARY_CRED PrimaryCredentials,
  1703. OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY * CachedCredentials
  1704. )
  1705. {
  1706. NTSTATUS Status = STATUS_NO_LOGON_SERVERS;
  1707. PNEG_PACKAGE Package;
  1708. PVOID LocalSubmitBuffer = ProtocolSubmitBuffer;
  1709. ULONG_PTR CurrentPackageId = GetCurrentPackageId();
  1710. PLSAP_SECURITY_PACKAGE * LogonPackages = NULL;
  1711. PNEG_LOGON_SESSION LogonSession ;
  1712. PWSTR AltName, AltNameScan ;
  1713. NEG_DOMAIN_TYPES DomainType ;
  1714. ULONG LogonPackageCount = 0;
  1715. ULONG Index;
  1716. if ( LogonType == NewCredentials )
  1717. {
  1718. ULONG ulTempSize = SubmitBufferSize;
  1719. #if _WIN64
  1720. Status = NegpConvertWOWInteractiveLogonBuffer(ProtocolSubmitBuffer,
  1721. ClientBufferBase,
  1722. &ulTempSize,
  1723. &LocalSubmitBuffer);
  1724. if (!NT_SUCCESS(Status))
  1725. {
  1726. return Status;
  1727. }
  1728. #endif // _WIN64
  1729. Status = NegpCloneLogonSession(LocalSubmitBuffer,
  1730. ClientBufferBase,
  1731. ulTempSize,
  1732. ProfileBuffer,
  1733. ProfileBufferLength,
  1734. NewLogonId,
  1735. ApiSubStatus,
  1736. TokenInformationType,
  1737. TokenInformation,
  1738. AccountName,
  1739. AuthenticatingAuthority,
  1740. MachineName,
  1741. PrimaryCredentials,
  1742. CachedCredentials);
  1743. #if _WIN64
  1744. if (ProtocolSubmitBuffer != LocalSubmitBuffer)
  1745. {
  1746. ZeroMemory(LocalSubmitBuffer, ulTempSize);
  1747. LsapFreePrivateHeap(LocalSubmitBuffer);
  1748. }
  1749. #endif // _WIN64
  1750. return Status;
  1751. }
  1752. //
  1753. // Allocate a local copy of the submit buffer so each package can
  1754. // mark it up.
  1755. //
  1756. LocalSubmitBuffer = LsapAllocateLsaHeap(SubmitBufferSize);
  1757. if (LocalSubmitBuffer == NULL)
  1758. {
  1759. return(STATUS_INSUFFICIENT_RESOURCES);
  1760. }
  1761. if ( LogonType == Service )
  1762. {
  1763. ULONG ulAccountId;
  1764. //
  1765. // Copy the submit buffer for the package to mark up
  1766. //
  1767. RtlCopyMemory(
  1768. LocalSubmitBuffer,
  1769. ProtocolSubmitBuffer,
  1770. SubmitBufferSize
  1771. );
  1772. if (NegpIsLocalOrNetworkService(
  1773. LocalSubmitBuffer,
  1774. ClientBufferBase,
  1775. SubmitBufferSize,
  1776. AccountName,
  1777. AuthenticatingAuthority,
  1778. MachineName,
  1779. &ulAccountId))
  1780. {
  1781. Status = NegpMakeServiceToken(
  1782. ulAccountId,
  1783. NewLogonId,
  1784. ProfileBuffer,
  1785. ProfileBufferLength,
  1786. ApiSubStatus,
  1787. TokenInformationType,
  1788. TokenInformation,
  1789. AccountName,
  1790. AuthenticatingAuthority,
  1791. MachineName,
  1792. PrimaryCredentials,
  1793. CachedCredentials
  1794. );
  1795. goto Cleanup;
  1796. }
  1797. }
  1798. SafeAllocaAllocate(LogonPackages, NegPackageCount * sizeof(PLSAP_SECURITY_PACKAGE));
  1799. if (LogonPackages == NULL)
  1800. {
  1801. Status = STATUS_INSUFFICIENT_RESOURCES;
  1802. goto Cleanup;
  1803. }
  1804. NegReadLockList();
  1805. Package = (PNEG_PACKAGE) NegPackageList.Flink ;
  1806. while ( (PVOID) Package != (PVOID) &NegPackageList )
  1807. {
  1808. if (((Package->LsaPackage->fCapabilities & SECPKG_FLAG_LOGON) != 0) &&
  1809. ((Package->Flags & NEG_PACKAGE_EXTRA_OID ) == 0 ) &&
  1810. (Package->LsaPackage->FunctionTable.LogonUserEx2 != NULL))
  1811. {
  1812. LogonPackages[LogonPackageCount++] = Package->LsaPackage;
  1813. }
  1814. Package = (PNEG_PACKAGE) Package->List.Flink ;
  1815. }
  1816. NegUnlockList();
  1817. for (Index = 0; Index < LogonPackageCount; Index++)
  1818. {
  1819. //
  1820. // Cleanup the old audit strings so they don't get leaked
  1821. // when the package re-allocates them.
  1822. //
  1823. if ((*MachineName) != NULL) {
  1824. if ((*MachineName)->Buffer != NULL) {
  1825. LsapFreeLsaHeap( (*MachineName)->Buffer );
  1826. }
  1827. LsapFreeLsaHeap( (*MachineName) );
  1828. (*MachineName) = NULL;
  1829. }
  1830. if ((*AccountName) != NULL) {
  1831. if ((*AccountName)->Buffer != NULL) {
  1832. LsapFreeLsaHeap( (*AccountName)->Buffer );
  1833. }
  1834. LsapFreeLsaHeap( (*AccountName) );
  1835. (*AccountName) = NULL ;
  1836. }
  1837. if ((*AuthenticatingAuthority) != NULL) {
  1838. if ((*AuthenticatingAuthority)->Buffer != NULL) {
  1839. LsapFreeLsaHeap( (*AuthenticatingAuthority)->Buffer );
  1840. }
  1841. LsapFreeLsaHeap( (*AuthenticatingAuthority) );
  1842. (*AuthenticatingAuthority) = NULL ;
  1843. }
  1844. //
  1845. // Copy the submit buffer for the package to mark up
  1846. //
  1847. RtlCopyMemory(
  1848. LocalSubmitBuffer,
  1849. ProtocolSubmitBuffer,
  1850. SubmitBufferSize
  1851. );
  1852. SetCurrentPackageId(LogonPackages[Index]->dwPackageID);
  1853. Status = LogonPackages[Index]->FunctionTable.LogonUserEx2(
  1854. ClientRequest,
  1855. LogonType,
  1856. LocalSubmitBuffer,
  1857. ClientBufferBase,
  1858. SubmitBufferSize,
  1859. ProfileBuffer,
  1860. ProfileBufferLength,
  1861. NewLogonId,
  1862. ApiSubStatus,
  1863. TokenInformationType,
  1864. TokenInformation,
  1865. AccountName,
  1866. AuthenticatingAuthority,
  1867. MachineName,
  1868. PrimaryCredentials,
  1869. CachedCredentials
  1870. );
  1871. SetCurrentPackageId(CurrentPackageId);
  1872. //
  1873. // Bug 226401 If the local machine secret is different from the
  1874. // machine account password, kerberos can't decrpyt the workstation
  1875. // ticket and returns STATUS_TRUSTED_RELATIONSHIP_FAILURE (used to
  1876. // return STATUS_TRUST_FAILURE). If this is a DC, we
  1877. // should fall back to NTLM.
  1878. //
  1879. if (Status == STATUS_TRUST_FAILURE ||
  1880. Status == STATUS_TRUSTED_RELATIONSHIP_FAILURE)
  1881. {
  1882. if (NegMachineState & SECPKG_STATE_DOMAIN_CONTROLLER)
  1883. {
  1884. Status = STATUS_NO_LOGON_SERVERS;
  1885. }
  1886. }
  1887. if ((Status != STATUS_NO_LOGON_SERVERS) &&
  1888. (Status != STATUS_NETLOGON_NOT_STARTED) &&
  1889. (Status != SEC_E_NO_AUTHENTICATING_AUTHORITY) &&
  1890. (Status != SEC_E_ETYPE_NOT_SUPP) &&
  1891. (Status != STATUS_KDC_UNKNOWN_ETYPE) &&
  1892. (Status != STATUS_NO_TRUST_SAM_ACCOUNT) &&
  1893. (Status != STATUS_INVALID_PARAMETER) &&
  1894. (Status != STATUS_INVALID_LOGON_TYPE) &&
  1895. (Status != STATUS_INVALID_INFO_CLASS ) &&
  1896. (Status != STATUS_NETWORK_UNREACHABLE) &&
  1897. (Status != STATUS_BAD_VALIDATION_CLASS) )
  1898. {
  1899. break;
  1900. }
  1901. }
  1902. if ( NT_SUCCESS( Status ) )
  1903. {
  1904. LogonSession = NegpBuildLogonSession(
  1905. NewLogonId,
  1906. LogonPackages[ Index ]->dwPackageID,
  1907. LogonPackages[ Index ]->dwPackageID );
  1908. if ( LogonSession )
  1909. {
  1910. if ( LogonPackages[ Index ]->dwRPCID == NTLMSP_RPCID )
  1911. {
  1912. DebugLog(( DEB_TRACE_NEG, "NTLM Logon\n" ));
  1913. //
  1914. // Check if this is an uplevel or downlevel domain
  1915. //
  1916. DomainType = NegpIsUplevelDomain( NewLogonId, LogonType, *AuthenticatingAuthority );
  1917. if( DomainType == NegLocalDomain )
  1918. {
  1919. //
  1920. // change from Win2k:
  1921. // allow full negotiation range by default for local logons.
  1922. // Kerberos now quickly fails local account originated operations.
  1923. //
  1924. LogonSession->DefaultPackage = NegPackageId ;
  1925. }
  1926. if ( DomainType == NegUpLevelDomain )
  1927. {
  1928. if( (LogonType == CachedInteractive) &&
  1929. ((PrimaryCredentials->Flags >> PRIMARY_CRED_LOGON_PACKAGE_SHIFT) == NTLMSP_RPCID)
  1930. )
  1931. {
  1932. //
  1933. // leave the package as NTLM.
  1934. //
  1935. } else {
  1936. LogonSession->DefaultPackage = NEG_INVALID_PACKAGE ;
  1937. }
  1938. }
  1939. else if ( DomainType == NegUpLevelTrustedDomain )
  1940. {
  1941. LogonSession->DefaultPackage = NegPackageId ;
  1942. }
  1943. else
  1944. {
  1945. //
  1946. // leave the DefaultPackage as NTLM.
  1947. //
  1948. NOTHING;
  1949. }
  1950. }
  1951. //
  1952. // Create the name:
  1953. //
  1954. AltName = (PWSTR) LsapAllocatePrivateHeap(
  1955. (*AccountName)->Length +
  1956. (*AuthenticatingAuthority)->Length +
  1957. 2 * sizeof( WCHAR ) );
  1958. if ( AltName )
  1959. {
  1960. AltNameScan = AltName ;
  1961. RtlCopyMemory( AltNameScan,
  1962. (*AuthenticatingAuthority)->Buffer,
  1963. (*AuthenticatingAuthority)->Length );
  1964. AltNameScan += (*AuthenticatingAuthority)->Length / sizeof(WCHAR) ;
  1965. *AltNameScan++ = L'\\';
  1966. RtlCopyMemory( AltNameScan,
  1967. (*AccountName)->Buffer,
  1968. (*AccountName)->Length );
  1969. AltNameScan += (*AccountName)->Length / sizeof( WCHAR ) ;
  1970. *AltNameScan++ = L'\0';
  1971. RtlInitUnicodeString( &LogonSession->AlternateName, AltName );
  1972. }
  1973. NegpDerefLogonSession( LogonSession );
  1974. }
  1975. }
  1976. Cleanup:
  1977. SafeAllocaFree(LogonPackages);
  1978. if( LocalSubmitBuffer )
  1979. {
  1980. ZeroMemory(LocalSubmitBuffer, SubmitBufferSize);
  1981. LsapFreeLsaHeap(LocalSubmitBuffer);
  1982. }
  1983. return(Status);
  1984. }
  1985. //+-------------------------------------------------------------------------
  1986. //
  1987. // Function: NegpMakeServiceToken
  1988. //
  1989. // Synopsis: Handles the logon for LocalService and NetworkService
  1990. //
  1991. // Effects:
  1992. //
  1993. // Arguments:
  1994. //
  1995. // Requires:
  1996. //
  1997. // Returns:
  1998. //
  1999. // Notes: On error, this routine frees the buffers allocated by
  2000. // the prior call to NegpIsLocalOrNetworkService
  2001. //
  2002. //--------------------------------------------------------------------------
  2003. NTSTATUS
  2004. NegpMakeServiceToken(
  2005. IN ULONG ulAccountId,
  2006. OUT PLUID pLogonId,
  2007. OUT PVOID *ProfileBuffer,
  2008. OUT PULONG ProfileBufferLength,
  2009. OUT PNTSTATUS ApiSubStatus,
  2010. OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
  2011. OUT PVOID *TokenInformation,
  2012. OUT PUNICODE_STRING *AccountName,
  2013. OUT PUNICODE_STRING *AuthenticatingAuthority,
  2014. OUT PUNICODE_STRING *MachineName,
  2015. OUT PSECPKG_PRIMARY_CRED PrimaryCredentials,
  2016. OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY * CachedCredentials
  2017. )
  2018. {
  2019. NTSTATUS Status;
  2020. LPBYTE pBuffer;
  2021. UINT i;
  2022. ULONG ulTokenLength = 0;
  2023. PSID Owner;
  2024. PSID UserSid;
  2025. ULONG DaclLength;
  2026. PACL pDacl;
  2027. DWORD dwSidLen;
  2028. HMODULE hStringsResource;
  2029. LUID SystemId = SYSTEM_LUID;
  2030. PTOKEN_GROUPS pGroups;
  2031. PSID_AND_ATTRIBUTES pSidAndAttrs;
  2032. TIME_FIELDS TimeFields;
  2033. SECPKG_CLIENT_INFO ClientInfo;
  2034. SID_IDENTIFIER_AUTHORITY IdentifierAuthority = SECURITY_NT_AUTHORITY;
  2035. PLSA_TOKEN_INFORMATION_V2 pTokenInfo = NULL;
  2036. PLSAP_LOGON_SESSION pLogonSession = NULL;
  2037. SAMPR_PSID_ARRAY SidArray;
  2038. SAMPR_SID_INFORMATION SidInfo;
  2039. PSAMPR_PSID_ARRAY ResourceGroups = NULL;
  2040. //
  2041. // Don't allow untrusted clients to call this API.
  2042. //
  2043. Status = LsapGetClientInfo(&ClientInfo);
  2044. if (!NT_SUCCESS(Status))
  2045. {
  2046. goto ErrorExit;
  2047. }
  2048. if (!RtlEqualLuid(&ClientInfo.LogonId, &SystemId))
  2049. {
  2050. Status = STATUS_ACCESS_DENIED;
  2051. goto ErrorExit;
  2052. }
  2053. if (ulAccountId == LSAP_SID_NAME_LOCALSERVICE)
  2054. {
  2055. LUID LocalServiceId = LOCALSERVICE_LUID;
  2056. UNICODE_STRING EmptyString = {0, 0, NULL};
  2057. UserSid = LsapLocalServiceSid;
  2058. PrimaryCredentials->LogonId = LocalServiceId;
  2059. *pLogonId = LocalServiceId;
  2060. Status = LsapDuplicateSid(&PrimaryCredentials->UserSid,
  2061. UserSid);
  2062. if (!NT_SUCCESS(Status))
  2063. {
  2064. goto ErrorExit;
  2065. }
  2066. Status = LsapDuplicateString(&PrimaryCredentials->DomainName,
  2067. &EmptyString);
  2068. if (!NT_SUCCESS(Status))
  2069. {
  2070. goto ErrorExit;
  2071. }
  2072. Status = LsapDuplicateString(&PrimaryCredentials->DownlevelName,
  2073. &EmptyString);
  2074. if (!NT_SUCCESS(Status))
  2075. {
  2076. goto ErrorExit;
  2077. }
  2078. Status = LsapDuplicateString(&PrimaryCredentials->Password,
  2079. &EmptyString);
  2080. if (!NT_SUCCESS(Status))
  2081. {
  2082. goto ErrorExit;
  2083. }
  2084. }
  2085. else
  2086. {
  2087. LUID NetworkServiceId = NETWORKSERVICE_LUID;
  2088. ASSERT( ulAccountId == LSAP_SID_NAME_NETWORKSERVICE );
  2089. UserSid = LsapNetworkServiceSid;
  2090. RtlEnterCriticalSection(&NegComputerNamesLock);
  2091. Status = NegpCopyCredsToBuffer(&NegPrimarySystemCredentials,
  2092. NULL,
  2093. PrimaryCredentials,
  2094. NULL);
  2095. RtlLeaveCriticalSection(&NegComputerNamesLock);
  2096. if (!NT_SUCCESS(Status))
  2097. {
  2098. goto ErrorExit;
  2099. }
  2100. PrimaryCredentials->LogonId = NetworkServiceId;
  2101. *pLogonId = NetworkServiceId;
  2102. Status = LsapDuplicateSid(&PrimaryCredentials->UserSid,
  2103. UserSid);
  2104. if (!NT_SUCCESS(Status))
  2105. {
  2106. goto ErrorExit;
  2107. }
  2108. }
  2109. *CachedCredentials = NULL;
  2110. ASSERT(UserSid != NULL);
  2111. //
  2112. // Make sure there's a logon session for this account
  2113. //
  2114. pLogonSession = LsapLocateLogonSession(pLogonId);
  2115. if (pLogonSession == NULL)
  2116. {
  2117. Status = LsapCreateLogonSession(pLogonId);
  2118. pLogonSession = LsapLocateLogonSession(pLogonId);
  2119. if( pLogonSession == NULL )
  2120. {
  2121. if (!NT_SUCCESS(Status))
  2122. {
  2123. goto ErrorExit;
  2124. }
  2125. ASSERT(pLogonSession != NULL);
  2126. Status = STATUS_NO_SUCH_LOGON_SESSION;
  2127. goto ErrorExit;
  2128. }
  2129. Status = STATUS_SUCCESS;
  2130. }
  2131. //
  2132. // Compute the length of the default DACL for the token
  2133. //
  2134. DaclLength = (ULONG) sizeof(ACL)
  2135. + 2 * ((ULONG) sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG))
  2136. + RtlLengthSid( LsapLocalSystemSid )
  2137. + RtlLengthSid( UserSid );
  2138. //
  2139. // Make sure SAM has been opened.
  2140. //
  2141. Status = LsapAuOpenSam( FALSE );
  2142. if (!NT_SUCCESS(Status))
  2143. {
  2144. goto ErrorExit;
  2145. }
  2146. //
  2147. // Expand out the account domain group information from the SAM. Builtin
  2148. // domain expansion will be done by the LSA's logon filter routines.
  2149. //
  2150. SidInfo.SidPointer = (PRPC_SID) UserSid;
  2151. SidArray.Count = 1;
  2152. SidArray.Sids = &SidInfo;
  2153. Status = SamIGetResourceGroupMembershipsTransitive(LsapAccountDomainHandle,
  2154. &SidArray,
  2155. 0,
  2156. &ResourceGroups);
  2157. if (!NT_SUCCESS(Status))
  2158. {
  2159. goto ErrorExit;
  2160. }
  2161. for (i = 0; i < ResourceGroups->Count; i++)
  2162. {
  2163. ulTokenLength += RtlLengthSid(ResourceGroups->Sids[i].SidPointer);
  2164. }
  2165. #define NUM_INHERENT_TOKEN_GROUPS 1
  2166. //
  2167. // The SIDs are 4-byte aligned so this shouldn't cause problems
  2168. // with unaligned accesses (as long as the DACL stays at the
  2169. // end of the buffer).
  2170. //
  2171. ulTokenLength += sizeof(LSA_TOKEN_INFORMATION_V2)
  2172. + RtlLengthSid( UserSid ) // User
  2173. + sizeof(TOKEN_GROUPS) - sizeof(SID_AND_ATTRIBUTES)
  2174. + NUM_INHERENT_TOKEN_GROUPS * sizeof(SID_AND_ATTRIBUTES)
  2175. + ResourceGroups->Count * sizeof(SID_AND_ATTRIBUTES)
  2176. + RtlLengthSid( UserSid ) // Primary group
  2177. + RtlLengthSid( LsapAliasUsersSid )
  2178. + RtlLengthSid( UserSid ) // Owner
  2179. + DaclLength; // DefaultDacl
  2180. pTokenInfo = (PLSA_TOKEN_INFORMATION_V2) LsapAllocateLsaHeap(ulTokenLength);
  2181. if (pTokenInfo == NULL)
  2182. {
  2183. Status = STATUS_NO_MEMORY;
  2184. goto ErrorExit;
  2185. }
  2186. //
  2187. // Set up expiration time
  2188. //
  2189. TimeFields.Year = 3000;
  2190. TimeFields.Month = 1;
  2191. TimeFields.Day = 1;
  2192. TimeFields.Hour = 1;
  2193. TimeFields.Minute = 1;
  2194. TimeFields.Second = 1;
  2195. TimeFields.Milliseconds = 1;
  2196. TimeFields.Weekday = 1;
  2197. RtlTimeFieldsToTime( &TimeFields, &pTokenInfo->ExpirationTime );
  2198. //
  2199. // Set up the groups -- do this first so the nested pointers
  2200. // don't cause 64-bit alignment faults
  2201. //
  2202. pGroups = (PTOKEN_GROUPS) (pTokenInfo + 1);
  2203. pSidAndAttrs = pGroups->Groups;
  2204. pBuffer = (LPBYTE) (pSidAndAttrs + NUM_INHERENT_TOKEN_GROUPS + ResourceGroups->Count);
  2205. pGroups->GroupCount = NUM_INHERENT_TOKEN_GROUPS + ResourceGroups->Count;
  2206. //
  2207. // Add the Inherent token groups
  2208. //
  2209. // Add the Users alias because of a timing window after a DC demote. The SCE makes
  2210. // Authenticated Users a member of the Users alias on the first boot after the DC demote.
  2211. // However, by that time, the local service token will already have been created.
  2212. // Unfortunately, except for that timing window, the following code results in a duplicate
  2213. // Users alias sid being in the token.
  2214. //
  2215. dwSidLen = RtlLengthSid(LsapAliasUsersSid);
  2216. RtlCopySid(dwSidLen, pBuffer, LsapAliasUsersSid);
  2217. pSidAndAttrs[0].Sid = (PSID) pBuffer;
  2218. pBuffer += dwSidLen;
  2219. pSidAndAttrs[0].Attributes = (SE_GROUP_MANDATORY |
  2220. SE_GROUP_ENABLED_BY_DEFAULT |
  2221. SE_GROUP_ENABLED);
  2222. //
  2223. // Add the resource groups
  2224. //
  2225. for (i = 0; i < ResourceGroups->Count; i++)
  2226. {
  2227. dwSidLen = RtlLengthSid(ResourceGroups->Sids[i].SidPointer);
  2228. RtlCopySid(dwSidLen, pBuffer, ResourceGroups->Sids[i].SidPointer);
  2229. pSidAndAttrs[i+NUM_INHERENT_TOKEN_GROUPS].Sid = (PSID) pBuffer;
  2230. pSidAndAttrs[i+NUM_INHERENT_TOKEN_GROUPS].Attributes = (SE_GROUP_MANDATORY |
  2231. SE_GROUP_ENABLED_BY_DEFAULT |
  2232. SE_GROUP_ENABLED);
  2233. pBuffer += dwSidLen;
  2234. }
  2235. #undef NUM_INHERENT_TOKEN_GROUPS
  2236. SamIFreeSidArray(ResourceGroups);
  2237. ResourceGroups = NULL;
  2238. pTokenInfo->Groups = pGroups;
  2239. //
  2240. // Set up the user ID
  2241. //
  2242. dwSidLen = RtlLengthSid(UserSid);
  2243. RtlCopySid(dwSidLen, (PSID) pBuffer, UserSid);
  2244. pTokenInfo->User.User.Sid = (PSID) pBuffer;
  2245. pTokenInfo->User.User.Attributes = 0;
  2246. pBuffer += dwSidLen;
  2247. //
  2248. // Establish the primary group
  2249. //
  2250. dwSidLen = RtlLengthSid(UserSid);
  2251. RtlCopySid(dwSidLen, (PSID) pBuffer, UserSid);
  2252. pTokenInfo->PrimaryGroup.PrimaryGroup = (PSID) pBuffer;
  2253. pBuffer += dwSidLen;
  2254. //
  2255. // Set the default owner
  2256. //
  2257. dwSidLen = RtlLengthSid(UserSid);
  2258. RtlCopySid(dwSidLen, (PSID) pBuffer, UserSid);
  2259. pTokenInfo->Owner.Owner = (PSID) pBuffer;
  2260. pBuffer += dwSidLen;
  2261. //
  2262. // Privileges -- none by default (set by policy)
  2263. //
  2264. pTokenInfo->Privileges = NULL;
  2265. //
  2266. // Set up the default DACL for token. Give system full reign of terror.
  2267. //
  2268. pDacl = (PACL) pBuffer;
  2269. Status = RtlCreateAcl(pDacl, DaclLength, ACL_REVISION2);
  2270. ASSERT( NT_SUCCESS(Status) );
  2271. Status = RtlAddAccessAllowedAce(pDacl,
  2272. ACL_REVISION2,
  2273. GENERIC_ALL,
  2274. LsapLocalSystemSid);
  2275. ASSERT( NT_SUCCESS(Status) );
  2276. Status = RtlAddAccessAllowedAce(pDacl,
  2277. ACL_REVISION2,
  2278. GENERIC_ALL,
  2279. UserSid);
  2280. ASSERT( NT_SUCCESS(Status) );
  2281. RtlCopyMemory(pBuffer, pDacl, DaclLength);
  2282. pTokenInfo->DefaultDacl.DefaultDacl = (PACL) pBuffer;
  2283. pBuffer += DaclLength;
  2284. ASSERT( (ULONG)(ULONG_PTR)(pBuffer - (LPBYTE) pTokenInfo) == ulTokenLength );
  2285. //
  2286. // Now fill in the out parameters
  2287. //
  2288. //
  2289. // LocalService/NetworkService have no profile
  2290. //
  2291. *ProfileBuffer = NULL;
  2292. *ProfileBufferLength = 0;
  2293. *TokenInformationType = LsaTokenInformationV2;
  2294. *TokenInformation = pTokenInfo;
  2295. LsapReleaseLogonSession(pLogonSession);
  2296. *ApiSubStatus = STATUS_SUCCESS;
  2297. return STATUS_SUCCESS;
  2298. ErrorExit:
  2299. if (*AuthenticatingAuthority)
  2300. {
  2301. LsapFreeLsaHeap((*AuthenticatingAuthority)->Buffer);
  2302. LsapFreeLsaHeap(*AuthenticatingAuthority);
  2303. *AuthenticatingAuthority = NULL;
  2304. }
  2305. if (*AccountName)
  2306. {
  2307. LsapFreeLsaHeap((*AccountName)->Buffer);
  2308. LsapFreeLsaHeap(*AccountName);
  2309. *AccountName = NULL;
  2310. }
  2311. if (*MachineName)
  2312. {
  2313. LsapFreeLsaHeap((*MachineName)->Buffer);
  2314. LsapFreeLsaHeap(*MachineName);
  2315. *MachineName = NULL;
  2316. }
  2317. LsapFreeLsaHeap(PrimaryCredentials->UserSid);
  2318. PrimaryCredentials->UserSid = NULL;
  2319. LsapFreeLsaHeap(PrimaryCredentials->DomainName.Buffer);
  2320. RtlZeroMemory(&PrimaryCredentials->DomainName, sizeof(UNICODE_STRING));
  2321. LsapFreeLsaHeap(PrimaryCredentials->DownlevelName.Buffer);
  2322. RtlZeroMemory(&PrimaryCredentials->DownlevelName, sizeof(UNICODE_STRING));
  2323. LsapFreeLsaHeap(PrimaryCredentials->Password.Buffer);
  2324. RtlZeroMemory(&PrimaryCredentials->Password, sizeof(UNICODE_STRING));
  2325. SamIFreeSidArray(ResourceGroups);
  2326. if (pLogonSession)
  2327. {
  2328. LsapReleaseLogonSession(pLogonSession);
  2329. }
  2330. LsapFreeLsaHeap(pTokenInfo);
  2331. *ApiSubStatus = Status;
  2332. return Status;
  2333. }
  2334. //+-------------------------------------------------------------------------
  2335. //
  2336. // Function: NegpIsLocalOrNetworkService
  2337. //
  2338. // Synopsis: Allocates memory for the account name, machine name,
  2339. // and authenticating authority for LocalService and
  2340. // NetworkService logons
  2341. //
  2342. // Effects:
  2343. //
  2344. // Arguments:
  2345. //
  2346. // Requires:
  2347. //
  2348. // Returns:
  2349. //
  2350. // Notes: The caller is responsible for freeing the allocated
  2351. // buffers if this routine succeeds
  2352. //
  2353. //--------------------------------------------------------------------------
  2354. BOOL
  2355. NegpIsLocalOrNetworkService(
  2356. IN PVOID ProtocolSubmitBuffer,
  2357. IN PVOID ClientBufferBase,
  2358. IN ULONG SubmitBufferSize,
  2359. OUT PUNICODE_STRING *AccountName,
  2360. OUT PUNICODE_STRING *AuthenticatingAuthority,
  2361. OUT PUNICODE_STRING *MachineName,
  2362. OUT PULONG pulAccountId
  2363. )
  2364. {
  2365. NTSTATUS Status;
  2366. PUNICODE_STRING pTempAccount;
  2367. PUNICODE_STRING pTempAuthority;
  2368. PMSV1_0_INTERACTIVE_LOGON Authentication = NULL;
  2369. *AccountName = NULL;
  2370. *AuthenticatingAuthority = NULL;
  2371. *MachineName = NULL;
  2372. //
  2373. // Parse the supplied buffer to come up with creds
  2374. //
  2375. Status = NegpMapLogonRequest(
  2376. ProtocolSubmitBuffer,
  2377. ClientBufferBase,
  2378. SubmitBufferSize,
  2379. &Authentication);
  2380. if (!NT_SUCCESS(Status))
  2381. {
  2382. goto ErrorExit ;
  2383. }
  2384. //
  2385. // Get the info to compare for LocalService first. Check both the
  2386. // localized version and the non-localized version (which could come
  2387. // from the registry).
  2388. //
  2389. pTempAuthority = &WellKnownSids[LsapLocalServiceSidIndex].DomainName;
  2390. pTempAccount = &WellKnownSids[LsapLocalServiceSidIndex].Name;
  2391. if (RtlCompareUnicodeString(&NTAuthorityName,
  2392. &Authentication->LogonDomainName,
  2393. TRUE) == 0)
  2394. {
  2395. //
  2396. // Hardcoded "NT AUTHORITY" -- check hardcoded
  2397. // "LocalService" and "NetworkService" and
  2398. // localize it here on a match.
  2399. //
  2400. if (RtlCompareUnicodeString(&LocalServiceName,
  2401. &Authentication->UserName,
  2402. TRUE) == 0)
  2403. {
  2404. pTempAccount = &WellKnownSids[LsapLocalServiceSidIndex].Name;
  2405. *pulAccountId = LSAP_SID_NAME_LOCALSERVICE;
  2406. Status = STATUS_SUCCESS;
  2407. }
  2408. else if (RtlCompareUnicodeString(&NetworkServiceName,
  2409. &Authentication->UserName,
  2410. TRUE) == 0)
  2411. {
  2412. pTempAccount = &WellKnownSids[LsapNetworkServiceSidIndex].Name;
  2413. *pulAccountId = LSAP_SID_NAME_NETWORKSERVICE;
  2414. Status = STATUS_SUCCESS;
  2415. }
  2416. else
  2417. {
  2418. Status = STATUS_NO_SUCH_USER;
  2419. }
  2420. }
  2421. else
  2422. {
  2423. Status = STATUS_NO_SUCH_USER;
  2424. }
  2425. //
  2426. // Hardcoded comparison failed -- try localized versions. Note that
  2427. // we have to check again (rather than using an "else" with the "if"
  2428. // above) since "NT AUTHORITY" may be both the hardcoded and the
  2429. // localized name (e.g., in English). Since Status is already a
  2430. // failure code, let the failure cases trickle through.
  2431. //
  2432. if (!NT_SUCCESS(Status))
  2433. {
  2434. if (RtlCompareUnicodeString(pTempAuthority,
  2435. &Authentication->LogonDomainName,
  2436. TRUE) == 0)
  2437. {
  2438. //
  2439. // Localized "NT AUTHORITY" -- check localized
  2440. // "LocalService" and "NetworkService"
  2441. //
  2442. pTempAccount = &WellKnownSids[LsapLocalServiceSidIndex].Name;
  2443. if (RtlCompareUnicodeString(pTempAccount,
  2444. &Authentication->UserName,
  2445. TRUE) == 0)
  2446. {
  2447. *pulAccountId = LSAP_SID_NAME_LOCALSERVICE;
  2448. Status = STATUS_SUCCESS;
  2449. }
  2450. else
  2451. {
  2452. pTempAccount = &WellKnownSids[LsapNetworkServiceSidIndex].Name;
  2453. if (RtlCompareUnicodeString(pTempAccount,
  2454. &Authentication->UserName,
  2455. TRUE) == 0)
  2456. {
  2457. *pulAccountId = LSAP_SID_NAME_NETWORKSERVICE;
  2458. Status = STATUS_SUCCESS;
  2459. }
  2460. else
  2461. {
  2462. Status = STATUS_NO_SUCH_USER;
  2463. }
  2464. }
  2465. }
  2466. else
  2467. {
  2468. Status = STATUS_NO_SUCH_USER;
  2469. }
  2470. }
  2471. if (!NT_SUCCESS(Status))
  2472. {
  2473. goto ErrorExit;
  2474. }
  2475. //
  2476. // Stuff the names:
  2477. //
  2478. *AccountName = (PUNICODE_STRING) LsapAllocateLsaHeap(sizeof(UNICODE_STRING));
  2479. if (!(*AccountName))
  2480. {
  2481. Status = STATUS_NO_MEMORY;
  2482. goto ErrorExit;
  2483. }
  2484. Status = LsapDuplicateString(*AccountName,
  2485. pTempAccount);
  2486. if (!NT_SUCCESS(Status))
  2487. {
  2488. goto ErrorExit;
  2489. }
  2490. *AuthenticatingAuthority = (PUNICODE_STRING) LsapAllocateLsaHeap(sizeof(UNICODE_STRING));
  2491. if (!(*AuthenticatingAuthority))
  2492. {
  2493. Status = STATUS_NO_MEMORY;
  2494. goto ErrorExit;
  2495. }
  2496. Status = LsapDuplicateString(*AuthenticatingAuthority,
  2497. pTempAuthority);
  2498. if (!NT_SUCCESS(Status))
  2499. {
  2500. goto ErrorExit;
  2501. }
  2502. *MachineName = (PUNICODE_STRING) LsapAllocateLsaHeap(sizeof(UNICODE_STRING));
  2503. if (!(*MachineName))
  2504. {
  2505. Status = STATUS_NO_MEMORY;
  2506. goto ErrorExit ;
  2507. }
  2508. return TRUE;
  2509. ErrorExit:
  2510. if (*AuthenticatingAuthority)
  2511. {
  2512. LsapFreeLsaHeap((*AuthenticatingAuthority)->Buffer);
  2513. LsapFreeLsaHeap(*AuthenticatingAuthority);
  2514. *AuthenticatingAuthority = NULL;
  2515. }
  2516. if (*AccountName)
  2517. {
  2518. LsapFreeLsaHeap((*AccountName)->Buffer);
  2519. LsapFreeLsaHeap(*AccountName);
  2520. *AccountName = NULL;
  2521. }
  2522. if (*MachineName)
  2523. {
  2524. LsapFreeLsaHeap((*MachineName)->Buffer);
  2525. LsapFreeLsaHeap(*MachineName);
  2526. *MachineName = NULL;
  2527. }
  2528. return FALSE;
  2529. }
  2530. BOOL
  2531. NegpRearrangeMechsIfNeccessary(
  2532. struct MechTypeList ** RealMechList,
  2533. PSECURITY_STRING Target,
  2534. PBOOL DirectPacket
  2535. )
  2536. {
  2537. PWSTR FirstSlash ;
  2538. PWSTR SecondSlash = NULL;
  2539. PNEG_TRUST_LIST TrustList = NULL ;
  2540. UNICODE_STRING TargetHost ;
  2541. UNICODE_STRING SpnPrefix;
  2542. UNICODE_STRING HttpPrefix;
  2543. struct MechTypeList * MechList ;
  2544. struct MechTypeList * Reorder = NULL ;
  2545. struct MechTypeList * Trailer ;
  2546. BOOL Rearranged = FALSE ;
  2547. BOOL HttpSpn = FALSE;
  2548. BOOLEAN PortInstance = FALSE;
  2549. if ( Target == NULL )
  2550. {
  2551. DebugLog(( DEB_TRACE_NEG, "Loopback detected for local target (no targetname)\n"));
  2552. goto loopback;
  2553. }
  2554. if ( Target->Length == 0 )
  2555. {
  2556. DebugLog(( DEB_TRACE_NEG, "Loopback detected for local target (no targetname)\n"));
  2557. goto loopback;
  2558. }
  2559. //
  2560. // Now, examine the target and determine if it is referring to us
  2561. //
  2562. FirstSlash = wcschr( Target->Buffer, L'/' );
  2563. if ( !FirstSlash )
  2564. {
  2565. //
  2566. // Not an SPN, we're out of here
  2567. //
  2568. return FALSE ;
  2569. } else {
  2570. *FirstSlash = L'\0';
  2571. }
  2572. //
  2573. // HACK HACK HACK: We've got to call NTLM directly in
  2574. // the loopback case, or Wininet can't handle our "extra" nego trips....
  2575. //
  2576. RtlInitUnicodeString(
  2577. &SpnPrefix,
  2578. Target->Buffer
  2579. );
  2580. RtlInitUnicodeString(
  2581. &HttpPrefix,
  2582. L"HTTP"
  2583. );
  2584. if (RtlEqualUnicodeString(
  2585. &SpnPrefix,
  2586. &HttpPrefix,
  2587. TRUE
  2588. ))
  2589. {
  2590. HttpSpn = TRUE;
  2591. DebugLog((DEB_TRACE_NEG, "Found HTTP SPN, about to force NTLM directly\n"));
  2592. }
  2593. *FirstSlash = L'/';
  2594. // END HACK END HACK
  2595. FirstSlash++ ;
  2596. //
  2597. // if this is a svc/instance:port/domain style SPN, ignore the trailer
  2598. // portion
  2599. // trailer portion can be a port, domain, or both.
  2600. // the port instance will occur first...
  2601. //
  2602. SecondSlash = wcschr( FirstSlash, L':' );
  2603. if ( SecondSlash )
  2604. {
  2605. //
  2606. // found a port instance.
  2607. //
  2608. *SecondSlash = L'\0';
  2609. PortInstance = TRUE;
  2610. } else {
  2611. //
  2612. // look for a realm/domain instance!
  2613. //
  2614. SecondSlash = wcschr( FirstSlash, L'/' );
  2615. if ( SecondSlash )
  2616. {
  2617. *SecondSlash = L'\0';
  2618. }
  2619. }
  2620. RtlInitUnicodeString( &TargetHost, FirstSlash );
  2621. NegReadLockComputerNames();
  2622. if (!RtlEqualUnicodeString( &TargetHost, &NegDnsComputerName_U, TRUE ) &&
  2623. !RtlEqualUnicodeString( &TargetHost, &NegNetbiosComputerName_U, TRUE ) &&
  2624. !RtlEqualUnicodeString( &TargetHost, &NegLocalHostName_U, TRUE ) )
  2625. {
  2626. NegUnlockComputerNames();
  2627. goto Cleanup ;
  2628. }
  2629. NegUnlockComputerNames();
  2630. //
  2631. // We have a loopback condition. The target we are going to is our own host
  2632. // name. So, scan through the mech list, and find the NTLM mech (if present)
  2633. // and bump it up.
  2634. //
  2635. #if DBG
  2636. if ( SecondSlash )
  2637. {
  2638. //
  2639. // for debug builds, reset the string now for the dump message, so that
  2640. // we can make sure the right targets are being caught. Free builds will
  2641. // reset this at the cleanup stage.
  2642. //
  2643. *SecondSlash = L'/';
  2644. SecondSlash = NULL ;
  2645. }
  2646. #endif
  2647. DebugLog(( DEB_TRACE_NEG, "Loopback detected for target %ws\n", Target->Buffer ));
  2648. loopback:
  2649. MechList = *RealMechList ;
  2650. Trailer = NULL ;
  2651. while ( MechList )
  2652. {
  2653. if ( (MechList->value != NULL) &&
  2654. (NegpCompareOid( MechList->value, NegNtlmMechOid ) == 0)
  2655. )
  2656. {
  2657. //
  2658. // Found NTLM. Unlink it and put it at the head of the new list
  2659. //
  2660. Reorder = MechList ;
  2661. if ( Trailer )
  2662. {
  2663. Trailer->next = MechList->next ;
  2664. }
  2665. else
  2666. {
  2667. // update original pointer
  2668. *RealMechList = MechList->next ;
  2669. }
  2670. MechList = MechList->next ;
  2671. Reorder->next = NULL ;
  2672. }
  2673. else
  2674. {
  2675. Trailer = MechList ;
  2676. MechList = MechList->next ;
  2677. }
  2678. }
  2679. //
  2680. // Reorder points to the NTLM element, if there are NTLM creds. If not, this is NULL.
  2681. // Now, append the rest of the list
  2682. //
  2683. if ( Reorder )
  2684. {
  2685. Reorder->next = *RealMechList ;
  2686. *RealMechList = Reorder ;
  2687. Rearranged = TRUE ;
  2688. }
  2689. // Only set this if everything else went well
  2690. // HACK PART 2
  2691. *DirectPacket = HttpSpn;
  2692. Cleanup:
  2693. if ( SecondSlash )
  2694. {
  2695. if ( !PortInstance )
  2696. {
  2697. *SecondSlash = L'/';
  2698. } else {
  2699. *SecondSlash = L':';
  2700. }
  2701. }
  2702. return Rearranged ;
  2703. }
  2704. #ifdef _WIN64
  2705. //
  2706. // WOW structure definitions
  2707. //
  2708. typedef UNICODE_STRING32 UNICODE_STRING_WOW64;
  2709. typedef UNICODE_STRING_WOW64 *PUNICODE_STRING_WOW64;
  2710. typedef struct _MSV1_0_INTERACTIVE_LOGON_WOW64 {
  2711. MSV1_0_LOGON_SUBMIT_TYPE MessageType;
  2712. UNICODE_STRING_WOW64 LogonDomainName;
  2713. UNICODE_STRING_WOW64 UserName;
  2714. UNICODE_STRING_WOW64 Password;
  2715. } MSV1_0_INTERACTIVE_LOGON_WOW64, *PMSV1_0_INTERACTIVE_LOGON_WOW64;
  2716. //
  2717. // Useful macros to thunk WOW structures to native structures
  2718. //
  2719. #define RELOCATE_WOW_UNICODE_STRING(WOWString, NativeString, Offset) \
  2720. NativeString.Length = WOWString.Length; \
  2721. NativeString.MaximumLength = WOWString.MaximumLength; \
  2722. NativeString.Buffer = (LPWSTR) ((LPBYTE) UlongToPtr(WOWString.Buffer) + Offset);
  2723. //+-------------------------------------------------------------------------
  2724. //
  2725. // Function: NegpConvertWOWInteractiveLogonBuffer
  2726. //
  2727. // Synopsis: Converts logon buffers passed in from WOW clients to 64-bit
  2728. //
  2729. // Effects:
  2730. //
  2731. // Arguments: ProtocolSubmitBuffer -- original 32-bit logon buffer
  2732. // pSubmitBufferSize -- size of the 32-bit logon buffer
  2733. // MessageType -- format of the logon buffer
  2734. // ppTempSubmitBuffer -- filled in with the converted buffer
  2735. //
  2736. // Requires:
  2737. //
  2738. // Returns:
  2739. //
  2740. // Notes: This routine allocates the converted buffer and returns it
  2741. // on success. It is the caller's responsibility to free it
  2742. // iff the returned OUT buffer is different from the original
  2743. // IN buffer (since native calls return the buffer untouched).
  2744. //
  2745. //--------------------------------------------------------------------------
  2746. NTSTATUS
  2747. NegpConvertWOWInteractiveLogonBuffer(
  2748. IN PVOID ProtocolSubmitBuffer,
  2749. IN PVOID ClientBufferBase,
  2750. IN OUT PULONG pSubmitBufferSize,
  2751. OUT PVOID *ppTempSubmitBuffer
  2752. )
  2753. {
  2754. NTSTATUS Status;
  2755. PVOID pTempBuffer = NULL;
  2756. ULONG dwBufferSize = *pSubmitBufferSize;
  2757. SECPKG_CALL_INFO CallInfo;
  2758. PMSV1_0_INTERACTIVE_LOGON Logon;
  2759. PMSV1_0_INTERACTIVE_LOGON_WOW64 LogonWOW;
  2760. DWORD dwOffset;
  2761. DWORD dwWOWOffset;
  2762. //
  2763. // Pacify the compiler
  2764. //
  2765. UNREFERENCED_PARAMETER(ClientBufferBase);
  2766. Status = LsapGetCallInfo(&CallInfo);
  2767. if (!NT_SUCCESS(Status))
  2768. {
  2769. return Status;
  2770. }
  2771. if ((CallInfo.Attributes & SECPKG_CALL_WOWCLIENT) == 0)
  2772. {
  2773. //
  2774. // Native 64-bit call -- no thunking required.
  2775. //
  2776. *ppTempSubmitBuffer = ProtocolSubmitBuffer;
  2777. return STATUS_SUCCESS;
  2778. }
  2779. //
  2780. // Scale up the size
  2781. //
  2782. dwBufferSize += sizeof(MSV1_0_INTERACTIVE_LOGON)
  2783. - sizeof(MSV1_0_INTERACTIVE_LOGON_WOW64);
  2784. if (dwBufferSize < sizeof(MSV1_0_INTERACTIVE_LOGON))
  2785. {
  2786. Status = STATUS_INVALID_PARAMETER;
  2787. goto Cleanup;
  2788. }
  2789. pTempBuffer = LsapAllocatePrivateHeap(dwBufferSize);
  2790. if (pTempBuffer == NULL)
  2791. {
  2792. Status = STATUS_INSUFFICIENT_RESOURCES;
  2793. goto Cleanup;
  2794. }
  2795. Logon = (PMSV1_0_INTERACTIVE_LOGON) pTempBuffer;
  2796. LogonWOW = (PMSV1_0_INTERACTIVE_LOGON_WOW64) ProtocolSubmitBuffer;
  2797. Logon->MessageType = LogonWOW->MessageType;
  2798. dwOffset = sizeof(MSV1_0_INTERACTIVE_LOGON);
  2799. dwWOWOffset = sizeof(MSV1_0_INTERACTIVE_LOGON_WOW64);
  2800. //
  2801. // Copy the variable-length data
  2802. //
  2803. RtlCopyMemory((LPBYTE) Logon + dwOffset,
  2804. (LPBYTE) LogonWOW + dwWOWOffset,
  2805. *pSubmitBufferSize - dwWOWOffset);
  2806. //
  2807. // Set up the pointers in the native struct
  2808. //
  2809. RELOCATE_WOW_UNICODE_STRING(LogonWOW->LogonDomainName,
  2810. Logon->LogonDomainName,
  2811. dwOffset - dwWOWOffset);
  2812. RELOCATE_WOW_UNICODE_STRING(LogonWOW->UserName,
  2813. Logon->UserName,
  2814. dwOffset - dwWOWOffset);
  2815. RELOCATE_WOW_UNICODE_STRING(LogonWOW->Password,
  2816. Logon->Password,
  2817. dwOffset - dwWOWOffset);
  2818. *pSubmitBufferSize = dwBufferSize;
  2819. *ppTempSubmitBuffer = pTempBuffer;
  2820. return STATUS_SUCCESS;
  2821. Cleanup:
  2822. if (pTempBuffer)
  2823. {
  2824. LsapFreePrivateHeap(pTempBuffer);
  2825. }
  2826. return Status;
  2827. }
  2828. #endif // _WIN64