2008-12-22 42 views
7

我正在尝试使用Novell发布的库(Novell.Directory.Ldap)。版本2.1.10。Novell LDAP C# - Novell.Directory.Ldap - 有人让它工作吗?

什么我迄今所做的:

  • 我测试与应用(LdapBrowser)的连接,它的工作,所以它不是一个沟通的问题。

  • 它在Mono中编译,但我正在使用Visual Studio。因此创建了一个包含源代码的项目。我还引用了Mono.Security,因为该项目取决于它。

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

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

    //创建LdapConnection实例

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

    //连接功能将创建一个套接字连接到服务器

    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服务器 LdapConnection.Bind()进行身份验证。我们只支持 明文认证。 SSL/TLS 支持尚未添加。

但是从2004年开始的文档日期已经有很多更新。并且库中有一个参数用于定义连接是否使用SSL。所以现在我很困惑。

(更新)找到更新的文档:http://developer.novell.com/documentation//ldapcsharp/index.html?page=/documentation//ldapcsharp/cnet/data/bqwa5p0.html。 SSL连接的方式是通过在服务器上注册证书。问题是我所做的并不是绑定到特定的Novell服务器,所以证书必须动态获取。

+0

获得SSL工作的常用方法是将签名CA的公钥转换为Java密钥库(通常为树CA)的等效项。不知道在C#中意味着什么。一旦拥有它,那么由该树CA签署的所有服务器证书都将工作。所以你需要每棵树一个。 – geoffc 2008-12-28 02:45:21

回答

4

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

首先,论文的职位帮助我在正确的轨道上: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

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

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

2

我想我可能已经提供这个答案给其他人在不同的问题。

[OtherQuestion对LDAP] [1]

两个问题,我认为:1)什么样绑定的,你想干什么? SSL?清除文字?匿名?

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

工具LDAP浏览器,你指的是这个链接上的一个? 免费LDAP浏览器

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

您可以请求另一端的人员启用LDAP跟踪(在启用了+ LDAP选项的情况下使用DStrace,有关如何在Novell eDirectory上使用Dstrace的链接,请参阅:不同类型的Dstrace捕获并理解DS Trace for身份管理器。)

这通常会显示一条错误消息,将启发你。

我的猜测是要么启用TLS,并且您可能没有做一个成功的SSL绑定。

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

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

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

下一种可能性是您指定的DN不完全正确。

让我知道你是否需要更多帮助。

+0

我们无法更改Novell服务器上的任何内容,它由另一个团队管理并在实时环境中运行。所以我们有一个连接访问它来测试身份验证,但这就是我们所拥有的。使用LDAP浏览器,我们可以连接到它,所以它是使这个DLL工作的问题。 – ceetheman 2008-12-23 20:11:12

+0

您的密钥库中是否有树根证书? (不知道C#等价物被称为什么)。它本身不是服务器特定的。它更具体树。即每棵树的一个根CA证书将允许访问所有服务器。 – geoffc 2008-12-28 02:42:44

1

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

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

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

+0

添加ldaps://使地址无效。服务器使用SSL并在客户端导入证书。 – ceetheman 2008-12-23 16:42:50

3

我开始寻找类似问题的解决方案。在使用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

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

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

1)确保从您绑定的Novell服务器获取SSL证书,并将其注册到正在执行的客户端/服务器上的受信任存储中。通常有两个IP地址和主机名取决于您要拨打的IP地址(DNS优先)

2)使用System.DirectoryServices导入以下/添加引用 ; using 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();