Udostępnij za pośrednictwem


Ustawianie uwierzytelniania przy użyciu języka C++

Jedno z głównych zadań IWbemLocator::ConnectServer dla WMI jest zwracanie wskaźnika do proxy usługi IWbemServices. Za pośrednictwem serwera proxy IWbemServices można uzyskać dostęp do możliwości infrastruktury WMI. Jednak wskaźnik do proxy IWbemServices ma tożsamość procesu aplikacji klienckiej, a nie tożsamość procesu IWbemServices. W związku z tym, jeśli próbujesz uzyskać dostęp do IWbemServices za pomocą wskaźnika, możesz otrzymać kod odmowy dostępu, taki jak E_ACCESSDENIED. Aby uniknąć błędu odmowy dostępu, musisz ustawić tożsamość nowego wskaźnika, wywołując interfejs CoSetProxyBlanket.

Dostawca może ustawić zabezpieczenia w przestrzeni nazw tak, aby żadne dane nie zostały zwrócone, chyba że używasz prywatności pakietów (PktPrivacy) w połączeniu z tą przestrzenią nazw. Dzięki temu dane są szyfrowane w miarę przekraczania sieci. Jeśli spróbujesz ustawić niższy poziom uwierzytelniania, otrzymasz komunikat o odmowie dostępu. Aby uzyskać więcej informacji, zobacz Setting Namepace Security Descriptors.

Aby uzyskać więcej informacji na temat ustawiania uwierzytelniania w skryptach, zobacz Ustawianie domyślnego poziomu zabezpieczeń procesu przy użyciu języka VBScript.

Ustawianie zabezpieczeń w zdalnym interfejsie IUnknown

W niektórych sytuacjach wymagany jest większy dostęp do serwera niż tylko wskazanie na serwer proxy. Czasami może być konieczne uzyskanie bezpiecznego połączenia z interfejsem IUnknown serwera proxy. Korzystając z IUnknown, można przeprowadzać zapytania do zdalnego systemu o interfejsy i inne potrzebne techniki.

Gdy serwer proxy znajduje się na komputerze zdalnym, serwer deleguje wszystkie wywołania do interfejsu IUnknown serwera proxy do interfejsu IUnknown. Jeśli na przykład wywołasz QueryInterface na serwerze proxy, a żądany interfejs nie był częścią serwera proxy, serwer proxy wysyła wywołanie do serwera zdalnego. Z kolei serwer zdalny sprawdza odpowiednią obsługę interfejsu. Jeśli serwer obsługuje interfejs, COM przekazuje nową reprezentację proxy z powrotem do klienta, aby aplikacja mogła korzystać z nowego interfejsu.

Problemy występują, jeśli klient nie ma uprawnień dostępu do serwera zdalnego, ale używa poświadczeń użytkownika, który to robi. W takiej sytuacji próba uzyskania dostępu do QueryInterface na serwerze zdalnym kończy się niepowodzeniem. Końcowa wersja serwera proxy również kończy się niepowodzeniem, ponieważ bieżący użytkownik nie ma dostępu do serwera zdalnego. Objawem jest jedno lub dwie sekundowe opóźnienie, zanim aplikacja kliencka zakończy się niepowodzeniem ostatecznej wersji serwera proxy. Błąd występuje, ponieważ com próbował uzyskać dostęp do serwera zdalnego przy użyciu domyślnych ustawień zabezpieczeń bieżącego użytkownika, które nie zawierają zmodyfikowanych poświadczeń, które zezwalały na dostęp do serwera w pierwszej kolejności. Aby uzyskać więcej informacji, zobacz Setting the Security on IWbemServices and Other Proxies.

Aby uniknąć nieudanego połączenia, użyj CoSetProxyBlanket, aby jawnie ustawić uwierzytelnianie zabezpieczeń na wskaźniku zwróconym z IUnknown. Za pomocą coSetProxyBlanketmożna upewnić się, że serwer zdalny otrzyma poprawną tożsamość uwierzytelniania.

Poniższy przykład kodu pokazuje, jak używać CoSetProxyBlanket w celu uzyskania dostępu do zdalnego interfejsu IUnknown.

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;

Notatka

Po ustawieniu zabezpieczeń w interfejsie IUnknown proxy, COM tworzy kopię proxy, której nie można zwolnić, dopóki nie wywołasz CoUninitialize.

 

Ustawianie uwierzytelniania w usłudze WMI