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.

747 lines
16 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1997.
  5. //
  6. // File: creds.c
  7. //
  8. // Contents: Cred Management for Xtcb Package
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 2-19-97 RichardW Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "xtcbpkg.h"
  18. LIST_ENTRY XtcbCredList ;
  19. CRITICAL_SECTION XtcbCredListLock ;
  20. #define ReadLockCredList() EnterCriticalSection( &XtcbCredListLock )
  21. #define WriteLockCredList() EnterCriticalSection( &XtcbCredListLock )
  22. #define WriteFromReadLockCredList()
  23. #define UnlockCredList() LeaveCriticalSection( &XtcbCredListLock )
  24. //+---------------------------------------------------------------------------
  25. //
  26. // Function: XtcbInitCreds
  27. //
  28. // Synopsis: Initialize the credential management
  29. //
  30. // Arguments: (none)
  31. //
  32. // History: 2-19-97 RichardW Created
  33. //
  34. // Notes:
  35. //
  36. //----------------------------------------------------------------------------
  37. BOOL
  38. XtcbInitCreds(
  39. VOID
  40. )
  41. {
  42. InitializeCriticalSection( &XtcbCredListLock );
  43. InitializeListHead( &XtcbCredList );
  44. return TRUE ;
  45. }
  46. //+---------------------------------------------------------------------------
  47. //
  48. // Function: XtcbFindCreds
  49. //
  50. // Synopsis: Look for credentials of a particular logon id, optionally
  51. // referencing them
  52. //
  53. // Arguments: [LogonId] --
  54. // [Ref] --
  55. //
  56. // History: 2-19-97 RichardW Created
  57. //
  58. // Notes:
  59. //
  60. //----------------------------------------------------------------------------
  61. PXTCB_CREDS
  62. XtcbFindCreds(
  63. PLUID LogonId,
  64. BOOL Ref
  65. )
  66. {
  67. PLIST_ENTRY Scan ;
  68. PXTCB_CREDS Cred ;
  69. Cred = NULL ;
  70. ReadLockCredList();
  71. Scan = XtcbCredList.Flink ;
  72. while ( Scan != &XtcbCredList )
  73. {
  74. Cred = CONTAINING_RECORD( Scan, XTCB_CREDS, List );
  75. DsysAssert( Cred->Check == XTCB_CRED_CHECK );
  76. if ( RtlEqualLuid( &Cred->LogonId, LogonId ) )
  77. {
  78. break;
  79. }
  80. Scan = Cred->List.Flink ;
  81. Cred = NULL ;
  82. }
  83. if ( Cred )
  84. {
  85. if ( Ref )
  86. {
  87. WriteFromReadLockCredList();
  88. Cred->RefCount++;
  89. }
  90. }
  91. UnlockCredList();
  92. return Cred ;
  93. }
  94. //+---------------------------------------------------------------------------
  95. //
  96. // Function: XtcbCreateCreds
  97. //
  98. // Synopsis: Create and initialize a credential structure. The reference
  99. // count is set to 1, so the pointer will remain valid.
  100. //
  101. // Arguments: [LogonId] --
  102. //
  103. // History: 2-19-97 RichardW Created
  104. //
  105. // Notes:
  106. //
  107. //----------------------------------------------------------------------------
  108. PXTCB_CREDS
  109. XtcbCreateCreds(
  110. PLUID LogonId
  111. )
  112. {
  113. PXTCB_CREDS Creds ;
  114. Creds = (PXTCB_CREDS) LocalAlloc( LMEM_FIXED, sizeof( XTCB_CREDS ) );
  115. if ( Creds )
  116. {
  117. DebugLog(( DEB_TRACE_CREDS, "Creating new credential for (%x:%x)\n",
  118. LogonId->HighPart, LogonId->LowPart ));
  119. ZeroMemory( Creds, sizeof( XTCB_CREDS ) );
  120. Creds->LogonId = *LogonId ;
  121. Creds->RefCount = 1 ;
  122. Creds->Check = XTCB_CRED_CHECK ;
  123. Creds->Pac = XtcbCreatePacForCaller();
  124. WriteLockCredList();
  125. InsertTailList( &XtcbCredList, &Creds->List );
  126. UnlockCredList();
  127. }
  128. return Creds ;
  129. }
  130. //+---------------------------------------------------------------------------
  131. //
  132. // Function: XtcbRefCreds
  133. //
  134. // Synopsis: Reference the credentials
  135. //
  136. // Arguments: [Creds] --
  137. //
  138. // History: 2-19-97 RichardW Created
  139. //
  140. // Notes:
  141. //
  142. //----------------------------------------------------------------------------
  143. VOID
  144. XtcbRefCreds(
  145. PXTCB_CREDS Creds
  146. )
  147. {
  148. WriteLockCredList();
  149. Creds->RefCount++ ;
  150. UnlockCredList();
  151. }
  152. //+---------------------------------------------------------------------------
  153. //
  154. // Function: XtcbDerefCreds
  155. //
  156. // Synopsis: Deref Credentials, freeing if the refcount goes to zero
  157. //
  158. // Arguments: [Creds] --
  159. //
  160. // History: 2-19-97 RichardW Created
  161. //
  162. // Notes:
  163. //
  164. //----------------------------------------------------------------------------
  165. VOID
  166. XtcbDerefCreds(
  167. PXTCB_CREDS Creds
  168. )
  169. {
  170. WriteLockCredList();
  171. Creds->RefCount--;
  172. if ( Creds->RefCount )
  173. {
  174. UnlockCredList();
  175. return;
  176. }
  177. RemoveEntryList( &Creds->List );
  178. UnlockCredList();
  179. Creds->Check = 0 ;
  180. LocalFree( Creds );
  181. }
  182. //+---------------------------------------------------------------------------
  183. //
  184. // Function: XtcbAllocateCredHandle
  185. //
  186. // Synopsis: Allocates and returns a cred handle (reference to a credential)
  187. //
  188. // Arguments: [Creds] -- Creds this handle is for
  189. //
  190. // History: 2-21-97 RichardW Created
  191. //
  192. // Notes:
  193. //
  194. //----------------------------------------------------------------------------
  195. PXTCB_CRED_HANDLE
  196. XtcbAllocateCredHandle(
  197. PXTCB_CREDS Creds
  198. )
  199. {
  200. PXTCB_CRED_HANDLE Handle ;
  201. Handle = (PXTCB_CRED_HANDLE) LocalAlloc( LMEM_FIXED,
  202. sizeof( XTCB_CRED_HANDLE ) );
  203. if ( Handle )
  204. {
  205. ZeroMemory( Handle, sizeof( XTCB_CRED_HANDLE ) );
  206. Handle->Check = XTCB_CRED_HANDLE_CHECK ;
  207. XtcbRefCreds( Creds );
  208. Handle->Creds = Creds ;
  209. Handle->RefCount = 1 ;
  210. }
  211. return Handle ;
  212. }
  213. //+---------------------------------------------------------------------------
  214. //
  215. // Function: XtcbRefCredHandle
  216. //
  217. // Synopsis: Reference a credential handle
  218. //
  219. // Arguments: [Handle] -- Handle to ref
  220. //
  221. // History: 2-24-97 RichardW Created
  222. //
  223. // Notes:
  224. //
  225. //----------------------------------------------------------------------------
  226. VOID
  227. XtcbRefCredHandle(
  228. PXTCB_CRED_HANDLE Handle
  229. )
  230. {
  231. WriteLockCredList();
  232. Handle->RefCount ++ ;
  233. UnlockCredList();
  234. }
  235. //+---------------------------------------------------------------------------
  236. //
  237. // Function: XtcbDerefCredHandle
  238. //
  239. // Synopsis: Dereference a cred handle
  240. //
  241. // Arguments: [Handle] --
  242. //
  243. // History: 2-24-97 RichardW Created
  244. //
  245. // Notes:
  246. //
  247. //----------------------------------------------------------------------------
  248. VOID
  249. XtcbDerefCredHandle(
  250. PXTCB_CRED_HANDLE Handle
  251. )
  252. {
  253. WriteLockCredList();
  254. Handle->RefCount -- ;
  255. if ( Handle->RefCount == 0 )
  256. {
  257. XtcbDerefCreds( Handle->Creds );
  258. LocalFree( Handle );
  259. }
  260. UnlockCredList();
  261. }
  262. //+---------------------------------------------------------------------------
  263. //
  264. // Function: XtcbCreatePacForCaller
  265. //
  266. // Synopsis: Creates an XTCB_PAC for the caller
  267. //
  268. // Arguments: none
  269. //
  270. // History: 3-14-00 RichardW Created
  271. //
  272. // Notes:
  273. //
  274. //----------------------------------------------------------------------------
  275. PXTCB_PAC
  276. XtcbCreatePacForCaller(
  277. VOID
  278. )
  279. {
  280. HANDLE Token ;
  281. NTSTATUS Status ;
  282. PXTCB_PAC Pac = NULL ;
  283. PTOKEN_USER User = NULL ;
  284. PTOKEN_GROUPS Groups = NULL ;
  285. PTOKEN_GROUPS Restrictions = NULL ;
  286. TOKEN_STATISTICS Stats ;
  287. ULONG UserSize ;
  288. ULONG GroupSize ;
  289. ULONG RestrictionSize ;
  290. ULONG PacGroupSize = 0 ;
  291. ULONG PacRestrictionSize = 0 ;
  292. ULONG PacUserName = 0 ;
  293. ULONG PacDomainName = 0 ;
  294. ULONG PacSize ;
  295. ULONG i ;
  296. PUCHAR CopyTo ;
  297. PUCHAR Base ;
  298. BOOL SpecialAccount = FALSE ;
  299. PSECURITY_LOGON_SESSION_DATA LogonSessionData = NULL ;
  300. Status = LsaTable->ImpersonateClient();
  301. if ( !NT_SUCCESS( Status ) )
  302. {
  303. return NULL ;
  304. }
  305. Status = NtOpenThreadToken(
  306. NtCurrentThread(),
  307. TOKEN_READ,
  308. TRUE,
  309. &Token );
  310. RevertToSelf();
  311. if ( !NT_SUCCESS( Status ) )
  312. {
  313. return NULL ;
  314. }
  315. //
  316. // Now that we have the token, capture all the information about this user,
  317. // and compute our own "PAC" structure.
  318. //
  319. Status = NtQueryInformationToken(
  320. Token,
  321. TokenStatistics,
  322. &Stats,
  323. sizeof( Stats ),
  324. &UserSize );
  325. if ( !NT_SUCCESS( Status ) )
  326. {
  327. goto CreatePac_Exit ;
  328. }
  329. //
  330. // If this is a special logon session (e.g. LocalSystem, LocalService, etc.),
  331. // then the LUID will be less than 1000. Set the flag to copy all SIDs in the token.
  332. //
  333. if ( (Stats.AuthenticationId.HighPart == 0) &&
  334. (Stats.AuthenticationId.LowPart < 1000 ) )
  335. {
  336. SpecialAccount = TRUE ;
  337. }
  338. UserSize = 0 ;
  339. (void) NtQueryInformationToken(
  340. Token,
  341. TokenUser,
  342. NULL,
  343. 0,
  344. &UserSize );
  345. if ( UserSize == 0 )
  346. {
  347. goto CreatePac_Exit ;
  348. }
  349. User = LocalAlloc( LMEM_FIXED, UserSize );
  350. if ( !User )
  351. {
  352. goto CreatePac_Exit ;
  353. }
  354. Status = NtQueryInformationToken(
  355. Token,
  356. TokenUser,
  357. User,
  358. UserSize,
  359. &UserSize );
  360. if ( !NT_SUCCESS( Status ) )
  361. {
  362. goto CreatePac_Exit ;
  363. }
  364. GroupSize = 0 ;
  365. (void) NtQueryInformationToken(
  366. Token,
  367. TokenGroups,
  368. NULL,
  369. 0,
  370. &GroupSize );
  371. if ( GroupSize == 0 )
  372. {
  373. goto CreatePac_Exit ;
  374. }
  375. Groups = LocalAlloc( LMEM_FIXED, GroupSize );
  376. if ( !Groups )
  377. {
  378. goto CreatePac_Exit ;
  379. }
  380. Status = NtQueryInformationToken(
  381. Token,
  382. TokenGroups,
  383. Groups,
  384. GroupSize,
  385. &GroupSize );
  386. if ( !NT_SUCCESS( Status ) )
  387. {
  388. goto CreatePac_Exit;
  389. }
  390. RestrictionSize = 0 ;
  391. (void) NtQueryInformationToken(
  392. Token,
  393. TokenRestrictedSids,
  394. NULL,
  395. 0,
  396. &RestrictionSize );
  397. if ( RestrictionSize != 0 )
  398. {
  399. Restrictions = LocalAlloc( LMEM_FIXED, RestrictionSize );
  400. if ( Restrictions )
  401. {
  402. Status = NtQueryInformationToken(
  403. Token,
  404. TokenRestrictedSids,
  405. Restrictions,
  406. RestrictionSize,
  407. &RestrictionSize );
  408. if ( !NT_SUCCESS( Status ) )
  409. {
  410. goto CreatePac_Exit ;
  411. }
  412. }
  413. else
  414. {
  415. goto CreatePac_Exit ;
  416. }
  417. }
  418. //
  419. // We now have all the users SIDs in the two (or three) pointers. First, grovel the Groups
  420. // for non-local SIDs, and set all the rest to 0. This will let us compute how much space
  421. // we need.
  422. //
  423. for ( i = 0 ; i < Groups->GroupCount ; i++ )
  424. {
  425. if ( (*RtlSubAuthorityCountSid( Groups->Groups[ i ].Sid ) > 2) ||
  426. (SpecialAccount) )
  427. {
  428. //
  429. // A "real" SID. Check to make sure it is not from this machine
  430. //
  431. if ( ( XtcbMachineSid != NULL ) &&
  432. RtlEqualPrefixSid( XtcbMachineSid, Groups->Groups[ i ].Sid ) )
  433. {
  434. //
  435. // Don't use this group
  436. //
  437. Groups->Groups[ i ].Attributes = 0 ;
  438. }
  439. else
  440. {
  441. //
  442. // We like this SID (it is not from the local machine)
  443. //
  444. Groups->Groups[ i ].Attributes = SE_GROUP_MANDATORY ;
  445. PacGroupSize += RtlLengthSid( Groups->Groups[ i ].Sid );
  446. }
  447. }
  448. else
  449. {
  450. Groups->Groups[ i ].Attributes = 0 ;
  451. }
  452. }
  453. //
  454. // Do the same for the restrictions, if any
  455. //
  456. if ( Restrictions )
  457. {
  458. for ( i = 0 ; i < Restrictions->GroupCount ; i++ )
  459. {
  460. PacRestrictionSize += RtlLengthSid( Restrictions->Groups[ i ].Sid );
  461. }
  462. }
  463. //
  464. // Get the user's name and domain:
  465. //
  466. Status = LsaGetLogonSessionData(
  467. &Stats.AuthenticationId,
  468. &LogonSessionData );
  469. if ( !NT_SUCCESS( Status ) )
  470. {
  471. goto CreatePac_Exit ;
  472. }
  473. PacUserName = LogonSessionData->UserName.Length ;
  474. PacDomainName = LogonSessionData->LogonDomain.Length ;
  475. //
  476. // In an advanced world, we'd query the other packages for
  477. // delegatable credentials, bundle them up and ship them
  478. // over.
  479. //
  480. //
  481. // Ok, we've got all the information we need
  482. //
  483. PacSize = sizeof( XTCB_PAC ) +
  484. RtlLengthSid( User->User.Sid ) +
  485. PacGroupSize +
  486. PacRestrictionSize +
  487. PacUserName +
  488. PacDomainName ;
  489. Pac = LocalAlloc( LMEM_FIXED, PacSize );
  490. if ( !Pac )
  491. {
  492. goto CreatePac_Exit ;
  493. }
  494. //
  495. // Create the PAC structure:
  496. //
  497. Pac->Tag = XTCB_PAC_TAG ;
  498. Pac->Length = PacSize ;
  499. CopyTo = (PUCHAR) (Pac + 1);
  500. Base = (PUCHAR) Pac ;
  501. //
  502. // Assemble the PAC:
  503. //
  504. // first, the user
  505. //
  506. Pac->UserOffset = (ULONG) (CopyTo - Base);
  507. Pac->UserLength = RtlLengthSid( User->User.Sid );
  508. RtlCopyMemory(
  509. CopyTo,
  510. User->User.Sid,
  511. Pac->UserLength );
  512. CopyTo += RtlLengthSid( User->User.Sid );
  513. //
  514. // Now the normal groups:
  515. //
  516. Pac->GroupCount = 0 ;
  517. Pac->GroupOffset = (ULONG) (CopyTo - Base);
  518. for ( i = 0 ; i < Groups->GroupCount ; i++ )
  519. {
  520. if ( Groups->Groups[ i ].Attributes & SE_GROUP_MANDATORY )
  521. {
  522. RtlCopyMemory(
  523. CopyTo,
  524. Groups->Groups[ i ].Sid,
  525. RtlLengthSid( Groups->Groups[ i ].Sid ) );
  526. CopyTo += RtlLengthSid( Groups->Groups[ i ].Sid );
  527. Pac->GroupCount++ ;
  528. }
  529. }
  530. Pac->GroupLength = (ULONG) (CopyTo - Base) - Pac->GroupOffset;
  531. //
  532. // If there are restrictions, copy them in as well
  533. //
  534. if ( (Restrictions == NULL) ||
  535. (Restrictions->GroupCount == 0 ) )
  536. {
  537. Pac->RestrictionCount = 0 ;
  538. Pac->RestrictionOffset = 0 ;
  539. Pac->RestrictionLength = 0 ;
  540. }
  541. else
  542. {
  543. Pac->RestrictionCount = Restrictions->GroupCount ;
  544. Pac->RestrictionOffset = (ULONG) ( CopyTo - Base );
  545. for ( i = 0 ; i < Restrictions->GroupCount ; i++ )
  546. {
  547. RtlCopyMemory(
  548. CopyTo,
  549. Restrictions->Groups[ i ].Sid,
  550. RtlLengthSid( Restrictions->Groups[ i ].Sid ) );
  551. CopyTo += RtlLengthSid( Restrictions->Groups[ i ].Sid );
  552. Pac->RestrictionCount++ ;
  553. }
  554. Pac->RestrictionLength = (ULONG) (CopyTo - Base) - Pac->RestrictionOffset ;
  555. }
  556. Pac->NameOffset = (ULONG) ( CopyTo - Base );
  557. Pac->NameLength = LogonSessionData->UserName.Length ;
  558. RtlCopyMemory(
  559. CopyTo,
  560. LogonSessionData->UserName.Buffer,
  561. LogonSessionData->UserName.Length );
  562. CopyTo += LogonSessionData->UserName.Length ;
  563. Pac->DomainLength = LogonSessionData->LogonDomain.Length ;
  564. Pac->DomainOffset = (ULONG) ( CopyTo - Base );
  565. RtlCopyMemory(
  566. CopyTo,
  567. LogonSessionData->LogonDomain.Buffer,
  568. LogonSessionData->LogonDomain.Length );
  569. //
  570. // Someday, maybe, copy credential data here
  571. //
  572. Pac->CredentialLength = 0 ;
  573. Pac->CredentialOffset = 0 ;
  574. CreatePac_Exit:
  575. if ( LogonSessionData )
  576. {
  577. LsaFreeReturnBuffer( LogonSessionData );
  578. }
  579. if ( User )
  580. {
  581. LocalFree( User );
  582. }
  583. if ( Groups )
  584. {
  585. LocalFree( Groups );
  586. }
  587. if ( Restrictions )
  588. {
  589. LocalFree( Restrictions );
  590. }
  591. NtClose( Token );
  592. return Pac ;
  593. }