1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/base/content/pageinfo/security.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,345 @@ 1.4 +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +var security = { 1.10 + // Display the server certificate (static) 1.11 + viewCert : function () { 1.12 + var cert = security._cert; 1.13 + viewCertHelper(window, cert); 1.14 + }, 1.15 + 1.16 + _getSecurityInfo : function() { 1.17 + const nsIX509Cert = Components.interfaces.nsIX509Cert; 1.18 + const nsIX509CertDB = Components.interfaces.nsIX509CertDB; 1.19 + const nsX509CertDB = "@mozilla.org/security/x509certdb;1"; 1.20 + const nsISSLStatusProvider = Components.interfaces.nsISSLStatusProvider; 1.21 + const nsISSLStatus = Components.interfaces.nsISSLStatus; 1.22 + 1.23 + // We don't have separate info for a frame, return null until further notice 1.24 + // (see bug 138479) 1.25 + if (gWindow != gWindow.top) 1.26 + return null; 1.27 + 1.28 + var hName = null; 1.29 + try { 1.30 + hName = gWindow.location.host; 1.31 + } 1.32 + catch (exception) { } 1.33 + 1.34 + var ui = security._getSecurityUI(); 1.35 + if (!ui) 1.36 + return null; 1.37 + 1.38 + var isBroken = 1.39 + (ui.state & Components.interfaces.nsIWebProgressListener.STATE_IS_BROKEN); 1.40 + var isInsecure = 1.41 + (ui.state & Components.interfaces.nsIWebProgressListener.STATE_IS_INSECURE); 1.42 + var isEV = 1.43 + (ui.state & Components.interfaces.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL); 1.44 + ui.QueryInterface(nsISSLStatusProvider); 1.45 + var status = ui.SSLStatus; 1.46 + 1.47 + if (!isInsecure && status) { 1.48 + status.QueryInterface(nsISSLStatus); 1.49 + var cert = status.serverCert; 1.50 + var issuerName = 1.51 + this.mapIssuerOrganization(cert.issuerOrganization) || cert.issuerName; 1.52 + 1.53 + var retval = { 1.54 + hostName : hName, 1.55 + cAName : issuerName, 1.56 + encryptionAlgorithm : undefined, 1.57 + encryptionStrength : undefined, 1.58 + isBroken : isBroken, 1.59 + isEV : isEV, 1.60 + cert : cert, 1.61 + fullLocation : gWindow.location 1.62 + }; 1.63 + 1.64 + try { 1.65 + retval.encryptionAlgorithm = status.cipherName; 1.66 + retval.encryptionStrength = status.secretKeyLength; 1.67 + } 1.68 + catch (e) { 1.69 + } 1.70 + 1.71 + return retval; 1.72 + } else { 1.73 + return { 1.74 + hostName : hName, 1.75 + cAName : "", 1.76 + encryptionAlgorithm : "", 1.77 + encryptionStrength : 0, 1.78 + isBroken : isBroken, 1.79 + isEV : isEV, 1.80 + cert : null, 1.81 + fullLocation : gWindow.location 1.82 + }; 1.83 + } 1.84 + }, 1.85 + 1.86 + // Find the secureBrowserUI object (if present) 1.87 + _getSecurityUI : function() { 1.88 + if (window.opener.gBrowser) 1.89 + return window.opener.gBrowser.securityUI; 1.90 + return null; 1.91 + }, 1.92 + 1.93 + // Interface for mapping a certificate issuer organization to 1.94 + // the value to be displayed. 1.95 + // Bug 82017 - this implementation should be moved to pipnss C++ code 1.96 + mapIssuerOrganization: function(name) { 1.97 + if (!name) return null; 1.98 + 1.99 + if (name == "RSA Data Security, Inc.") return "Verisign, Inc."; 1.100 + 1.101 + // No mapping required 1.102 + return name; 1.103 + }, 1.104 + 1.105 + /** 1.106 + * Open the cookie manager window 1.107 + */ 1.108 + viewCookies : function() 1.109 + { 1.110 + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] 1.111 + .getService(Components.interfaces.nsIWindowMediator); 1.112 + var win = wm.getMostRecentWindow("Browser:Cookies"); 1.113 + var eTLDService = Components.classes["@mozilla.org/network/effective-tld-service;1"]. 1.114 + getService(Components.interfaces.nsIEffectiveTLDService); 1.115 + 1.116 + var eTLD; 1.117 + var uri = gDocument.documentURIObject; 1.118 + try { 1.119 + eTLD = eTLDService.getBaseDomain(uri); 1.120 + } 1.121 + catch (e) { 1.122 + // getBaseDomain will fail if the host is an IP address or is empty 1.123 + eTLD = uri.asciiHost; 1.124 + } 1.125 + 1.126 + if (win) { 1.127 + win.gCookiesWindow.setFilter(eTLD); 1.128 + win.focus(); 1.129 + } 1.130 + else 1.131 + window.openDialog("chrome://browser/content/preferences/cookies.xul", 1.132 + "Browser:Cookies", "", {filterString : eTLD}); 1.133 + }, 1.134 + 1.135 + /** 1.136 + * Open the login manager window 1.137 + */ 1.138 + viewPasswords : function() 1.139 + { 1.140 + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] 1.141 + .getService(Components.interfaces.nsIWindowMediator); 1.142 + var win = wm.getMostRecentWindow("Toolkit:PasswordManager"); 1.143 + if (win) { 1.144 + win.setFilter(this._getSecurityInfo().hostName); 1.145 + win.focus(); 1.146 + } 1.147 + else 1.148 + window.openDialog("chrome://passwordmgr/content/passwordManager.xul", 1.149 + "Toolkit:PasswordManager", "", 1.150 + {filterString : this._getSecurityInfo().hostName}); 1.151 + }, 1.152 + 1.153 + _cert : null 1.154 +}; 1.155 + 1.156 +function securityOnLoad() { 1.157 + var info = security._getSecurityInfo(); 1.158 + if (!info) { 1.159 + document.getElementById("securityTab").hidden = true; 1.160 + document.getElementById("securityBox").collapsed = true; 1.161 + return; 1.162 + } 1.163 + else { 1.164 + document.getElementById("securityTab").hidden = false; 1.165 + document.getElementById("securityBox").collapsed = false; 1.166 + } 1.167 + 1.168 + const pageInfoBundle = document.getElementById("pageinfobundle"); 1.169 + 1.170 + /* Set Identity section text */ 1.171 + setText("security-identity-domain-value", info.hostName); 1.172 + 1.173 + var owner, verifier, generalPageIdentityString; 1.174 + if (info.cert && !info.isBroken) { 1.175 + // Try to pull out meaningful values. Technically these fields are optional 1.176 + // so we'll employ fallbacks where appropriate. The EV spec states that Org 1.177 + // fields must be specified for subject and issuer so that case is simpler. 1.178 + if (info.isEV) { 1.179 + owner = info.cert.organization; 1.180 + verifier = security.mapIssuerOrganization(info.cAName); 1.181 + generalPageIdentityString = pageInfoBundle.getFormattedString("generalSiteIdentity", 1.182 + [owner, verifier]); 1.183 + } 1.184 + else { 1.185 + // Technically, a non-EV cert might specify an owner in the O field or not, 1.186 + // depending on the CA's issuing policies. However we don't have any programmatic 1.187 + // way to tell those apart, and no policy way to establish which organization 1.188 + // vetting standards are good enough (that's what EV is for) so we default to 1.189 + // treating these certs as domain-validated only. 1.190 + owner = pageInfoBundle.getString("securityNoOwner"); 1.191 + verifier = security.mapIssuerOrganization(info.cAName || 1.192 + info.cert.issuerCommonName || 1.193 + info.cert.issuerName); 1.194 + generalPageIdentityString = owner; 1.195 + } 1.196 + } 1.197 + else { 1.198 + // We don't have valid identity credentials. 1.199 + owner = pageInfoBundle.getString("securityNoOwner"); 1.200 + verifier = pageInfoBundle.getString("notset"); 1.201 + generalPageIdentityString = owner; 1.202 + } 1.203 + 1.204 + setText("security-identity-owner-value", owner); 1.205 + setText("security-identity-verifier-value", verifier); 1.206 + setText("general-security-identity", generalPageIdentityString); 1.207 + 1.208 + /* Manage the View Cert button*/ 1.209 + var viewCert = document.getElementById("security-view-cert"); 1.210 + if (info.cert) { 1.211 + security._cert = info.cert; 1.212 + viewCert.collapsed = false; 1.213 + } 1.214 + else 1.215 + viewCert.collapsed = true; 1.216 + 1.217 + /* Set Privacy & History section text */ 1.218 + var yesStr = pageInfoBundle.getString("yes"); 1.219 + var noStr = pageInfoBundle.getString("no"); 1.220 + 1.221 + var uri = gDocument.documentURIObject; 1.222 + setText("security-privacy-cookies-value", 1.223 + hostHasCookies(uri) ? yesStr : noStr); 1.224 + setText("security-privacy-passwords-value", 1.225 + realmHasPasswords(uri) ? yesStr : noStr); 1.226 + 1.227 + var visitCount = previousVisitCount(info.hostName); 1.228 + if(visitCount > 1) { 1.229 + setText("security-privacy-history-value", 1.230 + pageInfoBundle.getFormattedString("securityNVisits", [visitCount.toLocaleString()])); 1.231 + } 1.232 + else if (visitCount == 1) { 1.233 + setText("security-privacy-history-value", 1.234 + pageInfoBundle.getString("securityOneVisit")); 1.235 + } 1.236 + else { 1.237 + setText("security-privacy-history-value", noStr); 1.238 + } 1.239 + 1.240 + /* Set the Technical Detail section messages */ 1.241 + const pkiBundle = document.getElementById("pkiBundle"); 1.242 + var hdr; 1.243 + var msg1; 1.244 + var msg2; 1.245 + 1.246 + if (info.isBroken) { 1.247 + hdr = pkiBundle.getString("pageInfo_MixedContent"); 1.248 + msg1 = pkiBundle.getString("pageInfo_Privacy_Mixed1"); 1.249 + msg2 = pkiBundle.getString("pageInfo_Privacy_None2"); 1.250 + } 1.251 + else if (info.encryptionStrength >= 90) { 1.252 + hdr = pkiBundle.getFormattedString("pageInfo_StrongEncryptionWithBits", 1.253 + [info.encryptionAlgorithm, info.encryptionStrength + ""]); 1.254 + msg1 = pkiBundle.getString("pageInfo_Privacy_Strong1"); 1.255 + msg2 = pkiBundle.getString("pageInfo_Privacy_Strong2"); 1.256 + security._cert = info.cert; 1.257 + } 1.258 + else if (info.encryptionStrength > 0) { 1.259 + hdr = pkiBundle.getFormattedString("pageInfo_WeakEncryptionWithBits", 1.260 + [info.encryptionAlgorithm, info.encryptionStrength + ""]); 1.261 + msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_Weak1", [info.hostName]); 1.262 + msg2 = pkiBundle.getString("pageInfo_Privacy_Weak2"); 1.263 + } 1.264 + else { 1.265 + hdr = pkiBundle.getString("pageInfo_NoEncryption"); 1.266 + if (info.hostName != null) 1.267 + msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_None1", [info.hostName]); 1.268 + else 1.269 + msg1 = pkiBundle.getString("pageInfo_Privacy_None3"); 1.270 + msg2 = pkiBundle.getString("pageInfo_Privacy_None2"); 1.271 + } 1.272 + setText("security-technical-shortform", hdr); 1.273 + setText("security-technical-longform1", msg1); 1.274 + setText("security-technical-longform2", msg2); 1.275 + setText("general-security-privacy", hdr); 1.276 +} 1.277 + 1.278 +function setText(id, value) 1.279 +{ 1.280 + var element = document.getElementById(id); 1.281 + if (!element) 1.282 + return; 1.283 + if (element.localName == "textbox" || element.localName == "label") 1.284 + element.value = value; 1.285 + else { 1.286 + if (element.hasChildNodes()) 1.287 + element.removeChild(element.firstChild); 1.288 + var textNode = document.createTextNode(value); 1.289 + element.appendChild(textNode); 1.290 + } 1.291 +} 1.292 + 1.293 +function viewCertHelper(parent, cert) 1.294 +{ 1.295 + if (!cert) 1.296 + return; 1.297 + 1.298 + var cd = Components.classes[CERTIFICATEDIALOGS_CONTRACTID].getService(nsICertificateDialogs); 1.299 + cd.viewCert(parent, cert); 1.300 +} 1.301 + 1.302 +/** 1.303 + * Return true iff we have cookies for uri 1.304 + */ 1.305 +function hostHasCookies(uri) { 1.306 + var cookieManager = Components.classes["@mozilla.org/cookiemanager;1"] 1.307 + .getService(Components.interfaces.nsICookieManager2); 1.308 + 1.309 + return cookieManager.countCookiesFromHost(uri.asciiHost) > 0; 1.310 +} 1.311 + 1.312 +/** 1.313 + * Return true iff realm (proto://host:port) (extracted from uri) has 1.314 + * saved passwords 1.315 + */ 1.316 +function realmHasPasswords(uri) { 1.317 + var passwordManager = Components.classes["@mozilla.org/login-manager;1"] 1.318 + .getService(Components.interfaces.nsILoginManager); 1.319 + return passwordManager.countLogins(uri.prePath, "", "") > 0; 1.320 +} 1.321 + 1.322 +/** 1.323 + * Return the number of previous visits recorded for host before today. 1.324 + * 1.325 + * @param host - the domain name to look for in history 1.326 + */ 1.327 +function previousVisitCount(host, endTimeReference) { 1.328 + if (!host) 1.329 + return false; 1.330 + 1.331 + var historyService = Components.classes["@mozilla.org/browser/nav-history-service;1"] 1.332 + .getService(Components.interfaces.nsINavHistoryService); 1.333 + 1.334 + var options = historyService.getNewQueryOptions(); 1.335 + options.resultType = options.RESULTS_AS_VISIT; 1.336 + 1.337 + // Search for visits to this host before today 1.338 + var query = historyService.getNewQuery(); 1.339 + query.endTimeReference = query.TIME_RELATIVE_TODAY; 1.340 + query.endTime = 0; 1.341 + query.domain = host; 1.342 + 1.343 + var result = historyService.executeQuery(query, options); 1.344 + result.root.containerOpen = true; 1.345 + var cc = result.root.childCount; 1.346 + result.root.containerOpen = false; 1.347 + return cc; 1.348 +}