简体   繁体   English

PrincipalContext LDAPS自签名证书

[英]PrincipalContext LDAPS Self-Signed Certificate

We have an application that authenticates against a remote AD using LDAP, by IP address, over a VPN tunnel, using the following code: 我们有一个应用程序,使用LDAP,IP地址,通过VPN隧道,使用以下代码对远程AD进行身份验证:

using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, ldap.Host, ldap.Path.Replace("/", ""), ContextOptions.Negotiate, UserName, Password))
{
    using (UserPrincipal user = UserPrincipal.FindByIdentity(pc, domainAndUsername))
    {
        if (user != null)
        {
            SAMAccountName = user.SamAccountName;
            retVal = true;
        }
    }
}

This works great for normal, non-SSL LDAP. 这适用于普通的非SSL LDAP。 However, we've encountered a situation where we need to be connecting to LDAPS, via SSL, and it doesn't work. 但是,我们遇到了一种情况,我们需要通过SSL连接到LDAPS,但它不起作用。 I've tried a ton of variations on the PrincipalContext constructor, but everything we do results in a failed connection, with this error: 我在PrincipalContext构造函数上尝试了大量的变体,但是我们所做的一切都会导致连接失败,并出现此错误:

System.DirectoryServices.AccountManagement.PrincipalServerDownException: The server could not be contacted. ---> System.DirectoryServices.Protocols.LdapException: The LDAP server is unavailable.
   at System.DirectoryServices.Protocols.LdapConnection.Connect()
   at System.DirectoryServices.Protocols.LdapConnection.SendRequestHelper(DirectoryRequest request, Int32& messageID)
   at System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request, TimeSpan requestTimeout)
   at System.DirectoryServices.AccountManagement.PrincipalContext.ReadServerConfig(String serverName, ServerProperties& properties)
   --- End of inner exception stack trace ---
   at System.DirectoryServices.AccountManagement.PrincipalContext.ReadServerConfig(String serverName, ServerProperties& properties)
   at System.DirectoryServices.AccountManagement.PrincipalContext.DoServerVerifyAndPropRetrieval()
   at System.DirectoryServices.AccountManagement.PrincipalContext..ctor(ContextType contextType, String name, String container, ContextOptions options, String userName, String password)

We know it's not the LDAP server itself, as trying by the method discussed here connects without errors. 我们知道它不是LDAP服务器本身,因为通过这里讨论的方法尝试连接没有错误。 I'm not really comfortable with using try...catch for logic flow, and I've read of some other issues with this method (like not properly respecting certificates and such), so I'm trying to make this work with PrincipalContext. 我不太习惯使用try ... catch来获取逻辑流程,而且我已经阅读了这个方法的一些其他问题(比如没有正确地尊重证书等),所以我试图用PrincipalContext来完成这个工作。 。

Could anybody offer me some guidance here? 有人能在这里给我一些指导吗? I'm going crazy on this one. 我在这个上疯了。

EDIT: Upon some further research, it looks like this may be a problem with self-signed certificates. 编辑:经过一些进一步的研究,看起来这可能是自签名证书的问题。

EDIT 2: After breaking it down into X509 chain calls, I'm getting this specific error: 编辑2:在将其分解为X509链调用后,我收到了这个特定的错误:

PartialChain A certificate chain could not be built to a trusted root authority. PartialChain无法将证书链构建到受信任的根颁发机构。

Looking at that, you'd think it's just a matter of adding the CA as a trusted root, but that didn't seem to fix the problem. 看一下,您认为只需将CA添加为受信任的根,但这似乎无法解决问题。

I'm wondering if this CodeProject article may be of assistance: 我想知道这个CodeProject文章是否有帮助:

"Recently, I ran into trouble using System.DirectoryServices.DirectoryEntry to connect to a Novell eDirectory server because the certificate was self-signed. When run in an ASP.NET application, the machine-level certificate store was not examined. So, even though the self-signed certificate was in the trusted store, DirectoryEntry was still refusing to establish a connection. “最近,我遇到了使用System.DirectoryServices.DirectoryEntry连接到Novell eDirectory服务器的问题,因为证书是自签名的。当在ASP.NET应用程序中运行时,机器级证书存储区未被检查。所以,甚至虽然自签名证书位于受信任的存储中,但DirectoryEntry仍然拒绝建立连接。

The LdapConnection class is a better choice for this situation, as it allows the user to validate the certificate manually. 对于这种情况,LdapConnection类是更好的选择,因为它允许用户手动验证证书。 Note that the DirectoryEntry approach works fine with a trusted self-signed certificate when run in a Windows Forms application." 请注意,在Windows窗体应用程序中运行时,DirectoryEntry方法可以使用受信任的自签名证书。“

With LdapConnection, you could use your own certificate authentication as shown here: 使用LdapConnection,您可以使用自己的证书身份验证,如下所示:

LdapConnection con = new LdapConnection(new LdapDirectoryIdentifier("EDIRECTORYSERVER:636"));
con.SessionOptions.SecureSocketLayer = true;
con.SessionOptions.VerifyServerCertificate = 
   new VerifyServerCertificateCallback(ServerCallback);
con.Credential = new NetworkCredential(String.Empty, String.Empty);
con.AuthType = AuthType.Basic;

And a verification callback like this: 这样的验证回调:

public static bool ServerCallback(LdapConnection connection, X509Certificate certificate)
{
  try
  {
    X509Certificate expectedCert = 
         X509Certificate.CreateFromCertFile("C:\\certificates\\certificate.cer");

    if (expectedCert.Equals(certificate))
    {
        return true;
    }
    else
    {
        return false;
    }
  }
  catch (Exception ex)
  {
      return false;
  }
}

Check this answer by Gabriel Luci 请查看Gabriel Luci的回答

Are you sure it supports SSL and that the firewall is open to allow that connection? 您确定它支持SSL并且防火墙是否已打开以允许该连接?

LDAP uses port 389. LDAPS uses port 636. LDAP使用端口389.LDAPS使用端口636。

If you have the telnet client installed, you can use it to check the connectivity: 如果安装了telnet客户端,则可以使用它来检查连接:

telnet yourdomain.com 636 If you get a blank screen, it worked. telnet yourdomain.com 636如果你得到一个空白的屏幕,它是有效的。 If it can't connect, it will tell you. 如果它无法连接,它会告诉你。

If that is open and it still does not work, it could be using a self-signed SSL certificate. 如果它已打开但仍然无效,则可能是使用自签名SSL证书。 Check the Windows event log for certificate-related errors. 检查Windows事件日志中是否存在与证书相关的错误。

I've also used Chrome to check the certificate. 我还使用Chrome来检查证书。 You have to run chrome like this: 你必须像这样运行chrome:

chrome.exe --explicitly-allowed-ports=636 Then browse to https://yourdomain.com:636 and see if it gives you any certificate errors. chrome.exe --explicitly-allowed-ports = 636然后浏览到https://yourdomain.com:636并查看它是否为您提供任何证书错误。 Then you can actually see the certificate. 然后你就可以看到证书了。 If that's the problem, you may be able to import the certificate and explicitly trust it. 如果这是问题,您可以导入证书并明确信任它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM