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.

1014 lines
30 KiB

  1. #include "precomp.h"
  2. typedef ULONG SECURITY_INFORMATION;
  3. NTSTATUS
  4. AddNetConfigOpsAce(IN PACL Dacl,
  5. OUT PACL * DeviceAcl
  6. )
  7. /*++
  8. Routine Description:
  9. This routine builds an ACL which adds the Network Configuration Operators group
  10. to the principals allowed to control the driver.
  11. Arguments:
  12. Dacl - Existing DACL.
  13. DeviceAcl - Output pointer to the new ACL.
  14. Return Value:
  15. STATUS_SUCCESS or an appropriate error code.
  16. --*/
  17. {
  18. PGENERIC_MAPPING GenericMapping;
  19. PSID NetConfigOpsSid = NULL;
  20. ULONG AclLength;
  21. NTSTATUS Status;
  22. ACCESS_MASK AccessMask = GENERIC_ALL;
  23. PACL NewAcl = NULL;
  24. ULONG SidSize;
  25. SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY;
  26. PISID ISid;
  27. PACCESS_ALLOWED_ACE AceTemp;
  28. int i;
  29. //
  30. // Enable access to all the globally defined SIDs
  31. //
  32. GenericMapping = IoGetFileObjectGenericMapping();
  33. RtlMapGenericMask(&AccessMask, GenericMapping);
  34. SidSize = RtlLengthRequiredSid(2);
  35. NetConfigOpsSid = (PSID)(ExAllocatePoolWithTag(PagedPool,SidSize, NDIS_TAG_NET_CFG_OPS_ID));
  36. if (NULL == NetConfigOpsSid) {
  37. return STATUS_INSUFFICIENT_RESOURCES;
  38. }
  39. Status = RtlInitializeSid(NetConfigOpsSid, &sidAuth, 2);
  40. if (Status != STATUS_SUCCESS) {
  41. goto clean_up;
  42. }
  43. ISid = (PISID)(NetConfigOpsSid);
  44. ISid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID;
  45. ISid->SubAuthority[1] = DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS;
  46. AclLength = Dacl->AclSize;
  47. AclLength += sizeof(ACL) + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
  48. AclLength += RtlLengthSid(NetConfigOpsSid);
  49. NewAcl = ExAllocatePoolWithTag(
  50. PagedPool,
  51. AclLength,
  52. NDIS_TAG_NET_CFG_OPS_ACL
  53. );
  54. if (NewAcl == NULL) {
  55. Status = STATUS_INSUFFICIENT_RESOURCES;
  56. goto clean_up;
  57. }
  58. Status = RtlCreateAcl(NewAcl, AclLength, ACL_REVISION2);
  59. if (!NT_SUCCESS(Status)) {
  60. goto clean_up;
  61. }
  62. for (i = 0; i < Dacl->AceCount; i++) {
  63. Status = RtlGetAce(Dacl, i, &AceTemp);
  64. if (NT_SUCCESS(Status)) {
  65. Status = RtlAddAccessAllowedAce(NewAcl,
  66. ACL_REVISION2,
  67. AceTemp->Mask,
  68. &AceTemp->SidStart);
  69. }
  70. if (!NT_SUCCESS(Status)) {
  71. goto clean_up;
  72. }
  73. }
  74. // Add Net Config Operators Ace
  75. Status = RtlAddAccessAllowedAce(NewAcl,
  76. ACL_REVISION2,
  77. AccessMask,
  78. NetConfigOpsSid);
  79. if (!NT_SUCCESS(Status)) {
  80. goto clean_up;
  81. }
  82. *DeviceAcl = NewAcl;
  83. clean_up:
  84. if (NetConfigOpsSid) {
  85. ExFreePool(NetConfigOpsSid);
  86. }
  87. if (!NT_SUCCESS(Status) && NewAcl) {
  88. ExFreePool(NewAcl);
  89. }
  90. return (Status);
  91. }
  92. NTSTATUS
  93. CreateDeviceDriverSecurityDescriptor(
  94. IN PVOID DeviceOrDriverObject,
  95. IN BOOLEAN AddNetConfigOps,
  96. IN PACL AclToAdd OPTIONAL
  97. )
  98. /*++
  99. Routine Description:
  100. Creates the SD responsible for giving access to different users.
  101. Arguments:
  102. None.
  103. Return Value:
  104. STATUS_SUCCESS or an appropriate error code.
  105. --*/
  106. {
  107. NTSTATUS status;
  108. BOOLEAN memoryAllocated = FALSE;
  109. PSECURITY_DESCRIPTOR sdSecurityDescriptor = NULL;
  110. PACL paclDacl = NULL;
  111. BOOLEAN bHasDacl;
  112. BOOLEAN bDaclDefaulted;
  113. PACL NewAcl = NULL;
  114. //
  115. // Get a pointer to the security descriptor from the driver/device object.
  116. //
  117. status = ObGetObjectSecurity(
  118. DeviceOrDriverObject,
  119. &sdSecurityDescriptor,
  120. &memoryAllocated
  121. );
  122. if (!NT_SUCCESS(status))
  123. {
  124. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  125. "TCP: Unable to get security descriptor, error: %x\n",
  126. status
  127. ));
  128. ASSERT(memoryAllocated == FALSE);
  129. return (status);
  130. }
  131. status = RtlGetDaclSecurityDescriptor(sdSecurityDescriptor,
  132. &bHasDacl,
  133. &paclDacl,
  134. &bDaclDefaulted);
  135. if (NT_SUCCESS(status))
  136. {
  137. if (bHasDacl)
  138. {
  139. if (AddNetConfigOps && paclDacl)
  140. {
  141. status = AddNetConfigOpsAce(paclDacl, &NewAcl);
  142. }
  143. else if (AclToAdd)
  144. {
  145. NewAcl = AclToAdd;
  146. }
  147. else
  148. {
  149. return STATUS_UNSUCCESSFUL;
  150. }
  151. ASSERT(NT_SUCCESS(status));
  152. if (NT_SUCCESS(status))
  153. {
  154. PSECURITY_DESCRIPTOR sdSecDesc = NULL;
  155. ULONG ulSecDescSize = 0;
  156. PACL daclAbs = NULL;
  157. ULONG ulDacl = 0;
  158. PACL saclAbs = NULL;
  159. ULONG ulSacl = 0;
  160. PSID Owner = NULL;
  161. ULONG ulOwnerSize = 0;
  162. PSID PrimaryGroup = NULL;
  163. ULONG ulPrimaryGroupSize = 0;
  164. BOOLEAN bOwnerDefault;
  165. BOOLEAN bGroupDefault;
  166. BOOLEAN HasSacl = FALSE;
  167. BOOLEAN SaclDefaulted = FALSE;
  168. SECURITY_INFORMATION secInfo = OWNER_SECURITY_INFORMATION |
  169. GROUP_SECURITY_INFORMATION |
  170. DACL_SECURITY_INFORMATION;
  171. ulSecDescSize = sizeof(SECURITY_DESCRIPTOR) + NewAcl->AclSize;
  172. sdSecDesc = ExAllocatePoolWithTag(PagedPool,
  173. ulSecDescSize,
  174. NDIS_TAG_NET_CFG_SEC_DESC);
  175. if (sdSecDesc)
  176. {
  177. ulDacl = NewAcl->AclSize;
  178. daclAbs = ExAllocatePoolWithTag(PagedPool,
  179. ulDacl,
  180. NDIS_TAG_NET_CFG_DACL);
  181. if (daclAbs)
  182. {
  183. status = RtlGetOwnerSecurityDescriptor(sdSecurityDescriptor,
  184. &Owner,
  185. &bOwnerDefault);
  186. if (NT_SUCCESS(status))
  187. {
  188. ulOwnerSize = RtlLengthSid(Owner);
  189. status = RtlGetGroupSecurityDescriptor(sdSecurityDescriptor,
  190. &PrimaryGroup,
  191. &bGroupDefault);
  192. if (NT_SUCCESS(status))
  193. {
  194. status = RtlGetSaclSecurityDescriptor(sdSecurityDescriptor,
  195. &HasSacl,
  196. &saclAbs,
  197. &SaclDefaulted);
  198. if (NT_SUCCESS(status))
  199. {
  200. if (HasSacl)
  201. {
  202. ulSacl = saclAbs->AclSize;
  203. secInfo |= SACL_SECURITY_INFORMATION;
  204. }
  205. ulPrimaryGroupSize= RtlLengthSid(PrimaryGroup);
  206. status = RtlSelfRelativeToAbsoluteSD(sdSecurityDescriptor,
  207. sdSecDesc,
  208. &ulSecDescSize,
  209. daclAbs,
  210. &ulDacl,
  211. saclAbs,
  212. &ulSacl,
  213. Owner,
  214. &ulOwnerSize,
  215. PrimaryGroup,
  216. &ulPrimaryGroupSize);
  217. if (NT_SUCCESS(status))
  218. {
  219. status = RtlSetDaclSecurityDescriptor(sdSecDesc, TRUE, NewAcl, FALSE);
  220. if (NT_SUCCESS(status))
  221. {
  222. status = ObSetSecurityObjectByPointer(DeviceOrDriverObject, secInfo, sdSecDesc);
  223. }
  224. }
  225. }
  226. }
  227. }
  228. }
  229. if (sdSecDesc)
  230. {
  231. // Since this is a Self-Relative security descriptor, freeing it also frees
  232. // Owner and PrimaryGroup.
  233. ExFreePool(sdSecDesc);
  234. }
  235. if (daclAbs)
  236. {
  237. ExFreePool(daclAbs);
  238. }
  239. }
  240. if ((AclToAdd == NULL) && NewAcl)
  241. {
  242. ExFreePool(NewAcl);
  243. }
  244. }
  245. }
  246. else
  247. {
  248. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"NDIS: No Dacl: %x\n", status));
  249. }
  250. }
  251. ObReleaseObjectSecurity(
  252. sdSecurityDescriptor,
  253. memoryAllocated
  254. );
  255. return (status);
  256. }
  257. NTSTATUS
  258. ndisBuildDeviceAcl(
  259. OUT PACL *DeviceAcl,
  260. IN BOOLEAN AddNetConfigOps,
  261. IN BOOLEAN AddNetworkService
  262. )
  263. /*++
  264. Routine Description:
  265. This routine builds an ACL which gives Administrators, LocalSystem,
  266. and NetworkService principals full access. All other principals have no access.
  267. Arguments:
  268. DeviceAcl - Output pointer to the new ACL.
  269. Return Value:
  270. STATUS_SUCCESS or an appropriate error code.
  271. --*/
  272. {
  273. NTSTATUS Status;
  274. PGENERIC_MAPPING GenericMapping;
  275. ULONG AclLength;
  276. ACCESS_MASK AccessMask = GENERIC_ALL;
  277. PACL NewAcl;
  278. PSID NetConfigOpsSid = NULL;
  279. ULONG NetConfigOpsSidSize;
  280. SID_IDENTIFIER_AUTHORITY NetConfigOpsSidAuth = SECURITY_NT_AUTHORITY;
  281. PISID ISid;
  282. do
  283. {
  284. //
  285. // Enable access to all the globally defined SIDs
  286. //
  287. GenericMapping = IoGetFileObjectGenericMapping();
  288. RtlMapGenericMask(&AccessMask, GenericMapping );
  289. AclLength = sizeof(ACL) +
  290. FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
  291. RtlLengthSid(SeExports->SeAliasAdminsSid);
  292. if (AddNetworkService)
  293. {
  294. AclLength += sizeof(ACL) +
  295. FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
  296. RtlLengthSid(SeExports->SeNetworkServiceSid);
  297. }
  298. if (AddNetConfigOps)
  299. {
  300. NetConfigOpsSidSize = RtlLengthRequiredSid(2);
  301. NetConfigOpsSid = (PSID)ALLOC_FROM_POOL(NetConfigOpsSidSize, NDIS_TAG_NET_CFG_OPS_ID);
  302. if (NULL == NetConfigOpsSid)
  303. {
  304. Status = STATUS_INSUFFICIENT_RESOURCES;
  305. break;
  306. }
  307. Status = RtlInitializeSid(NetConfigOpsSid, &NetConfigOpsSidAuth, 2);
  308. if (Status != STATUS_SUCCESS)
  309. {
  310. Status = STATUS_INSUFFICIENT_RESOURCES;
  311. break;
  312. }
  313. ISid = (PISID)(NetConfigOpsSid);
  314. ISid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID;
  315. ISid->SubAuthority[1] = DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS;
  316. AclLength += RtlLengthSid(NetConfigOpsSid) + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
  317. }
  318. NewAcl = ALLOC_FROM_POOL(AclLength, NDIS_TAG_SECURITY);
  319. if (NewAcl == NULL)
  320. {
  321. Status = STATUS_INSUFFICIENT_RESOURCES;
  322. break;
  323. }
  324. ZeroMemory(NewAcl, AclLength);
  325. Status = RtlCreateAcl(NewAcl, AclLength, ACL_REVISION );
  326. if (!NT_SUCCESS(Status))
  327. {
  328. FREE_POOL(NewAcl);
  329. break;
  330. }
  331. Status = RtlAddAccessAllowedAce (
  332. NewAcl,
  333. ACL_REVISION2,
  334. AccessMask,
  335. SeExports->SeAliasAdminsSid
  336. );
  337. ASSERT(NT_SUCCESS(Status));
  338. if (AddNetworkService)
  339. {
  340. Status = RtlAddAccessAllowedAce(
  341. NewAcl,
  342. ACL_REVISION2,
  343. AccessMask,
  344. SeExports->SeNetworkServiceSid
  345. );
  346. ASSERT(NT_SUCCESS(Status));
  347. }
  348. if (AddNetConfigOps)
  349. {
  350. // Add Net Config Operators Ace
  351. Status = RtlAddAccessAllowedAce(NewAcl,
  352. ACL_REVISION2,
  353. AccessMask,
  354. NetConfigOpsSid);
  355. ASSERT(NT_SUCCESS(Status));
  356. }
  357. *DeviceAcl = NewAcl;
  358. Status = STATUS_SUCCESS;
  359. }while (FALSE);
  360. if (NetConfigOpsSid)
  361. {
  362. ExFreePool(NetConfigOpsSid);
  363. }
  364. return(Status);
  365. }
  366. NTSTATUS
  367. ndisCreateSecurityDescriptor(
  368. IN PDEVICE_OBJECT DeviceObject,
  369. OUT PSECURITY_DESCRIPTOR * pSecurityDescriptor,
  370. IN BOOLEAN AddNetConfigOps,
  371. IN BOOLEAN AddNetworkService
  372. )
  373. /*++
  374. Routine Description:
  375. This routine creates a security descriptor which gives access
  376. only to certain priviliged accounts. This descriptor is used
  377. to access check processes that open a handle to miniport device
  378. objects.
  379. Arguments:
  380. None.
  381. Return Value:
  382. STATUS_SUCCESS or an appropriate error code.
  383. --*/
  384. {
  385. PACL devAcl = NULL;
  386. NTSTATUS Status;
  387. BOOLEAN memoryAllocated = FALSE;
  388. PSECURITY_DESCRIPTOR CurSecurityDescriptor;
  389. PSECURITY_DESCRIPTOR NewSecurityDescriptor;
  390. ULONG CurSecurityDescriptorLength;
  391. CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
  392. PSECURITY_DESCRIPTOR localSecurityDescriptor =
  393. (PSECURITY_DESCRIPTOR)buffer;
  394. SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION;
  395. BOOLEAN bReleaseObjectSecurity = FALSE;
  396. do
  397. {
  398. *pSecurityDescriptor = NULL;
  399. //
  400. // Get a pointer to the security descriptor from the device object.
  401. //
  402. Status = ObGetObjectSecurity(
  403. DeviceObject,
  404. &CurSecurityDescriptor,
  405. &memoryAllocated
  406. );
  407. if (!NT_SUCCESS(Status))
  408. {
  409. ASSERT(memoryAllocated == FALSE);
  410. break;
  411. }
  412. bReleaseObjectSecurity = TRUE;
  413. //
  414. // Build a local security descriptor with an ACL giving only
  415. // certain priviliged accounts.
  416. //
  417. Status = ndisBuildDeviceAcl(&devAcl, AddNetConfigOps, AddNetworkService);
  418. if (!NT_SUCCESS(Status))
  419. {
  420. break;
  421. }
  422. //1 why (VOID)?
  423. (VOID)RtlCreateSecurityDescriptor(
  424. localSecurityDescriptor,
  425. SECURITY_DESCRIPTOR_REVISION
  426. );
  427. (VOID)RtlSetDaclSecurityDescriptor(
  428. localSecurityDescriptor,
  429. TRUE,
  430. devAcl,
  431. FALSE
  432. );
  433. //
  434. // Make a copy of the security descriptor. This copy will be the raw descriptor.
  435. //
  436. CurSecurityDescriptorLength = RtlLengthSecurityDescriptor(
  437. CurSecurityDescriptor
  438. );
  439. NewSecurityDescriptor = ALLOC_FROM_POOL(CurSecurityDescriptorLength, NDIS_TAG_SECURITY);
  440. if (NewSecurityDescriptor == NULL)
  441. {
  442. Status = STATUS_INSUFFICIENT_RESOURCES;
  443. break;
  444. }
  445. RtlMoveMemory(
  446. NewSecurityDescriptor,
  447. CurSecurityDescriptor,
  448. CurSecurityDescriptorLength
  449. );
  450. *pSecurityDescriptor = NewSecurityDescriptor;
  451. //
  452. // Now apply the local descriptor to the raw descriptor.
  453. //
  454. Status = SeSetSecurityDescriptorInfo(
  455. NULL,
  456. &securityInformation,
  457. localSecurityDescriptor,
  458. pSecurityDescriptor,
  459. NonPagedPool,
  460. IoGetFileObjectGenericMapping()
  461. );
  462. if (!NT_SUCCESS(Status))
  463. {
  464. ASSERT(*pSecurityDescriptor == NewSecurityDescriptor);
  465. FREE_POOL(*pSecurityDescriptor);
  466. *pSecurityDescriptor = NULL;
  467. break;
  468. }
  469. if (*pSecurityDescriptor != NewSecurityDescriptor)
  470. {
  471. ExFreePool(NewSecurityDescriptor);
  472. }
  473. Status = STATUS_SUCCESS;
  474. }while (FALSE);
  475. if (bReleaseObjectSecurity)
  476. {
  477. ObReleaseObjectSecurity(
  478. CurSecurityDescriptor,
  479. memoryAllocated
  480. );
  481. }
  482. if (devAcl!=NULL)
  483. {
  484. FREE_POOL(devAcl);
  485. }
  486. return(Status);
  487. }
  488. BOOLEAN
  489. ndisCheckAccess (
  490. PIRP Irp,
  491. PIO_STACK_LOCATION IrpSp,
  492. PNTSTATUS Status,
  493. PSECURITY_DESCRIPTOR SecurityDescriptor
  494. )
  495. /*++
  496. Routine Description:
  497. Compares security context of the endpoint creator to that
  498. of the administrator and local system.
  499. Arguments:
  500. Irp - Pointer to I/O request packet.
  501. IrpSp - pointer to the IO stack location to use for this request.
  502. Status - returns status generated by access check on failure.
  503. Return Value:
  504. TRUE - the creator has admin or local system privilige
  505. FALSE - the creator is just a plain user
  506. --*/
  507. {
  508. BOOLEAN accessGranted;
  509. PACCESS_STATE accessState;
  510. PIO_SECURITY_CONTEXT securityContext;
  511. PPRIVILEGE_SET privileges = NULL;
  512. ACCESS_MASK grantedAccess;
  513. PGENERIC_MAPPING GenericMapping;
  514. ACCESS_MASK AccessMask = GENERIC_ALL;
  515. //
  516. // Enable access to all the globally defined SIDs
  517. //
  518. GenericMapping = IoGetFileObjectGenericMapping();
  519. RtlMapGenericMask( &AccessMask, GenericMapping );
  520. securityContext = IrpSp->Parameters.Create.SecurityContext;
  521. accessState = securityContext->AccessState;
  522. SeLockSubjectContext(&accessState->SubjectSecurityContext);
  523. accessGranted = SeAccessCheck(
  524. SecurityDescriptor,
  525. &accessState->SubjectSecurityContext,
  526. TRUE,
  527. AccessMask,
  528. 0,
  529. &privileges,
  530. IoGetFileObjectGenericMapping(),
  531. (KPROCESSOR_MODE)((IrpSp->Flags & SL_FORCE_ACCESS_CHECK)
  532. ? UserMode
  533. : Irp->RequestorMode),
  534. &grantedAccess,
  535. Status
  536. );
  537. if (privileges) {
  538. (VOID) SeAppendPrivileges(
  539. accessState,
  540. privileges
  541. );
  542. SeFreePrivileges(privileges);
  543. }
  544. if (accessGranted) {
  545. accessState->PreviouslyGrantedAccess |= grantedAccess;
  546. accessState->RemainingDesiredAccess &= ~( grantedAccess | MAXIMUM_ALLOWED );
  547. ASSERT (NT_SUCCESS (*Status));
  548. }
  549. else {
  550. ASSERT (!NT_SUCCESS (*Status));
  551. }
  552. SeUnlockSubjectContext(&accessState->SubjectSecurityContext);
  553. return accessGranted;
  554. }
  555. NTSTATUS
  556. ndisCreateGenericSD(
  557. PACL Acl,
  558. PCHAR AccessSecurityDescriptor
  559. )
  560. /*++
  561. Routine Description:
  562. Creates the SD responsible for giving access to different users.
  563. Arguments:
  564. None.
  565. Return Value:
  566. STATUS_SUCCESS or an appropriate error code.
  567. --*/
  568. {
  569. PSECURITY_DESCRIPTOR AccessSd;
  570. NTSTATUS Status;
  571. if (Acl == NULL)
  572. return STATUS_UNSUCCESSFUL;
  573. do
  574. {
  575. AccessSd = AccessSecurityDescriptor;
  576. Status = RtlCreateSecurityDescriptor(
  577. AccessSd,
  578. SECURITY_DESCRIPTOR_REVISION1
  579. );
  580. if (!NT_SUCCESS(Status))
  581. {
  582. DbgPrint("RtlCreateSecurityDescriptor failed, Status %lx.\n", Status);
  583. break;
  584. }
  585. Status = RtlSetDaclSecurityDescriptor(
  586. AccessSd,
  587. TRUE, // DaclPresent
  588. Acl,
  589. FALSE // DaclDefaulted
  590. );
  591. if (!NT_SUCCESS(Status))
  592. {
  593. DbgPrint("RtlSetDaclSecurityDescriptor failed, Status %lx.\n", Status);
  594. break;
  595. }
  596. Status = RtlSetOwnerSecurityDescriptor(AccessSd,
  597. SeExports->SeAliasAdminsSid,
  598. FALSE);
  599. if (!NT_SUCCESS(Status))
  600. {
  601. DbgPrint("RtlSetOwnerSecurityDescriptor failed, Status %lx.\n", Status);
  602. break;
  603. }
  604. Status = RtlSetGroupSecurityDescriptor(AccessSd,
  605. SeExports->SeAliasAdminsSid,
  606. FALSE);
  607. if (!NT_SUCCESS(Status))
  608. {
  609. DbgPrint("RtlSetGroupSecurityDescriptor failed, Status %lx.\n", Status);
  610. break;
  611. }
  612. }while (FALSE);
  613. return (Status);
  614. }
  615. PACL
  616. ndisCreateAcl(
  617. BOOLEAN Admins,
  618. BOOLEAN LocalSystem,
  619. BOOLEAN LocalService,
  620. BOOLEAN NetworkService,
  621. BOOLEAN NetConfigOps,
  622. BOOLEAN Users,
  623. ACCESS_MASK AccessMask
  624. )
  625. {
  626. PACL AccessDacl = NULL, pAcl = NULL;
  627. ULONG AclLength = 0;
  628. PSID NetConfigOpsSid = NULL;
  629. ULONG NetConfigOpsSidSize;
  630. SID_IDENTIFIER_AUTHORITY NetConfigOpsSidAuth = SECURITY_NT_AUTHORITY;
  631. PISID ISid;
  632. NTSTATUS Status;
  633. do
  634. {
  635. if (Admins)
  636. {
  637. AclLength += sizeof(ACL) +
  638. FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
  639. RtlLengthSid(SeExports->SeAliasAdminsSid);
  640. }
  641. if (LocalSystem)
  642. {
  643. AclLength += sizeof(ACL) +
  644. FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
  645. RtlLengthSid(SeExports->SeLocalSystemSid);
  646. }
  647. if (LocalService)
  648. {
  649. AclLength += sizeof(ACL) +
  650. FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
  651. RtlLengthSid(SeExports->SeLocalServiceSid);
  652. }
  653. if (NetworkService)
  654. {
  655. AclLength += sizeof(ACL) +
  656. FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
  657. RtlLengthSid(SeExports->SeNetworkServiceSid);
  658. }
  659. if (NetConfigOps)
  660. {
  661. NetConfigOpsSidSize = RtlLengthRequiredSid(2);
  662. NetConfigOpsSid = (PSID)ALLOC_FROM_POOL(NetConfigOpsSidSize, NDIS_TAG_NET_CFG_OPS_ID);
  663. if (NULL == NetConfigOpsSid)
  664. {
  665. Status = STATUS_INSUFFICIENT_RESOURCES;
  666. break;
  667. }
  668. Status = RtlInitializeSid(NetConfigOpsSid, &NetConfigOpsSidAuth, 2);
  669. if (Status != STATUS_SUCCESS)
  670. {
  671. Status = STATUS_INSUFFICIENT_RESOURCES;
  672. break;
  673. }
  674. ISid = (PISID)(NetConfigOpsSid);
  675. ISid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID;
  676. ISid->SubAuthority[1] = DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS;
  677. AclLength += sizeof(ACL) +
  678. FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
  679. RtlLengthSid(NetConfigOpsSid);
  680. }
  681. if (Users)
  682. {
  683. AclLength += sizeof(ACL) +
  684. FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
  685. RtlLengthSid(SeExports->SeAliasUsersSid);
  686. }
  687. AccessDacl = (PACL)ExAllocatePoolWithTag(PagedPool,
  688. AclLength,
  689. NDIS_TAG_SECURITY);
  690. if (AccessDacl == NULL)
  691. {
  692. Status = STATUS_INSUFFICIENT_RESOURCES;
  693. break;
  694. }
  695. Status = RtlCreateAcl(AccessDacl,
  696. AclLength,
  697. ACL_REVISION2);
  698. if (!NT_SUCCESS(Status))
  699. {
  700. DbgPrint("RtlCreateAcl failed, Status %lx.\n", Status);
  701. break;
  702. }
  703. if (Admins)
  704. {
  705. Status = RtlAddAccessAllowedAce(
  706. AccessDacl,
  707. ACL_REVISION2,
  708. (STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL),
  709. SeExports->SeAliasAdminsSid
  710. );
  711. if (!NT_SUCCESS(Status))
  712. {
  713. DbgPrint("RtlAddAccessAllowedAce failed, Status %lx.\n", Status);
  714. break;
  715. }
  716. }
  717. if (LocalSystem)
  718. {
  719. Status = RtlAddAccessAllowedAce(
  720. AccessDacl,
  721. ACL_REVISION2,
  722. (STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL),
  723. SeExports->SeLocalSystemSid
  724. );
  725. if (!NT_SUCCESS(Status))
  726. {
  727. DbgPrint("RtlAddAccessAllowedAce failed, Status %lx.\n", Status);
  728. break;
  729. }
  730. }
  731. if (LocalService)
  732. {
  733. Status = RtlAddAccessAllowedAce(
  734. AccessDacl,
  735. ACL_REVISION2,
  736. (STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL),
  737. SeExports->SeLocalServiceSid
  738. );
  739. if (!NT_SUCCESS(Status))
  740. {
  741. DbgPrint("RtlAddAccessAllowedAce failed, Status %lx.\n", Status);
  742. break;
  743. }
  744. }
  745. if (NetworkService)
  746. {
  747. Status = RtlAddAccessAllowedAce(
  748. AccessDacl,
  749. ACL_REVISION2,
  750. (STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL),
  751. SeExports->SeNetworkServiceSid
  752. );
  753. if (!NT_SUCCESS(Status))
  754. {
  755. DbgPrint("RtlAddAccessAllowedAce failed, Status %lx.\n", Status);
  756. break;
  757. }
  758. }
  759. if (NetConfigOps)
  760. {
  761. Status = RtlAddAccessAllowedAce(
  762. AccessDacl,
  763. ACL_REVISION2,
  764. (STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL),
  765. NetConfigOpsSid
  766. );
  767. if (!NT_SUCCESS(Status))
  768. {
  769. DbgPrint("RtlAddAccessAllowedAce failed, Status %lx.\n", Status);
  770. break;
  771. }
  772. }
  773. if (Users)
  774. {
  775. Status = RtlAddAccessAllowedAce(
  776. AccessDacl,
  777. ACL_REVISION2,
  778. AccessMask,
  779. SeExports->SeAliasUsersSid
  780. );
  781. if (!NT_SUCCESS(Status))
  782. {
  783. DbgPrint("RtlAddAccessAllowedAce failed, Status %lx.\n", Status);
  784. break;
  785. }
  786. }
  787. pAcl = AccessDacl;
  788. }while (FALSE);
  789. if (pAcl == NULL)
  790. {
  791. if (AccessDacl)
  792. FREE_POOL(AccessDacl);
  793. }
  794. return pAcl;
  795. }