Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

372 lines
9.6 KiB

//#pragma title( "IsAdmin.cpp - Determine if user is administrator" )
/*
Copyright (c) 1995-1998, Mission Critical Software, Inc. All rights reserved.
===============================================================================
Module - IsAdmin.cpp
System - Common
Author - Rich Denham
Created - 1996-06-04
Description - Determine if user is administrator (local or remote)
Updates -
===============================================================================
*/
#ifdef USE_STDAFX
# include "stdafx.h"
#else
# include <windows.h>
#endif
#include <lm.h>
#include "Common.hpp"
#include "UString.hpp"
#include "IsAdmin.hpp"
namespace
{
#ifndef SECURITY_MAX_SID_SIZE
#define SECURITY_MAX_SID_SIZE (sizeof(SID) - sizeof(DWORD) + (SID_MAX_SUB_AUTHORITIES * sizeof(DWORD)))
#endif
const DWORD MAX_VERSION_2_ACE_SIZE = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + SECURITY_MAX_SID_SIZE;
// GetEffectiveToken
//
// Brown, Keith. 2000. Programming Windows Security. Reading MA: Addison-Wesley
// Pages 120-121
HANDLE __stdcall GetEffectiveToken(DWORD dwDesiredAccess, BOOL bImpersonation, SECURITY_IMPERSONATION_LEVEL silLevel)
{
HANDLE hToken = 0;
if (!OpenThreadToken(GetCurrentThread(), dwDesiredAccess, TRUE, &hToken))
{
if (GetLastError() == ERROR_NO_TOKEN)
{
DWORD dwAccess = bImpersonation ? TOKEN_DUPLICATE : dwDesiredAccess;
if (OpenProcessToken(GetCurrentProcess(), dwAccess, &hToken))
{
if (bImpersonation)
{
// convert primary to impersonation token
HANDLE hImpersonationToken = 0;
DuplicateTokenEx(hToken, dwDesiredAccess, 0, silLevel, TokenImpersonation, &hImpersonationToken);
CloseHandle(hToken);
hToken = hImpersonationToken;
}
}
}
}
return hToken;
}
// CheckTokenMembership
//
// Brown, Keith. 2000. Programming Windows Security. Reading MA: Addison-Wesley
// Pages 130-131
//#if (_WIN32_WINNT < 0x0500)
#if TRUE // always use our function
BOOL WINAPI AdmtCheckTokenMembership(HANDLE hToken, PSID pSid, PBOOL pbIsMember)
{
// if no token was passed, CTM uses the effective
// security context (the thread or process token)
if (!hToken)
{
hToken = GetEffectiveToken(TOKEN_QUERY, TRUE, SecurityIdentification);
}
if (!hToken)
{
return FALSE;
}
// create a security descriptor that grants a
// specific permission only to the specified SID
BYTE dacl[sizeof ACL + MAX_VERSION_2_ACE_SIZE];
ACL* pdacl = (ACL*)dacl;
if (!InitializeAcl(pdacl, sizeof dacl, ACL_REVISION))
return FALSE;
AddAccessAllowedAce(pdacl, ACL_REVISION, 1, pSid);
SECURITY_DESCRIPTOR sd;
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
return FALSE;
SID sidWorld = { SID_REVISION, 1, SECURITY_WORLD_SID_AUTHORITY, SECURITY_WORLD_RID };
SetSecurityDescriptorOwner(&sd, &sidWorld, FALSE);
SetSecurityDescriptorGroup(&sd, &sidWorld, FALSE);
SetSecurityDescriptorDacl(&sd, TRUE, pdacl, FALSE);
// now let AccessCheck do all the hard work
GENERIC_MAPPING gm = { 0, 0, 0, 1 };
PRIVILEGE_SET ps;
DWORD cb = sizeof ps;
DWORD ga;
return AccessCheck(&sd, hToken, 1, &gm, &ps, &cb, &ga, pbIsMember);
}
#else
#define AdmtCheckTokenMembership CheckTokenMembership
#endif
} // namespace
///////////////////////////////////////////////////////////////////////////////
// Determine if user is administrator on local machine //
///////////////////////////////////////////////////////////////////////////////
typedef BOOL (APIENTRY *PCHECKTOKENMEMBERSHIP)(HANDLE, PSID, PBOOL);
DWORD // ret-OS return code, 0=User is admin
IsAdminLocal()
{
DWORD dwError = NO_ERROR;
PCHECKTOKENMEMBERSHIP pCheckTokenMembershipInDll = NULL;
// try to load the CheckTokenMembership function from advapi32.dl
HMODULE hAdvApi32 = LoadLibrary(L"advapi32.dll");
if (hAdvApi32 != NULL)
{
pCheckTokenMembershipInDll =
(PCHECKTOKENMEMBERSHIP) GetProcAddress(hAdvApi32, "CheckTokenMembership");
}
// create well known SID Administrators
SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
PSID psidAdministrators;
BOOL bSid = AllocateAndInitializeSid(
&siaNtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0,
0,
0,
0,
0,
0,
&psidAdministrators
);
if (bSid)
{
// check if token membership includes Administrators
BOOL bIsMember;
BOOL result;
if (pCheckTokenMembershipInDll != NULL)
{
result = (*pCheckTokenMembershipInDll)(0, psidAdministrators, &bIsMember);
}
else
result = AdmtCheckTokenMembership(0, psidAdministrators, &bIsMember);
if (result != FALSE)
{
dwError = bIsMember ? NO_ERROR : ERROR_ACCESS_DENIED;
}
else
{
dwError = GetLastError();
}
FreeSid(psidAdministrators);
}
else
{
dwError = GetLastError();
}
if (hAdvApi32 != NULL)
FreeLibrary(hAdvApi32);
return dwError;
}
//------------------------------------------------------------------------------
// IsDomainAdmin Function
//
// Synopsis
// Checks if caller is a domain administrator in the specified domain.
//
// Arguments
// psidDomain - SID for domain of interest
//
// Return Value
// Returns ERROR_SUCCESS if caller is a domain administrator,
// ERROR_ACCESS_DENIED if not or other error code if unable to check token
// membership.
//------------------------------------------------------------------------------
DWORD __stdcall IsDomainAdmin(PSID psidDomain)
{
DWORD dwError = ERROR_SUCCESS;
//
// Validate argument.
//
if ((psidDomain == NULL) || (IsValidSid(psidDomain) == FALSE))
{
return ERROR_INVALID_PARAMETER;
}
// try to load the CheckTokenMembership function from advapi32.dl
HMODULE hAdvApi32 = LoadLibrary(L"advapi32.dll");
PCHECKTOKENMEMBERSHIP pCheckTokenMembership = NULL;
if (hAdvApi32 != NULL)
{
pCheckTokenMembership = (PCHECKTOKENMEMBERSHIP) GetProcAddress(hAdvApi32, "CheckTokenMembership");
}
//
// create well known SID Administrators
//
PSID psidDomainAdmins = NULL;
SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
PUCHAR pcSubAuthority = GetSidSubAuthorityCount(psidDomain);
BOOL bSid = AllocateAndInitializeSid(
&siaNtAuthority,
*pcSubAuthority + 1,
0,
0,
0,
0,
0,
0,
0,
0,
&psidDomainAdmins
);
if (bSid)
{
//
//
//
if (CopySid(GetLengthSid(psidDomain), psidDomainAdmins, psidDomain))
{
pcSubAuthority = GetSidSubAuthorityCount(psidDomainAdmins);
PDWORD pdwRid = GetSidSubAuthority(psidDomainAdmins, *pcSubAuthority);
++(*pcSubAuthority);
*pdwRid = DOMAIN_GROUP_RID_ADMINS;
//
// check if token membership includes Domain Admins
//
BOOL bCheck;
BOOL bIsMember;
if (pCheckTokenMembership != NULL)
{
bCheck = (*pCheckTokenMembership)(0, psidDomainAdmins, &bIsMember);
}
else
{
bCheck = AdmtCheckTokenMembership(0, psidDomainAdmins, &bIsMember);
}
if (bCheck)
{
dwError = bIsMember ? ERROR_SUCCESS : ERROR_ACCESS_DENIED;
}
else
{
dwError = GetLastError();
}
}
else
{
dwError = GetLastError();
}
FreeSid(psidDomainAdmins);
}
else
{
dwError = GetLastError();
}
if (hAdvApi32 != NULL)
{
FreeLibrary(hAdvApi32);
}
return dwError;
}
///////////////////////////////////////////////////////////////////////////////
// Determine if user is administrator on remote machine //
///////////////////////////////////////////////////////////////////////////////
DWORD // ret-OS return code, 0=User is admin
IsAdminRemote(
WCHAR const * pMachine // in -\\machine name
)
{
DWORD osRc; // OS return code
WCHAR grpName[255];
PSID pSid;
SID_NAME_USE use;
DWORD dwNameLen = 255;
DWORD dwDomLen = 255;
WCHAR domain[255];
SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
BOOL bIsAdmin = FALSE;
// build the Administrators SID
if ( AllocateAndInitializeSid(
&sia,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&pSid
) )
{
// and look up the administrators group on the specified machine
if ( LookupAccountSid(pMachine, pSid, grpName, &dwNameLen, domain, &dwDomLen, &use) )
{
// remove explict administrator check
bIsAdmin = TRUE;
}
else
osRc = GetLastError();
FreeSid(pSid);
}
else
osRc = GetLastError();
if ( bIsAdmin )
osRc = 0;
else
if ( ! osRc )
osRc = ERROR_ACCESS_DENIED;
return osRc;
}
// IsAdmin.cpp - end of file