Функция InitializeSecurityContext (Schannel)

Функция InitializeSecurityContext (Schannel) инициирует исходящий контекст безопасности на стороне клиента из дескриптора учетных данных. Функция используется для создания контекста безопасности между клиентским приложением и удаленным одноранговым элементом. InitializeSecurityContext (Schannel) возвращает маркер, который клиент должен передать удаленному одноранговому элементу, который одноранговый узел, в свою очередь, отправляет в локальную реализацию безопасности с помощью вызова AcceptSecurityContext (Schannel). Созданный маркер должен считаться непрозрачным всеми вызывающими.

Как правило, функция InitializeSecurityContext (Schannel) вызывается в цикле, пока не будет установлен достаточный контекст безопасности .

Синтаксис

SECURITY_STATUS SEC_Entry InitializeSecurityContext(
  _In_opt_    PCredHandle    phCredential,
  _In_opt_    PCtxtHandle    phContext,
  _In_opt_    SEC_CHAR       *pszTargetName,
  _In_        ULONG          fContextReq,
  _In_        ULONG          Reserved1,
  _In_        ULONG          TargetDataRep,
  _In_opt_    PSecBufferDesc pInput,
  _In_        ULONG          Reserved2,
  _Inout_opt_ PCtxtHandle    phNewContext,
  _Inout_opt_ PSecBufferDesc pOutput,
  _Out_       PULONG         pfContextAttr,
  _Out_opt_   PTimeStamp     ptsExpiry
);

Параметры

phCredential[in, optional]

Дескриптор учетных данных, возвращенных AcquireCredentialsHandle (Schannel). Этот дескриптор используется для создания контекста безопасности. Функции InitializeSecurityContext (Schannel) требуются по крайней мере учетные данные OUTBOUND при первом вызове. При последующих вызовах это может быть NULL.

phContext[in, optional]

Указатель на структуру CtxtHandle . При первом вызове InitializeSecurityContext (Schannel) этот указатель имеет значение NULL. При последующих вызовах этот параметр является указателем на дескриптор частично сформированного контекста, возвращаемого в параметре phNewContext при первом вызове этой функции.

Предупреждение

Не используйте один и тот же дескриптор контекста в параллельных вызовах InitializeSecurityContext (Schannel). Реализация API в поставщиках служб безопасности не является потокобезопасной.

pszTargetName[in, optional]

Указатель на строку, завершающуюся значением NULL, которая однозначно идентифицирует целевой сервер. Schannel использует это значение для проверки сертификата сервера. Schannel также использует это значение для поиска сеанса в кэше сеансов при восстановлении подключения. Кэшированный сеанс используется только при выполнении всех следующих условий:

  • Целевое имя совпадает.
  • Срок действия записи кэша не истек.
  • Процесс приложения, вызывающий функцию, совпадает.
  • Сеанс входа в систему совпадает.
  • Дескриптор учетных данных совпадает.

fContextReq[in]

Битовые флаги, указывающие запросы для контекста. Не все пакеты могут поддерживать все требования. Флаги, используемые для этого параметра, имеют префикс ISC_REQ_, например ISC_REQ_DELEGATE. Этот параметр может быть одним или несколькими из следующих флагов атрибутов.

Значение Значение
ISC_REQ_ALLOCATE_MEMORY Пакет безопасности выделяет выходные буферы. Завершив использование выходных буферов, освободите их, вызвав функцию FreeContextBuffer .
ISC_REQ_CONFIDENTIALITY Шифруйте сообщения с помощью функции EncryptMessage .
ISC_REQ_CONNECTION Контекст безопасности не будет обрабатывать сообщения форматирования.
ISC_REQ_EXTENDED_ERROR При возникновении ошибок удаленная сторона будет уведомлена.
ISC_REQ_INTEGRITY Подписывая сообщения и проверяя подписи с помощью функций EncryptMessage и MakeSignature .
ISC_REQ_MANUAL_CRED_VALIDATION Schannel не должна автоматически проходить проверку подлинности сервера.
ISC_REQ_MUTUAL_AUTH Политика взаимной проверки подлинности службы будет выполнена.
ОСТОРОЖНОСТЬЮ: Это не обязательно означает, что выполняется взаимная проверка подлинности, а только то, что политика проверки подлинности службы выполняется. Чтобы обеспечить выполнение взаимной проверки подлинности, вызовите функцию QueryContextAttributes (Schannel).
ISC_REQ_REPLAY_DETECT Обнаружение повторно воспроизводимых сообщений, которые были закодированы с помощью функций EncryptMessage или MakeSignature .
ISC_REQ_SEQUENCE_DETECT Обнаружение сообщений, полученных вне последовательности.
ISC_REQ_STREAM Поддержка потокового подключения.
ISC_REQ_USE_SUPPLIED_CREDS Schannel не должен пытаться предоставить учетные данные для клиента автоматически.

Запрошенные атрибуты могут не поддерживаться клиентом. Дополнительные сведения см. в параметре pfContextAttr .

Дополнительные описания различных атрибутов см. в разделе Требования к контексту.

Зарезервировано1[in]

Этот параметр зарезервирован и должен иметь нулевое значение.

TargetDataRep[in]

Этот параметр не используется в Schannel. Присвойте ему значение 0.

pInput[in, optional]

Указатель на структуру SecBufferDesc , содержащую указатели на буферы, предоставленные в качестве входных данных для пакета. Если контекст клиента не был инициирован сервером, значение этого параметра должно быть NULL при первом вызове функции. При последующих вызовах функции или при инициировании контекста клиента сервером значение этого параметра является указателем на буфер, выделенный с достаточным объемом памяти для хранения маркера, возвращенного удаленным компьютером.

При вызовах этой функции после первоначального вызова должно быть два буфера. Первый имеет тип SECBUFFER_TOKEN и содержит маркер, полученный от сервера. Второй буфер имеет тип SECBUFFER_EMPTY; Установите для членов pvBuffer и cbBuffer значение 0.

Зарезервировано2[in]

Этот параметр зарезервирован и должен иметь нулевое значение.

phNewContext[in, out, optional]

Указатель на структуру CtxtHandle . При первом вызове InitializeSecurityContext (Schannel) этот указатель получает новый дескриптор контекста. Во втором вызове phNewContext может совпадать с дескриптором, указанным в параметре phContext . PhNewContext никогда не должен иметь значение NULL.

pOutput[in, out, optional]

Указатель на структуру SecBufferDesc , содержащую указатели на структуру SecBuffer , получающую выходные данные. Если буфер был введен как SEC_READWRITE во входных данных, он будет там на выходе. Система выделяет буфер для маркера безопасности при запросе (через ISC_REQ_ALLOCATE_MEMORY) и заполняет адрес в дескрипторе буфера для маркера безопасности.

Если указан флаг ISC_REQ_ALLOCATE_MEMORY, Schannel SSP выделяет память для буфера и помещает соответствующие сведения в SecBufferDesc. Кроме того, вызывающий объект должен передавать буфер типа SECBUFFER_ALERT. В выходных данных, если создается оповещение, этот буфер содержит сведения об этом оповещении, и функция завершается сбоем.

pfContextAttr[out]

Указатель на переменную для получения набора битовых флагов, указывающих атрибуты установленного контекста. Описание различных атрибутов см. в разделе Требования к контексту.

Флаги, используемые для этого параметра, имеют префикс ISC_RET, например ISC_RET_DELEGATE. Список допустимых значений см. в параметре fContextReq .

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

Примечание

Определенные атрибуты контекста могут изменяться во время согласования с удаленным одноранговым элементом.

ptsExpiry[out, optional]

Указатель на структуру TimeStamp , которая получает время истечения срока действия контекста. Рекомендуется, чтобы пакет безопасности всегда возвращал это значение в местное время. Этот параметр является необязательным и NULL должен передаваться для кратковременных клиентов.

Возвращаемое значение

Если функция выполнена успешно, функция возвращает один из следующих кодов успешного выполнения.

Код возврата Описание
SEC_I_COMPLETE_AND_CONTINUE Клиент должен вызвать CompleteAuthToken , а затем передать выходные данные серверу. Затем клиент ожидает возвращенного маркера и передает его в другом вызове в Приложение InitializeSecurityContext (Schannel).
SEC_I_COMPLETE_NEEDED Клиент должен завершить сборку сообщения, а затем вызвать функцию CompleteAuthToken .
SEC_I_CONTINUE_NEEDED Клиент должен отправить выходной маркер на сервер и дождаться возврата маркера. Затем возвращенный маркер передается в другом вызове Метода InitializeSecurityContext (Schannel). Выходной маркер может быть пустым.
SEC_I_INCOMPLETE_CREDENTIALS Сервер запросил проверку подлинности клиента, и предоставленные учетные данные либо не включают сертификат, либо сертификат не был выдан центром сертификации (ЦС), который является доверенным для сервера. Дополнительные сведения см. в подразделе "Примечания".
SEC_E_INCOMPLETE_MESSAGE Данные для всего сообщения не были считаны из провода.
При возвращении этого значения буфер pInput содержит структуру SecBuffer с элементом BufferTypeSECBUFFER_MISSING. Член cbBufferэлемента SecBuffer содержит значение, указывающее количество дополнительных байтов, которые функция должна считывать у клиента, прежде чем эта функция будет успешно выполнена. Хотя это число не всегда является точным, его использование может помочь повысить производительность, избегая нескольких вызовов этой функции.
SEC_E_OK Контекст безопасности успешно инициализирован. Другой вызов InitializeSecurityContext (Schannel) не требуется. Если функция возвращает выходной маркер, то есть если SECBUFFER_TOKEN в pOutput имеет ненулевой длины, этот маркер должен быть отправлен на сервер.

Если функция завершается ошибкой, функция возвращает один из следующих кодов ошибок.

Код возврата Описание
SEC_E_INSUFFICIENT_MEMORY Недостаточно памяти для выполнения запрошенного действия.
SEC_E_INTERNAL_ERROR Произошла ошибка, не сопоставленная с кодом ошибки SSPI.
SEC_E_INVALID_HANDLE Дескриптор, переданный функции, недопустим.
SEC_E_INVALID_TOKEN Ошибка возникает из-за неправильно сформированного входного маркера, например поврежденного маркера при передаче, маркера неправильного размера или маркера, переданного в неправильное ограниченное делегирование. Передача маркера в неправильный пакет может произойти, если клиент и сервер не согласуют правильное ограниченное делегирование.
SEC_E_LOGON_DENIED Сбой входа.
SEC_E_NO_AUTHENTICATING_AUTHORITY Невозможно связаться с центром для проверки подлинности. Доменное имя стороны, проверяющей подлинность, может быть неправильным, домен может быть недостижимым или произошел сбой отношения доверия.
SEC_E_NO_CREDENTIALS В ограниченном делегировании учетные данные недоступны.
SEC_E_TARGET_UNKNOWN Цель не распознана.
SEC_E_UNSUPPORTED_FUNCTION Недопустимый флаг контекстного атрибута (ISC_REQ_DELEGATE или ISC_REQ_PROMPT_FOR_CREDS) был указан в параметре fContextReq .
SEC_E_WRONG_PRINCIPAL Субъект, получивший запрос проверки подлинности, отличается от субъекта, переданного в параметр pszTargetName . Это указывает на сбой во взаимной проверке подлинности.
SEC_E_APPLICATION_PROTOCOL_MISMATCH Между клиентом и сервером не существует общего протокола приложения.

Комментарии

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

Если атрибутов контекста безопасности недостаточно, клиент должен освободить частично созданный контекст, вызвав функцию DeleteSecurityContext .

Функция InitializeSecurityContext (Schannel) используется клиентом для инициализации исходящего контекста.

Для двухуровневого контекста безопасности последовательность вызовов выглядит следующим образом:

  1. Клиент вызывает функцию с параметром phContext и NULL заполняет дескриптор буфера входным сообщением.
  2. Пакет безопасности проверяет параметры и создает непрозрачный маркер, помещая его в элемент TOKEN в буферном массиве. Если параметр fContextReq содержит флаг ISC_REQ_ALLOCATE_MEMORY, пакет безопасности выделяет память и возвращает указатель в элементе TOKEN.
  3. Клиент отправляет маркер, возвращенный в буфере POutput , на целевой сервер. Затем сервер передает маркер в качестве входного аргумента в вызове функции AcceptSecurityContext (Schannel).
  4. AcceptSecurityContext (Schannel) может возвращать маркер, который сервер отправляет клиенту для второго вызова InitializeSecurityContext (Schannel), если первый вызов вернул SEC_I_CONTINUE_NEEDED.

Для многоуровневых контекстов безопасности, таких как взаимная проверка подлинности, последовательность вызовов выглядит следующим образом:

  1. Клиент вызывает функцию, как описано выше, но пакет возвращает код SEC_I_CONTINUE_NEEDED успешного выполнения.
  2. Клиент отправляет выходной маркер на сервер и ожидает ответа сервера.
  3. Получив ответ сервера, клиент снова вызывает InitializeSecurityContext (Schannel), а параметру phContext задан дескриптор, возвращенный после последнего вызова. Маркер, полученный от сервера, предоставляется в параметре pInput .
  4. Не используйте значение phContext в параллельных вызовах InitializeSecurityContext (Schannel). Реализация в поставщиках безопасности не является потокобезопасной.

Если сервер успешно ответил, пакет безопасности возвращает SEC_E_OK и устанавливается безопасный сеанс.

Если функция возвращает один из ответов об ошибке, ответ сервера не принимается, и сеанс не устанавливается.

Если функция возвращает SEC_I_CONTINUE_NEEDED, SEC_I_COMPLETE_NEEDED или SEC_I_COMPLETE_AND_CONTINUE, шаги 2 и 3 повторяются.

Для инициализации контекста безопасности может потребоваться несколько вызовов этой функции в зависимости от базового механизма проверки подлинности, а также от вариантов, указанных в параметре fContextReq .

Параметры fContextReq и pfContextAttributes представляют собой битовые маски, представляющие различные атрибуты контекста. Описание различных атрибутов см. в разделе Требования к контексту. Параметр pfContextAttributes действителен при любом успешном возвращении, но только при окончательном успешном возвращении, если вы изучите флаги, относящиеся к аспектам безопасности контекста. Промежуточные возвраты могут задавать, например, флаг ISC_RET_ALLOCATED_MEMORY.

Если установлен флаг ISC_REQ_USE_SUPPLIED_CREDS, пакет безопасности должен искать тип буфера SECBUFFER_PKG_PARAMS во входном буфере pInput . Это не универсальное решение, но при необходимости оно позволяет надежно связать пакет безопасности и приложение.

Если указан ISC_REQ_ALLOCATE_MEMORY, вызывающий объект должен освободить память, вызвав функцию FreeContextBuffer .

Например, входной маркер может быть проблемой от диспетчера локальной сети. В этом случае выходной маркер будет ответом на запрос с шифрованием NTLM.

Действия, которые выполняет клиент, зависят от кода, возвращаемого этой функцией. Если код возврата SEC_E_OK, второй вызов InitializeSecurityContext (Schannel) не будет выполняться, и ответ от сервера не ожидается. Если код возврата SEC_I_CONTINUE_NEEDED, клиент ожидает маркер в ответ от сервера и передает его во втором вызове InitializeSecurityContext (Schannel). Код возврата SEC_I_COMPLETE_NEEDED указывает, что клиент должен завершить сборку сообщения и вызвать функцию CompleteAuthToken . Код SEC_I_COMPLETE_AND_CONTINUE включает в себя оба этих действия.

Если InitializeSecurityContext (Schannel) возвращает успешное выполнение при первом (или только) вызове, то вызывающий объект должен в конечном итоге вызвать функцию DeleteSecurityContext в возвращенном дескрипторе, даже если вызов завершается сбоем на более позднем этапе обмена проверкой подлинности.

Клиент может снова вызвать InitializeSecurityContext (Schannel) после успешного завершения. Это указывает пакету безопасности на то, что требуется повторная проверку подлинности.

Вызывающие объекты режима ядра имеют следующие отличия: целевое имя — это строка Юникода , которая должна быть выделена в виртуальной памяти с помощью VirtualAlloc; Он не должен быть выделен из пула. Буферы, переданные и предоставленные в pInput и pOutput , должны находиться в виртуальной памяти, а не в пуле.

Если функция возвращает SEC_I_INCOMPLETE_CREDENTIALS, проверка, что в учетных данных указан действительный и доверенный сертификат. Сертификат указывается при вызове функции AcquireCredentialsHandle (Schannel). Сертификат должен быть сертификатом проверки подлинности клиента, выданным центром сертификации (ЦС), доверенным сервером. Чтобы получить список ЦС, доверенных сервером, вызовите функцию QueryContextAttributes (Schannel) и укажите атрибут SECPKG_ATTR_ISSUER_LIST_EX.

После того как клиентское приложение получит сертификат проверки подлинности из ЦС, которому доверяет сервер, приложение создает новые учетные данные, вызывая функцию AcquireCredentialsHandle (Schannel), а затем снова вызывая InitializeSecurityContext (Schannel), указав новые учетные данные в параметре phCredential .

Требования

Требование Значение
Минимальная версия клиента Windows 8.1 [только классические приложения]
Минимальная версия сервера Windows Server 2012 R2 [только классические приложения]
Заголовок Sspi.h (включая Security.h)
Библиотека Secur32.lib
DLL Secur32.dll

См. также раздел

Функции SSPI

AcceptSecurityContext (Schannel)

AcquireCredentialsHandle (Schannel)

CompleteAuthToken

DeleteSecurityContext

FreeContextBuffer

SecBuffer

SecBufferDesc