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.

286 lines
9.5 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: DumpSecInfo.cpp
  4. //
  5. // Module: as required
  6. //
  7. // Synopsis: Functions to help figure out Permissions issues. To fix "NULL DACL"
  8. // security issues, or try and figure out permissions bugs, this module
  9. // may be useful. Entry point is DumpAclInfo.
  10. //
  11. // Copyright (c) 1998-2001 Microsoft Corporation
  12. //
  13. // Author: SumitC Created 18-Dec-2000
  14. //
  15. //+----------------------------------------------------------------------------
  16. #include "winbase.h"
  17. #include "sddl.h"
  18. //
  19. // support for dynamically loading Advapi32 Security functions
  20. //
  21. HMODULE g_hAdvapi32 = NULL;
  22. typedef BOOL (WINAPI *pfnLookupAccountSid) (LPCWSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE);
  23. typedef BOOL (WINAPI *pfnGetUserObjectSecurity) (HANDLE, PSECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
  24. typedef BOOL (WINAPI *pfnConvertSidToStringSid) (PSID, LPWSTR*);
  25. typedef BOOL (WINAPI *pfnGetSecurityDescriptorOwner) (PSECURITY_DESCRIPTOR, PSID *, LPBOOL);
  26. typedef BOOL (WINAPI *pfnGetSecurityDescriptorSacl) (PSECURITY_DESCRIPTOR, LPBOOL, PACL *, LPBOOL);
  27. typedef BOOL (WINAPI *pfnGetSecurityDescriptorDacl) (PSECURITY_DESCRIPTOR, LPBOOL, PACL *, LPBOOL);
  28. typedef BOOL (WINAPI *pfnGetAce) (PACL, DWORD, LPVOID *);
  29. pfnLookupAccountSid g_pfnLookupAccountSid = NULL;
  30. pfnGetUserObjectSecurity g_pfnGetUserObjectSecurity = NULL;
  31. pfnConvertSidToStringSid g_pfnConvertSidToStringSid = NULL;
  32. pfnGetSecurityDescriptorOwner g_pfnGetSecurityDescriptorOwner = NULL;
  33. pfnGetSecurityDescriptorSacl g_pfnGetSecurityDescriptorSacl = NULL;
  34. pfnGetSecurityDescriptorDacl g_pfnGetSecurityDescriptorDacl = NULL;
  35. pfnGetAce g_pfnGetAce = NULL;
  36. //+----------------------------------------------------------------------------
  37. //
  38. // Function: GetSidType
  39. //
  40. // Synopsis: Returns the string corresponding to a given SID type
  41. //
  42. // Arguments: [i] -- index representing the SID
  43. //
  44. // Returns: LPTSTR - static string containing a displayable Sid type
  45. //
  46. // Notes:
  47. //
  48. //-----------------------------------------------------------------------------
  49. LPTSTR GetSidType(int i)
  50. {
  51. static LPTSTR szMap[] =
  52. {
  53. TEXT("User"),
  54. TEXT("Group"),
  55. TEXT("Domain"),
  56. TEXT("Alias"),
  57. TEXT("WellKnownGroup"),
  58. TEXT("DeletedAccount"),
  59. TEXT("Invalid"),
  60. TEXT("Unknown"),
  61. TEXT("Computer")
  62. };
  63. if (i >= 1 && i <= 9)
  64. {
  65. return szMap[i - 1];
  66. }
  67. else
  68. {
  69. return TEXT("");
  70. }
  71. }
  72. //+----------------------------------------------------------------------------
  73. //
  74. // Function: DumpSid
  75. //
  76. // Synopsis: returns information for a give SID
  77. //
  78. // Arguments: [psid] -- ptr to SecurityID
  79. // [pszBuffer] -- where to return SID string (caller must free)
  80. //
  81. // Returns: LPTSTR - ptr to pszBuffer if success, NULL if failure
  82. //
  83. // Notes:
  84. //
  85. //-----------------------------------------------------------------------------
  86. LPTSTR DumpSid(PSID psid, LPTSTR pszBuffer)
  87. {
  88. LPTSTR pszSID = NULL;
  89. TCHAR szName[MAX_PATH + 1];
  90. DWORD cbName = MAX_PATH;
  91. TCHAR szDomain[MAX_PATH + 1];
  92. DWORD cbDomain = MAX_PATH;
  93. SID_NAME_USE snu;
  94. BOOL fDone = FALSE;
  95. CMASSERTMSG(pszBuffer, TEXT("DumpSid - pszBuffer must be allocated by caller"));
  96. if (g_pfnConvertSidToStringSid(psid, &pszSID) &&
  97. g_pfnLookupAccountSid(NULL, psid, szName, &cbName, szDomain, &cbDomain, &snu))
  98. {
  99. wsprintf(pszBuffer, TEXT("%s\\%s %s %s"), szDomain, szName, GetSidType(snu), pszSID);
  100. // looks like NTDEV\sumitc User xxxx-xxx-xxx-xxx
  101. fDone = TRUE;
  102. }
  103. if (pszSID)
  104. {
  105. LocalFree(pszSID);
  106. }
  107. return fDone ? pszBuffer : NULL;
  108. }
  109. //+----------------------------------------------------------------------------
  110. //
  111. // Function: DumpAclInfo
  112. //
  113. // Synopsis: Dumps out all ACL info for a given object
  114. //
  115. // Arguments: [h] -- handle to object about which info is needed
  116. //
  117. // Returns: (void)
  118. //
  119. // Notes:
  120. //
  121. //-----------------------------------------------------------------------------
  122. void DumpAclInfo(HANDLE h)
  123. {
  124. if (!OS_NT)
  125. {
  126. CMTRACE(TEXT("DumpAclInfo will not work on 9x systems"));
  127. return;
  128. }
  129. TCHAR szBuf[MAX_PATH];
  130. SECURITY_INFORMATION si = 0;
  131. //
  132. // dynamically pick up the DLLs we need
  133. //
  134. g_hAdvapi32 = LoadLibrary(TEXT("ADVAPI32.DLL"));
  135. if (NULL == g_hAdvapi32)
  136. {
  137. CMTRACE(TEXT("DumpAclInfo: failed to load advapi32.dll"));
  138. return;
  139. }
  140. g_pfnLookupAccountSid = (pfnLookupAccountSid) GetProcAddress(g_hAdvapi32, "LookupAccountSidW");
  141. g_pfnGetUserObjectSecurity = (pfnGetUserObjectSecurity) GetProcAddress(g_hAdvapi32, "GetUserObjectSecurity");
  142. g_pfnConvertSidToStringSid = (pfnConvertSidToStringSid) GetProcAddress(g_hAdvapi32, "ConvertSidToStringSidW");
  143. g_pfnGetSecurityDescriptorOwner = (pfnGetSecurityDescriptorOwner) GetProcAddress(g_hAdvapi32, "GetSecurityDescriptorOwner");
  144. g_pfnGetSecurityDescriptorSacl = (pfnGetSecurityDescriptorSacl) GetProcAddress(g_hAdvapi32, "GetSecurityDescriptorSacl");
  145. g_pfnGetSecurityDescriptorDacl = (pfnGetSecurityDescriptorDacl) GetProcAddress(g_hAdvapi32, "GetSecurityDescriptorDacl");
  146. g_pfnGetAce = (pfnGetAce) GetProcAddress(g_hAdvapi32, "GetAce");
  147. if (!(g_pfnLookupAccountSid && g_pfnGetUserObjectSecurity &&
  148. g_pfnConvertSidToStringSid && g_pfnGetSecurityDescriptorOwner &&
  149. g_pfnGetSecurityDescriptorSacl && g_pfnGetSecurityDescriptorDacl &&
  150. g_pfnGetAce))
  151. {
  152. CMTRACE(TEXT("DumpAclInfo: failed to load required functions in advapi32.dll"));
  153. goto Cleanup;
  154. }
  155. //
  156. // dump information on the ACL
  157. //
  158. DWORD dw;
  159. si |= OWNER_SECURITY_INFORMATION;
  160. si |= DACL_SECURITY_INFORMATION;
  161. if (!g_pfnGetUserObjectSecurity(h, &si, NULL, 0, &dw) &&
  162. ERROR_INSUFFICIENT_BUFFER == GetLastError())
  163. {
  164. PSECURITY_DESCRIPTOR pSD = NULL;
  165. pSD = (PSECURITY_DESCRIPTOR) CmMalloc(dw);
  166. if (g_pfnGetUserObjectSecurity(h, &si, pSD, dw, &dw))
  167. {
  168. // get the owner
  169. PSID psidOwner;
  170. BOOL fDefaulted;
  171. if (g_pfnGetSecurityDescriptorOwner(pSD, &psidOwner, &fDefaulted))
  172. {
  173. CMTRACE1(TEXT("SIDINFO: Owner is: %s"), DumpSid(psidOwner, szBuf));
  174. }
  175. PACL pacl;
  176. BOOL fPresent;
  177. int i;
  178. g_pfnGetSecurityDescriptorSacl(pSD, &fPresent, &pacl, &fDefaulted);
  179. CMTRACE1(TEXT("sacl gle=%d"), GetLastError());
  180. if (fPresent)
  181. {
  182. CMTRACE(TEXT("SIDINFO: found a SACL"));
  183. // has a SACL
  184. void * pv;
  185. for (i = 0 ; i < 15; ++i)
  186. {
  187. if (g_pfnGetAce(pacl, i, &pv))
  188. {
  189. // try access allowed ace
  190. //
  191. ACCESS_ALLOWED_ACE * pACE = (ACCESS_ALLOWED_ACE *)pv;
  192. if (pACE->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
  193. {
  194. CMTRACE1(TEXT("SIDINFO: allowed is: %s"), DumpSid(&(pACE->SidStart), szBuf));
  195. }
  196. else
  197. {
  198. ACCESS_DENIED_ACE * pACE = (ACCESS_DENIED_ACE *)pv;
  199. if (pACE->Header.AceType == ACCESS_DENIED_ACE_TYPE)
  200. {
  201. CMTRACE1(TEXT("SIDINFO: denied is: %s"), DumpSid(&(pACE->SidStart), szBuf));
  202. }
  203. }
  204. }
  205. }
  206. }
  207. g_pfnGetSecurityDescriptorDacl(pSD, &fPresent, &pacl, &fDefaulted);
  208. CMTRACE1(TEXT("dacl gle=%d"), GetLastError());
  209. if (fPresent)
  210. {
  211. CMTRACE(TEXT("SIDINFO: found a DACL"));
  212. // has a DACL
  213. void * pv;
  214. for (i = 0 ; i < 15; ++i)
  215. {
  216. if (g_pfnGetAce(pacl, i, &pv))
  217. {
  218. // try access allowed ace
  219. //
  220. ACCESS_ALLOWED_ACE * pACE = (ACCESS_ALLOWED_ACE *)pv;
  221. if (pACE->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
  222. {
  223. CMTRACE1(TEXT("SIDINFO: allowed is: %s"), DumpSid(&(pACE->SidStart), szBuf));
  224. }
  225. else
  226. {
  227. ACCESS_DENIED_ACE * pACE = (ACCESS_DENIED_ACE *)pv;
  228. if (pACE->Header.AceType == ACCESS_DENIED_ACE_TYPE)
  229. {
  230. CMTRACE1(TEXT("SIDINFO: denied is: %s"), DumpSid(&(pACE->SidStart), szBuf));
  231. }
  232. }
  233. }
  234. }
  235. }
  236. }
  237. CmFree(pSD);
  238. }
  239. Cleanup:
  240. if (g_hAdvapi32)
  241. {
  242. FreeLibrary(g_hAdvapi32);
  243. g_hAdvapi32 = NULL;
  244. g_pfnLookupAccountSid = NULL;
  245. g_pfnGetUserObjectSecurity = NULL;
  246. g_pfnConvertSidToStringSid = NULL;
  247. g_pfnGetSecurityDescriptorOwner = NULL;
  248. g_pfnGetSecurityDescriptorSacl = NULL;
  249. g_pfnGetSecurityDescriptorDacl = NULL;
  250. g_pfnGetAce = NULL;
  251. }
  252. }