调用 InitializeSecurityContext (Negotiate) 时使用什么 TargetName? [英] What TargetName to use when calling InitializeSecurityContext (Negotiate)?
问题描述
问题
当调用 .尝试登录几乎肯定会失败.但是 Windows 如何检查它们?
Windows 如何尝试验证这些凭据?Windows 如何验证凭据:
- 用户名:ian
- 密码:pass1
- 领域:涡轮增压器
Windows是否使用安全支持包接口?假设 windows 使用 Negotiate 或 Kerberos 进行身份验证,Windows 作为pszTarget
参数?几乎可以肯定,我输入的凭据将无效.Windows 如何确定它们是否有效?Windows 将调用什么 API 来验证凭据?
Windows 能够验证凭据.我还想验证凭据.
也许不是尝试连接到 TURBOENCABULATOR
域,我尝试通过将域添加到我的用户名作为 turboencabulator 来连接到
:turboencabulator.com
域.comian
同样的问题适用.Windows 如何验证凭据?我想做 Windows 所做的.假设 Windows 使用 kerberos 进行授权,Windows 将什么作为 SSPI 中的 pszTargetName
参数传递?
也许不是尝试连接到 turboencabulator.com
域,而是尝试连接到 turboencabulator.net
域:
请注意,在此示例中,我将域名附加到我的用户名,而不是附加.
也许不是尝试连接到 turboencabulator.net
域,我尝试通过在我的用户名前面加上 .
前缀来验证用户是本地(机器)帐户如:
Windows 如何根据本地帐户数据库验证用户名和密码?它是否将 SSPI 与 Negotiate 包一起使用?如果是这样,它作为 pszTargetName
传递什么值?
人们在谈论 Web 服务器、http、团队基础服务器.我真的不知道他们从哪里得到的.或者他们谈论在活动目录中编辑用户以确保存在某些内容 - 我不明白为什么我需要编辑任何内容:Windows 不编辑任何内容.
在调用 InitializeSecurityContext
以验证一组凭据时,我使用什么 TargetName
?
奖金聊天
这是应用程序验证程序文档中的一章,内容是如果有人错误地使用 NTLM,他们为什么要进行测试:
<块引用>为什么需要 NTLM 插件
NTLM 是一种过时的身份验证协议,存在以下缺陷:可能危及应用程序和操作的安全性系统.最大的缺点就是缺少服务器身份验证,这可能允许攻击者诱骗用户进入连接到欺骗服务器.作为缺少服务器的必然结果身份验证,使用 NTLM 的应用程序也容易受到攻击一种称为反射"攻击的攻击类型.后者允许攻击者将用户的身份验证对话劫持到合法服务器并使用它来验证攻击者的身份用户的电脑.NTLM 的漏洞和利用它们的方法是增加安全研究活动的目标社区.p>
虽然 Kerberos 已经可用很多年了仍然编写为仅使用 NTLM.这不必要地减少了应用程序的安全性.然而,Kerberos 不能完全取代 NTLM场景——主要是客户端需要验证的场景未加入域的系统(可能是家庭网络其中最常见的).协商安全包允许向后兼容的妥协,尽可能使用 Kerberos并且只有在没有其他选择时才恢复为 NTLM.切换码使用 Negotiate 而不是 NTLM 会显着增加在引入很少或不引入应用程序的同时为我们的客户提供安全性兼容性.谈判本身不是灵丹妙药——有是攻击者可以强制降级到 NTLM 的情况,但这些是明显更难以利用.然而,一个立即改进之处在于为正确使用 Negotiate 而编写的应用程序自动免疫 NTLM 反射攻击.
最后警告不要使用 NTLM:在未来版本的 Windows 将可以在以下位置禁用 NTLM操作系统.如果应用程序对 NTLM 有严格的依赖当 NTLM 被禁用时,他们将无法进行身份验证.
插件的工作原理
Verifier 插件检测到以下错误:
NTLM 包在对 AcquireCredentialsHandle(或更高级别的包装器 API)的调用中直接指定.
InitializeSecurityContext 调用中的目标名称为 NULL.
InitializeSecurityContext 调用中的目标名称不是格式正确的 SPN、UPN 或 NetBIOS 样式的域名.
后两种情况将强制 Negotiate 直接(第一种情况)或间接回退到 NTLM(域控制器将在第二种情况下返回找不到主体"错误,导致 Negotiate 回退).
>插件在检测到降级到 NTLM 时也会记录警告;例如,当域控制器未找到 SPN 时.这些仅记录为警告,因为它们通常是合法的情况 - 例如,在对未加入域的系统进行身份验证时.
NTLM 停止
5000 – 应用程序明确选择了 NTLM 包
严重性 - 错误
应用程序或子系统在对 AcquireCredentialsHandle 的调用中显式选择 NTLM 而不是 Negotiate.尽管客户端和服务器可以使用 Kerberos 进行身份验证,但显式选择 NTLM 可以防止这种情况发生.
如何修复这个错误
此错误的修复方法是选择协商包来代替 NTLM.如何做到这一点取决于客户端或服务器使用的特定网络子系统.下面给出了一些例子.您应该查阅有关您正在使用的特定库或 API 集的文档.
APIs(parameter) 被应用程序使用 错误值 正确值============================================================================AcquireCredentialsHandle (pszPackage) NTLM" NEGOSSP_NAME 协商"
另见
这是了解 TargetName 对 Kerberos 意味着什么很重要的地方:
- 我想向
steve@stackoverflow.local
证明我的身份 - 域控制器递给我一个加密的 blob 来证明我的身份
- blob 被加密,所以
steve@stackoverflow.local
是唯一能够解密它的人 - 域控制器知道为
steve@stackoverflow.local
加密它,因为我在 TargetName 中指定了steve@stackoverflow.local
莉> - 史蒂夫是目标
史蒂夫就是这样知道这个 blob 是有效的,它是加密的,所以只有他才能解密.
我必须告诉 Kerberos 谁我会将加密的 blob 提供给谁,以便域控制器知道为谁加密.
因此在上面的可能名称列表中,三个值起作用:
InitializeSecurityContext(credHandle, context, steve@stackoverflow.local", ...);InitializeSecurityContext(credHandle, context, stackoverflow.localsteve", ...);InitializeSecurityContext(credHandle, context, steve", ...);//如果我们在同一个森林里
所以你可以看到为什么我之前尝试调用 InitializeSecurityContext 都失败了:
InitializeSecurityContextA(credHandle, context, null, ...);InitializeSecurityContextA(credHandle, context, "", ...);InitializeSecurityContextA(credHandle, context, spn/HOSTNAME", ...);InitializeSecurityContextA(credHandle, context, spn/HOSTNAME.DOMAIN.COM", ...);InitializeSecurityContextA(credHandle, context, cargocult/PROGRAMMING", ...);InitializeSecurityContextA(credHandle, context, http/TFS.DOMAIN.COM", ...);InitializeSecurityContextA(credHandle, context, http/HOSTNAME", ...);InitializeSecurityContextA(credHandle, context, qwertyasdf", ...);InitializeSecurityContextA(credHandle, context, AuthSamp", ...);
因为我没有指定 Steve 作为 TargetName;我在指定一些毫无意义的东西:
spn/HOSTNAME
公平地说,
因此,使用 SSPI,您可以来回进行这种乒乓操作,直到您被告知停止为止.因此,他们能够将每个身份验证方案硬塞进那种乒乓直到被告知停止的高级抽象.
如何传输 blob?
您可以通过您使用的任何通信渠道传输 blob.
如果您通过 TCP/IP 与远程服务器通信,那么您可能会使用它:
//打开与服务器的连接sockConnect(162.210.196.166, 1433);斑点 = 空;Boolean bContinue = InitializeSecurityContext(ref blob);同时(b继续){袜子写(斑点);//将blob发送到服务器blob = sockRead();//等待服务器返回一个blobbContinue = InitializeSecurityContext(ref blob);}
如果您通过 http 进行操作:
blob = null;Boolean bContinue = InitializeSecurityContext(ref blob);同时(b继续){http = new HttpRequest("http://4chan.org/default.aspx");http.AddHeader(X-SSPI-Blob", blob.ToBase64());http.Send();blob = http.ReasponseHeader[X-SSPI-Blob"];如果 (blob.IsEmpty())休息;bContinue = InitializeSecurityContext(ref blob);}
SSPI API 不关心您来回传输 blob - 只是您必须来回传输它.
- 使用连接到 SQL Server,SQL 客户端驱动程序通过数据库连接进行传输
- 使用 http,浏览器在请求和响应头中发送 blob
如果您愿意,您甚至可以使用运营商 pidgeon、Skype 或电子邮件.
The Question
When calling
InitializeSecurityContext
, what value do i pass to theTargetName
parameter?Revised Background
I'm calling the function
InitializeSecurityContext
:InitializeSecurityContextA( @pAS.hcred, //[in] credentials phContext, //[in] optional] Context handle structure pszTargetName, //[in, optional] Target name 0, //[in] context requirements 0, //[in] reserved1, must be zero SECURITY_NATIVE_DREP, //[in] target data representation pInput, //[in] optional] SecBufferDescription 0, //[in] reserved2, must be zero @pAS.hctxt, //[in, out] pointer to context handle structure @OutBuffDesc, //[in, out] pointer to SecBufferDesc ContextAttributes, //[out] context attributes @lifetime); //[out] expiration timestamp
What do i pass to
pszTargetName
?I've tried
null
:InitializeSecurityContextA(@pAS.hcred, phContext, null, ...);
""
:InitializeSecurityContextA(@pAS.hcred, phContext, "", ...);
"spn/HOSTNAME"
:InitializeSecurityContextA(@pAS.hcred, phContext, "spn/HOSTNAME", ...);
spn/HOSTNAME.DOMAIN.COM
:InitializeSecurityContextA(@pAS.hcred, phContext, "spn/HOSTNAME.DOMAIN.COM", ...);
"cargocult/PROGRAMMING"
:InitializeSecurityContextA(@pAS.hcred, phContext, "cargocult/PROGRAMMING", ...);
"http/TFS.DOMAIN.COM"
:InitializeSecurityContextA(@pAS.hcred, phContext, "http/TFS.DOMAIN.COM", ...);
"http/HOSTNAME"
:InitializeSecurityContextA(@pAS.hcred, phContext, "http/HOSTNAME", ...);
"qwertyasdf"
:InitializeSecurityContextA(@pAS.hcred, phContext, "qwertyasdf", ...);
"AuthSamp"
:InitializeSecurityContextA(@pAS.hcred, phContext, "AuthSamp", ...);
They all either fail, or downgrade to NTLM.
Note: My machine is domain joined, but the domain is not named
domain.com
, or evenhostname.domain.com
, or evenqwertyasdf
. So i'm not surprised that those attempts fail. But people said try things likehttp/HOSTNAME
, so i put inhttp/HOSTNAME
.Background
The
InitializeSecurityContext
(Negotiate) function has an optionalTargetName
parameter:pszTargetName [in, optional]
A pointer to a null-terminated string that indicates the service principal name (SPN) or the security context of the destination server.
Applications must supply a valid SPN to help mitigate replay attacks.What is this supposed to be?
More Background
i am trying to validate a set of user's credentials, e.g.:
Boolean ValidateCredentials(String username, String password, String domain) { ... }
Validating a set of user's credentials requires using the SSPI API. The first function to call is
InitializeSecurityContext
. One of the parameters toInitializeSecurityContext
is a "TargetName" string.i've tried leaving it null, but the Application Verifier triggers a breakpoint, writing out the error:
VERIFIER STOP 00005003: pid 0xF08:
InitializeSecurityContext uses NULL target or malformed target for Kerberos service.
Please see pszTargetName for the value of the target.
00000000 : Not used.
00000000 : NotAt this point it would be helpful to remember that the
Negotiate
provider will attempt to useKerberos
, but fallback toNTLM
. In the case ofNegotiate
,Kerberos
orNTLM
, theTargetName
parameter is documented to be:Service principal name (SPN) or the security context of the destination server.
But then what should i pass?
i tried doing what the SSPI Knowledge Base article does, nothing (i.e. pass
NULL
):How to validate user credentials on Microsoft operating systems
ss = _InitializeSecurityContext( &pAS->hcred, pAS->fInitialized ? &pAS->hctxt : NULL, NULL, //<-------pszTargetName 0, 0, SECURITY_NATIVE_DREP, pAS->fInitialized ? &sbdIn : NULL, 0, &pAS->hctxt, &sbdOut, &fContextAttr, &tsExpiry);
But nothing (i.e.
NULL
) doesn't work.Note: The KB article was massivly rewritten in 2007. In its original 1999 incarnation they passed
"AuthSamp"
as the target, but that also fails.service principal name
(SPN) The name by which a client uniquely identifies an instance of a service. If you install multiple instances of a service on computers throughout a forest, each instance must have its own SPN. A given service instance can have multiple SPNs if there are multiple names that clients might use for authenticationsecurity context
The security attributes or rules that are currently in effect. For example, the current user logged on to the computer or the personal identification number entered by the smart card user. For SSPI, a security context is an opaque data structure that contains security data relevant to a connection, such as a session key or an indication of the duration of the session.Bonus Chatter 2
From the application verifier documentation:
The Verifier plug detects the following errors:
The NTLM package is directly specified in the call to AcquireCredentialsHandle (or higher level wrapper API).
The target name in the call to InitializeSecurityContext is NULL.
The target name in the call to InitializeSecurityContext is not a properly-formed SPN, UPN or NetBIOS-style domain name.
The latter two cases will force Negotiate to fall back to NTLM either directly (the first case) or indirectly (the domain controller will return a "principal not found" error in the second case causing Negotiate to fall back).
The plug-in also logs warnings when it detects downgrades to NTLM; for example, when an SPN is not found by the Domain Controller. These are only logged as warnings since they are often legitimate cases – for example, when authenticating to a system that is not domain-joined.
In my case the domain i am validating against is
null
(since i don't know the machine's domain name, or even if there is a domain). But the results are the same if the hard-code my development machine's domain name.Update 3
Values of pszTargetName that trigger AppVerifier error, but logon succeeds:
null
""
"AuthSamp"
"qwertyasdf"
- *the name of the domain i'm validating against (e.g.
"avatopia.com"
) - *the name of the domain the machine is joined to (e.g.
"avatopia.com"
) - *the name of the domain the user account is located in (e.g.
"avatopia.com"
)
Values of pszTargetName that do not trigger an AppVerifier error, but logon fails:
"http/HOSTNAME"
"http/TFS.DOMAIN.COM"
"frob/GROBBER"
"cargocult/PROGRAMMING"
"spn/HOSTNAME"
"spn/HOSTNAME.DOMAIN.COM"
Values of pszTargetname that do not trigger an AppVerifier error, and logon succeeds:
- none
Update 4
What i'm trying to do: figure out if a username/password is valid.
- i have a username: e.g.
"ian"
- i have a password: e.g.
"pass1"
Now there's the further wrinkle that the account
ian
could be a local account or a domain account. And you need to decide ifian
is a local or domain account before you can ask. This is becauseian
can have two accounts:ian
on domainstackoverflow.com
ian
on local machine
So i need to specify if i want to:
- ask a particular domain (e.g.
stackoverflow.com
), or - ask the local machine (which i'll represent as
"."
)
Now we can come up with a cross reference:
Username Password Domain Machine on domain? Validate as ======== ======== ================= ================== ============== iboyd pass1 . No Local account iboyd pass1 (empty) No Local account iboyd pass1 stackoverflow.com No Domain account iboyd pass1 . Yes Local account iboyd pass1 (empty) Yes Domain account iboyd pass1 stackoverflow.com Yes Domain account
Update 5
It might help to explain what i'm trying to do, then maybe how to do it will become easier. Lets say i walk into a random office building downtown, walk into a random cubicle, and type in a random username and password:
i'm going to try to login to the domain
TURBOENCABULATOR
. i specified i want to try to authenticate against theTURBOENCABULATOR
domain by prefixing my username as:TURBOENCABULATORian
Note: i highly doubt the network has a domain called turboencabulator, since the name itself only comes from Rockwell automation. The attempt to login will almost certainly fail. But how does Windows check them?
How does Windows attempt to validate these credentials? How does Windows validate the credentials:
- Username: ian
- Password: pass1
- Domain: TURBOENCABULATOR
Does Windows use the Security Support Package Interface? Assuming windows uses Negotiate or Kerberos for authentication, what does Windows pass as the
pszTarget
parameter? Almost certainly the credentials i enter will not be valid. How will Windows determine if they are valid? What API will Windows call to validate the credentails?Windows is able to validate credentails. I want to also validate credentials.
Perhaps instead of trying to connect to the
TURBOENCABULATOR
domain, i try to connect to theturboencabulator.com
domain by prepending the domain to my username asturboencabulator.comian
:Same question applies. How does Windows validate credentials? i want to do what Windows does. Assuming Windows uses kerberos for authorization, what does Windows pass as the
pszTargetName
parameter in SSPI?Perhaps instead of trying to connect to the
turboencabulator.com
domain, i try to connect to theturboencabulator.net
domain:Note that in this example i've appended the domain name to my username, rather than prepending it.
Perhaps instead of trying to connect to the
turboencabulator.net
domain, i try to validate the user as a local (machine) account by prefixing my username with.
as:How does Windows validate the username and password against the local account database? Does it use SSPI with Negotiate package? If so what value does it pass as the
pszTargetName
?People are talking about web servers, http, team foundation server. i really don't know where they're getting that from. Or they talk about editing a user in active directory to ensure something is present - i don't see why i need to edit anything: Windows doesn't edit anything.
What
TargetName
do i used when callingInitializeSecurityContext
in order to validate a set of credentials?Bonus Chatter
Here's a chapter from the Application Verifier documentation about why they have a test if someone is mistakenly using NTLM:
Why the NTLM Plug-in is Needed
NTLM is an outdated authentication protocol with flaws that potentially compromise the security of applications and the operating system. The most important shortcoming is the lack of server authentication, which could allow an attacker to trick users into connecting to a spoofed server. As a corollary of missing server authentication, applications using NTLM can also be vulnerable to a type of attack known as a "reflection" attack. This latter allows an attacker to hijack a user’s authentication conversation to a legitimate server and use it to authenticate the attacker to the user’s computer. NTLM’s vulnerabilities and ways of exploiting them are the target of increasing research activity in the security community.
Although Kerberos has been available for many years many applications are still written to use NTLM only. This needlessly reduces the security of applications. Kerberos cannot however replace NTLM in all scenarios – principally those where a client needs to authenticate to systems that are not joined to a domain (a home network perhaps being the most common of these). The Negotiate security package allows a backwards-compatible compromise that uses Kerberos whenever possible and only reverts to NTLM when there is no other option. Switching code to use Negotiate instead of NTLM will significantly increase the security for our customers while introducing few or no application compatibilities. Negotiate by itself is not a silver bullet – there are cases where an attacker can force downgrade to NTLM but these are significantly more difficult to exploit. However, one immediate improvement is that applications written to use Negotiate correctly are automatically immune to NTLM reflection attacks.
By way of a final word of caution against use of NTLM: in future versions of Windows it will be possible to disable the use of NTLM at the operating system. If applications have a hard dependency on NTLM they will simply fail to authenticate when NTLM is disabled.
How the Plug-in Works
The Verifier plug detects the following errors:
The NTLM package is directly specified in the call to AcquireCredentialsHandle (or higher level wrapper API).
The target name in the call to InitializeSecurityContext is NULL.
The target name in the call to InitializeSecurityContext is not a properly-formed SPN, UPN or NetBIOS-style domain name.
The latter two cases will force Negotiate to fall back to NTLM either directly (the first case) or indirectly (the domain controller will return a "principal not found" error in the second case causing Negotiate to fall back).
The plug-in also logs warnings when it detects downgrades to NTLM; for example, when an SPN is not found by the Domain Controller. These are only logged as warnings since they are often legitimate cases – for example, when authenticating to a system that is not domain-joined.
NTLM Stops
5000 – Application Has Explicitly Selected NTLM Package
Severity – Error
The application or subsystem explicitly selects NTLM instead of Negotiate in the call to AcquireCredentialsHandle. Even though it may be possible for the client and server to authenticate using Kerberos this is prevented by the explicit selection of NTLM.
How to Fix this Error
The fix for this error is to select the Negotiate package in place of NTLM. How this is done will depend on the particular Network subsystem being used by the client or server. Some examples are given below. You should consult the documentation on the particular library or API set that you are using.
APIs(parameter) Used by Application Incorrect Value Correct Value ===================================== =============== ======================== AcquireCredentialsHandle (pszPackage) "NTLM" NEGOSSP_NAME "Negotiate"
See also
解决方案Short Answer
The TargetName is the username that the "server" code will be running as.
- I'm logged in as
ian@stackoverflow.com
- I want to prove my identity to
steve@stackoverflow.com
- Set TargetName to
steve@stackoverflow.com
Background
The
Negotiate
authentication package will attempt to useKerberos
. If it cannot, it will attempt to fallback toNTLM
.- You don't want to use NTLM; it is old, deprecated, weak, broken, and should not be used.
- You want to use
Kerberos
. - In order to use
Kerberos
you must supply a TargetName - Without a TargetName,
Kerberos
is fundamentally unable the function
The question becomes, given all the parties involved:
- me (Ian)
- authenticating with Steve
what TargetName do i specify?
This is where it's important to know what TargetName means to Kerberos:
- i want to prove my identity to
steve@stackoverflow.local
- the domain controller hands me an encrypted blob that proves my identity
- the blob is encrytped so
steve@stackoverflow.local
is the only one able to decrypt it - the domain controller knows to encrypt it for
steve@stackoverflow.local
because i specifiedsteve@stackoverflow.local
in the TargetName - Steve is the target
That's how Steve knows the blob is valid, it was encrypted so only he can decrypt it.
I have to tell Kerberos who i will be giving the encrypted blob to, so the domain controller knows who to encrypt it for.
So in the above list of possible names, three values work:
InitializeSecurityContext(credHandle, context, "steve@stackoverflow.local", ...); InitializeSecurityContext(credHandle, context, "stackoverflow.localsteve", ...); InitializeSecurityContext(credHandle, context, "steve", ...); //if we're in the same forest
So you can see why my earlier attempts to call InitializeSecurityContext all failed:
InitializeSecurityContextA(credHandle, context, null, ...); InitializeSecurityContextA(credHandle, context, "", ...); InitializeSecurityContextA(credHandle, context, "spn/HOSTNAME", ...); InitializeSecurityContextA(credHandle, context, "spn/HOSTNAME.DOMAIN.COM", ...); InitializeSecurityContextA(credHandle, context, "cargocult/PROGRAMMING", ...); InitializeSecurityContextA(credHandle, context, "http/TFS.DOMAIN.COM", ...); InitializeSecurityContextA(credHandle, context, "http/HOSTNAME", ...); InitializeSecurityContextA(credHandle, context, "qwertyasdf", ...); InitializeSecurityContextA(credHandle, context, "AuthSamp", ...);
Because i wasn't specifying Steve as the TargetName; i was specifying something non-sensical:
spn/HOSTNAME
In fairness, people did keep telling me to pass
"spn/HOSTNAME"
.Extra confusion because flexibility (welcome to SPN)
SPNs Short version
- when using Kerberos you must specify a username as your TargetName
- an SPN is an "alias" for a username
- therefore you can specify an SPN as your TargetName
SPNs Long Version
In the case above i had to know that the "server" code will be running as
steve@stackoverflow.local
.That's a pain. I mean it's fine when i know it's steve. But if i'm talking to a remote machine, i have to find out the user account that the code is running as?
- i have to figure out that IIS is running as
iisagent@stackoverflow.local
? - i have to figure out that SQL Server is running as
sqldaemon@stackoverflow.local
? - and what if the service is running as Local Service; that isn't a domain user at all?
Fortunately(?), Kerberos created aliases (called Service Principle Names - or SPNs):
- if i need to authenticate to the web server
http://bugtracker.stackoverflow.local
- and IIS service is running under the domain account
iisagent@stackoverflow.local
- rather than have to specify the targetname of
iisagent@stackoverflow.local
- i can specify
HTTP/bugtracker.stackoverflow.local
- that's because IIS registered an alias with the domain controller
HTTP/bugtracker.stackoverflow.local
→iisagent@stackoverflow.local
All this requires that you know the SPN if you wish to use it as a TargetName. Various standard Microsoft products register SPNs when they install:
- IIS:
HTTP/[servername]
- SQL Server:
MSSQLSvc/[servername]:1433
- SMTP:
SMTPSVC/[servername]
- File sharing:
HOST/[servername]
These are all undocumented, and make your life hell when one isn't configured correctly.
But by no means do you have to supply a SPN. An SPN is simply an alias designed to make your life
easiermore difficult.It's roughly equivalent to attempting to specify "stackoverflow.com", rather than simply using "35.186.238.101".
Bonus Chatter - How does SSPI work?
SSPI was designed as a generic wrapper around different security algorithms. The way to use the API is pretty simple:
- Client: calls
InitializeSecurityContext
and is given a blob - client sends that blob to the server
- Server: calls
AcceptSecurityContext(blob)
, and is given a blob back - server sends that blob back to the client
- Client: calls
InitializeSecurityContext(blob)
, and is given back a blob - client sends that blob back to the server
- Server: calls
AcceptSecurityContext(blob)
, and is given a blob back - ...keep repeating until told to stop...
Both sides keep going back and forth until the function stops returning a blob that needs to be sent to the other side:
And so the with SSPI you do this ping-ponging back and forth until you're told to stop. And so they were able to shoe-horn every authentication scheme into that ping-pong-until-told-to-stop high level abstraction.
How do I transmit the blobs?
You transmit the blobs over whatever communication channel you're using.
If you're talking to a remote server over TCP/IP, then you'd probably use that:
// Open connection to server sockConnect(162.210.196.166, 1433); blob = null; Boolean bContinue = InitializeSecurityContext(ref blob); while (bContinue) { sockWrite(blob); //send the blob to the server blob = sockRead(); //wait for the server to return a blob bContinue = InitializeSecurityContext(ref blob); }
If you're doing it over http:
blob = null; Boolean bContinue = InitializeSecurityContext(ref blob); while (bContinue) { http = new HttpRequest("http://4chan.org/default.aspx"); http.AddHeader("X-SSPI-Blob", blob.ToBase64()); http.Send(); blob = http.ReasponseHeader["X-SSPI-Blob"]; if (blob.IsEmpty()) break; bContinue = InitializeSecurityContext(ref blob); }
The SSPI API doesn't care you to get the blob transmitted back and forth - just that you have to transmit it back and forth.
- using connecting to SQL Server, SQL client driver does the transmitting over the database connection
- using http, the browser sends the blobs in request and response header
You can even use a carrier pidgeon, Skype, or E-mail if you like.
这篇关于调用 InitializeSecurityContext (Negotiate) 时使用什么 TargetName?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- 我想向