Utföra åtkomstkontroller
En åtkomstkontroll avgör om en säkerhetsbeskrivning ger en angiven uppsättning åtkomsträttigheter till klienten eller tråden som identifieras av en åtkomsttoken. Du kan anropa säkerhetsfunktionen AccessCheck från WMI-klientprogram eller leverantörer som skrivits i C++ eller C#. Skript och Visual Basic-program kan inte utföra åtkomstkontroller med hjälp av metoden som beskrivs här.
Klientapplikationer bör göra en åtkomstkontroll för att fastställa identiteten för återanropet när resultaten returneras till mottagaren som tillhandahålls av klientens asynkrona anrop.
När leverantörer inte kan personifiera klientprogrammet eller skriptet som begär data bör de utföra åtkomstkontroller för följande situationer:
- Vid åtkomst till resurser som inte skyddas av åtkomstkontrollistor (ACL).
- När klienten har anslutit på RPC_C_LEVEL_IDENTIFY personifieringsnivå.
Obs
C++ och C#-program kan styra om åtkomstkontroller utförs av en separat process. Skript och Visual Basic-program kan läsa eller ändra en registernyckel för att säkerställa att WMI utför åtkomstkontroller. Mer information finns i Ställa in säkerhet på ett asynkront anrop.
Kodexemplet i det här avsnittet kräver följande referenser och #include-instruktioner för att kompilera korrekt.
#include <lmcons.h>
#define _WIN32_DCOM
#define SECURITY_WIN32
#include <wbemidl.h>
#include <security.h>
#include <safestr.h>
#pragma comment(lib, "wbemuuid.lib")
#pragma comment(lib, "Secur32.lib")
I följande kodexempel visas hur du kontrollerar att säkerhetstoken för en klientprogramtråd innehåller behörigheter som är lämpliga för en angiven säkerhetsbeskrivning. Funktionen tar strängen "domain\user" och returnerar SID. Om anropet misslyckas returnerar funktionen NULL-, annars måste anroparen frigöra den returnerade pekaren.
BYTE * GetSid(LPWSTR pwcUserName)
{
DWORD dwSidSize = 0, dwDomainSize = 0;
SID_NAME_USE use;
// first call is to get the size
BOOL bRet = LookupAccountNameW(
NULL, // system name
pwcUserName, // account name
NULL, // security identifier
&dwSidSize, // size of security identifier
NULL, // domain name
&dwDomainSize, // size of domain name
&use // SID-type indicator
);
if(bRet == FALSE && ERROR_INSUFFICIENT_BUFFER
!= GetLastError())\
return NULL;
BYTE * buff = new BYTE[dwSidSize];
if(buff == NULL)
return NULL;
WCHAR * pwcDomain = new WCHAR[dwDomainSize];
if(pwcDomain == NULL)
{
delete [] buff;
return FALSE;
}
// Call to LookupAccountNameW actually gets the SID
bRet = LookupAccountNameW(
NULL, // system name
pwcUserName, // account name
buff, // security identifier
&dwSidSize, // size of security identifier
pwcDomain, // domain name
&dwDomainSize, // size of domain name
&use // SID-type indicator
);
delete [] pwcDomain;
if(bRet == FALSE)
{
delete [] buff;
return NULL;
}
return buff;
}
// This returns true if the caller is coming
// from the expected computer in the expected domain.
BOOL IsAllowed(LPWSTR pwsExpectedDomain,
LPWSTR pwsExpectedMachine)
{
WCHAR wCallerName[UNLEN + 1];
DWORD nSize = UNLEN + 1;
// Impersonate the caller and get its name
HRESULT hr = CoImpersonateClient();
if(FAILED(hr))
return FALSE;
BOOL bRet = GetUserNameExW(NameSamCompatible,
wCallerName, &nSize);
CoRevertToSelf();
if(bRet == FALSE)
return FALSE;
// take the expected domain and lan manager
// style name and create a SID. In actual
// production code, it would be more efficient
// to do this only when necessary
WCHAR wExpectedName[UNLEN + 1];
HRESULT hrCopyCat;
hrCopyCat = StringCchCopy(wExpectedName,
sizeof(pwsExpectedDomain)*sizeof(WCHAR)+1,
pwsExpectedDomain);
if (FAILED(hrCopyCat))
{
return FALSE;
}
hrCopyCat =
StringCchCat(wExpectedName,sizeof(wExpectedName)
+ 2*sizeof(WCHAR)+1, L"\\");
if (FAILED(hrCopyCat))
{
return FALSE;
}
hrCopyCat = StringCchCat(wExpectedName,sizeof(wExpectedName)
+ sizeof(pwsExpectedMachine)*sizeof(WCHAR)+1,
pwsExpectedMachine);
if (FAILED(hrCopyCat))
{
return FALSE;
}
hrCopyCat = StringCchCat(wExpectedName,sizeof(wExpectedName)
+ sizeof(WCHAR)+1, L"$");
if (FAILED(hrCopyCat))
{
return FALSE;
}
// convert the two names to SIDs and compare.
// Note that SIDs are used since
// the format of the names might vary.
BYTE * pCaller = GetSid(wCallerName);
if(pCaller == NULL)
return FALSE;
BYTE * pExpected = GetSid(wExpectedName);
if(pExpected == NULL)
{
delete [] pCaller;
return FALSE;
}
bRet = EqualSid((PSID)pCaller, (PSID)pExpected);
delete [] pCaller;
delete [] pExpected;
return bRet;
}
Relaterade ämnen