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.

1209 lines
35 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: AccessCk.cpp
  7. //
  8. // Contents: Functions imported and modified from ntos\se\accessck.c
  9. //
  10. //
  11. //----------------------------------------------------------------------------
  12. #include "stdafx.h"
  13. #include "AccessCk.h"
  14. #include "adutils.h"
  15. typedef enum {
  16. UpdateRemaining,
  17. UpdateCurrentGranted,
  18. UpdateCurrentDenied
  19. } ACCESS_MASK_FIELD_TO_UPDATE;
  20. //
  21. // Prototypes
  22. //
  23. BOOLEAN
  24. SepSidInSIDList (
  25. IN list<PSID>& psidList,
  26. IN PSID PrincipalSelfSid,
  27. IN PSID Sid);
  28. HRESULT
  29. SepAddAccessTypeList (
  30. IN PIOBJECT_TYPE_LIST ObjectTypeList,
  31. IN size_t ObjectTypeListLength,
  32. IN ULONG StartIndex,
  33. IN ACCESS_MASK AccessMask,
  34. IN ACCESS_MASK_FIELD_TO_UPDATE FieldToUpdate,
  35. IN PSID grantingSid
  36. );
  37. BOOLEAN
  38. SepObjectInTypeList (
  39. IN GUID *ObjectType,
  40. IN PIOBJECT_TYPE_LIST ObjectTypeList,
  41. IN size_t ObjectTypeListLength,
  42. OUT PULONG ReturnedIndex
  43. );
  44. HRESULT
  45. SepUpdateParentTypeList (
  46. IN PIOBJECT_TYPE_LIST ObjectTypeList,
  47. IN size_t ObjectTypeListLength,
  48. IN ULONG StartIndex,
  49. IN PSID grantingSid
  50. );
  51. HRESULT
  52. SetGrantingSid (
  53. IOBJECT_TYPE_LIST& ObjectTypeItem,
  54. ACCESS_MASK_FIELD_TO_UPDATE FieldToUpdate,
  55. ACCESS_MASK oldAccessBits,
  56. ACCESS_MASK newAccessBits,
  57. PSID grantingSid);
  58. ///////////////////////////////////////////////////////////////////////////////
  59. PSID SePrincipalSelfSid = 0;
  60. static SID_IDENTIFIER_AUTHORITY SepNtAuthority = SECURITY_NT_AUTHORITY;
  61. HRESULT SepInit ()
  62. {
  63. HRESULT hr = S_OK;
  64. ULONG SidWithOneSubAuthority = RtlLengthRequiredSid (1);
  65. SePrincipalSelfSid = (PSID) CoTaskMemAlloc (SidWithOneSubAuthority);
  66. if ( SePrincipalSelfSid )
  67. {
  68. SID_IDENTIFIER_AUTHORITY SeNtAuthority = SepNtAuthority;
  69. RtlInitializeSid (SePrincipalSelfSid, &SeNtAuthority, 1);
  70. *(RtlSubAuthoritySid (SePrincipalSelfSid, 0)) = SECURITY_PRINCIPAL_SELF_RID;
  71. }
  72. else
  73. hr = E_OUTOFMEMORY;
  74. return hr;
  75. }
  76. VOID SepCleanup ()
  77. {
  78. if ( SePrincipalSelfSid )
  79. {
  80. CoTaskMemFree (SePrincipalSelfSid);
  81. SePrincipalSelfSid = 0;
  82. }
  83. }
  84. ///////////////////////////////////////////////////////////////////////////////
  85. HRESULT
  86. SepMaximumAccessCheck(
  87. list<PSID>& psidList,
  88. IN PACL Dacl,
  89. IN PSID PrincipalSelfSid,
  90. IN size_t LocalTypeListLength,
  91. IN PIOBJECT_TYPE_LIST LocalTypeList,
  92. IN size_t ObjectTypeListLength
  93. )
  94. /*++
  95. Routine Description:
  96. Does an access check for maximum allowed or with a result list. The current
  97. granted access is stored in the Remaining access and then another access
  98. check is run.
  99. Arguments:
  100. psidList - list of object sid to check, plus sids of all groups that the object belongs to
  101. Dacl - ACL to check
  102. PrincipalSelfSid - Sid to use in replacing the well-known self sid
  103. LocalTypeListLength - Length of list of types.
  104. LocalTypeList - List of types.
  105. ObjectTypeList - Length of caller-supplied list of object types.
  106. Return Value:
  107. none
  108. --*/
  109. {
  110. if ( !LocalTypeList || ! Dacl )
  111. return E_POINTER;
  112. if ( PrincipalSelfSid && !IsValidSid (PrincipalSelfSid) )
  113. return E_INVALIDARG;
  114. _TRACE (1, L"Entering SepMaximumAccessCheck\n");
  115. PVOID Ace = 0;
  116. ULONG AceCount = Dacl->AceCount;
  117. ULONG Index = 0;
  118. HRESULT hr = S_OK;
  119. //
  120. // granted == NUL
  121. // denied == NUL
  122. //
  123. // for each ACE
  124. //
  125. // if grant
  126. // for each SID
  127. // if SID match, then add all that is not denied to grant mask
  128. //
  129. // if deny
  130. // for each SID
  131. // if SID match, then add all that is not granted to deny mask
  132. //
  133. ULONG i = 0;
  134. for (Ace = FirstAce (Dacl);
  135. i < AceCount;
  136. i++, Ace = NextAce (Ace))
  137. {
  138. if ( !(((PACE_HEADER)Ace)->AceFlags & INHERIT_ONLY_ACE))
  139. {
  140. switch (((PACE_HEADER)Ace)->AceType)
  141. {
  142. case ACCESS_ALLOWED_ACE_TYPE:
  143. if (SepSidInSIDList(psidList, PrincipalSelfSid, &((PACCESS_ALLOWED_ACE)Ace)->SidStart))
  144. {
  145. //
  146. // Only grant access types from this mask that have
  147. // not already been denied
  148. //
  149. // Optimize 'normal' case
  150. if ( LocalTypeListLength == 1 )
  151. {
  152. // TODO: do granting SID
  153. LocalTypeList->CurrentGranted |=
  154. (((PACCESS_ALLOWED_ACE)Ace)->Mask & ~LocalTypeList->CurrentDenied);
  155. }
  156. else
  157. {
  158. //
  159. // The zeroeth object type represents the object itself.
  160. //
  161. hr = SepAddAccessTypeList(
  162. LocalTypeList, // List to modify
  163. LocalTypeListLength, // Length of list
  164. 0, // Element to update
  165. ((PACCESS_ALLOWED_ACE)Ace)->Mask, // Access Granted
  166. UpdateCurrentGranted,
  167. &((PACCESS_ALLOWED_ACE)Ace)->SidStart);
  168. }
  169. }
  170. break;
  171. //
  172. // Handle an object specific Access Allowed ACE
  173. //
  174. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  175. {
  176. //
  177. // If no object type is in the ACE,
  178. // treat this as an ACCESS_ALLOWED_ACE.
  179. //
  180. GUID* ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  181. if ( ObjectTypeInAce == NULL )
  182. {
  183. if ( SepSidInSIDList(psidList, PrincipalSelfSid, RtlObjectAceSid(Ace)) )
  184. {
  185. // Optimize 'normal' case
  186. if ( LocalTypeListLength == 1 )
  187. {
  188. // TODO: do granting SID
  189. LocalTypeList->CurrentGranted |=
  190. (((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask & ~LocalTypeList->CurrentDenied);
  191. }
  192. else
  193. {
  194. hr = SepAddAccessTypeList(
  195. LocalTypeList, // List to modify
  196. LocalTypeListLength, // Length of list
  197. 0, // Element to update
  198. ((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask, // Access Granted
  199. UpdateCurrentGranted,
  200. RtlObjectAceSid(Ace));
  201. }
  202. }
  203. //
  204. // If no object type list was passed,
  205. // don't grant access to anyone.
  206. //
  207. }
  208. else if ( ObjectTypeListLength == 0 )
  209. {
  210. // Drop through
  211. //
  212. // If an object type is in the ACE,
  213. // Find it in the LocalTypeList before using the ACE.
  214. //
  215. }
  216. else
  217. {
  218. if ( SepSidInSIDList(psidList, PrincipalSelfSid, RtlObjectAceSid(Ace)) )
  219. {
  220. if ( SepObjectInTypeList( ObjectTypeInAce,
  221. LocalTypeList,
  222. LocalTypeListLength,
  223. &Index ) )
  224. {
  225. hr = SepAddAccessTypeList(
  226. LocalTypeList, // List to modify
  227. LocalTypeListLength, // Length of list
  228. Index, // Element already updated
  229. ((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask, // Access Granted
  230. UpdateCurrentGranted,
  231. RtlObjectAceSid(Ace));
  232. }
  233. }
  234. }
  235. }
  236. break;
  237. case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  238. //
  239. // If we're impersonating, EToken is set to the Client, and if we're not,
  240. // EToken is set to the Primary. According to the DSA architecture, if
  241. // we're asked to evaluate a compound ACE and we're not impersonating,
  242. // pretend we are impersonating ourselves. So we can just use the EToken
  243. // for the client token, since it's already set to the right thing.
  244. //
  245. if ( SepSidInSIDList(psidList, PrincipalSelfSid, RtlCompoundAceClientSid( Ace )) &&
  246. SepSidInSIDList(psidList, NULL, RtlCompoundAceServerSid( Ace )) )
  247. {
  248. //
  249. // Only grant access types from this mask that have
  250. // not already been denied
  251. //
  252. // Optimize 'normal' case
  253. if ( LocalTypeListLength == 1 )
  254. {
  255. // TODO: do granting SID
  256. LocalTypeList->CurrentGranted |=
  257. (((PCOMPOUND_ACCESS_ALLOWED_ACE)Ace)->Mask & ~LocalTypeList->CurrentDenied);
  258. }
  259. else
  260. {
  261. //
  262. // The zeroeth object type represents the object itself.
  263. //
  264. hr = SepAddAccessTypeList(
  265. LocalTypeList, // List to modify
  266. LocalTypeListLength, // Length of list
  267. 0, // Element to update
  268. ((PCOMPOUND_ACCESS_ALLOWED_ACE)Ace)->Mask, // Access Granted
  269. UpdateCurrentGranted,
  270. RtlCompoundAceClientSid (Ace));
  271. }
  272. }
  273. break;
  274. case ACCESS_DENIED_ACE_TYPE:
  275. if ( SepSidInSIDList(psidList, PrincipalSelfSid, &((PACCESS_DENIED_ACE)Ace)->SidStart))
  276. {
  277. //
  278. // Only deny access types from this mask that have
  279. // not already been granted
  280. //
  281. // Optimize 'normal' case
  282. if ( LocalTypeListLength == 1 )
  283. {
  284. // TODO: do granting SID
  285. LocalTypeList->CurrentDenied |=
  286. (((PACCESS_DENIED_ACE)Ace)->Mask & ~LocalTypeList->CurrentGranted);
  287. }
  288. else
  289. {
  290. //
  291. // The zeroeth object type represents the object itself.
  292. //
  293. hr = SepAddAccessTypeList(
  294. LocalTypeList, // List to modify
  295. LocalTypeListLength, // Length of list
  296. 0, // Element to update
  297. ((PACCESS_DENIED_ACE)Ace)->Mask, // Access denied
  298. UpdateCurrentDenied,
  299. &((PACCESS_DENIED_ACE)Ace)->SidStart);
  300. }
  301. }
  302. break;
  303. //
  304. // Handle an object specific Access Denied ACE
  305. //
  306. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  307. {
  308. PSID psid = RtlObjectAceSid(Ace);
  309. ASSERT (IsValidSid (psid));
  310. if ( IsValidSid (psid) && SepSidInSIDList(psidList, PrincipalSelfSid, psid) )
  311. {
  312. //
  313. // If there is no object type in the ACE,
  314. // or if the caller didn't specify an object type list,
  315. // apply this deny ACE to the entire object.
  316. //
  317. GUID* ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  318. if ( ObjectTypeInAce == NULL ||
  319. ObjectTypeListLength == 0 )
  320. {
  321. // TODO: do granting SID
  322. LocalTypeList->CurrentDenied |=
  323. (((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask & ~LocalTypeList->CurrentGranted);
  324. //
  325. // Otherwise apply the deny ACE to the object specified
  326. // in the ACE.
  327. //
  328. }
  329. else if ( SepObjectInTypeList( ObjectTypeInAce,
  330. LocalTypeList,
  331. LocalTypeListLength,
  332. &Index ) )
  333. {
  334. hr = SepAddAccessTypeList(
  335. LocalTypeList, // List to modify
  336. LocalTypeListLength, // Length of list
  337. Index, // Element to update
  338. ((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask, // Access denied
  339. UpdateCurrentDenied,
  340. psid);
  341. }
  342. }
  343. }
  344. break;
  345. default:
  346. break;
  347. }
  348. }
  349. }
  350. _TRACE (-1, L"Leaving SepMaximumAccessCheck\n");
  351. return hr;
  352. }
  353. NTSTATUS
  354. SeCaptureObjectTypeList (
  355. IN POBJECT_TYPE_LIST ObjectTypeList OPTIONAL,
  356. IN size_t ObjectTypeListLength,
  357. OUT PIOBJECT_TYPE_LIST *CapturedObjectTypeList
  358. )
  359. /*++
  360. Routine Description:
  361. This routine probes and captures a copy of any object type list
  362. that might have been provided via the ObjectTypeList argument.
  363. The object type list is converted to the internal form that explicitly
  364. specifies the hierarchical relationship between the entries.
  365. The object typs list is validated to ensure a valid hierarchical
  366. relationship is represented.
  367. Arguments:
  368. ObjectTypeList - The object type list from which the type list
  369. information is to be retrieved.
  370. ObjectTypeListLength - Number of elements in ObjectTypeList
  371. CapturedObjectTypeList - Receives the captured type list which
  372. must be freed using SeFreeCapturedObjectTypeList().
  373. Return Value:
  374. STATUS_SUCCESS indicates no exceptions were encountered.
  375. Any access violations encountered will be returned.
  376. --*/
  377. {
  378. _TRACE (1, L"Entering SeCaptureObjectTypeList\n");
  379. NTSTATUS Status = STATUS_SUCCESS;
  380. PIOBJECT_TYPE_LIST LocalTypeList = NULL;
  381. ULONG Levels[ACCESS_MAX_LEVEL+1];
  382. //
  383. // Set default return
  384. //
  385. *CapturedObjectTypeList = NULL;
  386. if ( ObjectTypeListLength == 0 )
  387. {
  388. // Drop through
  389. }
  390. else if ( !ARGUMENT_PRESENT(ObjectTypeList) )
  391. {
  392. Status = STATUS_INVALID_PARAMETER;
  393. }
  394. else
  395. {
  396. //
  397. // Allocate a buffer to copy into.
  398. //
  399. LocalTypeList = new IOBJECT_TYPE_LIST[ObjectTypeListLength];
  400. if ( !LocalTypeList )
  401. {
  402. Status = STATUS_INSUFFICIENT_RESOURCES;
  403. //
  404. // Copy the callers structure to the local structure.
  405. //
  406. }
  407. else
  408. {
  409. GUID * CapturedObjectType = 0;
  410. for (ULONG i=0; i < ObjectTypeListLength; i++ )
  411. {
  412. //
  413. // Limit ourselves
  414. //
  415. USHORT CurrentLevel = ObjectTypeList[i].Level;
  416. if ( CurrentLevel > ACCESS_MAX_LEVEL )
  417. {
  418. Status = STATUS_INVALID_PARAMETER;
  419. break;
  420. }
  421. //
  422. // Copy data the caller passed in
  423. //
  424. LocalTypeList[i].Level = CurrentLevel;
  425. LocalTypeList[i].Flags = 0;
  426. CapturedObjectType = ObjectTypeList[i].ObjectType;
  427. LocalTypeList[i].ObjectType = *CapturedObjectType;
  428. LocalTypeList[i].Remaining = 0;
  429. LocalTypeList[i].CurrentGranted = 0;
  430. LocalTypeList[i].CurrentDenied = 0;
  431. //
  432. // Ensure that the level number is consistent with the
  433. // level number of the previous entry.
  434. //
  435. if ( i == 0 )
  436. {
  437. if ( CurrentLevel != 0 )
  438. {
  439. Status = STATUS_INVALID_PARAMETER;
  440. break;
  441. }
  442. }
  443. else
  444. {
  445. //
  446. // The previous entry is either:
  447. // my immediate parent,
  448. // my sibling, or
  449. // the child (or grandchild, etc.) of my sibling.
  450. //
  451. if ( CurrentLevel > LocalTypeList[i-1].Level + 1 )
  452. {
  453. Status = STATUS_INVALID_PARAMETER;
  454. break;
  455. }
  456. //
  457. // Don't support two roots.
  458. //
  459. if ( CurrentLevel == 0 )
  460. {
  461. Status = STATUS_INVALID_PARAMETER;
  462. break;
  463. }
  464. }
  465. //
  466. // If the above rules are maintained,
  467. // then my parent object is the last object seen that
  468. // has a level one less than mine.
  469. //
  470. if ( CurrentLevel == 0 )
  471. {
  472. LocalTypeList[i].ParentIndex = -1;
  473. }
  474. else
  475. {
  476. LocalTypeList[i].ParentIndex = Levels[CurrentLevel-1];
  477. }
  478. //
  479. // Save this obect as the last object seen at this level.
  480. //
  481. Levels[CurrentLevel] = i;
  482. }
  483. }
  484. } // end_if
  485. *CapturedObjectTypeList = LocalTypeList;
  486. _TRACE (-1, L"Leaving SeCaptureObjectTypeList: Status = 0x%x\n", Status);
  487. return Status;
  488. }
  489. BOOLEAN
  490. SepSidInSIDList (
  491. IN list<PSID>& psidList,
  492. IN PSID PrincipalSelfSid,
  493. IN PSID Sid)
  494. /*++
  495. Routine Description:
  496. Checks to see if a given restricted SID is in the given sid list.
  497. N.B. The code to compute the length of a SID and test for equality
  498. is duplicated from the security runtime since this is such a
  499. frequently used routine.
  500. Arguments:
  501. psidList - the list of sids to be examined
  502. PrincipalSelfSid - If the object being access checked is an object which
  503. represents a principal (e.g., a user object), this parameter should
  504. be the SID of the object. Any ACE containing the constant
  505. PRINCIPAL_SELF_SID is replaced by this SID.
  506. The parameter should be NULL if the object does not represent a principal.
  507. Sid - Pointer to the SID of interest
  508. DenyAce - The ACE being evaluated is a DENY or ACCESS DENIED ace
  509. Restricted - The access check being performed uses the restricted sids.
  510. Return Value:
  511. A value of TRUE indicates that the SID is in the token, FALSE
  512. otherwise.
  513. --*/
  514. {
  515. _TRACE (1, L"Entering SeSidInSIDList\n");
  516. BOOLEAN bRVal = FALSE;
  517. PISID MatchSid = 0;
  518. ASSERT (IsValidSid (Sid));
  519. if ( IsValidSid (Sid) )
  520. {
  521. //
  522. // If Sid is the constant PrincipalSelfSid,
  523. // replace it with the passed in PrincipalSelfSid.
  524. //
  525. if ( PrincipalSelfSid != NULL && EqualSid (SePrincipalSelfSid, Sid) )
  526. {
  527. Sid = PrincipalSelfSid;
  528. }
  529. //
  530. // Get address of user/group array and number of user/groups.
  531. //
  532. //
  533. // Scan through the user/groups and attempt to find a match with the
  534. // specified SID.
  535. //
  536. ULONG i = 0;
  537. for (list<PSID>::iterator itr = psidList.begin ();
  538. itr != psidList.end ();
  539. itr++, i++)
  540. {
  541. ASSERT (IsValidSid (*itr));
  542. MatchSid = (PISID)*itr;
  543. if ( ::EqualSid (Sid, *itr) )
  544. {
  545. bRVal = true;
  546. break;
  547. }
  548. }
  549. }
  550. _TRACE (-1, L"Leaving SeSidInSIDList: %s\n", bRVal ? L"TRUE" : L"FALSE");
  551. return bRVal;
  552. }
  553. HRESULT
  554. SepAddAccessTypeList (
  555. IN PIOBJECT_TYPE_LIST ObjectTypeList,
  556. IN size_t ObjectTypeListLength,
  557. IN ULONG StartIndex,
  558. IN ACCESS_MASK AccessMask,
  559. IN ACCESS_MASK_FIELD_TO_UPDATE FieldToUpdate,
  560. IN PSID grantingSid
  561. )
  562. /*++
  563. Routine Description:
  564. This routine grants the specified AccessMask to all of the objects that
  565. are descendents of the object specified by StartIndex.
  566. The Access fields of the parent objects are also recomputed as needed.
  567. For example, if an ACE granting access to a Property Set is found,
  568. that access is granted to all the Properties in the Property Set.
  569. Arguments:
  570. ObjectTypeList - The object type list to update.
  571. ObjectTypeListLength - Number of elements in ObjectTypeList
  572. StartIndex - Index to the target element to update.
  573. AccessMask - Mask of access to grant to the target element and
  574. all of its decendents
  575. FieldToUpdate - Indicate which fields to update in object type list
  576. Return Value:
  577. None.
  578. --*/
  579. {
  580. if ( !ObjectTypeList )
  581. return E_POINTER;
  582. if ( !IsValidSid (grantingSid) )
  583. return E_INVALIDARG;
  584. _TRACE (1, L"Entering SepAddAccessTypeList\n");
  585. ACCESS_MASK OldRemaining = 0;
  586. ACCESS_MASK OldCurrentGranted = 0;
  587. ACCESS_MASK OldCurrentDenied = 0;
  588. BOOLEAN AvoidParent = FALSE;
  589. HRESULT hr = S_OK;
  590. // PAGED_CODE();
  591. //
  592. // Update the requested field.
  593. //
  594. // Always handle the target entry.
  595. //
  596. // If we've not actually changed the bits,
  597. // early out.
  598. //
  599. switch (FieldToUpdate )
  600. {
  601. case UpdateRemaining:
  602. OldRemaining = ObjectTypeList[StartIndex].Remaining;
  603. ObjectTypeList[StartIndex].Remaining = OldRemaining & ~AccessMask;
  604. if ( OldRemaining == ObjectTypeList[StartIndex].Remaining )
  605. {
  606. return hr;
  607. }
  608. else
  609. {
  610. hr = SetGrantingSid (
  611. ObjectTypeList[StartIndex],
  612. FieldToUpdate,
  613. OldRemaining,
  614. AccessMask & ~ObjectTypeList[StartIndex].Remaining,
  615. grantingSid);
  616. }
  617. break;
  618. case UpdateCurrentGranted:
  619. OldCurrentGranted = ObjectTypeList[StartIndex].CurrentGranted;
  620. ObjectTypeList[StartIndex].CurrentGranted |=
  621. AccessMask & ~ObjectTypeList[StartIndex].CurrentDenied;
  622. if ( OldCurrentGranted == ObjectTypeList[StartIndex].CurrentGranted )
  623. {
  624. //
  625. // We can't simply return here.
  626. // We have to visit our children. Consider the case where there
  627. // was a previous deny ACE on a child. That deny would have
  628. // propagated up the tree to this entry. However, this allow ACE
  629. // needs to be added all of the children that haven't been
  630. // explictly denied.
  631. //
  632. AvoidParent = TRUE;
  633. }
  634. else
  635. {
  636. hr = SetGrantingSid (
  637. ObjectTypeList[StartIndex],
  638. FieldToUpdate,
  639. OldCurrentGranted,
  640. AccessMask & ~ObjectTypeList[StartIndex].CurrentDenied,
  641. grantingSid);
  642. }
  643. break;
  644. case UpdateCurrentDenied:
  645. OldCurrentDenied = ObjectTypeList[StartIndex].CurrentDenied;
  646. ObjectTypeList[StartIndex].CurrentDenied |=
  647. AccessMask & ~ObjectTypeList[StartIndex].CurrentGranted;
  648. if ( OldCurrentDenied == ObjectTypeList[StartIndex].CurrentDenied )
  649. {
  650. return hr;
  651. }
  652. else
  653. {
  654. hr = SetGrantingSid (
  655. ObjectTypeList[StartIndex],
  656. FieldToUpdate,
  657. OldCurrentDenied,
  658. AccessMask & ~ObjectTypeList[StartIndex].CurrentGranted,
  659. grantingSid);
  660. }
  661. break;
  662. default:
  663. return hr;
  664. }
  665. //
  666. // Go update parent of the target.
  667. //
  668. if ( !AvoidParent )
  669. {
  670. hr = SepUpdateParentTypeList( ObjectTypeList,
  671. ObjectTypeListLength,
  672. StartIndex,
  673. grantingSid);
  674. }
  675. //
  676. // Loop handling all children of the target.
  677. //
  678. for (ULONG Index = StartIndex + 1; Index < ObjectTypeListLength; Index++)
  679. {
  680. //
  681. // By definition, the children of an object are all those entries
  682. // immediately following the target. The list of children (or
  683. // grandchildren) stops as soon as we reach an entry the has the
  684. // same level as the target (a sibling) or lower than the target
  685. // (an uncle).
  686. //
  687. if ( ObjectTypeList[Index].Level <= ObjectTypeList[StartIndex].Level )
  688. {
  689. break;
  690. }
  691. //
  692. // Grant access to the children
  693. //
  694. switch (FieldToUpdate)
  695. {
  696. case UpdateRemaining:
  697. ObjectTypeList[Index].Remaining &= ~AccessMask;
  698. hr = SetGrantingSid (
  699. ObjectTypeList[Index],
  700. FieldToUpdate,
  701. OldRemaining,
  702. ~AccessMask,
  703. grantingSid);
  704. break;
  705. case UpdateCurrentGranted:
  706. ObjectTypeList[Index].CurrentGranted |=
  707. AccessMask & ~ObjectTypeList[Index].CurrentDenied;
  708. hr = SetGrantingSid (
  709. ObjectTypeList[Index],
  710. FieldToUpdate,
  711. OldCurrentGranted,
  712. AccessMask & ~ObjectTypeList[Index].CurrentDenied,
  713. grantingSid);
  714. break;
  715. case UpdateCurrentDenied:
  716. ObjectTypeList[Index].CurrentDenied |=
  717. AccessMask & ~ObjectTypeList[Index].CurrentGranted;
  718. hr = SetGrantingSid (
  719. ObjectTypeList[Index],
  720. FieldToUpdate,
  721. OldCurrentDenied,
  722. AccessMask & ~ObjectTypeList[Index].CurrentGranted,
  723. grantingSid);
  724. break;
  725. default:
  726. return hr;
  727. }
  728. }
  729. _TRACE (-1, L"Leaving SepAddAccessTypeList\n");
  730. return hr;
  731. }
  732. BOOLEAN
  733. SepObjectInTypeList (
  734. IN GUID *ObjectType,
  735. IN PIOBJECT_TYPE_LIST ObjectTypeList,
  736. IN size_t ObjectTypeListLength,
  737. OUT PULONG ReturnedIndex
  738. )
  739. /*++
  740. Routine Description:
  741. This routine searches an ObjectTypeList to determine if the specified
  742. object type is in the list.
  743. Arguments:
  744. ObjectType - Object Type to search for.
  745. ObjectTypeList - The object type list to search.
  746. ObjectTypeListLength - Number of elements in ObjectTypeList
  747. ReturnedIndex - Index to the element ObjectType was found in
  748. Return Value:
  749. TRUE: ObjectType was found in list.
  750. FALSE: ObjectType was not found in list.
  751. --*/
  752. {
  753. if ( !ObjectType || !ObjectTypeList )
  754. return FALSE;
  755. _TRACE (1, L"Entering SepObjectInTypeList\n");
  756. BOOLEAN bRVal = FALSE;
  757. GUID* LocalObjectType = 0;
  758. #if DBG
  759. HRESULT hr = S_OK;
  760. GUID_TYPE* pType = 0;
  761. wstring strClassName1;
  762. hr = _Module.GetClassFromGUID (*ObjectType, strClassName1, pType);
  763. ASSERT (SUCCEEDED (hr));
  764. #endif
  765. #pragma warning (disable : 4127)
  766. ASSERT( sizeof(GUID) == sizeof(ULONG) * 4 );
  767. #pragma warning (default : 4127)
  768. for (ULONG Index = 0; Index < ObjectTypeListLength; Index++)
  769. {
  770. LocalObjectType = &ObjectTypeList[Index].ObjectType;
  771. #if DBG
  772. wstring strClassName2;
  773. hr = _Module.GetClassFromGUID (*LocalObjectType, strClassName2, pType);
  774. ASSERT (SUCCEEDED (hr));
  775. _TRACE (0, L"\tComparing %s to %s\n", strClassName1.c_str (), strClassName2.c_str ());
  776. #endif
  777. if ( RtlpIsEqualGuid( ObjectType, LocalObjectType ) )
  778. {
  779. *ReturnedIndex = Index;
  780. bRVal = TRUE;
  781. break;
  782. }
  783. }
  784. _TRACE (-1, L"Leaving SepObjectInTypeList: %s\n", bRVal ? L"TRUE" : L"FALSE");
  785. return bRVal;
  786. }
  787. HRESULT
  788. SepUpdateParentTypeList (
  789. IN PIOBJECT_TYPE_LIST ObjectTypeList,
  790. IN size_t ObjectTypeListLength,
  791. IN ULONG StartIndex,
  792. PSID grantingSid
  793. )
  794. /*++
  795. Routine Description:
  796. Update the Access fields of the parent object of the specified object.
  797. The "remaining" field of a parent object is the logical OR of
  798. the remaining field of all of its children.
  799. The CurrentGranted field of the parent is the collection of bits
  800. granted to every one of its children..
  801. The CurrentDenied fields of the parent is the logical OR of
  802. the bits denied to any of its children.
  803. This routine takes an index to one of the children and updates the
  804. remaining field of the parent (and grandparents recursively).
  805. Arguments:
  806. ObjectTypeList - The object type list to update.
  807. ObjectTypeListLength - Number of elements in ObjectTypeList
  808. StartIndex - Index to the "child" element whose parents are to be updated.
  809. Return Value:
  810. None.
  811. --*/
  812. {
  813. if ( !ObjectTypeList )
  814. return E_POINTER;
  815. if ( !IsValidSid (grantingSid) )
  816. return E_INVALIDARG;
  817. _TRACE (1, L"Entering SepUpdateParentTypeList\n");
  818. ACCESS_MASK NewRemaining = 0;
  819. ACCESS_MASK NewCurrentGranted = 0xFFFFFFFF;
  820. ACCESS_MASK NewCurrentDenied = 0;
  821. HRESULT hr = S_OK;
  822. //
  823. // If the target node is at the root,
  824. // we're all done.
  825. //
  826. if ( ObjectTypeList[StartIndex].ParentIndex == -1 )
  827. {
  828. return hr;
  829. }
  830. //
  831. // Get the index to the parent that needs updating and the level of
  832. // the siblings.
  833. //
  834. ULONG ParentIndex = ObjectTypeList[StartIndex].ParentIndex;
  835. ULONG Level = ObjectTypeList[StartIndex].Level;
  836. //
  837. // Loop through all the children.
  838. //
  839. for (UINT Index=ParentIndex+1; Index<ObjectTypeListLength; Index++ )
  840. {
  841. //
  842. // By definition, the children of an object are all those entries
  843. // immediately following the target. The list of children (or
  844. // grandchildren) stops as soon as we reach an entry the has the
  845. // same level as the target (a sibling) or lower than the target
  846. // (an uncle).
  847. //
  848. if ( ObjectTypeList[Index].Level <= ObjectTypeList[ParentIndex].Level )
  849. {
  850. break;
  851. }
  852. //
  853. // Only handle direct children of the parent.
  854. //
  855. if ( ObjectTypeList[Index].Level != Level )
  856. {
  857. continue;
  858. }
  859. //
  860. // Compute the new bits for the parent.
  861. //
  862. NewRemaining |= ObjectTypeList[Index].Remaining;
  863. NewCurrentGranted &= ObjectTypeList[Index].CurrentGranted;
  864. NewCurrentDenied |= ObjectTypeList[Index].CurrentDenied;
  865. }
  866. //
  867. // If we've not changed the access to the parent,
  868. // we're done.
  869. //
  870. if ( NewRemaining == ObjectTypeList[ParentIndex].Remaining &&
  871. NewCurrentGranted == ObjectTypeList[ParentIndex].CurrentGranted &&
  872. NewCurrentDenied == ObjectTypeList[ParentIndex].CurrentDenied )
  873. {
  874. return hr;
  875. }
  876. //
  877. // Change the parent.
  878. //
  879. hr = SetGrantingSid (
  880. ObjectTypeList[ParentIndex],
  881. UpdateRemaining,
  882. ObjectTypeList[ParentIndex].Remaining,
  883. NewRemaining,
  884. grantingSid);
  885. ObjectTypeList[ParentIndex].Remaining = NewRemaining;
  886. hr = SetGrantingSid (
  887. ObjectTypeList[ParentIndex],
  888. UpdateCurrentGranted,
  889. ObjectTypeList[ParentIndex].CurrentGranted,
  890. NewCurrentGranted,
  891. grantingSid);
  892. ObjectTypeList[ParentIndex].CurrentGranted = NewCurrentGranted;
  893. hr = SetGrantingSid (
  894. ObjectTypeList[ParentIndex],
  895. UpdateCurrentDenied,
  896. ObjectTypeList[ParentIndex].CurrentDenied,
  897. NewCurrentDenied,
  898. grantingSid);
  899. ObjectTypeList[ParentIndex].CurrentDenied = NewCurrentDenied;
  900. //
  901. // Go update the grand parents.
  902. //
  903. hr = SepUpdateParentTypeList( ObjectTypeList,
  904. ObjectTypeListLength,
  905. ParentIndex,
  906. grantingSid);
  907. _TRACE (-1, L"Leaving SepUpdateParentTypeList\n");
  908. return hr;
  909. }
  910. PSID AllocAndCopySid (PSID pSid)
  911. {
  912. if ( !pSid )
  913. return 0;
  914. DWORD dwSidLen = GetLengthSid (pSid);
  915. PSID pSidCopy = CoTaskMemAlloc (dwSidLen);
  916. if ( pSidCopy )
  917. {
  918. if ( CopySid (dwSidLen, pSidCopy, pSid) )
  919. {
  920. ASSERT (IsValidSid (pSidCopy));
  921. }
  922. }
  923. return pSidCopy;
  924. }
  925. HRESULT SetGrantingSid (
  926. IOBJECT_TYPE_LIST& ObjectTypeItem,
  927. ACCESS_MASK_FIELD_TO_UPDATE FieldToUpdate,
  928. ACCESS_MASK oldAccessBits,
  929. ACCESS_MASK newAccessBits,
  930. PSID grantingSid)
  931. {
  932. if ( !IsValidSid (grantingSid) )
  933. return E_INVALIDARG;
  934. HRESULT hr = S_OK;
  935. UINT nSid = 0;
  936. for (ULONG nBit = 0x1; nBit; nBit <<= 1, nSid++)
  937. {
  938. if ( (newAccessBits & nBit) &&
  939. !(oldAccessBits & nBit) )
  940. {
  941. switch (FieldToUpdate)
  942. {
  943. case UpdateCurrentGranted:
  944. if ( !ObjectTypeItem.grantingSid[nSid] )
  945. {
  946. ObjectTypeItem.grantingSid[nSid] = AllocAndCopySid (grantingSid);
  947. if ( !ObjectTypeItem.grantingSid[nSid] )
  948. hr = E_OUTOFMEMORY;
  949. break;
  950. }
  951. break;
  952. case UpdateCurrentDenied:
  953. if ( !ObjectTypeItem.denyingSid[nSid] )
  954. {
  955. ObjectTypeItem.denyingSid[nSid] = AllocAndCopySid (grantingSid);
  956. if ( !ObjectTypeItem.denyingSid[nSid] )
  957. hr = E_OUTOFMEMORY;
  958. break;
  959. }
  960. break;
  961. case UpdateRemaining:
  962. break;
  963. default:
  964. break;
  965. }
  966. }
  967. }
  968. return hr;
  969. }