InitializeSecurityContextW 函数 (sspi.h)
InitializeSecurityContext(常规) 函数从凭据句柄启动客户端、出站 安全上下文。 该函数用于在客户端应用程序和远程对等方之间生成安全上下文。 InitializeSecurityContext(常规) 返回客户端必须传递给远程对等的令牌,而对等方又通过 AcceptSecurityContext(常规) 调用提交到本地安全实现。 所有调用方都应将生成的令牌视为不透明。
通常,InitializeSecurityContext(常规) 函数在建立足够的安全上下文之前在循环中调用。
有关将此函数与特定 安全支持提供程序(SSP)配合使用的信息,请参阅以下主题。
主题 | 描述 |
---|---|
InitializeSecurityContext (CredSSP) | 使用凭据安全支持提供程序(CredSSP)从凭据句柄启动客户端出站安全上下文。 |
InitializeSecurityContext (摘要) | 使用 Digest 安全包从凭据句柄启动客户端出站安全上下文。 |
InitializeSecurityContext (Kerberos) | 使用 Kerberos 安全包从凭据句柄启动客户端出站安全上下文。 |
InitializeSecurityContext (Negotiate) | 使用 Negotiate 安全包从凭据句柄启动客户端出站安全上下文。 |
InitializeSecurityContext (NTLM) | 使用 NTLM 安全包从凭据句柄启动客户端出站安全上下文。 |
InitializeSecurityContext (Schannel) | 使用 Schannel 安全包从凭据句柄启动客户端出站安全上下文。 |
语法
KSECDDDECLSPEC SECURITY_STATUS SEC_ENTRY InitializeSecurityContextW(
[in, optional] PCredHandle phCredential,
[in, optional] PCtxtHandle phContext,
[in, optional] PSECURITY_STRING pTargetName,
[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(常规) 函数至少需要出站凭据。
[in, optional] phContext
指向 CtxtHandle 结构的指针。 在第一次调用 InitializeSecurityContext (常规)时,此指针 NULL。 在第二次调用中,此参数是指向第一次调用 phNewContext 参数中返回的部分格式上下文的句柄的指针。
此参数是可选的Microsoft摘要 SSP,可设置为 NULL。
使用 Schannel SSP 时,在首次调用 InitializeSecurityContext (常规)时,指定 NULL。 在将来的调用中,指定在第一次调用此函数后 phNewContext 参数中收到的令牌。
[in, optional] pTargetName
指向以 null 结尾的字符串的指针,指示上下文的目标。 字符串内容 特定于安全包,如下表所述。 此列表并不详尽。 可以向系统添加其他系统 SSP 和第三方 SSP。
[in] fContextReq
指示上下文请求的位标志。 并非所有包都支持所有要求。 用于此参数的标志以ISC_REQ_为前缀,例如ISC_REQ_DELEGATE。 此参数可以是以下一个或多个属性标志。
价值 | 意义 |
---|---|
|
安全包为你分配输出缓冲区。 使用完输出缓冲区后,通过调用 FreeContextBuffer 函数释放它们。 |
|
使用 EncryptMessage 函数加密消息。 |
|
安全上下文不会处理格式设置消息。 此值是 Kerberos、Negotiate 和 NTLM 安全包的默认值。 |
|
服务器可以使用上下文作为客户端向其他服务器进行身份验证。 必须设置ISC_REQ_MUTUAL_AUTH标志才能运行此标志。 对 Kerberos 有效。 忽略 约束委派的此标志。 |
|
发生错误时,将通知远程方。 |
|
对 HTTP 使用摘要。 省略此标志以使用 Digest 作为 SASL 机制。 |
|
使用 EncryptMessage 和 MakeSignature 函数对消息进行签名和验证签名。 |
|
Schannel 不得自动对服务器进行身份验证。 |
|
将满足服务的相互身份验证策略。
警告 这不一定意味着执行相互身份验证,只表示满足服务的身份验证策略。 若要确保执行相互身份验证,请调用 QueryContextAttributes (常规) 函数。
|
|
如果设置了此标志,则忽略 ISC_REQ_INTEGRITY 标志。
只有 Negotiate 和 Kerberos 安全包才支持此值。 |
|
使用 EncryptMessage 或 MakeSignature 函数检测已编码的重播消息。 |
|
检测按顺序接收的消息。 |
|
支持面向流的连接。 |
|
必须协商新的 会话密钥。
此值仅受 Kerberos 安全包支持。 |
|
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 (常规)时,此指针将接收新的上下文句柄。 第二次调用时,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摘要 SSP 安全上下文或 凭据没有过期时间。
返回值
如果函数成功,该函数将返回以下成功代码之一。
返回代码 | 描述 |
---|---|
|
客户端必须调用 completeAuthToken ,然后将输出传递给服务器。 然后,客户端等待返回的令牌,并在另一个调用中将其传递给 InitializeSecurityContext(常规)。 |
|
客户端必须完成消息生成,然后调用 CompleteAuthToken 函数。 |
|
客户端必须将输出令牌发送到服务器并等待返回令牌。 然后,返回的令牌在另一个调用中传递给 InitializeSecurityContext (常规)。 输出令牌可以为空。 |
|
与 Schannel 一起使用。 服务器已请求客户端身份验证,提供的凭据要么不包括证书,要么证书不是由服务器信任的 证书颁发机构颁发的 颁发的。 有关详细信息,请参阅“备注”。 |
|
与 Schannel 一起使用。 整个消息的数据不是从网络读取的。
返回此值后,pInput 缓冲区包含具有 BufferTypeSECBUFFER_MISSING成员的 SecBuffer 结构。 |
|
已成功初始化 安全上下文。 无需另一 InitializeSecurityContext (常规) 调用。 如果函数返回输出令牌,即,如果 pOutput 中的SECBUFFER_TOKEN长度为非零,则必须将令牌发送到服务器。 |
如果函数失败,该函数将返回以下错误代码之一。
返回代码 | 描述 |
---|---|
|
没有足够的内存可用于完成请求的操作。 |
|
未映射到 SSPI 错误代码的错误。 |
|
传递给函数的句柄无效。 |
|
错误是由于输入令牌格式不正确,例如在传输过程中损坏的令牌、大小不正确的令牌或传递到错误的安全包中的令牌。 如果客户端和服务器未协商正确的安全包,则可能会将令牌传递到错误的包。 |
|
登录失败。 |
|
无法联系任何机构进行身份验证。 身份验证方的域名可能是错误的,域可能无法访问,或者可能存在信任关系失败。 |
|
安全包中没有可用的凭据。 |
|
无法识别目标。 |
|
fContextReq 参数中指定了无效的上下文属性标志(ISC_REQ_DELEGATE或ISC_REQ_PROMPT_FOR_CREDS)。 |
|
接收身份验证请求的主体与传递到 pszTargetName 参数的主体不同。 这表示相互身份验证失败。 |
言论
调用方负责确定最终上下文属性是否足够。 例如,如果请求了机密性,但无法建立,某些应用程序可能会选择立即关闭连接。
如果安全上下文的属性不够,客户端必须通过调用 DeleteSecurityContext 函数释放部分创建的上下文。
客户端使用 InitializeSecurityContext(常规) 函数初始化出站上下文。
对于双腿安全上下文,调用序列如下所示:
- 客户端调用 phContext 设置为 NULL 的函数,并使用输入消息填充缓冲区描述符。
- 安全包检查参数并构造不透明令牌,并将其放置在缓冲区数组中的 TOKEN 元素中。 如果 fContextReq 参数包括ISC_REQ_ALLOCATE_MEMORY标志,则安全包将分配内存并返回 TOKEN 元素中的指针。
- 客户端将 pOutput 缓冲区中返回的令牌发送到目标服务器。 然后,服务器在调用 AcceptSecurityContext(常规) 函数时将令牌作为输入参数传递。
- AcceptSecurityContext(常规) 可能会返回一个令牌,如果第一次调用返回SEC_I_CONTINUE_NEEDED,服务器会向客户端发送第二次调用 InitializeSecurityContext (常规)。
- 客户端如前所述调用函数,但包返回SEC_I_CONTINUE_NEEDED成功代码。
- 客户端将输出令牌发送到服务器,并等待服务器的回复。
- 收到服务器的响应后,客户端再次调用 InitializeSecurityContext (常规),phContext 设置为上次调用返回的句柄。 从服务器收到的令牌在 pInput 参数中提供。
如果函数返回错误响应之一,则不接受服务器的响应,并且未建立会话。
如果函数返回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标志,安全包 必须在 pInput 输入缓冲区中查找SECBUFFER_PKG_PARAMS缓冲区类型。 这不是一般解决方案,但它允许在适当的时候对安全包和应用程序进行强配对。
如果指定了ISC_REQ_ALLOCATE_MEMORY,调用方必须通过调用 FreeContextBuffer 函数释放内存。
例如,输入令牌可能是 LAN 管理器的质询。 在这种情况下,输出令牌将是对质询的 NTLM 加密响应。
客户端执行的操作取决于此函数的返回代码。 如果返回代码SEC_E_OK,则不会 InitializeSecurityContext(常规) 调用,并且不会收到来自服务器的响应。 如果返回代码SEC_I_CONTINUE_NEEDED,客户端需要来自服务器的响应令牌,并在第二次调用中传递给 InitializeSecurityContext (常规)。 SEC_I_COMPLETE_NEEDED返回代码指示客户端必须完成消息生成并调用 CompleteAuthToken 函数。 SEC_I_COMPLETE_AND_CONTINUE代码包含这两个操作。
如果 InitializeSecurityContext(常规) 在第一次(或仅)调用中返回成功,则调用方最终必须在返回的句柄上调用 DeleteSecurityContext 函数,即使调用在身份验证交换的后续部分失败。
客户端可以在成功完成后再次调用 InitializeSecurityContext (常规)。 这向安全包指示需要重新身份验证。
内核模式调用方具有以下差异:目标名称是 Unicode 字符串,必须使用 VirtualAlloc在虚拟内存中分配;不能从池中分配它。 在 pInput 中传递和提供的缓冲区,pOutput 必须位于虚拟内存中,而不是池中。
使用 Schannel SSP 时,如果函数返回SEC_I_INCOMPLETE_CREDENTIALS,请检查是否在凭据中指定了有效且受信任的证书。 调用 AcquireCredentialsHandle(常规) 函数时指定证书。 证书必须是由服务器信任的 证书颁发机构(CA)颁发的客户端身份验证证书。 若要获取服务器信任的 CA 列表,请调用 QueryContextAttributes (常规) 函数并指定SECPKG_ATTR_ISSUER_LIST_EX属性。
使用 Schannel SSP 时,客户端应用程序从受服务器信任的 CA 收到身份验证证书后,应用程序会通过调用 AcquireCredentialsHandle (General) 函数,然后再次调用 InitializeSecurityContext (常规),从而在 phCredential 参数中指定新凭据。
注意
sspi.h 标头将 InitializeSecurityContext 定义为一个别名,该别名根据 UNICODE 预处理器常量的定义自动选择此函数的 ANSI 或 Unicode 版本。 将中性编码别名与不中性编码的代码混合使用可能会导致编译或运行时错误不匹配。 有关详细信息,请参阅函数原型的
要求
要求 | 价值 |
---|---|
最低支持的客户端 | Windows XP [仅限桌面应用] |
支持的最低服务器 | Windows Server 2003 [仅限桌面应用] |
目标平台 | 窗户 |
标头 | sspi.h (包括 Security.h) |
库 | Secur32.lib |
DLL | Secur32.dll |