Skip to content

Instantly share code, notes, and snippets.

@cKlee
Created January 18, 2019 06:00
Show Gist options
  • Save cKlee/31921f316a82a224934f519adcb63b51 to your computer and use it in GitHub Desktop.
Save cKlee/31921f316a82a224934f519adcb63b51 to your computer and use it in GitHub Desktop.
Checking Status and Errors for XMLHTTP(S) Requests
var Ci = Components.interfaces;
var Cc = Components.classes;
function createTCPErrorFromFailedXHR(xhr) {
var status = xhr.channel.QueryInterface(Ci.nsIRequest).status;
var errType;
if ((status & 0xff0000) === 0x5a0000) { // Security module
const nsINSSErrorsService = Ci.nsINSSErrorsService;
var nssErrorsService = Cc['@mozilla.org/nss_errors_service;1'].getService(nsINSSErrorsService);
var errorClass;
// getErrorClass will throw a generic NS_ERROR_FAILURE if the error code is
// somehow not in the set of covered errors.
try {
errorClass = nssErrorsService.getErrorClass(status);
} catch (ex) {
//catching security protocol exception
errorClass = 'SecurityProtocol';
}
if (errorClass == nsINSSErrorsService.ERROR_CLASS_BAD_CERT) {
errType = 'SecurityCertificate';
} else {
errType = 'SecurityProtocol';
}
// NSS_SEC errors (happen below the base value because of negative vals)
if ((status & 0xffff) < Math.abs(nsINSSErrorsService.NSS_SEC_ERROR_BASE)) {
// The bases are actually negative, so in our positive numeric space, we
// need to subtract the base off our value.
var nssErr = Math.abs(nsINSSErrorsService.NSS_SEC_ERROR_BASE) - (status & 0xffff);
switch (nssErr) {
case 11: // SEC_ERROR_EXPIRED_CERTIFICATE, sec(11)
errName = 'SecurityExpiredCertificateError';
break;
case 12: // SEC_ERROR_REVOKED_CERTIFICATE, sec(12)
errName = 'SecurityRevokedCertificateError';
break;
// per bsmith, we will be unable to tell these errors apart very soon,
// so it makes sense to just folder them all together already.
case 13: // SEC_ERROR_UNKNOWN_ISSUER, sec(13)
case 20: // SEC_ERROR_UNTRUSTED_ISSUER, sec(20)
case 21: // SEC_ERROR_UNTRUSTED_CERT, sec(21)
case 36: // SEC_ERROR_CA_CERT_INVALID, sec(36)
errName = 'SecurityUntrustedCertificateIssuerError';
break;
case 90: // SEC_ERROR_INADEQUATE_KEY_USAGE, sec(90)
errName = 'SecurityInadequateKeyUsageError';
break;
case 176: // SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED, sec(176)
errName = 'SecurityCertificateSignatureAlgorithmDisabledError';
break;
default:
errName = 'SecurityError';
break;
}
} else {
// Calculating the difference
var sslErr = Math.abs(nsINSSErrorsService.NSS_SSL_ERROR_BASE) - (status & 0xffff);
switch (sslErr) {
case 3: // SSL_ERROR_NO_CERTIFICATE, ssl(3)
errName = 'SecurityNoCertificateError';
break;
case 4: // SSL_ERROR_BAD_CERTIFICATE, ssl(4)
errName = 'SecurityBadCertificateError';
break;
case 8: // SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE, ssl(8)
errName = 'SecurityUnsupportedCertificateTypeError';
break;
case 9: // SSL_ERROR_UNSUPPORTED_VERSION, ssl(9)
errName = 'SecurityUnsupportedTLSVersionError';
break;
case 12: // SSL_ERROR_BAD_CERT_DOMAIN, ssl(12)
errName = 'SecurityCertificateDomainMismatchError';
break;
default:
errName = 'SecurityError';
break;
}
}
} else {
errType = 'Network';
switch (status) {
// connect to host:port failed
case 0x804B000C: // NS_ERROR_CONNECTION_REFUSED, network(13)
errName = 'ConnectionRefusedError';
break;
// network timeout error
case 0x804B000E: // NS_ERROR_NET_TIMEOUT, network(14)
errName = 'NetworkTimeoutError';
break;
// hostname lookup failed
case 0x804B001E: // NS_ERROR_UNKNOWN_HOST, network(30)
errName = 'DomainNotFoundError';
break;
case 0x804B0047: // NS_ERROR_NET_INTERRUPT, network(71)
errName = 'NetworkInterruptError';
break;
default:
errName = 'NetworkError';
break;
}
}
// XXX we have no TCPError implementation right now because it's really hard to
// do on b2g18. On mozilla-central we want a proper TCPError that ideally
// sub-classes DOMError. Bug 867872 has been filed to implement this and
// contains a documented TCPError.webidl that maps all the error codes we use in
// this file to slightly more readable explanations.
//var error = Cc["@mozilla.org/dom-error;1"].createInstance(Ci.nsIDOMDOMError);
//error.wrappedJSObject.init(errName);
var error = {};
error.name = errName;
return error;
// XXX: errType goes unused
}
function dumpSecurityInfo(xhr, error) {
var channel = xhr.channel;
var dump;
try {
dump = "Connection status:\n";
if (!error) {
dump += "\tsucceeded\n";
} else {
dump += "\tfailed: " + error.name + "\n";
}
var secInfo = channel.securityInfo;
// Print general connection security state
dump += "Security Information:\n";
if (secInfo) {
secInfo.QueryInterface(Ci.nsITransportSecurityInfo);
dump += "\tSecurity state of connection: ";
// Check security state flags
if ((secInfo.securityState & Ci.nsIWebProgressListener.STATE_IS_SECURE)
== Ci.nsIWebProgressListener.STATE_IS_SECURE) {
dump += "secure connection\n";
} else if ((secInfo.securityState & Ci.nsIWebProgressListener.STATE_IS_INSECURE)
== Ci.nsIWebProgressListener.STATE_IS_INSECURE) {
dump += "insecure connection\n";
} else if ((secInfo.securityState & Ci.nsIWebProgressListener.STATE_IS_BROKEN)
== Ci.nsIWebProgressListener.STATE_IS_BROKEN) {
dump += "unknown\n";
dump += "\tSecurity description: " + secInfo.shortSecurityDescription + "\n";
dump += "\tSecurity error message: " + secInfo.errorMessage + "\n";
}
} else {
dump += "\tNo security info available for this channel\n";
}
// Print SSL certificate details
if (secInfo instanceof Ci.nsISSLStatusProvider) {
var cert = secInfo.QueryInterface(Ci.nsISSLStatusProvider)
.SSLStatus.QueryInterface(Ci.nsISSLStatus).serverCert;
dump += "\tCommon name (CN) = " + cert.commonName + "\n";
dump += "\tIssuer = " + cert.issuerOrganization + "\n";
dump += "\tOrganisation = " + cert.organization + "\n";
dump += "\tSHA1 fingerprint = " + cert.sha1Fingerprint + "\n";
var validity = cert.validity.QueryInterface(Ci.nsIX509CertValidity);
dump += "\tValid from " + validity.notBeforeGMT + "\n";
dump += "\tValid until " + validity.notAfterGMT + "\n";
}
} catch (err) {
__zdbError(err);
}
__zdbError(dump);
}
function testy() {
var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance();
req.mozSystem = false;
req.open('GET', 'https://www.gbv.de/bibliotheken/verbundbibliotheken/02Verbund/02Verbundsystem/02WinIBW/WinIBW3/w3update37/update.xml', true);
req.addEventListener("error",
function (e) {
var error = createTCPErrorFromFailedXHR(req);
dumpSecurityInfo(req, error);
},
false);
req.onload = function (e) {
dumpSecurityInfo(req);
};
req.send(null);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment