Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(198)

Side by Side Diff: chrome/browser/sync/notifier/gaia_auth/gaiahelper.cc

Issue 194065: Initial commit of sync engine code to browser/sync.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Fixes to gtest include path, reverted syncapi. Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/sync/notifier/gaia_auth/gaiahelper.h"
6 #include "talk/base/common.h"
7 #include "talk/base/cryptstring.h"
8 #include "talk/base/httpclient.h"
9 #include "talk/base/httpcommon-inl.h"
10 #include "talk/base/stringutils.h"
11 #include "talk/base/urlencode.h"
12 #include "talk/xmpp/constants.h"
13 #include "talk/xmpp/jid.h"
14
15 ///////////////////////////////////////////////////////////////////////////////
16
17 namespace {
18
19 std::string GetValueForKey(const std::string & key, const std::string & nvp) {
20 size_t start_of_line = 0;
21 size_t end_of_line = 0;
22 for (;;) { // for each line
23 start_of_line = nvp.find_first_not_of("\r\n", end_of_line);
24 if (start_of_line == std::string::npos)
25 break;
26 end_of_line = nvp.find_first_of("\r\n", start_of_line);
27 if (end_of_line == std::string::npos) {
28 end_of_line = nvp.length();
29 }
30 size_t equals = nvp.find('=', start_of_line);
31 if (equals >= end_of_line ||
32 equals == std::string::npos ||
33 equals - start_of_line != key.length()) {
34 continue;
35 }
36
37 if (nvp.find(key, start_of_line) == start_of_line) {
38 return std::string(nvp, equals + 1, end_of_line - equals - 1);
39 }
40 }
41 return "";
42 }
43
44 } // anonymous namespace
45
46 ///////////////////////////////////////////////////////////////////////////////
47
48 namespace buzz {
49
50 GaiaServer::GaiaServer()
51 : hostname_("www.google.com"),
52 port_(443),
53 use_ssl_(true) {
54 }
55
56 bool GaiaServer::SetServer(const char* url) {
57 talk_base::Url<char> parsed(url);
58 hostname_ = parsed.server();
59 port_ = parsed.port();
60 use_ssl_ = parsed.secure();
61 return true; // parsed.valid();
62 }
63
64 bool GaiaServer::SetDebugServer(const char* server) {
65 const char* colon = strchr(server, ':');
66 if (colon) {
67 hostname_ = std::string(server, colon - server);
68 port_ = atoi(colon+1);
69 use_ssl_ = false;
70 return true;
71 }
72 return false;
73 }
74
75 std::string GaiaServer::http_prefix() const {
76 talk_base::Url<char> parsed("", hostname_, port_);
77 parsed.set_secure(use_ssl_);
78 return parsed.url();
79 }
80
81 ///////////////////////////////////////////////////////////////////////////////
82
83 bool GaiaRequestSid(talk_base::HttpClient* client,
84 const std::string& username,
85 const talk_base::CryptString& password,
86 const std::string& signature,
87 const std::string& service,
88 const CaptchaAnswer& captcha_answer,
89 const GaiaServer& gaia_server) {
90 buzz::Jid jid(username);
91 std::string usable_name = username;
92 if (jid.domain() == buzz::STR_DEFAULT_DOMAIN) {
93 // The default domain (default.talk.google.com) is not usable
94 // for Gaia auth. But both gmail.com and googlemain.com will
95 // work, because the gaia server doesn't check to make sure the
96 // appropriate one is being used. So we just slam on gmail.com
97 usable_name = jid.node() + "@" + buzz::STR_GMAIL_COM;
98 }
99
100 std::string post_data;
101 post_data += "Email=" + UrlEncodeString(usable_name);
102 post_data += "&Passwd=" + password.UrlEncode();
103 post_data += "&PersistentCookie=false";
104 post_data += "&source=" + signature;
105 // TODO(chron): This behavior is not the same as in the other gaia auth
106 // loader. We should make it the same. Probably GOOGLE is enough, we don't
107 // want to auth against hosted accounts.
108 post_data += "&accountType=HOSTED_OR_GOOGLE";
109 post_data += "&skipvpage=true";
110 if (!service.empty()) {
111 post_data += "&service=" + service;
112 }
113
114 if (!captcha_answer.captcha_token().empty()) {
115 post_data += "&logintoken=" + captcha_answer.captcha_token();
116 post_data += "&logincaptcha="
117 + UrlEncodeString(captcha_answer.captcha_answer());
118 }
119
120 client->reset();
121 client->set_server(talk_base::SocketAddress(gaia_server.hostname(),
122 gaia_server.port(), false));
123 client->request().verb = talk_base::HV_POST;
124 client->request().path = "/accounts/ClientAuth";
125 client->request().setContent("application/x-www-form-urlencoded",
126 new talk_base::MemoryStream(post_data.data(), post_data.size()));
127 client->response().document.reset(new talk_base::MemoryStream);
128 client->start();
129 return true;
130 }
131
132 GaiaResponse GaiaParseSidResponse(const talk_base::HttpClient& client,
133 const GaiaServer& gaia_server,
134 std::string* captcha_token,
135 std::string* captcha_url,
136 std::string* sid,
137 std::string* lsid,
138 std::string* auth) {
139 uint32 status_code = client.response().scode;
140 const talk_base::MemoryStream* stream =
141 static_cast<const talk_base::MemoryStream*>(
142 client.response().document.get());
143 size_t length;
144 stream->GetPosition(&length);
145 std::string response;
146 if (length > 0) {
147 response.assign(stream->GetBuffer(), length);
148 }
149
150 LOG(LS_INFO) << "GaiaAuth request to " << client.request().path;
151 LOG(LS_INFO) << "GaiaAuth Status Code: " << status_code;
152 LOG(LS_INFO) << response;
153
154 if (status_code == talk_base::HC_FORBIDDEN) {
155 // The error URL may be the relative path to the captcha jpg.
156 std::string image_url = GetValueForKey("CaptchaUrl", response);
157 if (!image_url.empty()) {
158 // We should activate this "full url code" once we have a better ways
159 // to crack the URL for later download. Right now we are too
160 // dependent on what Gaia returns.
161 #if 0
162 if (image_url.find("http://") != 0 &&
163 image_url.find("https://") != 0) {
164 if (image_url.find("/") == 0) {
165 *captcha_url = gaia_server.http_prefix() + image_url;
166 } else {
167 *captcha_url = Utf8(gaia_server.http_prefix()).AsString()
168 + "/accounts/" + image_url;
169 }
170 }
171 #else
172 *captcha_url = "/accounts/" + image_url;
173 #endif
174
175 *captcha_token = GetValueForKey("CaptchaToken", response);
176 }
177 return GR_UNAUTHORIZED;
178 }
179
180 if (status_code != talk_base::HC_OK) {
181 return GR_ERROR;
182 }
183
184 *sid = GetValueForKey("SID", response);
185 *lsid = GetValueForKey("LSID", response);
186 if (auth) {
187 *auth = GetValueForKey("Auth", response);
188 }
189 if (sid->empty() || lsid->empty()) {
190 return GR_ERROR;
191 }
192
193 return GR_SUCCESS;
194 }
195
196 bool GaiaRequestAuthToken(talk_base::HttpClient* client,
197 const std::string& sid,
198 const std::string& lsid,
199 const std::string& service,
200 const GaiaServer& gaia_server) {
201 std::string post_data;
202 post_data += "SID=" + UrlEncodeString(sid);
203 post_data += "&LSID=" + UrlEncodeString(lsid);
204 post_data += "&service=" + service;
205 post_data += "&Session=true"; // creates two week cookie
206
207 client->reset();
208 client->set_server(talk_base::SocketAddress(gaia_server.hostname(),
209 gaia_server.port(), false));
210 client->request().verb = talk_base::HV_POST;
211 client->request().path = "/accounts/IssueAuthToken";
212 client->request().setContent("application/x-www-form-urlencoded",
213 new talk_base::MemoryStream(post_data.data(), post_data.size()));
214 client->response().document.reset(new talk_base::MemoryStream);
215 client->start();
216 return true;
217 }
218
219 GaiaResponse GaiaParseAuthTokenResponse(const talk_base::HttpClient& client,
220 std::string* auth_token) {
221 if (client.response().scode != talk_base::HC_OK) {
222 return GR_ERROR;
223 }
224
225 const talk_base::MemoryStream* stream =
226 static_cast<const talk_base::MemoryStream*>(
227 client.response().document.get());
228 size_t length;
229 stream->GetPosition(&length);
230 while ((length > 0) && isspace(stream->GetBuffer()[length-1]))
231 --length;
232 auth_token->assign(stream->GetBuffer(), length);
233 return auth_token->empty() ? GR_ERROR : GR_SUCCESS;
234 }
235
236 } // namespace buzz
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698