Teilen über


Durchführen von Zugriffsprüfungen

Eine Zugriffsprüfung bestimmt, ob eine Sicherheitsbeschreibung dem durch ein Zugriffstoken identifizierten Client oder Thread einen angegebenen Satz von Zugriffsrechten gewährt. Sie können die Sicherheitsfunktion AccessCheck von WMI-Clientanwendungen oder -Anbietern aufrufen, die in C++ oder C# geschrieben sind. Skripts und Visual Basic-Anwendungen können keine Zugriffsprüfungen mit der hier beschriebenen Methode durchführen.

Clientanwendungen sollten eine Zugriffsprüfung durchführen, um die Identität des Rückrufs zu ermitteln, wenn Ergebnisse an die vom asynchronen Clientaufruf bereitgestellte Senke zurückgegeben werden.

Wenn Anbieter die Identität von Clientanwendungen oder Skripts, die Daten anfordern, nicht annehmen können, sollten sie Zugriffsprüfungen in folgenden Situationen durchführen:

  • Beim Zugriff auf Ressourcen, die nicht durch Zugriffssteuerungslisten (Access Control Lists, ACL) geschützt sind.
  • Wenn der Client auf der Identitätswechselebene RPC_C_LEVEL_IDENTIFY verbunden ist.

Hinweis

C++- und C#-Anwendungen können steuern, ob Zugriffsprüfungen durch einen separaten Prozess durchgeführt werden. Skripts und Visual Basic-Anwendungen können einen Registrierungsschlüssel lesen oder ändern, um sicherzustellen, dass WMI Zugriffsprüfungen durchführt. Weitere Informationen finden Sie unter Festlegen der Sicherheit für einen asynchronen Aufruf.

 

Das Codebeispiel in diesem Thema erfordert die folgenden Verweise und #include-Anweisungen für eine ordnungsgemäße Kompilierung.

#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")

Das folgende Codebeispiel zeigt, wie Sie überprüfen, ob das Sicherheitstoken eines Clientanwendungsthreads die für eine angegebene Sicherheitsbeschreibung geeigneten Berechtigungen enthält. Die Funktion akzeptiert die Zeichenfolge „domäne\benutzer*in“ und gibt die SID zurück. Wenn der Aufruf fehlschlägt, gibt die Funktion NULL zurück. Andernfalls muss der Aufrufer den zurückgegebenen Zeiger freigeben.

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;
}

Auswählen der ordnungsgemäßen Registrierung

Aufrechterhalten der WMI-Sicherheit

Schützen Ihres Anbieters

Zugriff auf WMI-Namespaces