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.

1391 lines
33 KiB

  1. /*++
  2. Copyright (c) 1991-1992 Microsoft Corporation
  3. Module Name:
  4. secobj.c
  5. Abstract:
  6. This module provides support routines to simplify the creation of
  7. security descriptors for user-mode objects.
  8. Adapted the code from \nt\private\net\netlib\secobj.h
  9. Author:
  10. Rita Wong (ritaw) 27-Feb-1991
  11. Environment:
  12. Contains NT specific code.
  13. Revision History:
  14. 16-Apr-1991 JohnRo
  15. Include header files for <netlib.h>.
  16. 14 Apr 1992 RichardW
  17. Changed for modified ACE_HEADER struct.
  18. 19 Sep. 1995 MadanA
  19. Adapted the code for the internet project and made to use WIN32
  20. APIs instead RTL functions.
  21. --*/
  22. #include <windows.h>
  23. #include <rpc.h>
  24. #include <inetsec.h>
  25. #include <proto.h>
  26. #if DBG
  27. #define STATIC
  28. #else
  29. #define STATIC static
  30. #endif // DBG
  31. //-------------------------------------------------------------------//
  32. // //
  33. // Global variables //
  34. // //
  35. //-------------------------------------------------------------------//
  36. //
  37. // NT well-known SIDs
  38. //
  39. PSID NullSid = NULL; // No members SID
  40. PSID WorldSid = NULL; // All users SID
  41. PSID LocalSid = NULL; // NT local users SID
  42. PSID NetworkSid = NULL; // NT remote users SID
  43. PSID LocalSystemSid = NULL; // NT system processes SID
  44. PSID BuiltinDomainSid = NULL; // Domain Id of the Builtin Domain
  45. //
  46. // Well Known Aliases.
  47. //
  48. // These are aliases that are relative to the built-in domain.
  49. //
  50. PSID LocalAdminSid = NULL; // NT local admins SID
  51. PSID AliasAdminsSid = NULL;
  52. PSID AliasUsersSid = NULL;
  53. PSID AliasGuestsSid = NULL;
  54. PSID AliasPowerUsersSid = NULL;
  55. PSID AliasAccountOpsSid = NULL;
  56. PSID AliasSystemOpsSid = NULL;
  57. PSID AliasPrintOpsSid = NULL;
  58. PSID AliasBackupOpsSid = NULL;
  59. STATIC
  60. struct _SID_DATA {
  61. PSID *Sid;
  62. SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
  63. ULONG SubAuthority;
  64. } SidData[] = {
  65. {&NullSid, SECURITY_NULL_SID_AUTHORITY, SECURITY_NULL_RID},
  66. {&WorldSid, SECURITY_WORLD_SID_AUTHORITY, SECURITY_WORLD_RID},
  67. {&LocalSid, SECURITY_LOCAL_SID_AUTHORITY, SECURITY_LOCAL_RID},
  68. {&NetworkSid, SECURITY_NT_AUTHORITY, SECURITY_NETWORK_RID},
  69. {&LocalSystemSid, SECURITY_NT_AUTHORITY, SECURITY_LOCAL_SYSTEM_RID},
  70. {&BuiltinDomainSid, SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID}
  71. };
  72. STATIC
  73. struct _BUILTIN_DOMAIN_SID_DATA {
  74. PSID *Sid;
  75. ULONG RelativeId;
  76. } BuiltinDomainSidData[] = {
  77. { &LocalAdminSid, DOMAIN_ALIAS_RID_ADMINS},
  78. { &AliasAdminsSid, DOMAIN_ALIAS_RID_ADMINS },
  79. { &AliasUsersSid, DOMAIN_ALIAS_RID_USERS },
  80. { &AliasGuestsSid, DOMAIN_ALIAS_RID_GUESTS },
  81. { &AliasPowerUsersSid, DOMAIN_ALIAS_RID_POWER_USERS },
  82. { &AliasAccountOpsSid, DOMAIN_ALIAS_RID_ACCOUNT_OPS },
  83. { &AliasSystemOpsSid, DOMAIN_ALIAS_RID_SYSTEM_OPS },
  84. { &AliasPrintOpsSid, DOMAIN_ALIAS_RID_PRINT_OPS },
  85. { &AliasBackupOpsSid, DOMAIN_ALIAS_RID_BACKUP_OPS }
  86. };
  87. PVOID
  88. INetpMemoryAllocate(
  89. DWORD Size
  90. )
  91. /*++
  92. Routine Description:
  93. This function allocates the required size of memory by calling
  94. LocalAlloc.
  95. Arguments:
  96. Size - size of the memory block required.
  97. Return Value:
  98. Pointer to the allocated block.
  99. --*/
  100. {
  101. LPVOID NewPointer;
  102. NewPointer = LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, Size );
  103. #if DBG
  104. // ASSERT( NewPointer != NULL );
  105. #endif
  106. return( NewPointer );
  107. }
  108. VOID
  109. INetpMemoryFree(
  110. PVOID Memory
  111. )
  112. /*++
  113. Routine Description:
  114. This function frees up the memory that was allocated by
  115. InternetAllocateMemory.
  116. Arguments:
  117. Memory - pointer to the memory block that needs to be freed up.
  118. Return Value:
  119. none.
  120. --*/
  121. {
  122. LPVOID Ptr;
  123. #if DBG
  124. // ASSERT( Memory != NULL );
  125. #endif
  126. Ptr = LocalFree( Memory );
  127. #if DBG
  128. // ASSERT( Ptr == NULL );
  129. #endif
  130. }
  131. DWORD
  132. INetpInitializeAllowedAce(
  133. IN PACCESS_ALLOWED_ACE AllowedAce,
  134. IN USHORT AceSize,
  135. IN BYTE InheritFlags,
  136. IN BYTE AceFlags,
  137. IN ACCESS_MASK Mask,
  138. IN PSID AllowedSid
  139. )
  140. /*++
  141. Routine Description:
  142. This function assigns the specified ACE values into an allowed type ACE.
  143. Arguments:
  144. AllowedAce - Supplies a pointer to the ACE that is initialized.
  145. AceSize - Supplies the size of the ACE in bytes.
  146. InheritFlags - Supplies ACE inherit flags.
  147. AceFlags - Supplies ACE type specific control flags.
  148. Mask - Supplies the allowed access masks.
  149. AllowedSid - Supplies the pointer to the SID of user/group which is allowed
  150. the specified access.
  151. Return Value:
  152. WIN32 Error Code.
  153. --*/
  154. {
  155. AllowedAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
  156. AllowedAce->Header.AceSize = AceSize;
  157. AllowedAce->Header.AceFlags = AceFlags | InheritFlags;
  158. AllowedAce->Mask = Mask;
  159. if( CopySid(
  160. GetLengthSid(AllowedSid), // should be valid SID ??
  161. &(AllowedAce->SidStart),
  162. AllowedSid ) == FALSE ) {
  163. return( GetLastError() );
  164. }
  165. return( ERROR_SUCCESS );
  166. }
  167. DWORD
  168. INetpInitializeDeniedAce(
  169. IN PACCESS_DENIED_ACE DeniedAce,
  170. IN USHORT AceSize,
  171. IN BYTE InheritFlags,
  172. IN BYTE AceFlags,
  173. IN ACCESS_MASK Mask,
  174. IN PSID DeniedSid
  175. )
  176. /*++
  177. Routine Description:
  178. This function assigns the specified ACE values into a denied type ACE.
  179. Arguments:
  180. DeniedAce - Supplies a pointer to the ACE that is initialized.
  181. AceSize - Supplies the size of the ACE in bytes.
  182. InheritFlags - Supplies ACE inherit flags.
  183. AceFlags - Supplies ACE type specific control flags.
  184. Mask - Supplies the denied access masks.
  185. AllowedSid - Supplies the pointer to the SID of user/group which is denied
  186. the specified access.
  187. Return Value:
  188. WIN32 Error Code.
  189. --*/
  190. {
  191. DeniedAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
  192. DeniedAce->Header.AceSize = AceSize;
  193. DeniedAce->Header.AceFlags = AceFlags | InheritFlags;
  194. DeniedAce->Mask = Mask;
  195. if( CopySid(
  196. GetLengthSid(DeniedSid), // should be valid SID ??
  197. &(DeniedAce->SidStart),
  198. DeniedSid ) == FALSE ) {
  199. return( GetLastError() );
  200. }
  201. return( ERROR_SUCCESS );
  202. }
  203. DWORD
  204. INetpInitializeAuditAce(
  205. IN PACCESS_ALLOWED_ACE AuditAce,
  206. IN USHORT AceSize,
  207. IN BYTE InheritFlags,
  208. IN BYTE AceFlags,
  209. IN ACCESS_MASK Mask,
  210. IN PSID AuditSid
  211. )
  212. /*++
  213. Routine Description:
  214. This function assigns the specified ACE values into an audit type ACE.
  215. Arguments:
  216. AuditAce - Supplies a pointer to the ACE that is initialized.
  217. AceSize - Supplies the size of the ACE in bytes.
  218. InheritFlags - Supplies ACE inherit flags.
  219. AceFlags - Supplies ACE type specific control flags.
  220. Mask - Supplies the allowed access masks.
  221. AuditSid - Supplies the pointer to the SID of user/group which is to be
  222. audited.
  223. Return Value:
  224. WIN32 Error Code.
  225. --*/
  226. {
  227. AuditAce->Header.AceType = SYSTEM_AUDIT_ACE_TYPE;
  228. AuditAce->Header.AceSize = AceSize;
  229. AuditAce->Header.AceFlags = AceFlags | InheritFlags;
  230. AuditAce->Mask = Mask;
  231. if( CopySid(
  232. GetLengthSid(AuditSid),
  233. &(AuditAce->SidStart),
  234. AuditSid ) == FALSE ) {
  235. return( GetLastError() );
  236. }
  237. return( ERROR_SUCCESS );
  238. }
  239. DWORD
  240. INetpAllocateAndInitializeSid(
  241. OUT PSID *Sid,
  242. IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
  243. IN ULONG SubAuthorityCount
  244. )
  245. /*++
  246. Routine Description:
  247. This function allocates memory for a SID and initializes it.
  248. Arguments:
  249. None.
  250. Return Value:
  251. WIN32 Error Code.
  252. --*/
  253. {
  254. *Sid = (PSID)
  255. INetpMemoryAllocate(
  256. GetSidLengthRequired( (BYTE)SubAuthorityCount) );
  257. if (*Sid == NULL) {
  258. return ERROR_NOT_ENOUGH_MEMORY;
  259. }
  260. InitializeSid( *Sid, IdentifierAuthority, (BYTE)SubAuthorityCount );
  261. return( ERROR_SUCCESS );
  262. }
  263. DWORD
  264. INetpDomainIdToSid(
  265. IN PSID DomainId,
  266. IN ULONG RelativeId,
  267. OUT PSID *Sid
  268. )
  269. /*++
  270. Routine Description:
  271. Given a domain Id and a relative ID create a SID
  272. Arguments:
  273. DomainId - The template SID to use.
  274. RelativeId - The relative Id to append to the DomainId.
  275. Sid - Returns a pointer to an allocated buffer containing the resultant
  276. Sid. Free this buffer using NetpMemoryFree.
  277. Return Value:
  278. WIN32 Error Code.
  279. --*/
  280. {
  281. DWORD Error;
  282. BYTE DomainIdSubAuthorityCount; // Number of sub authorities in domain ID
  283. ULONG SidLength; // Length of newly allocated SID
  284. //
  285. // Allocate a Sid which has one more sub-authority than the domain ID.
  286. //
  287. DomainIdSubAuthorityCount = *(GetSidSubAuthorityCount( DomainId ));
  288. SidLength = GetSidLengthRequired( (BYTE)(DomainIdSubAuthorityCount+1) );
  289. if ((*Sid = (PSID) INetpMemoryAllocate( SidLength )) == NULL ) {
  290. return ERROR_NOT_ENOUGH_MEMORY;
  291. }
  292. //
  293. // Initialize the new SID to have the same inital value as the
  294. // domain ID.
  295. //
  296. if( CopySid(SidLength, *Sid, DomainId) == FALSE ) {
  297. Error = GetLastError();
  298. INetpMemoryFree( *Sid );
  299. return( Error );
  300. }
  301. //
  302. // Adjust the sub-authority count and
  303. // add the relative Id unique to the newly allocated SID
  304. //
  305. (*(GetSidSubAuthorityCount( *Sid ))) ++;
  306. *GetSidSubAuthority( *Sid, DomainIdSubAuthorityCount ) = RelativeId;
  307. return( ERROR_SUCCESS );
  308. }
  309. DWORD
  310. INetpCreateSecurityDescriptor(
  311. IN PACE_DATA AceData,
  312. IN ULONG AceCount,
  313. IN PSID OwnerSid OPTIONAL,
  314. IN PSID GroupSid OPTIONAL,
  315. OUT PSECURITY_DESCRIPTOR *NewDescriptor
  316. )
  317. /*++
  318. Routine Description:
  319. This function creates an absolutes security descriptor containing
  320. the supplied ACE information.
  321. A sample usage of this function:
  322. //
  323. // Order matters! These ACEs are inserted into the DACL in the
  324. // following order. Security access is granted or denied based on
  325. // the order of the ACEs in the DACL.
  326. //
  327. ACE_DATA AceData[4] = {
  328. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  329. GENERIC_ALL, &LocalAdminSid},
  330. {ACCESS_DENIED_ACE_TYPE, 0, 0,
  331. GENERIC_ALL, &NetworkSid},
  332. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  333. WKSTA_CONFIG_GUEST_INFO_GET |
  334. WKSTA_CONFIG_USER_INFO_GET, &DomainUsersSid},
  335. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  336. WKSTA_CONFIG_GUEST_INFO_GET, &DomainGuestsSid}
  337. };
  338. return NetpCreateSecurityDescriptor(
  339. AceData,
  340. 4,
  341. NullSid,
  342. LocalSystemSid,
  343. &ConfigurationInfoSd
  344. );
  345. Arguments:
  346. AceData - Supplies the structure of information that describes the DACL.
  347. AceCount - Supplies the number of entries in AceData structure.
  348. OwnerSid - Supplies the pointer to the SID of the security descriptor
  349. owner. If not specified, a security descriptor with no owner
  350. will be created.
  351. GroupSid - Supplies the pointer to the SID of the security descriptor
  352. primary group. If not specified, a security descriptor with no primary
  353. group will be created.
  354. NewDescriptor - Returns a pointer to the absolute secutiry descriptor
  355. allocated using NetpMemoryAllocate.
  356. Return Value:
  357. WIN32 Error Code.
  358. --*/
  359. {
  360. DWORD Error;
  361. DWORD i;
  362. //
  363. // Pointer to memory dynamically allocated by this routine to hold
  364. // the absolute security descriptor, the DACL, the SACL, and all the ACEs.
  365. //
  366. // +---------------------------------------------------------------+
  367. // | Security Descriptor |
  368. // +-------------------------------+-------+---------------+-------+
  369. // | DACL | ACE 1 | . . . | ACE n |
  370. // +-------------------------------+-------+---------------+-------+
  371. // | SACL | ACE 1 | . . . | ACE n |
  372. // +-------------------------------+-------+---------------+-------+
  373. //
  374. PSECURITY_DESCRIPTOR AbsoluteSd = NULL;
  375. PACL Dacl = NULL; // Pointer to the DACL portion of above buffer
  376. PACL Sacl = NULL; // Pointer to the SACL portion of above buffer
  377. DWORD DaclSize = sizeof(ACL);
  378. DWORD SaclSize = sizeof(ACL);
  379. DWORD MaxAceSize = 0;
  380. PVOID MaxAce = NULL;
  381. LPBYTE CurrentAvailable;
  382. DWORD Size;
  383. // ASSERT( AceCount > 0 );
  384. //
  385. // Compute the total size of the DACL and SACL ACEs and the maximum
  386. // size of any ACE.
  387. //
  388. for (i = 0; i < AceCount; i++) {
  389. DWORD AceSize;
  390. AceSize = GetLengthSid( *(AceData[i].Sid) );
  391. switch (AceData[i].AceType) {
  392. case ACCESS_ALLOWED_ACE_TYPE:
  393. AceSize += sizeof(ACCESS_ALLOWED_ACE);
  394. DaclSize += AceSize;
  395. break;
  396. case ACCESS_DENIED_ACE_TYPE:
  397. AceSize += sizeof(ACCESS_DENIED_ACE);
  398. DaclSize += AceSize;
  399. break;
  400. case SYSTEM_AUDIT_ACE_TYPE:
  401. AceSize += sizeof(SYSTEM_AUDIT_ACE);
  402. SaclSize += AceSize;
  403. break;
  404. default:
  405. return( ERROR_INVALID_PARAMETER );
  406. }
  407. MaxAceSize = max( MaxAceSize, AceSize );
  408. }
  409. //
  410. // Allocate a chunk of memory large enough the security descriptor
  411. // the DACL, the SACL and all ACEs.
  412. //
  413. // A security descriptor is of opaque data type but
  414. // SECURITY_DESCRIPTOR_MIN_LENGTH is the right size.
  415. //
  416. Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
  417. if ( DaclSize != sizeof(ACL) ) {
  418. Size += DaclSize;
  419. }
  420. if ( SaclSize != sizeof(ACL) ) {
  421. Size += SaclSize;
  422. }
  423. if ((AbsoluteSd = INetpMemoryAllocate( Size )) == NULL) {
  424. Error = ERROR_NOT_ENOUGH_MEMORY;
  425. goto Cleanup;
  426. }
  427. //
  428. // Initialize the Dacl and Sacl
  429. //
  430. CurrentAvailable = (LPBYTE)AbsoluteSd + SECURITY_DESCRIPTOR_MIN_LENGTH;
  431. if ( DaclSize != sizeof(ACL) ) {
  432. Dacl = (PACL)CurrentAvailable;
  433. CurrentAvailable += DaclSize;
  434. if( InitializeAcl( Dacl, DaclSize, ACL_REVISION ) == FALSE ) {
  435. Error = GetLastError();
  436. goto Cleanup;
  437. }
  438. }
  439. if ( SaclSize != sizeof(ACL) ) {
  440. Sacl = (PACL)CurrentAvailable;
  441. CurrentAvailable += SaclSize;
  442. if( InitializeAcl( Sacl, SaclSize, ACL_REVISION ) == FALSE ) {
  443. Error = GetLastError();
  444. goto Cleanup;
  445. }
  446. }
  447. //
  448. // Allocate a temporary buffer big enough for the biggest ACE.
  449. //
  450. if ((MaxAce = INetpMemoryAllocate( MaxAceSize )) == NULL ) {
  451. Error = ERROR_NOT_ENOUGH_MEMORY;
  452. goto Cleanup;
  453. }
  454. //
  455. // Initialize each ACE, and append it into the end of the DACL or SACL.
  456. //
  457. for (i = 0; i < AceCount; i++) {
  458. DWORD AceSize;
  459. PACL CurrentAcl;
  460. AceSize = GetLengthSid( *(AceData[i].Sid) );
  461. switch (AceData[i].AceType) {
  462. case ACCESS_ALLOWED_ACE_TYPE:
  463. AceSize += sizeof(ACCESS_ALLOWED_ACE);
  464. CurrentAcl = Dacl;
  465. Error = INetpInitializeAllowedAce(
  466. MaxAce,
  467. (USHORT) AceSize,
  468. AceData[i].InheritFlags,
  469. AceData[i].AceFlags,
  470. AceData[i].Mask,
  471. *(AceData[i].Sid) );
  472. break;
  473. case ACCESS_DENIED_ACE_TYPE:
  474. AceSize += sizeof(ACCESS_DENIED_ACE);
  475. CurrentAcl = Dacl;
  476. Error = INetpInitializeDeniedAce(
  477. MaxAce,
  478. (USHORT) AceSize,
  479. AceData[i].InheritFlags,
  480. AceData[i].AceFlags,
  481. AceData[i].Mask,
  482. *(AceData[i].Sid) );
  483. break;
  484. case SYSTEM_AUDIT_ACE_TYPE:
  485. AceSize += sizeof(SYSTEM_AUDIT_ACE);
  486. CurrentAcl = Sacl;
  487. Error = INetpInitializeAuditAce(
  488. MaxAce,
  489. (USHORT) AceSize,
  490. AceData[i].InheritFlags,
  491. AceData[i].AceFlags,
  492. AceData[i].Mask,
  493. *(AceData[i].Sid) );
  494. break;
  495. }
  496. if ( Error != ERROR_SUCCESS ) {
  497. goto Cleanup;
  498. }
  499. //
  500. // Append the initialized ACE to the end of DACL or SACL
  501. //
  502. if ( AddAce(
  503. CurrentAcl,
  504. ACL_REVISION,
  505. MAXDWORD,
  506. MaxAce,
  507. AceSize ) == FALSE ) {
  508. Error = GetLastError();
  509. goto Cleanup;
  510. }
  511. }
  512. //
  513. // Create the security descriptor with absolute pointers to SIDs
  514. // and ACLs.
  515. //
  516. // Owner = OwnerSid
  517. // Group = GroupSid
  518. // Dacl = Dacl
  519. // Sacl = Sacl
  520. //
  521. if ( InitializeSecurityDescriptor(
  522. AbsoluteSd,
  523. SECURITY_DESCRIPTOR_REVISION ) == FALSE ) {
  524. Error = GetLastError();
  525. goto Cleanup;
  526. }
  527. if ( SetSecurityDescriptorOwner(
  528. AbsoluteSd,
  529. OwnerSid,
  530. FALSE ) == FALSE ) {
  531. Error = GetLastError();
  532. goto Cleanup;
  533. }
  534. if ( SetSecurityDescriptorGroup(
  535. AbsoluteSd,
  536. GroupSid,
  537. FALSE ) == FALSE ) {
  538. Error = GetLastError();
  539. goto Cleanup;
  540. }
  541. if ( SetSecurityDescriptorDacl(
  542. AbsoluteSd,
  543. TRUE,
  544. Dacl,
  545. FALSE ) == FALSE ) {
  546. Error = GetLastError();
  547. goto Cleanup;
  548. }
  549. if ( SetSecurityDescriptorSacl(
  550. AbsoluteSd,
  551. FALSE,
  552. Sacl,
  553. FALSE ) == FALSE ) {
  554. Error = GetLastError();
  555. goto Cleanup;
  556. }
  557. //
  558. // Done
  559. //
  560. *NewDescriptor = AbsoluteSd;
  561. AbsoluteSd = NULL;
  562. Error = ERROR_SUCCESS;
  563. //
  564. // Clean up
  565. //
  566. Cleanup:
  567. if( AbsoluteSd != NULL ) {
  568. //
  569. // delete the partially made SD if we are not completely
  570. // successful
  571. //
  572. INetpMemoryFree( AbsoluteSd );
  573. }
  574. //
  575. // Delete the temporary ACE
  576. //
  577. if ( MaxAce != NULL ) {
  578. INetpMemoryFree( MaxAce );
  579. }
  580. return( Error );
  581. }
  582. DWORD
  583. INetCreateWellKnownSids(
  584. VOID
  585. )
  586. /*++
  587. Routine Description:
  588. This function creates some well-known SIDs and store them in global
  589. variables.
  590. Arguments:
  591. none.
  592. Return Value:
  593. WIN32 Error Code.
  594. --*/
  595. {
  596. DWORD Error;
  597. DWORD i;
  598. //
  599. // Allocate and initialize well-known SIDs which aren't relative to
  600. // the domain Id.
  601. //
  602. for (i = 0; i < (sizeof(SidData) / sizeof(SidData[0])) ; i++) {
  603. Error = INetpAllocateAndInitializeSid(
  604. SidData[i].Sid,
  605. &(SidData[i].IdentifierAuthority),
  606. 1);
  607. if ( Error != ERROR_SUCCESS ) {
  608. return Error;
  609. }
  610. *(GetSidSubAuthority(*(SidData[i].Sid), 0)) = SidData[i].SubAuthority;
  611. }
  612. //
  613. // Build each SID which is relative to the Builtin Domain Id.
  614. //
  615. for ( i = 0;
  616. i < (sizeof(BuiltinDomainSidData) /
  617. sizeof(BuiltinDomainSidData[0]));
  618. i++) {
  619. Error = INetpDomainIdToSid(
  620. BuiltinDomainSid,
  621. BuiltinDomainSidData[i].RelativeId,
  622. BuiltinDomainSidData[i].Sid );
  623. if ( Error != ERROR_SUCCESS ) {
  624. return Error;
  625. }
  626. }
  627. return ERROR_SUCCESS;
  628. }
  629. VOID
  630. INetFreeWellKnownSids(
  631. VOID
  632. )
  633. /*++
  634. Routine Description:
  635. This function frees up the dynamic memory consumed by the well-known
  636. SIDs.
  637. Arguments:
  638. none.
  639. Return Value:
  640. none
  641. --*/
  642. {
  643. DWORD i;
  644. //
  645. // free up memory allocated for well-known SIDs
  646. //
  647. for (i = 0; i < (sizeof(SidData) / sizeof(SidData[0])) ; i++) {
  648. if( *SidData[i].Sid != NULL ) {
  649. INetpMemoryFree( *SidData[i].Sid );
  650. *SidData[i].Sid = NULL;
  651. }
  652. }
  653. //
  654. // free up memory allocated for Builtin Domain SIDs
  655. //
  656. for (i = 0;
  657. i < (sizeof(BuiltinDomainSidData) /
  658. sizeof(BuiltinDomainSidData[0])) ;
  659. i++) {
  660. if( *BuiltinDomainSidData[i].Sid != NULL ) {
  661. INetpMemoryFree( *BuiltinDomainSidData[i].Sid );
  662. *BuiltinDomainSidData[i].Sid = NULL;
  663. }
  664. }
  665. }
  666. DWORD
  667. INetCreateSecurityObject(
  668. IN PACE_DATA AceData,
  669. IN ULONG AceCount,
  670. IN PSID OwnerSid,
  671. IN PSID GroupSid,
  672. IN PGENERIC_MAPPING GenericMapping,
  673. OUT PSECURITY_DESCRIPTOR *NewDescriptor
  674. )
  675. /*++
  676. Routine Description:
  677. This function creates the DACL for the security descriptor based on
  678. on the ACE information specified, and creates the security descriptor
  679. which becomes the user-mode security object.
  680. A sample usage of this function:
  681. //
  682. // Structure that describes the mapping of Generic access rights to
  683. // object specific access rights for the ConfigurationInfo object.
  684. //
  685. GENERIC_MAPPING WsConfigInfoMapping = {
  686. STANDARD_RIGHTS_READ | // Generic read
  687. WKSTA_CONFIG_GUEST_INFO_GET |
  688. WKSTA_CONFIG_USER_INFO_GET |
  689. WKSTA_CONFIG_ADMIN_INFO_GET,
  690. STANDARD_RIGHTS_WRITE | // Generic write
  691. WKSTA_CONFIG_INFO_SET,
  692. STANDARD_RIGHTS_EXECUTE, // Generic execute
  693. WKSTA_CONFIG_ALL_ACCESS // Generic all
  694. };
  695. //
  696. // Order matters! These ACEs are inserted into the DACL in the
  697. // following order. Security access is granted or denied based on
  698. // the order of the ACEs in the DACL.
  699. //
  700. ACE_DATA AceData[4] = {
  701. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  702. GENERIC_ALL, &LocalAdminSid},
  703. {ACCESS_DENIED_ACE_TYPE, 0, 0,
  704. GENERIC_ALL, &NetworkSid},
  705. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  706. WKSTA_CONFIG_GUEST_INFO_GET |
  707. WKSTA_CONFIG_USER_INFO_GET, &DomainUsersSid},
  708. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  709. WKSTA_CONFIG_GUEST_INFO_GET, &DomainGuestsSid}
  710. };
  711. return INetCreateSecurityObject(
  712. AceData,
  713. 4,
  714. NullSid,
  715. LocalSystemSid,
  716. &WsConfigInfoMapping,
  717. &ConfigurationInfoSd
  718. );
  719. Arguments:
  720. AceData - Supplies the structure of information that describes the DACL.
  721. AceCount - Supplies the number of entries in AceData structure.
  722. OwnerSid - Supplies the pointer to the SID of the security descriptor
  723. owner.
  724. GroupSid - Supplies the pointer to the SID of the security descriptor
  725. primary group.
  726. GenericMapping - Supplies the pointer to a generic mapping array denoting
  727. the mapping between each generic right to specific rights.
  728. NewDescriptor - Returns a pointer to the self-relative security descriptor
  729. which represents the user-mode object.
  730. Return Value:
  731. WIN32 Error Code.
  732. NOTE : the security object created by calling this function may be
  733. freed up by calling INetDeleteSecurityObject().
  734. --*/
  735. {
  736. DWORD Error;
  737. PSECURITY_DESCRIPTOR AbsoluteSd = NULL;
  738. HANDLE TokenHandle = NULL;
  739. Error = INetpCreateSecurityDescriptor(
  740. AceData,
  741. AceCount,
  742. OwnerSid,
  743. GroupSid,
  744. &AbsoluteSd
  745. );
  746. if( Error != ERROR_SUCCESS ) {
  747. return( Error );
  748. }
  749. if( OpenProcessToken(
  750. GetCurrentProcess(),
  751. TOKEN_QUERY,
  752. &TokenHandle ) == FALSE ) {
  753. TokenHandle = INVALID_HANDLE_VALUE;
  754. Error = GetLastError();
  755. goto Cleanup;
  756. }
  757. //
  758. // Create the security object (a user-mode object is really a pseudo-
  759. // object represented by a security descriptor that have relative
  760. // pointers to SIDs and ACLs). This routine allocates the memory to
  761. // hold the relative security descriptor so the memory allocated for the
  762. // DACL, ACEs, and the absolute descriptor can be freed.
  763. //
  764. if( CreatePrivateObjectSecurity(
  765. NULL, // Parent descriptor
  766. AbsoluteSd, // Creator descriptor
  767. NewDescriptor, // Pointer to new descriptor
  768. FALSE, // Is directory object
  769. TokenHandle, // Token
  770. GenericMapping // Generic mapping
  771. ) == FALSE ) {
  772. Error = GetLastError();
  773. goto Cleanup;
  774. }
  775. Error = ERROR_SUCCESS;
  776. Cleanup:
  777. if( TokenHandle != NULL ) {
  778. CloseHandle( TokenHandle );
  779. }
  780. //
  781. // Free dynamic memory before returning
  782. //
  783. if( AbsoluteSd != NULL ) {
  784. INetpMemoryFree( AbsoluteSd );
  785. }
  786. return( Error );
  787. }
  788. DWORD
  789. INetDeleteSecurityObject(
  790. IN PSECURITY_DESCRIPTOR *Descriptor
  791. )
  792. /*++
  793. Routine Description:
  794. This function deletes a security object that was created by calling
  795. INetCreateSecurityObject() function.
  796. Arguments:
  797. Descriptor - Returns a pointer to the self-relative security descriptor
  798. which represents the user-mode object.
  799. Return Value:
  800. WIN32 Error Code.
  801. --*/
  802. {
  803. if( DestroyPrivateObjectSecurity( Descriptor ) == FALSE ) {
  804. return( GetLastError() );
  805. }
  806. return( ERROR_SUCCESS );
  807. }
  808. DWORD
  809. INetAccessCheckAndAuditW(
  810. IN LPCWSTR SubsystemName,
  811. IN LPWSTR ObjectTypeName,
  812. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  813. IN ACCESS_MASK DesiredAccess,
  814. IN PGENERIC_MAPPING GenericMapping
  815. )
  816. /*++
  817. Routine Description:
  818. This function impersonates the caller so that it can perform access
  819. validation using NtAccessCheckAndAuditAlarm; and reverts back to
  820. itself before returning.
  821. Arguments:
  822. SubsystemName - Supplies a name string identifying the subsystem
  823. calling this routine.
  824. ObjectTypeName - Supplies the name of the type of the object being
  825. accessed.
  826. SecurityDescriptor - A pointer to the Security Descriptor against which
  827. acccess is to be checked.
  828. DesiredAccess - Supplies desired acccess mask. This mask must have been
  829. previously mapped to contain no generic accesses.
  830. GenericMapping - Supplies a pointer to the generic mapping associated
  831. with this object type.
  832. Return Value:
  833. NET_API_STATUS - NERR_Success or reason for failure.
  834. --*/
  835. {
  836. DWORD Error;
  837. ACCESS_MASK GrantedAccess;
  838. BOOL GenerateOnClose;
  839. BOOL AccessStatus;
  840. Error = RpcImpersonateClient( NULL ) ;
  841. if( Error != ERROR_SUCCESS ) {
  842. return( Error );
  843. }
  844. if( AccessCheckAndAuditAlarmW(
  845. SubsystemName,
  846. NULL, // No handle for object
  847. ObjectTypeName,
  848. NULL,
  849. SecurityDescriptor,
  850. DesiredAccess,
  851. GenericMapping,
  852. FALSE, // open existing object.
  853. &GrantedAccess,
  854. &AccessStatus,
  855. &GenerateOnClose ) == FALSE ) {
  856. Error = GetLastError();
  857. goto Cleanup;
  858. }
  859. if ( AccessStatus == FALSE ) {
  860. Error = ERROR_ACCESS_DENIED;
  861. goto Cleanup;
  862. }
  863. Error = ERROR_SUCCESS;
  864. Cleanup:
  865. RpcRevertToSelf();
  866. return( Error );
  867. }
  868. DWORD
  869. INetAccessCheckAndAuditA(
  870. IN LPCSTR SubsystemName,
  871. IN LPSTR ObjectTypeName,
  872. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  873. IN ACCESS_MASK DesiredAccess,
  874. IN PGENERIC_MAPPING GenericMapping
  875. )
  876. /*++
  877. Routine Description:
  878. This function impersonates the caller so that it can perform access
  879. validation using NtAccessCheckAndAuditAlarm; and reverts back to
  880. itself before returning.
  881. Arguments:
  882. SubsystemName - Supplies a name string identifying the subsystem
  883. calling this routine.
  884. ObjectTypeName - Supplies the name of the type of the object being
  885. accessed.
  886. SecurityDescriptor - A pointer to the Security Descriptor against which
  887. acccess is to be checked.
  888. DesiredAccess - Supplies desired acccess mask. This mask must have been
  889. previously mapped to contain no generic accesses.
  890. GenericMapping - Supplies a pointer to the generic mapping associated
  891. with this object type.
  892. Return Value:
  893. NET_API_STATUS - NERR_Success or reason for failure.
  894. --*/
  895. {
  896. DWORD Error;
  897. ACCESS_MASK GrantedAccess;
  898. BOOL GenerateOnClose;
  899. BOOL AccessStatus;
  900. Error = RpcImpersonateClient( NULL ) ;
  901. if( Error != ERROR_SUCCESS ) {
  902. return( Error );
  903. }
  904. if( AccessCheckAndAuditAlarmA(
  905. SubsystemName,
  906. NULL, // No handle for object
  907. ObjectTypeName,
  908. NULL,
  909. SecurityDescriptor,
  910. DesiredAccess,
  911. GenericMapping,
  912. FALSE, // open existing object.
  913. &GrantedAccess,
  914. &AccessStatus,
  915. &GenerateOnClose ) == FALSE ) {
  916. Error = GetLastError();
  917. goto Cleanup;
  918. }
  919. if ( AccessStatus == FALSE ) {
  920. Error = ERROR_ACCESS_DENIED;
  921. goto Cleanup;
  922. }
  923. Error = ERROR_SUCCESS;
  924. Cleanup:
  925. RpcRevertToSelf();
  926. return( Error );
  927. }
  928. DWORD
  929. INetAccessCheck(
  930. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  931. IN ACCESS_MASK DesiredAccess,
  932. IN PGENERIC_MAPPING GenericMapping
  933. )
  934. /*++
  935. Routine Description:
  936. This function impersonates the caller so that it can perform access
  937. validation using NtAccessCheck; and reverts back to
  938. itself before returning.
  939. This routine differs from NetpAccessCheckAndAudit in that it doesn't require
  940. the caller to have SE_AUDIT_PRIVILEGE nor does it generate audits.
  941. That is typically fine since the passed in security descriptor typically doesn't
  942. have a SACL requesting an audit.
  943. Arguments:
  944. SecurityDescriptor - A pointer to the Security Descriptor against which
  945. acccess is to be checked.
  946. DesiredAccess - Supplies desired acccess mask. This mask must have been
  947. previously mapped to contain no generic accesses.
  948. GenericMapping - Supplies a pointer to the generic mapping associated
  949. with this object type.
  950. Return Value:
  951. NET_API_STATUS - NERR_Success or reason for failure.
  952. --*/
  953. {
  954. DWORD Error;
  955. HANDLE ClientToken = NULL;
  956. DWORD GrantedAccess = 0;
  957. BOOL AccessStatus;
  958. BYTE PrivilegeSet[500]; // Large buffer
  959. DWORD PrivilegeSetSize;
  960. //
  961. // Impersonate the client.
  962. //
  963. Error = RpcImpersonateClient(NULL);
  964. if ( Error != ERROR_SUCCESS ) {
  965. return( Error );
  966. }
  967. //
  968. // Open the impersonated token.
  969. //
  970. if ( OpenThreadToken(
  971. GetCurrentThread(),
  972. TOKEN_QUERY,
  973. TRUE, // use process security context to open token
  974. &ClientToken ) == FALSE ) {
  975. Error = GetLastError();
  976. goto Cleanup;
  977. }
  978. //
  979. // Check if the client has the required access.
  980. //
  981. PrivilegeSetSize = sizeof(PrivilegeSet);
  982. if ( AccessCheck(
  983. SecurityDescriptor,
  984. ClientToken,
  985. DesiredAccess,
  986. GenericMapping,
  987. (PPRIVILEGE_SET)&PrivilegeSet,
  988. &PrivilegeSetSize,
  989. &GrantedAccess,
  990. &AccessStatus ) == FALSE ) {
  991. Error = GetLastError();
  992. goto Cleanup;
  993. }
  994. if ( AccessStatus == FALSE ) {
  995. Error = ERROR_ACCESS_DENIED;
  996. goto Cleanup;
  997. }
  998. //
  999. // Success
  1000. //
  1001. Error = ERROR_SUCCESS;
  1002. Cleanup:
  1003. RpcRevertToSelf();
  1004. if ( ClientToken != NULL ) {
  1005. CloseHandle( ClientToken );
  1006. }
  1007. return( Error );
  1008. }
  1009.