如何验证域凭据(从本机代码)? [英] How to validate domain credentials (from native code)?
问题描述
我想针对域控制器验证一组凭据.例如:
i want to validate a set of credentials against the domain controller. e.g.:
Username: joel
Password: splotchy
Domain: STACKOVERFLOW
在.NET 3.5和更高版本的中,您可以使用PrincipalContext.ValidateCredentials(username, password)
.
In .NET 3.5 and newer you can use PrincipalContext.ValidateCredentials(username, password)
.
否则,您会遇到麻烦.
按照Microsoft知识库文章>如何在Microsoft操作系统上验证用户凭据的代码进行操作,到了您所说的
Following the code in the Microsoft Knowledge Base article How to validate user credentials on Microsoft operating systems, i get to the point where you call AcceptSecurityContext
:
ss = AcceptSecurityContext(
@pAS._hcred, //[in]CredHandle structure
phContext, //[in,out]CtxtHandle structure
@InBuffDesc, //[in]SecBufferDesc structure
0, //[in]context requirement flags
SECURITY_NATIVE_DREP, //[in]target data representation
@pAS._hctxt, //[in,out]CtxtHandle strcture
@OutBuffDesc, //[in,out]SecBufferDesc structure
ContextAttributes, //[out]Context attribute flags
@Lifetime); //[out]Timestamp struture
该函数失败的原因是:
SEC_E_NO_AUTHENTICATING_AUTHORITY
(0x80090311)
SEC_E_NO_AUTHENTICATING_AUTHORITY
(0x80090311)
该功能失败.无法联系任何授权进行身份验证.这可能是由于以下情况造成的:
The function failed. No authority could be contacted for authentication. This could be due to the following conditions:
- 认证方的域名不正确.
- 该域不可用.
- 信任关系失败.
- The domain name of the authenticating party is incorrect.
- The domain is unavailable.
- The trust relationship has failed.
这将是一个有用的错误,除了我可以使用以下方法从.NET 3.5验证相同的凭据:
This would be a useful error, except that i can validate the same credentials from .NET 3.5 using:
using (PrincipalContext context = new PrincipalContext(ContextType.Domain, domain))
{
valid = context.ValidateCredentials(username, password);
}
会发生什么事情,允许.NET验证一组凭据,而本机代码无法验证?
What could be happening that allows .NET to validate a set of credentials, while native code cannot?
更新:LogonUser
也失败:
LogonUser("joel@stackoverflow.com", null, "splotchy",
LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_WINNT50, out token);
与
1311 - There are currently no logon servers available to service the logon request
更新两次:我已经尝试了首选的Negotiate
提供程序以及Windows NT4旧版"NTLM"提供程序
Update Two: i've tried both the preferred Negotiate
provider, as well as the Windows NT4 legacy "NTLM" provider
String package = "Negotiate"; //"NTLM"
QuerySecurityPackageInfo(package, [out] packageInfo);
...
AcquireCredentialsHandle(
null, //[in] principle
package, //[in] package
SECPKG_CRED_OUTBOUND, //[in] credential use
null, //[in] LogonID
pAuthIdentity, //[in] authData
null, //[in] GetKeyFn, not used and should be null
null, //[in] GetKeyArgument, not used and should be null
credHandle, //[out] CredHandle structure
expires); //[out] expiration TimeStamp structure
推荐答案
I presume that this is to solve the same problem as another question that you posted.
我有点理解您现在想做什么.让我回顾一下您在另一篇文章中写的内容.
I kind of understand what you are trying to do now. Let me recap what you wrote on another post.
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
您要
- 从您的计算机不信任的域中对用户进行身份验证
- 从您的计算机信任的域中对用户进行身份验证
- 验证本地用户
通过与域控制器进行适当的SSPI握手,可以实现前两种情况.您在另一个问题中引用的知识库文章正在做环回SSPI握手.在第一种情况下,它将无法正常工作,因为客户端计算机不信任您要验证的域.这就是为什么您看到SEC_E_NO_AUTHENTICATING_AUTHORITY
.
You can achieve the first two cases by doing proper SSPI handshaking with the domain controller. The KB article that you are referring to in another question is doing loop back SSPI handshaking. It's not going to work in case number one because the client machine does not trust the domain that you are authenticating to. That should be why you are seeing SEC_E_NO_AUTHENTICATING_AUTHORITY
.
简而言之,如果您想做与
To cut it short, if you want to do exactly the same thing as
PrincipalContext.ValidateCredentials(username, password);
您需要以与域用户不同的方式处理本地用户.对于域用户,您需要调用
you need to handle the local user differently from the domain user. For domain user, you need to call ldap_bind_s to bind to the domain controller using the given credentials. For local user, you need to use ADsOpenObject to bind to the WinnT://YourComputerName using the given credentials. This is what PrincipalContext.ValidateCredentials
doing from what I read in the Reflector.
我看不到有任何等效的单一本机API为您做同样的事情.
I don't see there is any equivalent one single native API doing the same thing for you.
这篇关于如何验证域凭据(从本机代码)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!