437 lines
9.4 KiB
C
437 lines
9.4 KiB
C
|
// ----------------------------------------------------------------------------
|
||
|
//
|
||
|
// SecDescr.c
|
||
|
//
|
||
|
//
|
||
|
// Author: Jost Eckhardt
|
||
|
//
|
||
|
// This code was written for ECO Kommunikation Insight
|
||
|
// Copyright (c) 1997-1999 Microsoft Corporation
|
||
|
// ----------------------------------------------------------------------------
|
||
|
#include <windows.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <malloc.h>
|
||
|
#include <TCHAR.h>
|
||
|
#include <WinSvc.h>
|
||
|
#include "_UMTool.h"
|
||
|
|
||
|
static PSECURITY_DESCRIPTOR GetObjectSecurityDescr(
|
||
|
obj_sec_descr_tsp obj,
|
||
|
DWORD dwAccessMaskOwner,
|
||
|
DWORD dwAccessMaskLoggedOnUser);
|
||
|
static BOOL GetUserSidFromToken(HANDLE hToken, PSID *ppSid);
|
||
|
static BOOL GetGroupSidFromToken(HANDLE hToken, PSID *ppSid);
|
||
|
|
||
|
// ---------------------------
|
||
|
// InitSecurityAttributes - initialize the security descriptor in the
|
||
|
// obj_sec_attr_tsp struct using a null DACL.
|
||
|
//
|
||
|
// Caller must call ClearSecurityAttributes when done with the struct.
|
||
|
//
|
||
|
void InitSecurityAttributes(obj_sec_attr_tsp psa)
|
||
|
{
|
||
|
memset(psa,0,sizeof(obj_sec_attr_ts));
|
||
|
psa->sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||
|
|
||
|
psa->sa.bInheritHandle = TRUE;
|
||
|
psa->sa.lpSecurityDescriptor = GetObjectSecurityDescr(&psa->objsd, 0, 0);
|
||
|
}
|
||
|
|
||
|
// ---------------------------
|
||
|
// InitSecurityAttributesEx - initialize the security descriptor in the
|
||
|
// obj_sec_attr_tsp struct using a non-null DACL
|
||
|
//
|
||
|
// dwAccessMaskOwner - If non-zero specifies the access allowed to the creator
|
||
|
// dwAccessMaskLoggedOnUser - If non-zero specifies the access allowed to the current user
|
||
|
//
|
||
|
// If dwAccessMaskOwner and dwAccessMaskLoggedOnUser are zero the security descriptor
|
||
|
// will have a NULL DACL. Caller must call ClearSecurityAttributes when done
|
||
|
// with the struct.
|
||
|
//
|
||
|
void InitSecurityAttributesEx(obj_sec_attr_tsp psa, DWORD dwAccessMaskOwner, DWORD dwAccessMaskLoggedOnUser)
|
||
|
{
|
||
|
memset(psa,0,sizeof(obj_sec_attr_ts));
|
||
|
psa->sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||
|
|
||
|
psa->sa.bInheritHandle = TRUE;
|
||
|
psa->sa.lpSecurityDescriptor = GetObjectSecurityDescr(&psa->objsd, dwAccessMaskOwner, dwAccessMaskLoggedOnUser);
|
||
|
}
|
||
|
|
||
|
// ---------------------------
|
||
|
// ClearSecurityAttributes - free memory from the security descriptor
|
||
|
//
|
||
|
void ClearSecurityAttributes(obj_sec_attr_tsp psa)
|
||
|
{
|
||
|
if (psa->sa.lpSecurityDescriptor)
|
||
|
free(psa->sa.lpSecurityDescriptor);
|
||
|
|
||
|
if (psa->objsd.psidUser)
|
||
|
free(psa->objsd.psidUser);
|
||
|
|
||
|
if (psa->objsd.psidGroup)
|
||
|
free(psa->objsd.psidGroup);
|
||
|
|
||
|
memset(psa,0,sizeof(obj_sec_attr_ts));
|
||
|
}
|
||
|
|
||
|
// ---------------------------
|
||
|
static PSECURITY_DESCRIPTOR GetObjectSecurityDescr(
|
||
|
obj_sec_descr_tsp obj,
|
||
|
DWORD dwAccessMaskOwner,
|
||
|
DWORD dwAccessMaskLoggedOnUser)
|
||
|
{
|
||
|
PSECURITY_DESCRIPTOR psd = NULL;
|
||
|
HANDLE hToken;
|
||
|
GENERIC_MAPPING gm = {1, 2, 4, 8};
|
||
|
DWORD dwDesired = 1;
|
||
|
BOOL fAccess = FALSE;
|
||
|
DWORD dwGranted;
|
||
|
PRIVILEGE_SET ps;
|
||
|
DWORD cbPriv = sizeof (ps);
|
||
|
PACL pAcl;
|
||
|
ULONG cbAcl;
|
||
|
PSID psidCurUser;
|
||
|
|
||
|
obj->psidUser = obj->psidGroup = NULL;
|
||
|
|
||
|
// Get the user's SID
|
||
|
|
||
|
if (!ImpersonateSelf(SecurityImpersonation))
|
||
|
return NULL;
|
||
|
|
||
|
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken))
|
||
|
goto GSSD_ERROR;
|
||
|
|
||
|
if (!GetUserSidFromToken(hToken, &obj->psidUser))
|
||
|
goto GSSD_ERROR;
|
||
|
|
||
|
// assumption: if either access masks are given
|
||
|
// then the owner access mask must be given
|
||
|
|
||
|
if (dwAccessMaskLoggedOnUser && !dwAccessMaskOwner)
|
||
|
goto GSSD_ERROR;
|
||
|
|
||
|
// Figure the size of an access-allowed ACL (if an
|
||
|
// access mask is supplied there will be one ACE)
|
||
|
|
||
|
cbAcl = 0;
|
||
|
if (dwAccessMaskOwner)
|
||
|
{
|
||
|
cbAcl = sizeof(ACL)
|
||
|
+ sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)
|
||
|
+ GetLengthSid(obj->psidUser);
|
||
|
}
|
||
|
|
||
|
psidCurUser = 0;
|
||
|
if (dwAccessMaskLoggedOnUser)
|
||
|
{
|
||
|
psidCurUser = InteractiveUserSid(TRUE);
|
||
|
if (psidCurUser)
|
||
|
{
|
||
|
cbAcl += sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)
|
||
|
+ GetLengthSid(psidCurUser);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Allocate space for the SD and the ACL
|
||
|
|
||
|
psd = malloc(SECURITY_DESCRIPTOR_MIN_LENGTH + cbAcl);
|
||
|
|
||
|
if (!psd)
|
||
|
goto GSSD_ERROR;
|
||
|
|
||
|
// Add ACEs to the ACL if specified
|
||
|
|
||
|
pAcl = NULL;
|
||
|
if (dwAccessMaskOwner)
|
||
|
{
|
||
|
// Point to the ACL in the security descriptor
|
||
|
|
||
|
pAcl = (ACL *)((BYTE *)psd + SECURITY_DESCRIPTOR_MIN_LENGTH);
|
||
|
|
||
|
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION))
|
||
|
goto GSSD_ERROR;
|
||
|
|
||
|
// Set access allowed for creator
|
||
|
|
||
|
if (!AddAccessAllowedAce(pAcl,
|
||
|
ACL_REVISION,
|
||
|
dwAccessMaskOwner,
|
||
|
obj->psidUser))
|
||
|
goto GSSD_ERROR;
|
||
|
|
||
|
// Set access allowed for everyone else
|
||
|
|
||
|
if (psidCurUser)
|
||
|
{
|
||
|
if (!AddAccessAllowedAce(pAcl,
|
||
|
ACL_REVISION,
|
||
|
dwAccessMaskLoggedOnUser,
|
||
|
psidCurUser))
|
||
|
goto GSSD_ERROR;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Initialize the security descriptor etc...
|
||
|
|
||
|
if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
|
||
|
goto GSSD_ERROR;
|
||
|
if (!SetSecurityDescriptorDacl(psd, TRUE, (dwAccessMaskOwner)?pAcl:NULL, FALSE))
|
||
|
goto GSSD_ERROR;
|
||
|
if (!SetSecurityDescriptorOwner(psd, obj->psidUser, FALSE))
|
||
|
goto GSSD_ERROR;
|
||
|
if (!GetGroupSidFromToken(hToken, &obj->psidGroup))
|
||
|
goto GSSD_ERROR;
|
||
|
if (!SetSecurityDescriptorGroup(psd, obj->psidGroup, FALSE))
|
||
|
goto GSSD_ERROR;
|
||
|
if (!AccessCheck(psd, hToken, dwDesired, &gm, &ps, &cbPriv,&dwGranted, &fAccess))
|
||
|
goto GSSD_ERROR;
|
||
|
|
||
|
RevertToSelf();
|
||
|
|
||
|
return psd;
|
||
|
|
||
|
GSSD_ERROR:
|
||
|
|
||
|
if (psd)
|
||
|
free(psd);
|
||
|
if (obj->psidUser)
|
||
|
free(obj->psidUser);
|
||
|
if (obj->psidGroup)
|
||
|
free(obj->psidGroup);
|
||
|
|
||
|
RevertToSelf();
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
// ----------------------------------------
|
||
|
static BOOL GetGroupSidFromToken(HANDLE hToken, PSID *ppSid)
|
||
|
{
|
||
|
TOKEN_PRIMARY_GROUP *pGroup = NULL;
|
||
|
PSID psidGroup = NULL;
|
||
|
DWORD cbSid;
|
||
|
DWORD cbRequired;
|
||
|
|
||
|
if (GetTokenInformation(hToken, TokenPrimaryGroup, NULL, 0, &cbRequired))
|
||
|
return FALSE;
|
||
|
|
||
|
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||
|
return FALSE;
|
||
|
|
||
|
pGroup = malloc(cbRequired);
|
||
|
|
||
|
if (!pGroup)
|
||
|
return FALSE;
|
||
|
|
||
|
if (!GetTokenInformation(hToken, TokenPrimaryGroup, pGroup,cbRequired, &cbRequired))
|
||
|
goto GGSFT_ERROR;
|
||
|
|
||
|
cbSid = GetLengthSid(pGroup->PrimaryGroup);
|
||
|
psidGroup = malloc(cbSid);
|
||
|
|
||
|
if (!psidGroup)
|
||
|
goto GGSFT_ERROR;
|
||
|
|
||
|
if (!CopySid(cbSid, psidGroup, pGroup->PrimaryGroup))
|
||
|
goto GGSFT_ERROR;
|
||
|
|
||
|
*ppSid = psidGroup;
|
||
|
psidGroup = NULL;
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
GGSFT_ERROR:
|
||
|
|
||
|
if (psidGroup)
|
||
|
free(psidGroup);
|
||
|
|
||
|
free(pGroup);
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// ----------------------------------------
|
||
|
static BOOL GetUserSidFromToken(HANDLE hToken, PSID *ppSid)
|
||
|
{
|
||
|
TOKEN_USER *pUser = NULL;
|
||
|
PSID psidUser = NULL;
|
||
|
DWORD cbSid;
|
||
|
DWORD cbRequired;
|
||
|
|
||
|
if (GetTokenInformation(hToken, TokenUser, NULL, 0, &cbRequired))
|
||
|
return FALSE;
|
||
|
|
||
|
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER )
|
||
|
return FALSE;
|
||
|
|
||
|
pUser = malloc(cbRequired);
|
||
|
|
||
|
if (!pUser)
|
||
|
return FALSE;
|
||
|
|
||
|
if (!GetTokenInformation(hToken, TokenUser, pUser, cbRequired,&cbRequired))
|
||
|
goto GUSFT_ERROR;
|
||
|
|
||
|
cbSid = GetLengthSid(pUser->User.Sid);
|
||
|
psidUser = malloc(cbSid);
|
||
|
|
||
|
if (!psidUser)
|
||
|
goto GUSFT_ERROR;
|
||
|
if (!CopySid(cbSid, psidUser, pUser->User.Sid))
|
||
|
goto GUSFT_ERROR;
|
||
|
|
||
|
*ppSid = psidUser;
|
||
|
psidUser = NULL;
|
||
|
return TRUE;
|
||
|
|
||
|
GUSFT_ERROR:
|
||
|
if (psidUser)
|
||
|
free(psidUser);
|
||
|
|
||
|
free(pUser);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
PSID EveryoneSid(BOOL fFetch)
|
||
|
{
|
||
|
static PSID psidEverybody = 0;
|
||
|
SID_IDENTIFIER_AUTHORITY siaEverybody = SECURITY_WORLD_SID_AUTHORITY;
|
||
|
BOOL fRv = FALSE;
|
||
|
|
||
|
if (!fFetch)
|
||
|
{
|
||
|
if (psidEverybody)
|
||
|
{
|
||
|
FreeSid(psidEverybody);
|
||
|
psidEverybody = 0;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (!psidEverybody)
|
||
|
{
|
||
|
if (!AllocateAndInitializeSid(
|
||
|
&siaEverybody,
|
||
|
1,
|
||
|
SECURITY_WORLD_RID,
|
||
|
0, 0, 0, 0, 0, 0, 0,
|
||
|
&psidEverybody
|
||
|
))
|
||
|
{
|
||
|
psidEverybody = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return psidEverybody;
|
||
|
}
|
||
|
|
||
|
PSID AdminSid(BOOL fFetch)
|
||
|
{
|
||
|
static PSID psidAdmin = 0;
|
||
|
SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
|
||
|
BOOL fRv = FALSE;
|
||
|
|
||
|
if (!fFetch)
|
||
|
{
|
||
|
if (psidAdmin)
|
||
|
{
|
||
|
FreeSid(psidAdmin);
|
||
|
psidAdmin = 0;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (!psidAdmin)
|
||
|
{
|
||
|
if (!AllocateAndInitializeSid(&siaNtAuthority,
|
||
|
2,
|
||
|
SECURITY_BUILTIN_DOMAIN_RID,
|
||
|
DOMAIN_ALIAS_RID_ADMINS,
|
||
|
0, 0, 0, 0, 0, 0,
|
||
|
&psidAdmin))
|
||
|
{
|
||
|
psidAdmin = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return psidAdmin;
|
||
|
}
|
||
|
|
||
|
PSID InteractiveUserSid(BOOL fFetch)
|
||
|
{
|
||
|
static PSID psidInteractiveUser = 0;
|
||
|
SID_IDENTIFIER_AUTHORITY siaLocalSystem = SECURITY_NT_AUTHORITY;
|
||
|
BOOL fRv = FALSE;
|
||
|
|
||
|
if (!fFetch)
|
||
|
{
|
||
|
if (psidInteractiveUser)
|
||
|
{
|
||
|
FreeSid(psidInteractiveUser);
|
||
|
psidInteractiveUser = 0;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (!psidInteractiveUser)
|
||
|
{
|
||
|
if (!AllocateAndInitializeSid(&siaLocalSystem,
|
||
|
1,
|
||
|
SECURITY_INTERACTIVE_RID,
|
||
|
0, 0, 0, 0, 0, 0, 0,
|
||
|
&psidInteractiveUser))
|
||
|
{
|
||
|
psidInteractiveUser = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return psidInteractiveUser;
|
||
|
}
|
||
|
|
||
|
PSID SystemSid(BOOL fFetch)
|
||
|
{
|
||
|
static PSID psidSystem = 0;
|
||
|
SID_IDENTIFIER_AUTHORITY siaLocalSystem = SECURITY_NT_AUTHORITY;
|
||
|
BOOL fRv = FALSE;
|
||
|
|
||
|
if (!fFetch)
|
||
|
{
|
||
|
if (psidSystem)
|
||
|
{
|
||
|
FreeSid(psidSystem);
|
||
|
psidSystem = 0;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (!psidSystem)
|
||
|
{
|
||
|
if (!AllocateAndInitializeSid(&siaLocalSystem,
|
||
|
1,
|
||
|
SECURITY_LOCAL_SYSTEM_RID,
|
||
|
0, 0, 0, 0, 0, 0, 0,
|
||
|
&psidSystem))
|
||
|
{
|
||
|
psidSystem = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return psidSystem;
|
||
|
}
|
||
|
|
||
|
void InitWellknownSids()
|
||
|
{
|
||
|
EveryoneSid(TRUE);
|
||
|
AdminSid(TRUE);
|
||
|
InteractiveUserSid(TRUE);
|
||
|
SystemSid(TRUE);
|
||
|
}
|
||
|
|
||
|
void UninitWellknownSids()
|
||
|
{
|
||
|
EveryoneSid(FALSE);
|
||
|
AdminSid(FALSE);
|
||
|
InteractiveUserSid(FALSE);
|
||
|
SystemSid(FALSE);
|
||
|
}
|