Compartir a través de


Establecimiento de la seguridad en una llamada asincrónica

Las llamadas asincrónicas presentan riesgos de seguridad graves, ya que puede que una devolución de llamada al receptor no sea el resultado de la llamada asincrónica realizada por la aplicación o el script originales. La seguridad de las conexiones remotas se basa en el cifrado de la comunicación entre el cliente y el proveedor en el equipo remoto. En C++, puede establecer el cifrado mediante el parámetro de nivel de autenticación en la llamada a CoInitializeSecurity. En el scripting, establezca AuthenticationLevel en la conexión del moniker o en un objeto SWbemSecurity. Para obtener más información, consulte Establecimiento del nivel de seguridad de proceso predeterminado mediante VBScript.

Existen riesgos de seguridad de las llamadas asincrónicas porque WMI reduce el nivel de autenticación en una devolución de llamada hasta que la devolución de llamada se realiza correctamente. En una llamada asincrónica saliente, el cliente puede establecer el nivel de autenticación en la conexión a WMI. WMI recupera la configuración de seguridad en la llamada de cliente e intenta devolver la llamada con el mismo nivel de autenticación. La devolución de llamada siempre se inicia en el nivel RPC_C_AUTHN_LEVEL_PKT_PRIVACY. Si se produce un error en la devolución de llamada, WMI reduce el nivel de autenticación a otro en el que la devolución de llamada pueda realizarse correctamente, si es necesario, en RPC_C_AUTHN_LEVEL_NONE. En el contexto de las llamadas dentro del sistema local donde el servicio de autenticación no es Kerberos, la devolución de llamada siempre se devuelve con RPC_C_AUTHN_LEVEL_NONE.

El nivel de autenticación mínimo es RPC_C_AUTHN_LEVEL_PKT (wbemAuthenticationLevelPkt para scripting). Sin embargo, puede especificar un nivel superior, como RPC_C_AUTHN_LEVEL_PKT_PRIVACY (wbemAuthenticationLevelPktPrivacy). Se recomienda que los scripts o las aplicaciones cliente establezcan el nivel de autenticación en RPC_C_AUTHN_LEVEL_DEFAULT (wbemAuthenticationLevelDefault), lo que permite negociar el nivel de autenticación en el nivel que especifica el servidor.

El valor de registro HKEY_LOCAL_MACHINE\Software\Microsoft\WBEM\CIMOM\UnsecAppAccessControlDefault controla si WMI comprueba si hay un nivel de autenticación aceptable en las devoluciones de llamada. Este es el único mecanismo para proteger la seguridad del receptor en las llamadas asincrónicas realizadas en el scripting o Visual Basic. De forma predeterminada, esta clave del Registro se establece en cero. Si la clave del Registro es cero, WMI no comprueba los niveles de autenticación. Para proteger las llamadas asincrónicas en el scripting, establezca la clave del Registro en 1. Los clientes de C++ pueden llamar a IWbemUnsecuredApartment::CreateSinkStub para controlar el acceso al receptor. El valor se crea en cualquier lugar de forma predeterminada.

En los temas siguientes se proporcionan ejemplos de configuración de la seguridad de las llamadas asincrónicas:

Establecimiento de la seguridad de las llamadas asincrónicas en C++

El método IWbemUnsecuredApartment::CreateSinkStub es similar al método IUnsecuredApartment::CreateObjectStub y crea un receptor en un proceso independiente, Unsecapp.exe, para recibir devoluciones de llamada. Sin embargo, el método CreateSinkStub tiene un parámetro dwFlagque especifica cómo administra ese proceso independiente el control de acceso.

El parámetro dwFlag especifica una de las acciones siguientes para Unsecapp.exe:

  • Use la configuración de la clave del Registro para determinar si se va a comprobar el acceso o no.
  • Ignore la clave del Registro y compruebe siempre el acceso.
  • Ignore la clave del Registro y no compruebe nunca el acceso.

El ejemplo de código de este tema requiere la siguiente instrucción #include para compilarse correctamente.

#include <wbemidl.h>

En el procedimiento siguiente se describe cómo realizar una llamada asincrónica con IWbemUnsecuredApartment.

Para realizar una llamada asincrónica con IWbemUnsecuredApartment:

  1. Cree un proceso dedicado con una llamada a CoCreateInstance.

    En el ejemplo de código siguiente se llama a CoCreateInstance para crear un proceso dedicado.

    CLSID                    CLSID_WbemUnsecuredApartment;
    IWbemUnsecuredApartment* pUnsecApp = NULL;
    
    CoCreateInstance(CLSID_WbemUnsecuredApartment, 
                     NULL, 
                     CLSCTX_LOCAL_SERVER, 
                     IID_IWbemUnsecuredApartment, 
                     (void**)&pUnsecApp);
    
  2. Cree una instancia del objeto receptor.

    En el ejemplo de código siguiente se crea un nuevo objeto receptor.

    CMySink* pSink = new CMySink;
    pSink->AddRef();
    
  3. Cree un código auxiliar para el receptor.

    Un código auxiliar es una función de contenedor generada a partir del receptor.

    En el ejemplo de código siguiente se crea código auxiliar para el receptor.

    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. Libere el puntero del objeto receptor.

    Puede liberar el puntero del objeto porque el código auxiliar ahora es el propietario del puntero.

    En el ejemplo de código siguiente se libera el puntero del objeto.

    pSink->Release();
    
  5. Use el código auxiliar en cualquier llamada asincrónica.

    Cuando termine con la llamada, libere el recuento de referencias locales.

    En el ejemplo de código siguiente se usa el código auxiliar en una llamada asincrónica.

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

    En ocasiones, es posible que tenga que cancelar una llamada asincrónica después de realizar la llamada. Si necesita cancelar la llamada, cancele la llamada con el mismo puntero que originalmente realizó la llamada.

    En el ejemplo de código siguiente se describe cómo cancelar una llamada asincrónica.

    pServices->CancelAsyncCall(pStubSink);
    
  6. Libere el recuento de referencias locales cuando haya terminado de usar la llamada asincrónica.

    Asegúrese de liberar el puntero pStubSink solo después de confirmar que no se debe cancelar la llamada asincrónica. Además, no libere pStubSink después de que WMI libere el puntero receptor pSink. La liberación de pStubSink después de pSink crea un recuento de referencias circular en el que el receptor y el código auxiliar permanecen en la memoria para siempre. Alternativamente, una posible ubicación para liberar el puntero está en la llamada IWbemObjectSink::SetStatus, realizada por WMI para informar de que la llamada asincrónica original está completa.

  7. Cuando termine, anule la inicialización de COM con una llamada a Release().

    En el ejemplo de código siguiente se muestra cómo llamar a Release() en el puntero pUnsecApp.

    pUnsecApp->Release();
    

Para obtener más información sobre los parámetros y la función CoInitializeSecurity, consulte la documentación de COM.