windows-nt/Source/XPSP1/NT/shell/osshell/progman/security.c
2020-09-26 16:20:57 +08:00

473 lines
12 KiB
C

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