如何验证域凭据(从本机代码)? [英] How to validate domain credentials (from native code)?

查看:494
本文介绍了如何验证域凭据(从本机代码)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想针对域控制器验证一组凭据.例如:

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

您要

  1. 从您的计算机不信任的域中对用户进行身份验证
  2. 从您的计算机信任的域中对用户进行身份验证
  3. 验证本地用户

通过与域控制器进行适当的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆