// // // obj is SslStream public bool ValidateClientCertificate(object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { m_log.InfoFormat("[NSL CERT VERIFY]: ValidateClientCertificate: Policy is ({0})", sslPolicyErrors); X509Certificate2 certificate2 = new X509Certificate2(certificate); string simplename = certificate2.GetNameInfo(X509NameType.SimpleName, false); //m_log.InfoFormat("[NSL CERT VERIFY]: ValidateClientCertificate: Simple Name is \"{0}\"", simplename); /* * // RemoteCertificateNotAvailableはエラーとする. * if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable)==SslPolicyErrors.RemoteCertificateNotAvailable) { * m_log.InfoFormat("[NSL CERT VERIFY]: ValidateClientCertificate: Policy Error! {0}", sslPolicyErrors); * return false; * } */ // None, ChainErrors 以外は全てエラーとする. if (sslPolicyErrors != SslPolicyErrors.None && sslPolicyErrors != SslPolicyErrors.RemoteCertificateChainErrors) { m_log.InfoFormat("[NSL 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 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 CERT VERIFY]: Valid Client Certification for \"{0}\"", simplename); } else { m_log.InfoFormat("[NSL CERT VERIFY]: Failed to Verify Client Certification for \"{0}\"", simplename); } return(valid); }
/// <summary> /// Validate Client Certificate Callback Function /// </summary> /// <param name="obj"></param> /// <param name="certificate"></param> /// <param name="chain"></param> /// <param name="sslPolicyErrors"></param> /// <returns></returns> public bool ValidateClientCertificate(object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { m_log.InfoFormat("[NSL CLIENT CERT VERIFY]: ValidateClientCertificate: Start."); if (certificate == null) { m_log.InfoFormat("[NSL CLIENT CERT VERIFY]: ValidateClientCertificate: Client does not have a Certificate!"); return(false); } X509Certificate2 certificate2 = new X509Certificate2(certificate); string commonname = certificate2.GetNameInfo(X509NameType.SimpleName, false); m_log.InfoFormat("[NSL CLIENT CERT VERIFY]: ValidateClientCertificate: Common Name is \"{0}\"", commonname); // 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}", commonname, entry.RevocationDate.ToString()); return(false); } } bool valid = CheckPrivateChain(certificate2); if (valid) { m_log.InfoFormat("[NSL CLIENT CERT VERIFY]: Valid Client Certification for \"{0}\"", commonname); } else { m_log.InfoFormat("[NSL CLIENT CERT VERIFY]: Failed to Verify Client Certification for \"{0}\"", commonname); } return(valid); }
private bool ProcessCrlEntryExtensions(MX.X509Crl.X509CrlEntry entry) { foreach (MX.X509Extension ext in entry.Extensions) { if (ext.Critical) { switch (ext.Oid) { case "2.5.29.21": // cRLReason // we processed/know about this extension break; default: return(false); } } } return(true); }
private X509ChainStatusFlags CheckRevocation(X509Certificate2 certificate, X509Certificate2 ca_cert, bool online) { // change this if/when we support OCSP X509KeyUsageExtension kue = (ca_cert.Extensions["2.5.29.15"] as X509KeyUsageExtension); if (kue != null) { // ... verify CrlSign is set X509KeyUsageFlags success = X509KeyUsageFlags.CrlSign; if ((kue.KeyUsages & success) != success) { // FIXME - we should try to find an alternative CA that has the CrlSign bit return(X509ChainStatusFlags.RevocationStatusUnknown); } } MX.X509Crl crl = FindCrl(ca_cert); if ((crl == null) && online) { // FIXME - download and install new CRL // then you get a second chance // crl = FindCrl (ca_cert, ref valid, ref out_of_date); // We need to get the subjectAltName and an URI from there (or use OCSP) // X509KeyUsageExtension subjectAltName = (ca_cert.Extensions["2.5.29.17"] as X509KeyUsageExtension); } if (crl != null) { // validate the digital signature on the CRL using the CA public key // note #1: we can't use X509Crl.VerifySignature(X509Certificate) because it duplicates // checks and we loose the "why" of the failure // note #2: we do this before other tests as an invalid signature could be a hacked CRL // (so anything within can't be trusted) if (!crl.VerifySignature(ca_cert.PublicKey.Key)) { return(X509ChainStatusFlags.RevocationStatusUnknown); } MX.X509Crl.X509CrlEntry entry = crl.GetCrlEntry(certificate.MonoCertificate); if (entry != null) { // We have an entry for this CRL that includes an unknown CRITICAL extension // See [X.509 7.3] NOTE 4 if (!ProcessCrlEntryExtensions(entry)) { return(X509ChainStatusFlags.Revoked); } // FIXME - a little more is involved if (entry.RevocationDate <= ChainPolicy.VerificationTime) { return(X509ChainStatusFlags.Revoked); } } // are we overdue for a CRL update ? if so we can't be sure of any certificate status if (crl.NextUpdate < ChainPolicy.VerificationTime) { return(X509ChainStatusFlags.RevocationStatusUnknown | X509ChainStatusFlags.OfflineRevocation); } // we have a CRL that includes an unknown CRITICAL extension // we put this check at the end so we do not "hide" any Revoked flags if (!ProcessCrlExtensions(crl)) { return(X509ChainStatusFlags.RevocationStatusUnknown); } } else { return(X509ChainStatusFlags.RevocationStatusUnknown); } return(X509ChainStatusFlags.NoError); }