Festlegen der Authentifizierung mithilfe von C++

Eine der Standardaufgaben von IWbemLocator::ConnectServer für WMI ist die Rückgabe eines Zeigers auf einen IWbemServices-Proxy. Über den IWbemServices-Proxy können Sie auf die Funktionen der WMI-Infrastruktur zugreifen. Der Zeiger auf den IWbemServices-Proxy weist jedoch die Identität des Clientanwendungsprozesses und nicht die Identität des IWbemServices-Prozesses auf. Wenn Sie daher versuchen, mit dem Zeiger auf IWbemServices zuzugreifen, können Sie einen Zugriffsverweigerungscode erhalten, z. B. E_ACCESSDENIED. Um den Zugriffsverweigerungsfehler zu vermeiden, müssen Sie die Identität des neuen Zeigers mit einem Aufruf der CoSetProxyBlanket-Schnittstelle festlegen.

Ein Anbieter kann die Sicherheit für einen Namespace so festlegen, dass nur dann Daten zurückgegeben werden, wenn Sie den Paketdatenschutz (PktPrivacy) in Ihrer Verbindung mit diesem Namespace verwenden. Dadurch wird sichergestellt, dass die Daten auf ihrem Weg durch das Netzwerk verschlüsselt werden. Wenn Sie versuchen, eine niedrigere Authentifizierungsstufe festzulegen, erhalten Sie eine Nachricht „Zugriff verweigert. Weitere Informationen finden Sie unter Festlegen von Namepace-Sicherheitsbeschreibungen.

Weitere Informationen zum Festlegen der Authentifizierung in Skripts finden Sie unter Festlegen der Standardprozesssicherheitsstufe mit VBScript.

Festlegen der Sicherheit für eine Remote-IUnknown-Schnittstelle

In einigen Situationen ist mehr Zugriff auf einen Server als nur ein Zeiger auf einen Proxy erforderlich. Manchmal müssen Sie möglicherweise eine sichere Verbindung mit der IUnknown-Schnittstelle des Proxys herstellen. Mit IUnknown können Sie das Remotesystem nach Schnittstellen und anderen erforderlichen Techniken abfragen.

Wenn sich ein Proxy auf einem Remotecomputer befindet, delegiert der Server alle Aufrufe an die IUnknown-Schnittstelle des Proxys an die IUnknown-Schnittstelle. Wenn Sie beispielsweise QueryInterface auf einem Proxy aufrufen und die angeforderte Schnittstelle nicht Teil des Proxys war, sendet der Proxy den Aufruf an den Remoteserver. Der Remoteserver sucht wiederum nach der entsprechenden Schnittstellenunterstützung. Wenn der Server die Schnittstelle unterstützt, marshallt COM einen neuen Proxy zurück an den Client, damit die Anwendung die neue Schnittstelle verwenden kann.

Probleme treten auf, wenn der Client nicht über Zugriffsberechtigungen für den Remoteserver verfügt, aber die Anmeldeinformationen eines Benutzers verwendet, der dies tut. In diesem Fall ist jeder Versuch fehlerhaft, auf dem Remoteserver auf QueryInterface zuzugreifen. Auch bei der endgültigen Freigabe auf dem Proxy tritt ein Fehler auf, da der aktuelle Benutzer keinen Zugriff auf den Remoteserver hat. Ein Symptom hierfür ist eine Verzögerung von ein oder zwei Sekunden, bevor bei der endgültigen Freigabe der Clientanwendung auf dem Proxy ein Fehler auftritt. Der Fehler tritt auf, weil COM versucht hat, mit den Standardsicherheitseinstellungen des aktuellen Benutzers auf den Remoteserver zuzugreifen, die nicht die geänderten Anmeldeinformationen enthalten, die den Zugriff auf den Server überhaupt zugelassen haben. Weitere Informationen finden Sie unter Festlegen von Sicherheitseinstellungen für IWbemServices und andere Proxys.

Um die fehlerhafte Verbindung zu vermeiden, verwenden Sie CoSetProxyBlanket, um die Sicherheitsauthentifizierung für den von IUnknown zurückgegebenen Zeiger explizit festzulegen. Mit CoSetProxyBlanket können Sie sicherstellen, dass der Remoteserver die richtige Authentifizierungsidentität erhält.

Im folgenden Codebeispiel wird gezeigt, wie Sie mit CoSetProxyBlanket auf eine IUnknown-Remoteschnittstelle zugreifen.

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;

Hinweis

Wenn Sie die Sicherheit für die IUnknown-Schnittstelle eines Proxys festlegen, erstellt COM eine Kopie des Proxys, die erst freigegeben werden kann, wenn Sie CoUninitialize aufrufen.

 

Festlegen der Authentifizierung in WMI