|
|
// Copied from \nt\private\net\config\upgrade\netupgrd
// August 98 -- t-sdey
#pragma hdrstop
#include <winnt32.h>
#include "idchange.h"
DWORD DwRegKeySetAdministratorSecurity(HKEY hkey, DWORD samDesired, PSECURITY_DESCRIPTOR* ppsdOld);
DWORD DwRegCreateOrOpenKeyExWithAdminAccess(HKEY hkey, LPCTSTR szSubKey, DWORD samDesired, BOOL fCreate, HKEY* phkeySubKey, PSECURITY_DESCRIPTOR* ppsd);
DWORD DwRegOpenKeyExWithAdminAccess(HKEY hkey, LPCTSTR szSubKey, DWORD samDesired, HKEY* phkeySubKey, PSECURITY_DESCRIPTOR* ppsd) { return DwRegCreateOrOpenKeyExWithAdminAccess(hkey, szSubKey, samDesired, FALSE, phkeySubKey, ppsd); }
//+--------------------------------------------------------------------------
//
// Function: DwRegCreateOrOpenKeyExWithAdminAccess
//
// Purpose: Creates/Opens a subkey. If the key exists but the local
// administrators group does not have samDesired access to
// it, the function will add the access needed to the
// security descriptor
//
// Arguments:
// hkeyParent [in] The key to create the subkey in
// szSubKey [in] The subkey name
// samDesired [in] The desired access for phkey
// fCreate [in] TRUE if the key is to be created.
// phSubkey [out] The handle to the subkey
// ppsdOrig [out] The previous security settings of the key
// if it already existed, optional
//
// Returns: DWORD. ERROR_SUCCESS or a failure code from winerror.h
//
// Author: billbe 15 Dec 1997
//
// Notes:
//
DWORD DwRegCreateOrOpenKeyExWithAdminAccess(HKEY hkey, LPCTSTR szSubKey, DWORD samDesired, BOOL fCreate, HKEY* phkeySubKey, PSECURITY_DESCRIPTOR* ppsd) { DWORD dwError = ERROR_SUCCESS;
if (ppsd) { *ppsd = NULL; }
// Create or open the key based on fCreate
//
if (fCreate) { dwError = RegCreateKeyEx(hkey, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, samDesired, NULL, phkeySubKey, NULL); } else { dwError = RegOpenKeyEx(hkey, szSubKey, 0, samDesired, phkeySubKey); }
// If access was denied we either tried to create or open a prexisting
// key that we didn't have access to. We need to grant ourselves
// permission.
//
if (ERROR_ACCESS_DENIED == dwError) { // open with access to read and set security
dwError = RegOpenKeyEx(hkey, szSubKey, 0, WRITE_DAC | READ_CONTROL, phkeySubKey);
if (ERROR_SUCCESS == dwError) { // Grant samDesired access to the local Administrators group
dwError = DwRegKeySetAdministratorSecurity(*phkeySubKey, samDesired, ppsd);
// Close and reopen the key with samDesired access
RegCloseKey(*phkeySubKey); if (ERROR_SUCCESS == dwError) { dwError = RegOpenKeyEx(hkey, szSubKey, 0, samDesired, phkeySubKey); } } }
return dwError; }
//+--------------------------------------------------------------------------
//
// Function: DwAddToRegKeySecurityDescriptor
//
// Purpose: Adds access for a specified SID to a registry key
//
// Arguments:
// hkey [in] The registry key that will receive the
// modified security descriptor
// psidGroup [in] The SID (in self-relative mode) that will be
// granted access to the key
// dwAccessMask [in] The access level to grant
// ppsd [out] The previous security descriptor
//
// Returns: DWORD. ERROR_SUCCESS or a failure code from winerror.h
//
// Author: billbe 13 Dec 1997
//
// Notes: This function is based on AddToRegKeySD in the MSDN
// article Windows NT Security by Christopher Nefcy
//
DWORD DwAddToRegKeySecurityDescriptor(HKEY hkey, PSID psidGroup, DWORD dwAccessMask, PSECURITY_DESCRIPTOR* ppsd) { PSECURITY_DESCRIPTOR psdAbsolute = NULL; PACL pdacl; DWORD cbSecurityDescriptor = 0; DWORD dwSecurityDescriptorRevision; DWORD cbDacl = 0; SECURITY_DESCRIPTOR_CONTROL sdc; PACL pdaclNew = NULL; DWORD cbAddDaclLength = 0; BOOL fAceFound = FALSE; BOOL fHasDacl = FALSE; BOOL fDaclDefaulted = FALSE; ACCESS_ALLOWED_ACE* pAce; DWORD i; BOOL fAceForGroupPresent = FALSE; DWORD dwMask; PSECURITY_DESCRIPTOR psdRelative = NULL; DWORD cbSize = 0;
// Get the current security descriptor for hkey
//
DWORD dwError = RegGetKeySecurity(hkey, DACL_SECURITY_INFORMATION, psdRelative, &cbSize);
if (ERROR_INSUFFICIENT_BUFFER == dwError) { psdRelative = malloc(cbSize); dwError = RegGetKeySecurity(hkey, DACL_SECURITY_INFORMATION, psdRelative, &cbSize); }
// get security descriptor control from the security descriptor
if (!GetSecurityDescriptorControl(psdRelative, (PSECURITY_DESCRIPTOR_CONTROL) &sdc, (LPDWORD) &dwSecurityDescriptorRevision)) { return (GetLastError()); }
// check if DACL is present
if (SE_DACL_PRESENT & sdc) { // get dacl
if (!GetSecurityDescriptorDacl(psdRelative, (LPBOOL) &fHasDacl, (PACL *) &pdacl, (LPBOOL) &fDaclDefaulted)) { return ( GetLastError()); } // get dacl length
cbDacl = pdacl->AclSize; // now check if SID's ACE is there
for (i = 0; i < pdacl->AceCount; i++) { if (!GetAce(pdacl, i, (LPVOID *) &pAce)) { return ( GetLastError()); } // check if group sid is already there
if (EqualSid((PSID) &(pAce->SidStart), psidGroup)) { // If the correct access is present, return success
if ((pAce->Mask & dwAccessMask) == dwAccessMask) { return ERROR_SUCCESS; } fAceForGroupPresent = TRUE; break; } } // if the group did not exist, we will need to add room
// for another ACE
if (!fAceForGroupPresent) { // get length of new DACL
cbAddDaclLength = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(psidGroup); } } else { // get length of new DACL
cbAddDaclLength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid (psidGroup); }
// get memory needed for new DACL
pdaclNew = (PACL) malloc (cbDacl + cbAddDaclLength); if (!pdaclNew) { return (GetLastError()); }
// get the sd length
cbSecurityDescriptor = GetSecurityDescriptorLength(psdRelative);
// get memory for new SD
psdAbsolute = (PSECURITY_DESCRIPTOR) malloc(cbSecurityDescriptor + cbAddDaclLength); if (!psdAbsolute) { dwError = GetLastError(); goto ErrorExit; } // change self-relative SD to absolute by making new SD
if (!InitializeSecurityDescriptor(psdAbsolute, SECURITY_DESCRIPTOR_REVISION)) { dwError = GetLastError(); goto ErrorExit; } // init new DACL
if (!InitializeAcl(pdaclNew, cbDacl + cbAddDaclLength, ACL_REVISION)) { dwError = GetLastError(); goto ErrorExit; }
// now add in all of the ACEs into the new DACL (if org DACL is there)
if (SE_DACL_PRESENT & sdc) { for (i = 0; i < pdacl->AceCount; i++) { // get ace from original dacl
if (!GetAce(pdacl, i, (LPVOID*) &pAce)) { dwError = GetLastError(); goto ErrorExit; } // If an ACE for our SID exists, we just need to bump
// up the access level instead of creating a new ACE
//
if (EqualSid((PSID) &(pAce->SidStart), psidGroup)) dwMask = dwAccessMask | pAce->Mask; else dwMask = pAce->Mask;
// now add ace to new dacl
if (!AddAccessAllowedAce(pdaclNew, ACL_REVISION, dwMask, (PSID) &(pAce->SidStart))) { dwError = GetLastError(); goto ErrorExit; } } }
// Add a new ACE for our SID if one was not already present
if (!fAceForGroupPresent) { // now add new ACE to new DACL
if (!AddAccessAllowedAce(pdaclNew, ACL_REVISION, dwAccessMask, psidGroup)) { dwError = GetLastError(); goto ErrorExit; } }
// check if everything went ok
if (!IsValidAcl(pdaclNew)) { dwError = GetLastError(); goto ErrorExit; }
// now set security descriptor DACL
if (!SetSecurityDescriptorDacl(psdAbsolute, TRUE, pdaclNew, fDaclDefaulted)) { dwError = GetLastError(); goto ErrorExit; }
// check if everything went ok
if (!IsValidSecurityDescriptor(psdAbsolute)) { dwError = GetLastError(); goto ErrorExit; }
// now set the reg key security (this will overwrite any
// existing security)
dwError = RegSetKeySecurity(hkey, (SECURITY_INFORMATION)(DACL_SECURITY_INFORMATION), psdAbsolute);
if (ppsd) { *ppsd = psdRelative; } ErrorExit: // free memory
if (psdAbsolute) { free (psdAbsolute); if (pdaclNew) { free((VOID*) pdaclNew); } }
return dwError; }
//+--------------------------------------------------------------------------
//
// Function: DwRegKeySetAdministratorSecurity
//
// Purpose: Grants the local Administrators group full access to
// hkey.
//
// Arguments:
// hkey [in] The registry key
// ppsdOld [out] The previous security descriptor for hkey
//
// Returns: DWORD. ERROR_SUCCESS or a failure code from winerror.h
//
// Author: billbe 13 Dec 1997
//
// Notes:
//
DWORD DwRegKeySetAdministratorSecurity(HKEY hkey, DWORD samDesired, PSECURITY_DESCRIPTOR* ppsdOld) { PSID psid; SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY; DWORD dwError = ERROR_SUCCESS;
// Get sid for the local Administrators group
if (!AllocateAndInitializeSid(&sidAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psid) ) { dwError = GetLastError(); }
if (ERROR_SUCCESS == dwError) { // Add all access privileges for the local administrators group
dwError = DwAddToRegKeySecurityDescriptor(hkey, psid, samDesired, ppsdOld); }
return dwError; }
|