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

时间:2008-12-22 18:36:10

标签: c# .net ldap novell

我正在尝试使用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);

    //绑定功能将用户对象凭据绑定到服务器

    ldapConn.Bind(用户DN,userPasswd);

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

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

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

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

  

使用LDAP验证LDAP服务器   LdapConnection.Bind()。我们只支持   明文认证。 SSL / TLS   支持尚未加入。

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

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

8 个答案:

答案 0 :(得分:5)

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

        // 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;
        }

答案 1 :(得分:3)

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

首先,这些帖子帮助我走上了正确的轨道: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处理程序动态获取证书,并使用X509StoreManager.LocalMachine,以便在网站运行时能够保存和获取证书。

答案 2 :(得分:2)

91是“无法连接”。尝试将服务器置于“ldap://x.x.x.x”格式,检查userDN是否设置正确(使用域等)。

我经常使用WireShark来查看网络级别的内容(它知道LDAP协议)。

答案 3 :(得分:2)

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

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

我认为有两个问题:1)你想做什么样的约束? SSL?明文?匿名?

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

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

在eDirectory端,他们可以要求TLS进行所有LDAP通信,并且他们可以禁止匿名绑定。

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

这通常会显示一条错误信息,可以启发你。

我猜是要么启用了需要TLS,要么你可能没有成功进行SSL绑定。

如果是这样,请尝试连接已启用SSL的端口636,以及您尝试登录的用户的完全限定DN。

如果您尝试启用SSL,并且没有获得有关接受树CA的受信任根证书的弹出框,则可能是用户已过期或已损坏的eDirectory服务器的CA或SSL证书。 (有许多原因可能很常见,需要花一点时间才能解决)。

通常在Dstrace中,如果出现问题,您将看到有关SSL证书的错误。本文将介绍Novell Identity Manager对过期证书的透视示例:证书已过期以及有关如何修复证书的一些详细信息。

下一种可能性是你指定的DN不太正确。

如果您需要更多帮助,请与我联系。

答案 4 :(得分:2)

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

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

1)确保从您绑定的Novell服务器获取SSL证书,并将其注册到正在执行的客户端/服务器上的受信任存储中。通常有两个用于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();

答案 5 :(得分:1)

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

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

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

答案 6 :(得分:1)

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

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

        LdapConnection connection = new LdapConnection(options);

        connection.Connect(...);
       

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

答案 7 :(得分:0)

我经历了这种情况,对我来说,在Kubernetes容器中运行的Novell LDAP服务。我尝试将CA证书添加到Mono信任存储中,这将在Linux容器的“ /usr/share/.mono/certs/Trust”内部添加文件。但是什么也没做,但是Novell连接仍然无法成功用于LDAP 636端口。

最后,我通过以下方式使其工作:

 $.ajax({
    url: '@Url.Action("ShowRealTimeValues", "RealTimeValues")',
    type: "GET",
    success: function (result) {
       var html='';
       html += '<tr><td>' + result.MeterNumber+'</td><td>' + result.Current_A+'</td></tr>';

        $("#tbl").append(html);
    }
    });