#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); }