Esecuzione di controlli di accesso

Un controllo di accesso determina se un descrittore di sicurezza concede un set specificato di diritti di accesso al client o al thread identificato da un token di accesso. È possibile chiamare la funzione di sicurezza AccessCheck da applicazioni client o provider WMI scritti in C++ o C#. Gli script e le applicazioni Visual Basic non possono eseguire controlli di accesso usando il metodo descritto qui.

Le applicazioni client devono eseguire un controllo di accesso per determinare l'identità del callback durante la restituzione dei risultati al sink fornito dalla chiamata asincrona del client.

Quando i provider non possono rappresentare l'applicazione client o lo script che richiede dati, devono eseguire controlli di accesso per le situazioni seguenti:

  • Quando si accede alle risorse che non sono protette dagli elenchi di controllo di accesso (ACL).
  • Quando il client è connesso a livello di rappresentazione RPC_C_LEVEL_IDENTIFY.

Nota

Le applicazioni C++ e C# possono controllare se i controlli di accesso vengono eseguiti da un processo separato. Gli script e le applicazioni Visual Basic possono leggere o modificare una chiave del Registro di sistema per garantire che WMI esegua controlli di accesso. Per altre informazioni, vedere Impostazione della sicurezza in una chiamata asincrona.

 

L'esempio di codice in questo argomento richiede i riferimenti seguenti e le istruzioni #include per la compilazione corretta.

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

Nell'esempio di codice seguente viene illustrato come verificare che il token di sicurezza di un thread dell'applicazione client contenga le autorizzazioni appropriate per un descrittore di sicurezza specificato. La funzione accetta la stringa "domain\user" e restituisce il SID. Se la chiamata ha esito negativo, la funzione restituisce NULL, altrimenti il chiamante deve liberare il puntatore restituito.

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

Scelta della registrazione corretta

Gestione della sicurezza WMI

Protezione del provider

Accesso agli spazi dei nomi WMI