Condividi tramite


Impostazione della sicurezza in una chiamata asincrona

Le chiamate asincrone presentano gravi rischi per la sicurezza perché un callback al sink potrebbe non essere il risultato di una chiamata asincrona dell'applicazione o dello script originale. La sicurezza nelle connessioni remote si basa sulla crittografia della comunicazione tra il client e il provider nel computer remoto. In C++ è possibile impostare la crittografia tramite il parametro del livello di autenticazione nella chiamata a CoInitializeSecurity. Nella creazione di script impostare il authenticationLevel nella connessione moniker o su un oggetto SWbemSecurity. Per altre informazioni, vedere Impostazione del livello di sicurezza del processo predefinito tramite VBScript.

I rischi di sicurezza per le chiamate asincrone esistono perché WMI riduce il livello di autenticazione su un callback fino a quando il callback riesce. In una chiamata asincrona in uscita, il client può impostare il livello di autenticazione sulla connessione a WMI. WMI recupera le impostazioni di sicurezza nella chiamata client e tenta di eseguire il callback con lo stesso livello di autenticazione. Il callback viene sempre avviato al livello di RPC_C_AUTHN_LEVEL_PKT_PRIVACY. Se il callback non riesce, WMI riduce il livello di autenticazione fino a un punto in cui il callback può avere esito positivo, se necessario, a RPC_C_AUTHN_LEVEL_NONE. Nel contesto delle chiamate all'interno del sistema locale in cui il servizio di autenticazione non è Kerberos, il callback viene sempre restituito in RPC_C_AUTHN_LEVEL_NONE.

Il livello di autenticazione minimo è RPC_C_AUTHN_LEVEL_PKT (wbemAuthenticationLevelPktper lo scripting). Tuttavia, è possibile specificare un livello superiore, ad esempio RPC_C_AUTHN_LEVEL_PKT_PRIVACY (wbemAuthenticationLevelPktPrivacy). È consigliabile che le applicazioni client o gli script impostino il livello di autenticazione su RPC_C_AUTHN_LEVEL_DEFAULT (wbemAuthenticationLevelDefault) che consente di negoziare il livello di autenticazione al livello specificato dal server.

Il valore del Registro di sistema HKEY_LOCAL_MACHINE\Software\Microsoft\WBEM\CIMOM\UnsecAppAccessControlDefault controlla se WMI verifica un livello di autenticazione accettabile nei callback. Questo è l'unico meccanismo per proteggere la sicurezza del punto di ricezione per le chiamate asincrone effettuate nello scripting o in Visual Basic. Per impostazione predefinita, questa chiave del Registro di sistema è impostata su zero. Se la chiave del Registro di sistema è zero, WMI non verifica i livelli di autenticazione. Per proteggere le chiamate asincrone nello scripting, impostare la chiave del Registro di sistema su 1. I client C++ possono chiamare IWbemUnsecuredApartment::CreateSinkStub per controllare l'accesso al sink. Il valore viene creato ovunque per impostazione predefinita.

Negli argomenti seguenti vengono forniti esempi di impostazione della sicurezza delle chiamate asincrone:

Impostazione della sicurezza delle chiamate asincrone in C++

Il metodo IWbemUnsecuredApartment::CreateSinkStub è simile al metodo IUnsecuredApartment::CreateObjectStub e crea un sink in un processo separato, Unsecapp.exe, per ricevere i callback. Tuttavia, il metodo createSinkStub ha un parametro dwFlagche specifica come il processo separato gestisce il controllo di accesso.

Il parametro dwFlag specifica una delle azioni seguenti per Unsecapp.exe:

  • Usare l'impostazione della chiave del Registro di sistema per determinare se controllare o meno l'accesso.
  • Ignorare la chiave del Registro di sistema e controllare sempre l'accesso.
  • Ignorare la chiave del Registro di sistema e non controllare mai l'accesso.

L'esempio di codice in questo argomento richiede che l'istruzione #include seguente venga compilata correttamente.

#include <wbemidl.h>

La procedura seguente descrive come eseguire una chiamata asincrona con IWbemUnsecuredApartment.

Per eseguire una chiamata asincrona con IWbemUnsecuredApartment

  1. Creare un processo dedicato con una chiamata a CoCreateInstance.

    Nell'esempio di codice seguente viene chiamato CoCreateInstance per creare un processo dedicato.

    CLSID                    CLSID_WbemUnsecuredApartment;
    IWbemUnsecuredApartment* pUnsecApp = NULL;
    
    CoCreateInstance(CLSID_WbemUnsecuredApartment, 
                     NULL, 
                     CLSCTX_LOCAL_SERVER, 
                     IID_IWbemUnsecuredApartment, 
                     (void**)&pUnsecApp);
    
  2. Creare un'istanza dell'oggetto sink.

    Nell'esempio di codice seguente viene creato un nuovo oggetto sink.

    CMySink* pSink = new CMySink;
    pSink->AddRef();
    
  3. Creare uno stub per il sink.

    Uno stub è una funzione wrapper prodotta dal sink.

    Nell'esempio di codice seguente viene creato uno stub per il sink.

    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. Rilasciare il puntatore dell'oggetto sink.

    È possibile rilasciare il puntatore all'oggetto perché lo stub è ora proprietario del puntatore.

    Nell'esempio di codice seguente viene rilasciato il puntatore all'oggetto.

    pSink->Release();
    
  5. Utilizzare lo stub in qualsiasi chiamata asincrona.

    Al termine della chiamata, rilasciare il conteggio dei riferimenti locali.

    Nell'esempio di codice seguente viene usato lo stub in una chiamata asincrona.

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

    A volte potrebbe essere necessario annullare una chiamata asincrona dopo aver effettuato la chiamata. Se è necessario annullare la chiamata, annullare la chiamata con lo stesso puntatore che ha originariamente effettuato la chiamata.

    Nell'esempio di codice seguente viene descritto come annullare una chiamata asincrona.

    pServices->CancelAsyncCall(pStubSink);
    
  6. Rilascia il conteggio dei riferimenti locali quando hai finito di usare la chiamata asincrona.

    Assicurarsi di rilasciare il puntatore pStubSink solo dopo aver verificato che la chiamata asincrona non deve essere annullata. Inoltre, non rilasciare pStubSink dopo che WMI rilascia il puntatore del sink pSink. Rilasciando pStubSink dopo pSink crea un conteggio di riferimenti circolare in cui il sink e lo stub rimangono in memoria per sempre. Al contrario, una possibile posizione in cui rilasciare il puntatore si trova nella chiamata IWbemObjectSink::SetStatus effettuata da WMI per segnalare che la chiamata asincrona originale è stata completata.

  7. Al termine, deinizializzare COM con una chiamata a Release().

    Nell'esempio di codice seguente viene illustrato come chiamare Release() sul puntatore pUnsecApp.

    pUnsecApp->Release();
    

Per ulteriori informazioni sulla funzione e sui parametri CoInitializeSecurity, vedere la documentazione COM.