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

671 lines
18 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 gives 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 AdminsSid = NULL;
  20. PSID SystemSid = NULL;
  21. PSID NetConfigOpsSid = NULL;
  22. PSID NetworkServiceSid = NULL;
  23. ULONG AclLength;
  24. NTSTATUS Status;
  25. ACCESS_MASK AccessMask = GENERIC_ALL;
  26. PACL NewAcl = NULL;
  27. ULONG SidSize;
  28. SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY;
  29. PISID ISid;
  30. PACCESS_ALLOWED_ACE AceTemp;
  31. int i;
  32. //
  33. // Enable access to all the globally defined SIDs
  34. //
  35. GenericMapping = IoGetFileObjectGenericMapping();
  36. RtlMapGenericMask(&AccessMask, GenericMapping);
  37. AdminsSid = SeExports->SeAliasAdminsSid;
  38. SystemSid = SeExports->SeLocalSystemSid;
  39. NetworkServiceSid = SeExports->SeNetworkServiceSid;
  40. SidSize = RtlLengthRequiredSid(2);
  41. NetConfigOpsSid = (PSID)(ExAllocatePool(PagedPool,SidSize));
  42. if (NULL == NetConfigOpsSid) {
  43. return STATUS_INSUFFICIENT_RESOURCES;
  44. }
  45. Status = RtlInitializeSid(NetConfigOpsSid, &sidAuth, 2);
  46. if (Status != STATUS_SUCCESS) {
  47. goto clean_up;
  48. }
  49. ISid = (PISID)(NetConfigOpsSid);
  50. ISid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID;
  51. ISid->SubAuthority[1] = DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS;
  52. AclLength = Dacl->AclSize;
  53. AclLength += sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - 2 * sizeof(ULONG);
  54. AclLength += RtlLengthSid(NetConfigOpsSid);
  55. NewAcl = ExAllocatePool(
  56. PagedPool,
  57. AclLength
  58. );
  59. if (NewAcl == NULL) {
  60. Status = STATUS_INSUFFICIENT_RESOURCES;
  61. goto clean_up;
  62. }
  63. Status = RtlCreateAcl(NewAcl, AclLength, ACL_REVISION2);
  64. if (!NT_SUCCESS(Status)) {
  65. goto clean_up;
  66. }
  67. for (i = 0; i < Dacl->AceCount; i++) {
  68. Status = RtlGetAce(Dacl, i, &AceTemp);
  69. if (NT_SUCCESS(Status)) {
  70. Status = RtlAddAccessAllowedAce(NewAcl,
  71. ACL_REVISION2,
  72. AceTemp->Mask,
  73. &AceTemp->SidStart);
  74. }
  75. if (!NT_SUCCESS(Status)) {
  76. goto clean_up;
  77. }
  78. }
  79. // Add Net Config Operators Ace
  80. Status = RtlAddAccessAllowedAce(NewAcl,
  81. ACL_REVISION2,
  82. AccessMask,
  83. NetConfigOpsSid);
  84. if (!NT_SUCCESS(Status)) {
  85. goto clean_up;
  86. }
  87. if (!NT_SUCCESS(Status)) {
  88. goto clean_up;
  89. }
  90. *DeviceAcl = NewAcl;
  91. clean_up:
  92. if (NetConfigOpsSid) {
  93. ExFreePool(NetConfigOpsSid);
  94. }
  95. if (!NT_SUCCESS(Status) && NewAcl) {
  96. ExFreePool(NewAcl);
  97. }
  98. return (Status);
  99. }
  100. NTSTATUS
  101. CreateDeviceDriverSecurityDescriptor(PVOID DeviceOrDriverObject)
  102. /*++
  103. Routine Description:
  104. Creates the SD responsible for giving access to different users.
  105. Arguments:
  106. None.
  107. Return Value:
  108. STATUS_SUCCESS or an appropriate error code.
  109. --*/
  110. {
  111. NTSTATUS status;
  112. BOOLEAN memoryAllocated = FALSE;
  113. PSECURITY_DESCRIPTOR sdSecurityDescriptor = NULL;
  114. ULONG sdSecurityDescriptorLength;
  115. CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
  116. PSECURITY_DESCRIPTOR localSecurityDescriptor =
  117. (PSECURITY_DESCRIPTOR) & buffer;
  118. SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION;
  119. PACL paclDacl = NULL;
  120. BOOLEAN bHasDacl;
  121. BOOLEAN bDaclDefaulted;
  122. PACCESS_ALLOWED_ACE pAce = NULL;
  123. PACL NewAcl = NULL;
  124. INT i;
  125. //
  126. // Get a pointer to the security descriptor from the driver/device object.
  127. //
  128. status = ObGetObjectSecurity(
  129. DeviceOrDriverObject,
  130. &sdSecurityDescriptor,
  131. &memoryAllocated
  132. );
  133. if (!NT_SUCCESS(status))
  134. {
  135. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  136. "TCP: Unable to get security descriptor, error: %x\n",
  137. status
  138. ));
  139. ASSERT(memoryAllocated == FALSE);
  140. return (status);
  141. }
  142. status = RtlGetDaclSecurityDescriptor(sdSecurityDescriptor, &bHasDacl, &paclDacl, &bDaclDefaulted);
  143. if (bHasDacl)
  144. {
  145. status = AddNetConfigOpsAce(paclDacl, &NewAcl);
  146. if (NT_SUCCESS(status))
  147. {
  148. PSECURITY_DESCRIPTOR sdSecDesc = NULL;
  149. ULONG ulSecDescSize = 0;
  150. PACL daclAbs = NULL;
  151. ULONG ulDacl = 0;
  152. PACL saclAbs = NULL;
  153. ULONG ulSacl = 0;
  154. PSID Owner = NULL;
  155. ULONG ulOwnerSize = 0;
  156. PSID PrimaryGroup = NULL;
  157. ULONG ulPrimaryGroupSize = 0;
  158. BOOLEAN bOwnerDefault;
  159. BOOLEAN bGroupDefault;
  160. BOOLEAN HasSacl = FALSE;
  161. BOOLEAN SaclDefaulted = FALSE;
  162. SECURITY_INFORMATION secInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
  163. HANDLE hIp;
  164. HANDLE hTcp;
  165. ulSecDescSize = sizeof(sdSecDesc) + NewAcl->AclSize;
  166. sdSecDesc = ExAllocatePool(PagedPool, ulSecDescSize);
  167. if (sdSecDesc)
  168. {
  169. ulDacl = NewAcl->AclSize;
  170. daclAbs = ExAllocatePool(PagedPool, ulDacl);
  171. if (daclAbs)
  172. {
  173. status = RtlGetOwnerSecurityDescriptor(sdSecurityDescriptor, &Owner, &bOwnerDefault);
  174. if (NT_SUCCESS(status))
  175. {
  176. ulOwnerSize = RtlLengthSid(Owner);
  177. status = RtlGetGroupSecurityDescriptor(sdSecurityDescriptor, &PrimaryGroup, &bGroupDefault);
  178. if (NT_SUCCESS(status))
  179. {
  180. status = RtlGetSaclSecurityDescriptor(sdSecurityDescriptor, &HasSacl, &saclAbs, &SaclDefaulted);
  181. if (NT_SUCCESS(status))
  182. {
  183. if (HasSacl)
  184. {
  185. ulSacl = saclAbs->AclSize;
  186. secInfo |= SACL_SECURITY_INFORMATION;
  187. }
  188. ulPrimaryGroupSize= RtlLengthSid(PrimaryGroup);
  189. status = RtlSelfRelativeToAbsoluteSD(sdSecurityDescriptor, sdSecDesc, &ulSecDescSize, daclAbs,
  190. &ulDacl, saclAbs, &ulSacl, Owner, &ulOwnerSize, PrimaryGroup, &ulPrimaryGroupSize);
  191. if (NT_SUCCESS(status))
  192. {
  193. status = RtlSetDaclSecurityDescriptor(sdSecDesc, TRUE, NewAcl, FALSE);
  194. if (NT_SUCCESS(status))
  195. {
  196. status = ObSetSecurityObjectByPointer(DeviceOrDriverObject, secInfo, sdSecDesc);
  197. }
  198. }
  199. }
  200. }
  201. }
  202. }
  203. if (sdSecDesc)
  204. {
  205. // Since this is a Self-Relative security descriptor, freeing it also frees
  206. // Owner and PrimaryGroup.
  207. ExFreePool(sdSecDesc);
  208. }
  209. if (daclAbs)
  210. {
  211. ExFreePool(daclAbs);
  212. }
  213. }
  214. if (NewAcl)
  215. {
  216. ExFreePool(NewAcl);
  217. }
  218. }
  219. }
  220. else
  221. {
  222. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"TCP: No Dacl: %x\n", status));
  223. }
  224. ObReleaseObjectSecurity(
  225. sdSecurityDescriptor,
  226. memoryAllocated
  227. );
  228. return (status);
  229. }
  230. NTSTATUS
  231. ndisBuildDeviceAcl(
  232. OUT PACL *DeviceAcl,
  233. IN BOOLEAN AddNetConfigOps
  234. )
  235. /*++
  236. Routine Description:
  237. This routine builds an ACL which gives Administrators, LocalSystem,
  238. and NetworkService principals full access. All other principals have no access.
  239. Arguments:
  240. DeviceAcl - Output pointer to the new ACL.
  241. Return Value:
  242. STATUS_SUCCESS or an appropriate error code.
  243. --*/
  244. {
  245. NTSTATUS Status;
  246. PGENERIC_MAPPING GenericMapping;
  247. ULONG AclLength;
  248. ACCESS_MASK AccessMask = GENERIC_ALL;
  249. PACL NewAcl;
  250. PSID NetConfigOpsSid = NULL;
  251. ULONG NetConfigOpsSidSize;
  252. SID_IDENTIFIER_AUTHORITY NetConfigOpsSidAuth = SECURITY_NT_AUTHORITY;
  253. PISID ISid;
  254. do
  255. {
  256. //
  257. // Enable access to all the globally defined SIDs
  258. //
  259. GenericMapping = IoGetFileObjectGenericMapping();
  260. RtlMapGenericMask(&AccessMask, GenericMapping );
  261. AclLength = sizeof(ACL) +
  262. FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
  263. RtlLengthSid(SeExports->SeAliasAdminsSid);
  264. if (AddNetConfigOps)
  265. {
  266. NetConfigOpsSidSize = RtlLengthRequiredSid(2);
  267. NetConfigOpsSid = (PSID)ALLOC_FROM_POOL(NetConfigOpsSidSize, NDIS_TAG_NET_CFG_OPS_ID);
  268. if (NULL == NetConfigOpsSid)
  269. {
  270. Status = STATUS_INSUFFICIENT_RESOURCES;
  271. break;
  272. }
  273. Status = RtlInitializeSid(NetConfigOpsSid, &NetConfigOpsSidAuth, 2);
  274. if (Status != STATUS_SUCCESS)
  275. {
  276. Status = STATUS_INSUFFICIENT_RESOURCES;
  277. break;
  278. }
  279. ISid = (PISID)(NetConfigOpsSid);
  280. ISid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID;
  281. ISid->SubAuthority[1] = DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS;
  282. AclLength += RtlLengthSid(NetConfigOpsSid) + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
  283. }
  284. NewAcl = ALLOC_FROM_POOL(AclLength, NDIS_TAG_SECURITY);
  285. if (NewAcl == NULL)
  286. {
  287. Status = STATUS_INSUFFICIENT_RESOURCES;
  288. break;
  289. }
  290. ZeroMemory(NewAcl, AclLength);
  291. Status = RtlCreateAcl(NewAcl, AclLength, ACL_REVISION );
  292. if (!NT_SUCCESS(Status))
  293. {
  294. FREE_POOL(NewAcl);
  295. break;
  296. }
  297. Status = RtlAddAccessAllowedAce (
  298. NewAcl,
  299. ACL_REVISION2,
  300. AccessMask,
  301. SeExports->SeAliasAdminsSid
  302. );
  303. ASSERT(NT_SUCCESS(Status));
  304. if (AddNetConfigOps)
  305. {
  306. // Add Net Config Operators Ace
  307. Status = RtlAddAccessAllowedAce(NewAcl,
  308. ACL_REVISION2,
  309. AccessMask,
  310. NetConfigOpsSid);
  311. ASSERT(NT_SUCCESS(Status));
  312. }
  313. *DeviceAcl = NewAcl;
  314. Status = STATUS_SUCCESS;
  315. }while (FALSE);
  316. if (NetConfigOpsSid)
  317. {
  318. ExFreePool(NetConfigOpsSid);
  319. }
  320. return(Status);
  321. }
  322. NTSTATUS
  323. ndisCreateSecurityDescriptor(
  324. IN PDEVICE_OBJECT DeviceObject,
  325. OUT PSECURITY_DESCRIPTOR * pSecurityDescriptor,
  326. BOOLEAN AddNetConfigOps
  327. )
  328. /*++
  329. Routine Description:
  330. This routine creates a security descriptor which gives access
  331. only to certain priviliged accounts. This descriptor is used
  332. to access check processes that open a handle to miniport device
  333. objects.
  334. Arguments:
  335. None.
  336. Return Value:
  337. STATUS_SUCCESS or an appropriate error code.
  338. --*/
  339. {
  340. PACL devAcl = NULL;
  341. NTSTATUS Status;
  342. BOOLEAN memoryAllocated = FALSE;
  343. PSECURITY_DESCRIPTOR CurSecurityDescriptor;
  344. PSECURITY_DESCRIPTOR NewSecurityDescriptor;
  345. ULONG CurSecurityDescriptorLength;
  346. CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
  347. PSECURITY_DESCRIPTOR localSecurityDescriptor =
  348. (PSECURITY_DESCRIPTOR)buffer;
  349. SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION;
  350. BOOLEAN bReleaseObjectSecurity = FALSE;
  351. do
  352. {
  353. *pSecurityDescriptor = NULL;
  354. //
  355. // Get a pointer to the security descriptor from the device object.
  356. //
  357. Status = ObGetObjectSecurity(
  358. DeviceObject,
  359. &CurSecurityDescriptor,
  360. &memoryAllocated
  361. );
  362. if (!NT_SUCCESS(Status))
  363. {
  364. ASSERT(memoryAllocated == FALSE);
  365. break;
  366. }
  367. bReleaseObjectSecurity = TRUE;
  368. //
  369. // Build a local security descriptor with an ACL giving only
  370. // certain priviliged accounts.
  371. //
  372. Status = ndisBuildDeviceAcl(&devAcl, AddNetConfigOps);
  373. if (!NT_SUCCESS(Status))
  374. {
  375. break;
  376. }
  377. (VOID)RtlCreateSecurityDescriptor(
  378. localSecurityDescriptor,
  379. SECURITY_DESCRIPTOR_REVISION
  380. );
  381. (VOID)RtlSetDaclSecurityDescriptor(
  382. localSecurityDescriptor,
  383. TRUE,
  384. devAcl,
  385. FALSE
  386. );
  387. //
  388. // Make a copy of the security descriptor. This copy will be the raw descriptor.
  389. //
  390. CurSecurityDescriptorLength = RtlLengthSecurityDescriptor(
  391. CurSecurityDescriptor
  392. );
  393. NewSecurityDescriptor = ALLOC_FROM_POOL(CurSecurityDescriptorLength, NDIS_TAG_SECURITY);
  394. if (NewSecurityDescriptor == NULL)
  395. {
  396. Status = STATUS_INSUFFICIENT_RESOURCES;
  397. break;
  398. }
  399. RtlMoveMemory(
  400. NewSecurityDescriptor,
  401. CurSecurityDescriptor,
  402. CurSecurityDescriptorLength
  403. );
  404. *pSecurityDescriptor = NewSecurityDescriptor;
  405. //
  406. // Now apply the local descriptor to the raw descriptor.
  407. //
  408. Status = SeSetSecurityDescriptorInfo(
  409. NULL,
  410. &securityInformation,
  411. localSecurityDescriptor,
  412. pSecurityDescriptor,
  413. NonPagedPool,
  414. IoGetFileObjectGenericMapping()
  415. );
  416. if (!NT_SUCCESS(Status))
  417. {
  418. ASSERT(*pSecurityDescriptor == NewSecurityDescriptor);
  419. FREE_POOL(*pSecurityDescriptor);
  420. *pSecurityDescriptor = NULL;
  421. break;
  422. }
  423. if (*pSecurityDescriptor != NewSecurityDescriptor)
  424. {
  425. ExFreePool(NewSecurityDescriptor);
  426. }
  427. Status = STATUS_SUCCESS;
  428. }while (FALSE);
  429. if (bReleaseObjectSecurity)
  430. {
  431. ObReleaseObjectSecurity(
  432. CurSecurityDescriptor,
  433. memoryAllocated
  434. );
  435. }
  436. if (devAcl!=NULL)
  437. {
  438. FREE_POOL(devAcl);
  439. }
  440. return(Status);
  441. }
  442. BOOLEAN
  443. ndisCheckAccess (
  444. PIRP Irp,
  445. PIO_STACK_LOCATION IrpSp,
  446. PNTSTATUS Status,
  447. PSECURITY_DESCRIPTOR SecurityDescriptor
  448. )
  449. /*++
  450. Routine Description:
  451. Compares security context of the endpoint creator to that
  452. of the administrator and local system.
  453. Arguments:
  454. Irp - Pointer to I/O request packet.
  455. IrpSp - pointer to the IO stack location to use for this request.
  456. Status - returns status generated by access check on failure.
  457. Return Value:
  458. TRUE - the creator has admin or local system privilige
  459. FALSE - the creator is just a plain user
  460. --*/
  461. {
  462. BOOLEAN accessGranted;
  463. PACCESS_STATE accessState;
  464. PIO_SECURITY_CONTEXT securityContext;
  465. PPRIVILEGE_SET privileges = NULL;
  466. ACCESS_MASK grantedAccess;
  467. PGENERIC_MAPPING GenericMapping;
  468. ACCESS_MASK AccessMask = GENERIC_ALL;
  469. //
  470. // Enable access to all the globally defined SIDs
  471. //
  472. GenericMapping = IoGetFileObjectGenericMapping();
  473. RtlMapGenericMask( &AccessMask, GenericMapping );
  474. securityContext = IrpSp->Parameters.Create.SecurityContext;
  475. accessState = securityContext->AccessState;
  476. SeLockSubjectContext(&accessState->SubjectSecurityContext);
  477. accessGranted = SeAccessCheck(
  478. SecurityDescriptor,
  479. &accessState->SubjectSecurityContext,
  480. TRUE,
  481. AccessMask,
  482. 0,
  483. &privileges,
  484. IoGetFileObjectGenericMapping(),
  485. (KPROCESSOR_MODE)((IrpSp->Flags & SL_FORCE_ACCESS_CHECK)
  486. ? UserMode
  487. : Irp->RequestorMode),
  488. &grantedAccess,
  489. Status
  490. );
  491. if (privileges) {
  492. (VOID) SeAppendPrivileges(
  493. accessState,
  494. privileges
  495. );
  496. SeFreePrivileges(privileges);
  497. }
  498. if (accessGranted) {
  499. accessState->PreviouslyGrantedAccess |= grantedAccess;
  500. accessState->RemainingDesiredAccess &= ~( grantedAccess | MAXIMUM_ALLOWED );
  501. ASSERT (NT_SUCCESS (*Status));
  502. }
  503. else {
  504. ASSERT (!NT_SUCCESS (*Status));
  505. }
  506. SeUnlockSubjectContext(&accessState->SubjectSecurityContext);
  507. return accessGranted;
  508. }