summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/chromeos/external_cookie_handler.cc1
-rw-r--r--chrome/browser/chromeos/login/auth_response_handler.cc15
-rw-r--r--chrome/browser/chromeos/login/auth_response_handler.h36
-rw-r--r--chrome/browser/chromeos/login/authenticator.h4
-rw-r--r--chrome/browser/chromeos/login/client_login_response_handler.cc45
-rw-r--r--chrome/browser/chromeos/login/client_login_response_handler.h42
-rw-r--r--chrome/browser/chromeos/login/existing_user_controller.cc5
-rw-r--r--chrome/browser/chromeos/login/existing_user_controller.h3
-rw-r--r--chrome/browser/chromeos/login/google_authenticator.cc99
-rw-r--r--chrome/browser/chromeos/login/google_authenticator.h39
-rw-r--r--chrome/browser/chromeos/login/google_authenticator_unittest.cc132
-rw-r--r--chrome/browser/chromeos/login/issue_response_handler.cc38
-rw-r--r--chrome/browser/chromeos/login/issue_response_handler.h38
-rw-r--r--chrome/browser/chromeos/login/login_manager_view.cc6
-rw-r--r--chrome/browser/chromeos/login/login_manager_view.h4
-rw-r--r--chrome/browser/chromeos/login/login_status_consumer.h3
-rw-r--r--chrome/browser/chromeos/login/mock_auth_response_handler.h28
-rw-r--r--chrome/browser/chromeos/login/pam_google_authenticator.cc3
-rw-r--r--chrome/browser/chromeos/login/utils.cc16
-rw-r--r--chrome/browser/chromeos/login/utils.h4
-rwxr-xr-xchrome/chrome_browser.gypi6
21 files changed, 477 insertions, 90 deletions
diff --git a/chrome/browser/chromeos/external_cookie_handler.cc b/chrome/browser/chromeos/external_cookie_handler.cc
index 525ed80..5881532 100644
--- a/chrome/browser/chromeos/external_cookie_handler.cc
+++ b/chrome/browser/chromeos/external_cookie_handler.cc
@@ -68,6 +68,7 @@ bool ExternalCookieHandler::HandleCookies(net::CookieStore *cookie_store) {
// it in to the cookie jar.
std::string cookie_line = ReadLine(kChunkSize);
while (!cookie_line.empty()) {
+ LOG(WARNING) << cookie_line;
if (!cookie_store->SetCookieWithOptions(url, cookie_line, options))
return false;
cookie_line = ReadLine(kChunkSize);
diff --git a/chrome/browser/chromeos/login/auth_response_handler.cc b/chrome/browser/chromeos/login/auth_response_handler.cc
new file mode 100644
index 0000000..fea29af
--- /dev/null
+++ b/chrome/browser/chromeos/login/auth_response_handler.cc
@@ -0,0 +1,15 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/auth_response_handler.h"
+
+const char AuthResponseHandler::kClientLoginUrl[] =
+ "https://www.google.com/accounts/ClientLogin";
+const char AuthResponseHandler::kIssueAuthTokenUrl[] =
+ "https://www.google.com/accounts/IssueAuthToken";
+// TODO(cmasone): make sure that using an http:// URL in the "continue"
+// parameter here doesn't open the system up to attack long-term.
+const char AuthResponseHandler::kTokenAuthUrl[] =
+ "https://www.google.com/accounts/TokenAuth?"
+ "continue=http://www.google.com/webhp&source=chromeos&auth=";
diff --git a/chrome/browser/chromeos/login/auth_response_handler.h b/chrome/browser/chromeos/login/auth_response_handler.h
new file mode 100644
index 0000000..0c672c7
--- /dev/null
+++ b/chrome/browser/chromeos/login/auth_response_handler.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_AUTH_RESPONSE_HANDLER_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_AUTH_RESPONSE_HANDLER_H_
+
+#include <string>
+
+#include "chrome/browser/net/url_fetcher.h"
+
+class GURL;
+
+class AuthResponseHandler {
+ public:
+ AuthResponseHandler() {}
+ virtual ~AuthResponseHandler() {}
+
+ // True if this object can handle responses from |url|, false otherwise.
+ virtual bool CanHandle(const GURL& url) = 0;
+
+ // Caller takes ownership of return value.
+ // Takes in |to_process|, creates an appropriate URLFetcher to handle
+ // the next step, sets |catcher| to get called back when that fetcher is done.
+ // Starts the fetch and returns the fetcher, so the the caller can handle
+ // the object lifetime.
+ virtual URLFetcher* Handle(const std::string& to_process,
+ URLFetcher::Delegate* catcher) = 0;
+
+ // The URLs for different calls in the Google Accounts programmatic login API.
+ static const char kClientLoginUrl[];
+ static const char kIssueAuthTokenUrl[];
+ static const char kTokenAuthUrl[];
+};
+
+#endif // CHROME_BROWSER_CHROMEOS_LOGIN_AUTH_RESPONSE_HANDLER_H_
diff --git a/chrome/browser/chromeos/login/authenticator.h b/chrome/browser/chromeos/login/authenticator.h
index d03be58..d335127 100644
--- a/chrome/browser/chromeos/login/authenticator.h
+++ b/chrome/browser/chromeos/login/authenticator.h
@@ -5,6 +5,8 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_AUTHENTICATOR_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_AUTHENTICATOR_H_
+#include <vector>
+
#include "base/logging.h"
#include "chrome/browser/chromeos/login/login_status_consumer.h"
@@ -42,7 +44,7 @@ class StubAuthenticator : public Authenticator {
// Returns true after calling OnLoginSuccess().
virtual bool Authenticate(const std::string& username,
const std::string& password) {
- consumer_->OnLoginSuccess(username);
+ consumer_->OnLoginSuccess(username, std::vector<std::string>());
return true;
}
diff --git a/chrome/browser/chromeos/login/client_login_response_handler.cc b/chrome/browser/chromeos/login/client_login_response_handler.cc
new file mode 100644
index 0000000..97a2edc
--- /dev/null
+++ b/chrome/browser/chromeos/login/client_login_response_handler.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/client_login_response_handler.h"
+
+#include <algorithm>
+#include <string>
+
+#include "chrome/browser/chromeos/login/google_authenticator.h"
+#include "chrome/browser/net/chrome_url_request_context.h"
+#include "chrome/browser/net/url_fetcher.h"
+#include "net/base/load_flags.h"
+
+// By setting "service=gaia", we get an uber-auth-token back.
+const char ClientLoginResponseHandler::kService[] = "service=gaia";
+
+// Overridden from AuthResponseHandler.
+bool ClientLoginResponseHandler::CanHandle(const GURL& url) {
+ return (url.spec().find(AuthResponseHandler::kClientLoginUrl) !=
+ std::string::npos);
+}
+
+// Overridden from AuthResponseHandler.
+URLFetcher* ClientLoginResponseHandler::Handle(
+ const std::string& to_process,
+ URLFetcher::Delegate* catcher) {
+ LOG(INFO) << "ClientLogin successful!";
+ payload_.assign(to_process);
+ std::replace(payload_.begin(), payload_.end(), '\n', '&');
+ payload_.append(kService);
+
+ URLFetcher* fetcher =
+ new URLFetcher(GURL(AuthResponseHandler::kIssueAuthTokenUrl),
+ URLFetcher::POST,
+ catcher);
+ fetcher->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES);
+ fetcher->set_upload_data("application/x-www-form-urlencoded", payload_);
+ if (getter_) {
+ LOG(INFO) << "Fetching " << fetcher->url().spec();
+ fetcher->set_request_context(getter_);
+ fetcher->Start();
+ }
+ return fetcher;
+}
diff --git a/chrome/browser/chromeos/login/client_login_response_handler.h b/chrome/browser/chromeos/login/client_login_response_handler.h
new file mode 100644
index 0000000..2650261
--- /dev/null
+++ b/chrome/browser/chromeos/login/client_login_response_handler.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_CLIENT_LOGIN_RESPONSE_HANDLER_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_CLIENT_LOGIN_RESPONSE_HANDLER_H_
+
+#include <string>
+
+#include "base/logging.h"
+#include "chrome/browser/chromeos/login/auth_response_handler.h"
+
+class URLRequestContextGetter;
+
+class ClientLoginResponseHandler : public AuthResponseHandler {
+ public:
+ explicit ClientLoginResponseHandler(URLRequestContextGetter* getter)
+ : getter_(getter) {}
+ ~ClientLoginResponseHandler() {}
+
+ // Overridden from AuthResponseHandler.
+ virtual bool CanHandle(const GURL& url);
+
+ // Overridden from AuthResponseHandler.
+ // Takes in a response from ClientLogin, formats into an appropriate query
+ // to sent to IssueAuthToken and issues said query. |catcher| will receive
+ // the response to the fetch.
+ virtual URLFetcher* Handle(const std::string& to_process,
+ URLFetcher::Delegate* catcher);
+
+ // exposed for tests.
+ std::string payload() { return payload_; }
+
+ // A string that tells the Accounts backend to which service we're trying to
+ // authenticate.
+ static const char kService[];
+ private:
+ std::string payload_;
+ URLRequestContextGetter* getter_;
+};
+
+#endif // CHROME_BROWSER_CHROMEOS_LOGIN_CLIENT_LOGIN_RESPONSE_HANDLER_H_
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index 5fd0e65..e8df4bc 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -144,13 +144,14 @@ void ExistingUserController::OnLoginFailure(const std::string error) {
chromeos::WmIpc::instance()->SendMessage(message);
}
-void ExistingUserController::OnLoginSuccess(const std::string username) {
+void ExistingUserController::OnLoginSuccess(const std::string username,
+ std::vector<std::string> cookies) {
// Hide the login windows now.
STLDeleteElements(&controllers_);
background_window_->Close();
- chromeos::login_utils::CompleteLogin(username);
+ chromeos::login_utils::CompleteLogin(username, cookies);
// Delay deletion as we're on the stack.
MessageLoop::current()->DeleteSoon(FROM_HERE, this);
diff --git a/chrome/browser/chromeos/login/existing_user_controller.h b/chrome/browser/chromeos/login/existing_user_controller.h
index ea25d99..9e587fd 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.h
+++ b/chrome/browser/chromeos/login/existing_user_controller.h
@@ -65,7 +65,8 @@ class ExistingUserController : public WmMessageListener::Observer,
// LoginStatusConsumer:
virtual void OnLoginFailure(const std::string error);
- virtual void OnLoginSuccess(const std::string username);
+ virtual void OnLoginSuccess(const std::string username,
+ std::vector<std::string> cookies);
// Bounds of the background window.
const gfx::Rect background_bounds_;
diff --git a/chrome/browser/chromeos/login/google_authenticator.cc b/chrome/browser/chromeos/login/google_authenticator.cc
index 0cb2ae4..347f5e9 100644
--- a/chrome/browser/chromeos/login/google_authenticator.cc
+++ b/chrome/browser/chromeos/login/google_authenticator.cc
@@ -5,6 +5,7 @@
#include <errno.h>
#include <string>
#include <vector>
+#include <time.h>
#include "base/logging.h"
#include "base/file_path.h"
@@ -14,9 +15,12 @@
#include "base/string_util.h"
#include "base/third_party/nss/blapi.h"
#include "base/third_party/nss/sha256.h"
+#include "base/time.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cryptohome_library.h"
+#include "chrome/browser/chromeos/login/client_login_response_handler.h"
+#include "chrome/browser/chromeos/login/issue_response_handler.h"
#include "chrome/browser/chromeos/login/google_authenticator.h"
#include "chrome/browser/chromeos/login/login_status_consumer.h"
#include "chrome/browser/net/chrome_url_request_context.h"
@@ -28,11 +32,11 @@
#include "net/url_request/url_request_status.h"
#include "third_party/libjingle/files/talk/base/urlencode.h"
+using base::Time;
+using base::TimeDelta;
using namespace chromeos;
using namespace file_util;
-const char GoogleAuthenticator::kClientLoginUrl[] =
- "https://www.google.com/accounts/ClientLogin";
const char GoogleAuthenticator::kFormat[] =
"Email=%s&"
"Passwd=%s&"
@@ -42,6 +46,7 @@ const char GoogleAuthenticator::kFormat[] =
const char GoogleAuthenticator::kCookiePersistence[] = "true";
const char GoogleAuthenticator::kAccountType[] = "HOSTED_OR_GOOGLE";
const char GoogleAuthenticator::kSource[] = "chromeos";
+const int GoogleAuthenticator::kHttpSuccess = 200;
// Chromium OS system salt stored here
const char GoogleAuthenticator::kSystemSalt[] = "/home/.shadow/salt";
@@ -55,12 +60,11 @@ bool GoogleAuthenticator::Authenticate(const std::string& username,
PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
ProfileManager* profile_manager = g_browser_process->profile_manager();
Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
- URLRequestContextGetter *getter =
- profile->GetOffTheRecordProfile()->GetRequestContext();
- fetcher_.reset(new URLFetcher(GURL(kClientLoginUrl),
+ getter_ = profile->GetOffTheRecordProfile()->GetRequestContext();
+ fetcher_.reset(new URLFetcher(GURL(AuthResponseHandler::kClientLoginUrl),
URLFetcher::POST,
this));
- fetcher_->set_request_context(getter);
+ fetcher_->set_request_context(getter_);
fetcher_->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES);
// TODO(cmasone): be more careful about zeroing memory that stores
// the user's password.
@@ -72,6 +76,10 @@ bool GoogleAuthenticator::Authenticate(const std::string& username,
kSource);
fetcher_->set_upload_data("application/x-www-form-urlencoded", body);
fetcher_->Start();
+ if (!client_login_handler_.get())
+ client_login_handler_.reset(new ClientLoginResponseHandler(getter_));
+ if (!issue_handler_.get())
+ issue_handler_.reset(new IssueResponseHandler(getter_));
username_.assign(username);
StoreHashedPassword(password);
return true;
@@ -84,27 +92,32 @@ void GoogleAuthenticator::OnURLFetchComplete(const URLFetcher* source,
const ResponseCookies& cookies,
const std::string& data) {
if (status.is_success() && response_code == 200) {
- LOG(INFO) << "ClientLogin successful!";
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableFunction(GoogleAuthenticator::OnLoginSuccess,
- consumer_,
- library_,
- username_,
- ascii_hash_,
- data));
- } else if (!status.is_success() &&
- library_->CheckKey(username_.c_str(), ascii_hash_.c_str())) {
- // The fetch didn't succeed, but offline login did.
- LOG(INFO) << "Offline login successful!";
+ if (client_login_handler_->CanHandle(url)) {
+ fetcher_.reset(client_login_handler_->Handle(data, this));
+ } else if (issue_handler_->CanHandle(url)) {
+ fetcher_.reset(issue_handler_->Handle(data, this));
+ } else {
+ LOG(INFO) << "Online login successful!";
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableFunction(GoogleAuthenticator::OnLoginSuccess,
+ consumer_,
+ library_,
+ username_,
+ ascii_hash_,
+ cookies));
+ }
+ } else if (!status.is_success()) {
+ LOG(INFO) << "Network fail";
+ // The fetch failed for network reasons, try offline login.
ChromeThread::PostTask(
ChromeThread::UI, FROM_HERE,
- NewRunnableFunction(GoogleAuthenticator::OnLoginSuccess,
+ NewRunnableFunction(GoogleAuthenticator::CheckOffline,
consumer_,
library_,
username_,
ascii_hash_,
- data));
+ status));
} else {
std::string error;
if (status.is_success()) {
@@ -119,30 +132,46 @@ void GoogleAuthenticator::OnURLFetchComplete(const URLFetcher* source,
NewRunnableFunction(
GoogleAuthenticator::OnLoginFailure, consumer_, error));
}
- fetcher_.reset(NULL);
}
// static
-void GoogleAuthenticator::OnLoginSuccess(
- LoginStatusConsumer* consumer,
- CryptohomeLibrary* library,
- const std::string& username,
- const std::string& passhash,
- const std::string& client_login_data) {
- bool success = library->Mount(username.c_str(), passhash.c_str());
-
- // Also, convert client_login_data into legit cookies.
-
- if (success) {
- consumer->OnLoginSuccess(username);
+void GoogleAuthenticator::OnLoginSuccess(LoginStatusConsumer* consumer,
+ CryptohomeLibrary* library,
+ const std::string& username,
+ const std::string& passhash,
+ const ResponseCookies& cookies) {
+ if (library->Mount(username.c_str(), passhash.c_str()))
+ consumer->OnLoginSuccess(username, cookies);
+ else
+ GoogleAuthenticator::OnLoginFailure(consumer, "Could not mount cryptohome");
+}
+
+// static
+void GoogleAuthenticator::CheckOffline(LoginStatusConsumer* consumer,
+ CryptohomeLibrary* library,
+ const std::string& username,
+ const std::string& passhash,
+ const URLRequestStatus& status) {
+ if (library->CheckKey(username.c_str(), passhash.c_str())) {
+ // The fetch didn't succeed, but offline login did.
+ LOG(INFO) << "Offline login successful!";
+ ResponseCookies cookies;
+ GoogleAuthenticator::OnLoginSuccess(consumer,
+ library,
+ username,
+ passhash,
+ cookies);
} else {
- GoogleAuthenticator::OnLoginFailure(consumer, client_login_data);
+ // We couldn't hit the network, and offline login failed.
+ GoogleAuthenticator::OnLoginFailure(consumer, strerror(status.os_error()));
}
}
// static
void GoogleAuthenticator::OnLoginFailure(LoginStatusConsumer* consumer,
const std::string& data) {
+ // TODO(cmasone): what can we do to expose these OS/server-side error strings
+ // in an internationalizable way?
consumer->OnLoginFailure(data);
}
diff --git a/chrome/browser/chromeos/login/google_authenticator.h b/chrome/browser/chromeos/login/google_authenticator.h
index ec1806b..f8b6e10 100644
--- a/chrome/browser/chromeos/login/google_authenticator.h
+++ b/chrome/browser/chromeos/login/google_authenticator.h
@@ -15,6 +15,7 @@
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/cryptohome_library.h"
#include "chrome/browser/chromeos/login/authenticator.h"
+#include "chrome/browser/chromeos/login/auth_response_handler.h"
#include "chrome/browser/net/url_fetcher.h"
class LoginStatusConsumer;
@@ -25,17 +26,25 @@ class GoogleAuthenticator : public Authenticator,
public URLFetcher::Delegate {
public:
GoogleAuthenticator(LoginStatusConsumer* consumer,
- chromeos::CryptohomeLibrary* library)
+ chromeos::CryptohomeLibrary* library,
+ AuthResponseHandler* cl_handler,
+ AuthResponseHandler* i_handler)
: Authenticator(consumer),
library_(library),
- fetcher_(NULL) {
+ fetcher_(NULL),
+ getter_(NULL),
+ client_login_handler_(cl_handler),
+ issue_handler_(i_handler) {
if (!library && chromeos::CrosLibrary::EnsureLoaded())
library_ = chromeos::CryptohomeLibrary::Get();
}
explicit GoogleAuthenticator(LoginStatusConsumer* consumer)
: Authenticator(consumer),
- fetcher_(NULL) {
+ fetcher_(NULL),
+ getter_(NULL),
+ client_login_handler_(NULL),
+ issue_handler_(NULL) {
CHECK(chromeos::CrosLibrary::EnsureLoaded());
library_ = chromeos::CryptohomeLibrary::Get();
}
@@ -43,7 +52,11 @@ class GoogleAuthenticator : public Authenticator,
virtual ~GoogleAuthenticator() {}
// Given a |username| and |password|, this method attempts to authenticate to
- // the Google accounts servers.
+ // the Google accounts servers. The ultimate result is either a callback to
+ // consumer_->OnLoginSuccess() with the |username| and a vector of
+ // authentication cookies or a callback to consumer_->OnLoginFailure() with
+ // an error message.
+ //
// Returns true if the attempt gets sent successfully and false if not.
bool Authenticate(const std::string& username,
const std::string& password);
@@ -59,6 +72,9 @@ class GoogleAuthenticator : public Authenticator,
const ResponseCookies& cookies,
const std::string& data);
+ // Returns the ascii encoding of the system salt.
+ std::string SaltAsAscii();
+
// I need these static methods so I can PostTasks that use methods
// of sublcasses of LoginStatusConsumer. I can't seem to make
// RunnableMethods out of methods belonging to subclasses without referring
@@ -68,7 +84,12 @@ class GoogleAuthenticator : public Authenticator,
chromeos::CryptohomeLibrary* library,
const std::string& username,
const std::string& passhash,
- const std::string& client_login_data);
+ const ResponseCookies& cookies);
+ static void CheckOffline(LoginStatusConsumer* consumer,
+ chromeos::CryptohomeLibrary* library,
+ const std::string& username,
+ const std::string& passhash,
+ const URLRequestStatus& status);
static void OnLoginFailure(LoginStatusConsumer* consumer,
const std::string& data);
@@ -76,23 +97,25 @@ class GoogleAuthenticator : public Authenticator,
void set_system_salt(const std::vector<unsigned char>& fake_salt) {
system_salt_ = fake_salt;
}
+ void set_username(const std::string& fake_user) { username_ = fake_user; }
void set_password_hash(const std::string& fake_hash) {
ascii_hash_ = fake_hash;
}
- // Returns the ascii encoding of the system salt.
- std::string SaltAsAscii();
private:
static const char kCookiePersistence[];
static const char kAccountType[];
static const char kSource[];
- static const char kClientLoginUrl[];
static const char kFormat[];
+ static const int kHttpSuccess;
static const char kSystemSalt[];
static const char kOpenSSLMagic[];
chromeos::CryptohomeLibrary* library_;
scoped_ptr<URLFetcher> fetcher_;
+ URLRequestContextGetter* getter_;
+ scoped_ptr<AuthResponseHandler> client_login_handler_;
+ scoped_ptr<AuthResponseHandler> issue_handler_;
std::vector<unsigned char> system_salt_;
std::string username_;
std::string ascii_hash_;
diff --git a/chrome/browser/chromeos/login/google_authenticator_unittest.cc b/chrome/browser/chromeos/login/google_authenticator_unittest.cc
index bfc4a19..570463f 100644
--- a/chrome/browser/chromeos/login/google_authenticator_unittest.cc
+++ b/chrome/browser/chromeos/login/google_authenticator_unittest.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "chrome/browser/chromeos/login/google_authenticator.h"
+#include "chrome/browser/chromeos/login/client_login_response_handler.h"
+#include "chrome/browser/chromeos/login/issue_response_handler.h"
#include <errno.h>
#include <string>
@@ -11,7 +13,9 @@
#include "base/message_loop.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/chromeos/cros/mock_cryptohome_library.h"
+#include "chrome/browser/chromeos/login/mock_auth_response_handler.h"
#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/net/url_fetcher.h"
#include "googleurl/src/gurl.h"
#include "net/url_request/url_request_status.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -27,12 +31,13 @@ class MockConsumer : public LoginStatusConsumer {
MockConsumer() {}
~MockConsumer() {}
MOCK_METHOD1(OnLoginFailure, void(const std::string error));
- MOCK_METHOD1(OnLoginSuccess, void(const std::string username));
+ MOCK_METHOD2(OnLoginSuccess, void(const std::string username,
+ const std::vector<std::string> cookies));
};
class GoogleAuthenticatorTest : public ::testing::Test {
public:
- GoogleAuthenticatorTest() {
+ GoogleAuthenticatorTest() : username_("me@nowhere.org") {
memset(fake_hash_, 0, sizeof(fake_hash_));
fake_hash_[0] = 10;
fake_hash_[1] = 1;
@@ -45,7 +50,7 @@ class GoogleAuthenticatorTest : public ::testing::Test {
unsigned char fake_hash_[32];
std::string hash_ascii_;
std::string username_;
- std::string error_;
+ ResponseCookies cookies_;
};
TEST_F(GoogleAuthenticatorTest, SaltToAsciiTest) {
@@ -56,38 +61,54 @@ TEST_F(GoogleAuthenticatorTest, SaltToAsciiTest) {
std::vector<unsigned char> salt_v(fake_salt, fake_salt + sizeof(fake_salt));
MockCryptohomeLibrary library;
- GoogleAuthenticator auth(NULL, &library);
+ GoogleAuthenticator auth(NULL, &library, NULL, NULL);
auth.set_system_salt(salt_v);
EXPECT_EQ("0a010000000000a0", auth.SaltAsAscii());
}
-TEST_F(GoogleAuthenticatorTest, OnLoginSuccessTest) {
- error_.assign("Unexpected error");
+TEST_F(GoogleAuthenticatorTest, ClientLoginResponseHandlerTest) {
+ ClientLoginResponseHandler handler(NULL);
+ std::string input("a\nb\n");
+ std::string expected("a&b&");
+ expected.append(ClientLoginResponseHandler::kService);
+
+ scoped_ptr<URLFetcher> fetcher(handler.Handle(input, NULL));
+ EXPECT_EQ(expected, handler.payload());
+}
+
+TEST_F(GoogleAuthenticatorTest, IssueResponseHandlerTest) {
+ IssueResponseHandler handler(NULL);
+ std::string input("a\n");
+ std::string expected(IssueResponseHandler::kTokenAuthUrl);
+ expected.append(input);
+
+ scoped_ptr<URLFetcher> fetcher(handler.Handle(input, NULL));
+ EXPECT_EQ(expected, handler.token_url());
+}
+TEST_F(GoogleAuthenticatorTest, OnLoginSuccessTest) {
MockConsumer consumer;
- EXPECT_CALL(consumer, OnLoginSuccess(username_));
+ EXPECT_CALL(consumer, OnLoginSuccess(username_, _));
MockCryptohomeLibrary library;
EXPECT_CALL(library, Mount(username_, hash_ascii_))
.WillOnce(Return(true));
- GoogleAuthenticator auth(&consumer, &library);
- auth.OnLoginSuccess(&consumer, &library, username_, hash_ascii_, error_);
+ GoogleAuthenticator auth(&consumer, &library, NULL, NULL);
+ auth.OnLoginSuccess(&consumer, &library, username_, hash_ascii_, cookies_);
}
TEST_F(GoogleAuthenticatorTest, MountFailureTest) {
- error_.assign("Expected error");
-
MockConsumer consumer;
- EXPECT_CALL(consumer, OnLoginFailure(error_));
+ EXPECT_CALL(consumer, OnLoginFailure(_));
MockCryptohomeLibrary library;
EXPECT_CALL(library, Mount(username_, hash_ascii_))
.WillOnce(Return(false));
- GoogleAuthenticator auth(&consumer, &library);
- auth.OnLoginSuccess(&consumer, &library, username_, hash_ascii_, error_);
+ GoogleAuthenticator auth(&consumer, &library, NULL, NULL);
+ auth.OnLoginSuccess(&consumer, &library, username_, hash_ascii_, cookies_);
}
static void Quit() { MessageLoop::current()->Quit(); }
@@ -96,22 +117,22 @@ TEST_F(GoogleAuthenticatorTest, LoginNetFailureTest) {
ChromeThread ui_thread(ChromeThread::UI, &message_loop);
int error_no = ECONNRESET;
- error_.assign(strerror(error_no));
+ std::string data(strerror(error_no));
GURL source;
- ResponseCookies cookies;
URLRequestStatus status(URLRequestStatus::FAILED, error_no);
MockConsumer consumer;
- EXPECT_CALL(consumer, OnLoginFailure(error_))
+ EXPECT_CALL(consumer, OnLoginFailure(data))
.WillOnce(InvokeWithoutArgs(Quit));
MockCryptohomeLibrary library;
EXPECT_CALL(library, CheckKey(username_, hash_ascii_))
.WillOnce(Return(false));
- GoogleAuthenticator auth(&consumer, &library);
+ GoogleAuthenticator auth(&consumer, &library, NULL, NULL);
auth.set_password_hash(hash_ascii_);
- auth.OnURLFetchComplete(NULL, source, status, 0, cookies, std::string());
+ auth.set_username(username_);
+ auth.OnURLFetchComplete(NULL, source, status, 0, cookies_, data);
MessageLoop::current()->Run(); // So tasks can be posted.
}
@@ -119,19 +140,18 @@ TEST_F(GoogleAuthenticatorTest, LoginDeniedTest) {
MessageLoopForUI message_loop;
ChromeThread ui_thread(ChromeThread::UI, &message_loop);
- error_.assign("Error: NO!");
- GURL source;
- ResponseCookies cookies;
+ std::string data("Error: NO!");
+ GURL source(AuthResponseHandler::kTokenAuthUrl);
URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
MockConsumer consumer;
- EXPECT_CALL(consumer, OnLoginFailure(error_))
+ EXPECT_CALL(consumer, OnLoginFailure(data))
.WillOnce(InvokeWithoutArgs(Quit));
MockCryptohomeLibrary library;
- GoogleAuthenticator auth(&consumer, &library);
- auth.OnURLFetchComplete(NULL, source, status, 403, cookies, error_);
+ GoogleAuthenticator auth(&consumer, &library, NULL, NULL);
+ auth.OnURLFetchComplete(NULL, source, status, 403, cookies_, data);
MessageLoop::current()->Run(); // So tasks can be posted.
}
@@ -140,14 +160,13 @@ TEST_F(GoogleAuthenticatorTest, OfflineLoginTest) {
ChromeThread ui_thread(ChromeThread::UI, &message_loop);
int error_no = ECONNRESET;
- error_.assign(strerror(error_no));
+ std::string data(strerror(error_no));
GURL source;
- ResponseCookies cookies;
URLRequestStatus status(URLRequestStatus::FAILED, error_no);
MockConsumer consumer;
- EXPECT_CALL(consumer, OnLoginSuccess(username_))
+ EXPECT_CALL(consumer, OnLoginSuccess(username_, cookies_))
.WillOnce(InvokeWithoutArgs(Quit));
MockCryptohomeLibrary library;
EXPECT_CALL(library, CheckKey(username_, hash_ascii_))
@@ -155,9 +174,49 @@ TEST_F(GoogleAuthenticatorTest, OfflineLoginTest) {
EXPECT_CALL(library, Mount(username_, hash_ascii_))
.WillOnce(Return(true));
- GoogleAuthenticator auth(&consumer, &library);
+ GoogleAuthenticator auth(&consumer, &library, NULL, NULL);
+ auth.set_password_hash(hash_ascii_);
+ auth.set_username(username_);
+ auth.OnURLFetchComplete(NULL, source, status, 0, cookies_, data);
+ MessageLoop::current()->Run(); // So tasks can be posted.
+}
+
+TEST_F(GoogleAuthenticatorTest, ClientLoginPassIssueAuthTokenFailTest) {
+ MessageLoopForUI message_loop;
+ ChromeThread ui_thread(ChromeThread::UI, &message_loop);
+
+ std::string data("Error: NO!");
+ GURL cl_source(AuthResponseHandler::kClientLoginUrl);
+ GURL iat_source(AuthResponseHandler::kIssueAuthTokenUrl);
+ URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
+
+ MockConsumer consumer;
+ EXPECT_CALL(consumer, OnLoginFailure(data))
+ .WillOnce(InvokeWithoutArgs(Quit));
+ MockCryptohomeLibrary library;
+ MockAuthResponseHandler* cl_handler = new MockAuthResponseHandler;
+ EXPECT_CALL(*cl_handler, CanHandle(cl_source))
+ .WillOnce(Return(true));
+
+ GoogleAuthenticator auth(&consumer,
+ &library,
+ cl_handler, // takes ownership.
+ new IssueResponseHandler(NULL));
auth.set_password_hash(hash_ascii_);
- auth.OnURLFetchComplete(NULL, source, status, 0, cookies, std::string());
+ auth.set_username(username_);
+
+ EXPECT_CALL(*cl_handler, Handle(_, &auth))
+ .WillOnce(Return(new URLFetcher(GURL(""),
+ URLFetcher::POST,
+ &auth)));
+
+ auth.OnURLFetchComplete(NULL,
+ cl_source,
+ status,
+ 200,
+ cookies_,
+ std::string());
+ auth.OnURLFetchComplete(NULL, iat_source, status, 403, cookies_, data);
MessageLoop::current()->Run(); // So tasks can be posted.
}
@@ -165,20 +224,23 @@ TEST_F(GoogleAuthenticatorTest, OnlineLoginTest) {
MessageLoopForUI message_loop;
ChromeThread ui_thread(ChromeThread::UI, &message_loop);
- GURL source;
- ResponseCookies cookies;
+ GURL source(AuthResponseHandler::kTokenAuthUrl);
URLRequestStatus status(URLRequestStatus::SUCCESS, 0);
MockConsumer consumer;
- EXPECT_CALL(consumer, OnLoginSuccess(username_))
+ EXPECT_CALL(consumer, OnLoginSuccess(username_, cookies_))
.WillOnce(InvokeWithoutArgs(Quit));
MockCryptohomeLibrary library;
EXPECT_CALL(library, Mount(username_, hash_ascii_))
.WillOnce(Return(true));
- GoogleAuthenticator auth(&consumer, &library);
+ GoogleAuthenticator auth(&consumer,
+ &library,
+ new ClientLoginResponseHandler(NULL),
+ new IssueResponseHandler(NULL));
auth.set_password_hash(hash_ascii_);
- auth.OnURLFetchComplete(NULL, source, status, 200, cookies, std::string());
+ auth.set_username(username_);
+ auth.OnURLFetchComplete(NULL, source, status, 200, cookies_, std::string());
MessageLoop::current()->Run(); // So tasks can be posted.
}
diff --git a/chrome/browser/chromeos/login/issue_response_handler.cc b/chrome/browser/chromeos/login/issue_response_handler.cc
new file mode 100644
index 0000000..7c0850a
--- /dev/null
+++ b/chrome/browser/chromeos/login/issue_response_handler.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/issue_response_handler.h"
+
+#include <string>
+
+#include "chrome/browser/net/chrome_url_request_context.h"
+#include "chrome/browser/net/url_fetcher.h"
+#include "net/base/load_flags.h"
+
+const int kMaxRedirs = 2;
+const int kTimeout = 2;
+
+// Overridden from AuthResponseHandler.
+bool IssueResponseHandler::CanHandle(const GURL& url) {
+ return (url.spec().find(AuthResponseHandler::kIssueAuthTokenUrl) !=
+ std::string::npos);
+}
+
+// Overridden from AuthResponseHandler.
+URLFetcher* IssueResponseHandler::Handle(
+ const std::string& to_process,
+ URLFetcher::Delegate* catcher) {
+ LOG(INFO) << "IssueAuthToken successful!";
+ token_url_.assign(StringPrintf("%s%s",
+ AuthResponseHandler::kTokenAuthUrl,
+ to_process.c_str()));
+ URLFetcher* fetcher =
+ new URLFetcher(GURL(token_url_), URLFetcher::GET, catcher);
+ fetcher->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES);
+ if (getter_) {
+ fetcher->set_request_context(getter_);
+ fetcher->Start();
+ }
+ return fetcher;
+}
diff --git a/chrome/browser/chromeos/login/issue_response_handler.h b/chrome/browser/chromeos/login/issue_response_handler.h
new file mode 100644
index 0000000..3153b97
--- /dev/null
+++ b/chrome/browser/chromeos/login/issue_response_handler.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_ISSUE_RESPONSE_HANDLER_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_ISSUE_RESPONSE_HANDLER_H_
+
+#include <string>
+
+#include "base/logging.h"
+#include "chrome/browser/chromeos/login/auth_response_handler.h"
+
+class URLRequestContextGetter;
+
+class IssueResponseHandler : public AuthResponseHandler {
+ public:
+ explicit IssueResponseHandler(URLRequestContextGetter* getter)
+ : getter_(getter) {}
+ virtual ~IssueResponseHandler() {}
+
+ // Overridden from AuthResponseHandler.
+ virtual bool CanHandle(const GURL& url);
+
+ // Overridden from AuthResponseHandler.
+ // Takes in a response from IssueAuthToken, formats into an appropriate query
+ // to sent to TokenAuth, and issues said query. |catcher| will receive
+ // the response to the fetch.
+ virtual URLFetcher* Handle(const std::string& to_process,
+ URLFetcher::Delegate* catcher);
+
+ // exposed for testing
+ std::string token_url() { return token_url_; }
+ private:
+ std::string token_url_;
+ URLRequestContextGetter* getter_;
+};
+
+#endif // CHROME_BROWSER_CHROMEOS_LOGIN_ISSUE_RESPONSE_HANDLER_H_
diff --git a/chrome/browser/chromeos/login/login_manager_view.cc b/chrome/browser/chromeos/login/login_manager_view.cc
index d2bd8a6..179c9ad 100644
--- a/chrome/browser/chromeos/login/login_manager_view.cc
+++ b/chrome/browser/chromeos/login/login_manager_view.cc
@@ -79,6 +79,7 @@ LoginManagerView::LoginManagerView(ScreenObserver* observer)
authenticator_.reset(new StubAuthenticator(this));
else
authenticator_.reset(login_utils::CreateAuthenticator(this));
+
}
LoginManagerView::~LoginManagerView() {
@@ -334,12 +335,13 @@ void LoginManagerView::OnLoginFailure(const std::string error) {
// TODO(someone): get |error| onto the UI somehow?
}
-void LoginManagerView::OnLoginSuccess(const std::string username) {
+void LoginManagerView::OnLoginSuccess(const std::string username,
+ std::vector<std::string> cookies) {
// TODO(cmasone): something sensible if errors occur.
if (observer_) {
observer_->OnExit(ScreenObserver::LOGIN_SIGN_IN_SELECTED);
}
- login_utils::CompleteLogin(username);
+ login_utils::CompleteLogin(username, cookies);
}
void LoginManagerView::ShowError(int error_id) {
diff --git a/chrome/browser/chromeos/login/login_manager_view.h b/chrome/browser/chromeos/login/login_manager_view.h
index be971eb..3c9a64c 100644
--- a/chrome/browser/chromeos/login/login_manager_view.h
+++ b/chrome/browser/chromeos/login/login_manager_view.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_MANAGER_VIEW_H_
#include <string>
+#include <vector>
#include "base/scoped_ptr.h"
#include "chrome/browser/chromeos/login/authenticator.h"
@@ -70,7 +71,8 @@ class LoginManagerView : public views::View,
// Overriden from LoginStatusConsumer.
virtual void OnLoginFailure(const std::string error);
- virtual void OnLoginSuccess(const std::string username);
+ virtual void OnLoginSuccess(const std::string username,
+ std::vector<std::string> cookies);
protected:
// views::View overrides:
diff --git a/chrome/browser/chromeos/login/login_status_consumer.h b/chrome/browser/chromeos/login/login_status_consumer.h
index 5e3b07a..bf8f7e3 100644
--- a/chrome/browser/chromeos/login/login_status_consumer.h
+++ b/chrome/browser/chromeos/login/login_status_consumer.h
@@ -15,7 +15,8 @@ class LoginStatusConsumer {
virtual ~LoginStatusConsumer() {}
// These copy data in, so as to avoid potential object lifetime problems.
virtual void OnLoginFailure(const std::string error) = 0;
- virtual void OnLoginSuccess(const std::string username) = 0;
+ virtual void OnLoginSuccess(const std::string username,
+ std::vector<std::string> cookies) = 0;
};
diff --git a/chrome/browser/chromeos/login/mock_auth_response_handler.h b/chrome/browser/chromeos/login/mock_auth_response_handler.h
new file mode 100644
index 0000000..394dc7c
--- /dev/null
+++ b/chrome/browser/chromeos/login/mock_auth_response_handler.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_MOCK_AUTH_RESPONSE_HANDLER_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_MOCK_AUTH_RESPONSE_HANDLER_H_
+
+#include "chrome/browser/chromeos/login/auth_response_handler.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+class GURL;
+class URLFetcher;
+
+class MockAuthResponseHandler : public AuthResponseHandler {
+ public:
+ MockAuthResponseHandler() {}
+ virtual ~MockAuthResponseHandler() {}
+
+ MOCK_METHOD1(CanHandle, bool(const GURL& url));
+ MOCK_METHOD2(Handle, URLFetcher*(const std::string& to_process,
+ URLFetcher::Delegate* catcher));
+};
+
+#endif // CHROME_BROWSER_CHROMEOS_LOGIN_MOCK_AUTH_RESPONSE_HANDLER_H_
diff --git a/chrome/browser/chromeos/login/pam_google_authenticator.cc b/chrome/browser/chromeos/login/pam_google_authenticator.cc
index 2bd6ae0..689fde3 100644
--- a/chrome/browser/chromeos/login/pam_google_authenticator.cc
+++ b/chrome/browser/chromeos/login/pam_google_authenticator.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <string>
+#include <vector>
#include "base/logging.h"
#include "base/path_service.h"
@@ -27,7 +28,7 @@ bool PamGoogleAuthenticator::Authenticate(const std::string& username,
child_exit_code == 0);
if (ret)
- consumer_->OnLoginSuccess(username);
+ consumer_->OnLoginSuccess(username, std::vector<std::string>());
else
consumer_->OnLoginFailure("");
return ret;
diff --git a/chrome/browser/chromeos/login/utils.cc b/chrome/browser/chromeos/login/utils.cc
index 0fd5126..d94252e 100644
--- a/chrome/browser/chromeos/login/utils.cc
+++ b/chrome/browser/chromeos/login/utils.cc
@@ -15,18 +15,23 @@
#include "chrome/browser/chromeos/login/google_authenticator.h"
#include "chrome/browser/chromeos/login/pam_google_authenticator.h"
#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/net/url_request_context_getter.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/cookie_store.h"
+#include "net/url_request/url_request_context.h"
#include "views/widget/widget_gtk.h"
namespace chromeos {
namespace login_utils {
-void CompleteLogin(const std::string& username) {
+void CompleteLogin(const std::string& username,
+ std::vector<std::string> cookies) {
LOG(INFO) << "LoginManagerView: OnLoginSuccess()";
if (CrosLibrary::EnsureLoaded())
@@ -52,8 +57,15 @@ void CompleteLogin(const std::string& username) {
Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
int return_code;
- if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kInChromeAuth))
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kInChromeAuth)) {
ExternalCookieHandler::GetCookies(command_line, profile);
+ } else {
+ GURL url(ExternalCookieHandler::kGoogleAccountsUrl);
+ net::CookieOptions options;
+ options.set_include_httponly();
+ profile->GetRequestContext()->GetCookieStore()->SetCookiesWithOptions(
+ url, cookies, options);
+ }
browser_init.LaunchBrowser(command_line, profile, std::wstring(), true,
&return_code);
}
diff --git a/chrome/browser/chromeos/login/utils.h b/chrome/browser/chromeos/login/utils.h
index b7e28a9..c062982 100644
--- a/chrome/browser/chromeos/login/utils.h
+++ b/chrome/browser/chromeos/login/utils.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_CHROMEOS_LOGIN_UTILS_H_
#include <string>
+#include <vector>
class Authenticator;
class LoginStatusConsumer;
@@ -20,7 +21,8 @@ namespace login_utils {
// Invoked after the user has successfully logged in. This launches a browser
// and does other bookkeeping after logging in.
-void CompleteLogin(const std::string& username);
+void CompleteLogin(const std::string& username,
+ std::vector<std::string> cookies);
// Creates and returns the authenticator to use. The caller owns the returned
// Authenticator and must delete it when done.
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index a6f0e91..492c4311 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -361,8 +361,14 @@
'browser/chromeos/login/authenticator.h',
'browser/chromeos/login/background_view.cc',
'browser/chromeos/login/background_view.h',
+ 'browser/chromeos/login/auth_response_handler.cc',
+ 'browser/chromeos/login/auth_response_handler.h',
+ 'browser/chromeos/login/client_login_response_handler.cc',
+ 'browser/chromeos/login/client_login_response_handler.h',
'browser/chromeos/login/existing_user_controller.cc',
'browser/chromeos/login/existing_user_controller.h',
+ 'browser/chromeos/login/issue_response_handler.cc',
+ 'browser/chromeos/login/issue_response_handler.h',
'browser/chromeos/login/google_authenticator.cc',
'browser/chromeos/login/google_authenticator.h',
'browser/chromeos/login/pam_google_authenticator.cc',