diff options
author | abarth@chromium.org <abarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-30 01:44:29 +0000 |
---|---|---|
committer | abarth@chromium.org <abarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-30 01:44:29 +0000 |
commit | 8155f1a70fb66b287df28784bab5235eb07ceb44 (patch) | |
tree | 80cec32822c451dd81b2b2af72fdd0722a4e0a7d | |
parent | f402503e9d2461d38f864560edac4c62b245a427 (diff) | |
download | chromium_src-8155f1a70fb66b287df28784bab5235eb07ceb44.zip chromium_src-8155f1a70fb66b287df28784bab5235eb07ceb44.tar.gz chromium_src-8155f1a70fb66b287df28784bab5235eb07ceb44.tar.bz2 |
MAC Cookies (patch 1 of N)
This is the first patch towards implementing
https://github.com/hueniverse/draft-hammer-http-mac/raw/master/draft-hammer-oauth-v2-mac-token.txt
Parse MAC-Key and MAC-Algorithm from Set-Cookie and store the values in
memory. Future patches will use these values to sign requests.
Review URL: http://codereview.chromium.org/6883253
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@83649 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/automation/automation_util.cc | 10 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_cookies_unittest.cc | 26 | ||||
-rw-r--r-- | chrome/browser/net/sqlite_persistent_cookie_store.cc | 2 | ||||
-rw-r--r-- | chrome/browser/net/sqlite_persistent_cookie_store_unittest.cc | 7 | ||||
-rw-r--r-- | net/base/cookie_monster.cc | 60 | ||||
-rw-r--r-- | net/base/cookie_monster.h | 17 | ||||
-rw-r--r-- | net/base/cookie_monster_store_test.cc | 8 | ||||
-rw-r--r-- | net/base/cookie_monster_unittest.cc | 29 |
8 files changed, 124 insertions, 35 deletions
diff --git a/chrome/browser/automation/automation_util.cc b/chrome/browser/automation/automation_util.cc index 2291a37..159b16c 100644 --- a/chrome/browser/automation/automation_util.cc +++ b/chrome/browser/automation/automation_util.cc @@ -269,6 +269,8 @@ void SetCookieJSON(AutomationProvider* provider, std::string name, value; std::string domain; std::string path = "/"; + std::string mac_key; + std::string mac_algorithm; bool secure = false; double expiry = 0; bool http_only = false; @@ -290,6 +292,11 @@ void SetCookieJSON(AutomationProvider* provider, reply.SendError("optional 'path' invalid"); return; } + // mac_key and mac_algorithm are optional. + if (cookie_dict->HasKey("mac_key")) + cookie_dict->GetString("mac_key", &mac_key); + if (cookie_dict->HasKey("mac_algorithm")) + cookie_dict->GetString("mac_algorithm", &mac_algorithm); if (cookie_dict->HasKey("secure") && !cookie_dict->GetBoolean("secure", &secure)) { reply.SendError("optional 'secure' invalid"); @@ -312,7 +319,8 @@ void SetCookieJSON(AutomationProvider* provider, scoped_ptr<net::CookieMonster::CanonicalCookie> cookie( net::CookieMonster::CanonicalCookie::Create( - GURL(url), name, value, domain, path, base::Time(), + GURL(url), name, value, domain, path, + mac_key, mac_algorithm, base::Time(), base::Time::FromDoubleT(expiry), secure, http_only)); if (!cookie.get()) { reply.SendError("given 'cookie' parameters are invalid"); diff --git a/chrome/browser/extensions/extension_cookies_unittest.cc b/chrome/browser/extensions/extension_cookies_unittest.cc index 5913412..c435fa4 100644 --- a/chrome/browser/extensions/extension_cookies_unittest.cc +++ b/chrome/browser/extensions/extension_cookies_unittest.cc @@ -107,8 +107,10 @@ TEST_F(ExtensionCookiesTest, ExtensionTypeCreation) { Value* value; net::CookieMonster::CanonicalCookie cookie1( - GURL(), "ABC", "DEF", "www.foobar.com", "/", base::Time(), base::Time(), - base::Time(), false, false, false); + GURL(), "ABC", "DEF", "www.foobar.com", "/", + std::string(), std::string(), + base::Time(), base::Time(), base::Time(), + false, false, false); scoped_ptr<DictionaryValue> cookie_value1( extension_cookies_helpers::CreateCookieValue( cookie1, "some cookie store")); @@ -134,7 +136,7 @@ TEST_F(ExtensionCookiesTest, ExtensionTypeCreation) { EXPECT_EQ("some cookie store", string_value); net::CookieMonster::CanonicalCookie cookie2( - GURL(), "ABC", "DEF", ".foobar.com", "/", + GURL(), "ABC", "DEF", ".foobar.com", "/", std::string(), std::string(), base::Time(), base::Time::FromDoubleT(10000), base::Time(), false, false, true); scoped_ptr<DictionaryValue> cookie_value2( @@ -160,15 +162,19 @@ TEST_F(ExtensionCookiesTest, ExtensionTypeCreation) { TEST_F(ExtensionCookiesTest, GetURLFromCanonicalCookie) { net::CookieMonster::CanonicalCookie cookie1( - GURL(), "ABC", "DEF", "www.foobar.com", "/", base::Time(), base::Time(), - base::Time(), false, false, false); + GURL(), "ABC", "DEF", "www.foobar.com", "/", + std::string(), std::string(), + base::Time(), base::Time(), base::Time(), + false, false, false); EXPECT_EQ("http://www.foobar.com/", extension_cookies_helpers::GetURLFromCanonicalCookie( cookie1).spec()); net::CookieMonster::CanonicalCookie cookie2( - GURL(), "ABC", "DEF", ".helloworld.com", "/", base::Time(), base::Time(), - base::Time(), true, false, false); + GURL(), "ABC", "DEF", ".helloworld.com", "/", + std::string(), std::string(), + base::Time(), base::Time(), base::Time(), + true, false, false); EXPECT_EQ("https://helloworld.com/", extension_cookies_helpers::GetURLFromCanonicalCookie( cookie2).spec()); @@ -199,9 +205,9 @@ TEST_F(ExtensionCookiesTest, DomainMatching) { details->SetString(keys::kDomainKey, std::string(tests[i].filter)); extension_cookies_helpers::MatchFilter filter(details.get()); net::CookieMonster::CanonicalCookie cookie(GURL(), "", "", tests[i].domain, - "", base::Time(), base::Time(), - base::Time(), false, false, - false); + "", "", "", base::Time(), + base::Time(), base::Time(), + false, false, false); EXPECT_EQ(tests[i].matches, filter.MatchesCookie(cookie)); } } diff --git a/chrome/browser/net/sqlite_persistent_cookie_store.cc b/chrome/browser/net/sqlite_persistent_cookie_store.cc index f4a4642..c3c9ac7 100644 --- a/chrome/browser/net/sqlite_persistent_cookie_store.cc +++ b/chrome/browser/net/sqlite_persistent_cookie_store.cc @@ -204,6 +204,8 @@ bool SQLitePersistentCookieStore::Backend::Load( smt.ColumnString(3), // value smt.ColumnString(1), // domain smt.ColumnString(4), // path + std::string(), // TODO(abarth): Persist mac_key + std::string(), // TODO(abarth): Persist mac_algorithm Time::FromInternalValue(smt.ColumnInt64(0)), // creation_utc Time::FromInternalValue(smt.ColumnInt64(5)), // expires_utc Time::FromInternalValue(smt.ColumnInt64(8)), // last_access_utc diff --git a/chrome/browser/net/sqlite_persistent_cookie_store_unittest.cc b/chrome/browser/net/sqlite_persistent_cookie_store_unittest.cc index be4edcb..7e05697 100644 --- a/chrome/browser/net/sqlite_persistent_cookie_store_unittest.cc +++ b/chrome/browser/net/sqlite_persistent_cookie_store_unittest.cc @@ -35,7 +35,8 @@ class SQLitePersistentCookieStoreTest : public testing::Test { // Make sure the store gets written at least once. store_->AddCookie( net::CookieMonster::CanonicalCookie(GURL(), "A", "B", "http://foo.bar", - "/", base::Time::Now(), + "/", std::string(), std::string(), + base::Time::Now(), base::Time::Now(), base::Time::Now(), false, false, true)); @@ -129,7 +130,9 @@ TEST_F(SQLitePersistentCookieStoreTest, TestFlush) { std::string value(1000, c); store_->AddCookie( net::CookieMonster::CanonicalCookie(GURL(), name, value, - "http://foo.bar", "/", t, t, t, + "http://foo.bar", "/", + std::string(), std::string(), + t, t, t, false, false, true)); } diff --git a/net/base/cookie_monster.cc b/net/base/cookie_monster.cc index eeb129e..6fe9bef 100644 --- a/net/base/cookie_monster.cc +++ b/net/base/cookie_monster.cc @@ -549,9 +549,14 @@ bool CookieMonster::SetCookieWithDetails( Time creation_time = CurrentTime(); last_time_seen_ = creation_time; + // TODO(abarth): Take these values as parameters. + std::string mac_key; + std::string mac_algorithm; + scoped_ptr<CanonicalCookie> cc; cc.reset(CanonicalCookie::Create( url, name, value, domain, path, + mac_key, mac_algorithm, creation_time, expiration_time, secure, http_only)); @@ -1212,11 +1217,16 @@ bool CookieMonster::SetCookieWithCreationTimeAndOptions( std::string cookie_path = CanonPath(url, pc); + // TODO(abarth): Take these values as parameters. + std::string mac_key; + std::string mac_algorithm; + scoped_ptr<CanonicalCookie> cc; Time cookie_expires = CanonExpiration(pc, creation_time, options); cc.reset(new CanonicalCookie(url, pc.Name(), pc.Value(), cookie_domain, - cookie_path, creation_time, cookie_expires, + cookie_path, mac_key, mac_algorithm, + creation_time, cookie_expires, creation_time, pc.IsSecure(), pc.IsHttpOnly(), !cookie_expires.is_null())); @@ -1634,6 +1644,8 @@ CookieMonster::ParsedCookie::ParsedCookie(const std::string& cookie_line) : is_valid_(false), path_index_(0), domain_index_(0), + mac_key_index_(0), + mac_algorithm_index_(0), expires_index_(0), maxage_index_(0), secure_index_(0), @@ -1881,12 +1893,14 @@ void CookieMonster::ParsedCookie::ParseTokenValuePairs( } void CookieMonster::ParsedCookie::SetupAttributes() { - static const char kPathTokenName[] = "path"; - static const char kDomainTokenName[] = "domain"; - static const char kExpiresTokenName[] = "expires"; - static const char kMaxAgeTokenName[] = "max-age"; - static const char kSecureTokenName[] = "secure"; - static const char kHttpOnlyTokenName[] = "httponly"; + static const char kPathTokenName[] = "path"; + static const char kDomainTokenName[] = "domain"; + static const char kMACKeyTokenName[] = "mac-key"; + static const char kMACAlgorithmTokenName[] = "mac-algorithm"; + static const char kExpiresTokenName[] = "expires"; + static const char kMaxAgeTokenName[] = "max-age"; + static const char kSecureTokenName[] = "secure"; + static const char kHttpOnlyTokenName[] = "httponly"; // We skip over the first token/value, the user supplied one. for (size_t i = 1; i < pairs_.size(); ++i) { @@ -1894,6 +1908,10 @@ void CookieMonster::ParsedCookie::SetupAttributes() { path_index_ = i; } else if (pairs_[i].first == kDomainTokenName) { domain_index_ = i; + } else if (pairs_[i].first == kMACKeyTokenName) { + mac_key_index_ = i; + } else if (pairs_[i].first == kMACAlgorithmTokenName) { + mac_algorithm_index_ = i; } else if (pairs_[i].first == kExpiresTokenName) { expires_index_ = i; } else if (pairs_[i].first == kMaxAgeTokenName) { @@ -1914,22 +1932,19 @@ CookieMonster::CanonicalCookie::CanonicalCookie() has_expires_(false) { } -CookieMonster::CanonicalCookie::CanonicalCookie(const GURL& url, - const std::string& name, - const std::string& value, - const std::string& domain, - const std::string& path, - const base::Time& creation, - const base::Time& expiration, - const base::Time& last_access, - bool secure, - bool httponly, - bool has_expires) +CookieMonster::CanonicalCookie::CanonicalCookie( + const GURL& url, const std::string& name, const std::string& value, + const std::string& domain, const std::string& path, + const std::string& mac_key, const std::string& mac_algorithm, + const base::Time& creation, const base::Time& expiration, + const base::Time& last_access, bool secure, bool httponly, bool has_expires) : source_(GetCookieSourceFromURL(url)), name_(name), value_(value), domain_(domain), path_(path), + mac_key_(mac_key), + mac_algorithm_(mac_algorithm), creation_date_(creation), expiry_date_(expiration), last_access_date_(last_access), @@ -1944,6 +1959,8 @@ CookieMonster::CanonicalCookie::CanonicalCookie(const GURL& url, name_(pc.Name()), value_(pc.Value()), path_(CanonPath(url, pc)), + mac_key_(pc.MACKey()), + mac_algorithm_(pc.MACAlgorithm()), creation_date_(Time::Now()), last_access_date_(Time()), secure_(pc.IsSecure()), @@ -1988,6 +2005,8 @@ CookieMonster::CanonicalCookie* CookieMonster::CanonicalCookie::Create( const std::string& value, const std::string& domain, const std::string& path, + const std::string& mac_key, + const std::string& mac_algorithm, const base::Time& creation, const base::Time& expiration, bool secure, @@ -2026,8 +2045,9 @@ CookieMonster::CanonicalCookie* CookieMonster::CanonicalCookie::Create( canon_path_component.len); return new CanonicalCookie(url, parsed_name, parsed_value, cookie_domain, - cookie_path, creation, expiration, creation, - secure, http_only, !expiration.is_null()); + cookie_path, mac_key, mac_algorithm, creation, + expiration, creation, secure, http_only, + !expiration.is_null()); } bool CookieMonster::CanonicalCookie::IsOnPath( diff --git a/net/base/cookie_monster.h b/net/base/cookie_monster.h index e150e25..00e53e4 100644 --- a/net/base/cookie_monster.h +++ b/net/base/cookie_monster.h @@ -539,6 +539,8 @@ class CookieMonster::CanonicalCookie { const std::string& value, const std::string& domain, const std::string& path, + const std::string& mac_key, + const std::string& mac_algorithm, const base::Time& creation, const base::Time& expiration, const base::Time& last_access, @@ -563,6 +565,8 @@ class CookieMonster::CanonicalCookie { const std::string& value, const std::string& domain, const std::string& path, + const std::string& mac_key, + const std::string& mac_algorithm, const base::Time& creation, const base::Time& expiration, bool secure, @@ -573,6 +577,8 @@ class CookieMonster::CanonicalCookie { const std::string& Value() const { return value_; } const std::string& Domain() const { return domain_; } const std::string& Path() const { return path_; } + const std::string& MACKey() const { return mac_key_; } + const std::string& MACAlgorithm() const { return mac_algorithm_; } const base::Time& CreationDate() const { return creation_date_; } const base::Time& LastAccessDate() const { return last_access_date_; } bool DoesExpire() const { return has_expires_; } @@ -624,11 +630,14 @@ class CookieMonster::CanonicalCookie { // this field will be null. CanonicalCookie consumers should not rely on // this field unless they guarantee that the creator of those // CanonicalCookies properly initialized the field. + // TODO(abarth): We might need to make this field persistent for MAC cookies. std::string source_; std::string name_; std::string value_; std::string domain_; std::string path_; + std::string mac_key_; // TODO(abarth): Persist to disk. + std::string mac_algorithm_; // TODO(abarth): Persist to disk. base::Time creation_date_; base::Time expiry_date_; base::Time last_access_date_; @@ -699,6 +708,12 @@ class CookieMonster::ParsedCookie { const std::string& Path() const { return pairs_[path_index_].second; } bool HasDomain() const { return domain_index_ != 0; } const std::string& Domain() const { return pairs_[domain_index_].second; } + bool HasMACKey() const { return mac_key_index_ != 0; } + const std::string& MACKey() const { return pairs_[mac_key_index_].second; } + bool HasMACAlgorithm() const { return mac_algorithm_index_ != 0; } + const std::string& MACAlgorithm() const { + return pairs_[mac_algorithm_index_].second; + } bool HasExpires() const { return expires_index_ != 0; } const std::string& Expires() const { return pairs_[expires_index_].second; } bool HasMaxAge() const { return maxage_index_ != 0; } @@ -759,6 +774,8 @@ class CookieMonster::ParsedCookie { // could fit these into 3 bits each if we're worried about size... size_t path_index_; size_t domain_index_; + size_t mac_key_index_; + size_t mac_algorithm_index_; size_t expires_index_; size_t maxage_index_; size_t secure_index_; diff --git a/net/base/cookie_monster_store_test.cc b/net/base/cookie_monster_store_test.cc index 3fcaa29..b3a6c13 100644 --- a/net/base/cookie_monster_store_test.cc +++ b/net/base/cookie_monster_store_test.cc @@ -95,6 +95,7 @@ void AddCookieToList( scoped_ptr<CookieMonster::CanonicalCookie> cookie( new CookieMonster::CanonicalCookie( GURL(), pc.Name(), pc.Value(), key, cookie_path, + pc.MACKey(), pc.MACAlgorithm(), creation_time, creation_time, cookie_expires, pc.IsSecure(), pc.IsHttpOnly(), !cookie_expires.is_null())); @@ -163,10 +164,13 @@ CookieMonster* CreateMonsterFromStoreForGC( (i < num_old_cookies) ? current - base::TimeDelta::FromDays(days_old) : current; + std::string mac_key; + std::string mac_algorithm; + CookieMonster::CanonicalCookie cc( GURL(), "a", "1", base::StringPrintf("h%05d.izzle", i), "/path", - creation_time, expiration_time, last_access_time, - false, false, true); + mac_key, mac_algorithm, creation_time, expiration_time, + last_access_time, false, false, true); store->AddCookie(cc); } diff --git a/net/base/cookie_monster_unittest.cc b/net/base/cookie_monster_unittest.cc index abaf84c..8233c7e 100644 --- a/net/base/cookie_monster_unittest.cc +++ b/net/base/cookie_monster_unittest.cc @@ -253,6 +253,35 @@ TEST(ParsedCookieTest, MultipleEquals) { EXPECT_EQ(4U, pc.NumberOfAttributes()); } +TEST(ParsedCookieTest, MACKey) { + CookieMonster::ParsedCookie pc("foo=bar; MAC-Key=3900ac9anw9incvw9f"); + EXPECT_TRUE(pc.IsValid()); + EXPECT_EQ("foo", pc.Name()); + EXPECT_EQ("bar", pc.Value()); + EXPECT_EQ("3900ac9anw9incvw9f", pc.MACKey()); + EXPECT_EQ(1U, pc.NumberOfAttributes()); +} + +TEST(ParsedCookieTest, MACAlgorithm) { + CookieMonster::ParsedCookie pc("foo=bar; MAC-Algorithm=hmac-sha-1"); + EXPECT_TRUE(pc.IsValid()); + EXPECT_EQ("foo", pc.Name()); + EXPECT_EQ("bar", pc.Value()); + EXPECT_EQ("hmac-sha-1", pc.MACAlgorithm()); + EXPECT_EQ(1U, pc.NumberOfAttributes()); +} + +TEST(ParsedCookieTest, MACKeyAndMACAlgorithm) { + CookieMonster::ParsedCookie pc( + "foo=bar; MAC-Key=voiae-09fj0302nfqf; MAC-Algorithm=hmac-sha-256"); + EXPECT_TRUE(pc.IsValid()); + EXPECT_EQ("foo", pc.Name()); + EXPECT_EQ("bar", pc.Value()); + EXPECT_EQ("voiae-09fj0302nfqf", pc.MACKey()); + EXPECT_EQ("hmac-sha-256", pc.MACAlgorithm()); + EXPECT_EQ(2U, pc.NumberOfAttributes()); +} + TEST(ParsedCookieTest, QuotedTrailingWhitespace) { CookieMonster::ParsedCookie pc("ANCUUID=\"zohNumRKgI0oxyhSsV3Z7D\" ; " "expires=Sun, 18-Apr-2027 21:06:29 GMT ; " |