Provádění kontrol přístupu
Kontrola přístupu určuje, zda popisovač zabezpečení uděluje zadanou sadu přístupových práv klientovi nebo vláknu identifikovanému přístupovým tokenem. Funkci zabezpečení můžete volat AccessCheck z klientských aplikací nebo poskytovatelů WMI napsaných v C++ nebo C#. Skripty a aplikace jazyka Visual Basic nemůžou provádět kontroly přístupu pomocí metody popsané zde.
Klientské aplikace by měly provést kontrolu přístupu k určení identity zpětného volání při vrácení výsledků do jímky poskytované asynchronním voláním klienta.
Pokud zprostředkovatelé nemohou zosobnit klientskou aplikaci nebo skript, který požaduje data, měli by provést kontroly přístupu v následujících situacích:
- Při přístupu k prostředkům, které nejsou chráněny seznamy řízení přístupu (ACL).
- Když se klient připojí na úrovni zosobnění RPC_C_LEVEL_IDENTIFY.
Poznámka
Aplikace C++ a C# můžou řídit, jestli se kontroly přístupu provádějí samostatným procesem. Skripty a aplikace jazyka Visual Basic mohou číst nebo měnit klíč registru, aby bylo zajištěno, že rozhraní WMI provádí kontroly přístupu. Další informace naleznete v tématu Nastavení zabezpečení asynchronního volání.
Příklad kódu v tomto tématu vyžaduje, aby byly správně kompilovány následující odkazy a příkazy #include.
#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")
Následující příklad kódu ukazuje, jak zkontrolovat, že token zabezpečení vlákna klientské aplikace obsahuje oprávnění odpovídající zadanému popisovači zabezpečení. Funkce vezme řetězec "domain\user" a vrátí identifikátor SID. Pokud volání selže, vrátí funkce NULL, jinak volající musí uvolnit vrácený ukazatel.
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;
}
Související témata
-
Přístup k názvovým oborům rozhraní WMI