/*
* Copyright (c) Contributors, http://www.nsl.tuis.ac.jp
*
*/
#pragma warning disable S1128 // Unused "using" should be removed
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Net;
using System.Net.Security;
using System.Text;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using log4net;
#pragma warning restore S1128 // Unused "using" should be removed
namespace NSL.Certificate.Tools
{
///
/// class NSL Certificate Verify
///
public class NSLCertificateVerify
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private X509Chain m_chain = null;
private X509Certificate2 m_cacert = null;
private Mono.Security.X509.X509Crl m_clientcrl = null;
///
/// NSL Certificate Verify
///
public NSLCertificateVerify()
{
m_chain = null;
m_cacert = null;
m_clientcrl = null;
}
///
/// NSL Certificate Verify
///
///
public NSLCertificateVerify(string certfile)
{
SetPrivateCA(certfile);
}
///
/// NSL Certificate Verify
///
///
///
public NSLCertificateVerify(string certfile, string crlfile)
{
SetPrivateCA (certfile);
}
///
/// Set Private CA
///
///
public void SetPrivateCA(string certfile)
{
try {
m_cacert = new X509Certificate2(certfile);
}
catch (Exception ex)
{
m_cacert = null;
m_log.ErrorFormat("[SET PRIVATE CA]: CA File reading error [{0}]. {1}", certfile, ex);
}
if (m_cacert!=null) {
m_chain = new X509Chain();
m_chain.ChainPolicy.ExtraStore.Add(m_cacert);
m_chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
m_chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
}
}
///
/// Check Private Chain
///
///
///
public bool CheckPrivateChain(X509Certificate2 cert)
{
if (m_chain==null || m_cacert==null) {
return false;
}
bool ret = m_chain.Build((X509Certificate2)cert);
if (ret) {
return true;
}
for (int i=0; i
/// Validate Server Certificate
///
///
///
///
///
///
public bool ValidateServerCertificate(object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (obj is HttpWebRequest)
{
HttpWebRequest Request = (HttpWebRequest)obj;
string noVerify = Request.Headers.Get("NoVerifyCert");
if (noVerify!=null && noVerify.ToLower()=="true")
{
return true;
}
}
X509Certificate2 certificate2 = new X509Certificate2(certificate);
string simplename = certificate2.GetNameInfo(X509NameType.SimpleName, false);
// None, ChainErrors Error except for.
if (sslPolicyErrors!=SslPolicyErrors.None && sslPolicyErrors!=SslPolicyErrors.RemoteCertificateChainErrors) {
m_log.InfoFormat("[NSL SERVER CERT VERIFY]: ValidateServerCertificate: Policy Error! {0}", sslPolicyErrors);
return false;
}
bool valid = CheckPrivateChain(certificate2);
if (valid) {
m_log.InfoFormat("[NSL SERVER CERT VERIFY]: Valid Server Certification for \"{0}\"", simplename);
}
else {
m_log.InfoFormat("[NSL SERVER CERT VERIFY]: Failed to Verify Server Certification for \"{0}\"", simplename);
}
return valid;
}
///
/// Validate Client Certificate
///
///
///
///
///
///
public bool ValidateClientCertificate(object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
X509Certificate2 certificate2 = new X509Certificate2(certificate);
string simplename = certificate2.GetNameInfo(X509NameType.SimpleName, false);
// None, ChainErrors 以外は全てエラーとする.
if (sslPolicyErrors!=SslPolicyErrors.None && sslPolicyErrors!=SslPolicyErrors.RemoteCertificateChainErrors) {
m_log.InfoFormat("[NSL CLIENT CERT VERIFY]: ValidateClientCertificate: Policy Error! {0}", sslPolicyErrors);
return false;
}
// check CRL
if (m_clientcrl!=null) {
Mono.Security.X509.X509Certificate monocert = new Mono.Security.X509.X509Certificate(certificate.GetRawCertData());
Mono.Security.X509.X509Crl.X509CrlEntry entry = m_clientcrl.GetCrlEntry(monocert);
if (entry!=null) {
m_log.InfoFormat("[NSL CLIENT CERT VERIFY]: Common Name \"{0}\" was revoked at {1}", simplename, entry.RevocationDate.ToString());
return false;
}
}
bool valid = CheckPrivateChain(certificate2);
if (valid) {
m_log.InfoFormat("[NSL CLIENT CERT VERIFY]: Valid Client Certification for \"{0}\"", simplename);
}
else {
m_log.InfoFormat("[NSL CLIENT CERT VERIFY]: Failed to Verify Client Certification for \"{0}\"", simplename);
}
return valid;
}
}
///
/// class NSL Certificate Policy
///
public class NSLCertificatePolicy : ICertificatePolicy
{
///
/// Check Validation Result
///
///
///
///
///
///
public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem)
{
if (certificateProblem == 0 || //normal
certificateProblem == -2146762487 || //Not trusted?
certificateProblem == -2146762495 || //Expired
certificateProblem == -2146762481) { //Incorrect name?
return true;
}
else {
return false;
}
}
}
}