AcceptSecurityContext (Schannel) 函数

AcceptSecurityContext (Schannel) 函数使传输应用程序的服务器组件能够在服务器和远程客户端之间建立安全上下文。 远程客户端使用 InitializeSecurityContext (Schannel) 函数启动建立 安全上下文的过程。 服务器可能需要远程客户端的一个或多个回复令牌才能完成 安全上下文的建立。

语法

SECURITY_STATUS SEC_Entry AcceptSecurityContext(
  _In_opt_    PCredHandle    phCredential,
  _Inout_opt_ PCtxtHandle    phContext,
  _In_opt_    PSecBufferDesc pInput,
  _In_        ULONG          fContextReq,
  _In_        ULONG          TargetDataRep,
  _Inout_opt_ PCtxtHandle    phNewContext,
  _Inout_opt_ PSecBufferDesc pOutput,
  _Out_       PULONG         pfContextAttr,
  _Out_opt_   PTimeStamp     ptsTimeStamp
);

参数

phCredential[in, optional]

服务器凭据的句柄。 服务器调用 AcquireCredentialsHandle (Schannel) 函数,并将 SECPKG_CRED_INBOUND 或 SECPKG_CRED_BOTH 标志设置为检索此句柄。

phContext[in, out, optional]

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

警告

不要在对 AcceptSecurityContext (Schannel) 进行并发调用时使用相同的上下文句柄。 安全服务提供程序中的 API 实现不是线程安全的。

pInput[in, optional]

指向客户端调用 InitializeSecurityContext 生成的 SecBufferDesc 结构的指针, (包含输入缓冲区描述符的 Schannel) 。

使用 Schannel 安全支持提供程序 (SSP) 时,第一个缓冲区的类型必须为 SECBUFFER_TOKEN,并包含从客户端接收的安全令牌。 第二个缓冲区的类型应为 SECBUFFER_EMPTY。

fContextReq[in]

指定服务器建立上下文所需的属性的位标志。 可以使用按位 OR 操作组合位标志。 此参数可使用以下一个或多个值。

含义
ASC_REQ_ALLOCATE_MEMORY 摘要和 Schannel 将为你分配输出缓冲区。 使用完输出缓冲区后,通过调用 FreeContextBuffer 函数释放它们。
ASC_REQ_CONFIDENTIALITY 加密和解密消息。
摘要 SSP 仅支持 SASL 的此标志。
ASC_REQ_CONNECTION 安全上下文不会处理格式化消息。
ASC_REQ_EXTENDED_ERROR 发生错误时,远程方将收到通知。
ASC_REQ_MUTUAL_AUTH 客户端需要提供用于客户端身份验证的证书。
ASC_REQ_REPLAY_DETECT 检测重播的数据包。
ASC_REQ_SEQUENCE_DETECT 检测不按顺序接收的消息。
ASC_REQ_STREAM 支持面向流的连接。
仅 Schannel 支持此标志。

有关可能的属性标志及其含义,请参阅 上下文要求。 用于此参数的标志以 ASC_REQ 为前缀,例如,ASC_REQ_DELEGATE。

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

TargetDataRep[in]

此参数不与 Schannel 一起使用。 为此参数指定零。

phNewContext[in, out, optional]

指向 CtxtHandle 结构的指针。 在首次调用 AcceptSecurityContext (Schannel) 时,此指针接收新的上下文句柄。 在后续调用中, phNewContext 可以与 phContext 参数中指定的句柄相同。 phNewContext 不应为 NULL

pOutput[in, out, optional]

指向包含输出缓冲区描述符 的 SecBufferDesc 结构的指针。 此缓冲区将发送到客户端,以便输入对 InitializeSecurityContext (Schannel) 的其他调用。 即使函数返回SEC_E_OK,也可能生成输出缓冲区。 生成的任何缓冲区都必须发送回客户端应用程序。

在输出时,此缓冲区接收 安全上下文的令牌。 必须将令牌发送到客户端。 函数还可以返回 SECBUFFER_EXTRA 类型的缓冲区。 此外,调用方必须传入 SECBUFFER_ALERT 类型的缓冲区。 在输出中,如果生成警报,则此缓冲区包含有关该警报的信息,并且函数将失败。

pfContextAttr[out]

指向变量的指针,该变量接收一组指示已建立上下文的属性的位标志。 有关各种属性的说明,请参阅 上下文要求。 用于此参数的标志以 ASC_RET 为前缀,例如,ASC_RET_DELEGATE。

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

ptsTimeStamp[out, optional]

指向接收上下文过期时间的 TimeStamp 结构的指针。 建议 安全包 始终在本地时间返回此值。

使用 Schannel SSP 时,这是可选的。 当远程方提供用于身份验证的证书时,此参数将接收该证书的过期时间。 如果未提供证书,则返回最大时间值。

注意

在最后一次调用身份验证过程之前,上下文的过期时间可能不正确,因为在协商的后续阶段将提供更多信息。 因此, ptsTimeStamp 必须在 NULL 最后一次调用函数之前。

返回值

此函数返回以下值之一。

返回代码/值说明
SEC_E_INCOMPLETE_MESSAGE
0x80090318L
函数成功。 输入缓冲区中的数据不完整。 应用程序必须从客户端读取其他数据,并再次调用 [AcceptSecurityContext (Schannel) ] (acceptsecuritycontext--schannel.md) 。
返回此值时, pInput 缓冲区包含 [SecBuffer] (/windows/win32/api/sspi/ns-sspi-secbuffer) 结构, 其 BufferType 成员为 SECBUFFER_MISSINGSecBuffer 的 cbBuffer 成员包含一个值,该值指示函数在此函数成功之前必须从客户端读取的其他字节数。 虽然此数字并非始终准确,但使用它可避免多次调用此函数,从而帮助提高性能。
SEC_E_INSUFFICIENT_MEMORY
0x80090300L
函数失败。 没有足够的内存可用于完成请求的操作。
SEC_E_INTERNAL_ERROR
0x80090304L
函数失败。 发生了未映射到 SSPI 错误代码的错误。
SEC_E_INVALID_HANDLE
0x80100003L
函数失败。 传递给函数的句柄无效。
SEC_E_INVALID_TOKEN
0x80090308L
函数失败。 传递给函数的令牌无效。
SEC_E_LOGON_DENIED
0x8009030CL
登录失败。
SEC_E_NO_AUTHENTICATING_AUTHORITY
0x80090311L
函数失败。 无法联系任何机构进行身份验证。 这可能是由于以下情况造成的:
  • 身份验证方的域名不正确。
  • 域不可用。
  • 信任关系失败。
SEC_E_NO_CREDENTIALS
0x8009030EL
函数失败。 phCredential 参数中指定的凭据句柄无效。 使用摘要或 Schannel SSP 时,可以返回此值。
SEC_E_OK
0x00000000L
函数成功。 [*security context*] (.已接受从客户端收到的 /secgloss/s-gly.md) 。 如果输出令牌由函数生成,则必须将其发送到客户端进程。
SEC_E_UNSUPPORTED_FUNCTION
0x80090302L
函数失败。 在 fContextReq 参数中指定了无效 (ASC_REQ_DELEGATE或ASC_REQ_PROMPT_FOR_CREDS) 上下文属性标志。
SEC_E_APPLICATION_PROTOCOL_MISMATCH
0x80090367L
客户端和服务器之间不存在通用的应用程序协议。
SEC_I_COMPLETE_AND_CONTINUE
0x00090314L
函数成功。 服务器必须调用 [CompleteAuthToken] (/windows/win32/api/sspi/nf-sspi-completeauthtoken) 并将输出令牌传递给客户端。 然后,服务器等待来自客户端的返回令牌,然后再次调用 [AcceptSecurityContext (Schannel) ] (acceptsecuritycontext--schannel.md) 。
SEC_I_COMPLETE_NEEDED
0x00090313L
函数成功。 服务器必须完成从客户端生成消息,然后调用 [CompleteAuthToken] (/windows/win32/api/sspi/nf-sspi-completeauthtoken) 函数。
SEC_I_CONTINUE_NEEDED
0x00090312L
函数成功。 服务器必须将输出令牌发送到客户端并等待返回的令牌。 返回的令牌应在 pInput 中传递,以便再次调用 [AcceptSecurityContext (Schannel) ] (acceptsecuritycontext--schannel.md) 。
STATUS_LOGON_FAILURE
0xC000006DL
函数失败。 [AcceptSecurityContext (Schannel) ] (acceptsecuritycontext--schannel.md) 函数是在指定上下文建立后调用的。 使用摘要 SSP 时,可以返回此值。

备注

AcceptSecurityContext (Schannel) 函数是 InitializeSecurityContext (Schannel) 函数的服务器对应函数。

当服务器收到来自客户端的请求时,服务器使用 fContextReq 参数指定会话所需的内容。 以这种方式,服务器可以指定客户端必须能够使用机密或 完整性检查会话,并且可以拒绝无法满足该需求的客户端。 或者,服务器不需要任何内容,客户端可以提供或要求的任何内容都会在 pfContextAttr 参数中返回。

对于支持多段身份验证(例如相互身份验证)的包,调用顺序如下所示:

  1. 客户端将令牌传输到服务器。
  2. 服务器在首次 ) 调用 AcceptSecurityContext (Schannel ,这会生成回复令牌,然后将其发送到客户端。
  3. 客户端接收令牌并将其传递给 InitializeSecurityContext (Schannel) 。 如果 InitializeSecurityContext (Schannel) 返回SEC_E_OK,则相互身份验证已完成,安全会话可以开始。 如果 InitializeSecurityContext (Schannel) 返回错误代码,则相互身份验证协商结束。 否则, 由 InitializeSecurityContext (Schannel) 返回的安全令牌将发送到客户端,并重复步骤 2 和 3。
  4. 不要在对 AcceptSecurityContext 的并发调用中使用 phContext, (Schannel) 。 安全提供程序中的实现不是线程安全的。

fContextReqpfContextAttr 参数是表示各种上下文属性的位掩码。 有关各种属性的说明,请参阅 上下文要求

注意

pfContextAttr 参数在任何成功返回时都有效,但只有在最终成功返回时,才应检查与上下文安全方面相关的标志。 例如,中间返回可以设置ISC_RET_ALLOCATED_MEMORY标志。

调用方负责确定最终上下文属性是否足够。 例如,如果请求了加密 (加密) ,但无法建立,则某些应用程序可能会选择立即关闭连接。 如果无法建立 安全上下文 ,服务器必须通过调用 DeleteSecurityContext 函数释放部分创建的上下文。 有关何时调用 DeleteSecurityContext 函数的信息,请参阅 DeleteSecurityContext

建立 安全上下文 后,服务器应用程序可以使用 QuerySecurityContextToken 函数检索客户端证书映射到的用户帐户的句柄。 此外,服务器可以使用 ImpersonateSecurityContext 函数来模拟用户。

要求

要求
最低受支持的客户端 Windows 8.1 [仅限桌面应用]
最低受支持的服务器 Windows Server 2012 R2 [仅限桌面应用]
标头 Sspi.h (包括 Security.h)
Secur32.lib
DLL Secur32.dll

另请参阅

SSPI 函数

DeleteSecurityContext

InitializeSecurityContext (Schannel)