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.

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