Написание клиента SSPI с проверкой подлинности
Для всех сеансов клиента или сервера RPC требуется привязка между клиентом и сервером. Чтобы обеспечить безопасность клиентских и серверных приложений, программы должны использовать привязку с проверкой подлинности. В этом разделе описывается процесс создания привязки, прошедшей проверку подлинности, между клиентом и сервером.
Дополнительные сведения см. в разделе Процедуры, используемые с большинством пакетов безопасности и протоколов в пакете SDK для платформы.
Создание дескрипторов привязки на стороне клиента
Чтобы создать сеанс с проверкой подлинности с помощью серверной программы, клиентские приложения должны предоставлять сведения о проверке подлинности с помощью дескриптора привязки. Чтобы настроить дескриптор привязки с проверкой подлинности, клиенты вызывают функцию RpcBindingSetAuthInfo или RpcBindingSetAuthInfoEx . Эти две функции почти идентичны. Единственное различие между ними заключается в том, что клиент может указать качество обслуживания с помощью функции RpcBindingSetAuthInfoEx .
В следующем фрагменте кода показано, как может выглядеть вызов RpcBindingSetAuthInfo .
// This code fragment assumes that rpcBinding is a valid binding
// handle between the client and the server. It also assumes that
// pAuthCredentials is a valid pointer to a data structure which
// contains the user's authentication credentials.
dwStatus = DsMakeSpn(
"ldap",
"ServerName.domain.com",
NULL,
0,
NULL,
&pcSpnLength,
pszSpn);
//...
rpcStatus = RpcBindingSetAuthInfo(
rpcBinding, // Valid binding handle
pszSpn, // Principal name
RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, // Authentication level
RPC_C_AUTHN_GSS_NEGOTIATE, // Use Negotiate SSP
NULL, // Authentication credentials <entity type="ndash"/> use current thread credentials
RPC_C_AUTHZ_NAME); // Authorization service
После успешного вызова клиентом функций RpcBindingSetAuthInfo или RpcBindingSetAuthInfoEx библиотека времени выполнения RPC автоматически проверяет подлинность всех вызовов RPC в привязке. Уровень безопасности и проверки подлинности, выбираемый клиентом, применяется только к такому дескрипторову привязки. Дескрипторы контекста, производные от дескриптора привязки, будут использовать те же сведения о безопасности, но последующие изменения дескриптора привязки не будут отражены в дескрипторах контекста. Дополнительные сведения см. в разделе Контекстные дескрипторы.
Уровень проверки подлинности остается в силе до тех пор, пока клиент не выберет другой уровень или пока процесс не завершится. Для большинства приложений не требуется изменение уровня безопасности. Клиент может запросить любой дескриптор привязки для получения сведений об авторизации, вызвав RpcBindingInqAuthClient и передав ему дескриптор привязки.
Предоставление учетных данных клиента серверу
Серверы используют сведения о привязке клиента для обеспечения безопасности. Клиенты всегда передают дескриптор привязки в качестве первого параметра вызова удаленной процедуры. Однако серверы не могут использовать дескриптор, если он не объявлен в качестве первого параметра для удаленных процедур в IDL-файле или в файле конфигурации приложения сервера (ACF). Вы можете выбрать перечисление дескриптора привязки в IDL-файле, но это заставляет все клиенты объявлять дескриптор привязки и управлять им, а не использовать автоматическую или неявную привязку. Дополнительные сведения см. в разделе Файлы IDL и ACF.
Другой способ — оставить дескрипторы привязки из IDL-файла и поместить атрибут explicit_handle в ACF сервера. Таким образом, клиент может использовать тип привязки, наиболее подходящий для приложения, в то время как сервер использует дескриптор привязки, как если бы он был объявлен явным образом.
Процесс извлечения учетных данных клиента из дескриптора привязки происходит следующим образом:
- Клиенты RPC вызывают RpcBindingSetAuthInfo и включают сведения о проверке подлинности в составе сведений о привязке, передаваемых на сервер.
- Обычно сервер вызывает RpcImpersonateClient , чтобы вести себя так, как если бы он был клиентом. Если дескриптор привязки не прошел проверку подлинности, вызов завершается сбоем с RPC_S_NO_CONTEXT_AVAILABLE. Чтобы получить имя пользователя клиента, вызовите RpcBindingInqAuthClient при олицетворении или в Windows XP или более поздних версиях Windows вызовите RpcGetAuthorizationContextForClient , чтобы получить контекст авторизации, а затем используйте функции Authz для получения имени.
- Сервер обычно вызывает CreatePrivateObjectSecurity для создания объектов с списками управления доступом. После этого последующие проверки безопасности становятся автоматическими.