browser/base/content/pageinfo/security.js

changeset 0
6474c204b198
     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 +}

mercurial