|
|
/****************************** Module Header ******************************\
* Module Name: security.c * * Copyright (c) 1992, Microsoft Corporation * * Handles security aspects of progman operation. * * History: * 01-16-92 JohanneC Created - mostly taken from old winlogon.c \***************************************************************************/
#include "sec.h"
#include <string.h>
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#include <lm.h>
/***************************************************************************\
* SetMyAce * * Helper routine that fills in a MYACE structure. * * History: * 02-06-92 Davidc Created \***************************************************************************/ VOID SetMyAce( PMYACE MyAce, PSID Sid, ACCESS_MASK Mask, UCHAR InheritFlags ) { MyAce->Sid = Sid; MyAce->AccessMask= Mask; MyAce->InheritFlags = InheritFlags; }
/***************************************************************************\
* SetWorldSecurity * * Sets the security given the logon sid passed. * * If the UserSid = NULL, no access is given to anyone other than world * Users will have read access and if bWriteAccess is TRUE, they will also * have write access. * * Returns TRUE on success, FALSE on failure * * History: * 04-16-91 Johannec Created \***************************************************************************/ BOOL SetWorldSecurity( PSID UserSid, PSECURITY_DESCRIPTOR *pSecDesc, BOOL bWriteAccess ) { MYACE Ace[4]; ACEINDEX AceCount = 0; PSECURITY_DESCRIPTOR SecurityDescriptor; PSID WorldSid = NULL; PSID AdminAliasSid = NULL; PSID PowerUserAliasSid = NULL; PSID SystemOpsAliasSid = NULL; SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; NTSTATUS Status; ACCESS_MASK AccessMask;
// Create the world Sid
Status = RtlAllocateAndInitializeSid( &WorldSidAuthority, 1, // Sub authority count
SECURITY_WORLD_RID, // Sub authorities
0, 0, 0, 0, 0, 0, 0, &WorldSid);
if (!NT_SUCCESS(Status)) { DbgOnlyPrint("progman failed to allocate memory for world sid\n"); return(FALSE); }
Status = RtlAllocateAndInitializeSid( &NtAuthority, 2, // Sub authority count
SECURITY_BUILTIN_DOMAIN_RID, // Sub authority[0]
DOMAIN_ALIAS_RID_ADMINS, // Sub authority[1]
0, 0, 0, 0, 0, 0, &AdminAliasSid);
Status = RtlAllocateAndInitializeSid( &NtAuthority, 2, // Sub authority count
SECURITY_BUILTIN_DOMAIN_RID, // Sub authority[0]
DOMAIN_ALIAS_RID_POWER_USERS, // Sub authority[1]
0, 0, 0, 0, 0, 0, &PowerUserAliasSid);
Status = RtlAllocateAndInitializeSid( &NtAuthority, 2, // Sub authority count
SECURITY_BUILTIN_DOMAIN_RID, // Sub authority[0]
DOMAIN_ALIAS_RID_SYSTEM_OPS, // Sub authority[1]
0, 0, 0, 0, 0, 0, &SystemOpsAliasSid);
if (!NT_SUCCESS(Status)) { DbgOnlyPrint("progman failed to allocate memory for admin sid\n"); return(FALSE); }
//
// Define the World ACEs
//
if (bWriteAccess) { AccessMask = KEY_READ | KEY_WRITE | DELETE; } else { AccessMask = KEY_READ; }
SetMyAce(&(Ace[AceCount++]), WorldSid, AccessMask, NO_PROPAGATE_INHERIT_ACE );
//
// Define the Admins ACEs
//
SetMyAce(&(Ace[AceCount++]), AdminAliasSid, GENERIC_ALL, NO_PROPAGATE_INHERIT_ACE );
//
// Define the Power Users ACEs
//
SetMyAce(&(Ace[AceCount++]), PowerUserAliasSid, GENERIC_ALL, NO_PROPAGATE_INHERIT_ACE );
//
// Define the System Operators ACEs
//
SetMyAce(&(Ace[AceCount++]), SystemOpsAliasSid, GENERIC_ALL, NO_PROPAGATE_INHERIT_ACE );
// Check we didn't goof
ASSERT((sizeof(Ace) / sizeof(MYACE)) >= AceCount);
//
// Create the security descriptor
//
SecurityDescriptor = CreateSecurityDescriptor(Ace, AceCount); if (SecurityDescriptor == NULL) { DbgOnlyPrint("Progman failed to create security descriptor\n\r"); return(FALSE); }
#if 0
// Keep security descriptor global
// delete only when exiting the program
//
// Free up the security descriptor
//
DeleteSecurityDescriptor(SecurityDescriptor); #endif
//
// Return success status
//
*pSecDesc = SecurityDescriptor; return(TRUE); }
/***************************************************************************\
* InitializeSecurityAttributes * * * Returns TRUE on success, FALSE on failure * * History: * 04-14-92 JohanneC Created \***************************************************************************/ BOOL InitializeSecurityAttributes(PSECURITY_ATTRIBUTES pSecurityAttributes, BOOL bWriteAccess) { PSECURITY_DESCRIPTOR pSecDesc;
if (!SetWorldSecurity(NULL, &pSecDesc, bWriteAccess)) { return(FALSE); }
pSecurityAttributes->nLength = sizeof(SECURITY_ATTRIBUTES); pSecurityAttributes->lpSecurityDescriptor = pSecDesc; pSecurityAttributes->bInheritHandle = TRUE;
return(TRUE); }
BOOL TestTokenForAdmin( HANDLE Token );
/***************************************************************************\
* TestUserForAdmin * * * Returns TRUE if the current user is part of the ADMIN group, * FALSE otherwise * * History: * 07-15-92 JohanneC Created \***************************************************************************/ BOOL TestUserForAdmin() { BOOL UserIsAdmin = FALSE; HANDLE Token; #if 0
ACCESS_MASK GrantedAccess; GENERIC_MAPPING GenericMapping; PPRIVILEGE_SET pPrivilegeSet; DWORD dwPrivilegeSetLength; MYACE Ace[1]; PSECURITY_DESCRIPTOR pSecDesc; NTSTATUS Status; #endif
PSID AdminAliasSid = NULL; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
//
// Get the token of the current process.
//
if (!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &Token ) ) { DbgOnlyPrint("Progman: Can't open own process token for token_query access\n\r"); return(FALSE); }
#if 0
// not working because of error = STATUS_NO_IMPERSONATION_TOKEN
so use the code from winlogon instead (see #else)
Status = RtlAllocateAndInitializeSid( &NtAuthority, 2, // Sub authority count
SECURITY_BUILTIN_DOMAIN_RID, // Sub authority[0]
DOMAIN_ALIAS_RID_ADMINS, // Sub authority[1]
0, 0, 0, 0, 0, 0, &AdminAliasSid);
if (!NT_SUCCESS(Status)) { DbgOnlyPrint(TEXT("progman failed to allocate memory for admin sid\n")); goto Exit; }
//
// Define the Admins ACEs
//
SetMyAce(&(Ace[0]), AdminAliasSid, GENERIC_ALL, NO_PROPAGATE_INHERIT_ACE );
//
// Create the security descriptor
//
pSecDesc = CreateSecurityDescriptor(Ace, 1); if (pSecDesc == NULL) { DbgOnlyPrint(TEXT("Progman failed to create security descriptor\n\r")); goto Exit; }
//
// Allocate memory for the PrivilegeSet buffer
//
dwPrivilegeSetLength = 256; pPrivilegeSet = Alloc(dwPrivilegeSetLength); if (!pPrivilegeSet) { DbgOnlyPrint(TEXT("Progman: Can't alloc memory for privilege set\n\r")); goto FreeSecDesc; }
//
// Test if user has admin privileges.
//
if(!AccessCheck(pSecDesc, Token, STANDARD_RIGHTS_ALL, &GenericMapping, pPrivilegeSet, &dwPrivilegeSetLength, &GrantedAccess, &UserIsAdmin) ){
DbgOnlyPrint(TEXT("Progman: AccessCheck failed, error = %d\n\r"), GetLastError()); }
//
// Free up the the PrivilegeSet
//
Free(pPrivilegeSet);
FreeSecDesc:
//
// Free up the security descriptor
//
DeleteSecurityDescriptor(pSecDesc);
#else
UserIsAdmin = TestTokenForAdmin(Token);
#endif
//Exit:
//
// We are finished with the token.
//
CloseHandle(Token);
return(UserIsAdmin); } /***************************************************************************\
* TestTokenForAdmin * * Returns TRUE if the token passed represents an admin user, otherwise FALSE * * The token handle passed must have TOKEN_QUERY access. * * History: * 08-01-92 JohanneC Extracted code from winlogon * 05-06-92 Davidc Created \***************************************************************************/ BOOL TestTokenForAdmin( HANDLE Token ) { NTSTATUS Status; DWORD InfoLength; PTOKEN_GROUPS TokenGroupList; DWORD GroupIndex; PSID AdminSid; BOOL FoundAdmin; SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
//
// Get a list of groups in the token
//
Status = NtQueryInformationToken( Token, // Handle
TokenGroups, // TokenInformationClass
NULL, // TokenInformation
0, // TokenInformationLength
&InfoLength // ReturnLength
);
if ((Status != STATUS_SUCCESS) && (Status != STATUS_BUFFER_TOO_SMALL)) {
DbgOnlyPrint("Winlogon failed to get group info for admin token, status = 0x%lx\n", Status); return(FALSE); }
TokenGroupList = Alloc(InfoLength);
if (TokenGroupList == NULL) { DbgOnlyPrint("Winlogon unable to allocate memory for token groups\n"); return(FALSE); }
Status = NtQueryInformationToken( Token, // Handle
TokenGroups, // TokenInformationClass
TokenGroupList, // TokenInformation
InfoLength, // TokenInformationLength
&InfoLength // ReturnLength
);
if (!NT_SUCCESS(Status)) { DbgOnlyPrint("Winlogon failed to query groups for admin token, status = 0x%lx\n", Status); Free(TokenGroupList); return(FALSE); }
//
// Create the admin sid
//
Status = RtlAllocateAndInitializeSid( &SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid);
if (!NT_SUCCESS(Status)) { DbgOnlyPrint("Winlogon failed to initialize admin alias sid\n"); Free(TokenGroupList); return(FALSE); }
//
// Search group list for admin alias
//
FoundAdmin = FALSE;
for (GroupIndex=0; GroupIndex < TokenGroupList->GroupCount; GroupIndex++ ) {
if (RtlEqualSid(TokenGroupList->Groups[GroupIndex].Sid, AdminSid)) { FoundAdmin = TRUE; break; } }
//
// Tidy up
//
RtlFreeSid(AdminSid); Free(TokenGroupList);
return(FoundAdmin); }
|