Backed out 3 changesets (bug 1382001) at developer's request a=backout

Backed out changeset 1fe47b777980 (bug 1382001)
Backed out changeset bd6770fadff3 (bug 1382001)
Backed out changeset 29353fb6613b (bug 1382001)

MozReview-Commit-ID: F4S2q5WAxe4
This commit is contained in:
Wes Kocher
2017-08-10 18:03:05 -07:00
parent 3facc4f334
commit 5662a0562f
6 changed files with 43605 additions and 21827 deletions

View File

@@ -176,13 +176,6 @@ LOCAL_INCLUDES += [
'!/dist/public/nss', '!/dist/public/nss',
] ]
GENERATED_FILES = [
'nsSTSPreloadList.h',
]
dafsa_data = GENERATED_FILES['nsSTSPreloadList.h']
dafsa_data.script = '../../../xpcom/ds/make_dafsa.py'
dafsa_data.inputs = ['nsSTSPreloadList.inc']
if CONFIG['NSS_DISABLE_DBM']: if CONFIG['NSS_DISABLE_DBM']:
DEFINES['NSS_DISABLE_DBM'] = '1' DEFINES['NSS_DISABLE_DBM'] = '1'

File diff suppressed because it is too large Load Diff

View File

@@ -41,7 +41,7 @@
// influence its HSTS status via include subdomains, however). // influence its HSTS status via include subdomains, however).
// This prevents the preload list from overriding the site's current // This prevents the preload list from overriding the site's current
// desired HSTS status. // desired HSTS status.
#include "nsSTSPreloadList.h" #include "nsSTSPreloadList.inc"
using namespace mozilla; using namespace mozilla;
using namespace mozilla::psm; using namespace mozilla::psm;
@@ -495,7 +495,6 @@ nsSiteSecurityService::nsSiteSecurityService()
: mMaxMaxAge(kSixtyDaysInSeconds) : mMaxMaxAge(kSixtyDaysInSeconds)
, mUsePreloadList(true) , mUsePreloadList(true)
, mPreloadListTimeOffset(0) , mPreloadListTimeOffset(0)
, mDafsa(kDafsa)
{ {
} }
@@ -731,7 +730,7 @@ nsSiteSecurityService::RemoveStateInternal(
mozilla::DataStorage_Persistent); mozilla::DataStorage_Persistent);
RefPtr<SiteHSTSState> dynamicState = RefPtr<SiteHSTSState> dynamicState =
new SiteHSTSState(aHost, aOriginAttributes, value); new SiteHSTSState(aHost, aOriginAttributes, value);
if (GetPreloadStatus(aHost) || if (GetPreloadListEntry(aHost.get()) ||
dynamicState->mHSTSState != SecurityPropertyUnset) { dynamicState->mHSTSState != SecurityPropertyUnset) {
SSSLOG(("SSS: storing knockout entry for %s", aHost.get())); SSSLOG(("SSS: storing knockout entry for %s", aHost.get()));
RefPtr<SiteHSTSState> siteState = new SiteHSTSState( RefPtr<SiteHSTSState> siteState = new SiteHSTSState(
@@ -1371,31 +1370,29 @@ nsSiteSecurityService::IsSecureURI(uint32_t aType, nsIURI* aURI,
source, aResult); source, aResult);
} }
// Checks if the given host is in the preload list. int STSPreloadCompare(const void *key, const void *entry)
//
// @param aHost The host to match. Only does exact host matching.
// @param aIncludeSubdomains Out, optional. Indicates whether or not to include
// subdomains. Only set if the host is matched and this function returns
// true.
//
// @return True if the host is matched, false otherwise.
bool
nsSiteSecurityService::GetPreloadStatus(const nsACString& aHost,
bool* aIncludeSubdomains) const
{ {
const int kIncludeSubdomains = 1; const char *keyStr = (const char *)key;
bool found = false; const nsSTSPreload *preloadEntry = (const nsSTSPreload *)entry;
return strcmp(keyStr, &kSTSHostTable[preloadEntry->mHostIndex]);
}
// Returns the preload list entry for the given host, if it exists.
// Only does exact host matching - the user must decide how to use the returned
// data. May return null.
const nsSTSPreload *
nsSiteSecurityService::GetPreloadListEntry(const char *aHost)
{
PRTime currentTime = PR_Now() + (mPreloadListTimeOffset * PR_USEC_PER_SEC); PRTime currentTime = PR_Now() + (mPreloadListTimeOffset * PR_USEC_PER_SEC);
if (mUsePreloadList && currentTime < gPreloadListExpirationTime) { if (mUsePreloadList && currentTime < gPreloadListExpirationTime) {
int result = mDafsa.Lookup(aHost); return (const nsSTSPreload *) bsearch(aHost,
found = (result != mozilla::Dafsa::kKeyNotFound); kSTSPreloadList,
if (found && aIncludeSubdomains) { mozilla::ArrayLength(kSTSPreloadList),
*aIncludeSubdomains = (result == kIncludeSubdomains); sizeof(nsSTSPreload),
} STSPreloadCompare);
} }
return found; return nullptr;
} }
// Allows us to determine if we have an HSTS entry for a given host (and, if // Allows us to determine if we have an HSTS entry for a given host (and, if
@@ -1479,7 +1476,7 @@ nsSiteSecurityService::HostHasHSTSEntry(
if (dynamicState->mHSTSState == SecurityPropertyUnset) { if (dynamicState->mHSTSState == SecurityPropertyUnset) {
SSSLOG(("No dynamic preload - checking for static preload")); SSSLOG(("No dynamic preload - checking for static preload"));
// Now check the static preload list. // Now check the static preload list.
if (!GetPreloadStatus(aHost)) { if (!GetPreloadListEntry(aHost.get())) {
SSSLOG(("No static preload - removing expired entry")); SSSLOG(("No static preload - removing expired entry"));
mSiteStateStorage->Remove(storageKey, storageType); mSiteStateStorage->Remove(storageKey, storageType);
} }
@@ -1523,7 +1520,7 @@ nsSiteSecurityService::HostHasHSTSEntry(
} else { } else {
// if a dynamic preload has expired and is not in the static preload // if a dynamic preload has expired and is not in the static preload
// list, we can remove it. // list, we can remove it.
if (!GetPreloadStatus(aHost)) { if (!GetPreloadListEntry(aHost.get())) {
mPreloadStateStorage->Remove(preloadKey, mPreloadStateStorage->Remove(preloadKey,
mozilla::DataStorage_Persistent); mozilla::DataStorage_Persistent);
} }
@@ -1531,18 +1528,18 @@ nsSiteSecurityService::HostHasHSTSEntry(
return false; return false;
} }
bool includeSubdomains = false; const nsSTSPreload* preload = nullptr;
// Finally look in the static preload list. // Finally look in the static preload list.
if (siteState->mHSTSState == SecurityPropertyUnset && if (siteState->mHSTSState == SecurityPropertyUnset &&
dynamicState->mHSTSState == SecurityPropertyUnset && dynamicState->mHSTSState == SecurityPropertyUnset &&
GetPreloadStatus(aHost, &includeSubdomains)) { (preload = GetPreloadListEntry(aHost.get())) != nullptr) {
SSSLOG(("%s is a preloaded HSTS host", aHost.get())); SSSLOG(("%s is a preloaded HSTS host", aHost.get()));
*aResult = aRequireIncludeSubdomains ? includeSubdomains *aResult = aRequireIncludeSubdomains ? preload->mIncludeSubdomains
: true; : true;
if (aCached) { if (aCached) {
// Only set cached if this includes subdomains // Only set cached if this includes subdomains
*aCached = aRequireIncludeSubdomains ? includeSubdomains *aCached = aRequireIncludeSubdomains ? preload->mIncludeSubdomains
: true; : true;
} }
if (aSource) { if (aSource) {

View File

@@ -6,7 +6,6 @@
#define __nsSiteSecurityService_h__ #define __nsSiteSecurityService_h__
#include "mozilla/BasePrincipal.h" #include "mozilla/BasePrincipal.h"
#include "mozilla/Dafsa.h"
#include "mozilla/DataStorage.h" #include "mozilla/DataStorage.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
@@ -209,8 +208,7 @@ private:
const OriginAttributes& aOriginAttributes, const OriginAttributes& aOriginAttributes,
bool* aResult, bool* aCached, bool* aResult, bool* aCached,
SecurityPropertySource* aSource); SecurityPropertySource* aSource);
bool GetPreloadStatus(const nsACString& aHost, const nsSTSPreload *GetPreloadListEntry(const char *aHost);
/*optional out*/ bool* aIncludeSubdomains = nullptr) const;
nsresult IsSecureHost(uint32_t aType, const nsACString& aHost, nsresult IsSecureHost(uint32_t aType, const nsACString& aHost,
uint32_t aFlags, uint32_t aFlags,
const OriginAttributes& aOriginAttributes, const OriginAttributes& aOriginAttributes,
@@ -223,7 +221,6 @@ private:
bool mProcessPKPHeadersFromNonBuiltInRoots; bool mProcessPKPHeadersFromNonBuiltInRoots;
RefPtr<mozilla::DataStorage> mSiteStateStorage; RefPtr<mozilla::DataStorage> mSiteStateStorage;
RefPtr<mozilla::DataStorage> mPreloadStateStorage; RefPtr<mozilla::DataStorage> mPreloadStateStorage;
const mozilla::Dafsa mDafsa;
}; };
#endif // __nsSiteSecurityService_h__ #endif // __nsSiteSecurityService_h__

View File

@@ -42,7 +42,6 @@ const HEADER = "/* This Source Code Form is subject to the terms of the Mozilla
"/*****************************************************************************/\n" + "/*****************************************************************************/\n" +
"\n" + "\n" +
"#include <stdint.h>\n"; "#include <stdint.h>\n";
const GPERF_DELIM = "%%\n";
function download() { function download() {
var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
@@ -241,6 +240,12 @@ function errorToString(status) {
: status.error); : status.error);
} }
function writeEntry(status, indices, outputStream) {
let includeSubdomains = (status.finalIncludeSubdomains ? "true" : "false");
writeTo(" { " + indices[status.name] + ", " + includeSubdomains + " },\n",
outputStream);
}
function output(sortedStatuses, currentList) { function output(sortedStatuses, currentList) {
try { try {
var file = FileUtils.getFile("CurWorkD", [OUTPUT]); var file = FileUtils.getFile("CurWorkD", [OUTPUT]);
@@ -293,14 +298,47 @@ function output(sortedStatuses, currentList) {
status.finalIncludeSubdomains = incSubdomainsBool; status.finalIncludeSubdomains = incSubdomainsBool;
} }
writeTo(GPERF_DELIM, fos); writeTo("\nstatic const char kSTSHostTable[] = {\n", fos);
var indices = {};
var currentIndex = 0;
for (let status of includedStatuses) { for (let status of includedStatuses) {
let includeSubdomains = (status.finalIncludeSubdomains ? 1 : 0); indices[status.name] = currentIndex;
writeTo(status.name + ", " + includeSubdomains + "\n", fos); // Add 1 for the null terminator in C.
currentIndex += status.name.length + 1;
// Rebuilding the preload list requires reading the previous preload
// list. Write out a comment describing each host prior to writing out
// the string for the host.
writeTo(" /* \"" + status.name + "\", " +
(status.finalIncludeSubdomains ? "true" : "false") + " */ ",
fos);
// Write out the string itself as individual characters, including the
// null terminator. We do it this way rather than using C's string
// concatentation because some compilers have hardcoded limits on the
// lengths of string literals, and the preload list is large enough
// that it runs into said limits.
for (let c of status.name) {
writeTo("'" + c + "', ", fos);
}
writeTo("'\\0',\n", fos);
} }
writeTo("};\n", fos);
writeTo(GPERF_DELIM, fos); const PREFIX = "\n" +
"struct nsSTSPreload\n" +
"{\n" +
" // See bug 1338873 about making these fields const.\n" +
" uint32_t mHostIndex : 31;\n" +
" uint32_t mIncludeSubdomains : 1;\n" +
"};\n" +
"\n" +
"static const nsSTSPreload kSTSPreloadList[] = {\n";
const POSTFIX = "};\n";
writeTo(PREFIX, fos);
for (let status of includedStatuses) {
writeEntry(status, indices, fos);
}
writeTo(POSTFIX, fos);
FileUtils.closeSafeFileOutputStream(fos); FileUtils.closeSafeFileOutputStream(fos);
FileUtils.closeSafeFileOutputStream(eos); FileUtils.closeSafeFileOutputStream(eos);
} catch (e) { } catch (e) {
@@ -360,22 +398,19 @@ function readCurrentList(filename) {
.createInstance(Ci.nsILineInputStream); .createInstance(Ci.nsILineInputStream);
fis.init(file, -1, -1, Ci.nsIFileInputStream.CLOSE_ON_EOF); fis.init(file, -1, -1, Ci.nsIFileInputStream.CLOSE_ON_EOF);
var line = {}; var line = {};
// While we generate entries matching the version 2 format (see bug 1255425
// While we generate entries matching the latest version format, // for details), we still need to be able to read entries in the version 1
// we still need to be able to read entries in the previous version formats // format for bootstrapping a version 2 preload list from a version 1
// for bootstrapping a latest version preload list from a previous version // preload list. Hence these two regexes.
// preload list. Hence these regexes. var v1EntryRegex = / {2}{ "([^"]*)", (true|false) },/;
const entryRegexes = [ var v2EntryRegex = / {2}\/\* "([^"]*)", (true|false) \*\//;
/([^,]+), (0|1)/, // v3
/ {2}\/\* "([^"]*)", (true|false) \*\//, // v2
/ {2}{ "([^"]*)", (true|false) },/, // v1
];
while (fis.readLine(line)) { while (fis.readLine(line)) {
let match; var match = v1EntryRegex.exec(line.value);
entryRegexes.find((r) => { match = r.exec(line.value); return match; } ); if (!match) {
match = v2EntryRegex.exec(line.value);
}
if (match) { if (match) {
currentHosts[match[1]] = (match[2] == "1" || match[2] == "true"); currentHosts[match[1]] = (match[2] == "true");
} }
} }
return currentHosts; return currentHosts;

View File

@@ -415,17 +415,12 @@ def encode(dafsa):
return output return output
def to_cxx(data, preamble=None): def to_cxx(data):
"""Generates C++ code from a list of encoded bytes.""" """Generates C++ code from a list of encoded bytes."""
text = '/* This file is generated. DO NOT EDIT!\n\n' text = '/* This file is generated. DO NOT EDIT!\n\n'
text += 'The byte array encodes a dictionary of strings and values. See ' text += 'The byte array encodes effective tld names. See make_dafsa.py for'
text += 'make_dafsa.py for documentation.' text += ' documentation.'
text += '*/\n\n' text += '*/\n\n'
if preamble:
text += preamble
text += '\n\n'
text += 'const unsigned char kDafsa[%s] = {\n' % len(data) text += 'const unsigned char kDafsa[%s] = {\n' % len(data)
for i in range(0, len(data), 12): for i in range(0, len(data), 12):
text += ' ' text += ' '
@@ -435,24 +430,19 @@ def to_cxx(data, preamble=None):
return text return text
def words_to_cxx(words, preamble=None): def words_to_cxx(words):
"""Generates C++ code from a word list""" """Generates C++ code from a word list"""
dafsa = to_dafsa(words) dafsa = to_dafsa(words)
for fun in (reverse, join_suffixes, reverse, join_suffixes, join_labels): for fun in (reverse, join_suffixes, reverse, join_suffixes, join_labels):
dafsa = fun(dafsa) dafsa = fun(dafsa)
return to_cxx(encode(dafsa), preamble) return to_cxx(encode(dafsa))
def parse_gperf(infile): def parse_gperf(infile):
"""Parses gperf file and extract strings and return code""" """Parses gperf file and extract strings and return code"""
lines = [line.strip() for line in infile] lines = [line.strip() for line in infile]
# Extract the preamble.
first_delimeter = lines.index('%%')
preamble = '\n'.join(lines[0:first_delimeter])
# Extract strings after the first '%%' and before the second '%%'. # Extract strings after the first '%%' and before the second '%%'.
begin = first_delimeter + 1 begin = lines.index('%%') + 1
end = lines.index('%%', begin) end = lines.index('%%', begin)
lines = lines[begin:end] lines = lines[begin:end]
for line in lines: for line in lines:
@@ -463,13 +453,12 @@ def parse_gperf(infile):
if line[-1] not in '0124': if line[-1] not in '0124':
raise InputError('Expected value to be one of {0,1,2,4}, found "%s"' % raise InputError('Expected value to be one of {0,1,2,4}, found "%s"' %
line[-1]) line[-1])
return (preamble, [line[:-3] + line[-1] for line in lines]) return [line[:-3] + line[-1] for line in lines]
def main(outfile, infile): def main(outfile, infile):
with open(infile, 'r') as infile: with open(infile, 'r') as infile:
preamble, words = parse_gperf(infile) outfile.write(words_to_cxx(parse_gperf(infile)))
outfile.write(words_to_cxx(words, preamble))
return 0 return 0