Impostazione della sicurezza su una chiamata asincrona

Le chiamate asincrone presentano gravi rischi per la sicurezza perché un callback al sink potrebbe non essere il risultato della chiamata asincrona da parte 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. Nello script impostare AuthenticationLevel nella connessione del 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 in un callback fino a quando il callback non 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 a livello di RPC_C_AUTHN_LEVEL_PKT_PRIVACY . Se il callback non riesce, WMI riduce il livello di autenticazione a un livello in cui il callback può avere esito positivo, se necessario, per 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 HKEY_LOCAL_MACHINE\Software\Microsoft\WBEMCIMOM\\UnsecAppAccessControlDefault del Registro di sistema controlla se WMI verifica se un livello di autenticazione accettabile nei callback. Si tratta dell'unico meccanismo per proteggere la sicurezza del sink 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.

    L'esempio di codice seguente chiama 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 a oggetti.

    pSink->Release();
    
  5. Usare 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 eseguito 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. Rilasciare il conteggio dei riferimenti locali al termine dell'uso della 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 sink pSink . Il rilascio di pStubSink dopo pSink crea un conteggio di riferimenti circolare in cui sia il sink che lo stub rimangono in memoria per sempre. È invece possibile rilasciare il puntatore nella chiamata IWbemObjectSink::SetStatus effettuata da WMI per segnalare che la chiamata asincrona originale è stata completata.

  7. Al termine, annullare l'inizializzazione di COM con una chiamata a Release().

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

    pUnsecApp->Release();
    

Per altre informazioni sulla funzione e i parametri CoInitializeSecurity , vedere la documentazione COM .