summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sync/notifier/gaia_auth/gaiaauth.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/sync/notifier/gaia_auth/gaiaauth.cc')
-rw-r--r--chrome/browser/sync/notifier/gaia_auth/gaiaauth.cc435
1 files changed, 0 insertions, 435 deletions
diff --git a/chrome/browser/sync/notifier/gaia_auth/gaiaauth.cc b/chrome/browser/sync/notifier/gaia_auth/gaiaauth.cc
deleted file mode 100644
index 1558b06..0000000
--- a/chrome/browser/sync/notifier/gaia_auth/gaiaauth.cc
+++ /dev/null
@@ -1,435 +0,0 @@
-// Copyright (c) 2009 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 <string>
-
-#include "base/logging.h"
-#include "base/message_loop.h"
-#include "base/task.h"
-#include "base/thread.h"
-#include "chrome/browser/sync/notifier/base/ssl_adapter.h"
-#include "chrome/browser/sync/notifier/gaia_auth/gaiaauth.h"
-#include "talk/base/asynchttprequest.h"
-#include "talk/base/firewallsocketserver.h"
-#include "talk/base/httpclient.h"
-#include "talk/base/physicalsocketserver.h"
-#include "talk/base/socketadapters.h"
-#include "talk/base/socketpool.h"
-#include "talk/base/stringutils.h"
-#include "talk/base/urlencode.h"
-#include "talk/xmpp/saslcookiemechanism.h"
-#include "talk/xmpp/saslplainmechanism.h"
-
-namespace buzz {
-
-static const int kGaiaAuthTimeoutMs = 30 * 1000; // 30 sec
-
-// Warning, this is externed.
-GaiaServer g_gaia_server;
-
-///////////////////////////////////////////////////////////////////////////////
-// GaiaAuth::WorkerTask
-///////////////////////////////////////////////////////////////////////////////
-
-// GaiaAuth is NOT invoked during SASL authentication, but it is invoked even
-// before XMPP login begins. As a PreXmppAuth object, it is driven by
-// XmppClient before the XMPP socket is opened. The job of GaiaAuth is to goes
-// out using HTTPS POST to grab cookies from GAIA.
-//
-// It is used by XmppClient. It grabs a SaslAuthenticator which knows how to
-// play the cookie login.
-
-class GaiaAuth::WorkerTask {
- public:
- WorkerTask(const std::string& username,
- const talk_base::CryptString& pass,
- const std::string& service,
- const talk_base::ProxyInfo& proxy,
- talk_base::FirewallManager* firewall,
- const std::string& token,
- const CaptchaAnswer& captcha_answer,
- bool obtain_auth,
- const std::string& user_agent,
- const std::string& signature,
- const std::string& token_service) :
- username_(username),
- pass_(pass),
- service_(service),
- proxy_(proxy),
- firewall_(firewall),
- success_(false),
- error_(true),
- error_code_(0),
- proxy_auth_required_(false),
- certificate_expired_(false),
- auth_token_(token),
- captcha_answer_(captcha_answer),
- fresh_auth_token_(false),
- obtain_auth_(obtain_auth),
- agent_(user_agent),
- signature_(signature),
- token_service_(token_service) {}
-
- ~WorkerTask() {}
-
- void DoWork(MessageLoop* parent_message_loop, Task* on_work_done_task) {
- DCHECK(parent_message_loop);
- DCHECK(on_work_done_task);
- LOG(INFO) << "GaiaAuth Begin";
- // Maybe we already have an auth token, then there is nothing to do.
- if (!auth_token_.empty()) {
- LOG(INFO) << "Reusing auth token:" << auth_token_;
- success_ = true;
- error_ = false;
- } else {
- // SocketFactory::CreateSSLAdapter() is called on the following
- // object somewhere in the depths of libjingle so we wrap it
- // with SSLAdapterSocketFactory to make sure it returns the
- // right SSLAdapter (see http://crbug.com/30721 ).
- notifier::SSLAdapterSocketFactory<talk_base::PhysicalSocketServer>
- physical;
- talk_base::SocketServer* ss = &physical;
- if (firewall_) {
- ss = new talk_base::FirewallSocketServer(ss, firewall_);
- }
-
- talk_base::SslSocketFactory factory(ss, agent_);
- factory.SetProxy(proxy_);
- if (g_gaia_server.use_ssl()) {
- factory.SetIgnoreBadCert(true);
- factory.UseSSL(g_gaia_server.hostname().c_str());
- }
- factory.SetLogging(talk_base::LS_VERBOSE, "GaiaAuth");
-
-#if defined(OS_WIN)
- talk_base::ReuseSocketPool pool(&factory);
-#else
- // On non-Windows platforms our SSL socket wrapper
- // implementation does not support restartable SSL sockets, so
- // we turn it off and use a NewSocketPool instead. This means
- // that we create separate connections for each HTTP request but
- // this is okay since we do only two (in GaiaRequestSid() and
- // GaiaRequestAuthToken()).
- factory.SetUseRestartableSSLSockets(false);
- talk_base::NewSocketPool pool(&factory);
-#endif
- talk_base::HttpClient http(agent_, &pool);
-
- talk_base::HttpMonitor monitor(ss);
- monitor.Connect(&http);
-
- // If we do not already have a SID, let's get one using our password.
- if (sid_.empty() || (auth_.empty() && obtain_auth_)) {
- GaiaRequestSid(&http, username_, pass_, signature_,
- obtain_auth_ ? service_ : "", captcha_answer_,
- g_gaia_server);
- // TODO(akalin): handle timeouts better; this can cause jank,
- // e.g. when we're waiting on this and the user stops syncing,
- // which causes the GaiaAuth object to be destroyed, which
- // waits on this. (bug: http://crbug.com/31981 )
- ss->Wait(kGaiaAuthTimeoutMs, true);
-
- error_code_ = monitor.error(); // Save off the error code.
-
- if (!monitor.done()) {
- LOG(INFO) << "GaiaAuth request timed out";
- goto Cleanup;
- } else if (monitor.error()) {
- LOG(INFO) << "GaiaAuth request error: " << monitor.error();
- if (monitor.error() == talk_base::HE_AUTH) {
- success_ = false;
- proxy_auth_required_ = true;
- } else if (monitor.error() == talk_base::HE_CERTIFICATE_EXPIRED) {
- success_ = false;
- certificate_expired_ = true;
- }
- goto Cleanup;
- } else {
- std::string captcha_token, captcha_url;
- switch (GaiaParseSidResponse(http, g_gaia_server,
- &captcha_token, &captcha_url,
- &sid_, &lsid_, &auth_)) {
- case GR_ERROR:
- goto Cleanup;
-
- case GR_UNAUTHORIZED:
- if (!captcha_url.empty()) {
- captcha_challenge_ = buzz::CaptchaChallenge(captcha_token,
- captcha_url);
- }
- // We had no "error" - we were just unauthorized.
- error_ = false;
- error_code_ = 0;
- goto Cleanup;
-
- case GR_SUCCESS:
- break;
- }
- }
- }
-
- // If all we need is a SID, then we are done now.
- if (service_.empty() || obtain_auth_) {
- success_ = true;
- error_ = false;
- error_code_ = 0;
- goto Cleanup;
- }
-
- monitor.reset();
- GaiaRequestAuthToken(&http, sid_, lsid_, service_, g_gaia_server);
- ss->Wait(kGaiaAuthTimeoutMs, true);
-
- error_code_ = monitor.error(); // Save off the error code.
-
- if (!monitor.done()) {
- LOG(INFO) << "GaiaAuth request timed out";
- } else if (monitor.error()) {
- LOG(INFO) << "GaiaAuth request error: " << monitor.error();
- if (monitor.error() == talk_base::HE_AUTH) {
- success_ = false;
- proxy_auth_required_ = true;
- } else if (monitor.error() == talk_base::HE_CERTIFICATE_EXPIRED) {
- success_ = false;
- certificate_expired_ = true;
- }
- } else {
- if (GR_SUCCESS == GaiaParseAuthTokenResponse(http, &auth_token_)) {
- fresh_auth_token_ = true;
- success_ = true;
- error_ = false;
- error_code_ = 0;
- }
- }
- }
-
- // Done authenticating.
-
- Cleanup:
- LOG(INFO) << "GaiaAuth done";
- parent_message_loop->PostTask(FROM_HERE, on_work_done_task);
- }
-
- bool Succeeded() const { return success_; }
- bool HadError() const { return error_; }
- int GetError() const { return error_code_; }
- bool ProxyAuthRequired() const { return proxy_auth_required_; }
- bool CertificateExpired() const { return certificate_expired_; }
- const buzz::CaptchaChallenge& GetCaptchaChallenge() {
- return captcha_challenge_;
- }
- bool fresh_auth_token() const { return fresh_auth_token_; }
-
- talk_base::CryptString GetPassword() const { return pass_; }
- std::string GetSID() const { return sid_; }
- std::string GetAuth() const { return auth_; }
- std::string GetToken() const { return auth_token_; }
- std::string GetUsername() const { return username_; }
- std::string GetTokenService() const { return token_service_; }
-
- private:
- std::string username_;
- talk_base::CryptString pass_;
- std::string service_;
- talk_base::ProxyInfo proxy_;
- talk_base::FirewallManager * firewall_;
- bool done_;
- bool success_;
- bool error_;
- int error_code_;
- bool proxy_auth_required_;
- bool certificate_expired_;
- std::string sid_;
- std::string lsid_;
- std::string auth_;
- std::string auth_token_;
- buzz::CaptchaChallenge captcha_challenge_;
- CaptchaAnswer captcha_answer_;
- bool fresh_auth_token_;
- bool obtain_auth_;
- std::string agent_;
- std::string signature_;
- std::string token_service_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerTask);
-};
-
-} // namespace buzz
-
-// We outlive any runnable methods we create, so stub out
-// RunnableMethodTraits for GaiaAuth and WorkerTask.
-
-template <>
-struct RunnableMethodTraits<buzz::GaiaAuth> {
- void RetainCallee(buzz::GaiaAuth* gaia_auth) {}
- void ReleaseCallee(buzz::GaiaAuth* gaia_auth) {}
-};
-
-template <>
-struct RunnableMethodTraits<buzz::GaiaAuth::WorkerTask> {
- void RetainCallee(buzz::GaiaAuth::WorkerTask* gaia_auth) {}
- void ReleaseCallee(buzz::GaiaAuth::WorkerTask* gaia_auth) {}
-};
-
-namespace buzz {
-
-///////////////////////////////////////////////////////////////////////////////
-// GaiaAuth
-///////////////////////////////////////////////////////////////////////////////
-
-GaiaAuth::GaiaAuth(const std::string &user_agent, const std::string &sig)
- : agent_(user_agent), signature_(sig), firewall_(0),
- worker_task_(NULL), on_work_done_task_(NULL),
- worker_thread_("GaiaAuth worker thread"), done_(false),
- current_message_loop_(MessageLoop::current()) {
- DCHECK(current_message_loop_);
-}
-
-GaiaAuth::~GaiaAuth() {
- DCHECK_EQ(MessageLoop::current(), current_message_loop_);
- // Wait until worker thread stops running.
- worker_thread_.Stop();
- // Then, if the worker thread posted an OnAuthDone() task that is
- // still pending, cancel it.
- if (on_work_done_task_) {
- on_work_done_task_->Cancel();
- }
-}
-
-void GaiaAuth::StartPreXmppAuth(const buzz::Jid& jid,
- const talk_base::SocketAddress& server,
- const talk_base::CryptString& pass,
- const std::string & auth_cookie) {
- InternalStartGaiaAuth(jid, server, pass, auth_cookie, "mail", false);
-}
-
-void GaiaAuth::StartTokenAuth(const buzz::Jid& jid,
- const talk_base::CryptString& pass,
- const std::string& service) {
- InternalStartGaiaAuth(jid, talk_base::SocketAddress(), pass, "", service,
- false);
-}
-
-void GaiaAuth::StartAuth(const buzz::Jid& jid,
- const talk_base::CryptString& pass,
- const std::string & service) {
- InternalStartGaiaAuth(jid, talk_base::SocketAddress(), pass, "", service,
- true);
-}
-
-void GaiaAuth::StartAuthFromSid(const buzz::Jid& jid,
- const std::string& sid,
- const std::string& service) {
- InternalStartGaiaAuth(jid, talk_base::SocketAddress(),
- talk_base::CryptString(), sid, service, false);
-}
-
-void GaiaAuth::InternalStartGaiaAuth(const buzz::Jid& jid,
- const talk_base::SocketAddress& server,
- const talk_base::CryptString& pass,
- const std::string& token,
- const std::string& service,
- bool obtain_auth) {
- DCHECK_EQ(MessageLoop::current(), current_message_loop_);
- worker_task_.reset(
- new WorkerTask(jid.Str(), pass, service, proxy_, firewall_,
- token, captcha_answer_, obtain_auth, agent_,
- signature_, token_service_));
- on_work_done_task_ = NewRunnableMethod(this, &GaiaAuth::OnAuthDone);
- LOG(INFO) << "GaiaAuth begin (async)";
- worker_thread_.Start();
- worker_thread_.message_loop()->PostTask(
- FROM_HERE, NewRunnableMethod(worker_task_.get(),
- &WorkerTask::DoWork,
- current_message_loop_,
- on_work_done_task_));
-}
-
-void GaiaAuth::OnAuthDone() {
- DCHECK_EQ(MessageLoop::current(), current_message_loop_);
- LOG(INFO) << "GaiaAuth done (async)";
- worker_thread_.Stop();
- on_work_done_task_ = NULL;
- done_ = true;
-
- if (worker_task_->fresh_auth_token()) {
- SignalFreshAuthCookie(worker_task_->GetToken());
- }
- if (worker_task_->ProxyAuthRequired()) {
- SignalAuthenticationError();
- }
- if (worker_task_->CertificateExpired()) {
- SignalCertificateExpired();
- }
- SignalAuthDone();
-}
-
-std::string GaiaAuth::CreateAuthenticatedUrl(
- const std::string & continue_url, const std::string & service) {
- if (!done_ || worker_task_->GetToken().empty())
- return "";
-
- std::string url;
- // Note that http_prefix always ends with a "/".
- url += g_gaia_server.http_prefix()
- + "accounts/TokenAuth?auth="
- // Do not URL encode - GAIA doesn't like that.
- + worker_task_->GetToken();
- url += "&service=" + service;
- url += "&continue=" + UrlEncodeString(continue_url);
- url += "&source=" + signature_;
- return url;
-}
-
-std::string GaiaAuth::GetAuthCookie() {
- assert(IsAuthDone() && IsAuthorized());
- if (!done_ || !worker_task_->Succeeded()) {
- return "";
- }
- return worker_task_->GetToken();
-}
-
-std::string GaiaAuth::GetAuth() {
- assert(IsAuthDone() && IsAuthorized());
- if (!done_ || !worker_task_->Succeeded()) {
- return "";
- }
- return worker_task_->GetAuth();
-}
-
-std::string GaiaAuth::GetSID() {
- assert(IsAuthDone() && IsAuthorized());
- if (!done_ || !worker_task_->Succeeded()) {
- return "";
- }
- return worker_task_->GetSID();
-}
-
-bool GaiaAuth::IsAuthDone() {
- return done_;
-}
-
-bool GaiaAuth::IsAuthorized() {
- return done_ && worker_task_ != NULL && worker_task_->Succeeded();
-}
-
-bool GaiaAuth::HadError() {
- return done_ && worker_task_ != NULL && worker_task_->HadError();
-}
-
-int GaiaAuth::GetError() {
- if (done_ && worker_task_ != NULL) {
- return worker_task_->GetError();
- }
- return 0;
-}
-
-buzz::CaptchaChallenge GaiaAuth::GetCaptchaChallenge() {
- if (!done_ || worker_task_->Succeeded()) {
- return buzz::CaptchaChallenge();
- }
- return worker_task_->GetCaptchaChallenge();
-}
-
-} // namespace buzz