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.

1723 lines
41 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. security.cpp
  5. Abstract:
  6. Initializes security descriptor object for STI services
  7. access validation
  8. Author:
  9. Vlad Sadovsky (vlads) 09-28-97
  10. Environment:
  11. User Mode - Win32
  12. Revision History:
  13. 28-Sep-1997 VladS created
  14. --*/
  15. //
  16. // Include Headers
  17. //
  18. #include "precomp.h"
  19. #include "stiexe.h"
  20. #include <stisvc.h>
  21. #ifdef DEBUG
  22. #define STATIC
  23. #else
  24. #define STATIC static
  25. #endif
  26. #ifdef WINNT
  27. //
  28. // Globals
  29. //
  30. //
  31. // NT well-known SIDs
  32. //
  33. PSID psidNull = NULL; // No members SID
  34. PSID psidWorld = NULL; // All users SID
  35. PSID psidLocal = NULL; // NT local users SID
  36. PSID psidLocalSystem= NULL; // NT system processes SID
  37. PSID psidNetwork = NULL; // NT remote users SID
  38. PSID psidAdmins = NULL;
  39. PSID psidServerOps = NULL;
  40. PSID psidPowerUsers = NULL;
  41. PSID psidGuestUser = NULL;
  42. PSID psidProcessUser= NULL;
  43. PSID psidBuiltinDomain = NULL; // Domain Id of the Builtin Domain
  44. //
  45. // Well Known Aliases.
  46. //
  47. // These are aliases that are relative to the built-in domain.
  48. //
  49. PSID psidLocalAdmin = NULL; // NT local admins
  50. PSID psidAliasAdmins = NULL;
  51. PSID psidAliasUsers = NULL;
  52. PSID psidAliasGuests = NULL;
  53. PSID psidAliasPowerUsers = NULL;
  54. PSID psidAliasAccountOps = NULL;
  55. PSID psidAliasSystemOps = NULL;
  56. PSID psidAliasPrintOps = NULL;
  57. PSID psidAliasBackupOps = NULL;
  58. //
  59. // List of well-known SID data structures we use to initialize globals
  60. //
  61. struct _SID_DATA {
  62. PSID *Sid;
  63. SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
  64. ULONG SubAuthority;
  65. } SidData[] = {
  66. {&psidNull, SECURITY_NULL_SID_AUTHORITY, SECURITY_NULL_RID},
  67. {&psidWorld, SECURITY_WORLD_SID_AUTHORITY, SECURITY_WORLD_RID},
  68. {&psidLocal, SECURITY_LOCAL_SID_AUTHORITY, SECURITY_LOCAL_RID},
  69. {&psidNetwork, SECURITY_NT_AUTHORITY, SECURITY_NETWORK_RID},
  70. {&psidLocalSystem, SECURITY_NT_AUTHORITY, SECURITY_LOCAL_SYSTEM_RID},
  71. {&psidBuiltinDomain, SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID}
  72. };
  73. #define NUM_SIDS (sizeof(SidData) / sizeof(SidData[0]))
  74. STATIC
  75. struct _BUILTIN_DOMAIN_SID_DATA {
  76. PSID *Sid;
  77. ULONG RelativeId;
  78. } psidBuiltinDomainData[] = {
  79. { &psidLocalAdmin, DOMAIN_ALIAS_RID_ADMINS},
  80. { &psidAliasAdmins, DOMAIN_ALIAS_RID_ADMINS },
  81. { &psidAliasUsers, DOMAIN_ALIAS_RID_USERS },
  82. { &psidAliasGuests, DOMAIN_ALIAS_RID_GUESTS },
  83. { &psidAliasPowerUsers, DOMAIN_ALIAS_RID_POWER_USERS },
  84. { &psidAliasAccountOps, DOMAIN_ALIAS_RID_ACCOUNT_OPS },
  85. { &psidAliasSystemOps, DOMAIN_ALIAS_RID_SYSTEM_OPS },
  86. { &psidAliasPrintOps, DOMAIN_ALIAS_RID_PRINT_OPS },
  87. { &psidAliasBackupOps, DOMAIN_ALIAS_RID_BACKUP_OPS }
  88. };
  89. #define NUM_DOMAIN_SIDS (sizeof(psidBuiltinDomainData) / sizeof(psidBuiltinDomainData[0]))
  90. //
  91. // List of ACEs definitions to initialize our security descriptor
  92. //
  93. typedef struct {
  94. BYTE AceType;
  95. BYTE InheritFlags;
  96. BYTE AceFlags;
  97. ACCESS_MASK Mask;
  98. PSID *Sid;
  99. } ACE_DATA, *PACE_DATA;
  100. STATIC
  101. ACE_DATA AcesData[] =
  102. {
  103. {
  104. ACCESS_ALLOWED_ACE_TYPE,
  105. 0,
  106. 0,
  107. STI_ALL_ACCESS,
  108. &psidLocalSystem
  109. },
  110. {
  111. ACCESS_ALLOWED_ACE_TYPE,
  112. 0,
  113. 0,
  114. STI_ALL_ACCESS,
  115. &psidAliasAdmins
  116. },
  117. {
  118. ACCESS_ALLOWED_ACE_TYPE,
  119. 0,
  120. 0,
  121. STI_ALL_ACCESS,
  122. &psidAliasSystemOps
  123. },
  124. {
  125. ACCESS_ALLOWED_ACE_TYPE,
  126. 0,
  127. 0,
  128. STI_ALL_ACCESS,
  129. &psidAliasPowerUsers
  130. },
  131. {
  132. ACCESS_ALLOWED_ACE_TYPE,
  133. 0,
  134. 0,
  135. STI_ALL_ACCESS, // BUGBUG only need to syncronize
  136. // STI_GENERIC_EXECUTE | SYNCHRONIZE,
  137. &psidWorld
  138. },
  139. {
  140. ACCESS_ALLOWED_ACE_TYPE,
  141. 0,
  142. 0,
  143. STI_ALL_ACCESS, // BUGBUG only need to syncronize
  144. &psidLocal
  145. },
  146. // {
  147. // ACCESS_ALLOWED_ACE_TYPE,
  148. // 0,
  149. // 0,
  150. // STI_GENERIC_EXECUTE,
  151. // &psidProcessUser
  152. // },
  153. };
  154. #define NUM_ACES (sizeof(AcesData) / sizeof(AcesData[0]))
  155. //
  156. // Local variables and types definitions
  157. //
  158. //
  159. // The API security object. Client access STI Server APIs
  160. // are validated against this object.
  161. //
  162. PSECURITY_DESCRIPTOR sdApiObject;
  163. //
  164. // This table maps generic rights (like GENERIC_READ) to
  165. // specific rights (like STI_QUERY_SECURITY).
  166. //
  167. GENERIC_MAPPING ApiObjectMapping = {
  168. STI_GENERIC_READ, // generic read
  169. STI_GENERIC_WRITE, // generic write
  170. STI_GENERIC_EXECUTE, // generic execute
  171. STI_ALL_ACCESS // generic all
  172. };
  173. //
  174. // Private prototypes.
  175. //
  176. DWORD
  177. CreateWellKnownSids(
  178. VOID
  179. );
  180. VOID
  181. FreeWellKnownSids(
  182. VOID
  183. );
  184. DWORD
  185. CreateSecurityObject(
  186. IN PACE_DATA AceData,
  187. IN ULONG AceCount,
  188. IN PSID psidOwner,
  189. IN PSID psidGroup,
  190. IN PGENERIC_MAPPING GenericMapping,
  191. OUT PSECURITY_DESCRIPTOR *NewDescriptor
  192. );
  193. DWORD
  194. DeleteSecurityObject(
  195. IN PSECURITY_DESCRIPTOR *Descriptor
  196. );
  197. //
  198. // Code
  199. //
  200. DWORD
  201. AllocateAndInitializeSid(
  202. OUT PSID *Sid,
  203. IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
  204. IN ULONG SubAuthorityCount
  205. )
  206. /*++
  207. Routine Description:
  208. This function allocates memory for a SID and initializes it.
  209. Arguments:
  210. None.
  211. Return Value:
  212. WIN32 Error Code.
  213. --*/
  214. {
  215. *Sid = (PSID)
  216. LocalAlloc(LPTR,
  217. GetSidLengthRequired( (BYTE)SubAuthorityCount) );
  218. if (*Sid == NULL) {
  219. return ERROR_NOT_ENOUGH_MEMORY;
  220. }
  221. InitializeSid( *Sid, IdentifierAuthority, (BYTE)SubAuthorityCount );
  222. return( NOERROR );
  223. }
  224. DWORD
  225. DomainIdToSid(
  226. IN PSID DomainId,
  227. IN ULONG RelativeId,
  228. OUT PSID *Sid
  229. )
  230. /*++
  231. Routine Description:
  232. Given a domain Id and a relative ID create a SID
  233. Arguments:
  234. DomainId - The template SID to use.
  235. RelativeId - The relative Id to append to the DomainId.
  236. Sid - Returns a pointer to an allocated buffer containing the resultant Sid.
  237. Return Value:
  238. WIN32 Error Code.
  239. --*/
  240. {
  241. DWORD dwError;
  242. BYTE DomainIdSubAuthorityCount; // Number of sub authorities in domain ID
  243. UINT SidLength; // Length of newly allocated SID
  244. //
  245. // Allocate a Sid which has one more sub-authority than the domain ID.
  246. //
  247. DomainIdSubAuthorityCount = *(GetSidSubAuthorityCount( DomainId ));
  248. SidLength = GetSidLengthRequired( (BYTE)(DomainIdSubAuthorityCount+1) );
  249. if ((*Sid = (PSID) LocalAlloc(LPTR, SidLength )) == NULL ) {
  250. return ERROR_NOT_ENOUGH_MEMORY;
  251. }
  252. //
  253. // Initialize the new SID to have the same inital value as the
  254. // domain ID.
  255. //
  256. if( CopySid(SidLength, *Sid, DomainId) == FALSE ) {
  257. dwError = GetLastError();
  258. LocalFree( *Sid );
  259. return( dwError );
  260. }
  261. //
  262. // Adjust the sub-authority count and
  263. // add the relative Id unique to the newly allocated SID
  264. //
  265. (*(GetSidSubAuthorityCount( *Sid ))) ++;
  266. *GetSidSubAuthority( *Sid, DomainIdSubAuthorityCount ) = RelativeId;
  267. return( NOERROR );
  268. }
  269. DWORD
  270. WINAPI
  271. CreateWellKnownSids(
  272. VOID
  273. )
  274. /*++
  275. Routine Description:
  276. This function creates some well-known SIDs and store them in global
  277. variables.
  278. Arguments:
  279. none.
  280. Return Value:
  281. WIN32 Error Code.
  282. --*/
  283. {
  284. DWORD dwError;
  285. DWORD i;
  286. //
  287. // Allocate and initialize well-known SIDs which aren't relative to
  288. // the Domain Id.
  289. //
  290. for (i = 0; i< NUM_SIDS ; i++) {
  291. dwError = AllocateAndInitializeSid(
  292. SidData[i].Sid,
  293. &(SidData[i].IdentifierAuthority),
  294. 1);
  295. if ( dwError != NOERROR ) {
  296. return dwError;
  297. }
  298. *(GetSidSubAuthority(*(SidData[i].Sid), 0)) = SidData[i].SubAuthority;
  299. }
  300. //
  301. // Build each SID which is relative to the Builtin Domain Id.
  302. //
  303. for ( i = 0;i < NUM_DOMAIN_SIDS; i++) {
  304. dwError = DomainIdToSid(
  305. psidBuiltinDomain,
  306. psidBuiltinDomainData[i].RelativeId,
  307. psidBuiltinDomainData[i].Sid );
  308. if ( dwError != NOERROR ) {
  309. return dwError;
  310. }
  311. }
  312. return NOERROR;
  313. } // CreateWellKnownSids
  314. VOID
  315. WINAPI
  316. FreeWellKnownSids(
  317. VOID
  318. )
  319. /*++
  320. Routine Description:
  321. This function frees up the dynamic memory consumed by the well-known
  322. SIDs.
  323. Arguments:
  324. none.
  325. Return Value:
  326. none
  327. --*/
  328. {
  329. DWORD i;
  330. //
  331. // free up memory allocated for well-known SIDs
  332. //
  333. for (i = 0; i < NUM_SIDS ; i++) {
  334. if( *SidData[i].Sid != NULL ) {
  335. LocalFree( *SidData[i].Sid );
  336. *SidData[i].Sid = NULL;
  337. }
  338. }
  339. //
  340. // free up memory allocated for Builtin Domain SIDs
  341. //
  342. for (i = 0; i < NUM_DOMAIN_SIDS; i++) {
  343. if( *psidBuiltinDomainData[i].Sid != NULL ) {
  344. LocalFree( *psidBuiltinDomainData[i].Sid );
  345. *psidBuiltinDomainData[i].Sid = NULL;
  346. }
  347. }
  348. } //FreeWellKnownSids
  349. DWORD
  350. WINAPI
  351. InitializeAllowedAce(
  352. IN PACCESS_ALLOWED_ACE AllowedAce,
  353. IN USHORT AceSize,
  354. IN BYTE InheritFlags,
  355. IN BYTE AceFlags,
  356. IN ACCESS_MASK Mask,
  357. IN PSID AllowedSid
  358. )
  359. /*++
  360. Routine Description:
  361. This function assigns the specified ACE values into an allowed type ACE.
  362. Arguments:
  363. AllowedAce - Supplies a pointer to the ACE that is initialized.
  364. AceSize - Supplies the size of the ACE in bytes.
  365. InheritFlags - Supplies ACE inherit flags.
  366. AceFlags - Supplies ACE type specific control flags.
  367. Mask - Supplies the allowed access masks.
  368. AllowedSid - Supplies the pointer to the SID of user/group which is allowed
  369. the specified access.
  370. Return Value:
  371. WIN32 Error Code.
  372. --*/
  373. {
  374. AllowedAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
  375. AllowedAce->Header.AceSize = AceSize;
  376. AllowedAce->Header.AceFlags = AceFlags | InheritFlags;
  377. AllowedAce->Mask = Mask;
  378. if( CopySid(
  379. GetLengthSid(AllowedSid), // should be valid SID ??
  380. &(AllowedAce->SidStart),
  381. AllowedSid ) == FALSE ) {
  382. return( GetLastError() );
  383. }
  384. return( NOERROR );
  385. }
  386. DWORD
  387. WINAPI
  388. InitializeDeniedAce(
  389. IN PACCESS_DENIED_ACE DeniedAce,
  390. IN USHORT AceSize,
  391. IN BYTE InheritFlags,
  392. IN BYTE AceFlags,
  393. IN ACCESS_MASK Mask,
  394. IN PSID DeniedSid
  395. )
  396. /*++
  397. Routine Description:
  398. This function assigns the specified ACE values into a denied type ACE.
  399. Arguments:
  400. DeniedAce - Supplies a pointer to the ACE that is initialized.
  401. AceSize - Supplies the size of the ACE in bytes.
  402. InheritFlags - Supplies ACE inherit flags.
  403. AceFlags - Supplies ACE type specific control flags.
  404. Mask - Supplies the denied access masks.
  405. AllowedSid - Supplies the pointer to the SID of user/group which is denied
  406. the specified access.
  407. Return Value:
  408. WIN32 Error Code.
  409. --*/
  410. {
  411. DeniedAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
  412. DeniedAce->Header.AceSize = AceSize;
  413. DeniedAce->Header.AceFlags = AceFlags | InheritFlags;
  414. DeniedAce->Mask = Mask;
  415. if( CopySid(
  416. GetLengthSid(DeniedSid), // should be valid SID ??
  417. &(DeniedAce->SidStart),
  418. DeniedSid ) == FALSE ) {
  419. return( GetLastError() );
  420. }
  421. return( NOERROR );
  422. }
  423. DWORD
  424. WINAPI
  425. InitializeAuditAce(
  426. IN PACCESS_ALLOWED_ACE AuditAce,
  427. IN USHORT AceSize,
  428. IN BYTE InheritFlags,
  429. IN BYTE AceFlags,
  430. IN ACCESS_MASK Mask,
  431. IN PSID AuditSid
  432. )
  433. /*++
  434. Routine Description:
  435. This function assigns the specified ACE values into an audit type ACE.
  436. Arguments:
  437. AuditAce - Supplies a pointer to the ACE that is initialized.
  438. AceSize - Supplies the size of the ACE in bytes.
  439. InheritFlags - Supplies ACE inherit flags.
  440. AceFlags - Supplies ACE type specific control flags.
  441. Mask - Supplies the allowed access masks.
  442. AuditSid - Supplies the pointer to the SID of user/group which is to be
  443. audited.
  444. Return Value:
  445. WIN32 Error Code.
  446. --*/
  447. {
  448. AuditAce->Header.AceType = SYSTEM_AUDIT_ACE_TYPE;
  449. AuditAce->Header.AceSize = AceSize;
  450. AuditAce->Header.AceFlags = AceFlags | InheritFlags;
  451. AuditAce->Mask = Mask;
  452. if( CopySid(
  453. GetLengthSid(AuditSid),
  454. &(AuditAce->SidStart),
  455. AuditSid ) == FALSE ) {
  456. return( GetLastError() );
  457. }
  458. return( NOERROR );
  459. }
  460. DWORD
  461. WINAPI
  462. CreateSecurityDescriptorHelper(
  463. IN PACE_DATA AceData,
  464. IN ULONG AceCount,
  465. IN PSID psidOwner OPTIONAL,
  466. IN PSID psidGroup OPTIONAL,
  467. OUT PSECURITY_DESCRIPTOR *NewDescriptor
  468. )
  469. /*++
  470. Routine Description:
  471. This function creates an absolute security descriptor containing
  472. the supplied ACE information.
  473. A sample usage of this function:
  474. //
  475. // Order matters! These ACEs are inserted into the DACL in the
  476. // following order. Security access is granted or denied based on
  477. // the order of the ACEs in the DACL.
  478. //
  479. ACE_DATA AceData[4] = {
  480. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  481. GENERIC_ALL, &psidLocalAdmin},
  482. {ACCESS_DENIED_ACE_TYPE, 0, 0,
  483. GENERIC_ALL, &psidNetwork},
  484. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  485. WKSTA_CONFIG_GUEST_INFO_GET |
  486. WKSTA_CONFIG_USER_INFO_GET, &DomainUsersSid},
  487. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  488. WKSTA_CONFIG_GUEST_INFO_GET, &DomainGuestsSid}
  489. };
  490. return CreateSecurityDescriptor(
  491. AceData,
  492. 4,
  493. psidNull,
  494. psidLocalSystem,
  495. &ConfigurationInfoSd
  496. );
  497. Arguments:
  498. AceData - Supplies the structure of information that describes the DACL.
  499. AceCount - Supplies the number of entries in AceData structure.
  500. psidOwner - Supplies the pointer to the SID of the security descriptor
  501. owner. If not specified, a security descriptor with no owner
  502. will be created.
  503. psidGroup - Supplies the pointer to the SID of the security descriptor
  504. primary group. If not specified, a security descriptor with no primary
  505. group will be created.
  506. NewDescriptor - Returns a pointer to the absolute secutiry descriptor
  507. allocated using MemoryAllocate.
  508. Return Value:
  509. WIN32 Error Code.
  510. --*/
  511. {
  512. DWORD dwError = 0;
  513. DWORD i;
  514. //
  515. // Pointer to memory dynamically allocated by this routine to hold
  516. // the absolute security descriptor, the DACL, the SACL, and all the ACEs.
  517. //
  518. // +---------------------------------------------------------------+
  519. // | Security Descriptor |
  520. // +-------------------------------+-------+---------------+-------+
  521. // | DACL | ACE 1 | . . . | ACE n |
  522. // +-------------------------------+-------+---------------+-------+
  523. // | SACL | ACE 1 | . . . | ACE n |
  524. // +-------------------------------+-------+---------------+-------+
  525. //
  526. PSECURITY_DESCRIPTOR AbsoluteSd = NULL;
  527. PACL Dacl = NULL; // Pointer to the DACL portion of above buffer
  528. PACL Sacl = NULL; // Pointer to the SACL portion of above buffer
  529. DWORD DaclSize = sizeof(ACL);
  530. DWORD SaclSize = sizeof(ACL);
  531. DWORD MaxAceSize = 0;
  532. PVOID MaxAce = NULL;
  533. LPBYTE CurrentAvailable;
  534. DWORD Size;
  535. // ASSERT( AceCount > 0 );
  536. //
  537. // Compute the total size of the DACL and SACL ACEs and the maximum
  538. // size of any ACE.
  539. //
  540. for (i = 0; i < AceCount; i++) {
  541. DWORD AceSize;
  542. AceSize = GetLengthSid( *(AceData[i].Sid) );
  543. switch (AceData[i].AceType) {
  544. case ACCESS_ALLOWED_ACE_TYPE:
  545. AceSize += sizeof(ACCESS_ALLOWED_ACE);
  546. DaclSize += AceSize;
  547. break;
  548. case ACCESS_DENIED_ACE_TYPE:
  549. AceSize += sizeof(ACCESS_DENIED_ACE);
  550. DaclSize += AceSize;
  551. break;
  552. case SYSTEM_AUDIT_ACE_TYPE:
  553. AceSize += sizeof(SYSTEM_AUDIT_ACE);
  554. SaclSize += AceSize;
  555. break;
  556. default:
  557. return( ERROR_INVALID_PARAMETER );
  558. }
  559. MaxAceSize = max( MaxAceSize, AceSize );
  560. }
  561. //
  562. // Allocate a chunk of memory large enough the security descriptor
  563. // the DACL, the SACL and all ACEs.
  564. //
  565. // A security descriptor is of opaque data type but
  566. // SECURITY_DESCRIPTOR_MIN_LENGTH is the right size.
  567. //
  568. __try {
  569. Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
  570. if ( DaclSize != sizeof(ACL) ) {
  571. Size += DaclSize;
  572. }
  573. if ( SaclSize != sizeof(ACL) ) {
  574. Size += SaclSize;
  575. }
  576. if ((AbsoluteSd = LocalAlloc(LPTR, Size )) == NULL) {
  577. dwError = ERROR_NOT_ENOUGH_MEMORY;
  578. __leave;
  579. }
  580. //
  581. // Initialize the Dacl and Sacl
  582. //
  583. CurrentAvailable = (LPBYTE)AbsoluteSd + SECURITY_DESCRIPTOR_MIN_LENGTH;
  584. if ( DaclSize != sizeof(ACL) ) {
  585. Dacl = (PACL)CurrentAvailable;
  586. CurrentAvailable += DaclSize;
  587. if( InitializeAcl( Dacl, DaclSize, ACL_REVISION ) == FALSE ) {
  588. dwError = GetLastError();
  589. __leave;
  590. }
  591. }
  592. if ( SaclSize != sizeof(ACL) ) {
  593. Sacl = (PACL)CurrentAvailable;
  594. CurrentAvailable += SaclSize;
  595. if( InitializeAcl( Sacl, SaclSize, ACL_REVISION ) == FALSE ) {
  596. dwError = GetLastError();
  597. __leave;
  598. }
  599. }
  600. //
  601. // Allocate a temporary buffer big enough for the biggest ACE.
  602. //
  603. if ((MaxAce = LocalAlloc(LPTR, MaxAceSize )) == NULL ) {
  604. dwError = ERROR_NOT_ENOUGH_MEMORY;
  605. __leave;
  606. }
  607. //
  608. // Initialize each ACE, and append it into the end of the DACL or SACL.
  609. //
  610. for (i = 0; i < AceCount; i++) {
  611. DWORD AceSize;
  612. PACL CurrentAcl = NULL;
  613. AceSize = GetLengthSid( *(AceData[i].Sid) );
  614. switch (AceData[i].AceType) {
  615. case ACCESS_ALLOWED_ACE_TYPE:
  616. AceSize += sizeof(ACCESS_ALLOWED_ACE);
  617. CurrentAcl = Dacl;
  618. dwError = InitializeAllowedAce(
  619. (PACCESS_ALLOWED_ACE)MaxAce,
  620. (USHORT) AceSize,
  621. AceData[i].InheritFlags,
  622. AceData[i].AceFlags,
  623. AceData[i].Mask,
  624. *(AceData[i].Sid) );
  625. break;
  626. case ACCESS_DENIED_ACE_TYPE:
  627. AceSize += sizeof(ACCESS_DENIED_ACE);
  628. CurrentAcl = Dacl;
  629. dwError = InitializeDeniedAce(
  630. (PACCESS_DENIED_ACE)MaxAce,
  631. (USHORT) AceSize,
  632. AceData[i].InheritFlags,
  633. AceData[i].AceFlags,
  634. AceData[i].Mask,
  635. *(AceData[i].Sid) );
  636. break;
  637. case SYSTEM_AUDIT_ACE_TYPE:
  638. AceSize += sizeof(SYSTEM_AUDIT_ACE);
  639. CurrentAcl = Sacl;
  640. dwError = InitializeAuditAce(
  641. (PACCESS_ALLOWED_ACE)MaxAce,
  642. (USHORT) AceSize,
  643. AceData[i].InheritFlags,
  644. AceData[i].AceFlags,
  645. AceData[i].Mask,
  646. *(AceData[i].Sid) );
  647. break;
  648. }
  649. if ( dwError != NOERROR ) {
  650. __leave;
  651. }
  652. //
  653. // Append the initialized ACE to the end of DACL or SACL
  654. //
  655. if ( AddAce(
  656. CurrentAcl,
  657. ACL_REVISION,
  658. MAXDWORD,
  659. MaxAce,
  660. AceSize ) == FALSE ) {
  661. dwError = GetLastError();
  662. __leave;
  663. }
  664. }
  665. //
  666. // Create the security descriptor with absolute pointers to SIDs
  667. // and ACLs.
  668. //
  669. // Owner = psidOwner
  670. // Group = psidGroup
  671. // Dacl = Dacl
  672. // Sacl = Sacl
  673. //
  674. if ( InitializeSecurityDescriptor(
  675. AbsoluteSd,
  676. SECURITY_DESCRIPTOR_REVISION ) == FALSE ) {
  677. dwError = GetLastError();
  678. __leave;
  679. }
  680. if ( SetSecurityDescriptorOwner(
  681. AbsoluteSd,
  682. psidOwner,
  683. FALSE ) == FALSE ) {
  684. dwError = GetLastError();
  685. __leave;
  686. }
  687. if ( SetSecurityDescriptorGroup(
  688. AbsoluteSd,
  689. psidGroup,
  690. FALSE ) == FALSE ) {
  691. dwError = GetLastError();
  692. __leave;
  693. }
  694. if ( SetSecurityDescriptorDacl(
  695. AbsoluteSd,
  696. TRUE,
  697. Dacl,
  698. FALSE ) == FALSE ) {
  699. dwError = GetLastError();
  700. __leave;
  701. }
  702. if ( SetSecurityDescriptorSacl(
  703. AbsoluteSd,
  704. FALSE,
  705. Sacl,
  706. FALSE ) == FALSE ) {
  707. dwError = GetLastError();
  708. __leave;
  709. }
  710. //
  711. // Done
  712. //
  713. *NewDescriptor = AbsoluteSd;
  714. AbsoluteSd = NULL;
  715. dwError = NOERROR;
  716. }
  717. __finally {
  718. // Cleanup
  719. if( AbsoluteSd != NULL ) {
  720. //
  721. // delete the partially made SD if we are not completely
  722. // successful
  723. //
  724. LocalFree( AbsoluteSd );
  725. AbsoluteSd = NULL;
  726. }
  727. //
  728. // Delete the temporary ACE
  729. //
  730. if ( MaxAce != NULL ) {
  731. LocalFree( MaxAce );
  732. MaxAce = NULL;
  733. }
  734. }
  735. return( dwError );
  736. }
  737. DWORD
  738. WINAPI
  739. CreateSecurityObject(
  740. IN PACE_DATA AceData,
  741. IN ULONG AceCount,
  742. IN PSID psidOwner,
  743. IN PSID psidGroup,
  744. IN PGENERIC_MAPPING GenericMapping,
  745. OUT PSECURITY_DESCRIPTOR *NewDescriptor
  746. )
  747. /*++
  748. Routine Description:
  749. This function creates the DACL for the security descriptor based on
  750. on the ACE information specified, and creates the security descriptor
  751. which becomes the user-mode security object.
  752. Arguments:
  753. AceData - Supplies the structure of information that describes the DACL.
  754. AceCount - Supplies the number of entries in AceData structure.
  755. psidOwner - Supplies the pointer to the SID of the security descriptor
  756. owner.
  757. psidGroup - Supplies the pointer to the SID of the security descriptor
  758. primary group.
  759. GenericMapping - Supplies the pointer to a generic mapping array denoting
  760. the mapping between each generic right to specific rights.
  761. NewDescriptor - Returns a pointer to the self-relative security descriptor
  762. which represents the user-mode object.
  763. Return Value:
  764. WIN32 Error Code.
  765. NOTE : the security object created by calling this function may be
  766. freed up by calling DeleteSecurityObject().
  767. --*/
  768. {
  769. DWORD dwError;
  770. PSECURITY_DESCRIPTOR AbsoluteSd = NULL;
  771. HANDLE hTokenHandle = NULL;
  772. __try {
  773. dwError = CreateSecurityDescriptorHelper(
  774. AceData,
  775. AceCount,
  776. psidOwner,
  777. psidGroup,
  778. &AbsoluteSd
  779. );
  780. if( dwError != NOERROR ) {
  781. __leave;
  782. }
  783. if( OpenProcessToken(
  784. GetCurrentProcess(),
  785. TOKEN_QUERY,
  786. &hTokenHandle ) == FALSE ) {
  787. hTokenHandle = INVALID_HANDLE_VALUE;
  788. dwError = GetLastError();
  789. __leave;
  790. }
  791. //
  792. // Create the security object (a user-mode object is really a pseudo-
  793. // object represented by a security descriptor that have relative
  794. // pointers to SIDs and ACLs). This routine allocates the memory to
  795. // hold the relative security descriptor so the memory allocated for the
  796. // DACL, ACEs, and the absolute descriptor can be freed.
  797. //
  798. if( CreatePrivateObjectSecurity(
  799. NULL, // Parent descriptor
  800. AbsoluteSd, // Creator descriptor
  801. NewDescriptor, // Pointer to new descriptor
  802. FALSE, // Is directory object
  803. hTokenHandle, // Token
  804. GenericMapping // Generic mapping
  805. ) == FALSE ) {
  806. dwError = GetLastError();
  807. __leave;
  808. }
  809. dwError = NOERROR;
  810. }
  811. __finally {
  812. //
  813. // Finally clean up used resources
  814. if( hTokenHandle != NULL ) {
  815. CloseHandle( hTokenHandle );
  816. }
  817. //
  818. // Free dynamic memory before returning
  819. //
  820. if( AbsoluteSd != NULL ) {
  821. LocalFree( AbsoluteSd );
  822. }
  823. }
  824. return( dwError );
  825. }
  826. DWORD
  827. WINAPI
  828. DeleteSecurityObject(
  829. IN PSECURITY_DESCRIPTOR *Descriptor
  830. )
  831. /*++
  832. Routine Description:
  833. This function deletes a security object that was created by calling
  834. CreateSecurityObject() function.
  835. Arguments:
  836. Descriptor - Returns a pointer to the self-relative security descriptor
  837. which represents the user-mode object.
  838. Return Value:
  839. WIN32 Error Code.
  840. --*/
  841. {
  842. if( DestroyPrivateObjectSecurity( Descriptor ) == FALSE ) {
  843. return( GetLastError() );
  844. }
  845. return( NOERROR );
  846. }
  847. DWORD
  848. WINAPI
  849. StiAccessCheckAndAuditW(
  850. IN LPCWSTR SubsystemName,
  851. IN LPWSTR ObjectTypeName,
  852. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  853. IN ACCESS_MASK DesiredAccess,
  854. IN PGENERIC_MAPPING GenericMapping
  855. )
  856. /*++
  857. Routine Description:
  858. This function impersonates the caller so that it can perform access
  859. validation using NtAccessCheckAndAuditAlarm; and reverts back to
  860. itself before returning.
  861. Arguments:
  862. SubsystemName - Supplies a name string identifying the subsystem
  863. calling this routine.
  864. ObjectTypeName - Supplies the name of the type of the object being
  865. accessed.
  866. SecurityDescriptor - A pointer to the Security Descriptor against which
  867. acccess is to be checked.
  868. DesiredAccess - Supplies desired acccess mask. This mask must have been
  869. previously mapped to contain no generic accesses.
  870. GenericMapping - Supplies a pointer to the generic mapping associated
  871. with this object type.
  872. Return Value:
  873. WIN32 Error - NOERROR or reason for failure.
  874. --*/
  875. {
  876. DWORD dwError;
  877. ACCESS_MASK GrantedAccess;
  878. BOOL GenerateOnClose;
  879. BOOL AccessStatus;
  880. dwError = RpcImpersonateClient( NULL ) ;
  881. if( dwError != NOERROR ) {
  882. return( dwError );
  883. }
  884. __try {
  885. if( AccessCheckAndAuditAlarmW(
  886. SubsystemName,
  887. NULL, // No handle for object
  888. ObjectTypeName,
  889. NULL,
  890. SecurityDescriptor,
  891. DesiredAccess,
  892. GenericMapping,
  893. FALSE, // open existing object.
  894. &GrantedAccess,
  895. &AccessStatus,
  896. &GenerateOnClose ) == FALSE ) {
  897. dwError = GetLastError();
  898. __leave;
  899. }
  900. if ( AccessStatus == FALSE ) {
  901. dwError = ERROR_ACCESS_DENIED;
  902. __leave;
  903. }
  904. dwError = NOERROR;
  905. }
  906. __finally {
  907. DWORD dwTemp = RpcRevertToSelf(); // We don't care about the return here
  908. }
  909. return( dwError );
  910. }
  911. DWORD
  912. WINAPI
  913. StiAccessCheckAndAuditA(
  914. IN LPCSTR SubsystemName,
  915. IN LPSTR ObjectTypeName,
  916. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  917. IN ACCESS_MASK DesiredAccess,
  918. IN PGENERIC_MAPPING GenericMapping
  919. )
  920. /*++
  921. Routine Description:
  922. This function impersonates the caller so that it can perform access
  923. validation using NtAccessCheckAndAuditAlarm; and reverts back to
  924. itself before returning.
  925. Arguments:
  926. SubsystemName - Supplies a name string identifying the subsystem
  927. calling this routine.
  928. ObjectTypeName - Supplies the name of the type of the object being
  929. accessed.
  930. SecurityDescriptor - A pointer to the Security Descriptor against which
  931. acccess is to be checked.
  932. DesiredAccess - Supplies desired acccess mask. This mask must have been
  933. previously mapped to contain no generic accesses.
  934. GenericMapping - Supplies a pointer to the generic mapping associated
  935. with this object type.
  936. Return Value:
  937. WIN32 Error - NOERROR or reason for failure.
  938. --*/
  939. {
  940. DWORD dwError;
  941. ACCESS_MASK GrantedAccess;
  942. BOOL GenerateOnClose;
  943. BOOL AccessStatus;
  944. dwError = RpcImpersonateClient( NULL ) ;
  945. if( dwError != NOERROR ) {
  946. return( dwError );
  947. }
  948. __try {
  949. if( AccessCheckAndAuditAlarmA(
  950. SubsystemName,
  951. NULL, // No handle for object
  952. ObjectTypeName,
  953. NULL,
  954. SecurityDescriptor,
  955. DesiredAccess,
  956. GenericMapping,
  957. FALSE, // open existing object.
  958. &GrantedAccess,
  959. &AccessStatus,
  960. &GenerateOnClose ) == FALSE ) {
  961. dwError = GetLastError();
  962. __leave;
  963. }
  964. if ( AccessStatus == FALSE ) {
  965. dwError = ERROR_ACCESS_DENIED;
  966. __leave;
  967. }
  968. dwError = NOERROR;
  969. }
  970. __finally {
  971. DWORD dwTemp = RpcRevertToSelf(); // We don't care about the return here
  972. }
  973. return( dwError );
  974. }
  975. DWORD
  976. WINAPI
  977. StiAccessCheck(
  978. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  979. IN ACCESS_MASK DesiredAccess,
  980. IN PGENERIC_MAPPING GenericMapping
  981. )
  982. /*++
  983. Routine Description:
  984. This function impersonates the caller so that it can perform access
  985. validation using AccessCheck; and reverts back to
  986. itself before returning.
  987. This routine differs from AccessCheckAndAudit in that it doesn't require
  988. the caller to have SE_AUDIT_PRIVILEGE nor does it generate audits.
  989. That is typically fine since the passed in security descriptor typically doesn't
  990. have a SACL requesting an audit.
  991. Arguments:
  992. SecurityDescriptor - A pointer to the Security Descriptor against which
  993. acccess is to be checked.
  994. DesiredAccess - Supplies desired acccess mask. This mask must have been
  995. previously mapped to contain no generic accesses.
  996. GenericMapping - Supplies a pointer to the generic mapping associated
  997. with this object type.
  998. Return Value:
  999. WINAPI_STATUS - NOERROR or reason for failure.
  1000. --*/
  1001. {
  1002. DWORD dwError;
  1003. HANDLE hClientToken = NULL;
  1004. DWORD GrantedAccess;
  1005. BOOL AccessStatus;
  1006. BYTE PrivilegeSet[500]; // Large buffer
  1007. DWORD PrivilegeSetSize;
  1008. //
  1009. // Impersonate the client.
  1010. //
  1011. dwError = RpcImpersonateClient(NULL);
  1012. if ( dwError != NOERROR ) {
  1013. return( dwError );
  1014. }
  1015. __try {
  1016. //
  1017. // Open the impersonated token.
  1018. //
  1019. if ( OpenThreadToken(
  1020. GetCurrentThread(),
  1021. TOKEN_QUERY,
  1022. TRUE, // use process security context to open token
  1023. &hClientToken ) == FALSE ) {
  1024. dwError = GetLastError();
  1025. __leave;
  1026. }
  1027. //
  1028. // Check if the client has the required access.
  1029. //
  1030. PrivilegeSetSize = sizeof(PrivilegeSet);
  1031. if ( AccessCheck(
  1032. SecurityDescriptor,
  1033. hClientToken,
  1034. DesiredAccess,
  1035. GenericMapping,
  1036. (PPRIVILEGE_SET)PrivilegeSet,
  1037. &PrivilegeSetSize,
  1038. &GrantedAccess,
  1039. &AccessStatus ) == FALSE ) {
  1040. dwError = GetLastError();
  1041. __leave;
  1042. }
  1043. if ( AccessStatus == FALSE ) {
  1044. dwError = ERROR_ACCESS_DENIED;
  1045. __leave;
  1046. }
  1047. //
  1048. // Success
  1049. //
  1050. dwError = NOERROR;
  1051. }
  1052. __finally {
  1053. DWORD dwTemp = RpcRevertToSelf(); // We don't care about the return here
  1054. if ( hClientToken != NULL ) {
  1055. CloseHandle( hClientToken );
  1056. }
  1057. }
  1058. return( dwError );
  1059. }
  1060. DWORD
  1061. WINAPI
  1062. StiApiAccessCheck(
  1063. IN ACCESS_MASK DesiredAccess
  1064. )
  1065. /*++
  1066. Routine Description:
  1067. Arguments:
  1068. DesiredAccess - Supplies desired acccess mask. This mask must have been
  1069. previously mapped to contain no generic accesses.
  1070. Return Value:
  1071. WINAPI_STATUS - NOERROR or reason for failure.
  1072. --*/
  1073. {
  1074. return StiAccessCheck(
  1075. sdApiObject,
  1076. DesiredAccess,
  1077. &ApiObjectMapping
  1078. );
  1079. }
  1080. BOOL
  1081. WINAPI
  1082. AdjustSecurityDescriptorForSync(
  1083. HANDLE hObject
  1084. )
  1085. /*++
  1086. Routine Description:
  1087. Arguments:
  1088. None
  1089. Return Value:
  1090. --*/
  1091. {
  1092. #define SD_SIZE (65536 + SECURITY_DESCRIPTOR_MIN_LENGTH)
  1093. BOOL fRet;
  1094. BYTE *bSDbuf = NULL;
  1095. PSECURITY_DESCRIPTOR pProcessSD;
  1096. DWORD dwSDLengthNeeded;
  1097. PACL pACL;
  1098. BOOL bDaclPresent;
  1099. BOOL bDaclDefaulted;
  1100. ACL_SIZE_INFORMATION AclInfo;
  1101. PACL pNewACL = NULL;
  1102. DWORD dwNewACLSize;
  1103. UCHAR NewSD[SECURITY_DESCRIPTOR_MIN_LENGTH];
  1104. PSECURITY_DESCRIPTOR psdNewSD=(PSECURITY_DESCRIPTOR)NewSD;
  1105. PVOID pTempAce;
  1106. UINT CurrentAceIndex;
  1107. fRet = FALSE;
  1108. bSDbuf = (BYTE*) LocalAlloc(LPTR, SD_SIZE);
  1109. if (!bSDbuf) {
  1110. DBG_ERR(("AdjustSecurityDescriptorForSync, Out of memory!"));
  1111. return FALSE;
  1112. }
  1113. pProcessSD = (PSECURITY_DESCRIPTOR)bSDbuf;
  1114. __try {
  1115. if (!GetKernelObjectSecurity(hObject,
  1116. DACL_SECURITY_INFORMATION,
  1117. pProcessSD,
  1118. SD_SIZE,
  1119. (LPDWORD)&dwSDLengthNeeded)) {
  1120. __leave;
  1121. }
  1122. // Initialize new SD
  1123. if(!InitializeSecurityDescriptor(psdNewSD,SECURITY_DESCRIPTOR_REVISION)) {
  1124. fRet = FALSE;
  1125. __leave;
  1126. }
  1127. // Get DACL from SD
  1128. if (!GetSecurityDescriptorDacl(pProcessSD,&bDaclPresent,&pACL,&bDaclDefaulted)) {
  1129. fRet = FALSE;
  1130. __leave;
  1131. }
  1132. // Get file ACL size information
  1133. if(!GetAclInformation(pACL,&AclInfo,sizeof(ACL_SIZE_INFORMATION),AclSizeInformation)) {
  1134. fRet = FALSE;
  1135. __leave;
  1136. }
  1137. // Compute size needed for the new ACL
  1138. dwNewACLSize = AclInfo.AclBytesInUse +
  1139. sizeof(ACCESS_ALLOWED_ACE) +
  1140. GetLengthSid(psidLocal) - sizeof(DWORD);
  1141. // Allocate memory for new ACL
  1142. pNewACL = (PACL)LocalAlloc(LPTR, dwNewACLSize);
  1143. if (!pNewACL) {
  1144. fRet = FALSE;
  1145. __leave;
  1146. }
  1147. // Initialize the new ACL
  1148. if(!InitializeAcl(pNewACL, dwNewACLSize, ACL_REVISION2)) {
  1149. fRet = FALSE;
  1150. __leave;
  1151. }
  1152. // If DACL is present, copy it to a new DACL
  1153. if(bDaclPresent) {
  1154. if(AclInfo.AceCount) {
  1155. for(CurrentAceIndex = 0;
  1156. CurrentAceIndex < AclInfo.AceCount;
  1157. CurrentAceIndex++) {
  1158. if(!GetAce(pACL,CurrentAceIndex,&pTempAce)) {
  1159. fRet = FALSE;
  1160. __leave;
  1161. }
  1162. // Add the ACE to the new ACL
  1163. if(!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,((PACE_HEADER)pTempAce)->AceSize)){
  1164. fRet = FALSE;
  1165. __leave;
  1166. }
  1167. }
  1168. }
  1169. }
  1170. // Add the access-allowed ACE to the new DACL
  1171. if(!AddAccessAllowedAce(pNewACL,ACL_REVISION2, READ_CONTROL | SYNCHRONIZE,psidLocal)) {
  1172. fRet = FALSE;
  1173. __leave;
  1174. }
  1175. // Set our new DACL to the file SD
  1176. if (!SetSecurityDescriptorDacl(psdNewSD,TRUE,pNewACL,FALSE)) {
  1177. fRet = FALSE;
  1178. __leave;
  1179. }
  1180. if (!SetKernelObjectSecurity(hObject,DACL_SECURITY_INFORMATION,psdNewSD)) {
  1181. fRet = FALSE;
  1182. __leave;
  1183. }
  1184. fRet = TRUE;
  1185. }
  1186. __finally {
  1187. if (bSDbuf) {
  1188. LocalFree(bSDbuf);
  1189. bSDbuf = NULL;
  1190. }
  1191. if (pNewACL) {
  1192. LocalFree((HLOCAL) pNewACL);
  1193. pNewACL = NULL;
  1194. }
  1195. }
  1196. return(fRet);
  1197. }
  1198. BOOL
  1199. WINAPI
  1200. InitializeNTSecurity(
  1201. VOID
  1202. )
  1203. /*++
  1204. Routine Description:
  1205. Creates and initializes security related data
  1206. Arguments:
  1207. None
  1208. Return Value:
  1209. TRUE if successful
  1210. --*/
  1211. {
  1212. DWORD dwError = NOERROR;
  1213. HANDLE hProcess = NULL;
  1214. DBG_FN(InitializeNTSecurity);
  1215. CreateWellKnownSids();
  1216. //
  1217. // Set proper process and thread security descriptor
  1218. //
  1219. hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,GetCurrentProcessId());
  1220. if (IS_VALID_HANDLE(hProcess)) {
  1221. AdjustSecurityDescriptorForSync(hProcess);
  1222. CloseHandle(hProcess);
  1223. }
  1224. else {
  1225. dwError = GetLastError();
  1226. return FALSE;
  1227. }
  1228. AdjustSecurityDescriptorForSync(GetCurrentThread());
  1229. dwError = CreateSecurityObject( AcesData,
  1230. NUM_ACES,
  1231. NULL,
  1232. NULL,
  1233. &ApiObjectMapping,
  1234. &sdApiObject );
  1235. return (dwError == NOERROR) ? TRUE : FALSE;
  1236. } // InitializeNTSecurity
  1237. BOOL
  1238. WINAPI
  1239. TerminateNTSecurity(
  1240. VOID
  1241. )
  1242. /*++
  1243. Routine Description:
  1244. Cleans up security related data
  1245. Arguments:
  1246. None
  1247. Return Value:
  1248. TRUE if successful
  1249. --*/
  1250. {
  1251. DeleteSecurityObject(&sdApiObject);
  1252. FreeWellKnownSids();
  1253. return TRUE;
  1254. } //TerminateNTSecurity
  1255. #else
  1256. //
  1257. // We don't support security on non-NT platforms
  1258. //
  1259. DWORD
  1260. WINAPI
  1261. StiApiAccessCheck(
  1262. IN ACCESS_MASK DesiredAccess
  1263. )
  1264. /*++
  1265. Routine Description:
  1266. Arguments:
  1267. DesiredAccess - Supplies desired acccess mask. This mask must have been
  1268. previously mapped to contain no generic accesses.
  1269. Return Value:
  1270. WINAPI_STATUS - NOERROR or reason for failure.
  1271. --*/
  1272. {
  1273. return NOERROR;
  1274. }
  1275. #endif