Configurando a segurança em uma chamada assíncrona

Chamadas assíncronas apresentam sérios riscos de segurança porque um retorno de chamada para o coletor pode não ser resultado da chamada assíncrona pelo aplicativo ou script original. A segurança em conexões remotas baseia-se na criptografia da comunicação entre o cliente e o provedor no computador remoto. No C++, você pode definir a criptografia por meio do parâmetro de nível de autenticação na chamada para CoInitializeSecurity. No script, defina AuthenticationLevel na conexão moniker ou em um objeto SWbemSecurity . Para obter mais informações, consulte Como definir o nível de segurança do processo padrão usando o VBScript.

Os riscos de segurança para chamadas assíncronas existem porque o WMI reduz o nível de autenticação em um retorno de chamada até que o retorno de chamada seja bem-sucedido. Em uma chamada assíncrona de saída, o cliente pode definir o nível de autenticação na conexão com o WMI. O WMI recupera as configurações de segurança na chamada do cliente e tenta chamar de volta com o mesmo nível de autenticação. O retorno de chamada é sempre iniciado no nível RPC_C_AUTHN_LEVEL_PKT_PRIVACY . Se o retorno de chamada falhar, o WMI reduzirá o nível de autenticação para um nível em que o retorno de chamada poderá ser bem-sucedido, se necessário, para RPC_C_AUTHN_LEVEL_NONE. No contexto de chamadas dentro do sistema local em que o serviço de autenticação não é Kerberos, o retorno de chamada sempre é retornado em RPC_C_AUTHN_LEVEL_NONE.

O nível mínimo de autenticação é RPC_C_AUTHN_LEVEL_PKT (wbemAuthenticationLevelPktfor scripting). No entanto, você pode especificar um nível mais alto, como RPC_C_AUTHN_LEVEL_PKT_PRIVACY (wbemAuthenticationLevelPktPrivacy). É recomendável que os aplicativos cliente ou scripts definam o nível de autenticação como RPC_C_AUTHN_LEVEL_DEFAULT (wbemAuthenticationLevelDefault) que permite que o nível de autenticação seja negociado para o nível especificado pelo servidor.

O valor do registro HKEY_LOCAL_MACHINE\ SoftwareMicrosoftWBEMCIMOMUnsecAppAccessControlDefault\\\\ controla se o WMI verifica se há um nível de autenticação aceitável em retornos de chamada. Esse é o único mecanismo para proteger a segurança do coletor para chamadas assíncronas feitas em scripts ou Visual Basic. Por padrão, essa chave do Registro é definida como zero. Se a chave do Registro for zero, o WMI não verificará os níveis de autenticação. Para proteger chamadas assíncronas no script, defina a chave do Registro como 1. Os clientes C++ podem chamar IWbemUnsecuredApartment::CreateSinkStub para controlar o acesso ao coletor. O valor é criado em qualquer lugar por padrão.

Os tópicos a seguir fornecem exemplos de configuração de segurança de chamada assíncrona:

Configurando a segurança de chamada assíncrona no C++

O método IWbemUnsecuredApartment::CreateSinkStub é semelhante ao método IUnsecuredApartment::CreateObjectStub e cria um coletor em um processo separado, Unsecapp.exe, para receber retornos de chamada. No entanto, o método CreateSinkStub tem um dwFlagparameter que especifica como o processo separado lida com o controle de acesso.

O parâmetro dwFlag especifica uma das seguintes ações para Unsecapp.exe:

  • Use a configuração de chave do Registro para determinar se deseja ou não verificar o acesso.
  • Ignore a chave do Registro e sempre verifique o acesso.
  • Ignore a chave do Registro e nunca verifique o acesso.

O exemplo de código neste tópico requer a seguinte instrução #include para compilar corretamente.

#include <wbemidl.h>

O procedimento a seguir descreve como executar uma chamada assíncrona com IWbemUnsecuredApartment.

Para executar uma chamada assíncrona com IWbemUnsecuredApartment

  1. Crie um processo dedicado com uma chamada para CoCreateInstance.

    O exemplo de código a seguir chama CoCreateInstance para criar um processo dedicado.

    CLSID                    CLSID_WbemUnsecuredApartment;
    IWbemUnsecuredApartment* pUnsecApp = NULL;
    
    CoCreateInstance(CLSID_WbemUnsecuredApartment, 
                     NULL, 
                     CLSCTX_LOCAL_SERVER, 
                     IID_IWbemUnsecuredApartment, 
                     (void**)&pUnsecApp);
    
  2. Instancie o objeto coletor.

    O exemplo de código a seguir cria um novo objeto de coletor.

    CMySink* pSink = new CMySink;
    pSink->AddRef();
    
  3. Crie um stub para o coletor.

    Um stub é uma função wrapper produzida do coletor.

    O exemplo de código a seguir cria um stub para o coletor.

    LPCWSTR          wszReserved = NULL;           
    IWbemObjectSink* pStubSink   = NULL;
    IUnknown*        pStubUnk    = NULL; 
    
    pUnsecApp->CreateSinkStub(pSink,
                              WBEM_FLAG_UNSECAPP_CHECK_ACCESS,  //Authenticate callbacks regardless of registry key
                              wszReserved,
                              &pStubSink);
    
  4. Solte o ponteiro do objeto coletor.

    Você pode liberar o ponteiro do objeto porque o stub agora possui o ponteiro.

    O exemplo de código a seguir libera o ponteiro do objeto.

    pSink->Release();
    
  5. Use o stub em qualquer chamada assíncrona.

    Quando terminar a chamada, libere a contagem de referência local.

    O exemplo de código a seguir usa o stub em uma chamada assíncrona.

    // pServices is an IWbemServices* object
    pServices->CreateInstanceEnumAsync(strClassName, 0, NULL, pStubSink);
    

    Às vezes, talvez você precise cancelar uma chamada assíncrona depois de fazer a chamada. Se você precisar cancelar a chamada, cancele a chamada com o mesmo ponteiro que originalmente fez a chamada.

    O exemplo de código a seguir descreve como cancelar uma chamada assíncrona.

    pServices->CancelAsyncCall(pStubSink);
    
  6. Libere a contagem de referência local quando terminar de usar a chamada assíncrona.

    Certifique-se de liberar o ponteiro pStubSink somente depois de confirmar que a chamada assíncrona não deve ser cancelada. Além disso, não libere pStubSink depois que o WMI liberar o ponteiro do coletor pSink . A liberação de pStubSink após o pSink cria uma contagem de referência circular na qual o coletor e o stub permanecem na memória para sempre. Em vez disso, um possível local para liberar o ponteiro está na chamada IWbemObjectSink::SetStatus , feita pela WMI para informar que a chamada assíncrona original está concluída.

  7. Quando terminar, uninitialize COM com uma chamada para Release().

    O exemplo de código a seguir mostra como chamar Release() no ponteiro pUnsecApp .

    pUnsecApp->Release();
    

Para obter mais informações sobre a função e parâmetros CoInitializeSecurity , consulte a documentação com .