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.

186 lines
5.3 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: exnc.cpp
  8. //
  9. // Specific Non-Canonical Test
  10. //
  11. // Test if a Security Descriptor contains an ACL with non-Canonical ACEs
  12. //
  13. // Created by: Marcelo Calbucci (MCalbu)
  14. // June 23rd, 1999.
  15. //
  16. //--------------------------------------------------------------------------
  17. #include "pch.h"
  18. extern "C" {
  19. #include <seopaque.h> // RtlObjectAceSid, etc.
  20. }
  21. #include "exnc.h"
  22. static const GUID guidMember = NT_RIGHT_MEMBER;
  23. //
  24. // ENCCompareSids
  25. // Compare if pSid is the same SID inside pAce.
  26. //
  27. BOOL ENCCompareSids(PSID pSid, PACE_HEADER pAce)
  28. {
  29. if (!pAce)
  30. return FALSE;
  31. PSID pSid2 = NULL;
  32. switch (pAce->AceType)
  33. {
  34. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  35. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  36. pSid2 = RtlObjectAceSid(pAce);
  37. break;
  38. case ACCESS_ALLOWED_ACE_TYPE:
  39. case ACCESS_DENIED_ACE_TYPE:
  40. pSid2 = (PSID)&((PKNOWN_ACE)pAce)->SidStart;
  41. break;
  42. default:
  43. return FALSE;
  44. }
  45. return (pSid && pSid2 && EqualSid(pSid, pSid2));
  46. }
  47. //
  48. // IsSpecificNonCanonicalSD
  49. // This function verifies if the Security Descriptor (*pSD) it is or not in the
  50. // specific non-canonical format.
  51. // Parameters:
  52. // pSD: The Security Descriptor to be analyzed
  53. // Result:
  54. // ENC_RESULT_NOT_PRESENT: This is not a Specific Non-Canonical SD.
  55. // (It still can be a Canonical SD)
  56. // ENC_RESULT_HIDEMEMBER : We have the Non-Canonical part referent to HideMembership
  57. // ENC_RESULT_HIDEOBJECT : We have the Non-Canonical part referent to HideFromAB
  58. // ENC_RESULT_ALL : We have both Non-Canonical parts, HideMembership and HideFromAB
  59. //
  60. DWORD IsSpecificNonCanonicalSD(PSECURITY_DESCRIPTOR pSD)
  61. {
  62. // Check the Security Descriptor
  63. if(pSD==NULL)
  64. return FALSE;
  65. if(!IsValidSecurityDescriptor(pSD))
  66. return FALSE;
  67. // Get and Check the DACL
  68. PACL pDacl = NULL;
  69. BOOL fDaclPresent, fDaclDefaulted;
  70. if(!GetSecurityDescriptorDacl(pSD, &fDaclPresent, &pDacl, &fDaclDefaulted))
  71. return FALSE;
  72. if(!fDaclPresent)
  73. return FALSE;
  74. if(!pDacl)
  75. return FALSE;
  76. // Do a lazy evaluation:
  77. // If we have less than 4 ACEs, this is not a Specific Non-Canonical ACL
  78. if (pDacl->AceCount < 4)
  79. return FALSE;
  80. //
  81. // Check if the "member" or "list object" are in the Non-Canonical format
  82. //
  83. // Info (flags): Count how many alloweds we have
  84. DWORD dwInfoMember = 0;
  85. DWORD dwInfoListObject = 0;
  86. // Get the Sids...
  87. SID sidEveryone; // SID contains 1 subauthority, which is enough
  88. // -1 = Unknown
  89. // 0 = Not Present
  90. // 1 = Present
  91. int iMemberResult = -1;
  92. int iListObjectResult = -1;
  93. // # Everyone
  94. SID_IDENTIFIER_AUTHORITY siaNtAuthority1 = SECURITY_WORLD_SID_AUTHORITY;
  95. InitializeSid(&sidEveryone, &siaNtAuthority1, 1);
  96. *(GetSidSubAuthority(&sidEveryone, 0)) = SECURITY_WORLD_RID;
  97. DWORD dwCurAce;
  98. PACE_HEADER pAce;
  99. for (dwCurAce = 0, pAce = (PACE_HEADER)FirstAce(pDacl);
  100. dwCurAce < pDacl->AceCount;
  101. dwCurAce++, pAce = (PACE_HEADER)NextAce(pAce))
  102. {
  103. // Test the "member"
  104. if (-1 == iMemberResult && IsObjectAceType(pAce))
  105. {
  106. const GUID *pObjectType = RtlObjectAceObjectType(pAce);
  107. if (pObjectType && (guidMember == *pObjectType))
  108. {
  109. switch(pAce->AceType)
  110. {
  111. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  112. dwInfoMember++;
  113. break;
  114. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  115. if (ENCCompareSids(&sidEveryone, pAce))
  116. {
  117. if (dwInfoMember >= ENC_MINIMUM_ALLOWED)
  118. iMemberResult = 1;
  119. else
  120. iMemberResult = 0;
  121. if (-1 != iListObjectResult)
  122. dwCurAce = pDacl->AceCount; // Quit the loop
  123. }
  124. break;
  125. }
  126. }
  127. }
  128. // Test the "list object"
  129. if (-1 == iListObjectResult &&
  130. ACTRL_DS_LIST_OBJECT == ((PKNOWN_ACE)pAce)->Mask)
  131. {
  132. switch(pAce->AceType)
  133. {
  134. case ACCESS_ALLOWED_ACE_TYPE:
  135. dwInfoListObject++;
  136. break;
  137. case ACCESS_DENIED_ACE_TYPE:
  138. if (ENCCompareSids(&sidEveryone, pAce))
  139. {
  140. if (dwInfoListObject >= ENC_MINIMUM_ALLOWED)
  141. iListObjectResult = 1;
  142. else
  143. iListObjectResult = 0;
  144. if (-1 != iMemberResult)
  145. dwCurAce = pDacl->AceCount; // Quit the loop
  146. }
  147. break;
  148. }
  149. }
  150. }
  151. DWORD dwResult = 0;
  152. if (iMemberResult == 1)
  153. dwResult |= ENC_RESULT_HIDEMEMBER;
  154. if (iListObjectResult == 1)
  155. dwResult |= ENC_RESULT_HIDEOBJECT;
  156. return dwResult;
  157. }