//+---------------------------------------------------------------------------- // // File: DumpSecInfo.cpp // // Module: as required // // Synopsis: Functions to help figure out Permissions issues. To fix "NULL DACL" // security issues, or try and figure out permissions bugs, this module // may be useful. Entry point is DumpAclInfo. // // Copyright (c) 1998-2001 Microsoft Corporation // // Author: SumitC Created 18-Dec-2000 // //+---------------------------------------------------------------------------- #include "winbase.h" #include "sddl.h" // // support for dynamically loading Advapi32 Security functions // HMODULE g_hAdvapi32 = NULL; typedef BOOL (WINAPI *pfnLookupAccountSid) (LPCWSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE); typedef BOOL (WINAPI *pfnGetUserObjectSecurity) (HANDLE, PSECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD); typedef BOOL (WINAPI *pfnConvertSidToStringSid) (PSID, LPWSTR*); typedef BOOL (WINAPI *pfnGetSecurityDescriptorOwner) (PSECURITY_DESCRIPTOR, PSID *, LPBOOL); typedef BOOL (WINAPI *pfnGetSecurityDescriptorSacl) (PSECURITY_DESCRIPTOR, LPBOOL, PACL *, LPBOOL); typedef BOOL (WINAPI *pfnGetSecurityDescriptorDacl) (PSECURITY_DESCRIPTOR, LPBOOL, PACL *, LPBOOL); typedef BOOL (WINAPI *pfnGetAce) (PACL, DWORD, LPVOID *); pfnLookupAccountSid g_pfnLookupAccountSid = NULL; pfnGetUserObjectSecurity g_pfnGetUserObjectSecurity = NULL; pfnConvertSidToStringSid g_pfnConvertSidToStringSid = NULL; pfnGetSecurityDescriptorOwner g_pfnGetSecurityDescriptorOwner = NULL; pfnGetSecurityDescriptorSacl g_pfnGetSecurityDescriptorSacl = NULL; pfnGetSecurityDescriptorDacl g_pfnGetSecurityDescriptorDacl = NULL; pfnGetAce g_pfnGetAce = NULL; //+---------------------------------------------------------------------------- // // Function: GetSidType // // Synopsis: Returns the string corresponding to a given SID type // // Arguments: [i] -- index representing the SID // // Returns: LPTSTR - static string containing a displayable Sid type // // Notes: // //----------------------------------------------------------------------------- LPTSTR GetSidType(int i) { static LPTSTR szMap[] = { TEXT("User"), TEXT("Group"), TEXT("Domain"), TEXT("Alias"), TEXT("WellKnownGroup"), TEXT("DeletedAccount"), TEXT("Invalid"), TEXT("Unknown"), TEXT("Computer") }; if (i >= 1 && i <= 9) { return szMap[i - 1]; } else { return TEXT(""); } } //+---------------------------------------------------------------------------- // // Function: DumpSid // // Synopsis: returns information for a give SID // // Arguments: [psid] -- ptr to SecurityID // [pszBuffer] -- where to return SID string (caller must free) // // Returns: LPTSTR - ptr to pszBuffer if success, NULL if failure // // Notes: // //----------------------------------------------------------------------------- LPTSTR DumpSid(PSID psid, LPTSTR pszBuffer) { LPTSTR pszSID = NULL; TCHAR szName[MAX_PATH + 1]; DWORD cbName = MAX_PATH; TCHAR szDomain[MAX_PATH + 1]; DWORD cbDomain = MAX_PATH; SID_NAME_USE snu; BOOL fDone = FALSE; CMASSERTMSG(pszBuffer, TEXT("DumpSid - pszBuffer must be allocated by caller")); if (g_pfnConvertSidToStringSid(psid, &pszSID) && g_pfnLookupAccountSid(NULL, psid, szName, &cbName, szDomain, &cbDomain, &snu)) { wsprintf(pszBuffer, TEXT("%s\\%s %s %s"), szDomain, szName, GetSidType(snu), pszSID); // looks like NTDEV\sumitc User xxxx-xxx-xxx-xxx fDone = TRUE; } if (pszSID) { LocalFree(pszSID); } return fDone ? pszBuffer : NULL; } //+---------------------------------------------------------------------------- // // Function: DumpAclInfo // // Synopsis: Dumps out all ACL info for a given object // // Arguments: [h] -- handle to object about which info is needed // // Returns: (void) // // Notes: // //----------------------------------------------------------------------------- void DumpAclInfo(HANDLE h) { if (!OS_NT) { CMTRACE(TEXT("DumpAclInfo will not work on 9x systems")); return; } TCHAR szBuf[MAX_PATH]; SECURITY_INFORMATION si = 0; // // dynamically pick up the DLLs we need // g_hAdvapi32 = LoadLibrary(TEXT("ADVAPI32.DLL")); if (NULL == g_hAdvapi32) { CMTRACE(TEXT("DumpAclInfo: failed to load advapi32.dll")); return; } g_pfnLookupAccountSid = (pfnLookupAccountSid) GetProcAddress(g_hAdvapi32, "LookupAccountSidW"); g_pfnGetUserObjectSecurity = (pfnGetUserObjectSecurity) GetProcAddress(g_hAdvapi32, "GetUserObjectSecurity"); g_pfnConvertSidToStringSid = (pfnConvertSidToStringSid) GetProcAddress(g_hAdvapi32, "ConvertSidToStringSidW"); g_pfnGetSecurityDescriptorOwner = (pfnGetSecurityDescriptorOwner) GetProcAddress(g_hAdvapi32, "GetSecurityDescriptorOwner"); g_pfnGetSecurityDescriptorSacl = (pfnGetSecurityDescriptorSacl) GetProcAddress(g_hAdvapi32, "GetSecurityDescriptorSacl"); g_pfnGetSecurityDescriptorDacl = (pfnGetSecurityDescriptorDacl) GetProcAddress(g_hAdvapi32, "GetSecurityDescriptorDacl"); g_pfnGetAce = (pfnGetAce) GetProcAddress(g_hAdvapi32, "GetAce"); if (!(g_pfnLookupAccountSid && g_pfnGetUserObjectSecurity && g_pfnConvertSidToStringSid && g_pfnGetSecurityDescriptorOwner && g_pfnGetSecurityDescriptorSacl && g_pfnGetSecurityDescriptorDacl && g_pfnGetAce)) { CMTRACE(TEXT("DumpAclInfo: failed to load required functions in advapi32.dll")); goto Cleanup; } // // dump information on the ACL // DWORD dw; si |= OWNER_SECURITY_INFORMATION; si |= DACL_SECURITY_INFORMATION; if (!g_pfnGetUserObjectSecurity(h, &si, NULL, 0, &dw) && ERROR_INSUFFICIENT_BUFFER == GetLastError()) { PSECURITY_DESCRIPTOR pSD = NULL; pSD = (PSECURITY_DESCRIPTOR) CmMalloc(dw); if (g_pfnGetUserObjectSecurity(h, &si, pSD, dw, &dw)) { // get the owner PSID psidOwner; BOOL fDefaulted; if (g_pfnGetSecurityDescriptorOwner(pSD, &psidOwner, &fDefaulted)) { CMTRACE1(TEXT("SIDINFO: Owner is: %s"), DumpSid(psidOwner, szBuf)); } PACL pacl; BOOL fPresent; int i; g_pfnGetSecurityDescriptorSacl(pSD, &fPresent, &pacl, &fDefaulted); CMTRACE1(TEXT("sacl gle=%d"), GetLastError()); if (fPresent) { CMTRACE(TEXT("SIDINFO: found a SACL")); // has a SACL void * pv; for (i = 0 ; i < 15; ++i) { if (g_pfnGetAce(pacl, i, &pv)) { // try access allowed ace // ACCESS_ALLOWED_ACE * pACE = (ACCESS_ALLOWED_ACE *)pv; if (pACE->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) { CMTRACE1(TEXT("SIDINFO: allowed is: %s"), DumpSid(&(pACE->SidStart), szBuf)); } else { ACCESS_DENIED_ACE * pACE = (ACCESS_DENIED_ACE *)pv; if (pACE->Header.AceType == ACCESS_DENIED_ACE_TYPE) { CMTRACE1(TEXT("SIDINFO: denied is: %s"), DumpSid(&(pACE->SidStart), szBuf)); } } } } } g_pfnGetSecurityDescriptorDacl(pSD, &fPresent, &pacl, &fDefaulted); CMTRACE1(TEXT("dacl gle=%d"), GetLastError()); if (fPresent) { CMTRACE(TEXT("SIDINFO: found a DACL")); // has a DACL void * pv; for (i = 0 ; i < 15; ++i) { if (g_pfnGetAce(pacl, i, &pv)) { // try access allowed ace // ACCESS_ALLOWED_ACE * pACE = (ACCESS_ALLOWED_ACE *)pv; if (pACE->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) { CMTRACE1(TEXT("SIDINFO: allowed is: %s"), DumpSid(&(pACE->SidStart), szBuf)); } else { ACCESS_DENIED_ACE * pACE = (ACCESS_DENIED_ACE *)pv; if (pACE->Header.AceType == ACCESS_DENIED_ACE_TYPE) { CMTRACE1(TEXT("SIDINFO: denied is: %s"), DumpSid(&(pACE->SidStart), szBuf)); } } } } } } CmFree(pSD); } Cleanup: if (g_hAdvapi32) { FreeLibrary(g_hAdvapi32); g_hAdvapi32 = NULL; g_pfnLookupAccountSid = NULL; g_pfnGetUserObjectSecurity = NULL; g_pfnConvertSidToStringSid = NULL; g_pfnGetSecurityDescriptorOwner = NULL; g_pfnGetSecurityDescriptorSacl = NULL; g_pfnGetSecurityDescriptorDacl = NULL; g_pfnGetAce = NULL; } }