2012-01-18 123 views
1

我试图连接到需要StartTLS但没有运气的LDAP服务器 - 每当我使用SessionOptions.StartTransportLayerSecurity(..)或将SessionOptions.SecureSocketLayer设置为true时,我得到例外。从System.DirectoryServices使用StartTLS与LDAP

下面是我使用的代码:

using (var connection = new LdapConnection(new LdapDirectoryIdentifier(config.LdapServer, config.Port, false, false))) 
{ 
    connection.SessionOptions.ProtocolVersion = 3; 
    connection.Credential = new NetworkCredential(config.BindDN, config.BindPassword); 
    connection.SessionOptions.VerifyServerCertificate += (conn, cert) => {return true;}; 
    connection.AuthType = AuthType.Basic; 
    //connection.SessionOptions.SecureSocketLayer = true; 
    connection.SessionOptions.StartTransportLayerSecurity(null); // throws here, same if done after bind. 
    connection.Bind(); 

    ... do stuff with connection 
} 

产生的例外是“TlsOperationException:出现未知错误”,调用StartTransportLayerSecurity方法时发生。

我已经测试了针对OpenLDAP服务器和Active Directory的代码,但都不起作用。

有谁知道如何让StartTLS使用System.DirectoryServices?

+3

可否请你指定的OpenLDAP针对特定版本,Active Directory和特别是操作系统*双向*客户端和服务器这里涉及到缩小范围有多大?过去有相当多的微妙的LDAP堆栈不兼容,这仍然适用于您的客户可能使用的潜在遗留场景。 – 2012-01-23 11:46:10

+1

斯特芬嗨,信息是OpenLDAP的2.4.18,FreeBSD的服务器和客户端是在Windows Server 2008 R2的计算机(客户端代码中的ASP.Net应用程序托管,.Net框架3.5 SP1)。 在LDAP的版本上进一步搜索,让我有关于该主题的一些博客文章,包括: http://pongo15.wordpress.com/2009/12/18/on-getting-openldap-and-windows- ldap-to-interop/- 帮助我深入了解问题的底部。 我要去尝试,并鼓励用户向上移动到最新的OpenLDAP,因为我认为这个问题可能是固定在以后的版本(他们的版本是真的老了,太阳公布,2009年6月) – Bittercoder 2012-01-26 10:26:16

+0

感谢跟进信息,这将有助于后来的读者对这样的问题(+1)!我[更新我的答案](http://stackoverflow.com/posts/9020311/revisions#)相应... – 2012-01-26 15:40:50

回答

1

在这个问题上,我发现我跑了agains更多的工作之后t几个问题:

  1. 在我们的测试套件(doh!)连接到AD时,端口号被错误地更改为SSL端口(636)的代码中存在一个错误。
  2. OpenLDAP测试服务器(这是我们客户的复制品)正在使用openldap-2.4.18--它具有StartTLS的已知问题。

应用补丁的OpenLDAP(如这里讨论 - http://www.openldap.org/lists/openldap-bugs/200405/msg00096.html)后,我们能够解决#2 - 在这一点,我们开始收到不同的错误“出现了一个本地错误”。

虽然最初我们有这样的代码:

connection.SessionOptions.VerifyServerCertificate 
    += (conn, cert) => {return true;}; 

测试,因为OpenLDAP服务器使用自签名的证书,而我们已经删除了,这不是一个值得信赖的商店。重新引入回调解决了这个问题,但我们现在将其设置为可配置选项,即“验证服务器证书是/否”,以便客户选择跳过检查(主要是供我们的QA团队使用)。

感谢Steffen指出我在OpenLDAP版本的方向,这导致了我的解决方案。

+0

感谢您的调查结果的详细摘要(+1) - 我已经学到了一些东西为好,即到后我的研究成果作为一个答案马上为避免重复工作(毕竟,答案可以随时精炼),并提出研究有趣的问题慷慨富饶像你这样比较划算,即使!我[扩展为一个答案我的评论](http://stackoverflow.com/a/9020311/45773)现在相应的得到这种方法认识 - 感谢很多;) – 2012-01-26 15:18:06

1

请阅读本主题: Binding over a TLS/SSL Encrypted Connection

例19.使用基本身份验证和SSL/TLS

string hostNameAndSSLPort = "sea-dc-02.fabrikam.com:50001"; 
string userName = "cn=User1,cn=AdamUsers,cn=ap1,dc=fabrikam,dc=com"; 
string password = "adamPassword01!"; 

// establish a connection 
LdapConnection connection = new LdapConnection(hostNameAndSSLPort); 

// create an LdapSessionOptions object to configure session 
// settings on the connection. 
LdapSessionOptions options = connection.SessionOptions; 

options.ProtocolVersion = 3; 

options.SecureSocketLayer = true; 

connection.AuthType = AuthType.Basic; 

NetworkCredential credential = 
     new NetworkCredential(userName, password); 

connection.Credential = credential; 

try 
{ 
    connection.Bind(); 
    Console.WriteLine("\nUser account {0} validated using " + 
     "ssl.", userName); 

    if (options.SecureSocketLayer == true) 
    { 
     Console.WriteLine("SSL for encryption is enabled\nSSL information:\n" + 
     "\tcipher strength: {0}\n" + 
     "\texchange strength: {1}\n" + 
     "\tprotocol: {2}\n" + 
     "\thash strength: {3}\n" + 
     "\talgorithm: {4}\n", 
     options.SslInformation.CipherStrength, 
     options.SslInformation.ExchangeStrength, 
     options.SslInformation.Protocol, 
     options.SslInformation.HashStrength, 
     options.SslInformation.AlgorithmIdentifier); 
    } 

} 
catch (LdapException e) 
{ 
    Console.WriteLine("\nCredential validation for User " + 
     "account {0} using ssl failed\n" + 
     "LdapException: {1}", userName, e.Message); 
} 
catch (DirectoryOperationException e) 
{ 
    Console.WriteLine("\nCredential validation for User " + 
    "account {0} using ssl failed\n" + 
    "DirectoryOperationException: {1}", userName, e.Message); 
} 

而接下来的例子显示绑定到安全端口50001 ADAM实例“如何使用TLS认证和执行任务”

string hostOrDomainName = "fabrikam.com"; 
string userName = "user1"; 
string password = "password1"; 

// establish a connection to the directory 
LdapConnection connection = new LdapConnection(hostOrDomainName); 

NetworkCredential credential = 
    new NetworkCredential(userName, password, domainName); 

connection.Credential = credential; 

connection.AuthType = AuthType.Basic; 

LdapSessionOptions options = connection.SessionOptions; 

options.ProtocolVersion = 3; 

try 
{ 
    options.StartTransportLayerSecurity(null); 
    Console.WriteLine("TLS started.\n"); 
} 
catch (Exception e) 
{ 
    Console.WriteLine("Start TLS failed with {0}", 
     e.Message); 
    return; 
} 

try 
{ 
    connection.Bind(); 
    Console.WriteLine("Bind succeeded using basic " + 
     "authentication and SSL.\n"); 

    Console.WriteLine("Complete another task over " + 
     "this SSL connection"); 
    TestTask(hostName); 
} 
catch (LdapException e) 
{ 
    Console.WriteLine(e.Message); 
} 

try 
{ 
    options.StopTransportLayerSecurity(); 
    Console.WriteLine("Stop TLS succeeded\n"); 
} 
catch (Exception e) 
{ 
    Console.WriteLine("Stop TLS failed with {0}", e.Message); 
} 

Console.WriteLine("Switching to negotiate auth type"); 
connection.AuthType = AuthType.Negotiate; 

Console.WriteLine("\nRe-binding to the directory"); 
connection.Bind(); 

// complete some action over this non-SSL connection 
// note, because Negotiate was used, the bind request 
// is secure. 
// run a task using this new binding 
TestTask(hostName); 
3

过去有相当多的微妙的LDAP堆栈不兼容,这仍然适用于您的客户可能使用的潜在遗留场景。

以下是关于OpenLDAP和微软的LDAP堆栈 之间不兼容的最常见的问题(我将修改和/或替换这些链接,一旦更多信息可用)

很显然,无论是更新OpenLDAP和/或Windows(最好当然两者)应该解决这些问题,如果他们变成是这里的罪魁祸首。

祝你好运!