windows-nt/Source/XPSP1/NT/ds/security/gina/profmap/dll/userenv.c
2020-09-26 16:20:57 +08:00

2167 lines
53 KiB
C

#include "pch.h"
//*************************************************************
//
// CheckSlash()
//
// Purpose: Checks for an ending slash and adds one if
// it is missing.
//
// Parameters: lpDir - directory
//
// Return: Pointer to the end of the string
//
// Comments:
//
// History: Date Author Comment
// 6/19/95 ericflo Created
//
//*************************************************************
LPTSTR CheckSlash (LPTSTR lpDir)
{
LPTSTR lpEnd;
lpEnd = lpDir + lstrlen(lpDir);
if (*(lpEnd - 1) != TEXT('\\')) {
*lpEnd = TEXT('\\');
lpEnd++;
*lpEnd = TEXT('\0');
}
return lpEnd;
}
//*************************************************************
//
// RegDelnodeRecurse()
//
// Purpose: Deletes a registry key and all it's subkeys / values.
// Called by RegDelnode
//
// Parameters: hKeyRoot - Root key
// lpSubKey - SubKey to delete
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 10/3/95 ericflo Created
//
//*************************************************************
BOOL RegDelnodeRecurse (HKEY hKeyRoot, PWSTR lpSubKey)
{
PWSTR End;
LONG rc;
DWORD dwSize;
WCHAR szName[MAX_PATH];
HKEY hKey;
FILETIME ftWrite;
//
// First, see if we can delete the key without having
// to recurse.
//
rc = RegDeleteKey(hKeyRoot, lpSubKey);
if (rc == ERROR_SUCCESS) {
return TRUE;
}
rc = RegOpenKeyEx (hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
if (rc != ERROR_SUCCESS) {
if (rc == ERROR_FILE_NOT_FOUND) {
return TRUE;
} else {
return FALSE;
}
}
End = CheckSlash(lpSubKey);
//
// Enumerate the keys
//
dwSize = MAX_PATH;
rc = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
NULL, NULL, &ftWrite);
if (rc == ERROR_SUCCESS) {
do {
lstrcpy (End, szName);
if (!RegDelnodeRecurse(hKeyRoot, lpSubKey)) {
break;
}
//
// Enumerate again
//
dwSize = MAX_PATH;
rc = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
NULL, NULL, &ftWrite);
} while (rc == ERROR_SUCCESS);
}
End--;
*End = TEXT('\0');
RegCloseKey (hKey);
//
// Try again to delete the key
//
rc = RegDeleteKey(hKeyRoot, lpSubKey);
if (rc == ERROR_SUCCESS) {
return TRUE;
}
return FALSE;
}
//*************************************************************
//
// RegDelnode()
//
// Purpose: Deletes a registry key and all it's subkeys / values
//
// Parameters: hKeyRoot - Root key
// lpSubKey - SubKey to delete
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 10/3/95 ericflo Created
//
//*************************************************************
BOOL RegDelnode (HKEY hKeyRoot, PWSTR lpSubKey)
{
WCHAR szDelKey[2 * MAX_PATH];
lstrcpy (szDelKey, lpSubKey);
return RegDelnodeRecurse(hKeyRoot, szDelKey);
}
//*************************************************************
//
// CreateNestedDirectory()
//
// Purpose: Creates a subdirectory and all it's parents
// if necessary.
//
// Parameters: lpDirectory - Directory name
// lpSecurityAttributes - Security Attributes
//
// Return: > 0 if successful
// 0 if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 8/08/95 ericflo Created
//
//*************************************************************
UINT CreateNestedDirectory(LPCTSTR lpDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
TCHAR szDirectory[2*MAX_PATH];
LPTSTR lpEnd;
PACL Acl;
BOOL Present;
BOOL Defaulted;
//
// Check for NULL pointer
//
if (!lpDirectory || !(*lpDirectory)) {
DEBUGMSG ((DM_WARNING, "CreateNestedDirectory: Received a NULL pointer."));
return 0;
}
//
// First, see if we can create the directory without having
// to build parent directories.
//
if (CreateDirectory (lpDirectory, lpSecurityAttributes)) {
return 1;
}
//
// If this directory exists already, this is OK too.
//
if (GetLastError() == ERROR_ALREADY_EXISTS) {
//
// Update the security
//
if (lpSecurityAttributes) {
if (!GetSecurityDescriptorDacl (
lpSecurityAttributes->lpSecurityDescriptor,
&Present,
&Acl,
&Defaulted
)) {
Present = FALSE;
}
if (Present && !Defaulted) {
if (!SetNamedSecurityInfo (
(PTSTR) lpDirectory,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION|PROTECTED_DACL_SECURITY_INFORMATION,
NULL,
NULL,
Acl,
NULL
)) {
return GetLastError();
}
}
}
return ERROR_ALREADY_EXISTS;
}
//
// No luck, copy the string to a buffer we can munge
//
lstrcpy (szDirectory, lpDirectory);
//
// Find the first subdirectory name
//
lpEnd = szDirectory;
if (szDirectory[1] == TEXT(':')) {
lpEnd += 3;
} else if (szDirectory[1] == TEXT('\\')) {
//
// Skip the first two slashes
//
lpEnd += 2;
//
// Find the slash between the server name and
// the share name.
//
while (*lpEnd && *lpEnd != TEXT('\\')) {
lpEnd++;
}
if (!(*lpEnd)) {
return 0;
}
//
// Skip the slash, and find the slash between
// the share name and the directory name.
//
lpEnd++;
while (*lpEnd && *lpEnd != TEXT('\\')) {
lpEnd++;
}
if (!(*lpEnd)) {
return 0;
}
//
// Leave pointer at the beginning of the directory.
//
lpEnd++;
} else if (szDirectory[0] == TEXT('\\')) {
lpEnd++;
}
while (*lpEnd) {
while (*lpEnd && *lpEnd != TEXT('\\')) {
lpEnd++;
}
if (*lpEnd == TEXT('\\')) {
*lpEnd = TEXT('\0');
if (!CreateDirectory (szDirectory, NULL)) {
if (GetLastError() != ERROR_ALREADY_EXISTS) {
DEBUGMSG ((DM_WARNING, "CreateNestedDirectory: CreateDirectory failed with %d.", GetLastError()));
return 0;
}
}
*lpEnd = TEXT('\\');
lpEnd++;
}
}
//
// Create the final directory
//
if (CreateDirectory (szDirectory, lpSecurityAttributes)) {
return 1;
}
if (GetLastError() == ERROR_ALREADY_EXISTS) {
return ERROR_ALREADY_EXISTS;
}
//
// Failed
//
DEBUGMSG ((DM_VERBOSE, "CreateNestedDirectory: Failed to create the directory with error %d.", GetLastError()));
return 0;
}
//*************************************************************
//
// CreateSecureDirectory()
//
// Purpose: Creates a secure directory that only the user,
// admin, and system have access to in the normal case
// and for only the user and system in the restricted case.
//
//
// Parameters: lpDirectory - Directory Name
// pSid - Sid (used by CreateUserProfile)
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 7/20/95 ericflo Created
// 9/30/98 ushaji added fRestricted flag
//
//*************************************************************
BOOL CreateSecureDirectory (LPTSTR lpDirectory, PSID pSid)
{
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
PACL pAcl = NULL;
BOOL bRetVal = FALSE;
//
// Verbose Output
//
DEBUGMSG ((DM_VERBOSE, "CreateSecureDirectory: Entering with <%s>", lpDirectory));
if (!pSid) {
//
// Attempt to create the directory
//
if (CreateNestedDirectory(lpDirectory, NULL)) {
DEBUGMSG ((DM_VERBOSE, "CreateSecureDirectory: Created the directory <%s>", lpDirectory));
bRetVal = TRUE;
} else {
DEBUGMSG ((DM_VERBOSE, "CreateSecureDirectory: Failed to created the directory <%s>", lpDirectory));
}
goto Exit;
}
//
// Get the default ACL
//
pAcl = CreateDefaultAcl (pSid);
//
// Put together the security descriptor
//
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
DEBUGMSG ((DM_VERBOSE, "CreateSecureDirectory: Failed to initialize security descriptor. Error = %d", GetLastError()));
goto Exit;
}
if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
DEBUGMSG ((DM_VERBOSE, "CreateSecureDirectory: Failed to set security descriptor dacl. Error = %d", GetLastError()));
goto Exit;
}
//
// Add the security descriptor to the sa structure
//
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;
//
// Attempt to create the directory
//
if (CreateNestedDirectory(lpDirectory, &sa)) {
DEBUGMSG ((DM_VERBOSE, "CreateSecureDirectory: Created the directory <%s>", lpDirectory));
bRetVal = TRUE;
} else {
DEBUGMSG ((DM_VERBOSE, "CreateSecureDirectory: Failed to created the directory <%s>", lpDirectory));
}
Exit:
FreeDefaultAcl (pAcl);
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
)
{
WCHAR LocalProfileKey[MAX_PATH];
HKEY hKey;
DWORD Size;
DWORD Type;
DWORD Attributes;
PWSTR SidString;
WCHAR ExpandedRoot[MAX_PATH];
ProfileDir[0] = 0;
if (!OurConvertSidToStringSid (Sid, &SidString)) {
DEBUGMSG ((DM_WARNING, "GetProfileRoot: Can't convert SID to string"));
return FALSE;
}
//
// Check if this user's profile exists
//
lstrcpy (LocalProfileKey, PROFILE_LIST_PATH);
lstrcat (LocalProfileKey, TEXT("\\"));
lstrcat (LocalProfileKey, SidString);
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, LocalProfileKey,
0, KEY_READ, &hKey) == ERROR_SUCCESS) {
Size = MAX_PATH;
RegQueryValueEx (hKey, PROFILE_IMAGE_VALUE_NAME, NULL,
&Type, (LPBYTE) ProfileDir, &Size);
RegCloseKey (hKey);
}
if (ProfileDir[0]) {
ExpandEnvironmentStrings (ProfileDir, ExpandedRoot, MAX_PATH);
Attributes = GetFileAttributes (ExpandedRoot);
if (Attributes == 0xFFFFFFFF || !(Attributes & FILE_ATTRIBUTE_DIRECTORY)) {
ProfileDir[0] = 0;
DEBUGMSG ((DM_VERBOSE, "GetProfileRoot: Profile %s is not vaild", SidString));
} else {
lstrcpy (ProfileDir, ExpandedRoot);
}
} else {
DEBUGMSG ((DM_VERBOSE, "GetProfileRoot: SID %s does not have a profile directory", SidString));
}
DeleteSidString (SidString);
return ProfileDir[0] != 0;
}
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;
DWORD dwSize;
DWORD dwType;
HKEY hKey;
BOOL b = FALSE;
BOOL UnloadProfile = FALSE;
__try {
//
// Convert the sid into text format
//
if (!OurConvertSidToStringSid (Sid, &SidString)) {
DEBUGMSG ((
DM_WARNING,
"UpdateProfileSecurity: Can't convert SID to string"
));
__leave;
}
//
// Check if this user's profile exists already
//
lstrcpy(LocalProfileKey, PROFILE_LIST_PATH);
lstrcat(LocalProfileKey, TEXT("\\"));
lstrcat(LocalProfileKey, SidString);
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"));
SetLastError (ERROR_BAD_PROFILE);
__leave;
}
//
// The user has a profile, so update the security settings
//
ExpandEnvironmentStrings (
ProfileDir,
ExpProfileDir,
ARRAYSIZE(ExpProfileDir)
);
//
// Load the hive temporary so the security can be fixed
//
End = CheckSlash (ExpProfileDir);
Save = End - 1;
lstrcpy (End, L"NTUSER.DAT");
rc = MyRegLoadKey (HKEY_USERS, SidString, ExpProfileDir);
*Save = 0;
if (rc != ERROR_SUCCESS) {
DEBUGMSG((DM_WARNING, "UpdateProfileSecurity: Failed to load hive, error = %d.", rc));
SetLastError (rc);
__leave;
}
UnloadProfile = TRUE;
if (!SetupNewHive (SidString, Sid)) {
DEBUGMSG((DM_WARNING, "UpdateProfileSecurity: SetupNewHive failed, error = %d.", GetLastError()));
__leave;
}
//
// Fix the file system security
//
if (!CreateSecureDirectory (ExpProfileDir, Sid)) {
DEBUGMSG((DM_WARNING, "UpdateProfileSecurity: CreateSecureDirectory failed, error = %d.", GetLastError()));
__leave;
}
b = TRUE;
}
__finally {
dwError = GetLastError();
if (UnloadProfile) {
MyRegUnLoadKey (HKEY_USERS, SidString);
}
DeleteSidString (SidString);
SetLastError (dwError);
}
return b;
}
//*************************************************************
//
// DeleteProfileRegistrySettings()
//
// Purpose: Deletes the specified profile from the
// registry.
//
// Parameters: lpSidString - Registry subkey
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/23/95 ericflo Created
// 5/20/99 jimschm Moved out of DeleteProfile
//
//*************************************************************
BOOL DeleteProfileRegistrySettings (LPTSTR lpSidString)
{
LONG lResult;
TCHAR szTemp[MAX_PATH];
TCHAR szUserGuid[MAX_PATH];
HKEY hKey;
DWORD dwType, dwSize;
if (lpSidString && *lpSidString) {
lstrcpy(szTemp, PROFILE_LIST_PATH);
lstrcat(szTemp, TEXT("\\"));
lstrcat(szTemp, lpSidString);
//
// get the user guid
//
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szTemp, 0, KEY_READ, &hKey);
if (lResult == ERROR_SUCCESS) {
//
// Query for the user guid
//
dwSize = MAX_PATH * sizeof(TCHAR);
lResult = RegQueryValueEx (hKey, PROFILE_GUID, NULL, &dwType, (LPBYTE) szUserGuid, &dwSize);
if (lResult != ERROR_SUCCESS) {
DEBUGMSG((DM_WARNING, "DeleteProfile: Failed to query profile guid with error %d", lResult));
}
else {
lstrcpy(szTemp, PROFILE_GUID_PATH);
lstrcat(szTemp, TEXT("\\"));
lstrcat(szTemp, szUserGuid);
//
// 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));
}
}
RegCloseKey(hKey);
}
lstrcpy(szTemp, PROFILE_LIST_PATH);
lstrcat(szTemp, TEXT("\\"));
lstrcat(szTemp, lpSidString);
lResult = RegDeleteKey(HKEY_LOCAL_MACHINE, szTemp);
if (lResult != ERROR_SUCCESS) {
DEBUGMSG((DM_WARNING, "DeleteProfile: Unable to delete registry entry. Error = %d", lResult));
SetLastError(lResult);
return FALSE;
}
}
return TRUE;
}
/***************************************************************************\
* 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;
int error;
DWORD dwException;
WCHAR szException[20];
__try {
//
// Enable the restore privilege
//
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, TRUE, &WasEnabled);
if (NT_SUCCESS(Status)) {
error = RegLoadKey(hKey, lpSubKey, lpFile);
//
// Restore the privilege to its previous state
//
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, TRUE, &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) {
dwException = GetExceptionCode();
ASSERT(dwException == 0);
wsprintf(szException, L"!!!! 0x%x ", dwException);
OutputDebugString(szException);
OutputDebugString(L"Exception hit in MyRegLoadKey in userenv\n");
ASSERT(dwException == 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;
DWORD dwException;
WCHAR szException[20];
__try {
//
// Enable the restore privilege
//
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, TRUE, &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, TRUE, &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) {
dwException = GetExceptionCode();
ASSERT(dwException == 0);
wsprintf(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;
//
// Verbose Output
//
DEBUGMSG((DM_VERBOSE, "SetupNewHive: Entering"));
//
// Open the root of the user's profile
//
Error = RegOpenKeyEx(HKEY_USERS,
lpSidString,
0,
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.
//
lstrcpy (szSubKey, lpSidString);
lpEnd = CheckSlash(szSubKey);
lstrcpy (lpEnd, WINDOWS_POLICIES_KEY);
if (!SecureUserKey(szSubKey, pSid)) {
DEBUGMSG((DM_WARNING, "SetupNewHive: Failed to secure windows policies key"));
}
lstrcpy (lpEnd, ROOT_POLICIES_KEY);
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 cchSubKeySize = MAX_PATH + 1;
//
// First apply security
//
RegSetKeySecurity(RootKey, DACL_SECURITY_INFORMATION, pSD);
//
// Open each sub-key and apply security to its sub-tree
//
SubKeyIndex = 0;
SubKeyName = GlobalAlloc (GPTR, cchSubKeySize * 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, cchSubKeySize);
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,
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);
}