InitializeSecurityContextA 函数 (sspi.h)

InitializeSecurityContext (常规) 函数从凭据句柄启动客户端出站安全上下文。 函数用于在客户端应用程序和远程对等方之间生成安全上下文。 InitializeSecurityContext (常规) 返回一个令牌,客户端必须传递给远程对等方,后者又通过 AcceptSecurityContext (常规) 调用提交到本地安全实现。 所有调用方都应将生成的令牌视为不透明。

通常,在建立足够的安全上下文之前,在循环中调用 InitializeSecurityContext (General) 函数。

有关将此函数与特定 安全支持提供程序 (SSP) 配合使用的信息,请参阅以下主题。

主题 说明
InitializeSecurityContext (CredSSP) 使用凭据安全支持提供程序 (CredSSP) 从凭据句柄启动客户端出站安全上下文。
InitializeSecurityContext (摘要) 使用摘要安全包从凭据句柄启动客户端出站安全上下文。
InitializeSecurityContext (Kerberos) 使用 Kerberos 安全包从凭据句柄启动客户端出站安全上下文。
InitializeSecurityContext (协商) 使用协商安全包从凭据句柄启动客户端出站安全上下文。
InitializeSecurityContext (NTLM) 使用 NTLM 安全包从凭据句柄启动客户端出站安全上下文。
InitializeSecurityContext (Schannel) 使用 Schannel 安全包从凭据句柄启动客户端出站安全上下文。

语法

SECURITY_STATUS SEC_ENTRY InitializeSecurityContextA(
  [in, optional]      PCredHandle    phCredential,
  [in, optional]      PCtxtHandle    phContext,
                      SEC_CHAR       *pszTargetName,
  [in]                unsigned long  fContextReq,
  [in]                unsigned long  Reserved1,
  [in]                unsigned long  TargetDataRep,
  [in, optional]      PSecBufferDesc pInput,
  [in]                unsigned long  Reserved2,
  [in, out, optional] PCtxtHandle    phNewContext,
  [in, out, optional] PSecBufferDesc pOutput,
  [out]               unsigned long  *pfContextAttr,
  [out, optional]     PTimeStamp     ptsExpiry
);

参数

[in, optional] phCredential

AcquireCredentialsHandle 返回的凭据的句柄 (常规) 。 此句柄用于生成 安全上下文InitializeSecurityContext (General) 函数至少需要出站凭据。

[in, optional] phContext

指向 CtxtHandle 结构的指针。 在首次调用 InitializeSecurityContext (General) 时,此指针为 NULL。 在第二次调用中,此参数是指向第一次调用在 phNewContext 参数中返回的部分格式上下文的句柄的指针。

此参数对于 Microsoft Digest SSP 是可选的,可以设置为 NULL

使用 Schannel SSP 时,在首次调用 InitializeSecurityContext (General) 时指定 NULL。 在将来的调用中,指定在首次调用此函数后 在 phNewContext 参数中收到的令牌。

pszTargetName

TBD

[in] fContextReq

指示上下文请求的位标志。 并非所有包都可以支持所有要求。 用于此参数的标志以 ISC_REQ_ 为前缀,例如,ISC_REQ_DELEGATE。 此参数可以是以下一个或多个属性标志。

含义
ISC_REQ_ALLOCATE_MEMORY
安全包会为你分配输出缓冲区。 使用完输出缓冲区后,通过调用 FreeContextBuffer 函数释放它们。
ISC_REQ_CONFIDENTIALITY
使用 EncryptMessage 函数加密 消息。
ISC_REQ_CONNECTION
安全上下文不会处理格式化消息。 此值是 Kerberos、Negotiate 和 NTLM 安全包的默认值。
ISC_REQ_DELEGATE
服务器可以使用上下文作为客户端向其他服务器进行身份验证。 必须设置ISC_REQ_MUTUAL_AUTH标志才能使此标志正常工作。 对 Kerberos 有效。 对于 受约束委派,请忽略此标志。
ISC_REQ_EXTENDED_ERROR
发生错误时,远程方将收到通知。
ISC_REQ_HTTP
使用用于 HTTP 的摘要。 省略此标志以将摘要用作 SASL 机制。
ISC_REQ_INTEGRITY
使用 EncryptMessageMakeSignature 函数对消息进行签名和验证签名。
ISC_REQ_MANUAL_CRED_VALIDATION
Schannel 不得自动对服务器进行身份验证。
ISC_REQ_MUTUAL_AUTH
将满足服务的相互身份验证策略。
谨慎 这并不一定意味着要执行相互身份验证,只意味着满足服务的身份验证策略。 若要确保执行相互身份验证,请调用 QueryContextAttributes (General) 函数。
 
ISC_REQ_NO_INTEGRITY
如果设置了此标志,则忽略 ISC_REQ_INTEGRITY 标志。

只有 Negotiate 和 Kerberos 安全包支持此值。

ISC_REQ_REPLAY_DETECT
检测已使用 EncryptMessageMakeSignature 函数编码的重播消息。
ISC_REQ_SEQUENCE_DETECT
检测不按顺序接收的消息。
ISC_REQ_STREAM
支持面向流的连接。
ISC_REQ_USE_SESSION_KEY
必须协商新的 会话密钥

仅 Kerberos 安全包支持此值。

ISC_REQ_USE_SUPPLIED_CREDS
Schannel 不得尝试自动为客户端提供凭据。
 

客户端可能不支持请求的属性。 有关详细信息,请参阅 pfContextAttr 参数。

有关各种属性的进一步说明,请参阅 上下文要求

[in] Reserved1

此参数是保留的,必须设置为零。

[in] TargetDataRep

目标上的数据表示形式,例如字节排序。 此参数可以是SECURITY_NATIVE_DREP或SECURITY_NETWORK_DREP。

此参数不与 Digest 或 Schannel 一起使用。 将其设置为零。

[in, optional] pInput

指向 SecBufferDesc 结构的指针,该结构包含指向作为输入提供给包的缓冲区的指针。 除非客户端上下文由服务器启动,否则首次调用函数时此参数的值必须为 NULL 。 在对函数的后续调用或服务器启动客户端上下文时,此参数的值是指向分配的缓冲区的指针,该缓冲区具有足够的内存来保存远程计算机返回的令牌。

[in] Reserved2

此参数是保留的,必须设置为零。

[in, out, optional] phNewContext

指向 CtxtHandle 结构的指针。 在第一次调用 InitializeSecurityContext (General) 时,此指针接收新的上下文句柄。 第二次调用 时,phNewContext 可以与 phContext 参数中指定的句柄相同。

使用 Schannel SSP 时,在第一次调用后的调用中,将此处返回的句柄作为 phContext 参数传递,并为 phNewContext 指定 NULL

[in, out, optional] pOutput

指向 SecBufferDesc 结构的指针,该结构包含指向接收输出数据的 SecBuffer 结构的指针。 如果在输入中将缓冲区键入为SEC_READWRITE,则输出中将存在缓冲区。 如果通过ISC_REQ_ALLOCATE_MEMORY) 请求 (安全令牌,系统会为安全令牌分配缓冲区,并在安全令牌的缓冲区描述符中填写地址。

使用 Microsoft Digest SSP 时,此参数接收必须发送到服务器的质询响应。

使用 Schannel SSP 时,如果指定了 ISC_REQ_ALLOCATE_MEMORY 标志,则 Schannel SSP 将为缓冲区分配内存,并将相应的信息放入 SecBufferDesc 中。 此外,调用方必须传入 SECBUFFER_ALERT 类型的缓冲区。 在输出中,如果生成警报,则此缓冲区包含有关该警报的信息,并且函数将失败。

[out] pfContextAttr

指向变量的指针,用于接收一组指示已建立上下文的属性的位标志。 有关各种属性的说明,请参阅 上下文要求

用于此参数的标志以 ISC_RET 为前缀,例如 ISC_RET_DELEGATE。

有关有效值的列表,请参阅 fContextReq 参数。

在最终函数调用成功返回之前,不要检查与安全相关的属性。 与安全性无关的属性标志(如ASC_RET_ALLOCATED_MEMORY标志)可以在最终返回之前进行检查。

注意 在与远程对等方协商期间,特定上下文属性可能会更改。
 

[out, optional] ptsExpiry

指向接收上下文过期时间的 TimeStamp 结构的指针。 建议 安全包 始终在本地时间返回此值。 此参数是可选的,应为生存期较短的客户端传递 NULL

Microsoft Digest SSP 安全上下文或 凭据没有过期时间。

返回值

如果函数成功,该函数将返回以下成功代码之一。

返回代码 说明
SEC_I_COMPLETE_AND_CONTINUE
客户端必须调用 CompleteAuthToken ,然后将输出传递给服务器。 然后,客户端等待返回的令牌,并在另一次调用中将其传递给 InitializeSecurityContext (General)
SEC_I_COMPLETE_NEEDED
客户端必须完成消息的生成,然后调用 CompleteAuthToken 函数。
SEC_I_CONTINUE_NEEDED
客户端必须将输出令牌发送到服务器并等待返回令牌。 然后,返回的令牌在对 InitializeSecurityContext (General) 的另一次调用中传递。 输出令牌可以为空。
SEC_I_INCOMPLETE_CREDENTIALS
与 Schannel 一起使用。 服务器已请求客户端身份验证,并且提供的凭据不包含证书,或者证书不是由服务器信任的 证书颁发机构 颁发的。 有关详细信息,请参阅“备注”。
SEC_E_INCOMPLETE_MESSAGE
与 Schannel 一起使用。 未从线路中读取整个消息的数据。

返回此值时, pInput 缓冲区包含一个 SecBuffer 结构, 其 BufferType 成员 为 SECBUFFER_MISSINGSecBuffer 的 cbBuffer 成员包含一个值,该值指示函数在此函数成功之前必须从客户端读取的其他字节数。 虽然此数字并非始终准确,但使用它可避免多次调用此函数,从而帮助提高性能。

SEC_E_OK
已成功初始化安全上下文。 无需另一个 InitializeSecurityContext (常规) 调用。 如果函数返回输出标记,即 pOutput 中的SECBUFFER_TOKEN长度为非零,则必须将该令牌发送到服务器。
 

如果函数失败,该函数将返回以下错误代码之一。

返回代码 说明
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
fContextReq 参数中指定了无效 (ISC_REQ_DELEGATE 或ISC_REQ_PROMPT_FOR_CREDS) 的上下文属性标志。
SEC_E_WRONG_PRINCIPAL
接收身份验证请求的主体与传递到 pszTargetName 参数的主体不同。 这表示相互身份验证失败。

注解

调用方负责确定最终的上下文属性是否足够。 例如,如果请求了机密性,但无法建立,则某些应用程序可能会选择立即关闭连接。

如果安全上下文的属性不够,客户端必须通过调用 DeleteSecurityContext 函数释放部分创建的上下文。

客户端使用 InitializeSecurityContext (General) 函数初始化出站上下文。

对于双腿安全上下文,调用顺序如下:

  1. 客户端调用 phContext 设置为 NULL 的函数,并使用输入消息填充缓冲区描述符。
  2. 安全包检查参数并构造一个不透明的令牌,并将其放置在缓冲区数组的 TOKEN 元素中。 如果 fContextReq 参数包含 ISC_REQ_ALLOCATE_MEMORY 标志,则安全包将分配内存并返回 TOKEN 元素中的指针。
  3. 客户端将 pOutput 缓冲区中返回的令牌发送到目标服务器。 然后,服务器在调用 AcceptSecurityContext (General) 函数时将令牌作为输入参数传递。
  4. AcceptSecurityContext (常规) 可能会返回一个令牌,如果第一次调用返回SEC_I_CONTINUE_NEEDED,则服务器会将其发送到客户端,以便对 InitializeSecurityContext 进行第二次调用 (常规) 。
对于多段安全上下文(例如相互身份验证),调用顺序如下:
  1. 客户端如前所述调用函数,但包返回SEC_I_CONTINUE_NEEDED成功代码。
  2. 客户端将输出令牌发送到服务器,并等待服务器的回复。
  3. 收到服务器的响应后,客户端再次调用 InitializeSecurityContext (General) ,并将 phContext 设置为从上次调用返回的句柄。 从服务器接收的令牌在 pInput 参数中提供。
如果服务器已成功响应,则安全包将返回SEC_E_OK并建立安全会话。

如果函数返回错误响应之一,则不接受服务器的响应,并且不会建立会话。

如果函数返回SEC_I_CONTINUE_NEEDED、SEC_I_COMPLETE_NEEDED或SEC_I_COMPLETE_AND_CONTINUE,则重复步骤 2 和 3。

若要初始化 安全上下文,可能需要多次调用此函数,具体取决于基础身份验证机制以及在 fContextReq 参数中指定的选项。

fContextReqpfContextAttributes 参数是表示各种上下文属性的位掩码。 有关各种属性的说明,请参阅 上下文要求pfContextAttributes 参数对任何成功返回都有效,但只有在最终成功返回时,才应检查与上下文安全方面相关的标志。 例如,中间返回可以设置ISC_RET_ALLOCATED_MEMORY标志。

如果设置了ISC_REQ_USE_SUPPLIED_CREDS标志, 则安全包 必须在 pInput 输入缓冲区中查找SECBUFFER_PKG_PARAMS缓冲区类型。 这不是泛型解决方案,但它允许在适当的时候对安全包和应用程序进行强配对。

如果指定了ISC_REQ_ALLOCATE_MEMORY,则调用方必须通过调用 FreeContextBuffer 函数来释放内存。

例如,输入令牌可能是来自 LAN 管理器的质询。 在这种情况下,输出令牌将是对质询的 NTLM 加密响应。

客户端执行的操作取决于此函数的返回代码。 如果返回代码SEC_E_OK,则不会有第二 次 InitializeSecurityContext (常规) 调用,并且服务器不会响应。 如果返回代码SEC_I_CONTINUE_NEEDED,则客户端需要一个令牌来响应服务器,并在第二次调用 InitializeSecurityContext (General) 传递它。 SEC_I_COMPLETE_NEEDED返回代码指示客户端必须完成消息生成并调用 CompleteAuthToken 函数。 SEC_I_COMPLETE_AND_CONTINUE代码合并了这两个操作。

如果 InitializeSecurityContext (常规) 在第一个 (返回成功或仅) 调用,则调用方最终必须在返回的句柄上调用 DeleteSecurityContext 函数,即使调用在身份验证交换的后续部分失败也是如此。

客户端可以在成功完成后再次调用 InitializeSecurityContext (General) 。 这向安全包指示需要重新身份验证。

内核模式调用方具有以下差异:目标名称是必须使用 VirtualAlloc 在虚拟内存中分配的 Unicode 字符串;不得从池中分配它。 在 pInputpOutput 中传递和提供的缓冲区必须位于虚拟内存中,而不是在池中。

使用 Schannel SSP 时,如果函数返回SEC_I_INCOMPLETE_CREDENTIALS,检查在凭据中指定了有效且受信任的证书。 在调用 AcquireCredentialsHandle (General) 函数时指定证书。 证书必须是证书颁发机构颁发的客户端身份验证 证书, ( CA) 服务器信任。 若要获取服务器信任的 CA 的列表,请调用 QueryContextAttributes (General) 函数并指定 SECPKG_ATTR_ISSUER_LIST_EX 属性。

使用 Schannel SSP 时,客户端应用程序从服务器信任的 CA 收到身份验证证书后,应用程序通过调用 AcquireCredentialsHandle (General) 函数,然后再次调用 InitializeSecurityContext (General) ,在 phCredential 参数中指定新凭据来创建新凭据。

注意

sspi.h 标头将 InitializeSecurityContext 定义为别名,该别名根据 UNICODE 预处理器常量的定义自动选择此函数的 ANSI 或 Unicode 版本。 将非特定编码别名的使用与非非特定编码的代码混合使用可能会导致不匹配,从而导致编译或运行时错误。 有关详细信息,请参阅 函数原型的约定

要求

要求
最低受支持的客户端 Windows XP [仅限桌面应用]
最低受支持的服务器 Windows Server 2003 [仅限桌面应用]
目标平台 Windows
标头 sspi.h (包括 Security.h)
Library Secur32.lib
DLL Secur32.dll

另请参阅

AcceptSecurityContext (常规)

AcquireCredentialsHandle (General)

CompleteAuthToken

DeleteSecurityContext

FreeContextBuffer

SSPI 函数

SecBuffer

SecBufferDesc