Commit ef993102 authored by mef@chromium.org's avatar mef@chromium.org

Enable SDCH support over HTTPS if --enable-sdch=2 switch is present.

BUG=313716

Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=243957

Review URL: https://codereview.chromium.org/123383002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@244217 0039d316-1c4b-4281-b951-d872f2087c98
parent 689941c2
......@@ -1367,13 +1367,20 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
browser_process_->intranet_redirect_detector();
GoogleSearchCounter::RegisterForNotifications();
// Disable SDCH filtering if switches::kEnableSdch is 0.
int sdch_enabled = 1;
if (parsed_command_line().HasSwitch(switches::kEnableSdch)) {
base::StringToInt(parsed_command_line().GetSwitchValueASCII(
switches::kEnableSdch), &sdch_enabled);
if (!sdch_enabled)
net::SdchManager::EnableSdchSupport(false);
// SDCH options via switches::kEnableSdch include:
const int kSdchDisabled = 0;
const int kSdchOverHttpEnabled = 1;
const int kSdchOverBothHttpAndHttpsEnabled = 2;
int sdch_enabled = kSdchOverHttpEnabled;
if (base::StringToInt(parsed_command_line().GetSwitchValueASCII(
switches::kEnableSdch), &sdch_enabled)) {
if (sdch_enabled == kSdchDisabled) {
net::SdchManager::EnableSdchSupport(false);
} else if (sdch_enabled == kSdchOverBothHttpAndHttpsEnabled) {
net::SdchManager::EnableSecureSchemeSupport(true);
}
}
}
if (parsed_command_line().HasSwitch(switches::kEnableWatchdog))
......
......@@ -1232,6 +1232,83 @@ TEST_F(SdchFilterTest, CanSetExactMatchDictionary) {
GURL("http://" + dictionary_domain)));
}
TEST_F(SdchFilterTest, CanAdvertiseDictionaryOverHTTP) {
std::string dictionary_domain("x.y.z.google.com");
std::string dictionary_text(NewSdchDictionary(dictionary_domain));
EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary_text,
GURL("http://" + dictionary_domain)));
std::string dictionary_list;
// HTTP target URL can advertise dictionary.
sdch_manager_->GetAvailDictionaryList(
GURL("http://" + dictionary_domain + "/test"),
&dictionary_list);
EXPECT_FALSE(dictionary_list.empty());
}
TEST_F(SdchFilterTest, CanNotAdvertiseDictionaryOverHTTPS) {
std::string dictionary_domain("x.y.z.google.com");
std::string dictionary_text(NewSdchDictionary(dictionary_domain));
EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary_text,
GURL("http://" + dictionary_domain)));
std::string dictionary_list;
// HTTPS target URL should NOT advertise dictionary.
sdch_manager_->GetAvailDictionaryList(
GURL("https://" + dictionary_domain + "/test"),
&dictionary_list);
EXPECT_TRUE(dictionary_list.empty());
}
TEST_F(SdchFilterTest, CanUseHTTPSDictionaryOverHTTPSIfEnabled) {
std::string dictionary_domain("x.y.z.google.com");
std::string dictionary_text(NewSdchDictionary(dictionary_domain));
EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary_text,
GURL("https://" + dictionary_domain)));
GURL target_url("https://" + dictionary_domain + "/test");
std::string dictionary_list;
// HTTPS target URL should advertise dictionary if secure scheme support is
// enabled.
sdch_manager_->EnableSecureSchemeSupport(true);
sdch_manager_->GetAvailDictionaryList(target_url, &dictionary_list);
EXPECT_FALSE(dictionary_list.empty());
// Dictionary should be available.
SdchManager::Dictionary* dictionary = NULL;
std::string client_hash;
std::string server_hash;
sdch_manager_->GenerateHash(dictionary_text, &client_hash, &server_hash);
sdch_manager_->GetVcdiffDictionary(server_hash, target_url, &dictionary);
EXPECT_TRUE(dictionary != NULL);
}
TEST_F(SdchFilterTest, CanNotUseHTTPDictionaryOverHTTPS) {
std::string dictionary_domain("x.y.z.google.com");
std::string dictionary_text(NewSdchDictionary(dictionary_domain));
EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary_text,
GURL("http://" + dictionary_domain)));
GURL target_url("https://" + dictionary_domain + "/test");
std::string dictionary_list;
// HTTPS target URL should not advertise dictionary acquired over HTTP even if
// secure scheme support is enabled.
sdch_manager_->EnableSecureSchemeSupport(true);
sdch_manager_->GetAvailDictionaryList(target_url, &dictionary_list);
EXPECT_TRUE(dictionary_list.empty());
SdchManager::Dictionary* dictionary = NULL;
std::string client_hash;
std::string server_hash;
sdch_manager_->GenerateHash(dictionary_text, &client_hash, &server_hash);
sdch_manager_->GetVcdiffDictionary(server_hash, target_url, &dictionary);
EXPECT_TRUE(dictionary == NULL);
}
TEST_F(SdchFilterTest, FailToSetDomainMismatchDictionary) {
std::string dictionary_domain("x.y.z.google.com");
std::string dictionary_text(NewSdchDictionary(dictionary_domain));
......
......@@ -28,6 +28,9 @@ SdchManager* SdchManager::global_ = NULL;
// static
bool SdchManager::g_sdch_enabled_ = true;
// static
bool SdchManager::g_secure_scheme_supported_ = false;
//------------------------------------------------------------------------------
SdchManager::Dictionary::Dictionary(const std::string& dictionary_text,
size_t offset,
......@@ -63,6 +66,8 @@ bool SdchManager::Dictionary::CanAdvertise(const GURL& target_url) {
ports listed in the Port attribute.
3. The request URI path-matches the path header of the dictionary.
4. The request is not an HTTPS request.
We can override (ignore) item (4) only when we have explicitly enabled
HTTPS support AND dictionary has been acquired over HTTPS.
*/
if (!DomainMatch(target_url, domain_))
return false;
......@@ -70,7 +75,9 @@ bool SdchManager::Dictionary::CanAdvertise(const GURL& target_url) {
return false;
if (path_.size() && !PathMatch(target_url.path(), path_))
return false;
if (target_url.SchemeIsSecure())
if (!SdchManager::secure_scheme_supported() && target_url.SchemeIsSecure())
return false;
if (target_url.SchemeIsSecure() && !url_.SchemeIsSecure())
return false;
if (base::Time::Now() > expiration_)
return false;
......@@ -152,6 +159,8 @@ bool SdchManager::Dictionary::CanUse(const GURL& referring_url) {
ports listed in the Port attribute.
3. The request URL path-matches the path attribute of the dictionary.
4. The request is not an HTTPS request.
We can override (ignore) item (4) only when we have explicitly enabled
HTTPS support AND dictionary has been acquired over HTTPS.
*/
if (!DomainMatch(referring_url, domain_)) {
SdchErrorRecovery(DICTIONARY_FOUND_HAS_WRONG_DOMAIN);
......@@ -166,14 +175,19 @@ bool SdchManager::Dictionary::CanUse(const GURL& referring_url) {
SdchErrorRecovery(DICTIONARY_FOUND_HAS_WRONG_PATH);
return false;
}
if (referring_url.SchemeIsSecure()) {
if (!SdchManager::secure_scheme_supported() &&
referring_url.SchemeIsSecure()) {
SdchErrorRecovery(DICTIONARY_FOUND_HAS_WRONG_SCHEME);
return false;
}
if (referring_url.SchemeIsSecure() && !url_.SchemeIsSecure()) {
SdchErrorRecovery(DICTIONARY_FOUND_HAS_WRONG_SCHEME);
return false;
}
// TODO(jar): Remove overly restrictive failsafe test (added per security
// review) when we have a need to be more general.
if (!referring_url.SchemeIs("http")) {
if (!referring_url.SchemeIsHTTPOrHTTPS()) {
SdchErrorRecovery(ATTEMPT_TO_DECODE_NON_HTTP_DATA);
return false;
}
......@@ -251,6 +265,11 @@ void SdchManager::EnableSdchSupport(bool enabled) {
g_sdch_enabled_ = enabled;
}
// static
void SdchManager::EnableSecureSchemeSupport(bool enabled) {
g_secure_scheme_supported_ = enabled;
}
// static
void SdchManager::BlacklistDomain(const GURL& url) {
if (!global_ )
......@@ -344,7 +363,8 @@ bool SdchManager::CanFetchDictionary(const GURL& referring_url,
DCHECK(CalledOnValidThread());
/* The user agent may retrieve a dictionary from the dictionary URL if all of
the following are true:
1 The dictionary URL host name matches the referrer URL host name
1 The dictionary URL host name matches the referrer URL host name and
scheme.
2 The dictionary URL host name domain matches the parent domain of the
referrer URL host name
3 The parent domain of the referrer URL host name is not a top level
......@@ -353,18 +373,19 @@ bool SdchManager::CanFetchDictionary(const GURL& referring_url,
*/
// Item (1) above implies item (2). Spec should be updated.
// I take "host name match" to be "is identical to"
if (referring_url.host() != dictionary_url.host()) {
if (referring_url.host() != dictionary_url.host() ||
referring_url.scheme() != dictionary_url.scheme()) {
SdchErrorRecovery(DICTIONARY_LOAD_ATTEMPT_FROM_DIFFERENT_HOST);
return false;
}
if (referring_url.SchemeIs("https")) {
if (!secure_scheme_supported() && referring_url.SchemeIsSecure()) {
SdchErrorRecovery(DICTIONARY_SELECTED_FOR_SSL);
return false;
}
// TODO(jar): Remove this failsafe conservative hack which is more restrictive
// than current SDCH spec when needed, and justified by security audit.
if (!referring_url.SchemeIs("http")) {
if (!referring_url.SchemeIsHTTPOrHTTPS()) {
SdchErrorRecovery(DICTIONARY_SELECTED_FROM_NON_HTTP);
return false;
}
......
......@@ -251,6 +251,11 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) {
static bool sdch_enabled() { return g_sdch_enabled_; }
// Enables or disables SDCH compression over secure connection.
static void EnableSecureSchemeSupport(bool enabled);
static bool secure_scheme_supported() { return g_secure_scheme_supported_; }
// Briefly prevent further advertising of SDCH on this domain (if SDCH is
// enabled). After enough calls to IsInSupportedDomain() the blacklisting
// will be removed. Additional blacklists take exponentially more calls
......@@ -344,6 +349,10 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) {
// Support SDCH compression, by advertising in headers.
static bool g_sdch_enabled_;
// Support SDCH compression for HTTPS requests and responses. When supported,
// HTTPS applicable dictionaries MUST have been acquired securely via HTTPS.
static bool g_secure_scheme_supported_;
// A simple implementation of a RFC 3548 "URL safe" base64 encoder.
static void UrlSafeBase64Encode(const std::string& input,
std::string* output);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment