Udostępnij przez


Przeprowadzanie kontroli dostępu

Kontrola dostępu określa, czy deskryptor zabezpieczeń udziela określonego zestawu praw dostępu do klienta lub wątku identyfikowanego przez token dostępu. Funkcję zabezpieczeń można wywołać AccessCheck z poziomu aplikacji klienckich lub dostawców WMI napisanych w języku C++ lub C#. Skrypty i aplikacje języka Visual Basic nie mogą przeprowadzać kontroli dostępu przy użyciu metody opisanej tutaj.

Aplikacje klienckie powinny sprawdzić dostęp, aby określić tożsamość wywołania zwrotnego podczas zwracania wyników do ujścia dostarczonego przez wywołanie asynchroniczne klienta.

Jeśli dostawcy nie mogą personifikować aplikacji klienckiej lub skryptu, który żąda danych, powinni przeprowadzić kontrole dostępu w następujących sytuacjach:

  • Podczas uzyskiwania dostępu do zasobów, które nie są chronione przez listy kontroli dostępu (ACL).
  • Gdy klient nawiązał połączenie na poziomie personifikacji RPC_C_LEVEL_IDENTIFY.

Notatka

Aplikacje C++ i C# mogą kontrolować, czy kontrole dostępu są wykonywane przez oddzielny proces. Skrypty i aplikacje języka Visual Basic mogą odczytywać lub zmieniać klucz rejestru, aby upewnić się, że usługa WMI wykonuje kontrole dostępu. Aby uzyskać więcej informacji, zobacz Ustawianie zabezpieczeń dla wywołania asynchronicznego.

 

Przykład kodu w tym temacie wymaga następujących odwołań i instrukcji #include w celu poprawnego skompilowania.

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

Poniższy przykład kodu pokazuje, jak sprawdzić, czy token zabezpieczający wątku aplikacji klienckiej zawiera uprawnienia odpowiednie dla określonego deskryptora zabezpieczeń. Funkcja pobiera ciąg "domain\user" i zwraca identyfikator SID. Jeśli wywołanie zakończy się niepowodzeniem, funkcja zwróci NULL, w przeciwnym razie wywołujący musi zwolnić zwrócony wskaźnik.

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

Wybór poprawnej rejestracji

Utrzymywanie zabezpieczenia usługi WMI

Zabezpieczanie usługodawcy

dostęp do przestrzeni nazw usługi WMI