Compartilhar via


Configurar a autenticação usando C++

Uma das tarefas principais do IWbemLocator::ConnectServer para WMI é retornar um ponteiro para um proxy IWbemServices. Por meio do proxy IWbemServices, você pode acessar os recursos da infraestrutura do WMI. No entanto, o ponteiro para o proxy IWbemServices tem a identidade do processo de aplicativo cliente e não a identidade do processo IWbemServices. Portanto, se você tentar acessar IWbemServices com o ponteiro, poderá receber um código de acesso negado, como E_ACCESSDENIED. Para evitar o erro de acesso negado, é necessário definir a identidade do novo ponteiro com uma chamada à interface CoSetProxyBlanket.

Um provedor pode definir a segurança em um namespace para que nenhum dado seja retornado, a menos que você use a privacidade de pacotes (PktPrivacy) em sua conexão com esse namespace. Isso garante que os dados sejam criptografados à medida que cruzam a rede. Se você tentar definir um nível de autenticação mais baixo, receberá uma mensagem de acesso negado. Para obter mais informações, consulte Configurar descritores de segurança de namespace.

Para obter mais informações sobre a configuração de autenticação no script, consulte Definir o nível de segurança do processo padrão usando VBScript.

Configurar a segurança em uma interface IUnknown remota

Em algumas situações, é necessário mais acesso a um servidor do que apenas um ponteiro para um proxy. Às vezes, pode ser necessário obter uma conexão segura com a interface IUnknown do proxy. Usando o IUnknown, você pode consultar o sistema remoto em busca de interfaces e outras técnicas necessárias.

Quando um proxy está localizado em um computador remoto, o servidor delega todas as chamadas à interface IUnknown do proxy para a interface IUnknown. Por exemplo, se você chamar QueryInterface em um proxy e a interface solicitada não fizer parte do proxy, o proxy enviará a chamada para o servidor remoto. Por sua vez, o servidor remoto verificará se há suporte à interface apropriada. Se o servidor der suporte à interface, o COM realizará marshaling de um novo proxy de volta para o cliente para que o aplicativo possa usar a nova interface.

Problemas podem ocorrer quando o cliente não tem permissões de acesso ao servidor remoto, mas esteja usando as credenciais de um usuário autorizado. Nessa situação, qualquer tentativa de acessar QueryInterface no servidor remoto falhará. A versão final no proxy também falhará, pois o usuário atual não tem acesso ao servidor remoto. Um sintoma disso é um atraso de um ou dois segundos antes que o aplicativo cliente falhe na versão final do proxy. A falha ocorre porque o COM tentou acessar o servidor remoto usando as configurações de segurança padrão do usuário atual, que não incluem as credenciais modificadas que permitiram o acesso ao servidor inicialmente. Para obter mais informações, consulte Configurar a segurança em IWbemServices e outros proxies.

Para evitar a conexão com falha, use CoSetProxyBlanket para definir explicitamente a autenticação de segurança no ponteiro retornado de IUnknown. Usando CoSetProxyBlanket, você pode garantir que o servidor remoto receba a identidade de autenticação correta.

O exemplo de código a seguir mostra como usar CoSetProxyBlanket para acessar uma interface IUnknown remota.

SEC_WINNT_AUTH_IDENTITY_W* pAuthIdentity = 
   new SEC_WINNT_AUTH_IDENTITY_W;
ZeroMemory(pAuthIdentity, sizeof(SEC_WINNT_AUTH_IDENTITY_W));

pAuthIdentity->User = new WCHAR[32];
StringCbCopyW(pAuthIdentity->User,sizeof(L"MyUser"),L"MyUser");
pAuthIdentity->UserLength = wcslen(pAuthIdentity->User);

pAuthIdentity->Domain = new WCHAR[32];
StringCbCopyW(pAuthIdentity->Domain,sizeof(L"MyDomain"),L"MyDomain");
pAuthIdentity->DomainLength = wcslen(pAuthIdentity->Domain);

pAuthIdentity->Password = new WCHAR[32];
pAuthIdentity->Password[0] = NULL;
pAuthIdentity->PasswordLength = wcslen( pAuthIdentity->Password);

pAuthIdentity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;

IWbemServices* pWbemServices = 0;

// Set proxy security
hr = CoSetProxyBlanket(pWbemServices, 
                       RPC_C_AUTHN_DEFAULT, 
                       RPC_C_AUTHZ_NONE, 
                       COLE_DEFAULT_PRINCIPAL, 
                       RPC_C_AUTHN_LEVEL_DEFAULT, 
                       RPC_C_IMP_LEVEL_IMPERSONATE, 
                       pAuthIdentity, 
                       EOAC_NONE 
);
if (FAILED(hr))
{
   cout << "Count not set proxy blanket. Error code = 0x"
        << hex << hr << endl;
   pWbemServices->Release();
   return 1;
}

// Set IUnknown security
IUnknown*    pUnk = NULL;
pWbemServices->QueryInterface(IID_IUnknown, (void**) &pUnk);

hr = CoSetProxyBlanket(pUnk, 
                       RPC_C_AUTHN_DEFAULT, 
                       RPC_C_AUTHZ_NONE, 
                       COLE_DEFAULT_PRINCIPAL, 
                       RPC_C_AUTHN_LEVEL_DEFAULT, 
                       RPC_C_IMP_LEVEL_IMPERSONATE, 
                       pAuthIdentity, 
                       EOAC_NONE 
);
if (FAILED(hr))
{
   cout << "Count not set proxy blanket. Error code = 0x"
        << hex << hr << endl;
   pUnk->Release();
   pWbemServices->Release();
   delete [] pAuthIdentity->User;
   delete [] pAuthIdentity->Domain;
   delete [] pAuthIdentity->Password;
   delete pAuthIdentity;   
   return 1;
}

// cleanup IUnknown
pUnk->Release();

//
// Perform a bunch of operations
//

// Cleanup
pWbemServices->Release();

delete [] pAuthIdentity->User;
delete [] pAuthIdentity->Domain;
delete [] pAuthIdentity->Password;

delete pAuthIdentity;

Observação

Quando você define a segurança na interface IUnknown de um proxy, o COM cria uma cópia do proxy que não pode ser lançada até que você chame o CoUninitialize.

 

Definir a autenticação no WMI