int main(int argc, char* argv[]) #endif { if (GetVersion() & 0x80000000) { _tprintf(_T("This application only runs on Windows NT/2000 or later")); return 0; } if (!ParseCommandLine(argc, argv)) return 0; if (g_eat != ExamineAccessTokenNo) { CAccessToken at; if (!at.GetProcessToken(TOKEN_READ | TOKEN_QUERY_SOURCE)) Log(_T("Could not open process token")); else { Log(_T("Process Access Token:")); DumpAccessToken(at); } } for (size_t i=0; i<g_aObjects.GetCount(); i++) { Log(_T("Security Descriptor for object %s:"), (LPCTSTR)g_aObjects[i]); switch (g_eot) { case ExamineObjectTypeDefault: case ExamineObjectTypeFile: DumpSecurityDescriptor(g_aObjects[i], SE_FILE_OBJECT, mapFileAccess); break; case ExamineObjectTypeRegkey: DumpSecurityDescriptor(g_aObjects[i], SE_REGISTRY_KEY, mapRegkeyAccess); break; case ExamineObjectTypeService: DumpSecurityDescriptor(g_aObjects[i], SE_SERVICE, mapServiceAccess); break; case ExamineObjectTypeKernel: DumpSecurityDescriptor(g_aObjects[i], SE_KERNEL_OBJECT, mapKernelAccess); break; case ExamineObjectTypePrinter: DumpSecurityDescriptor(g_aObjects[i], SE_PRINTER, mapPrinterAccess); break; default: ATLASSERT(FALSE); } } return 0; }
void DumpSecurityDescriptor(LPCTSTR szObject, SE_OBJECT_TYPE type, Mapping* pAccessMappings) { CSecurityDesc sd; SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION; if (!AtlGetSecurityDescriptor(szObject, type, &sd)) { CIndent scope; si = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; if (!AtlGetSecurityDescriptor(szObject, type, &sd, si)) { Log(_T("Could not retrieve security descriptor")); return; } Log(_T("Could not retrieve SACL")); } DumpSecurityDescriptor(sd, si, pAccessMappings); }
STDMETHODIMP CObjSecurity::SetSecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR pSD) { if(!::IsValidSecurityDescriptor(pSD)) { return E_POINTER; } DWORD dwErr = 0; PSECURITY_DESCRIPTOR pParentSD = NULL; if (mp_NewSD) { LocalFree(mp_NewSD); mp_NewSD = NULL; } if (mhk_ParentRead != NULL) { dwErr = mp_Worker->GetKeySecurity(mhk_ParentRead, DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION, &pParentSD); } dwErr = CreateNewDescriptor(m_pOrigSD, // Old pParentSD, // Used for inheritance calculation, may be NULL si, pSD, // Changed (it must be merged with Old) &mp_NewSD, &m_SI); // Resultant if ((dwErr == 0) && (mhk_Write != NULL)) { //dwErr = SetKeySecurityWindows(mhk_Write, m_SI, mp_NewSD); dwErr = mp_Worker->SetKeySecurity(mhk_Write, m_SI, mp_NewSD); // сразу чистим дескриптор, независимо от того "успешно или нет" LocalFree(mp_NewSD); mp_NewSD = NULL; } if (pParentSD) LocalFree(pParentSD); return HRESULT_FROM_WIN32(dwErr); #if 0 TCHAR szDbgLabel[64]; wsprintf(szDbgLabel, _T("CObjSecurity::SetSecurity(0x%X)"), si); DumpSecurityDescriptor(pSD, si, szDbgLabel); PSID pNewOwner = NULL; BOOL lbOwnerDefaulted = FALSE; TRUSTEE *ptNewOwner = NULL, NewOwner = {NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_UNKNOWN}; if (!dwErr && (si & OWNER_SECURITY_INFORMATION)) { if (::GetSecurityDescriptorOwner(pSD, &pNewOwner, &lbOwnerDefaulted)) { NewOwner.ptstrName = (LPTSTR)pNewOwner; ptNewOwner = &NewOwner; } else dwErr = GetLastError(); } PSID pNewGroup = NULL; BOOL lbGroupDefaulted = FALSE; TRUSTEE *ptNewGroup = NULL, NewGroup = {NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_UNKNOWN}; if (!dwErr && (si & GROUP_SECURITY_INFORMATION)) { if (::GetSecurityDescriptorGroup(pSD, &pNewGroup, &lbGroupDefaulted)) { NewGroup.ptstrName = (LPTSTR)pNewGroup; ptNewGroup = &NewGroup; } else dwErr = GetLastError(); } PACL pNewDacl = NULL; BOOL lbDacl = FALSE, lbDaclDefaulted = FALSE; ULONG nDaclCount = 0; PEXPLICIT_ACCESS pDaclEntries = NULL; if (!dwErr && (si & DACL_SECURITY_INFORMATION)) { if (::GetSecurityDescriptorDacl(pSD, &lbDacl, &pNewDacl, &lbDaclDefaulted)) { dwErr = ::GetExplicitEntriesFromAcl(pNewDacl, &nDaclCount, &pDaclEntries); } else dwErr = GetLastError(); } PACL pNewSacl = NULL; BOOL lbSacl = FALSE, lbSaclDefaulted = FALSE; ULONG nSaclCount = 0; PEXPLICIT_ACCESS pSaclEntries = NULL; if (!dwErr && (si & SACL_SECURITY_INFORMATION)) { if (::GetSecurityDescriptorSacl(pSD, &lbSacl, &pNewSacl, &lbSaclDefaulted)) { dwErr = ::GetExplicitEntriesFromAcl(pNewSacl, &nSaclCount, &pSaclEntries); } else dwErr = GetLastError(); } PSECURITY_DESCRIPTOR pNewSD = NULL; ULONG nNewSize = 0; BOOL lbRc = FALSE; if (dwErr == 0) dwErr = BuildSecurityDescriptor(ptNewOwner, ptNewGroup, nDaclCount, pDaclEntries, nSaclCount, pSaclEntries, m_pOrigSD/*self-relative!*/, &nNewSize, &pNewSD); if (dwErr == 0) { DumpSecurityDescriptor(pNewSD, OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION, _T("After BuildSecurityDescriptor")); if (pNewOwner) { if (!::SetSecurityDescriptorOwner(pNewSD, pNewOwner, lbOwnerDefaulted)) dwErr = GetLastError(); else DumpSecurityDescriptor(pNewSD, OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION, _T("After SetSecurityDescriptorOwner")); } if (dwErr != 0) LocalFree(pNewSD); else { if (mp_NewSD) LocalFree(mp_NewSD); mp_NewSD = pNewSD; m_SI = si; } } else dwErr = GetLastError(); //BOOL lb1 = IsValidSecurityDescriptor((PSECURITY_DESCRIPTOR)m_ppSD); //BOOL lb2 = IsValidSecurityDescriptor(*m_ppSD); //DumpSecurityDescriptor(*m_ppSD, OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, _T("Stored descriptor pointer")); //WARNING("BuildSecurityDescriptor"); //// она корректно выполнит //// builds the new security descriptor by merging the specified owner, group, access control, //// and audit-control information with the information in this security descriptor //// Наверное вообще не нужно со строками заморачиваться - сразу звать Build из SetSecurity. //// Ведь в m_pSD(новая!) уже лежит наша копия дескриптора. //// Ест-но в SetSecurity нужно проверить, что вернулось - если Absolute - звать MakeSelfRelativeSD //WARNING("Сделать OR на новую переменную масок - что юзер поменял"); // //if (si & DACL_SECURITY_INFORMATION) //{ // if (mp_DaclSD) // { // LocalFree(mp_DaclSD); // mp_DaclSD = NULL; // } // if (mpsz_DaclSD) // { // LocalFree(mpsz_DaclSD); // mpsz_DaclSD = NULL; // } // ULONG nLen = 0; // if (!ConvertSecurityDescriptorToStringSecurityDescriptor(pSD, SDDL_REVISION_1, DACL_SECURITY_INFORMATION, // &mpsz_DaclSD, &nLen)) // dwErr = GetLastError(); //} //if (si & OWNER_SECURITY_INFORMATION) //{ // if (mp_OwnerSD) // { // LocalFree(mp_OwnerSD); // mp_OwnerSD = NULL; // } // if (mpsz_OwnerSD) // { // LocalFree(mpsz_OwnerSD); // mpsz_OwnerSD = NULL; // } // ULONG nLen = 0; // if (!ConvertSecurityDescriptorToStringSecurityDescriptor(pSD, SDDL_REVISION_1, OWNER_SECURITY_INFORMATION, // &mpsz_OwnerSD, &nLen)) // dwErr = GetLastError(); // //DWORD nLen = GetSecurityDescriptorLength(pSD); // //if (nLen) // //{ // // mp_OwnerSD = LocalAlloc(LPTR, nLen); // // if (mp_OwnerSD) // // memmove(mp_OwnerSD, pSD, nLen); // //} // //else // //{ // // mp_OwnerSD = NULL; // //} // //PSID pOwner = NULL; BOOL lbOwnerDefaulted = FALSE; // //if (GetSecurityDescriptorOwner(pSD, &pOwner, &lbOwnerDefaulted)) // //{ // // if (SetSecurityDescriptorOwner(*m_ppSD, pOwner, lbOwnerDefaulted)) // // { // // DumpSecurityDescriptor(pSD, si, _T("CObjSecurity::SetSecurity Applied")); // // } // // else // // { // // dwErr = GetLastError(); // // } // //} // //else // //{ // // dwErr = GetLastError(); // //} //} #ifdef APPLY_SECURITY_TO_REG // // Assume that required privileges have already been enabled // //if (!SetPrivateObjectSecurity(si, pSD, m_ppSD, &ObjMap, mh_Token)) // dwErr = GetLastError(); if (mpsz_KeyPath && *mpsz_KeyPath) { HKEY hk; dwErr = RegOpenKeyExW(mhk_Root, mpsz_KeyPath, 0, mdw_RegFlags, &hk); if (dwErr == 0) { dwErr = RegSetKeySecurity(hk, DACL_SECURITY_INFORMATION, pSD); RegCloseKey(hk); } } else { dwErr = RegSetKeySecurity(mhk_Root, DACL_SECURITY_INFORMATION, pSD); } if (dwErr == 0) { DWORD dwLength = 0; // // Assume that required privileges have already been enabled // GetPrivateObjectSecurity(pSD, DACL_SECURITY_INFORMATION, NULL, 0, &dwLength); if (dwLength) { PSECURITY_DESCRIPTOR pNewSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwLength); if (pNewSD && !GetPrivateObjectSecurity(pSD, DACL_SECURITY_INFORMATION, pNewSD, dwLength, &dwLength)) { dwErr = GetLastError(); LocalFree(pNewSD); pNewSD = NULL; } else { LocalFree((HLOCAL)*m_ppSD); *m_ppSD = pNewSD; } } else dwErr = GetLastError(); } #endif return HRESULT_FROM_WIN32(dwErr); #endif }
STDMETHODIMP CObjSecurity::Initialize( DWORD dwFlags, PSECURITY_DESCRIPTOR pSD, LPCWSTR pszServerName, DWORD sam, MRegistryBase* apWorker, HKEY hkRoot, LPCWSTR pszKeyName, HKEY hkWrite, HKEY hkParentRead) { HRESULT hr = S_OK; // Обязательно сделать копию дескриптора MakeSelfRelativeSD, т.к. функция GetSecurity тупо делает memcopy // Но учесть, что если он уже self-relative - то звать функцию здесь не нужно - просто сразу сделать копию памяти DWORD dwRevision = 0, nNewLen = 0; if (!GetSecurityDescriptorControl(pSD, &m_OrigControl, &dwRevision)) return HRESULT_FROM_WIN32(GetLastError()); if (m_OrigControl & SE_SELF_RELATIVE) { m_pOrigSD = pSD; mb_OrigSdDuplicated = FALSE; } else { //nNewLen = 8192; //m_pOrigSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, nNewLen); if ((!::MakeSelfRelativeSD(pSD, NULL, &nNewLen) && !nNewLen) || !nNewLen) return HRESULT_FROM_WIN32(GetLastError()); m_pOrigSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, nNewLen); if (!::MakeSelfRelativeSD(pSD, &m_pOrigSD, &nNewLen)) return HRESULT_FROM_WIN32(GetLastError()); mb_OrigSdDuplicated = TRUE; } #ifdef _DEBUG PACL pNewDacl = NULL; BOOL lbDacl = FALSE, lbDaclDefaulted = FALSE; ULONG nDaclCount = 0; PEXPLICIT_ACCESS pDaclEntries = NULL; DWORD dwErr = 0; PTRUSTEE pOwner = NULL, pGroup = NULL; ULONG nSaclCount = 0; PEXPLICIT_ACCESS pSaclEntries = NULL; dwErr = ::GetSecurityDescriptorDacl(m_pOrigSD, &lbDacl, &pNewDacl, &lbDaclDefaulted); ACL_SIZE_INFORMATION size_info = {0}; ACCESS_ALLOWED_ACE *Ace = NULL; BOOL lbAce = FALSE; if (pNewDacl) { dwErr = ::GetAclInformation(pNewDacl, &size_info, sizeof(size_info), AclSizeInformation); for (UINT i = 0; i < size_info.AceCount; i++) { lbAce = ::GetAce(pNewDacl, i, (void**)&Ace); } } dwErr = ::LookupSecurityDescriptorParts(&pOwner, &pGroup, &nDaclCount, &pDaclEntries, &nSaclCount, &pSaclEntries, m_pOrigSD); DumpSecurityDescriptor(m_pOrigSD, DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION, _T("CObjSecurity::Initialize")); #endif m_dwSIFlags = dwFlags; //#ifdef _DEBUG // m_dwSIFlags = SI_ADVANCED | SI_EDIT_ALL; //#endif //m_wClient = wClient; //mh_Token = hToken; mp_Worker = apWorker; mhk_Write = hkWrite; mhk_ParentRead = hkParentRead; mhk_Root = hkRoot; mpsz_KeyPath = pszKeyName; mn_WowSamDesired = sam; //TODO: А нужно ли "\\" перед именем сервера? hr = LocalAllocString(&m_pszServerName, pszServerName); LPCWSTR pszName = NULL, pszRoot = NULL; if (hkRoot == HKEY_CLASSES_ROOT) pszRoot = L"CLASSES_ROOT"; else if (hkRoot == HKEY_CURRENT_USER) pszRoot = L"CURRENT_USER"; else if (hkRoot == HKEY_LOCAL_MACHINE) pszRoot = L"MACHINE"; else if (hkRoot == HKEY_USERS) pszRoot = L"USERS"; else pszRoot = L"UNKNOWN"; if (pszKeyName && *pszKeyName) { pszName = wcsrchr(pszKeyName, L'\\'); if (pszName) pszName++; else pszName = pszKeyName; } else { pszName = pszRoot ? pszRoot : L"<Unknown>"; } hr = LocalAllocString(&m_pszObjectName, pszName); BOOL lbAllowInheritLookup = (sam == 0); if (!lbAllowInheritLookup) { #ifdef _WIN64 lbAllowInheritLookup = (sam & KEY_WOW64_64KEY) == KEY_WOW64_64KEY; #else lbAllowInheritLookup = (sam & KEY_WOW64_32KEY) == KEY_WOW64_32KEY; #endif } // Если наследование проверить можно - создаем полный путь if (lbAllowInheritLookup) { int nFullLen = 10 + (pszServerName ? lstrlenW(pszServerName) : 0) + (lstrlenW(pszRoot)) + (pszKeyName ? lstrlenW(pszKeyName) : 0); mpsz_KeyForInherit = (wchar_t*)calloc(nFullLen,sizeof(wchar_t)); if (pszServerName && *pszServerName) { while (*pszServerName == L'\\' || *pszServerName == L'/') pszServerName++; lstrcatW(mpsz_KeyForInherit, L"\\\\"); lstrcatW(mpsz_KeyForInherit, pszServerName); lstrcatW(mpsz_KeyForInherit, L"\\"); } lstrcatW(mpsz_KeyForInherit, pszRoot); if (pszKeyName && *pszKeyName) { lstrcatW(mpsz_KeyForInherit, L"\\"); lstrcatW(mpsz_KeyForInherit, pszKeyName); } } // Result //mp_OwnerSD = mp_DaclSD = NULL; mp_NewSD = NULL; m_SI = 0; return hr; }