Поделиться через


Настройка проверки подлинности с помощью C++

Одной из main задач IWbemLocator::ConnectServer для WMI является возврат указателя на прокси-сервер IWbemServices. Через прокси-сервер IWbemServices можно получить доступ к возможностям инфраструктуры WMI. Однако указатель на прокси-сервер IWbemServices имеет удостоверение процесса клиентского приложения, а не удостоверение процесса IWbemServices . Поэтому при попытке получить доступ к IWbemServices с помощью указателя можно получить код с отказом в доступе, например E_ACCESSDENIED. Чтобы избежать ошибки отказа в доступе, необходимо задать удостоверение нового указателя с помощью вызова интерфейса CoSetProxyBlanket .

Поставщик может задать безопасность пространства имен таким образом, чтобы данные не возвращались, если вы не используете конфиденциальность пакетов (PktPrivacy) в подключении к пространству имен. Это гарантирует, что данные шифруются по мере того, как они пересекают сеть. При попытке задать более низкий уровень проверки подлинности вы получите сообщение об отказе в доступе. Дополнительные сведения см. в разделе Настройка дескрипторов безопасности для платформы имен.

Дополнительные сведения о настройке проверки подлинности в скриптах см. в разделе Настройка уровня безопасности процесса по умолчанию с помощью VBScript.

Настройка безопасности в удаленном интерфейсе IUnknown

В некоторых ситуациях требуется больше доступа к серверу, чем просто указатель на прокси-сервер. Иногда может потребоваться безопасное подключение к интерфейсу IUnknown прокси-сервера. С помощью IUnknown можно запросить у удаленной системы интерфейсы и другие необходимые методы.

Если прокси-сервер находится на удаленном компьютере, сервер делегирует все вызовы интерфейса IUnknown прокси-сервера интерфейсу IUnknown . Например, если вы вызываете QueryInterface на прокси-сервере и запрошенный интерфейс не был частью прокси-сервера, прокси-сервер отправляет вызов удаленному серверу. В свою очередь, удаленный сервер проверяет наличие соответствующей поддержки интерфейса. Если сервер поддерживает интерфейс , COM маршалирует новый прокси-сервер обратно клиенту, чтобы приложение пользовалось новым интерфейсом.

Проблемы возникают, если клиент не имеет разрешений на доступ к удаленному серверу, но использует учетные данные пользователя, который это делает. В этом случае любая попытка получить доступ к QueryInterface на удаленном сервере завершается сбоем. Окончательный выпуск на прокси-сервере также завершается сбоем, так как текущий пользователь не имеет доступа к удаленному серверу. Признаком этого является задержка в одну или две секунды, прежде чем клиентское приложение не сможет окончательно освободить прокси-сервер. Сбой происходит из-за того, что COM попыталась получить доступ к удаленному серверу с помощью параметров безопасности по умолчанию текущего пользователя, которые не включают измененные учетные данные, разрешающие доступ к серверу. Дополнительные сведения см. в разделе Настройка безопасности для IWbemServices и других прокси-серверов.

Чтобы избежать неудачного подключения, используйте CoSetProxyBlanket , чтобы явно задать проверку подлинности безопасности для указателя, возвращаемого из IUnknown. С помощью CoSetProxyBlanket можно убедиться, что удаленный сервер получает правильное удостоверение проверки подлинности.

В следующем примере кода показано, как использовать CoSetProxyBlanket для доступа к удаленному интерфейсу 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;

Примечание

При настройке безопасности в интерфейсе IUnknown прокси-сервера COM создает копию прокси-сервера, которая не может быть освобождена, пока вы не вызовете CoUninitialize.

 

Настройка проверки подлинности в WMI