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


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

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

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

Дополнительные сведения о настройке проверки подлинности в скриптах см. в разделе Настройка уровня безопасности процесса по умолчанию с помощью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