簡體   English   中英

通過System.DirectoryServices將StartTLS與LDAP一起使用

[英]Using StartTLS with LDAP from System.DirectoryServices

我試圖連接到需要StartTLS但沒有運氣的LDAP服務器-每當我使用SessionOptions.StartTransportLayerSecurity(..)或將SessionOptions.SecureSocketLayer設置為true時,都會出現異常。

這是我正在使用的代碼:

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一起使用?

過去在野外通常存在許多細微的LDAP堆棧不兼容問題,這些不兼容問題仍可能適用於客戶可能正在使用的潛在舊有方案。

以下是有關OpenLDAP與Microsoft LDAP堆棧不兼容的最常見問題 (一旦有更多信息可用,我將修改和/或替換這些鏈接)

顯然,更新OpenLDAP和/或Windows(當然最好同時更新)應該可以解決這些問題,如果它們確實是造成這種情況的罪魁禍首。

祝好運!

請閱讀本主題: 通過TLS / SSL加密連接進行綁定

例子19.使用基本身份驗證和SSL / TLS綁定到安全端口50001上的ADAM實例

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

下一個示例顯示“如何使用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);

在此問題上進行了更多工作之后,我發現我遇到了幾個問題:

  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服務器使用的是自簽名證書,因此不在受信任的存儲區中。 重新引入該回調解決了此問題,盡管我們現在將其設為可配置的選項,即“驗證服務器證書是/否”,因此客戶需要選擇跳過檢查(主要是供我們的質量檢查小組使用)。

感謝Steffen向我指出了引導我使用該解決方案的OpenLDAP版本的方向。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM