当在C#中覆盖ServicePointManager.ServerCertificateValidationCallback时,如何调用默认证书检查? [英] How to call the default certificate check when overriding ServicePointManager.ServerCertificateValidationCallback in C#?

查看:2339
本文介绍了当在C#中覆盖ServicePointManager.ServerCertificateValidationCallback时,如何调用默认证书检查?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在应用程序中信任一些自签名证书,所以我重写验证回调,像这样:

  ServicePointManager。 ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback; 
...

public static bool MyRemoteCertificateValidationCallback(
Object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{

if(sslPolicyErrors == SslPolicyErrors.None)
return true;

if(IsAprrovedByMyApplication(sender,certificate))//< - 不管这里的检查是什么
return true;
else
return false; //< - 这里我想调用默认的Windwos处理程序,而不是返回'false'
}

但是当一些策略错误,并且我连接到的网站不被应用程序批准,抛出异常。
这里的问题是它不同于标准的Windows行为。



请考虑这个网站: https://www.dscoduc.com/



这是证书具有未知发行者,因此不受信任。



如果我运行此代码而不覆盖证书验证回调:

  HttpWebRequest http =(HttpWebRequest)HttpWebRequest.Create(https://www.dscoduc.com/); 
using(WebResponse resp = http.GetResponse())
{
using(StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
string html = sr.ReadToEnd();
}
}

这意味着Windows默认验证器决定信任此证书。



但是一旦我重写了ServerCertificateValidationCallback,我的回调用 SslPolicyErrors .RemoteCertificateChainErrors
,链包含一个状态为 X509ChainStatusFlags.PartialChain的元素(实际上我预计在这里不会收到错误,因为当前的证书应该是可信的) / p>

此网站不包括在我的信任列表中,并且不想从我的回调返回'true'。
但是我不想返回'false',否则我会得到一个异常:远程证书根据验证过程是无效的,这显然不是期望的 https://www.dscoduc.com/ ,因为它已添加到受信任的人存储中,并且在证书回拨未被覆盖时由Windows批准。
所以我要Windows使用这个网站的默认验证过程。我不想自己调查Windows Trusted商店,并且通过所有的链接元素,因为它已经(并希望正确)在Windows中实现。



换句话说,我需要明确信任用户批准的网站(存储在其设置中的某个位置),并为所有其他网站调用默认认证检查。



ServicePointManager.ServerCertificateValidationCallback的默认值为null,因此没有默认回调供我稍后调用。
我应该如何调用此默认证书处理程序?



感谢

解决方案



查看 http://msdn.microsoft.com/en-us/library/dd633677(v = exchg.80).aspx



如果证书是自签名的,那么该示例中的代码将检查证书链是否正确,如果是,请信任它。您可以改为接受 PartialChain 。您会希望这样做:

  if(status.Status == X509ChainStatusFlags.PartialChain || 
(certificate.Subject == certificate.Issuer&&
status.Status == X509ChainStatusFlags.UntrustedRoot)
{
//断开链的证书和
//具有不可信根的自签名证书是有效的
continue;
}
else if(status.Status!= X509ChainStatusFlags.NoError)
{
// If在证书链中还有其他错误,
//证书无效,因此方法返回false。
return false;
}

或者,检查主题属性:

  private static bool CertificateValidationCallBack(
object sender,
System.Security.Cryptography.X509Certificates.X509Certificate certificate,
System.Security.Cryptography.X509Certificates .x509链接,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
return certificate.Subject.Contains(。dsoduc.com);
}


I need to trust some self-signed certificates in the application, so I override validation callback like this:

ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;
...

public static bool MyRemoteCertificateValidationCallback(
            Object sender,
            X509Certificate certificate,
            X509Chain chain,
            SslPolicyErrors sslPolicyErrors)
{

    if (sslPolicyErrors == SslPolicyErrors.None)
        return true;

    if (IsAprrovedByMyApplication(sender, certificate))  // <-- no matter what the check here is
       return true;
    else 
       return false;  // <-- here I'd like to call the default Windwos handler rather than returning 'false'
}

But when there're some policy errors, and the site I am connecting to is not approved by application, the Exception is thrown. The problem here is that it differs from standard Windows behavior.

Consider this site: https://www.dscoduc.com/

It's certificate has an unknown issuer, and therefore untrusted. I have added it with MMC to the Local Copmuter's Trusted People (it's Windows 7).

If I run this code without overriding certificate validation callback:

HttpWebRequest http = (HttpWebRequest)HttpWebRequest.Create("https://www.dscoduc.com/");
using (WebResponse resp = http.GetResponse())
{
    using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
    {
        string htmlpage = sr.ReadToEnd();
    }
}

it connects successfully. It means that Windows default validator decided to trust this certificate.

But once I override the ServerCertificateValidationCallback, my callback is called with SslPolicyErrors.RemoteCertificateChainErrors and the chain contains one element with status X509ChainStatusFlags.PartialChain (in fact I would expect to receive no errors here, becuase current cert is supposed to be trusted)

This site is not included in my trusted list, and do not want to return 'true' from my callback. But I don't want to return 'false' neither, or I'll get an Exception: "The remote certificate is invalid according to the validation procedure", which is obviously not expected for https://www.dscoduc.com/, becuase it's added to Trusted People store, and is approved by Windows when certificate callback is not overriden. So I want Windows to take the default validation procedure for this site. I don't want to look into Windows Trusted stores myself and go through all the chain elements, because it's already (and hopefully correctly) implemented in Windows.

In other words, I need to explicitly trust to sites approvied by the user (wich are stored somewhere in his settings), and call the default certification check for all others.

The default value for ServicePointManager.ServerCertificateValidationCallback is null, so there's no 'default' callback for me to call later. How should I call this 'default' certificate handler?

Thanks

解决方案

It's less difficult than you think to walk the chain from within your callback.

Have a look at http://msdn.microsoft.com/en-us/library/dd633677(v=exchg.80).aspx

The code in that sample examines the certificate chain to work out if the certificate is self-signed and if so, trust it. You could adapt that to accept a PartialChain instead or as well. You'd be looking to do something like this:

if (status.Status == X509ChainStatusFlags.PartialChain ||
    (certificate.Subject == certificate.Issuer &&
     status.Status == X509ChainStatusFlags.UntrustedRoot)
{
    // Certificates with a broken chain and
    // self-signed certificates with an untrusted root are valid. 
    continue;
}
else if (status.Status != X509ChainStatusFlags.NoError)
{
    // If there are any other errors in the certificate chain,
    // the certificate is invalid, so the method returns false.
    return false;
}

Alternatively, inspect the Subject property:

private static bool CertificateValidationCallBack(
    object sender,
    System.Security.Cryptography.X509Certificates.X509Certificate certificate,
    System.Security.Cryptography.X509Certificates.X509Chain chain,
    System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
    return certificate.Subject.Contains(".dsoduc.com");
}

这篇关于当在C#中覆盖ServicePointManager.ServerCertificateValidationCallback时,如何调用默认证书检查?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆