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.
 
 
 
 
 
 

387 lines
12 KiB

// 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;
}