2012-01-18 44 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(最好當然兩者)應該解決這些問題,如果他們變成是這裏的罪魁禍首。

祝你好運!