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

2925 lines
81 KiB

  1. /*++
  2. Copyright (c) 1996-1998 Microsoft Corporation
  3. Module Name:
  4. Security.c
  5. Abstract:
  6. This module contains common security routines for
  7. NT Clusters.
  8. Author:
  9. John Vert (jvert) 12-Mar-1996
  10. --*/
  11. #include "clusrtlp.h"
  12. #include "api_rpc.h"
  13. #include <aclapi.h>
  14. #include <accctrl.h>
  15. #include <malloc.h>
  16. //
  17. // Use this SD to adjust access to tokens so that the cluster
  18. // service can access and adjust privileges.
  19. //
  20. // This is initialized in ClRtlBuildClusterServiceSecurityDescriptor()
  21. // and freed in ClRtlFreeClusterServiceSecurityDescriptor( ).
  22. //
  23. PSECURITY_DESCRIPTOR g_pClusterSecurityDescriptor = NULL;
  24. //
  25. // local defines
  26. //
  27. #define FREE_IF_NOT_NULL( _ptr, _func ) \
  28. if (( _ptr ) != NULL ) { \
  29. _func( _ptr ); \
  30. }
  31. LONG
  32. MapSAToRpcSA (
  33. IN LPSECURITY_ATTRIBUTES lpSA,
  34. OUT PRPC_SECURITY_ATTRIBUTES lpRpcSA
  35. )
  36. /*++
  37. Routine Description:
  38. Maps a SECURITY_ATTRIBUTES structure to a RPC_SECURITY_ATTRIBUTES
  39. structure by converting the SECURITY_DESCRIPTOR to a form where it can
  40. be marshalled/unmarshalled.
  41. Arguments:
  42. lpSA - Supplies a pointer to the SECURITY_ATTRIBUTES structure to be
  43. converted.
  44. lpRpcSA - Supplies a pointer to the converted RPC_SECURITY_ATTRIBUTES
  45. structure. The caller should free (using RtlFreeHeap) the field
  46. lpSecurityDescriptor when its finished using it.
  47. Return Value:
  48. LONG - Returns ERROR_SUCCESS if the SECURITY_ATTRIBUTES is
  49. succesfully mapped.
  50. --*/
  51. {
  52. LONG Error;
  53. ASSERT( lpSA != NULL );
  54. ASSERT( lpRpcSA != NULL );
  55. //
  56. // Map the SECURITY_DESCRIPTOR to a RPC_SECURITY_DESCRIPTOR.
  57. //
  58. lpRpcSA->RpcSecurityDescriptor.lpSecurityDescriptor = NULL;
  59. if( lpSA->lpSecurityDescriptor != NULL ) {
  60. Error = MapSDToRpcSD(
  61. lpSA->lpSecurityDescriptor,
  62. &lpRpcSA->RpcSecurityDescriptor
  63. );
  64. } else {
  65. lpRpcSA->RpcSecurityDescriptor.cbInSecurityDescriptor = 0;
  66. lpRpcSA->RpcSecurityDescriptor.cbOutSecurityDescriptor = 0;
  67. Error = ERROR_SUCCESS;
  68. }
  69. if( Error == ERROR_SUCCESS ) {
  70. //
  71. //
  72. // The supplied SECURITY_DESCRIPTOR was successfully converted
  73. // to self relative format so assign the remaining fields.
  74. //
  75. lpRpcSA->nLength = lpSA->nLength;
  76. lpRpcSA->bInheritHandle = ( BOOLEAN ) lpSA->bInheritHandle;
  77. }
  78. return Error;
  79. }
  80. LONG
  81. MapSDToRpcSD (
  82. IN PSECURITY_DESCRIPTOR lpSD,
  83. IN OUT PRPC_SECURITY_DESCRIPTOR lpRpcSD
  84. )
  85. /*++
  86. Routine Description:
  87. Maps a SECURITY_DESCRIPTOR to a RPC_SECURITY_DESCRIPTOR by converting
  88. it to a form where it can be marshalled/unmarshalled.
  89. Arguments:
  90. lpSD - Supplies a pointer to the SECURITY_DESCRIPTOR
  91. structure to be converted.
  92. lpRpcSD - Supplies a pointer to the converted RPC_SECURITY_DESCRIPTOR
  93. structure. Memory for the security descriptor is allocated if
  94. not provided. The caller must take care of freeing up the memory
  95. if necessary.
  96. Return Value:
  97. LONG - Returns ERROR_SUCCESS if the SECURITY_DESCRIPTOR is
  98. succesfully mapped.
  99. --*/
  100. {
  101. DWORD cbLen;
  102. ASSERT( lpSD != NULL );
  103. ASSERT( lpRpcSD != NULL );
  104. if( RtlValidSecurityDescriptor( lpSD )) {
  105. cbLen = RtlLengthSecurityDescriptor( lpSD );
  106. CL_ASSERT( cbLen > 0 );
  107. //
  108. // If we're not provided a buffer for the security descriptor,
  109. // allocate it.
  110. //
  111. if ( !lpRpcSD->lpSecurityDescriptor ) {
  112. //
  113. // Allocate space for the converted SECURITY_DESCRIPTOR.
  114. //
  115. lpRpcSD->lpSecurityDescriptor =
  116. ( PBYTE ) RtlAllocateHeap(
  117. RtlProcessHeap( ), 0,
  118. cbLen
  119. );
  120. //
  121. // If the memory allocation failed, return.
  122. //
  123. if( lpRpcSD->lpSecurityDescriptor == NULL ) {
  124. return ERROR_OUTOFMEMORY;
  125. }
  126. lpRpcSD->cbInSecurityDescriptor = cbLen;
  127. } else {
  128. //
  129. // Make sure that the buffer provided is big enough
  130. //
  131. if ( lpRpcSD->cbInSecurityDescriptor < cbLen ) {
  132. return ERROR_OUTOFMEMORY;
  133. }
  134. }
  135. //
  136. // Set the size of the transmittable buffer
  137. //
  138. lpRpcSD->cbOutSecurityDescriptor = cbLen;
  139. //
  140. // Convert the supplied SECURITY_DESCRIPTOR to self relative form.
  141. //
  142. return RtlNtStatusToDosError(
  143. RtlMakeSelfRelativeSD(
  144. lpSD,
  145. lpRpcSD->lpSecurityDescriptor,
  146. &lpRpcSD->cbInSecurityDescriptor
  147. )
  148. );
  149. } else {
  150. //
  151. // The supplied SECURITY_DESCRIPTOR is invalid.
  152. //
  153. return ERROR_INVALID_PARAMETER;
  154. }
  155. }
  156. DWORD
  157. ClRtlSetObjSecurityInfo(
  158. IN HANDLE hObject,
  159. IN SE_OBJECT_TYPE SeObjType,
  160. IN DWORD dwAdminMask,
  161. IN DWORD dwOwnerMask,
  162. IN DWORD dwEveryOneMask
  163. )
  164. /*++
  165. Routine Description:
  166. Sets the proper security on the cluster object(registry root/cluster files
  167. directory).
  168. Arguments:
  169. None
  170. Return Value:
  171. ERROR_SUCCESS if successful
  172. Win32 error code otherwise
  173. --*/
  174. {
  175. DWORD Status;
  176. PACL pAcl = NULL;
  177. DWORD cbDaclSize;
  178. PACCESS_ALLOWED_ACE pAce;
  179. PSID pAdminSid = NULL;
  180. PSID pOwnerSid = NULL;
  181. PSID pEveryoneSid = NULL;
  182. PULONG pSubAuthority;
  183. SID_IDENTIFIER_AUTHORITY SidIdentifierNtAuth = SECURITY_NT_AUTHORITY;
  184. SID_IDENTIFIER_AUTHORITY siaWorld = SECURITY_WORLD_SID_AUTHORITY;
  185. SID_IDENTIFIER_AUTHORITY siaCreator = SECURITY_CREATOR_SID_AUTHORITY;
  186. DWORD AceIndex = 0;
  187. //
  188. // Create the local Administrators group SID.
  189. //
  190. pAdminSid = LocalAlloc(LMEM_FIXED, GetSidLengthRequired( 2 ));
  191. if (pAdminSid == NULL) {
  192. Status = ERROR_NOT_ENOUGH_MEMORY;
  193. goto error_exit;
  194. }
  195. if (!InitializeSid(pAdminSid, &SidIdentifierNtAuth, 2)) {
  196. Status = GetLastError();
  197. goto error_exit;
  198. }
  199. //
  200. // Set the sub-authorities on the ACE for the local Administrators group.
  201. //
  202. pSubAuthority = GetSidSubAuthority( pAdminSid, 0 );
  203. *pSubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
  204. pSubAuthority = GetSidSubAuthority( pAdminSid, 1 );
  205. *pSubAuthority = DOMAIN_ALIAS_RID_ADMINS;
  206. //
  207. // Create the owner's SID
  208. //
  209. pOwnerSid = LocalAlloc(LMEM_FIXED, GetSidLengthRequired( 1 ));
  210. if (pOwnerSid == NULL) {
  211. Status = ERROR_NOT_ENOUGH_MEMORY;
  212. goto error_exit;
  213. }
  214. if (!InitializeSid(pOwnerSid, &siaCreator, 1)) {
  215. Status = GetLastError();
  216. goto error_exit;
  217. }
  218. pSubAuthority = GetSidSubAuthority(pOwnerSid, 0);
  219. *pSubAuthority = SECURITY_CREATOR_OWNER_RID;
  220. //
  221. // Create the Everyone SID
  222. //
  223. pEveryoneSid = LocalAlloc(LMEM_FIXED, GetSidLengthRequired( 1 ));
  224. if (pEveryoneSid == NULL) {
  225. Status = ERROR_NOT_ENOUGH_MEMORY;
  226. goto error_exit;
  227. }
  228. if (!InitializeSid(pEveryoneSid, &siaWorld, 1)) {
  229. Status = GetLastError();
  230. goto error_exit;
  231. }
  232. pSubAuthority = GetSidSubAuthority(pEveryoneSid, 0);
  233. *pSubAuthority = SECURITY_WORLD_RID;
  234. //
  235. // now calculate the size of the buffer needed to hold the
  236. // ACL and its ACEs and initialize it.
  237. //
  238. cbDaclSize = sizeof(ACL) +
  239. 3 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(pAce->SidStart)) +
  240. GetLengthSid(pAdminSid) + GetLengthSid(pOwnerSid) + GetLengthSid(pEveryoneSid);
  241. pAcl = (PACL)LocalAlloc( LMEM_FIXED, cbDaclSize );
  242. if ( pAcl == NULL ) {
  243. Status = ERROR_NOT_ENOUGH_MEMORY;
  244. goto error_exit;
  245. }
  246. if ( !InitializeAcl( pAcl, cbDaclSize, ACL_REVISION )) {
  247. Status = GetLastError();
  248. goto error_exit;
  249. }
  250. //
  251. // add in the specified ACEs
  252. //
  253. if (dwAdminMask) {
  254. //
  255. // Add the ACE for the local Administrators group to the DACL
  256. //
  257. if ( !AddAccessAllowedAce( pAcl,
  258. ACL_REVISION,
  259. dwAdminMask,
  260. pAdminSid )) {
  261. Status = GetLastError();
  262. goto error_exit;
  263. }
  264. GetAce(pAcl, AceIndex, (PVOID *)&pAce);
  265. ++AceIndex;
  266. pAce->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
  267. }
  268. if (dwOwnerMask) {
  269. //
  270. // Add the ACE for the Creator/Owner to the DACL
  271. //
  272. if ( !AddAccessAllowedAce( pAcl,
  273. ACL_REVISION,
  274. dwOwnerMask,
  275. pOwnerSid )) {
  276. Status = GetLastError();
  277. goto error_exit;
  278. }
  279. GetAce(pAcl, AceIndex, (PVOID *)&pAce);
  280. ++AceIndex;
  281. pAce->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
  282. }
  283. if (dwEveryOneMask) {
  284. //
  285. // Add the ACE for Everyone to the DACL
  286. //
  287. if ( !AddAccessAllowedAce( pAcl,
  288. ACL_REVISION,
  289. dwEveryOneMask,
  290. pEveryoneSid )) {
  291. Status = GetLastError();
  292. goto error_exit;
  293. }
  294. GetAce(pAcl, AceIndex, (PVOID *)&pAce);
  295. ++AceIndex;
  296. pAce->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
  297. }
  298. //
  299. // Now that we have an ACL we can set the appropriate security.
  300. //
  301. Status = SetSecurityInfo(hObject,
  302. SeObjType,
  303. DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
  304. NULL,
  305. NULL,
  306. pAcl,
  307. NULL);
  308. error_exit:
  309. if (pAdminSid != NULL) {
  310. LocalFree(pAdminSid);
  311. }
  312. if (pOwnerSid != NULL) {
  313. LocalFree(pOwnerSid);
  314. }
  315. if (pEveryoneSid != NULL) {
  316. LocalFree(pEveryoneSid);
  317. }
  318. if (pAcl != NULL) {
  319. LocalFree(pAcl);
  320. }
  321. //
  322. // Chittur Subbaraman (chitturs) - 01/04/2001
  323. //
  324. // Change error code to support file systems that don't support setting
  325. // security. This specific change is made to support AhmedM's quorum (of
  326. // nodes) resource DLL.
  327. //
  328. if ( Status == ERROR_NOT_SUPPORTED ) Status = ERROR_SUCCESS;
  329. return(Status);
  330. }
  331. DWORD
  332. ClRtlFreeClusterServiceSecurityDescriptor( )
  333. /*++
  334. Frees the security descriptor that is used to give the cluster
  335. service access to tokens.
  336. --*/
  337. {
  338. LocalFree( g_pClusterSecurityDescriptor );
  339. g_pClusterSecurityDescriptor = NULL;
  340. return ERROR_SUCCESS;
  341. }
  342. DWORD
  343. ClRtlBuildClusterServiceSecurityDescriptor(
  344. PSECURITY_DESCRIPTOR * poutSD
  345. )
  346. /*++
  347. Routine Description:
  348. Builds a security descriptor that gives the cluster service
  349. access to tokens. It places this in a global that can be
  350. reused when other tokens are generated.
  351. This should be called when the process starts to initialize
  352. the global. It can pass in NULL if no reference is needed
  353. right away.
  354. NOTE: poutSD should NOT be freed by the caller.
  355. Arguments:
  356. Return Value:
  357. --*/
  358. {
  359. NTSTATUS Status;
  360. HANDLE ProcessToken = NULL;
  361. ULONG AclLength;
  362. ULONG SDLength;
  363. PACL NewDacl = NULL;
  364. ULONG TokenUserSize;
  365. PTOKEN_USER ProcessTokenUser = NULL;
  366. SECURITY_DESCRIPTOR SecurityDescriptor;
  367. PSECURITY_DESCRIPTOR pNewSD = NULL;
  368. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  369. PSID GlobalLocalSystemSid = NULL;
  370. PSID GlobalAliasAdminsSid = NULL;
  371. // If we already have a SD, reuse it.
  372. if ( g_pClusterSecurityDescriptor != NULL ) {
  373. Status = ERROR_SUCCESS;
  374. goto Cleanup;
  375. }
  376. //
  377. // Build the two well known sids we need.
  378. //
  379. Status = RtlAllocateAndInitializeSid(
  380. &NtAuthority,
  381. 1,
  382. SECURITY_LOCAL_SYSTEM_RID,
  383. 0,0,0,0,0,0,0,
  384. &GlobalLocalSystemSid
  385. );
  386. if ( ! NT_SUCCESS( Status ) ) {
  387. goto Cleanup;
  388. }
  389. Status = RtlAllocateAndInitializeSid(
  390. &NtAuthority,
  391. 2,
  392. SECURITY_BUILTIN_DOMAIN_RID,
  393. DOMAIN_ALIAS_RID_ADMINS,
  394. 0,0,0,0,0,0,
  395. &GlobalAliasAdminsSid
  396. );
  397. if (!NT_SUCCESS(Status)) {
  398. goto Cleanup;
  399. }
  400. //
  401. // Open the process token to find out the user sid
  402. //
  403. Status = NtOpenProcessToken(
  404. NtCurrentProcess(),
  405. TOKEN_QUERY | WRITE_DAC,
  406. &ProcessToken
  407. );
  408. if (!NT_SUCCESS(Status)) {
  409. goto Cleanup;
  410. }
  411. // find out the size
  412. Status = NtQueryInformationToken(
  413. ProcessToken,
  414. TokenUser,
  415. NULL,
  416. 0,
  417. &TokenUserSize
  418. );
  419. CL_ASSERT( Status == STATUS_BUFFER_TOO_SMALL );
  420. if ( Status != STATUS_BUFFER_TOO_SMALL ) {
  421. goto Cleanup;
  422. }
  423. ProcessTokenUser = (PTOKEN_USER) LocalAlloc( 0, TokenUserSize );
  424. if ( ProcessTokenUser == NULL ) {
  425. Status = STATUS_INSUFFICIENT_RESOURCES;
  426. goto Cleanup;
  427. }
  428. Status = NtQueryInformationToken(
  429. ProcessToken,
  430. TokenUser,
  431. ProcessTokenUser,
  432. TokenUserSize,
  433. &TokenUserSize
  434. );
  435. if (!NT_SUCCESS(Status)) {
  436. goto Cleanup;
  437. }
  438. AclLength = 3 * sizeof( ACCESS_ALLOWED_ACE ) - 3 * sizeof( ULONG ) +
  439. RtlLengthSid( ProcessTokenUser->User.Sid ) +
  440. RtlLengthSid( GlobalLocalSystemSid ) +
  441. RtlLengthSid( GlobalAliasAdminsSid ) +
  442. sizeof( ACL );
  443. NewDacl = (PACL) LocalAlloc(0, AclLength );
  444. if (NewDacl == NULL) {
  445. Status = STATUS_INSUFFICIENT_RESOURCES;
  446. goto Cleanup;
  447. }
  448. Status = RtlCreateAcl( NewDacl, AclLength, ACL_REVISION2 );
  449. CL_ASSERT(NT_SUCCESS( Status ));
  450. Status = RtlAddAccessAllowedAce (
  451. NewDacl,
  452. ACL_REVISION2,
  453. TOKEN_ALL_ACCESS,
  454. ProcessTokenUser->User.Sid
  455. );
  456. CL_ASSERT( NT_SUCCESS( Status ));
  457. Status = RtlAddAccessAllowedAce (
  458. NewDacl,
  459. ACL_REVISION2,
  460. TOKEN_ALL_ACCESS,
  461. GlobalAliasAdminsSid
  462. );
  463. CL_ASSERT( NT_SUCCESS( Status ));
  464. Status = RtlAddAccessAllowedAce (
  465. NewDacl,
  466. ACL_REVISION2,
  467. TOKEN_ALL_ACCESS,
  468. GlobalLocalSystemSid
  469. );
  470. CL_ASSERT( NT_SUCCESS( Status ));
  471. Status = RtlCreateSecurityDescriptor (
  472. &SecurityDescriptor,
  473. SECURITY_DESCRIPTOR_REVISION
  474. );
  475. CL_ASSERT( NT_SUCCESS( Status ));
  476. Status = RtlSetDaclSecurityDescriptor(
  477. &SecurityDescriptor,
  478. TRUE,
  479. NewDacl,
  480. FALSE
  481. );
  482. CL_ASSERT( NT_SUCCESS( Status ));
  483. // Convert the newly created SD into a relative SD to make cleanup
  484. // easier.
  485. SDLength = sizeof( SECURITY_DESCRIPTOR_RELATIVE ) + AclLength;
  486. pNewSD = (PSECURITY_DESCRIPTOR) LocalAlloc( 0, SDLength );
  487. if ( pNewSD == NULL ) {
  488. Status = STATUS_INSUFFICIENT_RESOURCES;
  489. goto Cleanup;
  490. }
  491. if ( !MakeSelfRelativeSD( &SecurityDescriptor, pNewSD, &SDLength ) ) {
  492. Status = GetLastError( );
  493. if ( Status != STATUS_BUFFER_TOO_SMALL ) {
  494. ClRtlLogPrint(LOG_CRITICAL, "[ClRtl] MakeSelfRelativeSD failed 0x%1!.8x!\n", Status );
  495. goto Cleanup;
  496. }
  497. pNewSD = (PSECURITY_DESCRIPTOR) LocalAlloc( 0, SDLength );
  498. if ( pNewSD == NULL ) {
  499. Status = STATUS_INSUFFICIENT_RESOURCES;
  500. goto Cleanup;
  501. }
  502. }
  503. if ( !MakeSelfRelativeSD( &SecurityDescriptor, pNewSD, &SDLength ) ) {
  504. Status = GetLastError( );
  505. goto Cleanup;
  506. }
  507. // give ownership to global
  508. g_pClusterSecurityDescriptor = pNewSD;
  509. pNewSD = NULL;
  510. Cleanup:
  511. if (ProcessTokenUser != NULL) {
  512. LocalFree( ProcessTokenUser );
  513. }
  514. if (NewDacl != NULL) {
  515. LocalFree( NewDacl );
  516. }
  517. if (ProcessToken != NULL) {
  518. NtClose(ProcessToken);
  519. }
  520. // This should be NULL if successful.
  521. if ( pNewSD != NULL ) {
  522. LocalFree( pNewSD );
  523. }
  524. // If successful and the caller wanted to reference the SD, assign it now.
  525. if ( Status == ERROR_SUCCESS && poutSD != NULL ) {
  526. *poutSD = g_pClusterSecurityDescriptor;
  527. }
  528. if ( GlobalLocalSystemSid != NULL )
  529. {
  530. RtlFreeSid( GlobalLocalSystemSid );
  531. }
  532. if ( GlobalAliasAdminsSid != NULL )
  533. {
  534. RtlFreeSid( GlobalAliasAdminsSid );
  535. }
  536. if ( ! NT_SUCCESS( Status ) ) {
  537. ClRtlLogPrint(LOG_NOISE, "[ClRtl] ClRtlBuildClusterServiceSecurityDescriptor exit. Status = 0x%1!.8x!\n", Status );
  538. }
  539. return (DWORD) Status; // hack it to a DWORD...
  540. }
  541. NTSTATUS
  542. ClRtlImpersonateSelf(
  543. IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
  544. IN ACCESS_MASK AccessMask
  545. )
  546. /*++
  547. Routine Description:
  548. This routine may be used to obtain an Impersonation token representing
  549. your own process's context. This may be useful for enabling a privilege
  550. for a single thread rather than for the entire process; or changing
  551. the default DACL for a single thread.
  552. The token is assigned to the callers thread.
  553. Arguments:
  554. ImpersonationLevel - The level to make the impersonation token.
  555. AccessMask - Access control to the new token.
  556. Return Value:
  557. STATUS_SUCCESS - The thread is now impersonating the calling process.
  558. Other - Status values returned by:
  559. NtOpenProcessToken()
  560. NtDuplicateToken()
  561. NtSetInformationThread()
  562. --*/
  563. {
  564. NTSTATUS
  565. Status,
  566. IgnoreStatus;
  567. HANDLE
  568. Token1,
  569. Token2;
  570. OBJECT_ATTRIBUTES
  571. ObjectAttributes;
  572. SECURITY_QUALITY_OF_SERVICE
  573. Qos;
  574. PSECURITY_DESCRIPTOR
  575. pSecurityDescriptor = NULL;
  576. Status = ClRtlBuildClusterServiceSecurityDescriptor( &pSecurityDescriptor );
  577. if(NT_SUCCESS(Status))
  578. {
  579. InitializeObjectAttributes(&ObjectAttributes, NULL, 0, 0, NULL);
  580. Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  581. Qos.ImpersonationLevel = ImpersonationLevel;
  582. Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  583. Qos.EffectiveOnly = FALSE;
  584. ObjectAttributes.SecurityQualityOfService = &Qos;
  585. ObjectAttributes.SecurityDescriptor = pSecurityDescriptor;
  586. Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE, &Token1 );
  587. if (NT_SUCCESS(Status)) {
  588. Status = NtDuplicateToken(
  589. Token1,
  590. AccessMask,
  591. &ObjectAttributes,
  592. FALSE, //EffectiveOnly
  593. TokenImpersonation,
  594. &Token2
  595. );
  596. if (NT_SUCCESS(Status)) {
  597. Status = NtSetInformationThread(
  598. NtCurrentThread(),
  599. ThreadImpersonationToken,
  600. &Token2,
  601. sizeof(HANDLE)
  602. );
  603. IgnoreStatus = NtClose( Token2 );
  604. }
  605. IgnoreStatus = NtClose( Token1 );
  606. }
  607. }
  608. return(Status);
  609. }
  610. DWORD
  611. ClRtlEnableThreadPrivilege(
  612. IN ULONG Privilege,
  613. OUT BOOLEAN *pWasEnabled
  614. )
  615. /*++
  616. Routine Description:
  617. Enables a privilege for the current thread.
  618. Arguments:
  619. Privilege - The privilege to be enabled.
  620. pWasEnabled - Returns whether this privilege was originally
  621. enabled or disabled. This should be passed into
  622. ClRtlRestoreThreadPrivilege() for restoring the privileges of
  623. the thread back.
  624. Return Value:
  625. ERROR_SUCCESS if successful
  626. Win32 error code otherwise
  627. --*/
  628. {
  629. DWORD Status;
  630. BOOL bImpersonate = FALSE;
  631. //obtain a token that impersonates the security context
  632. //of the calling process
  633. Status = ClRtlImpersonateSelf( SecurityImpersonation, TOKEN_ALL_ACCESS );
  634. if ( !NT_SUCCESS( Status ) )
  635. {
  636. CL_LOGFAILURE(Status);
  637. goto FnExit;
  638. }
  639. bImpersonate = TRUE;
  640. //
  641. // Enable the required privilege
  642. //
  643. Status = RtlAdjustPrivilege(Privilege, TRUE, TRUE, pWasEnabled);
  644. if (!NT_SUCCESS(Status)) {
  645. CL_LOGFAILURE(Status);
  646. goto FnExit;
  647. }
  648. FnExit:
  649. if (Status != ERROR_SUCCESS)
  650. {
  651. if (bImpersonate)
  652. {
  653. //if this failed and if we
  654. //
  655. // terminate impersonation
  656. //
  657. HANDLE NullHandle;
  658. NullHandle = NULL;
  659. NtSetInformationThread(
  660. NtCurrentThread(),
  661. ThreadImpersonationToken,
  662. (PVOID) &NullHandle,
  663. sizeof( HANDLE ) );
  664. }
  665. }
  666. return(Status);
  667. }
  668. DWORD
  669. ClRtlRestoreThreadPrivilege(
  670. IN ULONG Privilege,
  671. IN BOOLEAN WasEnabled
  672. )
  673. /*++
  674. Routine Description:
  675. Restores the privilege for the current thread.
  676. Arguments:
  677. Privilege - The privilege to be enabled.
  678. WasEnabled - TRUE to restore this privilege to enabled state.
  679. FALSE otherwise.
  680. Return Value:
  681. ERROR_SUCCESS if successful
  682. Win32 error code otherwise
  683. --*/
  684. {
  685. DWORD Status = ERROR_SUCCESS;
  686. HANDLE NullHandle;
  687. DWORD ReturnStatus = ERROR_SUCCESS;
  688. //
  689. // If the privilege was originally disabled, disable it now.
  690. // Else we dont have to do anything.
  691. //
  692. if (!WasEnabled)
  693. {
  694. ReturnStatus = RtlAdjustPrivilege(Privilege,
  695. WasEnabled, TRUE, &WasEnabled);
  696. if (!NT_SUCCESS(ReturnStatus)) {
  697. CL_LOGFAILURE(ReturnStatus);
  698. //we still need to terminate the impersonation
  699. }
  700. }
  701. //
  702. // terminate impersonation
  703. //
  704. NullHandle = NULL;
  705. Status = NtSetInformationThread(
  706. NtCurrentThread(),
  707. ThreadImpersonationToken,
  708. (PVOID) &NullHandle,
  709. sizeof( HANDLE ) );
  710. if ( !NT_SUCCESS( Status ) )
  711. {
  712. CL_LOGFAILURE(Status);
  713. //Let the first error be reported
  714. if (ReturnStatus != ERROR_SUCCESS)
  715. ReturnStatus = Status;
  716. goto FnExit;
  717. }
  718. FnExit:
  719. return (ReturnStatus);
  720. }
  721. PSECURITY_DESCRIPTOR
  722. ClRtlCopySecurityDescriptor(
  723. IN PSECURITY_DESCRIPTOR psd
  724. )
  725. /*++
  726. Routine Description:
  727. Copy an NT security descriptor. The security descriptor must
  728. be in self-relative (not absolute) form. Delete the result using LocalFree()
  729. Arguments:
  730. psd - the SD to copy
  731. Return Value:
  732. NULL if an error occured or an invalid SD
  733. Call GetLastError for more detailed information
  734. --*/
  735. {
  736. PSECURITY_DESCRIPTOR pSelfSecDesc = NULL;
  737. SECURITY_DESCRIPTOR_CONTROL sdc;
  738. DWORD dwLen = 0;
  739. DWORD cbSelfSecDesc = 0;
  740. DWORD dwRevision = 0;
  741. DWORD status = ERROR_SUCCESS;
  742. if (NULL == psd) {
  743. SetLastError( ERROR_INVALID_PARAMETER );
  744. return NULL;
  745. }
  746. ASSERT(IsValidSecurityDescriptor(psd));
  747. if ( ! GetSecurityDescriptorControl( psd, &sdc, &dwRevision ) ) {
  748. status = GetLastError();
  749. ClRtlLogPrint(LOG_NOISE, "[ClRtl] CopySecurityDescriptor: GetSecurityDescriptorControl() failed:%1!d1\n", GetLastError());
  750. SetLastError( status );
  751. return NULL; // actually, should probably return an error
  752. }
  753. dwLen = GetSecurityDescriptorLength(psd);
  754. pSelfSecDesc = LocalAlloc( LMEM_ZEROINIT, dwLen );
  755. if (pSelfSecDesc == NULL) {
  756. ClRtlLogPrint(LOG_NOISE, "[ClRtl] CopySecurityDescriptor: LocalAlloc() SECURITY_DESCRIPTOR (2) failed\n");
  757. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  758. return NULL; // actually, should probably return an error
  759. }
  760. cbSelfSecDesc = dwLen;
  761. if (!MakeSelfRelativeSD(psd, pSelfSecDesc, &cbSelfSecDesc)) {
  762. if ( ( sdc & SE_SELF_RELATIVE ) == 0 ) {
  763. ClRtlLogPrint(LOG_NOISE, "[ClRtl] CopySecurityDescriptor: MakeSelfRelativeSD failed, 0x%1!.8x!\n", GetLastError());
  764. } // if: only log this error if the old SD was not already self-relative
  765. // assume it failed because it was already self-relative
  766. CopyMemory(pSelfSecDesc, psd, dwLen);
  767. }
  768. ASSERT(IsValidSecurityDescriptor(pSelfSecDesc));
  769. return pSelfSecDesc;
  770. } //*** ClRtlCopySecurityDescriptor()
  771. static VOID
  772. ClRtlGetSidTypeDesc(
  773. SID_NAME_USE SidType,
  774. LPSTR pszSidType,
  775. size_t cchSidType
  776. )
  777. /*++
  778. Routine Description:
  779. Convert the SidType into a meaningful string.
  780. Arguments:
  781. SidType -
  782. pszSidType
  783. cchSidType
  784. Return Value:
  785. none
  786. --*/
  787. {
  788. if ((pszSidType != NULL) && (cchSidType > 0))
  789. {
  790. char szSidType [128];
  791. switch (SidType)
  792. {
  793. case SidTypeUser:
  794. lstrcpyA(szSidType, "has a user SID for");
  795. break;
  796. case SidTypeGroup:
  797. lstrcpyA(szSidType, "has a group SID for");
  798. break;
  799. case SidTypeDomain:
  800. lstrcpyA(szSidType, "has a domain SID for");
  801. break;
  802. case SidTypeAlias:
  803. lstrcpyA(szSidType, "has an alias SID for");
  804. break;
  805. case SidTypeWellKnownGroup:
  806. lstrcpyA(szSidType, "has an SID for a well-known group for");
  807. break;
  808. case SidTypeDeletedAccount:
  809. lstrcpyA(szSidType, "has an SID for a deleted account for");
  810. break;
  811. case SidTypeInvalid:
  812. lstrcpyA(szSidType, "has an invalid SID for");
  813. break;
  814. case SidTypeUnknown:
  815. lstrcpyA(szSidType, "has an unknown SID type:");
  816. break;
  817. default:
  818. szSidType [0] = '\0';
  819. break;
  820. } // switch: SidType
  821. strncpy(pszSidType, szSidType, cchSidType);
  822. } // if: buffer not null and has space allocated
  823. } //*** ClRtlGetSidTypeDesc()
  824. static VOID
  825. ClRtlExamineSid(
  826. PSID pSid,
  827. LPSTR lpszOldIndent
  828. )
  829. /*++
  830. Routine Description:
  831. Dump the SID.
  832. Arguments:
  833. pSid -
  834. lpzOldIndent -
  835. Return Value:
  836. none
  837. --*/
  838. {
  839. CHAR szUserName [128];
  840. CHAR szDomainName [128];
  841. DWORD cbUser = sizeof(szUserName);
  842. DWORD cbDomain = sizeof(szDomainName);
  843. SID_NAME_USE SidType;
  844. if ( LookupAccountSidA( NULL, pSid, szUserName, &cbUser, szDomainName, &cbDomain, &SidType ) )
  845. {
  846. char szSidType [128];
  847. ClRtlGetSidTypeDesc( SidType, szSidType, sizeof( szSidType ) );
  848. ClRtlLogPrint( LOG_NOISE, "%1!hs!%2!hs! %3!hs!\\%4!hs!\n", lpszOldIndent, szSidType, szDomainName, szUserName ) ;
  849. }
  850. } // *** ClRtlExamineSid()
  851. VOID
  852. ClRtlExamineMask(
  853. ACCESS_MASK amMask,
  854. LPSTR lpszOldIndent
  855. )
  856. /*++
  857. Routine Description:
  858. Dump the AccessMask context.
  859. Arguments:
  860. amMask -
  861. lpzOldIndent -
  862. Return Value:
  863. none
  864. --*/
  865. {
  866. #define STANDARD_RIGHTS_ALL_THE_BITS 0x00FF0000L
  867. #define GENERIC_RIGHTS_ALL_THE_BITS 0xF0000000L
  868. CHAR szIndent[100] = "";
  869. CHAR ucIndentBitsBuf[100] = "";
  870. DWORD dwGenericBits;
  871. DWORD dwStandardBits;
  872. DWORD dwSpecificBits;
  873. DWORD dwAccessSystemSecurityBit;
  874. DWORD dwExtraBits;
  875. _snprintf( szIndent, sizeof( szIndent ), "%s ", lpszOldIndent );
  876. _snprintf( ucIndentBitsBuf, sizeof(ucIndentBitsBuf),
  877. "%s ",
  878. szIndent);
  879. dwStandardBits = (amMask & STANDARD_RIGHTS_ALL_THE_BITS);
  880. dwSpecificBits = (amMask & SPECIFIC_RIGHTS_ALL );
  881. dwAccessSystemSecurityBit = (amMask & ACCESS_SYSTEM_SECURITY );
  882. dwGenericBits = (amMask & GENERIC_RIGHTS_ALL_THE_BITS );
  883. // **************************************************************************
  884. // *
  885. // * Print then decode the standard rights bits
  886. // *
  887. // **************************************************************************
  888. ClRtlLogPrint(LOG_NOISE, "%1!hs! Standard Rights == 0x%2!.8x!\n", szIndent, dwStandardBits);
  889. if (dwStandardBits) {
  890. if ((dwStandardBits & DELETE) == DELETE) {
  891. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x%2!.8x! DELETE\n", ucIndentBitsBuf, DELETE);
  892. }
  893. if ((dwStandardBits & READ_CONTROL) == READ_CONTROL) {
  894. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x%2!.8x! READ_CONTROL\n", ucIndentBitsBuf, READ_CONTROL);
  895. }
  896. if ((dwStandardBits & STANDARD_RIGHTS_READ) == STANDARD_RIGHTS_READ) {
  897. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x%2!.8x! STANDARD_RIGHTS_READ\n", ucIndentBitsBuf, STANDARD_RIGHTS_READ);
  898. }
  899. if ((dwStandardBits & STANDARD_RIGHTS_WRITE) == STANDARD_RIGHTS_WRITE) {
  900. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x%2!.8x! STANDARD_RIGHTS_WRITE\n", ucIndentBitsBuf, STANDARD_RIGHTS_WRITE);
  901. }
  902. if ((dwStandardBits & STANDARD_RIGHTS_EXECUTE) == STANDARD_RIGHTS_EXECUTE) {
  903. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x%2!.8x! STANDARD_RIGHTS_EXECUTE\n", ucIndentBitsBuf, STANDARD_RIGHTS_EXECUTE);
  904. }
  905. if ((dwStandardBits & WRITE_DAC) == WRITE_DAC) {
  906. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x%2!.8x! WRITE_DAC\n", ucIndentBitsBuf, WRITE_DAC);
  907. }
  908. if ((dwStandardBits & WRITE_OWNER) == WRITE_OWNER) {
  909. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x%2!.8x! WRITE_OWNER\n", ucIndentBitsBuf, WRITE_OWNER);
  910. }
  911. if ((dwStandardBits & SYNCHRONIZE) == SYNCHRONIZE) {
  912. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x%2!.8x! SYNCHRONIZE\n", ucIndentBitsBuf, SYNCHRONIZE);
  913. }
  914. if ((dwStandardBits & STANDARD_RIGHTS_REQUIRED) == STANDARD_RIGHTS_REQUIRED) {
  915. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x%2!.8x! STANDARD_RIGHTS_REQUIRED\n", ucIndentBitsBuf, STANDARD_RIGHTS_REQUIRED);
  916. }
  917. if ((dwStandardBits & STANDARD_RIGHTS_ALL) == STANDARD_RIGHTS_ALL) {
  918. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x%2!.8x! STANDARD_RIGHTS_ALL\n", ucIndentBitsBuf, STANDARD_RIGHTS_ALL);
  919. }
  920. dwExtraBits = dwStandardBits & (~(DELETE
  921. | READ_CONTROL
  922. | STANDARD_RIGHTS_READ
  923. | STANDARD_RIGHTS_WRITE
  924. | STANDARD_RIGHTS_EXECUTE
  925. | WRITE_DAC
  926. | WRITE_OWNER
  927. | SYNCHRONIZE
  928. | STANDARD_RIGHTS_REQUIRED
  929. | STANDARD_RIGHTS_ALL));
  930. if (dwExtraBits) {
  931. ClRtlLogPrint(LOG_NOISE, "%1!hs! Extra standard bits == 0x%2!.8x! <-This is a problem, should be all 0s\n", szIndent, dwExtraBits);
  932. }
  933. }
  934. ClRtlLogPrint(LOG_NOISE, "%1!hs! Specific Rights == 0x%2!.8x!\n", szIndent, dwSpecificBits);
  935. // **************************************************************************
  936. // *
  937. // * Print then decode the ACCESS_SYSTEM_SECURITY bit
  938. // *
  939. // *************************************************************************
  940. ClRtlLogPrint(LOG_NOISE, "%1!hs! Access System Security == 0x%2!.8x!\n", szIndent, dwAccessSystemSecurityBit);
  941. // **************************************************************************
  942. // *
  943. // * Print then decode the generic rights bits, which will rarely be on
  944. // *
  945. // * Generic bits are nearly always mapped by Windows NT before it tries to do
  946. // * anything with them. You can ignore the fact that generic bits are
  947. // * special in any way, although it helps to keep track of what the mappings
  948. // * are so that you don't have any surprises
  949. // *
  950. // * The only time the generic bits are not mapped immediately is if they are
  951. // * placed in an inheritable ACE in an ACL, or in an ACL that will be
  952. // * assigned by default (such as the default DACL in an access token). In
  953. // * that case they're mapped when the child object is created (or when the
  954. // * default DACL is used at object creation time)
  955. // *
  956. // **************************************************************************
  957. ClRtlLogPrint(LOG_NOISE, "%1!hs! Generic Rights == 0x%2!.8x!\n", szIndent, dwGenericBits);
  958. if (dwGenericBits) {
  959. if ((dwGenericBits & GENERIC_READ) == GENERIC_READ) {
  960. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x%2!.8x! GENERIC_READ\n", ucIndentBitsBuf, GENERIC_READ);
  961. }
  962. if ((dwGenericBits & GENERIC_WRITE) == GENERIC_WRITE) {
  963. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x%2!.8x! GENERIC_WRITE\n", ucIndentBitsBuf, GENERIC_WRITE);
  964. }
  965. if ((dwGenericBits & GENERIC_EXECUTE) == GENERIC_EXECUTE) {
  966. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x%2!.8x! GENERIC_EXECUTE\n", ucIndentBitsBuf, GENERIC_EXECUTE);
  967. }
  968. if ((dwGenericBits & GENERIC_ALL) == GENERIC_ALL) {
  969. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x%2!.8x! GENERIC_ALL\n", ucIndentBitsBuf, GENERIC_ALL);
  970. }
  971. dwExtraBits = dwGenericBits & (~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL));
  972. if (dwExtraBits) {
  973. ClRtlLogPrint(LOG_NOISE, "%1!hs! Extra generic bits == 0x%2!.8x! <-This is a problem, should be all 0s\n", szIndent, dwExtraBits);
  974. }
  975. }
  976. } // *** ClRtlExamineMask()
  977. static BOOL
  978. ClRtlExamineACL(
  979. PACL paclACL,
  980. LPSTR lpszOldIndent
  981. )
  982. /*++
  983. Routine Description:
  984. Dump the Access Control List context.
  985. Arguments:
  986. amMask -
  987. lpzOldIndent -
  988. Return Value:
  989. none
  990. --*/
  991. {
  992. #define SZ_INDENT_BUF 80
  993. CHAR szIndent[100] = "";
  994. ACL_SIZE_INFORMATION asiAclSize;
  995. ACL_REVISION_INFORMATION ariAclRevision;
  996. DWORD dwBufLength;
  997. DWORD dwAcl_i;
  998. ACCESS_ALLOWED_ACE * paaAllowedAce;
  999. lstrcpyA(szIndent, lpszOldIndent);
  1000. lstrcatA(szIndent, " ");
  1001. if (!IsValidAcl(paclACL)) {
  1002. ClRtlLogPrint(LOG_NOISE, "%1!hs!ClRtlExamineACL() - IsValidAcl() failed.\n", szIndent);
  1003. return FALSE;
  1004. }
  1005. dwBufLength = sizeof(asiAclSize);
  1006. if (!GetAclInformation(paclACL, &asiAclSize, dwBufLength, AclSizeInformation)) {
  1007. ClRtlLogPrint(LOG_NOISE, "%1!hs!ClRtlExamineACL() - GetAclInformation failed.\n", szIndent);
  1008. return FALSE;
  1009. }
  1010. dwBufLength = sizeof(ariAclRevision);
  1011. if (!GetAclInformation(paclACL, (LPVOID) &ariAclRevision, dwBufLength, AclRevisionInformation)) {
  1012. ClRtlLogPrint(LOG_NOISE, "%1!hs!ClRtlExamineACL() - GetAclInformation failed\n", szIndent);
  1013. return FALSE;
  1014. }
  1015. ClRtlLogPrint(LOG_NOISE, "%1!hs!ACL has %2!d! ACE(s), %3!d! bytes used, %4!d! bytes free\n",
  1016. szIndent,
  1017. asiAclSize.AceCount,
  1018. asiAclSize.AclBytesInUse,
  1019. asiAclSize.AclBytesFree);
  1020. switch (ariAclRevision.AclRevision) {
  1021. case ACL_REVISION1:
  1022. ClRtlLogPrint(LOG_NOISE, "%1!hs!ACL revision is %2!d! == ACL_REVISION1\n", szIndent, ariAclRevision.AclRevision);
  1023. break;
  1024. case ACL_REVISION2:
  1025. ClRtlLogPrint(LOG_NOISE, "%1!hs!ACL revision is %2!d! == ACL_REVISION2\n", szIndent, ariAclRevision.AclRevision);
  1026. break;
  1027. default:
  1028. ClRtlLogPrint(LOG_NOISE, "%1!hs!ACL revision is %2!d! == ACL Revision is an IMPOSSIBLE ACL revision!!! Perhaps a new revision was added...\n",
  1029. szIndent,
  1030. ariAclRevision.AclRevision);
  1031. return FALSE;
  1032. break;
  1033. }
  1034. for (dwAcl_i = 0; dwAcl_i < asiAclSize.AceCount; dwAcl_i++) {
  1035. if (!GetAce(paclACL, dwAcl_i, (LPVOID *) &paaAllowedAce)) {
  1036. ClRtlLogPrint(LOG_NOISE, "%1!hs!ClRtlExamineACL() - GetAce failed.\n", szIndent);
  1037. return FALSE;
  1038. }
  1039. ClRtlLogPrint(LOG_NOISE, "%1!hs!ACE %2!d! size %3!d!\n", szIndent, dwAcl_i, paaAllowedAce->Header.AceSize);
  1040. {
  1041. char szBuf [128];
  1042. wsprintfA(szBuf, "%sACE %d ", szIndent, dwAcl_i);
  1043. ClRtlExamineSid(&(paaAllowedAce->SidStart), szBuf );
  1044. }
  1045. {
  1046. DWORD dwAceFlags = paaAllowedAce->Header.AceFlags;
  1047. ClRtlLogPrint(LOG_NOISE, "%1!hs!ACE %2!d! flags 0x%3!.2x!\n", szIndent, dwAcl_i, dwAceFlags);
  1048. if (dwAceFlags) {
  1049. DWORD dwExtraBits;
  1050. CHAR ucIndentBitsBuf[SZ_INDENT_BUF] = "";
  1051. lstrcpyA(ucIndentBitsBuf, szIndent);
  1052. lstrcatA(ucIndentBitsBuf, " ");
  1053. if ((dwAceFlags & OBJECT_INHERIT_ACE) == OBJECT_INHERIT_ACE) {
  1054. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x01 OBJECT_INHERIT_ACE\n", ucIndentBitsBuf);
  1055. }
  1056. if ((dwAceFlags & CONTAINER_INHERIT_ACE) == CONTAINER_INHERIT_ACE) {
  1057. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x02 CONTAINER_INHERIT_ACE\n", ucIndentBitsBuf);
  1058. }
  1059. if ((dwAceFlags & NO_PROPAGATE_INHERIT_ACE) == NO_PROPAGATE_INHERIT_ACE) {
  1060. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x04 NO_PROPAGATE_INHERIT_ACE\n", ucIndentBitsBuf);
  1061. }
  1062. if ((dwAceFlags & INHERIT_ONLY_ACE) == INHERIT_ONLY_ACE) {
  1063. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x08 INHERIT_ONLY_ACE\n", ucIndentBitsBuf);
  1064. }
  1065. if ((dwAceFlags & VALID_INHERIT_FLAGS) == VALID_INHERIT_FLAGS) {
  1066. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x0F VALID_INHERIT_FLAGS\n", ucIndentBitsBuf);
  1067. }
  1068. if ((dwAceFlags & SUCCESSFUL_ACCESS_ACE_FLAG) == SUCCESSFUL_ACCESS_ACE_FLAG) {
  1069. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x40 SUCCESSFUL_ACCESS_ACE_FLAG\n", ucIndentBitsBuf);
  1070. }
  1071. if ((dwAceFlags & FAILED_ACCESS_ACE_FLAG) == FAILED_ACCESS_ACE_FLAG) {
  1072. ClRtlLogPrint(LOG_NOISE, "%1!hs!0x80 FAILED_ACCESS_ACE_FLAG\n", ucIndentBitsBuf);
  1073. }
  1074. dwExtraBits = dwAceFlags & (~(OBJECT_INHERIT_ACE
  1075. | CONTAINER_INHERIT_ACE
  1076. | NO_PROPAGATE_INHERIT_ACE
  1077. | INHERIT_ONLY_ACE
  1078. | VALID_INHERIT_FLAGS
  1079. | SUCCESSFUL_ACCESS_ACE_FLAG
  1080. | FAILED_ACCESS_ACE_FLAG));
  1081. if (dwExtraBits) {
  1082. ClRtlLogPrint(LOG_NOISE, "%1!hs! Extra AceFlag bits == 0x%2!.8x! <-This is a problem, should be all 0s\n",
  1083. szIndent,
  1084. dwExtraBits);
  1085. }
  1086. }
  1087. }
  1088. switch (paaAllowedAce->Header.AceType) {
  1089. case ACCESS_ALLOWED_ACE_TYPE:
  1090. ClRtlLogPrint(LOG_NOISE, "%1!hs!ACE %2!d! is an ACCESS_ALLOWED_ACE_TYPE\n", szIndent, dwAcl_i);
  1091. break;
  1092. case ACCESS_DENIED_ACE_TYPE:
  1093. ClRtlLogPrint(LOG_NOISE, "%1!hs!ACE %2!d! is an ACCESS_DENIED_ACE_TYPE\n", szIndent, dwAcl_i);
  1094. break;
  1095. case SYSTEM_AUDIT_ACE_TYPE:
  1096. ClRtlLogPrint(LOG_NOISE, "%1!hs!ACE %2!d! is a SYSTEM_AUDIT_ACE_TYPE\n", szIndent, dwAcl_i);
  1097. break;
  1098. case SYSTEM_ALARM_ACE_TYPE:
  1099. ClRtlLogPrint(LOG_NOISE, "%1!hs!ACE %2!d! is a SYSTEM_ALARM_ACE_TYPE\n", szIndent, dwAcl_i);
  1100. break;
  1101. default :
  1102. ClRtlLogPrint(LOG_NOISE, "%1!hs!ACE %2!d! is an IMPOSSIBLE ACE_TYPE!!! Run debugger, examine value!\n", szIndent, dwAcl_i);
  1103. return FALSE;
  1104. }
  1105. ClRtlLogPrint(LOG_NOISE, "%1!hs!ACE %2!d! mask == 0x%3!.8x!\n", szIndent, dwAcl_i, paaAllowedAce->Mask);
  1106. ClRtlExamineMask(paaAllowedAce->Mask, szIndent);
  1107. }
  1108. return TRUE;
  1109. } // *** ClRtlExamineACL()
  1110. BOOL
  1111. ClRtlExamineSD(
  1112. PSECURITY_DESCRIPTOR psdSD,
  1113. LPSTR pszPrefix
  1114. )
  1115. /*++
  1116. Routine Description:
  1117. Dump the Security descriptor context.
  1118. Arguments:
  1119. psdSD - the SD to dump
  1120. Return Value:
  1121. BOOL, TRUE for success, FALSE for failure
  1122. --*/
  1123. {
  1124. PACL paclDACL;
  1125. PACL paclSACL;
  1126. BOOL bHasDACL = FALSE;
  1127. BOOL bHasSACL = FALSE;
  1128. BOOL bDaclDefaulted = FALSE;
  1129. BOOL bSaclDefaulted = FALSE;
  1130. BOOL bOwnerDefaulted = FALSE;
  1131. BOOL bGroupDefaulted = FALSE;
  1132. PSID psidOwner;
  1133. PSID psidGroup;
  1134. SECURITY_DESCRIPTOR_CONTROL sdcSDControl;
  1135. DWORD dwSDRevision;
  1136. DWORD dwSDLength;
  1137. char szIndent [33];
  1138. strncpy(szIndent, pszPrefix, sizeof(szIndent) - 1);
  1139. strcat(szIndent, " ");
  1140. if (!IsValidSecurityDescriptor(psdSD)) {
  1141. ClRtlLogPrint(LOG_NOISE, "%1!hs!ClRtlExamineSD() - IsValidSecurityDescriptor failed.\n", szIndent);
  1142. return FALSE;
  1143. }
  1144. dwSDLength = GetSecurityDescriptorLength(psdSD);
  1145. if (!GetSecurityDescriptorDacl(psdSD, (LPBOOL) &bHasDACL, (PACL *) &paclDACL, (LPBOOL) &bDaclDefaulted)) {
  1146. ClRtlLogPrint(LOG_NOISE, "%1!hs!ClRtlExamineSD() - GetSecurityDescriptorDacl failed.\n", szIndent);
  1147. return FALSE;
  1148. }
  1149. if (!GetSecurityDescriptorSacl(psdSD, (LPBOOL) &bHasSACL, (PACL *) &paclSACL, (LPBOOL) &bSaclDefaulted)) {
  1150. ClRtlLogPrint(LOG_NOISE, "%1!hs!ClRtlExamineSD() - GetSecurityDescriptorSacl failed.\n", szIndent);
  1151. return FALSE;
  1152. }
  1153. if (!GetSecurityDescriptorOwner(psdSD, (PSID *)&psidOwner, (LPBOOL)&bOwnerDefaulted)) {
  1154. ClRtlLogPrint(LOG_NOISE, "%1!hs!ClRtlExamineSD() - GetSecurityDescriptorOwner failed.\n", szIndent);
  1155. return FALSE;
  1156. }
  1157. if (!GetSecurityDescriptorGroup(psdSD, (PSID *) &psidGroup, (LPBOOL) &bGroupDefaulted)) {
  1158. ClRtlLogPrint(LOG_NOISE, "%1!hs!ClRtlExamineSD() - GetSecurityDescriptorGroup failed.\n", szIndent);
  1159. return FALSE;
  1160. }
  1161. if (!GetSecurityDescriptorControl(
  1162. psdSD,
  1163. (PSECURITY_DESCRIPTOR_CONTROL) &sdcSDControl,
  1164. (LPDWORD) &dwSDRevision)) {
  1165. ClRtlLogPrint(LOG_NOISE, "%1!hs!ClRtlExamineSD() - GetSecurityDescriptorControl failed.\n", szIndent);
  1166. return FALSE;
  1167. }
  1168. switch (dwSDRevision) {
  1169. case SECURITY_DESCRIPTOR_REVISION1:
  1170. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD is valid. SD is %2!d! bytes long. SD revision is %3!d! == SECURITY_DESCRIPTOR_REVISION1\n", szIndent, dwSDLength, dwSDRevision);
  1171. break;
  1172. default :
  1173. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD is valid. SD is %2!d! bytes long. SD revision is %3!d! == ! SD Revision is an IMPOSSIBLE SD revision!!! Perhaps a new revision was added...\n",
  1174. szIndent,
  1175. dwSDLength,
  1176. dwSDRevision);
  1177. return FALSE;
  1178. }
  1179. if (SE_SELF_RELATIVE & sdcSDControl) {
  1180. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD is in self-relative format (all SDs returned by the system are)\n", szIndent);
  1181. }
  1182. if (NULL == psidOwner) {
  1183. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD's Owner is NULL, so SE_OWNER_DEFAULTED is ignored\n", szIndent);
  1184. }
  1185. else {
  1186. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD's Owner is Not NULL\n", szIndent);
  1187. if (bOwnerDefaulted) {
  1188. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD's Owner-Defaulted flag is TRUE\n", szIndent);
  1189. }
  1190. else {
  1191. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD's Owner-Defaulted flag is FALSE\n", szIndent);
  1192. }
  1193. }
  1194. // **************************************************************************
  1195. // *
  1196. // * The other use for psidGroup is for Macintosh client support
  1197. // *
  1198. // **************************************************************************
  1199. if (NULL == psidGroup) {
  1200. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD's Group is NULL, so SE_GROUP_DEFAULTED is ignored. SD's Group being NULL is typical, GROUP in SD(s) is mainly for POSIX compliance\n", szIndent);
  1201. }
  1202. else {
  1203. if (bGroupDefaulted) {
  1204. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD's Group-Defaulted flag is TRUE\n", szIndent);
  1205. }
  1206. else {
  1207. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD's Group-Defaulted flag is FALSE\n", szIndent);
  1208. }
  1209. }
  1210. if (SE_DACL_PRESENT & sdcSDControl) {
  1211. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD's DACL is Present\n", szIndent);
  1212. if (bDaclDefaulted) {
  1213. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD's DACL-Defaulted flag is TRUE\n", szIndent);
  1214. } else {
  1215. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD's DACL-Defaulted flag is FALSE\n", szIndent);
  1216. }
  1217. if (NULL == paclDACL) {
  1218. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD has a NULL DACL explicitly specified (allows all access to Everyone). This does not apply to this SD, but for comparison, a non-NULL DACL pointer to a 0-length ACL allows no access to anyone\n", szIndent);
  1219. }
  1220. else if(!ClRtlExamineACL(paclDACL, pszPrefix)) {
  1221. ClRtlLogPrint(LOG_NOISE, "%1!hs!ClRtlExamineSD() - ClRtlExamineACL failed.\n", szIndent);
  1222. }
  1223. }
  1224. else {
  1225. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD's DACL is Not Present, so SE_DACL_DEFAULTED is ignored. SD has no DACL at all (allows all access to Everyone)\n", szIndent);
  1226. }
  1227. if (SE_SACL_PRESENT & sdcSDControl) {
  1228. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD's SACL is Present\n", szIndent);
  1229. if (bSaclDefaulted) {
  1230. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD's SACL-Defaulted flag is TRUE\n", szIndent);
  1231. }
  1232. else {
  1233. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD's SACL-Defaulted flag is FALSE\n", szIndent);
  1234. }
  1235. if (NULL == paclSACL) {
  1236. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD has a NULL SACL explicitly specified\n", szIndent);
  1237. }
  1238. else if (!ClRtlExamineACL(paclSACL, pszPrefix)) {
  1239. ClRtlLogPrint(LOG_NOISE, "%1!hs!ClRtlExamineSD() - ClRtlExamineACL failed.\n", szIndent);
  1240. }
  1241. }
  1242. else {
  1243. ClRtlLogPrint(LOG_NOISE, "%1!hs!SD's SACL is Not Present, so SE_SACL_DEFAULTED is ignored. SD has no SACL at all (or we did not request to see it)\n", szIndent);
  1244. }
  1245. return TRUE;
  1246. } // *** ClRtlExamineSD()
  1247. DWORD
  1248. ClRtlBuildDefaultClusterSD(
  1249. IN PSID pOwnerSid,
  1250. PSECURITY_DESCRIPTOR * SD,
  1251. ULONG * SizeSD
  1252. )
  1253. /*++
  1254. Routine Description:
  1255. Builds the default security descriptor to control access to
  1256. the cluster API
  1257. Modified permissions in ACEs in order to augment cluster security
  1258. administration.
  1259. Arguments:
  1260. pOwnerSid - Supplies the SID that the cluster account runs in
  1261. SD - Returns a pointer to the created security descriptor. This
  1262. should be freed by the caller.
  1263. SizeSD - Returns the size in bytes of the security descriptor
  1264. Return Value:
  1265. ERROR_SUCCESS if successful
  1266. Win32 error code otherwise
  1267. --*/
  1268. {
  1269. DWORD Status;
  1270. HANDLE Token;
  1271. PACL pAcl = NULL;
  1272. DWORD cbDaclSize;
  1273. PSECURITY_DESCRIPTOR psd;
  1274. PSECURITY_DESCRIPTOR NewSD;
  1275. BYTE SDBuffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
  1276. PACCESS_ALLOWED_ACE pAce;
  1277. PSID pAdminSid = NULL;
  1278. PSID pSystemSid = NULL;
  1279. PSID pServiceSid = NULL;
  1280. PULONG pSubAuthority;
  1281. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  1282. ULONG NewSDLen;
  1283. psd = (PSECURITY_DESCRIPTOR) SDBuffer;
  1284. //
  1285. // allocate and init the Administrators group sid
  1286. //
  1287. if ( !AllocateAndInitializeSid( &siaNtAuthority,
  1288. 2,
  1289. SECURITY_BUILTIN_DOMAIN_RID,
  1290. DOMAIN_ALIAS_RID_ADMINS,
  1291. 0, 0, 0, 0, 0, 0,
  1292. &pAdminSid ) ) {
  1293. Status = GetLastError();
  1294. goto error_exit;
  1295. }
  1296. //
  1297. // allocate and init the SYSTEM sid
  1298. //
  1299. if ( !AllocateAndInitializeSid( &siaNtAuthority,
  1300. 1,
  1301. SECURITY_LOCAL_SYSTEM_RID,
  1302. 0, 0, 0, 0, 0, 0, 0,
  1303. &pSystemSid ) ) {
  1304. Status = GetLastError();
  1305. goto error_exit;
  1306. }
  1307. if ( pOwnerSid == NULL ) {
  1308. pOwnerSid = pAdminSid;
  1309. }
  1310. //
  1311. // allocate and init the Service sid
  1312. //
  1313. if ( !AllocateAndInitializeSid( &siaNtAuthority,
  1314. 1,
  1315. SECURITY_SERVICE_RID,
  1316. 0, 0, 0, 0, 0, 0, 0,
  1317. &pServiceSid ) ) {
  1318. Status = GetLastError();
  1319. goto error_exit;
  1320. }
  1321. //
  1322. // Set up the DACL that will allow admins all access.
  1323. // It should be large enough to hold 3 ACEs and their SIDs
  1324. //
  1325. cbDaclSize = ( 3 * sizeof( ACCESS_ALLOWED_ACE ) ) +
  1326. GetLengthSid( pAdminSid ) +
  1327. GetLengthSid( pSystemSid ) +
  1328. GetLengthSid( pServiceSid );
  1329. pAcl = (PACL) LocalAlloc( LPTR, cbDaclSize );
  1330. if ( pAcl == NULL ) {
  1331. Status = ERROR_NOT_ENOUGH_MEMORY;
  1332. goto error_exit;
  1333. }
  1334. InitializeSecurityDescriptor( psd, SECURITY_DESCRIPTOR_REVISION );
  1335. InitializeAcl( pAcl, cbDaclSize, ACL_REVISION );
  1336. //
  1337. // Add the ACE for the local Administrators group to the DACL
  1338. //
  1339. if ( !AddAccessAllowedAce( pAcl,
  1340. ACL_REVISION,
  1341. CLUSAPI_ALL_ACCESS, // What the admin can do
  1342. pAdminSid ) ) {
  1343. Status = GetLastError();
  1344. goto error_exit;
  1345. }
  1346. //
  1347. // Add the ACE for the SYSTEM account to the DACL
  1348. //
  1349. if ( !AddAccessAllowedAce( pAcl,
  1350. ACL_REVISION,
  1351. CLUSAPI_ALL_ACCESS, // What local system can do
  1352. pSystemSid ) ) {
  1353. Status = GetLastError();
  1354. goto error_exit;
  1355. }
  1356. //
  1357. // Add the ACE for the Service account to the DACL
  1358. //
  1359. if ( !AddAccessAllowedAce( pAcl,
  1360. ACL_REVISION,
  1361. CLUSAPI_ALL_ACCESS, // What services can do
  1362. pServiceSid ) ) {
  1363. Status = GetLastError();
  1364. goto error_exit;
  1365. }
  1366. if ( !GetAce( pAcl, 0, (PVOID *) &pAce ) ) {
  1367. Status = GetLastError();
  1368. goto error_exit;
  1369. }
  1370. pAce->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
  1371. if ( !GetAce( pAcl, 1, (PVOID *) &pAce ) ) {
  1372. Status = GetLastError();
  1373. goto error_exit;
  1374. }
  1375. pAce->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
  1376. if ( !GetAce( pAcl, 2, (PVOID *) &pAce ) ) {
  1377. Status = GetLastError();
  1378. goto error_exit;
  1379. }
  1380. pAce->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
  1381. if ( !SetSecurityDescriptorDacl( psd, TRUE, pAcl, FALSE ) ) {
  1382. Status = GetLastError();
  1383. goto error_exit;
  1384. }
  1385. if ( !SetSecurityDescriptorOwner( psd, pOwnerSid, FALSE ) ) {
  1386. Status = GetLastError();
  1387. goto error_exit;
  1388. }
  1389. if ( !SetSecurityDescriptorGroup( psd, pOwnerSid, FALSE ) ) {
  1390. Status = GetLastError();
  1391. goto error_exit;
  1392. }
  1393. if ( !SetSecurityDescriptorSacl( psd, TRUE, NULL, FALSE ) ) {
  1394. Status = GetLastError();
  1395. goto error_exit;
  1396. }
  1397. NewSDLen = 0 ;
  1398. if ( !MakeSelfRelativeSD( psd, NULL, &NewSDLen ) ) {
  1399. Status = GetLastError();
  1400. if ( Status != ERROR_INSUFFICIENT_BUFFER ) { // Duh, we're trying to find out how big the buffer should be?
  1401. goto error_exit;
  1402. }
  1403. }
  1404. NewSD = LocalAlloc( LPTR, NewSDLen );
  1405. if ( NewSD ) {
  1406. if ( !MakeSelfRelativeSD( psd, NewSD, &NewSDLen ) ) {
  1407. Status = GetLastError();
  1408. goto error_exit;
  1409. }
  1410. Status = ERROR_SUCCESS;
  1411. *SD = NewSD;
  1412. *SizeSD = NewSDLen;
  1413. } else {
  1414. Status = ERROR_NOT_ENOUGH_MEMORY;
  1415. }
  1416. error_exit:
  1417. if ( pAdminSid != NULL ) {
  1418. FreeSid( pAdminSid );
  1419. }
  1420. if ( pSystemSid != NULL ) {
  1421. FreeSid( pSystemSid );
  1422. }
  1423. if ( pServiceSid != NULL ) {
  1424. FreeSid( pServiceSid );
  1425. }
  1426. if ( pAcl != NULL ) {
  1427. LocalFree( pAcl );
  1428. }
  1429. return( Status );
  1430. } // *** ClRtlBuildDefaultClusterSD()
  1431. static BOOL
  1432. ClRtlGetTokenInformation(
  1433. HANDLE hClientToken,
  1434. TOKEN_INFORMATION_CLASS ticRequest,
  1435. PBYTE * ppb,
  1436. LPSTR pszPrefix
  1437. )
  1438. /*++
  1439. Routine Description:
  1440. Get the requested information from the passed in client token.
  1441. Arguments:
  1442. hClientToken - the client token to dump
  1443. Return Value:
  1444. BOOL, TRUE for success, FALSE for failure
  1445. --*/
  1446. {
  1447. PBYTE _pb = NULL;
  1448. DWORD _cb = 64;
  1449. DWORD _cbNeeded = 0;
  1450. DWORD _sc = NO_ERROR;
  1451. //
  1452. // Get the user information from the client token.
  1453. //
  1454. do {
  1455. _pb = LocalAlloc( LMEM_ZEROINIT, _cb );
  1456. if ( _pb == NULL ) {
  1457. _sc = GetLastError();
  1458. ClRtlLogPrint( LOG_NOISE, "%1!hs!ClRtlGetTokenInformation() - LocalAlloc() failed:%2!d!\n", pszPrefix, _sc ) ;
  1459. return FALSE;
  1460. } // if: LocalAlloc failed
  1461. if ( ! GetTokenInformation( hClientToken, ticRequest, _pb, _cb, &_cbNeeded ) ) {
  1462. _sc = GetLastError();
  1463. if ( _sc == ERROR_INSUFFICIENT_BUFFER ) {
  1464. _cb = _cbNeeded;
  1465. LocalFree( _pb );
  1466. _pb = NULL;
  1467. continue;
  1468. } // if: buffer size is too small
  1469. else {
  1470. ClRtlLogPrint( LOG_NOISE, "%1!hs!ClRtlGetTokenInformation() - GetTokenInformation() failed:%2!d!\n", pszPrefix, _sc ) ;
  1471. return FALSE;
  1472. } // else: fatal error
  1473. } // if: GetTokenInformation failed
  1474. break; // everything is ok and we can exit the loop normally
  1475. } while( TRUE );
  1476. *ppb = _pb;
  1477. return TRUE;
  1478. } // *** ClRtlGetTokenInformation()
  1479. BOOL
  1480. ClRtlExamineClientToken(
  1481. HANDLE hClientToken,
  1482. LPSTR pszPrefix
  1483. )
  1484. /*++
  1485. Routine Description:
  1486. Dump the client token.
  1487. Arguments:
  1488. hClientToken - the client token to dump
  1489. Return Value:
  1490. BOOL, TRUE for success, FALSE for failure
  1491. --*/
  1492. {
  1493. char _szIndent [33];
  1494. char _szBuf [128];
  1495. PBYTE _pb = NULL;
  1496. strncpy( _szIndent, pszPrefix, sizeof( _szIndent ) - 1 );
  1497. strcat( _szIndent, " " );
  1498. //
  1499. // Get the user information from the client token.
  1500. //
  1501. if ( ClRtlGetTokenInformation( hClientToken, TokenUser, &_pb, _szIndent ) ) {
  1502. PTOKEN_USER _ptu = NULL;
  1503. wsprintfA( _szBuf, "%sClientToken ", _szIndent );
  1504. _ptu = (PTOKEN_USER) _pb;
  1505. ClRtlExamineSid( _ptu->User.Sid, _szBuf );
  1506. LocalFree( _pb );
  1507. _pb = NULL;
  1508. }
  1509. //
  1510. // Get the user's group information from the client token.
  1511. //
  1512. if ( ClRtlGetTokenInformation( hClientToken, TokenGroups, &_pb, _szIndent ) ) {
  1513. PTOKEN_GROUPS _ptg = NULL;
  1514. DWORD _nIndex = 0;
  1515. wsprintfA( _szBuf, "%s ClientToken ", _szIndent );
  1516. _ptg = (PTOKEN_GROUPS) _pb;
  1517. for ( _nIndex = 0; _nIndex < _ptg->GroupCount; _nIndex++ )
  1518. {
  1519. ClRtlExamineSid( _ptg->Groups[ _nIndex ].Sid, _szBuf );
  1520. }
  1521. LocalFree( _pb );
  1522. _pb = NULL;
  1523. }
  1524. //
  1525. // Get the token type information from the client token.
  1526. //
  1527. if ( ClRtlGetTokenInformation( hClientToken, TokenType, &_pb, _szIndent ) ) {
  1528. PTOKEN_TYPE _ptt = NULL;
  1529. wsprintfA( _szBuf, "%s ClientToken type is", _szIndent );
  1530. _ptt = (PTOKEN_TYPE) _pb;
  1531. if ( *_ptt == TokenPrimary ) {
  1532. ClRtlLogPrint( LOG_NOISE, "%1!hs! primary.\n", _szBuf ) ;
  1533. }
  1534. if ( *_ptt == TokenImpersonation ) {
  1535. ClRtlLogPrint( LOG_NOISE, "%1!hs! impersonation.\n", _szBuf ) ;
  1536. }
  1537. LocalFree( _pb );
  1538. _pb = NULL;
  1539. }
  1540. //
  1541. // Get the token impersonation level information from the client token.
  1542. //
  1543. if ( ClRtlGetTokenInformation( hClientToken, TokenImpersonationLevel, &_pb, _szIndent ) ) {
  1544. PSECURITY_IMPERSONATION_LEVEL _psil = NULL;
  1545. wsprintfA( _szBuf, "%s ClientToken security impersonation level is", _szIndent );
  1546. _psil = (PSECURITY_IMPERSONATION_LEVEL) _pb;
  1547. switch ( *_psil )
  1548. {
  1549. case SecurityAnonymous :
  1550. ClRtlLogPrint( LOG_NOISE, "%1!hs! Anonymous.\n", _szBuf ) ;
  1551. break;
  1552. case SecurityIdentification :
  1553. ClRtlLogPrint( LOG_NOISE, "%1!hs! Identification.\n", _szBuf ) ;
  1554. break;
  1555. case SecurityImpersonation :
  1556. ClRtlLogPrint( LOG_NOISE, "%1!hs! Impersonation.\n", _szBuf ) ;
  1557. break;
  1558. case SecurityDelegation :
  1559. ClRtlLogPrint( LOG_NOISE, "%1!hs! Delegation.\n", _szBuf ) ;
  1560. break;
  1561. }
  1562. LocalFree( _pb );
  1563. _pb = NULL;
  1564. }
  1565. return TRUE;
  1566. } // *** ClRtlExamineClientToken()
  1567. DWORD
  1568. ClRtlIsCallerAccountLocalSystemAccount(
  1569. OUT PBOOL pbIsLocalSystemAccount
  1570. )
  1571. /*++
  1572. Routine Description:
  1573. This function checks whether the caller's account is the local system
  1574. account.
  1575. Arguments:
  1576. pbIsLocalSystemAccount - The caller's account is local system account or not.
  1577. Return Value:
  1578. ERROR_SUCCESS on success.
  1579. Win32 error code on failure.
  1580. Remarks:
  1581. Must be called by an impersonating thread.
  1582. --*/
  1583. {
  1584. DWORD dwStatus = ERROR_SUCCESS;
  1585. SID_IDENTIFIER_AUTHORITY
  1586. siaNtAuthority = SECURITY_NT_AUTHORITY;
  1587. PSID psidLocalSystem = NULL;
  1588. *pbIsLocalSystemAccount = FALSE;
  1589. if ( !AllocateAndInitializeSid(
  1590. &siaNtAuthority,
  1591. 1,
  1592. SECURITY_LOCAL_SYSTEM_RID,
  1593. 0, 0, 0, 0, 0, 0, 0,
  1594. &psidLocalSystem ) )
  1595. {
  1596. dwStatus = GetLastError();
  1597. goto FnExit;
  1598. }
  1599. if ( !CheckTokenMembership(
  1600. NULL,
  1601. psidLocalSystem,
  1602. pbIsLocalSystemAccount ) )
  1603. {
  1604. dwStatus = GetLastError();
  1605. }
  1606. FnExit:
  1607. if( psidLocalSystem != NULL )
  1608. {
  1609. FreeSid( psidLocalSystem );
  1610. }
  1611. return( dwStatus );
  1612. }
  1613. PTOKEN_USER
  1614. ClRtlGetSidOfCallingThread(
  1615. VOID
  1616. )
  1617. /*++
  1618. Routine Description:
  1619. Get the SID associated with the calling thread (or process if the thread
  1620. has no token)
  1621. Arguments:
  1622. none
  1623. Return Value:
  1624. pointer to TOKEN_USER data; null if error with last error set on thread
  1625. --*/
  1626. {
  1627. HANDLE currentToken;
  1628. PTOKEN_USER tokenUserData;
  1629. DWORD sizeRequired;
  1630. BOOL success;
  1631. // check if there is a thread token
  1632. if (!OpenThreadToken(GetCurrentThread(),
  1633. MAXIMUM_ALLOWED,
  1634. TRUE,
  1635. &currentToken))
  1636. {
  1637. // get the process token
  1638. if (!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &currentToken )) {
  1639. return NULL;
  1640. }
  1641. }
  1642. //
  1643. // get the size needed
  1644. //
  1645. success = GetTokenInformation(currentToken,
  1646. TokenUser,
  1647. NULL,
  1648. 0,
  1649. &sizeRequired);
  1650. tokenUserData = LocalAlloc( LMEM_FIXED, sizeRequired );
  1651. if ( tokenUserData == NULL ) {
  1652. CloseHandle( currentToken );
  1653. return NULL;
  1654. }
  1655. success = GetTokenInformation(currentToken,
  1656. TokenUser,
  1657. tokenUserData,
  1658. sizeRequired,
  1659. &sizeRequired);
  1660. CloseHandle( currentToken );
  1661. if ( !success ) {
  1662. LocalFree( tokenUserData );
  1663. return NULL;
  1664. }
  1665. return tokenUserData;
  1666. } // ClRtlGetSidOfCallingThread
  1667. #if 0
  1668. //
  1669. // not needed but no point in throwing it away just yet
  1670. //
  1671. DWORD
  1672. ClRtlConvertDomainAccountToSid(
  1673. IN LPWSTR AccountInfo,
  1674. OUT PSID * AccountSid
  1675. )
  1676. /*++
  1677. Routine Description:
  1678. For the given credentials, look up the account SID for the specified
  1679. domain.
  1680. Arguments:
  1681. AccountInfo - pointer to string of the form 'domain\user'
  1682. AccountSid - address of pointer that receives the SID for this user
  1683. Return Value:
  1684. ERROR_SUCCESS if everything worked
  1685. --*/
  1686. {
  1687. DWORD dwStatus = ERROR_SUCCESS;
  1688. DWORD dwSidSize = 128;
  1689. DWORD dwDomainNameSize = DNS_MAX_NAME_BUFFER_LENGTH;
  1690. LPWSTR pwszDomainName;
  1691. SID_NAME_USE SidType;
  1692. PSID accountSid;
  1693. do {
  1694. //
  1695. // Attempt to allocate a buffer for the SID.
  1696. //
  1697. accountSid = LocalAlloc( LMEM_FIXED, dwSidSize );
  1698. pwszDomainName = (LPWSTR) LocalAlloc( LMEM_FIXED, dwDomainNameSize * sizeof(WCHAR) );
  1699. // Was space allocated for the SID and domain name successfully?
  1700. if ( accountSid == NULL || pwszDomainName == NULL ) {
  1701. if ( accountSid != NULL ) {
  1702. LocalFree( accountSid );
  1703. }
  1704. if ( pwszDomainName != NULL ) {
  1705. LocalFree( pwszDomainName );
  1706. }
  1707. return ERROR_NOT_ENOUGH_MEMORY;
  1708. }
  1709. //
  1710. // Attempt to Retrieve the SID and domain name. If LookupAccountName fails
  1711. // because of insufficient buffer size(s) dwSidSize and dwDomainNameSize
  1712. // will be set correctly for the next attempt.
  1713. //
  1714. if ( !LookupAccountName( NULL,
  1715. AccountInfo,
  1716. accountSid,
  1717. &dwSidSize,
  1718. pwszDomainName,
  1719. &dwDomainNameSize,
  1720. &SidType ))
  1721. {
  1722. // free the Sid buffer and find out why we failed
  1723. LocalFree( accountSid );
  1724. dwStatus = GetLastError();
  1725. }
  1726. // domain name isn't needed at any time
  1727. LocalFree( pwszDomainName );
  1728. pwszDomainName = NULL;
  1729. } while ( dwStatus == ERROR_INSUFFICIENT_BUFFER );
  1730. if ( dwStatus == ERROR_SUCCESS ) {
  1731. *AccountSid = accountSid;
  1732. }
  1733. return dwStatus;
  1734. } // ClRtlConvertDomainAccountToSid
  1735. #endif
  1736. DWORD
  1737. AddAceToAcl(
  1738. IN PACL pOldAcl,
  1739. IN PSID pClientSid,
  1740. IN ACCESS_MASK AccessMask,
  1741. OUT PACL * ppNewAcl
  1742. )
  1743. /*++
  1744. Routine Description:
  1745. This routine creates a new ACL by copying the ACEs from the old ACL and
  1746. creating a new ACE with pClientSid and AccessMask. Stolen from
  1747. \nt\ds\ds\src\ntdsa\dra\remove.c
  1748. Arguments:
  1749. pOldAcl - pointer to old ACL with its ACEs
  1750. pClientSid - SID to add
  1751. AccessMask - access mask associated with SID
  1752. pNewAcl - brand spanking new ACL with ACE for the SID and access mask
  1753. Return Values:
  1754. ERROR_SUCCESS if the ace was put in the sd
  1755. --*/
  1756. {
  1757. DWORD WinError = ERROR_SUCCESS;
  1758. BOOL fStatus;
  1759. ACL_SIZE_INFORMATION AclSizeInfo;
  1760. ACL_REVISION_INFORMATION AclRevInfo;
  1761. ACCESS_ALLOWED_ACE Dummy;
  1762. PVOID FirstAce = 0;
  1763. PACL pNewAcl = 0;
  1764. ULONG NewAclSize, NewAceCount, AceSize;
  1765. // Parameter check
  1766. if ( !pOldAcl || !pClientSid || !ppNewAcl ) {
  1767. return ERROR_INVALID_PARAMETER;
  1768. }
  1769. // Init the out parameter
  1770. *ppNewAcl = NULL;
  1771. memset( &AclSizeInfo, 0, sizeof( AclSizeInfo ) );
  1772. memset( &AclRevInfo, 0, sizeof( AclRevInfo ) );
  1773. //
  1774. // Get the old sd's values
  1775. //
  1776. fStatus = GetAclInformation( pOldAcl,
  1777. &AclSizeInfo,
  1778. sizeof( AclSizeInfo ),
  1779. AclSizeInformation );
  1780. if ( !fStatus )
  1781. {
  1782. WinError = GetLastError();
  1783. goto Cleanup;
  1784. }
  1785. fStatus = GetAclInformation( pOldAcl,
  1786. &AclRevInfo,
  1787. sizeof( AclRevInfo ),
  1788. AclRevisionInformation );
  1789. if ( !fStatus )
  1790. {
  1791. WinError = GetLastError();
  1792. goto Cleanup;
  1793. }
  1794. //
  1795. // Calculate the new sd's values
  1796. //
  1797. AceSize = sizeof( ACCESS_ALLOWED_ACE ) - sizeof( Dummy.SidStart )
  1798. + GetLengthSid( pClientSid );
  1799. NewAclSize = AceSize + AclSizeInfo.AclBytesInUse;
  1800. NewAceCount = AclSizeInfo.AceCount + 1;
  1801. //
  1802. // Init the new acl
  1803. //
  1804. pNewAcl = LocalAlloc( 0, NewAclSize );
  1805. if ( NULL == pNewAcl )
  1806. {
  1807. WinError = ERROR_NOT_ENOUGH_MEMORY;
  1808. goto Cleanup;
  1809. }
  1810. fStatus = InitializeAcl( pNewAcl,
  1811. NewAclSize,
  1812. AclRevInfo.AclRevision );
  1813. if ( !fStatus )
  1814. {
  1815. WinError = GetLastError();
  1816. goto Cleanup;
  1817. }
  1818. //
  1819. // Copy the old into the new
  1820. //
  1821. fStatus = GetAce( pOldAcl,
  1822. 0,
  1823. &FirstAce );
  1824. if ( !fStatus )
  1825. {
  1826. WinError = GetLastError();
  1827. goto Cleanup;
  1828. }
  1829. fStatus = AddAce( pNewAcl,
  1830. AclRevInfo.AclRevision,
  1831. 0,
  1832. FirstAce,
  1833. AclSizeInfo.AclBytesInUse - sizeof( ACL ) );
  1834. if ( !fStatus )
  1835. {
  1836. WinError = GetLastError();
  1837. goto Cleanup;
  1838. }
  1839. //
  1840. // Finally, add the new ace
  1841. //
  1842. fStatus = AddAccessAllowedAce( pNewAcl,
  1843. ACL_REVISION,
  1844. AccessMask,
  1845. pClientSid );
  1846. if ( !fStatus )
  1847. {
  1848. WinError = GetLastError();
  1849. goto Cleanup;
  1850. }
  1851. // Assign the out parameter
  1852. *ppNewAcl = pNewAcl;
  1853. //
  1854. // That's it fall through to cleanup
  1855. //
  1856. Cleanup:
  1857. if ( ERROR_SUCCESS != WinError )
  1858. {
  1859. if ( pNewAcl )
  1860. {
  1861. LocalFree( pNewAcl );
  1862. }
  1863. }
  1864. return WinError;
  1865. } // AddAceToAcl
  1866. DWORD
  1867. AddAceToSd(
  1868. IN PSECURITY_DESCRIPTOR pOldSd,
  1869. IN PSID pClientSid,
  1870. IN ACCESS_MASK AccessMask,
  1871. OUT PSECURITY_DESCRIPTOR * ppNewSd
  1872. )
  1873. /*++
  1874. Routine Description:
  1875. This routine creates a new sd with a new ace with pClientSid and
  1876. AccessMask. Stolen from \nt\ds\ds\src\ntdsa\dra\remove.c
  1877. Arguments:
  1878. pOldSd - existing SD in self relative format
  1879. pClientSid - SID to add to an ACE
  1880. AccessMask - 'nuff said
  1881. pNewAcl - pointer to new SD that contains new ACE
  1882. Return Values:
  1883. ERROR_SUCCESS if the ace was put in the sd
  1884. --*/
  1885. {
  1886. DWORD WinError = ERROR_SUCCESS;
  1887. BOOL fStatus;
  1888. PSECURITY_DESCRIPTOR pNewSelfRelativeSd = NULL;
  1889. DWORD NewSelfRelativeSdSize = 0;
  1890. PACL pNewDacl = NULL;
  1891. SECURITY_DESCRIPTOR AbsoluteSd;
  1892. PACL pDacl = NULL;
  1893. PACL pSacl = NULL;
  1894. PSID pGroup = NULL;
  1895. PSID pOwner = NULL;
  1896. DWORD AbsoluteSdSize = sizeof( SECURITY_DESCRIPTOR );
  1897. DWORD DaclSize = 0;
  1898. DWORD SaclSize = 0;
  1899. DWORD GroupSize = 0;
  1900. DWORD OwnerSize = 0;
  1901. // Parameter check
  1902. if ( !pOldSd || !pClientSid || !ppNewSd ) {
  1903. return ERROR_INVALID_PARAMETER;
  1904. }
  1905. // Init the out parameter
  1906. *ppNewSd = NULL;
  1907. RtlZeroMemory( &AbsoluteSd, AbsoluteSdSize );
  1908. //
  1909. // Make sd absolute
  1910. //
  1911. fStatus = MakeAbsoluteSD( pOldSd,
  1912. &AbsoluteSd,
  1913. &AbsoluteSdSize,
  1914. pDacl,
  1915. &DaclSize,
  1916. pSacl,
  1917. &SaclSize,
  1918. pOwner,
  1919. &OwnerSize,
  1920. pGroup,
  1921. &GroupSize );
  1922. if ( !fStatus && (ERROR_INSUFFICIENT_BUFFER == (WinError = GetLastError())))
  1923. {
  1924. WinError = ERROR_SUCCESS;
  1925. if ( 0 == DaclSize )
  1926. {
  1927. // No Dacl? We can't write to the dacl, then
  1928. WinError = ERROR_ACCESS_DENIED;
  1929. goto Cleanup;
  1930. }
  1931. if ( DaclSize > 0 ) pDacl = alloca( DaclSize );
  1932. if ( SaclSize > 0 ) pSacl = alloca( SaclSize );
  1933. if ( OwnerSize > 0 ) pOwner = alloca( OwnerSize );
  1934. if ( GroupSize > 0 ) pGroup = alloca( GroupSize );
  1935. if ( pDacl )
  1936. {
  1937. fStatus = MakeAbsoluteSD( pOldSd,
  1938. &AbsoluteSd,
  1939. &AbsoluteSdSize,
  1940. pDacl,
  1941. &DaclSize,
  1942. pSacl,
  1943. &SaclSize,
  1944. pOwner,
  1945. &OwnerSize,
  1946. pGroup,
  1947. &GroupSize );
  1948. if ( !fStatus )
  1949. {
  1950. WinError = GetLastError();
  1951. }
  1952. }
  1953. else
  1954. {
  1955. WinError = ERROR_NOT_ENOUGH_MEMORY;
  1956. }
  1957. }
  1958. if ( ERROR_SUCCESS != WinError )
  1959. {
  1960. goto Cleanup;
  1961. }
  1962. //
  1963. // Create a new dacl with the new ace
  1964. //
  1965. WinError = AddAceToAcl(pDacl,
  1966. pClientSid,
  1967. AccessMask,
  1968. &pNewDacl );
  1969. if ( ERROR_SUCCESS != WinError )
  1970. {
  1971. goto Cleanup;
  1972. }
  1973. //
  1974. // Set the dacl
  1975. //
  1976. fStatus = SetSecurityDescriptorDacl ( &AbsoluteSd,
  1977. TRUE, // dacl is present
  1978. pNewDacl,
  1979. FALSE ); // facl is not defaulted
  1980. if ( !fStatus )
  1981. {
  1982. WinError = GetLastError();
  1983. goto Cleanup;
  1984. }
  1985. //
  1986. // Make the new sd self relative
  1987. //
  1988. fStatus = MakeSelfRelativeSD( &AbsoluteSd,
  1989. pNewSelfRelativeSd,
  1990. &NewSelfRelativeSdSize );
  1991. if ( !fStatus && (ERROR_INSUFFICIENT_BUFFER == (WinError = GetLastError())))
  1992. {
  1993. WinError = ERROR_SUCCESS;
  1994. pNewSelfRelativeSd = LocalAlloc( 0, NewSelfRelativeSdSize );
  1995. if ( pNewSelfRelativeSd )
  1996. {
  1997. fStatus = MakeSelfRelativeSD( &AbsoluteSd,
  1998. pNewSelfRelativeSd,
  1999. &NewSelfRelativeSdSize );
  2000. if ( !fStatus )
  2001. {
  2002. WinError = GetLastError();
  2003. }
  2004. }
  2005. else
  2006. {
  2007. WinError = ERROR_NOT_ENOUGH_MEMORY;
  2008. }
  2009. }
  2010. //
  2011. // That's it fall through to cleanup
  2012. //
  2013. Cleanup:
  2014. if ( pNewDacl )
  2015. {
  2016. LocalFree( pNewDacl );
  2017. }
  2018. if ( ERROR_SUCCESS == WinError )
  2019. {
  2020. *ppNewSd = pNewSelfRelativeSd;
  2021. }
  2022. else
  2023. {
  2024. if ( pNewSelfRelativeSd )
  2025. {
  2026. LocalFree( pNewSelfRelativeSd );
  2027. }
  2028. }
  2029. return WinError;
  2030. } // AddAceToSd
  2031. DWORD
  2032. ClRtlAddClusterServiceAccountToWinsta0DACL(
  2033. VOID
  2034. )
  2035. /*++
  2036. Routine Description:
  2037. Modify the DACL on the interactive window station (Winsta0) and its
  2038. desktop such that resmon child processes (such as gennap resources) can
  2039. display on the desktop if so desired.
  2040. MEGA-IMPORTANT: this routine must be synchronized in a multi-threaded
  2041. environment, i.e., make sure that you're holding a lock of some sort
  2042. before calling it. It won't solve the race condition on setting the DACL
  2043. that exists between processes but it will make sure that the window
  2044. station APIs work correctly.
  2045. Arguments:
  2046. None
  2047. Return Value:
  2048. ERROR_SUCCESS if it worked...
  2049. --*/
  2050. {
  2051. DWORD status = ERROR_SUCCESS;
  2052. LPWSTR accountInfo = NULL;
  2053. PTOKEN_USER sidData = NULL;
  2054. HWINSTA winsta0 = NULL;
  2055. HWINSTA previousWinStation = NULL;
  2056. HDESK desktop = NULL;
  2057. SECURITY_INFORMATION requestedSI = DACL_SECURITY_INFORMATION;
  2058. BOOL success;
  2059. DWORD lengthRequired = 0;
  2060. DWORD lengthRequired2;
  2061. DWORD i;
  2062. PSECURITY_DESCRIPTOR winstaSD = NULL;
  2063. PSECURITY_DESCRIPTOR deskSD = NULL;
  2064. PSECURITY_DESCRIPTOR newSD = NULL;
  2065. BOOL hasDACL;
  2066. PACL dacl;
  2067. BOOL daclDefaulted;
  2068. //
  2069. // first see if we have the access we need by trying to open the
  2070. // interactive window station and its default desktop. if so, don't go any
  2071. // further and return success
  2072. //
  2073. winsta0 = OpenWindowStation( L"winsta0", FALSE, GENERIC_ALL );
  2074. if ( winsta0 != NULL ) {
  2075. previousWinStation = GetProcessWindowStation();
  2076. success = SetProcessWindowStation( winsta0 );
  2077. if ( success ) {
  2078. //
  2079. // if we have window station access, we should have desktop as well
  2080. //
  2081. desktop = OpenDesktop( L"default", 0, FALSE, GENERIC_ALL );
  2082. SetProcessWindowStation( previousWinStation );
  2083. previousWinStation = NULL;
  2084. if ( desktop != NULL ) {
  2085. //
  2086. // always switch the winstation back to the previous one
  2087. // before closing the desktop and winstation handles
  2088. //
  2089. CloseDesktop( desktop );
  2090. CloseWindowStation( winsta0 );
  2091. return ERROR_SUCCESS;
  2092. }
  2093. }
  2094. CloseWindowStation( winsta0 );
  2095. }
  2096. //
  2097. // get the SID of the account associated with this thread. This is the
  2098. // account that will be added to the DACL
  2099. //
  2100. sidData = ClRtlGetSidOfCallingThread();
  2101. if ( sidData == NULL ) {
  2102. status = GetLastError();
  2103. ClRtlLogPrint(LOG_CRITICAL, "[ClRtl] ClRtlGetSidOfCallingThread failed. Status %1!u!\n", status );
  2104. goto error_exit;
  2105. }
  2106. //
  2107. // open handles to Winsta0 and its default desktop. Temporarily switch to
  2108. // winsta0 to get its default desktop
  2109. //
  2110. winsta0 = OpenWindowStation( L"winsta0", TRUE, MAXIMUM_ALLOWED );
  2111. if ( winsta0 == NULL ) {
  2112. status = GetLastError();
  2113. ClRtlLogPrint(LOG_CRITICAL, "[ClRtl] OpenWindowStation failed. Status %1!u!\n", status );
  2114. goto error_exit;
  2115. }
  2116. previousWinStation = GetProcessWindowStation();
  2117. success = SetProcessWindowStation( winsta0 );
  2118. if ( !success ) {
  2119. status = GetLastError();
  2120. ClRtlLogPrint(LOG_CRITICAL, "[ClRtl] SetProcessWindowStation(winsta0) failed. Status %1!u!\n", status );
  2121. goto error_exit;
  2122. }
  2123. desktop = OpenDesktop( L"default", 0, TRUE, MAXIMUM_ALLOWED );
  2124. if ( desktop == NULL ) {
  2125. status = GetLastError();
  2126. ClRtlLogPrint(LOG_CRITICAL, "[ClRtl] OpenDesktop(default) failed. Status %1!u!\n", status );
  2127. goto error_exit;
  2128. }
  2129. //
  2130. // get the SD and its DACL for Winsta0
  2131. //
  2132. success = GetUserObjectSecurity(winsta0,
  2133. &requestedSI,
  2134. NULL,
  2135. 0,
  2136. &lengthRequired);
  2137. if ( !success ) {
  2138. status = GetLastError();
  2139. if ( status != ERROR_INSUFFICIENT_BUFFER ) {
  2140. ClRtlLogPrint(LOG_CRITICAL, "[ClRtl] GetUOSecurityLen(winsta0) failed. Status %1!u!\n", status );
  2141. goto error_exit;
  2142. }
  2143. }
  2144. //
  2145. // If UserObjectLen grew on us more than a few times,
  2146. // something is fishy, so we will fail the request
  2147. //
  2148. for(i = 0; i < 5; ++i) {
  2149. winstaSD = LocalAlloc( LMEM_FIXED, lengthRequired );
  2150. if ( winstaSD == NULL ) {
  2151. status = GetLastError();
  2152. goto error_exit;
  2153. }
  2154. success = GetUserObjectSecurity(winsta0,
  2155. &requestedSI,
  2156. winstaSD,
  2157. lengthRequired,
  2158. &lengthRequired2);
  2159. if ( success ) {
  2160. status = ERROR_SUCCESS;
  2161. break;
  2162. }
  2163. status = GetLastError();
  2164. if ( status != ERROR_INSUFFICIENT_BUFFER ) {
  2165. ClRtlLogPrint(LOG_CRITICAL, "[ClRtl] GetUOSecurity(winsta0) failed. Status %1!u!\n", status );
  2166. goto error_exit;
  2167. }
  2168. lengthRequired = lengthRequired2;
  2169. LocalFree(winstaSD);
  2170. winstaSD = NULL;
  2171. }
  2172. if ( status != ERROR_SUCCESS ) {
  2173. ClRtlLogPrint(LOG_CRITICAL, "[ClRtl] GetUOSecurity(winsta0) failed. Status %1!u!\n", status );
  2174. goto error_exit;
  2175. }
  2176. //
  2177. // build a new SD that includes our service account SID giving it complete
  2178. // access
  2179. //
  2180. status = AddAceToSd(winstaSD,
  2181. sidData->User.Sid,
  2182. GENERIC_ALL,
  2183. &newSD);
  2184. if ( status != ERROR_SUCCESS ) {
  2185. ClRtlLogPrint(LOG_CRITICAL, "[ClRtl] AddAceToSd(winsta) failed. Status %1!u!\n", status );
  2186. goto error_exit;
  2187. }
  2188. //
  2189. // set the new SD on Winsta0
  2190. //
  2191. success = SetUserObjectSecurity( winsta0, &requestedSI, newSD );
  2192. if ( !success ) {
  2193. status = GetLastError();
  2194. ClRtlLogPrint(LOG_CRITICAL, "[ClRtl] SetUOSecurity(winsta0) failed. Status %1!u!\n", status );
  2195. goto error_exit;
  2196. }
  2197. LocalFree( newSD );
  2198. newSD = NULL;
  2199. //
  2200. // repeat the process for the desktop SD and its DACL
  2201. //
  2202. success = GetUserObjectSecurity(desktop,
  2203. &requestedSI,
  2204. NULL,
  2205. 0,
  2206. &lengthRequired);
  2207. if ( !success ) {
  2208. status = GetLastError();
  2209. if ( status != ERROR_INSUFFICIENT_BUFFER ) {
  2210. ClRtlLogPrint(LOG_CRITICAL, "[ClRtl] GetUOSecurityLen(desktop) failed. Status %1!u!\n", status );
  2211. goto error_exit;
  2212. }
  2213. }
  2214. //
  2215. // If UserObjectLen grew on us more than a few times,
  2216. // something is fishy, so we will fail the request
  2217. //
  2218. for (i = 0; i < 5; ++i) {
  2219. deskSD = LocalAlloc( LMEM_FIXED, lengthRequired );
  2220. if ( deskSD == NULL ) {
  2221. status = GetLastError();
  2222. goto error_exit;
  2223. }
  2224. success = GetUserObjectSecurity(desktop,
  2225. &requestedSI,
  2226. deskSD,
  2227. lengthRequired,
  2228. &lengthRequired2);
  2229. if ( success ) {
  2230. status = ERROR_SUCCESS;
  2231. break;
  2232. }
  2233. status = GetLastError();
  2234. if ( status != ERROR_INSUFFICIENT_BUFFER ) {
  2235. ClRtlLogPrint(LOG_CRITICAL, "[ClRtl] GetUOSecurity(desktop) failed. Status %1!u!\n", status );
  2236. goto error_exit;
  2237. }
  2238. lengthRequired = lengthRequired2;
  2239. LocalFree(deskSD);
  2240. deskSD = NULL;
  2241. }
  2242. if ( status != ERROR_SUCCESS ) {
  2243. ClRtlLogPrint(LOG_CRITICAL, "[ClRtl] GetUOSecurity(desktop) failed. Status %1!u!\n", status );
  2244. goto error_exit;
  2245. }
  2246. status = AddAceToSd(deskSD,
  2247. sidData->User.Sid,
  2248. GENERIC_ALL,
  2249. &newSD);
  2250. if ( status != ERROR_SUCCESS ) {
  2251. ClRtlLogPrint(LOG_CRITICAL, "[ClRtl] AddAceToSd(desktop) failed. Status %1!u!\n", status );
  2252. goto error_exit;
  2253. }
  2254. success = SetUserObjectSecurity( desktop, &requestedSI, newSD );
  2255. if ( !success ) {
  2256. status = GetLastError();
  2257. ClRtlLogPrint(LOG_CRITICAL, "[ClRtl] SetUserObjectSecurity(desktop) failed. Status %1!u!\n", status );
  2258. }
  2259. error_exit:
  2260. FREE_IF_NOT_NULL( newSD, LocalFree );
  2261. FREE_IF_NOT_NULL( deskSD, LocalFree );
  2262. FREE_IF_NOT_NULL( winstaSD, LocalFree );
  2263. //
  2264. // always switch the winstation back to the previous one before closing
  2265. // the desktop and winstation handles
  2266. //
  2267. if ( previousWinStation != NULL ) {
  2268. success = SetProcessWindowStation( previousWinStation );
  2269. if ( !success ) {
  2270. status = GetLastError();
  2271. ClRtlLogPrint(LOG_CRITICAL, "[ClRtl] SetWindowsStation(previous) failed. Status %1!u!\n", status );
  2272. }
  2273. }
  2274. FREE_IF_NOT_NULL( desktop, CloseDesktop );
  2275. FREE_IF_NOT_NULL( winsta0, CloseWindowStation );
  2276. FREE_IF_NOT_NULL( sidData, LocalFree );
  2277. FREE_IF_NOT_NULL( accountInfo, LocalFree );
  2278. return status;
  2279. }