C# 从System.DirectoryServices将StartTLS与LDAP一起使用

C# 从System.DirectoryServices将StartTLS与LDAP一起使用,c#,ldap,directoryservices,starttls,C#,Ldap,Directoryservices,Starttls,我正在尝试连接到需要StartTLS的LDAP服务器,但运气不好-每当我使用SessionOptions.StartTransportLayerSecurity(..)或将SessionOptions.SecureSocketLayer设置为true时,我都会遇到异常 以下是我使用的代码: using (var connection = new LdapConnection(new LdapDirectoryIdentifier(config.LdapServer, config.Port, f

我正在尝试连接到需要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一起工作吗?

请阅读本主题:

例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进行身份验证和执行任务”

请阅读本主题:

例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进行身份验证和执行任务”


在这个问题上做了更多的工作之后,我发现我遇到了几个问题:

  • 代码中有一个bug,在我们的测试套件(doh!)中连接到AD时,端口号被错误地更改为SSL端口(636)
  • OpenLDAP测试服务器(它是我们客户的复制品)使用的是OpenLDAP-2.4.18,而OpenLDAP-2.4.18与StartTLS存在已知问题
  • 在将补丁应用到OpenLDAP(如本文所讨论的-)之后,我们能够修复#2-在这一点上,我们开始得到一个不同的错误“发生了一个本地错误”

    虽然最初我们有以下代码:

    connection.SessionOptions.VerifyServerCertificate 
        += (conn, cert) => {return true;};
    
    我们在测试时删除了它,因为OpenLDAP服务器使用的是自签名证书,而该证书不在受信任的存储中。重新引入该回调解决了这个问题,尽管我们现在将其设置为可配置选项,即“验证服务器证书Y/N”,因此客户需要选择跳过检查(主要供我们的QA团队使用)


    感谢Steffen为我指明了OpenLDAP版本的方向,这使我找到了这个解决方案。

    在这个问题上做了更多的工作后,我发现我遇到了几个问题:

  • 代码中有一个bug,在我们的测试套件(doh!)中连接到AD时,端口号被错误地更改为SSL端口(636)
  • OpenLDAP测试服务器(它是我们客户的复制品)使用的是OpenLDAP-2.4.18,而OpenLDAP-2.4.18与StartTLS存在已知问题
  • 在将补丁应用到OpenLDAP(如本文所讨论的-)之后,我们能够修复#2-在这一点上,我们开始得到一个不同的错误“发生了一个本地错误”

    虽然最初我们有以下代码:

    connection.SessionOptions.VerifyServerCertificate 
        += (conn, cert) => {return true;};
    
    我们在测试时删除了它,因为OpenLDAP服务器使用的是自签名证书,而该证书不在受信任的存储中。重新引入该回调解决了这个问题,尽管我们现在将其设置为可配置选项,即“验证服务器证书Y/N”,因此客户需要选择跳过检查(主要供我们的QA团队使用)


    感谢Steffen为我指明了OpenLDAP版本的方向,这使我找到了这个解决方案。

    过去在野外存在大量微妙的LDAP堆栈不兼容,这仍然适用于您的客户可能正在使用的潜在遗留方案

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

    • OpenLDAP(在中总结)触发了相应的修补程序:
    显然,更新OpenLDAP和/或Windows(当然最好两者都更新)应该可以解决这些问题,如果它们是罪魁祸首的话


    祝你好运

    过去在野外存在大量微妙的LDAP堆栈不兼容,这可能仍然适用于您的客户可能正在使用的潜在遗留方案

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

    • OpenLDAP(在中总结)触发了相应的修补程序:
    显然,更新OpenLDAP和/或Windows(当然最好两者都更新)应该可以解决这些问题,如果它们是罪魁祸首的话


    祝你好运

    您能否指定OpenLDAP、Active Directory的具体版本,特别是此处涉及的客户端和服务器的操作系统,以缩小范围?过去在野外存在大量微妙的LDAP堆栈不兼容,这可能仍然适用于您的客户可能使用的潜在遗留方案。嗨,Steffen,信息是OpenLDAP 2.4.18,服务器和客户端的FreeBSD是Windows server 2008 r2计算机(客户端代码托管在ASP.Net应用程序中,.Net Framework 3.5 SP1). 通过进一步搜索LDAP版本,我找到了一些关于这个主题的博客文章,包括:-这帮助我找到了问题的根源。我将尝试并鼓励用户升级到最新的OpenLDAP,因为我认为这个问题可能在以后的版本中得到修复(他们的版本非常旧,于2009年9月6日发布于Sun),感谢后续信息,这将有助于以后的读者解决类似的问题(+1)!我已经相应地…您可以指定OpenLDAP、Active Directory的具体版本,特别是此处涉及的客户端和服务器的操作系统,以缩小范围吗?过去,在野外存在大量微妙的LDAP堆栈不兼容,这仍然适用于客户可能使用的潜在遗留方案。嗨,Steffen,信息是OpenLDAP 2.4.18,服务器和客户端的FreeBSD是Windows