Partilhar via


Executando verificações de acesso

Uma verificação de acesso determina se um descritor de segurança concede um conjunto especificado de direitos de acesso ao cliente ou thread identificado por um token de acesso. Você pode chamar a função de segurança AccessCheck de aplicações cliente de WMI ou de fornecedores escritos em C++ ou C#. Scripts e aplicativos Visual Basic não podem executar verificações de acesso usando o método descrito aqui.

Os aplicativos cliente devem fazer uma verificação de acesso para determinar a identidade do callback ao retornar resultados para o destino fornecido pela chamada assíncrona do cliente.

Quando os provedores não podem representar o aplicativo cliente ou script que está solicitando dados, eles devem executar verificações de acesso para as seguintes situações:

  • Ao acessar recursos que não estão protegidos por listas de controle de acesso (ACL).
  • Quando o cliente se conectou no nível de representação RPC_C_LEVEL_IDENTIFY.

Observação

Os aplicativos C++ e C# podem controlar se as verificações de acesso são executadas por um processo separado. Scripts e aplicativos Visual Basic podem ler ou alterar uma chave do Registro para garantir que o WMI execute verificações de acesso. Para obter mais informações, consulte Definindo a segurança em uma chamada assíncrona.

 

O exemplo de código neste tópico requer as seguintes referências e instruções #include para compilar corretamente.

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

O exemplo de código a seguir mostra como verificar se o token de segurança de um thread de aplicativo cliente contém permissões apropriadas para um descritor de segurança especificado. A função usa a string "domain\user" e retorna o SID. Se a chamada falhar, a função retornará NULL, caso contrário, o chamador deve liberar o ponteiro retornado.

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

Escolher o Registo Correto

Manutenção da segurança WMI

Proteger o seu fornecedor

Acesso a Namespaces WMI