繁体   English   中英

Novell LDAP C# - Novell.Directory.Ldap - 有没有人让它工作?

[英]Novell LDAP C# - Novell.Directory.Ldap - Has anybody made it work?

我正在尝试使用 Novell (Novell.Directory.Ldap) 发布的库。 版本 2.1.10。

到目前为止我所做的:

  • 我测试了与应用程序( LdapBrowser )的连接并且它正在工作,所以它不是通信问题。

  • 它是用 Mono 编译的,但我正在使用 Visual Studio。 所以创建了一个带有源的项目。 我还引用了 Mono.Security,因为项目依赖于它。

  • 我在连接的错误捕获部分评论了一个调用 (freeWriteSemaphore(semId);),因为它抛出了更多异常。 我检查了那个调用做了什么,它只是一个错误跟踪机制。

  • 我遵循了 Novell ( http://www.novell.com/coolsolutions/feature/11204.html ) 文档中提供的基本步骤。

    // 创建一个 LdapConnection 实例

    LdapConnection ldapConn= new LdapConnection(); ldapConn.SecureSocketLayer = ldapPort == 636;

    //Connect 函数将创建一个到服务器的套接字连接

    ldapConn.Connect(ldapHost,ldapPort);

    //绑定函数将用户对象Credentials绑定到服务器

    ldapConn.Bind(userDN,userPasswd);

  • 现在它在 Bind() 函数处崩溃。 我收到错误 91。

那么,有没有人使用过这个库并看到它工作? 如果是这样,你做了什么使它工作,是否需要一些特殊的配置? 有没有办法让它在没有 Mono 的 .NET 环境中工作(我可以引用 Mono dll,但我不希望它安装在服务器上)?

(更新)连接在端口 636 上,因此使用 SSL。 我检查了 WireShark 的通信并与我从 LDAP 浏览器获得的内容进行了比较。 我已经看到传递 SSL 证书的步骤不是由 LDAP 库完成的。 那么,让它做它应该做的最好的方法是什么?

(更新)我检查了文档,它表明它不支持 SSL。 http://www.novell.com/coolsolutions/feature/11204.html

使用 LdapConnection.Bind() 对 LDAP 服务器进行身份验证。 我们仅支持明文身份验证。 尚未添加 SSL/TLS 支持。

但是文档的日期是 2004 年,从那时起,已经进行了许多更新。 并且库中有一个参数来定义连接是否使用 SSL。 所以现在我很困惑。

(更新)找到了更新的文档: http : //developer.novell.com/documentation//ldapcsharp/index.html?page=/ documentation //ldapcsharp/cnet/data/bqwa5p0.html 建立 SSL 连接的方式是在服务器上注册证书。 问题是我正在做的事情没有绑定到特定的 Novell 服务器,因此必须动态获取证书。

我是来寻找类似问题的解决方案的。 使用 Novell 网站上的相同代码时,我的绑定命令也会失败。 对我有用的解决方案是添加动态证书验证回调。 你可以在这里阅读它。

        // Creating an LdapConnection instance 
        LdapConnection ldapConn = new LdapConnection();

        ldapConn.SecureSocketLayer = true;

        ldapConn.UserDefinedServerCertValidationDelegate += new
                CertificateValidationCallback(MySSLHandler);


        //Connect function will create a socket connection to the server
        ldapConn.Connect(ldapHost, ldapPort);

        //Bind function will Bind the user object Credentials to the Server
        ldapConn.Bind(userDN, userPasswd);

        // Searches in the Marketing container and return all child entries just below this
        //container i.e. Single level search
        LdapSearchResults lsc = ldapConn.Search("ou=users,o=uga",
                           LdapConnection.SCOPE_SUB,
                           "objectClass=*",
                           null,
                           false);

        while (lsc.hasMore())
        {
            LdapEntry nextEntry = null;
            try
            {
                nextEntry = lsc.next();
            }
            catch (LdapException e)
            {
                Console.WriteLine("Error: " + e.LdapErrorMessage);
                // Exception is thrown, go for next entry
                continue;
            }
            Console.WriteLine("\n" + nextEntry.DN);
            LdapAttributeSet attributeSet = nextEntry.getAttributeSet();
            System.Collections.IEnumerator ienum = attributeSet.GetEnumerator();
            while (ienum.MoveNext())
            {
                LdapAttribute attribute = (LdapAttribute)ienum.Current;
                string attributeName = attribute.Name;
                string attributeVal = attribute.StringValue;
                Console.WriteLine(attributeName + "value:" + attributeVal);
            }
        }
        ldapConn.Disconnect();
        Console.ReadKey();
    }

public static bool MySSLHandler(Syscert.X509Certificate certificate,
            int[] certificateErrors)
        {

            X509Store store = null;
            X509Stores stores = X509StoreManager.CurrentUser;
            //string input;
            store = stores.TrustedRoot;

            X509Certificate x509 = null;
            X509CertificateCollection coll = new X509CertificateCollection();
            byte[] data = certificate.GetRawCertData();
            if (data != null)
                x509 = new X509Certificate(data);

            return true;
        }

我终于找到了一种方法来完成这项工作。

首先,这些帖子帮助我走上了正轨: http : //directoryprogramming.net/forums/thread/788.aspx

其次,我得到了 Novell LDAP 库的编译 dll 并使用了 Mono.Security.Dll。

解决办法:

我在代码中添加了这个函数

// This is the Callback handler - after "Binding" this is called
        public bool MySSLHandler(Syscert.X509Certificate certificate, int[] certificateErrors)
        {

            X509Store store = null;
            X509Stores stores = X509StoreManager.LocalMachine;
            store = stores.TrustedRoot;

            //Import the details of the certificate from the server.

            X509Certificate x509 = null;
            X509CertificateCollection coll = new X509CertificateCollection();
            byte[] data = certificate.GetRawCertData();
            if (data != null)
                x509 = new X509Certificate(data);

            //List the details of the Server

            //if (bindCount == 1)
            //{

            Response.Write("<b><u>CERTIFICATE DETAILS:</b></u> <br>");
            Response.Write("  Self Signed = " + x509.IsSelfSigned + "  X.509  version=" + x509.Version + "<br>");
            Response.Write("  Serial Number: " + CryptoConvert.ToHex(x509.SerialNumber) + "<br>");
            Response.Write("  Issuer Name:   " + x509.IssuerName.ToString() + "<br>");
            Response.Write("  Subject Name:  " + x509.SubjectName.ToString() + "<br>");
            Response.Write("  Valid From:    " + x509.ValidFrom.ToString() + "<br>");
            Response.Write("  Valid Until:   " + x509.ValidUntil.ToString() + "<br>");
            Response.Write("  Unique Hash:   " + CryptoConvert.ToHex(x509.Hash).ToString() + "<br>");
            // }

            bHowToProceed = true;
            if (bHowToProceed == true)
            {
                //Add the certificate to the store. This is \Documents and Settings\program data\.mono. . .
                if (x509 != null)
                    coll.Add(x509);
                store.Import(x509);
                if (bindCount == 1)
                    removeFlag = true;
            }

            if (bHowToProceed == false)
            {
                //Remove the certificate added from the store.

                if (removeFlag == true && bindCount > 1)
                {
                    foreach (X509Certificate xt509 in store.Certificates)
                    {
                        if (CryptoConvert.ToHex(xt509.Hash) == CryptoConvert.ToHex(x509.Hash))
                        {
                            store.Remove(x509);
                        }
                    }
                }
                Response.Write("SSL Bind Failed.");
            }
            return bHowToProceed;
        }

我在绑定过程中使用了它

// Create Connection
                LdapConnection conn = new LdapConnection();
                conn.SecureSocketLayer = true;
                Response.Write("Connecting to:" + ldapHost);

                conn.UserDefinedServerCertValidationDelegate += new
                    CertificateValidationCallback(MySSLHandler);

                if (bHowToProceed == false)
                    conn.Disconnect();
                if (bHowToProceed == true)
                {
                    conn.Connect(ldapHost, ldapPort);
                    conn.Bind(loginDN, password);
                    Response.Write(" SSL Bind Successfull ");

                    conn.Disconnect();
                }
                quit = false;

关键是使用 SSL Handler 动态获取证书,并使用 X509StoreManager.LocalMachine 以便在网站运行时能够保存和获取证书。

我致力于 Forefront Identity Manager 集成。 所以我写的代码总是来自几个调用客户端。 如果您尝试打包应用程序以供“任何地方”使用,这可能不合适。

我只是想用一个简单的解决方案来更新这个线程,这些解决方案适用于启用了默认 TLS/SSL“需要保密”选项的 Novell 服务器。

1) 确保您也从您绑定的 Novell 服务器上获取 SSL 证书,并将这些证书注册到正在执行的客户端/服务器上的可信存储中。 通常有两个 1 用于 IP 和取决于您将调用的主机名(最好使用 DNS)

2) 使用 System.DirectoryServices 导入以下/添加引用; 使用 System.DirectoryServices.Protocols;

3)这是一个片段。 确保选择 AuthenticationTypes.SecureSocketsLayer 这是关键。

// serverAddress = Server IP or DNS (Match SSL certificate)
// ObjectDN = The DN of the user you are binding to
// userName = Account which will be used to make the bind
// password = password of the user which will make the bind
// value = The value you wish to add to the attribute

// Connect to the user in LDAP
DirectoryEntry entry = new DirectoryEntry("LDAP://" + serverAddress + "/" + ObjectDN + ""
                , userName
                , password
                , AuthenticationTypes.SecureSocketsLayer);
// Write the Updated attribute
entry.Properties["attribute"].Value = value;
// Read back the updated Attribute into a label
label.Text = entry.Properties["attribute"].Value.ToString();

91 是“无法连接”。 尝试将服务器设置为“ldap://xxxx”格式,检查 userDN 是否设置正确(包括域等)。

我经常使用WireShark来查看网络级别发生了什么(它知道 LDAP 协议)。

我想我可能已经在另一个问题中向其他人提供了这个答案。

[有关 LDAP 的其他问题][1]

我认为有两个问题:1)你想做什么类型的绑定? SSL? 清晰的文字? 匿名?

2) 如何在 eDirectory 端为 LDAP 绑定配置?

LDAP 浏览器工具,您指的是此链接中的工具吗? 免费 LDAP 浏览器

在 eDirectory 方面,它们可以要求所有 LDAP 通信都使用 TLS,并且可以禁止匿名绑定。

您能否要求另一端的人启用 LDAP 跟踪(使用 Dstrace 并启用 +LDAP 选项,有关如何在 Novell eDirectory 上使用 Dstrace 的一些链接请查看:不同类型的 Dstrace 捕获和了解身份管理器的 DS 跟踪。)

这通常会显示一条错误消息,让您有所启发。

我的猜测是 Require TLS 已启用,并且您可能没有成功进行 SSL 绑定。

如果是这样,请尝试在端口 636 上连接,启用 SSL,并为您尝试登录的用户提供完全限定的 DN。

如果您尝试启用 SSL,并且没有收到关于接受树 CA 的受信任根证书的弹出框,则可能是 eDirectory 服务器用户的 CA 或 SSL 证书已过期或损坏。 (造成这种情况的原因有很多,这些原因可能很常见,只需花点时间即可解决)。

通常在 Dstrace 中,如果出现问题,您会看到有关 SSL 证书的错误。 从 Novell Identity Manager 的角度来看,过期证书的一个示例在这篇文章中:证书过期以及有关如何修复证书的一些详细信息。

下一个可能是您指定的 DN 不太正确。

如果您需要更多帮助,请告诉我。

按照我之前的帖子 - 如果您必须使用安全连接,请尝试使用 ldaps:// 作为服务器地址的前缀。

如果没有 SSL/TLS 支持,您可以试试这个- OpenLDAP 库的指南和 .NET 包装器。

重要的一点 - OpenLDAP 中有 TLS 安全级别的设置,因此如果您的 LDAP 服务器具有自签名证书,您要么必须在客户端导入它,要么将 TLS 设置为不检查签名权限*这当然不太安全)。

我已经经历过这个场景,对我来说是在 Kubernetes 容器中运行的 Novell LDAP 服务。 我尝试将 CA 证书添加到 Mono 信任库,这将在 linux 容器中的“/usr/share/.mono/certs/Trust”中添加文件。 但是没有任何效果,对于 LDAP 636 端口,Novell 连接仍然没有成功。

最后我让它以下面的方式工作:

LdapConnection Connection = new LdapConnection();
    Connection.SecureSocketLayer = true;
    Connection.UserDefinedServerCertValidationDelegate += new
            Novell.Directory.Ldap.RemoteCertificateValidationCallback(LdapSSLHandler);

    public bool LdapSSLHandler(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain,
                  System.Net.Security.SslPolicyErrors sslPolicyErrors)
    {
        if (sslPolicyErrors == sslPolicyErrors.None)
        {
            return true;   //Is valid
        }

        if (certificate.GetCertHashString() == "YOUR CERTIFICATE HASH KEY") // Thumbprint value of the certificate
        {
            return true;
        }

        return false;
    }

UserDefinedServerCertValidationDelegate 已过时,因此如果它是无效 ssl 证书的问题,您可以通过以下方式跳过证书验证:

        LdapConnectionOptions options = new LdapConnectionOptions()
            .ConfigureRemoteCertificateValidationCallback(new CertCallback((a, b, c, d) => true))
            .UseSsl();

        LdapConnection connection = new LdapConnection(options);

        connection.Connect(...);
       

但是,您应该检查忽略证书是否是您应用程序的安全解决方案。

暂无
暂无

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

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