Last active
August 29, 2015 14:14
-
-
Save jay/17940f346ab5a164a8c2 to your computer and use it in GitHub Desktop.
Excerpt from my Fiddler CustomRules.js of ValidateCert. https://groups.google.com/forum/#!topic/httpfiddler/cjGlrTWnnZk
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static function Main() { | |
var today: Date = new Date(); | |
FiddlerObject.StatusText = " CustomRules.js was loaded at: " + today; | |
// Uncomment to add a "Server" column containing the response "Server" header, if present | |
// FiddlerObject.UI.lvSessions.AddBoundColumn("Server", 50, "@response.server"); | |
// https://groups.google.com/forum/#!topic/httpfiddler/RIjfLBU58Io | |
CONFIG.oAcceptedServerHTTPSProtocols = System.Security.Authentication.SslProtocols.Tls | |
| System.Security.Authentication.SslProtocols.Tls11 | |
| System.Security.Authentication.SslProtocols.Tls12; | |
FiddlerApplication.add_OnValidateServerCertificate(ValidateCert); | |
} | |
static function OnRetire() { | |
FiddlerApplication.remove_OnValidateServerCertificate(ValidateCert); | |
} | |
// https://groups.google.com/forum/#!topic/httpfiddler/cjGlrTWnnZk | |
static function ValidateCert(sender, ea: ValidateServerCertificateEventArgs) | |
{ | |
if (ea.CertificatePolicyErrors == System.Net.Security.SslPolicyErrors.None) { | |
return; | |
} | |
var arrIgnoreInvalid: String[] = ["www.whitehouse.gov"]; | |
var host = ea.ExpectedCN.ToLower(); | |
for (var i in arrIgnoreInvalid) { | |
if (host.Equals(arrIgnoreInvalid[i])) { | |
ea.ValidityState = CertificateValidity.ForceInvalid; | |
return; | |
} | |
} | |
var store_chain: Boolean = FiddlerApplication.Prefs.GetBoolPref( | |
"fiddler.network.https.storeservercertchain", false); | |
var reason: String = "unknown"; | |
switch (ea.CertificatePolicyErrors) { | |
case System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors: | |
reason = "RemoteCertificateChainErrors"; | |
break; | |
case System.Net.Security.SslPolicyErrors.RemoteCertificateNameMismatch: | |
reason = "RemoteCertificateNameMismatch"; | |
break; | |
case System.Net.Security.SslPolicyErrors.RemoteCertificateNotAvailable: | |
reason = "RemoteCertificateNotAvailable"; | |
break; | |
} | |
var details = "Session #" + ea.Session.id + ": The remote server (" + ea.ExpectedCN | |
+ ") presented a certificate that did not validate, due to " + reason + "." + endl; | |
if (store_chain) { | |
details += endl + "##### CHAIN_START #####" + endl; | |
} | |
var found: Boolean = false; | |
if (store_chain | |
&& ea.ServerCertificateChain != undefined | |
&& ea.ServerCertificateChain.ChainElements != undefined) | |
{ | |
for (var i = 0; i < ea.ServerCertificateChain.ChainElements.Count; i++) { | |
details += endl; | |
/* X509Certificate.Equals method only compares issuer and serial number. | |
For speed we compare those first before the raw data comparison. | |
StructuralComparisons is only .NET 4+ so substitute if necessary: | |
http://stackoverflow.com/questions/43289/comparing-two-byte-arrays-in-net | |
*/ | |
if (!found | |
&& ea.ServerCertificate != undefined | |
&& ea.ServerCertificateChain.ChainElements[i].Certificate != undefined | |
&& ea.ServerCertificate.Equals( | |
ea.ServerCertificateChain.ChainElements[i].Certificate) | |
&& System.Collections.StructuralComparisons.StructuralEqualityComparer.Equals( | |
ea.ServerCertificate.GetRawCertData(), | |
ea.ServerCertificateChain.ChainElements[i].Certificate.GetRawCertData())) | |
{ | |
found = true; | |
details += GetServerCertSessionString(ea.Session, ea.ExpectedCN); | |
} | |
details += GetCertDetailString( | |
ea.ServerCertificateChain.ChainElements[i].Certificate, | |
ea.ServerCertificateChain.ChainElements[i].ChainElementStatus); | |
} | |
} | |
if (store_chain) { | |
details += endl + "##### CHAIN_END #####" + endl; | |
} | |
if (!found) { | |
details += endl; | |
if (store_chain) { | |
details += "WARNING: The server's certificate was not found in the chain." + endl | |
+ endl; | |
} | |
details += GetServerCertSessionString(ea.Session, ea.ExpectedCN) | |
+ GetCertDetailString(ea.ServerCertificate); | |
} | |
ea.Session["cert_validation_details"] = details; | |
// For tunnels append details to the request data so they're visible in the inspector | |
if (ea.Session.isTunnel) | |
{ | |
var a: Byte[] = ea.Session.requestBodyBytes; | |
var b: Byte[] = System.Text.Encoding.UTF8.GetBytes(details); | |
ea.Session.requestBodyBytes = new Byte[a.Length + b.Length]; | |
System.Buffer.BlockCopy(a, 0, ea.Session.requestBodyBytes, 0, a.Length); | |
System.Buffer.BlockCopy(b, 0, ea.Session.requestBodyBytes, a.Length, b.Length); | |
} | |
FiddlerObject.log(details); | |
} | |
static function GetServerCertSessionString(oSession: Session, expectedCN: String): String | |
{ | |
var comments = "## Server certificate from " + oSession.hostname + ":" + oSession.port | |
+ " (m_hostIP: " + oSession.m_hostIP + ", expectedCN: " + expectedCN + ")." + endl; | |
comments += "## Timers.ServerConnected: " + oSession.Timers.ServerConnected.ToString() | |
+ " (UTC: " + oSession.Timers.ServerConnected.ToUniversalTime().ToString("o") + ")." | |
+ endl; | |
comments += "##" + endl; | |
return comments; | |
} | |
static function GetCertDetailString( | |
cert: System.Security.Cryptography.X509Certificates.X509Certificate, | |
... status: System.Security.Cryptography.X509Certificates.X509ChainStatus[]): String | |
{ | |
var details = ""; | |
if (cert != undefined) { | |
details += "## SUBJECT: " + cert.Subject + endl | |
+ "## ISSUER: " + cert.Issuer + endl | |
+ "## EXPIRES: " + cert.GetExpirationDateString() + endl; | |
} | |
if (status != undefined) { | |
for (var j = 0; j < status.Length; j++) { | |
details += "## STATUS: " + status[j].StatusInformation.Trim() + endl; | |
} | |
} | |
if (cert != undefined) { | |
details += "-----BEGIN CERTIFICATE-----" + endl | |
+ Convert.ToBase64String(cert.GetRawCertData(), | |
Base64FormattingOptions.InsertLineBreaks) + endl | |
+ "-----END CERTIFICATE-----" + endl; | |
} else { | |
details += "## Certificate undefined!" + endl; | |
} | |
return details; | |
} | |
public static ContextAction("Copy certificate validation details") | |
function CopyCertValidationDetails(oSessions: Fiddler.Session[]) | |
{ | |
if (oSessions == undefined || !oSessions.Length) { | |
FiddlerObject.alert("Please select sessions to copy certificate validation details."); | |
return; | |
} | |
var found: int = 0; | |
var border = "============================================================================"; | |
var s = border + endl + endl; | |
for (var i = 0; i < oSessions.Length; i++) { | |
if (!oSessions[i].oFlags.ContainsKey("cert_validation_details")) { | |
continue; | |
} | |
s += oSessions[i].oFlags["cert_validation_details"] + endl + border + endl + endl; | |
found++; | |
} | |
if (!found) { | |
FiddlerObject.alert("The selected sessions don't have certificate validation details."); | |
return; | |
} | |
Utilities.CopyToClipboard(s); | |
} | |
static const endl: String = "\r\n"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment