browser/base/content/pageinfo/security.js

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

michael@0 1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 var security = {
michael@0 7 // Display the server certificate (static)
michael@0 8 viewCert : function () {
michael@0 9 var cert = security._cert;
michael@0 10 viewCertHelper(window, cert);
michael@0 11 },
michael@0 12
michael@0 13 _getSecurityInfo : function() {
michael@0 14 const nsIX509Cert = Components.interfaces.nsIX509Cert;
michael@0 15 const nsIX509CertDB = Components.interfaces.nsIX509CertDB;
michael@0 16 const nsX509CertDB = "@mozilla.org/security/x509certdb;1";
michael@0 17 const nsISSLStatusProvider = Components.interfaces.nsISSLStatusProvider;
michael@0 18 const nsISSLStatus = Components.interfaces.nsISSLStatus;
michael@0 19
michael@0 20 // We don't have separate info for a frame, return null until further notice
michael@0 21 // (see bug 138479)
michael@0 22 if (gWindow != gWindow.top)
michael@0 23 return null;
michael@0 24
michael@0 25 var hName = null;
michael@0 26 try {
michael@0 27 hName = gWindow.location.host;
michael@0 28 }
michael@0 29 catch (exception) { }
michael@0 30
michael@0 31 var ui = security._getSecurityUI();
michael@0 32 if (!ui)
michael@0 33 return null;
michael@0 34
michael@0 35 var isBroken =
michael@0 36 (ui.state & Components.interfaces.nsIWebProgressListener.STATE_IS_BROKEN);
michael@0 37 var isInsecure =
michael@0 38 (ui.state & Components.interfaces.nsIWebProgressListener.STATE_IS_INSECURE);
michael@0 39 var isEV =
michael@0 40 (ui.state & Components.interfaces.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL);
michael@0 41 ui.QueryInterface(nsISSLStatusProvider);
michael@0 42 var status = ui.SSLStatus;
michael@0 43
michael@0 44 if (!isInsecure && status) {
michael@0 45 status.QueryInterface(nsISSLStatus);
michael@0 46 var cert = status.serverCert;
michael@0 47 var issuerName =
michael@0 48 this.mapIssuerOrganization(cert.issuerOrganization) || cert.issuerName;
michael@0 49
michael@0 50 var retval = {
michael@0 51 hostName : hName,
michael@0 52 cAName : issuerName,
michael@0 53 encryptionAlgorithm : undefined,
michael@0 54 encryptionStrength : undefined,
michael@0 55 isBroken : isBroken,
michael@0 56 isEV : isEV,
michael@0 57 cert : cert,
michael@0 58 fullLocation : gWindow.location
michael@0 59 };
michael@0 60
michael@0 61 try {
michael@0 62 retval.encryptionAlgorithm = status.cipherName;
michael@0 63 retval.encryptionStrength = status.secretKeyLength;
michael@0 64 }
michael@0 65 catch (e) {
michael@0 66 }
michael@0 67
michael@0 68 return retval;
michael@0 69 } else {
michael@0 70 return {
michael@0 71 hostName : hName,
michael@0 72 cAName : "",
michael@0 73 encryptionAlgorithm : "",
michael@0 74 encryptionStrength : 0,
michael@0 75 isBroken : isBroken,
michael@0 76 isEV : isEV,
michael@0 77 cert : null,
michael@0 78 fullLocation : gWindow.location
michael@0 79 };
michael@0 80 }
michael@0 81 },
michael@0 82
michael@0 83 // Find the secureBrowserUI object (if present)
michael@0 84 _getSecurityUI : function() {
michael@0 85 if (window.opener.gBrowser)
michael@0 86 return window.opener.gBrowser.securityUI;
michael@0 87 return null;
michael@0 88 },
michael@0 89
michael@0 90 // Interface for mapping a certificate issuer organization to
michael@0 91 // the value to be displayed.
michael@0 92 // Bug 82017 - this implementation should be moved to pipnss C++ code
michael@0 93 mapIssuerOrganization: function(name) {
michael@0 94 if (!name) return null;
michael@0 95
michael@0 96 if (name == "RSA Data Security, Inc.") return "Verisign, Inc.";
michael@0 97
michael@0 98 // No mapping required
michael@0 99 return name;
michael@0 100 },
michael@0 101
michael@0 102 /**
michael@0 103 * Open the cookie manager window
michael@0 104 */
michael@0 105 viewCookies : function()
michael@0 106 {
michael@0 107 var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
michael@0 108 .getService(Components.interfaces.nsIWindowMediator);
michael@0 109 var win = wm.getMostRecentWindow("Browser:Cookies");
michael@0 110 var eTLDService = Components.classes["@mozilla.org/network/effective-tld-service;1"].
michael@0 111 getService(Components.interfaces.nsIEffectiveTLDService);
michael@0 112
michael@0 113 var eTLD;
michael@0 114 var uri = gDocument.documentURIObject;
michael@0 115 try {
michael@0 116 eTLD = eTLDService.getBaseDomain(uri);
michael@0 117 }
michael@0 118 catch (e) {
michael@0 119 // getBaseDomain will fail if the host is an IP address or is empty
michael@0 120 eTLD = uri.asciiHost;
michael@0 121 }
michael@0 122
michael@0 123 if (win) {
michael@0 124 win.gCookiesWindow.setFilter(eTLD);
michael@0 125 win.focus();
michael@0 126 }
michael@0 127 else
michael@0 128 window.openDialog("chrome://browser/content/preferences/cookies.xul",
michael@0 129 "Browser:Cookies", "", {filterString : eTLD});
michael@0 130 },
michael@0 131
michael@0 132 /**
michael@0 133 * Open the login manager window
michael@0 134 */
michael@0 135 viewPasswords : function()
michael@0 136 {
michael@0 137 var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
michael@0 138 .getService(Components.interfaces.nsIWindowMediator);
michael@0 139 var win = wm.getMostRecentWindow("Toolkit:PasswordManager");
michael@0 140 if (win) {
michael@0 141 win.setFilter(this._getSecurityInfo().hostName);
michael@0 142 win.focus();
michael@0 143 }
michael@0 144 else
michael@0 145 window.openDialog("chrome://passwordmgr/content/passwordManager.xul",
michael@0 146 "Toolkit:PasswordManager", "",
michael@0 147 {filterString : this._getSecurityInfo().hostName});
michael@0 148 },
michael@0 149
michael@0 150 _cert : null
michael@0 151 };
michael@0 152
michael@0 153 function securityOnLoad() {
michael@0 154 var info = security._getSecurityInfo();
michael@0 155 if (!info) {
michael@0 156 document.getElementById("securityTab").hidden = true;
michael@0 157 document.getElementById("securityBox").collapsed = true;
michael@0 158 return;
michael@0 159 }
michael@0 160 else {
michael@0 161 document.getElementById("securityTab").hidden = false;
michael@0 162 document.getElementById("securityBox").collapsed = false;
michael@0 163 }
michael@0 164
michael@0 165 const pageInfoBundle = document.getElementById("pageinfobundle");
michael@0 166
michael@0 167 /* Set Identity section text */
michael@0 168 setText("security-identity-domain-value", info.hostName);
michael@0 169
michael@0 170 var owner, verifier, generalPageIdentityString;
michael@0 171 if (info.cert && !info.isBroken) {
michael@0 172 // Try to pull out meaningful values. Technically these fields are optional
michael@0 173 // so we'll employ fallbacks where appropriate. The EV spec states that Org
michael@0 174 // fields must be specified for subject and issuer so that case is simpler.
michael@0 175 if (info.isEV) {
michael@0 176 owner = info.cert.organization;
michael@0 177 verifier = security.mapIssuerOrganization(info.cAName);
michael@0 178 generalPageIdentityString = pageInfoBundle.getFormattedString("generalSiteIdentity",
michael@0 179 [owner, verifier]);
michael@0 180 }
michael@0 181 else {
michael@0 182 // Technically, a non-EV cert might specify an owner in the O field or not,
michael@0 183 // depending on the CA's issuing policies. However we don't have any programmatic
michael@0 184 // way to tell those apart, and no policy way to establish which organization
michael@0 185 // vetting standards are good enough (that's what EV is for) so we default to
michael@0 186 // treating these certs as domain-validated only.
michael@0 187 owner = pageInfoBundle.getString("securityNoOwner");
michael@0 188 verifier = security.mapIssuerOrganization(info.cAName ||
michael@0 189 info.cert.issuerCommonName ||
michael@0 190 info.cert.issuerName);
michael@0 191 generalPageIdentityString = owner;
michael@0 192 }
michael@0 193 }
michael@0 194 else {
michael@0 195 // We don't have valid identity credentials.
michael@0 196 owner = pageInfoBundle.getString("securityNoOwner");
michael@0 197 verifier = pageInfoBundle.getString("notset");
michael@0 198 generalPageIdentityString = owner;
michael@0 199 }
michael@0 200
michael@0 201 setText("security-identity-owner-value", owner);
michael@0 202 setText("security-identity-verifier-value", verifier);
michael@0 203 setText("general-security-identity", generalPageIdentityString);
michael@0 204
michael@0 205 /* Manage the View Cert button*/
michael@0 206 var viewCert = document.getElementById("security-view-cert");
michael@0 207 if (info.cert) {
michael@0 208 security._cert = info.cert;
michael@0 209 viewCert.collapsed = false;
michael@0 210 }
michael@0 211 else
michael@0 212 viewCert.collapsed = true;
michael@0 213
michael@0 214 /* Set Privacy & History section text */
michael@0 215 var yesStr = pageInfoBundle.getString("yes");
michael@0 216 var noStr = pageInfoBundle.getString("no");
michael@0 217
michael@0 218 var uri = gDocument.documentURIObject;
michael@0 219 setText("security-privacy-cookies-value",
michael@0 220 hostHasCookies(uri) ? yesStr : noStr);
michael@0 221 setText("security-privacy-passwords-value",
michael@0 222 realmHasPasswords(uri) ? yesStr : noStr);
michael@0 223
michael@0 224 var visitCount = previousVisitCount(info.hostName);
michael@0 225 if(visitCount > 1) {
michael@0 226 setText("security-privacy-history-value",
michael@0 227 pageInfoBundle.getFormattedString("securityNVisits", [visitCount.toLocaleString()]));
michael@0 228 }
michael@0 229 else if (visitCount == 1) {
michael@0 230 setText("security-privacy-history-value",
michael@0 231 pageInfoBundle.getString("securityOneVisit"));
michael@0 232 }
michael@0 233 else {
michael@0 234 setText("security-privacy-history-value", noStr);
michael@0 235 }
michael@0 236
michael@0 237 /* Set the Technical Detail section messages */
michael@0 238 const pkiBundle = document.getElementById("pkiBundle");
michael@0 239 var hdr;
michael@0 240 var msg1;
michael@0 241 var msg2;
michael@0 242
michael@0 243 if (info.isBroken) {
michael@0 244 hdr = pkiBundle.getString("pageInfo_MixedContent");
michael@0 245 msg1 = pkiBundle.getString("pageInfo_Privacy_Mixed1");
michael@0 246 msg2 = pkiBundle.getString("pageInfo_Privacy_None2");
michael@0 247 }
michael@0 248 else if (info.encryptionStrength >= 90) {
michael@0 249 hdr = pkiBundle.getFormattedString("pageInfo_StrongEncryptionWithBits",
michael@0 250 [info.encryptionAlgorithm, info.encryptionStrength + ""]);
michael@0 251 msg1 = pkiBundle.getString("pageInfo_Privacy_Strong1");
michael@0 252 msg2 = pkiBundle.getString("pageInfo_Privacy_Strong2");
michael@0 253 security._cert = info.cert;
michael@0 254 }
michael@0 255 else if (info.encryptionStrength > 0) {
michael@0 256 hdr = pkiBundle.getFormattedString("pageInfo_WeakEncryptionWithBits",
michael@0 257 [info.encryptionAlgorithm, info.encryptionStrength + ""]);
michael@0 258 msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_Weak1", [info.hostName]);
michael@0 259 msg2 = pkiBundle.getString("pageInfo_Privacy_Weak2");
michael@0 260 }
michael@0 261 else {
michael@0 262 hdr = pkiBundle.getString("pageInfo_NoEncryption");
michael@0 263 if (info.hostName != null)
michael@0 264 msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_None1", [info.hostName]);
michael@0 265 else
michael@0 266 msg1 = pkiBundle.getString("pageInfo_Privacy_None3");
michael@0 267 msg2 = pkiBundle.getString("pageInfo_Privacy_None2");
michael@0 268 }
michael@0 269 setText("security-technical-shortform", hdr);
michael@0 270 setText("security-technical-longform1", msg1);
michael@0 271 setText("security-technical-longform2", msg2);
michael@0 272 setText("general-security-privacy", hdr);
michael@0 273 }
michael@0 274
michael@0 275 function setText(id, value)
michael@0 276 {
michael@0 277 var element = document.getElementById(id);
michael@0 278 if (!element)
michael@0 279 return;
michael@0 280 if (element.localName == "textbox" || element.localName == "label")
michael@0 281 element.value = value;
michael@0 282 else {
michael@0 283 if (element.hasChildNodes())
michael@0 284 element.removeChild(element.firstChild);
michael@0 285 var textNode = document.createTextNode(value);
michael@0 286 element.appendChild(textNode);
michael@0 287 }
michael@0 288 }
michael@0 289
michael@0 290 function viewCertHelper(parent, cert)
michael@0 291 {
michael@0 292 if (!cert)
michael@0 293 return;
michael@0 294
michael@0 295 var cd = Components.classes[CERTIFICATEDIALOGS_CONTRACTID].getService(nsICertificateDialogs);
michael@0 296 cd.viewCert(parent, cert);
michael@0 297 }
michael@0 298
michael@0 299 /**
michael@0 300 * Return true iff we have cookies for uri
michael@0 301 */
michael@0 302 function hostHasCookies(uri) {
michael@0 303 var cookieManager = Components.classes["@mozilla.org/cookiemanager;1"]
michael@0 304 .getService(Components.interfaces.nsICookieManager2);
michael@0 305
michael@0 306 return cookieManager.countCookiesFromHost(uri.asciiHost) > 0;
michael@0 307 }
michael@0 308
michael@0 309 /**
michael@0 310 * Return true iff realm (proto://host:port) (extracted from uri) has
michael@0 311 * saved passwords
michael@0 312 */
michael@0 313 function realmHasPasswords(uri) {
michael@0 314 var passwordManager = Components.classes["@mozilla.org/login-manager;1"]
michael@0 315 .getService(Components.interfaces.nsILoginManager);
michael@0 316 return passwordManager.countLogins(uri.prePath, "", "") > 0;
michael@0 317 }
michael@0 318
michael@0 319 /**
michael@0 320 * Return the number of previous visits recorded for host before today.
michael@0 321 *
michael@0 322 * @param host - the domain name to look for in history
michael@0 323 */
michael@0 324 function previousVisitCount(host, endTimeReference) {
michael@0 325 if (!host)
michael@0 326 return false;
michael@0 327
michael@0 328 var historyService = Components.classes["@mozilla.org/browser/nav-history-service;1"]
michael@0 329 .getService(Components.interfaces.nsINavHistoryService);
michael@0 330
michael@0 331 var options = historyService.getNewQueryOptions();
michael@0 332 options.resultType = options.RESULTS_AS_VISIT;
michael@0 333
michael@0 334 // Search for visits to this host before today
michael@0 335 var query = historyService.getNewQuery();
michael@0 336 query.endTimeReference = query.TIME_RELATIVE_TODAY;
michael@0 337 query.endTime = 0;
michael@0 338 query.domain = host;
michael@0 339
michael@0 340 var result = historyService.executeQuery(query, options);
michael@0 341 result.root.containerOpen = true;
michael@0 342 var cc = result.root.childCount;
michael@0 343 result.root.containerOpen = false;
michael@0 344 return cc;
michael@0 345 }

mercurial