【问题标题】:.Net program does not get validated server certificate.Net 程序未获得经过验证的服务器证书
【发布时间】:2019-09-30 09:42:03
【问题描述】:

我有一个相当简单的 LDAP 客户端,它在连接到 389 端口 (LDAP) 时工作​​正常,但在我尝试连接到 636 端口 (LDAPS) 时失败并显示“LDAP 服务器不可用”。

namespace MyNS
{
  class ProgramLdap
  {
    private static LdapConnection CreateConnection(String baseDn, string usuario, string password)
    {
      LdapConnection ldapConnection = new LdapConnection(
        new LdapDirectoryIdentifier("myserver.example", 636, true, false));
      ldapConnection.SessionOptions.SecureSocketLayer = true;
      ldapConnection.SessionOptions.ProtocolVersion = 3;
      // [CODE MODIFICATION HERE]
      ldapConnection.Credential = new NetworkCredential(usuario, password);
      ldapConnection.AuthType = AuthType.Basic;
      ldapConnection.Timeout = new TimeSpan(1, 0, 0);
      return ldapConnection;
    }

    static void Main(string[] args)
    {

      LdapConnection ldapConnection = CreateConnection("", "myLdapUser", "noneOfYourBusiness");
      SearchRequest searchRequest = new SearchRequest(
        "ou=usuarios,dc=Dexter,dc=local",
         String.Format("(&(objectclass=person)(cn={0}))", user),
         SearchScope.Subtree,
         new string[0]);
       SearchResponse searchResponse =
          (SearchResponse) ldapConnection.SendRequest(searchRequest);
      System.Diagnostics.Debug.WriteLine("Resultados " + searchResponse.Entries.Count);
    }
  }
}

如果我在 [CODE MODIFICATION HERE] 处添加以下内容以接受所有服务器证书,则可以:

ldapConnection.SessionOptions.VerifyServerCertificate =
   new VerifyServerCertificateCallback((conn, certificate) => true);

证书由自签名 CA 签名,我已将 CA 公共证书添加到“受信任的根证书颁发机构”的本地计算机列表中1

如果我使用该 CA 的证书通过 openSSL 检查服务器证书,它会验证它。另外,我尝试过LdapAdmin,当 CA 在该列表中时,连接到 LDAP 服务器时不会显示警告。

如果我使用 VerifyServerCertificateCallback 打印证书的内容:

ldapConnection.SessionOptions.VerifyServerCertificate =
  new VerifyServerCertificateCallback(
    (conn, certificate) => {
       X509Certificate2 certificate2 = new X509Certificate2(certificate);
       bool verify = certificate2.Verify();
       System.Diagnostics.Debug.WriteLine(
         String.Format(
           "certificate2.Verify {0}; Name {1}; NameOID {2}; FriendlyName {3}; Thumbprint {4}; Algorithm FriendlyName {5}",
           verify,
           certificate2.SubjectName.Name,
           certificate2.SubjectName.Oid,
           certificate2.FriendlyName,
           certificate2.Thumbprint,
           certificate2.SignatureAlgorithm.FriendlyName));

           foreach (X509Extension extension in certificate2.Extensions) 
           {
             System.Diagnostics.Debug.WriteLine(extension.ToString() + " " + extension.Oid.FriendlyName + " " + Encoding.UTF8.GetString(extension.RawData));
            }
            return verify;
         });

它显示了服务器证书的指纹,但 验证 失败。

我能成为什么?似乎我遗漏了一些非常基本的东西,但我不明白是什么。


更新:

我检查了@FrankNielsen 的建议,并在 VerifyServerCertificateCallback 中添加了这段代码:

(conn, certificate) => {
  X509Chain ch = new X509Chain();
  ch.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
  ch.Build(new X509Certificate2(certificate));
  System.Diagnostics.Debug.WriteLine("Chain Information");
  System.Diagnostics.Debug.WriteLine(String.Format("Chain revocation flag: {0}", ch.ChainPolicy.RevocationFlag));
  System.Diagnostics.Debug.WriteLine(String.Format("Chain revocation mode: {0}", ch.ChainPolicy.RevocationMode));
  System.Diagnostics.Debug.WriteLine(String.Format("Chain verification flag: {0}", ch.ChainPolicy.VerificationFlags));
  System.Diagnostics.Debug.WriteLine(String.Format("Chain verification time: {0}", ch.ChainPolicy.VerificationTime));
  System.Diagnostics.Debug.WriteLine(String.Format("Chain status length: {0}", ch.ChainStatus.Length));
  System.Diagnostics.Debug.WriteLine(String.Format("Chain application policy count: {0}", ch.ChainPolicy.ApplicationPolicy.Count));
  System.Diagnostics.Debug.WriteLine(String.Format("Chain certificate policy count: {0} {1}", ch.ChainPolicy.CertificatePolicy.Count, Environment.NewLine));

  System.Diagnostics.Debug.WriteLine("Chain Element Information");
  System.Diagnostics.Debug.WriteLine(String.Format("Number of chain elements: {0}", ch.ChainElements.Count));
  System.Diagnostics.Debug.WriteLine(String.Format("Chain elements synchronized? {0} {1}", ch.ChainElements.IsSynchronized, Environment.NewLine));
  foreach (X509ChainElement element in ch.ChainElements)
  {
    System.Diagnostics.Debug.WriteLine(String.Format("Element issuer name: {0}", element.Certificate.Issuer));
    System.Diagnostics.Debug.WriteLine(String.Format("Element certificate valid from: {0}", element.Certificate.NotBefore));
    System.Diagnostics.Debug.WriteLine(String.Format("Element certificate valid until: {0}", element.Certificate.NotAfter));
    System.Diagnostics.Debug.WriteLine(String.Format("Element certificate is valid: {0}", element.Certificate.Verify()));
    System.Diagnostics.Debug.WriteLine(String.Format("Element error status length: {0}", element.ChainElementStatus.Length));
    System.Diagnostics.Debug.WriteLine(String.Format("Element information: {0}", element.Information));
    System.Diagnostics.Debug.WriteLine(String.Format("Thumbprint: {0}", element.Certificate.Thumbprint));
    System.Diagnostics.Debug.WriteLine(String.Format("Number of element extensions: {0}{1}", element.Certificate.Extensions.Count, Environment.NewLine));
    if (ch.ChainStatus.Length > 1)
    {
      for (int index = 0; index < element.ChainElementStatus.Length; index++)
      {
         System.Diagnostics.Debug.WriteLine(element.ChainElementStatus[index].Status);
        System.Diagnostics.Debug.WriteLine(element.ChainElementStatus[index].StatusInformation);
       }
     }
   }
   return true;
 });

然后它返回:

链信息
链撤销标志:ExcludeRoot 链撤销模式:NoCheck
链验证标志:NoFlag
链验证时间:07/10/2019 15:53:00
链状态长度:0
链应用策略计数:0
链证书策略计数:0

链元信息
链元素数:2
链元素同步?假的

元素发行者名称:CN=dexter-SCPDPRDEXTER01V-CA, DC=dexter, DC=local
元素证书有效期自:02/09/2019 12:24:22
元素证书有效期至:01/09/2020 12:24:22
元素证书有效:False
元素错误状态长度:0
元素信息:
指纹:63DCF4EFE0C96EF021BCC9CE662E2627A3CDF399
元素扩展数:9

元素发行者名称:CN=dexter-SCPDPRDEXTER01V-CA, DC=dexter, DC=local
元素证书有效期自:11/06/2019 7:39:01
元素证书有效期至:11/06/2069 7:49:01
元素证书有效:True
元素错误状态长度:0 元素信息:
指纹:7BD9C718E336A50FA006CAEF539895C7E3EA5DA0
元素扩展数:4

证书与预期匹配(检索 CA),CA 向 Verify() 返回 true,但服务器证书向 Verify() 返回 false。


1为了更好地衡量,我也尝试将其添加到“中级证书颁发机构”,但无济于事。

【问题讨论】:

  • 正在尝试但.... 使用 System.Net; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
  • @StephenMcDowell 谢谢你的建议,但它不起作用(事实上我在.Net 4.5 上,只有 Ssl3Tls i> 可用;我都试过了,但都失败了)。无论如何,这似乎不是通信问题,而是证书验证问题,因为当我绕过证书验证(通过让 VerifyServerCertificate 始终返回 true)时,通信建立正确。
  • 您是否在您的 AD 服务器上配置了 SSL?您必须将证书导入 AD DS 个人存储区active-directory-faq.de/2012/08/…
  • 您是否尝试通过X509Chain 获得更详细的错误 - 请参阅此处(备注下方):docs.microsoft.com/en-us/dotnet/api/…
  • @AndreasSchmidt 是正确的。如果您在 Windows 域上运行,域服务器将覆盖本地证书。您需要让您的证书在域控制器上受信任。

标签: c# .net ssl ldap


【解决方案1】:

最后,正确调试它的方法是检查 ChainStatus 的元素,如 X509Certificate2.Verify() returns false always 中所述

这样我确实发现我的程序无法连接到证书吊销列表 URL。

解决方案(除了打开对 URL 的访问)是使用 X509Chain 类在回调中验证证书并将其设置为不检查 CRL:

ldapConnection.SessionOptions.VerifyServerCertificate =
    new VerifyServerCertificateCallback(
        (conn, certificate) =>
            {
                X509Chain x509Chain = new X509Chain();
                x509Chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
                X509Certificate2 cert2 = new X509Certificate2(certificate);
                bool buildResult = x509Chain.Build(cert2);
                if (!buildResult)
                {
                    foreach (X509ChainStatus chainStatus in x509Chain.ChainStatus)
                    {
                        System.Diagnostics.Debug.WriteLine(
                            String.Format(
                                "Chain Status {0} : {1}", chainStatus.Status, chainStatus.StatusInformation));
                    }
                }
                return buildResult;
            });

【讨论】:

    【解决方案2】:

    请在每个域控制器上完成此步骤以在 LDAP 上启用 SSL。

    1. 转到每个域控制器,打开 MMC
    2. 点击文件,添加管理单元
    3. 选择证书
    4. 选择服务帐号并点击下一步
    5. 选择本地计算机并单击下一步
    6. 选择 Active Directory 服务并单击完成以完成对话框
    7. 单击“确定”将管理单元添加到 MMC

    现在在证书管理单元中将您的证书添加到 NTDS/个人,如果需要,将 CA 证书添加到 NTDS/受信任的根证书颁发机构

    我来自德国系统,如果技术名称与您的不匹配,我很抱歉。

    来源:https://www.active-directory-faq.de/2012/08/ldap-over-ssl-oder-sercure-ldap-ldaps-mit-server-2008r2/

    【讨论】:

      猜你喜欢
      • 2015-03-22
      • 1970-01-01
      • 2015-05-13
      • 2019-10-20
      • 2014-09-16
      • 2012-01-31
      • 2021-11-11
      • 2011-07-07
      • 1970-01-01
      相关资源
      最近更新 更多