From 365e58249dc44bee22613cd3be73b6010d101ee0 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Wed, 20 Sep 2017 00:19:42 -0400 Subject: [PATCH] Check for invalid certificate in Zotero.HTTP.request() We were checking for this in the sync API client, but that didn't apply to Amazon S3 for ZFS. --- chrome/content/zotero/xpcom/http.js | 63 +++++++++++++++++++ chrome/content/zotero/xpcom/storage/zfs.js | 5 ++ .../zotero/xpcom/sync/syncAPIClient.js | 35 +---------- 3 files changed, 69 insertions(+), 34 deletions(-) diff --git a/chrome/content/zotero/xpcom/http.js b/chrome/content/zotero/xpcom/http.js index 0218c3953..bb8bbfdd1 100644 --- a/chrome/content/zotero/xpcom/http.js +++ b/chrome/content/zotero/xpcom/http.js @@ -58,6 +58,16 @@ Zotero.HTTP = new function() { }; this.TimeoutException.prototype = Object.create(Error.prototype); + this.SecurityException = function (msg, options = {}) { + this.message = msg; + this.stack = new Error().stack; + for (let i in options) { + this[i] = options[i]; + } + }; + this.SecurityException.prototype = Object.create(Zotero.Error.prototype); + + this.promise = function () { Zotero.debug("Zotero.HTTP.promise() is deprecated -- use Zotero.HTTP.request()", 2); return this.request.apply(this, arguments); @@ -257,6 +267,15 @@ Zotero.HTTP = new function() { msg += ":\n\n" + xmlhttp.responseText; } Zotero.debug(msg, 1); + + try { + _checkSecurity(xmlhttp, channel); + } + catch (e) { + deferred.reject(e); + return; + } + deferred.reject(new Zotero.HTTP.UnexpectedStatusException(xmlhttp, msg)); } }; @@ -934,6 +953,50 @@ Zotero.HTTP = new function() { break; } } + + function _checkSecurity(xmlhttp, channel) { + if (xmlhttp.status != 0 || !channel) { + return; + } + + let secInfo = channel.securityInfo; + if (secInfo instanceof Ci.nsITransportSecurityInfo) { + secInfo.QueryInterface(Ci.nsITransportSecurityInfo); + if ((secInfo.securityState & Ci.nsIWebProgressListener.STATE_IS_INSECURE) + == Ci.nsIWebProgressListener.STATE_IS_INSECURE) { + let url = channel.name; + let ios = Components.classes["@mozilla.org/network/io-service;1"] + .getService(Components.interfaces.nsIIOService); + try { + var uri = ios.newURI(url, null, null); + var host = uri.host; + } + catch (e) { + Zotero.debug(e); + } + let kbURL = 'https://www.zotero.org/support/kb/ssl_certificate_error'; + msg = Zotero.getString('sync.storage.error.webdav.sslCertificateError', host); + dialogButtonText = Zotero.getString('general.moreInformation'); + dialogButtonCallback = function () { + let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + let win = wm.getMostRecentWindow("navigator:browser"); + win.ZoteroPane.loadURI(kbURL, { metaKey: true, shiftKey: true }); + }; + } + else if ((secInfo.securityState & Ci.nsIWebProgressListener.STATE_IS_BROKEN) + == Ci.nsIWebProgressListener.STATE_IS_BROKEN) { + msg = Zotero.getString('sync.error.sslConnectionError'); + } + throw new Zotero.HTTP.SecurityException( + msg, + { + dialogButtonText, + dialogButtonCallback + } + ); + } + } /** * Mimics the window.location/document.location interface, given an nsIURL diff --git a/chrome/content/zotero/xpcom/storage/zfs.js b/chrome/content/zotero/xpcom/storage/zfs.js index 563a78a3c..1362cce6b 100644 --- a/chrome/content/zotero/xpcom/storage/zfs.js +++ b/chrome/content/zotero/xpcom/storage/zfs.js @@ -643,6 +643,11 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = { ); } catch (e) { + // Certificate error + if (e instanceof Zotero.Error) { + throw e; + } + // For timeouts and failures from S3, which happen intermittently, // wait a little and try again let timeoutMessage = "Your socket connection to the server was not read from or " diff --git a/chrome/content/zotero/xpcom/sync/syncAPIClient.js b/chrome/content/zotero/xpcom/sync/syncAPIClient.js index 802f085ea..5a6fce111 100644 --- a/chrome/content/zotero/xpcom/sync/syncAPIClient.js +++ b/chrome/content/zotero/xpcom/sync/syncAPIClient.js @@ -799,40 +799,7 @@ Zotero.Sync.APIClient.prototype = { let dialogButtonText = null; let dialogButtonCallback = null; - // Check SSL cert - if (channel) { - let secInfo = channel.securityInfo; - if (secInfo instanceof Ci.nsITransportSecurityInfo) { - secInfo.QueryInterface(Ci.nsITransportSecurityInfo); - if ((secInfo.securityState & Ci.nsIWebProgressListener.STATE_IS_INSECURE) - == Ci.nsIWebProgressListener.STATE_IS_INSECURE) { - let url = channel.name; - let ios = Components.classes["@mozilla.org/network/io-service;1"] - .getService(Components.interfaces.nsIIOService); - try { - var uri = ios.newURI(url, null, null); - var host = uri.host; - } - catch (e) { - Zotero.debug(e); - } - let kbURL = 'https://www.zotero.org/support/kb/ssl_certificate_error'; - msg = Zotero.getString('sync.storage.error.webdav.sslCertificateError', host); - dialogButtonText = Zotero.getString('general.moreInformation'); - dialogButtonCallback = function () { - let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - let win = wm.getMostRecentWindow("navigator:browser"); - win.ZoteroPane.loadURI(kbURL, { metaKey: true, shiftKey: true }); - }; - } - else if ((secInfo.securityState & Ci.nsIWebProgressListener.STATE_IS_BROKEN) - == Ci.nsIWebProgressListener.STATE_IS_BROKEN) { - msg = Zotero.getString('sync.error.sslConnectionError'); - } - } - } - if (!msg && xmlhttp.status === 0) { + if (xmlhttp.status === 0) { msg = Zotero.getString('sync.error.checkConnection'); } if (!msg) {