Configurar la autenticación mediante C++

Una de las tareas principales de IWbemLocator::ConnectServer para WMI devuelve un puntero a un proxy IWbemServices. A través del proxy IWbemServices, puede acceder a las funcionalidades de la infraestructura de WMI. Sin embargo, el puntero al proxy IWbemServices tiene la identidad del proceso de aplicación cliente y no la identidad del proceso de IWbemServices. Por lo tanto, si intenta acceder a IWbemServices con el puntero, puede recibir un código de acceso denegado, como E_ACCESSDENIED. Para evitar el error de acceso denegado, debe establecer la identidad del nuevo puntero con una llamada a la interfaz CoSetProxyBlanket.

Un proveedor puede establecer la seguridad en un espacio de nombres para que no se devuelva ningún dato a menos que use la privacidad de paquetes (PktPrivacy) en la conexión a ese espacio de nombres. Esto garantiza que los datos se cifren a medida que cruzan la red. Si intenta establecer un nivel de autenticación inferior, recibirá un mensaje de acceso denegado. Para obtener más información, consulte Establecer descriptores de seguridad de espacio de nombres.

Para obtener más información sobre cómo establecer la autenticación en scripting, consulte Establecer el nivel de seguridad de proceso predeterminado mediante VBScript.

Establecer la seguridad en una interfaz IUnknown remota

En algunas situaciones, se requiere más acceso a un servidor que solo un puntero a un proxy. En ocasiones, es posible que tenga que obtener una conexión segura a la interfaz IUnknown del proxy. Con IUnknown, puede consultar el sistema remoto para obtener interfaces y otras técnicas necesarias.

Cuando un proxy se encuentra en un equipo remoto, el servidor delega todas las llamadas a la interfaz IUnknown del proxy a la interfaz IUnknown. Por ejemplo, si llama a QueryInterface en un proxy y la interfaz solicitada no formaba parte del proxy, este envía la llamada al servidor remoto. A su vez, el servidor remoto comprueba la compatibilidad con la interfaz adecuada. Si el servidor admite la interfaz, COM serializa un nuevo proxy al cliente para que la aplicación pueda usar la nueva interfaz.

Surgen problemas si el cliente no tiene permisos de acceso al servidor remoto, pero está usando las credenciales de un usuario que sí lo hace. En esta situación, se produce un error en cualquier intento de acceso a QueryInterface en el servidor remoto. También se produce un error en la versión final del proxy, ya que el usuario actual no tiene acceso al servidor remoto. Un síntoma de esto es un retraso de uno o dos segundos antes de que la aplicación cliente produzca un error en la versión final del proxy. El error se produce porque COM intentó acceder al servidor remoto mediante la configuración de seguridad predeterminada del usuario actual, que no incluye las credenciales modificadas que permitían el acceso al servidor en primer lugar. Para obtener más información, consulte Establecer la seguridad en IWbemServices y otros servidores proxy.

Para evitar la conexión con errores, use CoSetProxyBlanket para establecer explícitamente la autenticación de seguridad en el puntero devuelto desde IUnknown. Con CoSetProxyBlanket, puede asegurarse de que el servidor remoto recibe la identidad de autenticación correcta.

En el ejemplo de código siguiente se muestra cómo usar CoSetProxyBlanket para acceder a una interfaz 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;

Nota

Al establecer la seguridad en la interfaz IUnknown de un proxy, COM crea una copia del proxy que no se puede liberar hasta que se llama a CoUninitialize.

 

Configurar la autenticación en WMI