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.
2075 lines
57 KiB
2075 lines
57 KiB
#include "pch.h"
|
|
|
|
//*************************************************************
|
|
//
|
|
// CheckSlash()
|
|
//
|
|
// Purpose: Checks for an ending slash and adds one if
|
|
// it is missing.
|
|
//
|
|
// Parameters: lpDir - directory
|
|
// cchBuffer - Buffer size in char
|
|
// pcchRemaining - buffer remaining after adding '\',
|
|
// can be NULL if not required
|
|
//
|
|
// Return: Pointer to the end of the string
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 02/14/02 santanuc Created
|
|
//
|
|
//*************************************************************
|
|
LPTSTR CheckSlash (LPTSTR lpDir, UINT cchBuffer, UINT* pcchRemaining)
|
|
{
|
|
UINT cchDir = lstrlen(lpDir);
|
|
LPTSTR lpEnd;
|
|
|
|
lpEnd = lpDir + cchDir;
|
|
if (pcchRemaining) {
|
|
*pcchRemaining = cchBuffer - cchDir - 1;
|
|
}
|
|
|
|
if (*(lpEnd - 1) != TEXT('\\')) {
|
|
if (cchDir + 1 >= cchBuffer) { // No space to put \, should never happen
|
|
return NULL;
|
|
}
|
|
*lpEnd = TEXT('\\');
|
|
lpEnd++;
|
|
*lpEnd = TEXT('\0');
|
|
if (pcchRemaining)
|
|
*pcchRemaining -= 1;
|
|
}
|
|
|
|
return lpEnd;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// SecureProfileDirectory()
|
|
//
|
|
// Purpose: Creates a secure directory that only the user
|
|
// (identified by pSid), admin, and system have
|
|
// access to.
|
|
//
|
|
// Parameters: lpDirectory - Directory Name
|
|
// pSid - Sid for user
|
|
//
|
|
// Return: ERROR_SUCCESS if successful
|
|
// Win32 error code if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 7/20/95 ericflo Created
|
|
// 2/14/02 santanuc Changed to secure the directory
|
|
// only rather than creating it recursively
|
|
//
|
|
//*************************************************************
|
|
|
|
DWORD SecureProfileDirectory (LPTSTR lpDirectory, PSID pSid)
|
|
{
|
|
PACL pAcl = NULL;
|
|
DWORD dwError;
|
|
|
|
|
|
//
|
|
// Verbose Output
|
|
//
|
|
|
|
DEBUGMSG ((DM_VERBOSE, "SecureProfileDirectory: Entering with <%s>", lpDirectory));
|
|
|
|
if (!pSid) {
|
|
// Nothing to secure
|
|
|
|
DEBUGMSG ((DM_VERBOSE, "SecureProfileDirectory: NULL sid specified"));
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Get the default ACL
|
|
//
|
|
|
|
pAcl = CreateDefaultAcl (pSid);
|
|
if (!pAcl) {
|
|
DEBUGMSG ((DM_WARNING, "SecureProfileDirectory: Fail to create ACL"));
|
|
}
|
|
|
|
//
|
|
// Attempt to secure the directory
|
|
//
|
|
|
|
dwError = SetNamedSecurityInfo( (PTSTR) lpDirectory,
|
|
SE_FILE_OBJECT,
|
|
DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
NULL,
|
|
pAcl,
|
|
NULL );
|
|
|
|
if (dwError != ERROR_SUCCESS) {
|
|
DEBUGMSG ((DM_WARNING, "SecureProfileDirectory: Failed to set security descriptor dacl for profile directory. Error = %d", GetLastError()));
|
|
}
|
|
else {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureProfileDirectory: Secure the directory <%s>", lpDirectory));
|
|
}
|
|
|
|
FreeDefaultAcl (pAcl);
|
|
|
|
return dwError;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// SetMachineProfileKeySecurity
|
|
//
|
|
// Purpose: Sets the security on the profile key under HKLM/ProfileList
|
|
//
|
|
// Parameters: pSid - User's sid
|
|
// lpKeyName - Name of the registry key
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 2/22/99 ushaji adapted
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL SetMachineProfileKeySecurity (PSID pSid, LPTSTR lpKeyName)
|
|
{
|
|
SECURITY_DESCRIPTOR sd;
|
|
SECURITY_ATTRIBUTES sa;
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
PACL pAcl = NULL;
|
|
PSID psidSystem = NULL, psidAdmin = NULL, psidUsers = NULL;
|
|
DWORD cbAcl, aceIndex;
|
|
ACE_HEADER * lpAceHeader;
|
|
BOOL bRetVal = FALSE;
|
|
HKEY hKeyProfile=NULL;
|
|
DWORD Error, dwDisp;
|
|
|
|
//
|
|
// Get the system sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
|
|
DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to initialize system sid. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the Admin sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS, 0, 0,
|
|
0, 0, 0, 0, &psidAdmin)) {
|
|
DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to initialize admin sid. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the users sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_USERS,
|
|
0, 0, 0, 0, 0, 0, &psidUsers)) {
|
|
|
|
DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to initialize authenticated users sid. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Allocate space for the ACL. (No Inheritable Aces)
|
|
//
|
|
|
|
cbAcl = (GetLengthSid (psidSystem)) +
|
|
(GetLengthSid (psidAdmin)) +
|
|
(GetLengthSid (psidUsers)) +
|
|
(GetLengthSid (pSid)) +
|
|
sizeof(ACL) +
|
|
(4 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
|
|
|
|
|
|
pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
|
|
if (!pAcl) {
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
|
|
DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to initialize acl. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Add Aces. Non-inheritable ACEs first
|
|
//
|
|
|
|
aceIndex = 0;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) {
|
|
DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) {
|
|
DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidUsers)) {
|
|
DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS ^ (WRITE_DAC | WRITE_OWNER), pSid)) {
|
|
DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Put together the security descriptor
|
|
//
|
|
|
|
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
|
|
DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to initialize security descriptor. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
|
|
DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Failed to set security descriptor dacl. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
Error = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
|
|
lpKeyName,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
|
|
NULL,
|
|
&hKeyProfile,
|
|
&dwDisp);
|
|
|
|
if (Error != ERROR_SUCCESS) {
|
|
DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Couldn't open registry key to set security. Error = %d", Error));
|
|
SetLastError(Error);
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Set the security
|
|
//
|
|
|
|
Error = RegSetKeySecurity(hKeyProfile, DACL_SECURITY_INFORMATION, &sd);
|
|
|
|
if (Error != ERROR_SUCCESS) {
|
|
DEBUGMSG((DM_WARNING, "SetMachineProfileKeySecurity: Couldn't set security. Error = %d", Error));
|
|
SetLastError(Error);
|
|
goto Exit;
|
|
}
|
|
else {
|
|
bRetVal = TRUE;
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
if (psidSystem) {
|
|
FreeSid(psidSystem);
|
|
}
|
|
|
|
if (psidAdmin) {
|
|
FreeSid(psidAdmin);
|
|
}
|
|
|
|
if (psidUsers) {
|
|
FreeSid(psidUsers);
|
|
}
|
|
|
|
if (pAcl) {
|
|
GlobalFree (pAcl);
|
|
}
|
|
|
|
if (hKeyProfile) {
|
|
RegCloseKey(hKeyProfile);
|
|
}
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
|
|
PACL
|
|
CreateDefaultAcl (
|
|
PSID pSid
|
|
)
|
|
{
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
PACL pAcl = NULL;
|
|
PSID psidSystem = NULL, psidAdmin = NULL;
|
|
DWORD cbAcl, aceIndex;
|
|
ACE_HEADER * lpAceHeader;
|
|
BOOL bRetVal = FALSE;
|
|
BOOL bFreeSid = TRUE;
|
|
|
|
//
|
|
// Get the system sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to initialize system sid. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Get the Admin sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS, 0, 0,
|
|
0, 0, 0, 0, &psidAdmin)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to initialize admin sid. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Allocate space for the ACL
|
|
//
|
|
|
|
cbAcl = (2 * GetLengthSid (pSid)) + (2 * GetLengthSid (psidSystem)) +
|
|
(2 * GetLengthSid (psidAdmin)) + sizeof(ACL) +
|
|
(6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
|
|
|
|
|
|
pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
|
|
if (!pAcl) {
|
|
goto Exit;
|
|
}
|
|
|
|
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to initialize acl. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Add Aces for User, System, and Admin. Non-inheritable ACEs first
|
|
//
|
|
|
|
aceIndex = 0;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, pSid)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidSystem)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidAdmin)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Now the inheritable ACEs
|
|
//
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, pSid)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to get ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to get ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to get ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
Exit:
|
|
|
|
if (psidSystem) {
|
|
FreeSid(psidSystem);
|
|
}
|
|
|
|
if (psidAdmin) {
|
|
FreeSid(psidAdmin);
|
|
}
|
|
|
|
return pAcl;
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeDefaultAcl (
|
|
PACL pAcl
|
|
)
|
|
{
|
|
if (pAcl) {
|
|
GlobalFree (pAcl);
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
OurConvertSidToStringSid (
|
|
IN PSID Sid,
|
|
OUT PWSTR *SidString
|
|
)
|
|
{
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS NtStatus;
|
|
|
|
//
|
|
// Convert the sid into text format
|
|
//
|
|
|
|
NtStatus = RtlConvertSidToUnicodeString (&UnicodeString, Sid, TRUE);
|
|
|
|
if (!NT_SUCCESS (NtStatus)) {
|
|
|
|
DEBUGMSG ((
|
|
DM_WARNING,
|
|
"CreateUserProfile: RtlConvertSidToUnicodeString failed, status = 0x%x",
|
|
NtStatus
|
|
));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
*SidString = UnicodeString.Buffer;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
DeleteSidString (
|
|
PWSTR SidString
|
|
)
|
|
{
|
|
UNICODE_STRING String;
|
|
|
|
if (!SidString) {
|
|
return;
|
|
}
|
|
|
|
RtlInitUnicodeString (&String, SidString);
|
|
RtlFreeUnicodeString (&String);
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
GetProfileRoot (
|
|
IN PSID Sid,
|
|
OUT PWSTR ProfileDir,
|
|
IN UINT cchBuffer
|
|
)
|
|
{
|
|
WCHAR LocalProfileKey[MAX_PATH];
|
|
HKEY hKey;
|
|
DWORD Size;
|
|
DWORD Type;
|
|
DWORD Attributes;
|
|
DWORD cchExpandedRoot;
|
|
PWSTR SidString = NULL;
|
|
WCHAR ExpandedRoot[MAX_PATH];
|
|
HRESULT hr;
|
|
BOOL bResult = FALSE;
|
|
|
|
if (cchBuffer) {
|
|
ProfileDir[0] = 0;
|
|
}
|
|
|
|
if (!OurConvertSidToStringSid (Sid, &SidString)) {
|
|
DEBUGMSG ((DM_WARNING, "GetProfileRoot: Can't convert SID to string"));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Check if this user's profile exists
|
|
//
|
|
|
|
hr = StringCchCopy(LocalProfileKey, ARRAYSIZE(LocalProfileKey), PROFILE_LIST_PATH);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
hr = StringCchCat(LocalProfileKey, ARRAYSIZE(LocalProfileKey), TEXT("\\"));
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
hr = StringCchCat(LocalProfileKey, ARRAYSIZE(LocalProfileKey), SidString);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, LocalProfileKey,
|
|
0, KEY_READ, &hKey) == ERROR_SUCCESS) {
|
|
|
|
Size = cchBuffer * sizeof(WCHAR);
|
|
RegQueryValueEx (hKey, PROFILE_IMAGE_VALUE_NAME, NULL,
|
|
&Type, (LPBYTE) ProfileDir, &Size);
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
if (cchBuffer && ProfileDir[0]) {
|
|
|
|
cchExpandedRoot = ExpandEnvironmentStrings (ProfileDir, ExpandedRoot, ARRAYSIZE(ExpandedRoot));
|
|
if (!cchExpandedRoot || cchExpandedRoot > ARRAYSIZE(ExpandedRoot)) {
|
|
ProfileDir[0] = 0;
|
|
DEBUGMSG ((DM_VERBOSE, "GetProfileRoot: ExpandEnvironmentStrings failed."));
|
|
goto Exit;
|
|
}
|
|
|
|
Attributes = GetFileAttributes (ExpandedRoot);
|
|
|
|
if (Attributes == 0xFFFFFFFF || !(Attributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
ProfileDir[0] = 0;
|
|
DEBUGMSG ((DM_VERBOSE, "GetProfileRoot: Profile %s is not vaild", SidString));
|
|
} else {
|
|
if (FAILED(StringCchCopy(ProfileDir, cchBuffer, ExpandedRoot))) {
|
|
ProfileDir[0] = 0;
|
|
DEBUGMSG ((DM_VERBOSE, "GetProfileRoot: Not enough buffer space"));
|
|
}
|
|
else {
|
|
bResult = TRUE;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
DEBUGMSG ((DM_VERBOSE, "GetProfileRoot: SID %s does not have a profile directory", SidString));
|
|
}
|
|
|
|
Exit:
|
|
|
|
DeleteSidString (SidString);
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
BOOL
|
|
UpdateProfileSecurity (
|
|
PSID Sid
|
|
)
|
|
{
|
|
WCHAR ProfileDir[MAX_PATH];
|
|
WCHAR ExpProfileDir[MAX_PATH];
|
|
WCHAR LocalProfileKey[MAX_PATH];
|
|
PWSTR SidString = NULL;
|
|
PWSTR End, Save;
|
|
LONG rc;
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
DWORD dwSize;
|
|
DWORD dwType;
|
|
DWORD cchExpProfileDir;
|
|
HKEY hKey;
|
|
BOOL b = FALSE;
|
|
BOOL UnloadProfile = FALSE;
|
|
HRESULT hr;
|
|
UINT cchRemaining;
|
|
|
|
__try {
|
|
//
|
|
// Convert the sid into text format
|
|
//
|
|
|
|
if (!OurConvertSidToStringSid (Sid, &SidString)) {
|
|
dwError = GetLastError();
|
|
DEBUGMSG ((DM_WARNING, "UpdateProfileSecurity: Can't convert SID to string"));
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Check if this user's profile exists already
|
|
//
|
|
|
|
hr = StringCchCopy(LocalProfileKey, ARRAYSIZE(LocalProfileKey), PROFILE_LIST_PATH);
|
|
if (FAILED(hr)) {
|
|
dwError = HRESULT_CODE(hr);
|
|
__leave;
|
|
}
|
|
hr = StringCchCat(LocalProfileKey, ARRAYSIZE(LocalProfileKey), TEXT("\\"));
|
|
if (FAILED(hr)){
|
|
dwError = HRESULT_CODE(hr);
|
|
__leave;
|
|
}
|
|
hr = StringCchCat(LocalProfileKey, ARRAYSIZE(LocalProfileKey), SidString);
|
|
if (FAILED(hr)) {
|
|
dwError = HRESULT_CODE(hr);
|
|
__leave;
|
|
}
|
|
|
|
ProfileDir[0] = 0;
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, LocalProfileKey,
|
|
0, KEY_READ, &hKey) == ERROR_SUCCESS) {
|
|
|
|
dwSize = sizeof(ProfileDir);
|
|
RegQueryValueEx (hKey, PROFILE_IMAGE_VALUE_NAME, NULL,
|
|
&dwType, (LPBYTE) ProfileDir, &dwSize);
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
if (!ProfileDir[0]) {
|
|
DEBUGMSG ((DM_WARNING, "UpdateProfileSecurity: No profile for specified user"));
|
|
dwError = ERROR_BAD_PROFILE;
|
|
__leave;
|
|
}
|
|
|
|
if (!SetMachineProfileKeySecurity(Sid, LocalProfileKey)) {
|
|
DEBUGMSG ((DM_WARNING, "UpdateProfileSecurity: Fail to set security for ProfileList entry. Error %d", GetLastError()));
|
|
}
|
|
|
|
//
|
|
// The user has a profile, so update the security settings
|
|
//
|
|
|
|
cchExpProfileDir = ExpandEnvironmentStrings (ProfileDir, ExpProfileDir, ARRAYSIZE(ExpProfileDir));
|
|
if (!cchExpProfileDir || cchExpProfileDir > ARRAYSIZE(ExpProfileDir)) {
|
|
dwError = cchExpProfileDir ? ERROR_BUFFER_OVERFLOW : GetLastError();
|
|
DEBUGMSG ((DM_WARNING, "UpdateProfileSecurity: ExpandEnvironmentStrings failed. Error %d", dwError));
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Load the hive temporary so the security can be fixed
|
|
//
|
|
|
|
End = CheckSlash (ExpProfileDir, ARRAYSIZE(ExpProfileDir), &cchRemaining);
|
|
if (!End) {
|
|
dwError = ERROR_BUFFER_OVERFLOW;
|
|
__leave;
|
|
}
|
|
|
|
Save = End - 1;
|
|
hr = StringCchCopy(End, cchRemaining, L"NTUSER.DAT");
|
|
if (FAILED(hr)) {
|
|
dwError = HRESULT_CODE(hr);
|
|
__leave;
|
|
}
|
|
|
|
rc = MyRegLoadKey (HKEY_USERS, SidString, ExpProfileDir);
|
|
|
|
*Save = 0;
|
|
|
|
if (rc != ERROR_SUCCESS) {
|
|
DEBUGMSG((DM_WARNING, "UpdateProfileSecurity: Failed to load hive, error = %d.", rc));
|
|
dwError = rc;
|
|
__leave;
|
|
}
|
|
|
|
UnloadProfile = TRUE;
|
|
|
|
if (!SetupNewHive (SidString, Sid)) {
|
|
dwError = GetLastError();
|
|
DEBUGMSG((DM_WARNING, "UpdateProfileSecurity: SetupNewHive failed, error = %d.", GetLastError()));
|
|
__leave;
|
|
|
|
}
|
|
|
|
//
|
|
// Fix the file system security
|
|
//
|
|
|
|
dwError = SecureProfileDirectory (ExpProfileDir, Sid);
|
|
|
|
if (dwError != ERROR_SUCCESS) {
|
|
DEBUGMSG((DM_WARNING, "UpdateProfileSecurity: SecureProfileDirectory failed, error = %d.", GetLastError()));
|
|
__leave;
|
|
}
|
|
|
|
b = TRUE;
|
|
|
|
}
|
|
__finally {
|
|
if (UnloadProfile) {
|
|
MyRegUnLoadKey (HKEY_USERS, SidString);
|
|
}
|
|
|
|
DeleteSidString (SidString);
|
|
|
|
SetLastError (dwError);
|
|
}
|
|
|
|
return b;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// DeleteProfileGuidSettings()
|
|
//
|
|
// Purpose: Deletes the GUID value and associated GUID entry
|
|
// from ProfileGuid key
|
|
//
|
|
// Parameters: hProfile - Profile List sid entry key
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 02/13/2002 Santanuc Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL DeleteProfileGuidSettings (HKEY hProfile)
|
|
{
|
|
LONG lResult;
|
|
TCHAR szTemp[MAX_PATH];
|
|
TCHAR szUserGuid[MAX_PATH];
|
|
HKEY hKey;
|
|
DWORD dwType, dwSize;
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Query for the user guid
|
|
//
|
|
|
|
dwSize = MAX_PATH * sizeof(TCHAR);
|
|
lResult = RegQueryValueEx (hProfile, PROFILE_GUID, NULL, &dwType, (LPBYTE) szUserGuid, &dwSize);
|
|
|
|
if (lResult == ERROR_SUCCESS) {
|
|
//
|
|
// Delete the profile GUID value
|
|
//
|
|
|
|
RegDeleteValue (hProfile, PROFILE_GUID);
|
|
|
|
hr = StringCchCopy(szTemp, ARRAYSIZE(szTemp), PROFILE_GUID_PATH);
|
|
if (FAILED(hr))
|
|
return FALSE;
|
|
hr = StringCchCat(szTemp, ARRAYSIZE(szTemp), TEXT("\\"));
|
|
if (FAILED(hr))
|
|
return FALSE;
|
|
hr = StringCchCat(szTemp, ARRAYSIZE(szTemp), szUserGuid);
|
|
if (FAILED(hr))
|
|
return FALSE;
|
|
|
|
//
|
|
// Delete the profile guid from the guid list
|
|
//
|
|
|
|
lResult = RegDeleteKey(HKEY_LOCAL_MACHINE, szTemp);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DEBUGMSG((DM_WARNING, "DeleteProfile: failed to delete profile guid. Error = %d", lResult));
|
|
}
|
|
}
|
|
else if (lResult == ERROR_FILE_NOT_FOUND) {
|
|
lResult = ERROR_SUCCESS;
|
|
}
|
|
|
|
return (lResult == ERROR_SUCCESS) ? TRUE : FALSE;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* GetUserSid
|
|
*
|
|
* Allocs space for the user sid, fills it in and returns a pointer. Caller
|
|
* The sid should be freed by calling DeleteUserSid.
|
|
*
|
|
* Note the sid returned is the user's real sid, not the per-logon sid.
|
|
*
|
|
* Returns pointer to sid or NULL on failure.
|
|
*
|
|
* History:
|
|
* 26-Aug-92 Davidc Created.
|
|
\***************************************************************************/
|
|
PSID GetUserSid (HANDLE UserToken)
|
|
{
|
|
PTOKEN_USER pUser, pTemp;
|
|
PSID pSid;
|
|
DWORD BytesRequired = 200;
|
|
NTSTATUS status;
|
|
|
|
|
|
//
|
|
// Allocate space for the user info
|
|
//
|
|
|
|
pUser = (PTOKEN_USER)LocalAlloc(LMEM_FIXED, BytesRequired);
|
|
|
|
|
|
if (pUser == NULL) {
|
|
DEBUGMSG((DM_WARNING, "GetUserSid: Failed to allocate %d bytes",
|
|
BytesRequired));
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// Read in the UserInfo
|
|
//
|
|
|
|
status = NtQueryInformationToken(
|
|
UserToken, // Handle
|
|
TokenUser, // TokenInformationClass
|
|
pUser, // TokenInformation
|
|
BytesRequired, // TokenInformationLength
|
|
&BytesRequired // ReturnLength
|
|
);
|
|
|
|
if (status == STATUS_BUFFER_TOO_SMALL) {
|
|
|
|
//
|
|
// Allocate a bigger buffer and try again.
|
|
//
|
|
|
|
pTemp = LocalReAlloc(pUser, BytesRequired, LMEM_MOVEABLE);
|
|
if (pTemp == NULL) {
|
|
DEBUGMSG((DM_WARNING, "GetUserSid: Failed to allocate %d bytes",
|
|
BytesRequired));
|
|
LocalFree (pUser);
|
|
return NULL;
|
|
}
|
|
|
|
pUser = pTemp;
|
|
|
|
status = NtQueryInformationToken(
|
|
UserToken, // Handle
|
|
TokenUser, // TokenInformationClass
|
|
pUser, // TokenInformation
|
|
BytesRequired, // TokenInformationLength
|
|
&BytesRequired // ReturnLength
|
|
);
|
|
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DEBUGMSG((DM_WARNING, "GetUserSid: Failed to query user info from user token, status = 0x%x",
|
|
status));
|
|
LocalFree(pUser);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
BytesRequired = RtlLengthSid(pUser->User.Sid);
|
|
pSid = LocalAlloc(LMEM_FIXED, BytesRequired);
|
|
if (pSid == NULL) {
|
|
DEBUGMSG((DM_WARNING, "GetUserSid: Failed to allocate %d bytes",
|
|
BytesRequired));
|
|
LocalFree(pUser);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
status = RtlCopySid(BytesRequired, pSid, pUser->User.Sid);
|
|
|
|
LocalFree(pUser);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DEBUGMSG((DM_WARNING, "GetUserSid: RtlCopySid Failed. status = %d",
|
|
status));
|
|
LocalFree(pSid);
|
|
pSid = NULL;
|
|
}
|
|
|
|
|
|
return pSid;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* DeleteUserSid
|
|
*
|
|
* Deletes a user sid previously returned by GetUserSid()
|
|
*
|
|
* Returns nothing.
|
|
*
|
|
* History:
|
|
* 26-Aug-92 Davidc Created
|
|
*
|
|
\***************************************************************************/
|
|
VOID DeleteUserSid(PSID Sid)
|
|
{
|
|
LocalFree(Sid);
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// MyRegLoadKey()
|
|
//
|
|
// Purpose: Loads a hive into the registry
|
|
//
|
|
// Parameters: hKey - Key to load the hive into
|
|
// lpSubKey - Subkey name
|
|
// lpFile - hive filename
|
|
//
|
|
// Return: ERROR_SUCCESS if successful
|
|
// Error number if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 6/22/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
LONG MyRegLoadKey(HKEY hKey, LPTSTR lpSubKey, LPTSTR lpFile)
|
|
{
|
|
NTSTATUS Status;
|
|
BOOLEAN WasEnabled;
|
|
HANDLE hToken;
|
|
BOOLEAN bClient = FALSE;
|
|
int error;
|
|
WCHAR szException[20];
|
|
|
|
__try {
|
|
|
|
if (OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken)) {
|
|
CloseHandle(hToken);
|
|
bClient = TRUE; // Enable privilege on thread token
|
|
}
|
|
|
|
//
|
|
// Enable the restore privilege
|
|
//
|
|
|
|
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, bClient, &WasEnabled);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
error = RegLoadKey(hKey, lpSubKey, lpFile);
|
|
|
|
//
|
|
// Restore the privilege to its previous state
|
|
//
|
|
|
|
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, bClient, &WasEnabled);
|
|
if (!NT_SUCCESS(Status)) {
|
|
DEBUGMSG((DM_WARNING, "MyRegLoadKey: Failed to restore RESTORE privilege to previous enabled state"));
|
|
}
|
|
|
|
|
|
//
|
|
// Convert a sharing violation error to success since the hive
|
|
// is already loaded
|
|
//
|
|
|
|
if (error == ERROR_SHARING_VIOLATION) {
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
//
|
|
// Check if the hive was loaded
|
|
//
|
|
|
|
if (error != ERROR_SUCCESS) {
|
|
DEBUGMSG((DM_WARNING, "MyRegLoadKey: Failed to load subkey <%s>, error =%d", lpSubKey, error));
|
|
}
|
|
|
|
} else {
|
|
error = ERROR_ACCESS_DENIED;
|
|
DEBUGMSG((DM_WARNING, "MyRegLoadKey: Failed to enable restore privilege to load registry key, error %u", error));
|
|
}
|
|
|
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
error = GetExceptionCode();
|
|
if (SUCCEEDED(StringCchPrintf(szException, ARRAYSIZE(szException), L"!!!! 0x%x ", error))) {
|
|
OutputDebugString(szException);
|
|
OutputDebugString(L"Exception hit in MyRegLoadKey in userenv\n");
|
|
}
|
|
ASSERT(error == 0);
|
|
}
|
|
|
|
DEBUGMSG((DM_VERBOSE, "MyRegLoadKey: Returning %d.", error));
|
|
|
|
return error;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// MyRegUnLoadKey()
|
|
//
|
|
// Purpose: Unloads a registry key
|
|
//
|
|
// Parameters: hKey - Registry handle
|
|
// lpSubKey - Subkey to be unloaded
|
|
//
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 6/19/95 ericflo Ported
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL MyRegUnLoadKey(HKEY hKey, LPTSTR lpSubKey)
|
|
{
|
|
BOOL bResult = TRUE;
|
|
LONG error;
|
|
NTSTATUS Status;
|
|
BOOLEAN WasEnabled;
|
|
HANDLE hToken;
|
|
BOOLEAN bClient = FALSE;
|
|
DWORD dwException;
|
|
WCHAR szException[20];
|
|
|
|
|
|
__try {
|
|
|
|
if (OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken)) {
|
|
CloseHandle(hToken);
|
|
bClient = TRUE; // Enable privilege on thread token
|
|
}
|
|
|
|
//
|
|
// Enable the restore privilege
|
|
//
|
|
|
|
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, bClient, &WasEnabled);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
error = RegUnLoadKey(hKey, lpSubKey);
|
|
|
|
if ( error != ERROR_SUCCESS) {
|
|
DEBUGMSG((DM_WARNING, "MyRegUnLoadKey: Failed to unmount hive %x", error));
|
|
SetLastError(error);
|
|
bResult = FALSE;
|
|
}
|
|
|
|
//
|
|
// Restore the privilege to its previous state
|
|
//
|
|
|
|
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, bClient, &WasEnabled);
|
|
if (!NT_SUCCESS(Status)) {
|
|
DEBUGMSG((DM_WARNING, "MyRegUnLoadKey: Failed to restore RESTORE privilege to previous enabled state"));
|
|
}
|
|
|
|
} else {
|
|
DEBUGMSG((DM_WARNING, "MyRegUnloadKey: Failed to enable restore privilege to unload registry key"));
|
|
Status = ERROR_ACCESS_DENIED;
|
|
SetLastError(Status);
|
|
bResult = FALSE;
|
|
}
|
|
|
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
bResult = FALSE;
|
|
dwException = GetExceptionCode();
|
|
if (SUCCEEDED(StringCchPrintf(szException, ARRAYSIZE(szException), L"!!!! 0x%x ", dwException))) {
|
|
OutputDebugString(szException);
|
|
OutputDebugString(L"Exception hit in MyRegUnLoadKey in userenv\n");
|
|
}
|
|
ASSERT(dwException == 0);
|
|
}
|
|
|
|
DEBUGMSG((DM_VERBOSE, "MyRegUnloadKey: Returning %d, error %u.", bResult, GetLastError()));
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// SetDefaultUserHiveSecurity()
|
|
//
|
|
// Purpose: Initializes a user hive with the
|
|
// appropriate acls
|
|
//
|
|
// Parameters: pSid - Sid (used by CreateNewUser)
|
|
// RootKey - registry handle to hive root
|
|
//
|
|
// Return: ERROR_SUCCESS if successful
|
|
// other error code if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 7/18/95 ericflo Created as part of
|
|
// SetupNewHive
|
|
// 3/29/98 adamed Moved out of SetupNewHive
|
|
// to this function
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL SetDefaultUserHiveSecurity(PSID pSid, HKEY RootKey)
|
|
{
|
|
DWORD Error;
|
|
SECURITY_DESCRIPTOR sd;
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
PACL pAcl = NULL;
|
|
PSID psidUser = NULL, psidSystem = NULL, psidAdmin = NULL, psidRestricted = NULL;
|
|
DWORD cbAcl, AceIndex;
|
|
ACE_HEADER * lpAceHeader;
|
|
BOOL bRetVal = FALSE;
|
|
BOOL bFreeSid = TRUE;
|
|
|
|
|
|
//
|
|
// Verbose Output
|
|
//
|
|
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Entering"));
|
|
|
|
|
|
//
|
|
// Create the security descriptor that will be applied to each key
|
|
//
|
|
|
|
//
|
|
// Give the user access by their real sid so they still have access
|
|
// when they logoff and logon again
|
|
//
|
|
|
|
psidUser = pSid;
|
|
bFreeSid = FALSE;
|
|
|
|
if (!psidUser) {
|
|
DEBUGMSG((DM_WARNING, "SetDefaultUserHiveSecurity: Failed to get user sid"));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Get the system sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to initialize system sid. Error = %d",
|
|
GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the admin sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS, 0, 0,
|
|
0, 0, 0, 0, &psidAdmin)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to initialize admin sid. Error = %d",
|
|
GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Get the Restricted sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_RESTRICTED_CODE_RID,
|
|
0, 0, 0, 0, 0, 0, 0, &psidRestricted)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to initialize restricted sid. Error = %d",
|
|
GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Allocate space for the ACL
|
|
//
|
|
|
|
cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
|
|
(2 * GetLengthSid (psidAdmin)) + (2*GetLengthSid(psidRestricted)) +
|
|
sizeof(ACL) +
|
|
(8 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
|
|
|
|
|
|
pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
|
|
if (!pAcl) {
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to initialize acl. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Add Aces for User, System, and Admin. Non-inheritable ACEs first
|
|
//
|
|
|
|
AceIndex = 0;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidUser)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for user. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for system. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for admin. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidRestricted)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for Restricted. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Now the inheritable ACEs
|
|
//
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidUser)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for user. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for system. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for admin. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ, psidRestricted)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for restricted. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
|
|
//
|
|
// Put together the security descriptor
|
|
//
|
|
|
|
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to initialize security descriptor. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to set security descriptor dacl. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Set the security descriptor on the entire tree
|
|
//
|
|
|
|
Error = ApplySecurityToRegistryTree(RootKey, &sd);
|
|
|
|
if (ERROR_SUCCESS == Error) {
|
|
bRetVal = TRUE;
|
|
}
|
|
else
|
|
SetLastError(Error);
|
|
|
|
Exit:
|
|
|
|
//
|
|
// Free the sids and acl
|
|
//
|
|
|
|
if (bFreeSid && psidUser) {
|
|
DeleteUserSid (psidUser);
|
|
}
|
|
|
|
if (psidSystem) {
|
|
FreeSid(psidSystem);
|
|
}
|
|
|
|
if (psidAdmin) {
|
|
FreeSid(psidAdmin);
|
|
}
|
|
|
|
if (pAcl) {
|
|
GlobalFree (pAcl);
|
|
}
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// SetupNewHive()
|
|
//
|
|
// Purpose: Initializes the new user hive created by copying
|
|
// the default hive.
|
|
//
|
|
// Parameters: lpSidString - Sid string
|
|
// pSid - Sid (used by CreateNewUser)
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 7/18/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL SetupNewHive(LPTSTR lpSidString, PSID pSid)
|
|
{
|
|
DWORD Error, IgnoreError;
|
|
HKEY RootKey;
|
|
BOOL bRetVal = FALSE;
|
|
HRESULT hr;
|
|
UINT cchRemaining;
|
|
|
|
|
|
//
|
|
// Verbose Output
|
|
//
|
|
|
|
DEBUGMSG((DM_VERBOSE, "SetupNewHive: Entering"));
|
|
|
|
|
|
//
|
|
// Open the root of the user's profile
|
|
//
|
|
|
|
Error = RegOpenKeyEx(HKEY_USERS,
|
|
lpSidString,
|
|
0,
|
|
KEY_READ | WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
|
|
&RootKey);
|
|
|
|
if (Error != ERROR_SUCCESS) {
|
|
|
|
DEBUGMSG((DM_WARNING, "SetupNewHive: Failed to open root of user registry, error = %d", Error));
|
|
|
|
} else {
|
|
|
|
//
|
|
// First Secure the entire hive -- use security that
|
|
// will be sufficient for most of the hive.
|
|
// After this, we can add special settings to special
|
|
// sections of this hive.
|
|
//
|
|
|
|
if (SetDefaultUserHiveSecurity(pSid, RootKey)) {
|
|
|
|
TCHAR szSubKey[MAX_PATH];
|
|
LPTSTR lpEnd;
|
|
|
|
//
|
|
// Change the security on certain keys in the user's registry
|
|
// so that only Admin's and the OS have write access.
|
|
//
|
|
|
|
hr = StringCchCopy(szSubKey, ARRAYSIZE(szSubKey), lpSidString);
|
|
if (FAILED(hr)) {
|
|
SetLastError(HRESULT_CODE(hr));
|
|
return FALSE;
|
|
}
|
|
|
|
lpEnd = CheckSlash(szSubKey, ARRAYSIZE(szSubKey), &cchRemaining);
|
|
if (!lpEnd) {
|
|
SetLastError(ERROR_BUFFER_OVERFLOW);
|
|
return FALSE;
|
|
}
|
|
|
|
hr = StringCchCopy(lpEnd, cchRemaining, WINDOWS_POLICIES_KEY);
|
|
if (FAILED(hr)) {
|
|
SetLastError(HRESULT_CODE(hr));
|
|
return FALSE;
|
|
}
|
|
|
|
if (!SecureUserKey(szSubKey, pSid)) {
|
|
DEBUGMSG((DM_WARNING, "SetupNewHive: Failed to secure windows policies key"));
|
|
}
|
|
|
|
hr = StringCchCopy(lpEnd, cchRemaining, ROOT_POLICIES_KEY);
|
|
if (FAILED(hr)) {
|
|
SetLastError(HRESULT_CODE(hr));
|
|
return FALSE;
|
|
}
|
|
|
|
if (!SecureUserKey(szSubKey, pSid)) {
|
|
DEBUGMSG((DM_WARNING, "SetupNewHive: Failed to secure root policies key"));
|
|
}
|
|
|
|
bRetVal = TRUE;
|
|
|
|
} else {
|
|
Error = GetLastError();
|
|
DEBUGMSG((DM_WARNING, "SetupNewHive: Failed to apply security to user registry tree, error = %d", Error));
|
|
}
|
|
|
|
RegFlushKey (RootKey);
|
|
|
|
IgnoreError = RegCloseKey(RootKey);
|
|
if (IgnoreError != ERROR_SUCCESS) {
|
|
DEBUGMSG((DM_WARNING, "SetupNewHive: Failed to close reg key, error = %d", IgnoreError));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Verbose Output
|
|
//
|
|
|
|
DEBUGMSG((DM_VERBOSE, "SetupNewHive: Leaving with a return value of %d, error %u", bRetVal, Error));
|
|
|
|
if (!bRetVal)
|
|
SetLastError(Error);
|
|
|
|
return(bRetVal);
|
|
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// ApplySecurityToRegistryTree()
|
|
//
|
|
// Purpose: Applies the passed security descriptor to the passed
|
|
// key and all its descendants. Only the parts of
|
|
// the descriptor inddicated in the security
|
|
// info value are actually applied to each registry key.
|
|
//
|
|
// Parameters: RootKey - Registry key
|
|
// pSD - Security Descriptor
|
|
//
|
|
// Return: ERROR_SUCCESS if successful
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 7/19/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
DWORD ApplySecurityToRegistryTree(HKEY RootKey, PSECURITY_DESCRIPTOR pSD)
|
|
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
DWORD SubKeyIndex;
|
|
LPTSTR SubKeyName;
|
|
HKEY SubKey;
|
|
DWORD cchMaxSubKeySize;
|
|
|
|
|
|
|
|
//
|
|
// First apply security
|
|
//
|
|
|
|
RegSetKeySecurity(RootKey, DACL_SECURITY_INFORMATION, pSD);
|
|
|
|
Error = RegQueryInfoKey(RootKey, NULL, NULL, NULL, NULL,
|
|
&cchMaxSubKeySize, NULL, NULL,
|
|
NULL, NULL, NULL, NULL);
|
|
if (Error != ERROR_SUCCESS) {
|
|
DEBUGMSG ((DM_WARNING, "ApplySecurityToRegistryTree: Failed to query reg key. error = %d", Error));
|
|
return Error;
|
|
}
|
|
|
|
cchMaxSubKeySize++; // Include the null terminator
|
|
|
|
//
|
|
// Open each sub-key and apply security to its sub-tree
|
|
//
|
|
|
|
SubKeyIndex = 0;
|
|
|
|
SubKeyName = GlobalAlloc (GPTR, cchMaxSubKeySize * sizeof(TCHAR));
|
|
|
|
if (!SubKeyName) {
|
|
DEBUGMSG ((DM_WARNING, "ApplySecurityToRegistryTree: Failed to allocate memory, error = %d", GetLastError()));
|
|
return GetLastError();
|
|
}
|
|
|
|
while (TRUE) {
|
|
|
|
//
|
|
// Get the next sub-key name
|
|
//
|
|
|
|
Error = RegEnumKey(RootKey, SubKeyIndex, SubKeyName, cchMaxSubKeySize);
|
|
|
|
|
|
if (Error != ERROR_SUCCESS) {
|
|
|
|
if (Error == ERROR_NO_MORE_ITEMS) {
|
|
|
|
//
|
|
// Successful end of enumeration
|
|
//
|
|
|
|
Error = ERROR_SUCCESS;
|
|
|
|
} else {
|
|
|
|
DEBUGMSG ((DM_WARNING, "ApplySecurityToRegistryTree: Registry enumeration failed with error = %d", Error));
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// Open the sub-key
|
|
//
|
|
|
|
Error = RegOpenKeyEx(RootKey,
|
|
SubKeyName,
|
|
0,
|
|
KEY_READ | WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
|
|
&SubKey);
|
|
|
|
if (Error == ERROR_SUCCESS) {
|
|
|
|
//
|
|
// Apply security to the sub-tree
|
|
//
|
|
|
|
ApplySecurityToRegistryTree(SubKey, pSD);
|
|
|
|
|
|
//
|
|
// We're finished with the sub-key
|
|
//
|
|
|
|
RegCloseKey(SubKey);
|
|
}
|
|
|
|
|
|
//
|
|
// Go enumerate the next sub-key
|
|
//
|
|
|
|
SubKeyIndex ++;
|
|
}
|
|
|
|
|
|
GlobalFree (SubKeyName);
|
|
|
|
return Error;
|
|
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// SecureUserKey()
|
|
//
|
|
// Purpose: Sets security on a key in the user's hive
|
|
// so only admin's can change it.
|
|
//
|
|
// Parameters: lpKey - Key to secure
|
|
// pSid - Sid (used by CreateNewUser)
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 6/20/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL SecureUserKey(LPTSTR lpKey, PSID pSid)
|
|
{
|
|
DWORD Error;
|
|
HKEY RootKey;
|
|
SECURITY_DESCRIPTOR sd;
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
PACL pAcl = NULL;
|
|
PSID psidUser = NULL, psidSystem = NULL, psidAdmin = NULL, psidRestricted = NULL;
|
|
DWORD cbAcl, AceIndex, dwDisp;
|
|
ACE_HEADER * lpAceHeader;
|
|
BOOL bRetVal = FALSE;
|
|
BOOL bFreeSid = TRUE;
|
|
|
|
|
|
//
|
|
// Verbose Output
|
|
//
|
|
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Entering"));
|
|
|
|
|
|
//
|
|
// Create the security descriptor
|
|
//
|
|
|
|
//
|
|
// Give the user access by their real sid so they still have access
|
|
// when they logoff and logon again
|
|
//
|
|
|
|
psidUser = pSid;
|
|
bFreeSid = FALSE;
|
|
|
|
if (!psidUser) {
|
|
DEBUGMSG ((DM_WARNING, "SecureUserKey: Failed to get user sid"));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Get the system sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to initialize system sid. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the admin sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS, 0, 0,
|
|
0, 0, 0, 0, &psidAdmin)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to initialize admin sid. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the restricted sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_RESTRICTED_CODE_RID,
|
|
0, 0, 0, 0, 0, 0, 0, &psidRestricted)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to initialize restricted sid. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Allocate space for the ACL
|
|
//
|
|
|
|
cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
|
|
(2 * GetLengthSid (psidAdmin)) + (2 * GetLengthSid (psidRestricted)) +
|
|
sizeof(ACL) +
|
|
(8 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
|
|
|
|
|
|
pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
|
|
if (!pAcl) {
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to initialize acl. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Add Aces for User, System, and Admin. Non-inheritable ACEs first
|
|
//
|
|
|
|
AceIndex = 0;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidUser)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for user. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for system. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for admin. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidRestricted)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for restricted. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Now the inheritable ACEs
|
|
//
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ, psidUser)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for user. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for system. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for admin. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ, psidRestricted)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for restricted. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
|
|
//
|
|
// Put together the security descriptor
|
|
//
|
|
|
|
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to initialize security descriptor. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to set security descriptor dacl. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Open the root of the user's profile
|
|
//
|
|
|
|
Error = RegCreateKeyEx(HKEY_USERS,
|
|
lpKey,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
|
|
NULL,
|
|
&RootKey,
|
|
&dwDisp);
|
|
|
|
if (Error != ERROR_SUCCESS) {
|
|
|
|
DEBUGMSG ((DM_WARNING, "SecureUserKey: Failed to open root of user registry, error = %d", Error));
|
|
|
|
} else {
|
|
|
|
//
|
|
// Set the security descriptor on the key
|
|
//
|
|
|
|
Error = ApplySecurityToRegistryTree(RootKey, &sd);
|
|
|
|
|
|
if (Error == ERROR_SUCCESS) {
|
|
bRetVal = TRUE;
|
|
|
|
} else {
|
|
|
|
DEBUGMSG ((DM_WARNING, "SecureUserKey: Failed to apply security to registry key, error = %d", Error));
|
|
SetLastError(Error);
|
|
}
|
|
|
|
RegCloseKey(RootKey);
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
//
|
|
// Free the sids and acl
|
|
//
|
|
|
|
if (bFreeSid && psidUser) {
|
|
DeleteUserSid (psidUser);
|
|
}
|
|
|
|
if (psidRestricted) {
|
|
FreeSid(psidRestricted);
|
|
}
|
|
|
|
if (psidSystem) {
|
|
FreeSid(psidSystem);
|
|
}
|
|
|
|
if (psidAdmin) {
|
|
FreeSid(psidAdmin);
|
|
}
|
|
|
|
if (pAcl) {
|
|
GlobalFree (pAcl);
|
|
}
|
|
|
|
|
|
//
|
|
// Verbose Output
|
|
//
|
|
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Leaving with a return value of %d", bRetVal));
|
|
|
|
|
|
return(bRetVal);
|
|
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// ProduceWFromA()
|
|
//
|
|
// Purpose: Creates a buffer for a Unicode string and copies
|
|
// the ANSI text into it (converting in the process)
|
|
//
|
|
// Parameters: pszA - ANSI string
|
|
//
|
|
//
|
|
// Return: Unicode pointer if successful
|
|
// NULL if an error occurs
|
|
//
|
|
// Comments: The caller needs to free this pointer.
|
|
//
|
|
//
|
|
// History: Date Author Comment
|
|
// 5/24/95 ericflo Ported
|
|
//
|
|
//*************************************************************
|
|
|
|
LPWSTR ProduceWFromA(LPCSTR pszA)
|
|
{
|
|
LPWSTR pszW;
|
|
int cch;
|
|
|
|
if (!pszA)
|
|
return (LPWSTR)pszA;
|
|
|
|
cch = MultiByteToWideChar(CP_ACP, 0, pszA, -1, NULL, 0);
|
|
|
|
if (cch == 0)
|
|
cch = 1;
|
|
|
|
pszW = LocalAlloc(LPTR, cch * sizeof(WCHAR));
|
|
|
|
if (pszW) {
|
|
if (!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszA, -1, pszW, cch)) {
|
|
LocalFree(pszW);
|
|
pszW = NULL;
|
|
}
|
|
}
|
|
|
|
return pszW;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// IsUserAnAdminMember()
|
|
//
|
|
// Purpose: Determines if the user is a member of the administrators group.
|
|
//
|
|
// Parameters: hToken - User's token
|
|
//
|
|
// Return: TRUE if user is a admin
|
|
// FALSE if not
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 7/25/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL IsUserAnAdminMember(HANDLE hToken)
|
|
{
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
NTSTATUS Status;
|
|
BOOL FoundAdmins = FALSE;
|
|
PSID AdminsDomainSid=NULL;
|
|
HANDLE hImpToken = NULL;
|
|
|
|
//
|
|
// Create Admins domain sid.
|
|
//
|
|
|
|
|
|
Status = RtlAllocateAndInitializeSid(
|
|
&authNT,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0, 0, 0, 0, 0, 0,
|
|
&AdminsDomainSid
|
|
);
|
|
|
|
if (Status == STATUS_SUCCESS) {
|
|
|
|
//
|
|
// Test if user is in the Admins domain
|
|
//
|
|
|
|
if (!DuplicateTokenEx(hToken, TOKEN_IMPERSONATE | TOKEN_QUERY,
|
|
NULL, SecurityImpersonation, TokenImpersonation,
|
|
&hImpToken)) {
|
|
DEBUGMSG((DM_WARNING, "IsUserAnAdminMember: DuplicateTokenEx failed with error %d", GetLastError()));
|
|
FoundAdmins = FALSE;
|
|
hImpToken = NULL;
|
|
goto Exit;
|
|
}
|
|
|
|
if (!CheckTokenMembership(hImpToken, AdminsDomainSid, &FoundAdmins)) {
|
|
DEBUGMSG((DM_WARNING, "IsUserAnAdminmember: CheckTokenMembership failed for AdminsDomainSid with error %d", GetLastError()));
|
|
FoundAdmins = FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Tidy up
|
|
//
|
|
|
|
Exit:
|
|
|
|
if (hImpToken)
|
|
CloseHandle(hImpToken);
|
|
|
|
if (AdminsDomainSid)
|
|
RtlFreeSid(AdminsDomainSid);
|
|
|
|
return(FoundAdmins);
|
|
}
|
|
|