OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/common/net/gaia/oauth_request_signer.h" | 5 #include "chrome/common/net/gaia/oauth_request_signer.h" |
6 | 6 |
7 #include <cctype> | 7 #include <cctype> |
8 #include <cstddef> | 8 #include <cstddef> |
9 #include <cstdlib> | 9 #include <cstdlib> |
10 #include <cstring> | 10 #include <cstring> |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 // oauth_signature_method is RSA-SHA1. | 227 // oauth_signature_method is RSA-SHA1. |
228 // | 228 // |
229 // Not yet implemented, and might never be. | 229 // Not yet implemented, and might never be. |
230 bool SignRsaSha1(const std::string& text, | 230 bool SignRsaSha1(const std::string& text, |
231 const std::string& key, | 231 const std::string& key, |
232 std::string* result) { | 232 std::string* result) { |
233 NOTIMPLEMENTED(); | 233 NOTIMPLEMENTED(); |
234 return false; | 234 return false; |
235 } | 235 } |
236 | 236 |
237 // Adds parameters that are required by OAuth added as needed to |parameters|. | |
238 void PrepareParameters(OAuthRequestSigner::Parameters* parameters, | |
239 OAuthRequestSigner::SignatureMethod signature_method, | |
240 OAuthRequestSigner::HttpMethod http_method, | |
241 const std::string& consumer_key, | |
242 const std::string& token_key) { | |
243 if (parameters->find(kOAuthNonceLabel) == parameters->end()) | |
244 (*parameters)[kOAuthNonceLabel] = GenerateNonce(); | |
245 | |
246 if (parameters->find(kOAuthTimestampLabel) == parameters->end()) | |
247 (*parameters)[kOAuthTimestampLabel] = GenerateTimestamp(); | |
248 | |
249 (*parameters)[kOAuthConsumerKeyLabel] = consumer_key; | |
250 (*parameters)[kOAuthSignatureMethodLabel] = | |
251 SignatureMethodName(signature_method); | |
252 (*parameters)[kOAuthTokenLabel] = token_key; | |
253 (*parameters)[kOAuthVersionLabel] = kOAuthVersion; | |
254 } | |
255 | |
256 // Implements shared signing logic, generating the signature and storing it in | |
257 // |parameters|. Returns true if the signature has been generated succesfully. | |
258 bool SignParameters(const GURL& request_base_url, | |
259 OAuthRequestSigner::SignatureMethod signature_method, | |
260 OAuthRequestSigner::HttpMethod http_method, | |
261 const std::string& consumer_key, | |
262 const std::string& consumer_secret, | |
263 const std::string& token_key, | |
264 const std::string& token_secret, | |
265 OAuthRequestSigner::Parameters* parameters) { | |
266 DCHECK(request_base_url.is_valid()); | |
267 PrepareParameters(parameters, signature_method, http_method, | |
268 consumer_key, token_key); | |
269 std::string base_parameters = BuildBaseStringParameters(*parameters); | |
270 std::string base = BuildBaseString(request_base_url, http_method, | |
271 base_parameters); | |
272 std::string key = consumer_secret + '&' + token_secret; | |
273 bool is_signed = false; | |
274 std::string signature; | |
275 switch (signature_method) { | |
276 case OAuthRequestSigner::HMAC_SHA1_SIGNATURE: | |
277 is_signed = SignHmacSha1(base, key, &signature); | |
278 break; | |
279 case OAuthRequestSigner::RSA_SHA1_SIGNATURE: | |
280 is_signed = SignRsaSha1(base, key, &signature); | |
281 break; | |
282 case OAuthRequestSigner::PLAINTEXT_SIGNATURE: | |
283 is_signed = SignPlaintext(base, key, &signature); | |
284 break; | |
285 default: | |
286 NOTREACHED(); | |
287 } | |
288 if (is_signed) | |
289 (*parameters)[kOAuthSignatureLabel] = signature; | |
290 return is_signed; | |
291 } | |
292 | |
293 | |
294 } // namespace | 237 } // namespace |
295 | 238 |
296 // static | 239 // static |
297 bool OAuthRequestSigner::Decode(const std::string& text, | 240 bool OAuthRequestSigner::Decode(const std::string& text, |
298 std::string* decoded_text) { | 241 std::string* decoded_text) { |
299 std::string accumulator = ""; | 242 std::string accumulator = ""; |
300 std::string::const_iterator cursor; | 243 std::string::const_iterator cursor; |
301 std::string::const_iterator limit; | 244 std::string::const_iterator limit; |
302 for (limit = text.end(), cursor = text.begin(); cursor != limit; ++cursor) { | 245 for (limit = text.end(), cursor = text.begin(); cursor != limit; ++cursor) { |
303 char character = *cursor; | 246 char character = *cursor; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 if (!query.empty()) { | 318 if (!query.empty()) { |
376 if (!ParseQuery(query, ¶meters)) | 319 if (!ParseQuery(query, ¶meters)) |
377 return false; | 320 return false; |
378 } | 321 } |
379 } | 322 } |
380 std::string spec = request_url_with_parameters.spec(); | 323 std::string spec = request_url_with_parameters.spec(); |
381 std::string url_without_parameters = spec; | 324 std::string url_without_parameters = spec; |
382 std::string::size_type question = spec.find("?"); | 325 std::string::size_type question = spec.find("?"); |
383 if (question != std::string::npos) | 326 if (question != std::string::npos) |
384 url_without_parameters = spec.substr(0,question); | 327 url_without_parameters = spec.substr(0,question); |
385 return SignURL(GURL(url_without_parameters), parameters, signature_method, | 328 return Sign (GURL(url_without_parameters), parameters, signature_method, |
386 http_method, consumer_key, consumer_secret, token_key, | 329 http_method, consumer_key, consumer_secret, token_key, |
387 token_secret, result); | 330 token_secret, result); |
| 331 } |
| 332 |
| 333 // Returns a copy of request_parameters, with parameters that are required by |
| 334 // OAuth added as needed. |
| 335 OAuthRequestSigner::Parameters |
| 336 PrepareParameters(const OAuthRequestSigner::Parameters& request_parameters, |
| 337 OAuthRequestSigner::SignatureMethod signature_method, |
| 338 OAuthRequestSigner::HttpMethod http_method, |
| 339 const std::string& consumer_key, |
| 340 const std::string& token_key) { |
| 341 OAuthRequestSigner::Parameters result(request_parameters); |
| 342 |
| 343 if (result.find(kOAuthNonceLabel) == result.end()) |
| 344 result[kOAuthNonceLabel] = GenerateNonce(); |
| 345 |
| 346 if (result.find(kOAuthTimestampLabel) == result.end()) |
| 347 result[kOAuthTimestampLabel] = GenerateTimestamp(); |
| 348 |
| 349 result[kOAuthConsumerKeyLabel] = consumer_key; |
| 350 result[kOAuthSignatureMethodLabel] = SignatureMethodName(signature_method); |
| 351 result[kOAuthTokenLabel] = token_key; |
| 352 result[kOAuthVersionLabel] = kOAuthVersion; |
| 353 |
| 354 return result; |
388 } | 355 } |
389 | 356 |
390 // static | 357 // static |
391 bool OAuthRequestSigner::SignURL( | 358 bool OAuthRequestSigner::Sign( |
392 const GURL& request_base_url, | 359 const GURL& request_base_url, |
393 const Parameters& request_parameters, | 360 const Parameters& request_parameters, |
394 SignatureMethod signature_method, | 361 SignatureMethod signature_method, |
395 HttpMethod http_method, | 362 HttpMethod http_method, |
396 const std::string& consumer_key, | 363 const std::string& consumer_key, |
397 const std::string& consumer_secret, | 364 const std::string& consumer_secret, |
398 const std::string& token_key, | 365 const std::string& token_key, |
399 const std::string& token_secret, | 366 const std::string& token_secret, |
400 std::string* signed_text_return) { | 367 std::string* signed_text_return) { |
401 DCHECK(request_base_url.is_valid()); | 368 DCHECK(request_base_url.is_valid()); |
402 Parameters parameters(request_parameters); | 369 Parameters parameters = PrepareParameters(request_parameters, |
403 bool is_signed = SignParameters(request_base_url, signature_method, | 370 signature_method, |
404 http_method, consumer_key, consumer_secret, | 371 http_method, |
405 token_key, token_secret, ¶meters); | 372 consumer_key, |
| 373 token_key); |
| 374 std::string base_parameters = BuildBaseStringParameters(parameters); |
| 375 std::string base = BuildBaseString(request_base_url, |
| 376 http_method, |
| 377 base_parameters); |
| 378 std::string key = consumer_secret + '&' + token_secret; |
| 379 bool is_signed = false; |
| 380 std::string signature; |
| 381 switch (signature_method) { |
| 382 case HMAC_SHA1_SIGNATURE: |
| 383 is_signed = SignHmacSha1(base, key, &signature); |
| 384 break; |
| 385 case RSA_SHA1_SIGNATURE: |
| 386 is_signed = SignRsaSha1(base, key, &signature); |
| 387 break; |
| 388 case PLAINTEXT_SIGNATURE: |
| 389 is_signed = SignPlaintext(base, key, &signature); |
| 390 break; |
| 391 default: |
| 392 NOTREACHED(); |
| 393 } |
406 if (is_signed) { | 394 if (is_signed) { |
407 std::string signed_text; | 395 std::string signed_text; |
408 switch (http_method) { | 396 switch (http_method) { |
409 case GET_METHOD: | 397 case GET_METHOD: |
410 signed_text = request_base_url.spec() + '?'; | 398 signed_text = request_base_url.spec() + '?'; |
411 // Intentionally falling through | 399 // Intentionally falling through |
412 case POST_METHOD: | 400 case POST_METHOD: |
413 signed_text += BuildBaseStringParameters(parameters); | 401 signed_text += base_parameters + '&' + kOAuthSignatureLabel + '=' + |
| 402 Encode(signature); |
414 break; | 403 break; |
415 default: | 404 default: |
416 NOTREACHED(); | 405 NOTREACHED(); |
417 } | 406 } |
418 *signed_text_return = signed_text; | 407 *signed_text_return = signed_text; |
419 } | 408 } |
420 return is_signed; | 409 return is_signed; |
421 } | 410 } |
422 | |
423 // static | |
424 bool OAuthRequestSigner::SignAuthHeader( | |
425 const GURL& request_base_url, | |
426 const Parameters& request_parameters, | |
427 SignatureMethod signature_method, | |
428 HttpMethod http_method, | |
429 const std::string& consumer_key, | |
430 const std::string& consumer_secret, | |
431 const std::string& token_key, | |
432 const std::string& token_secret, | |
433 std::string* signed_text_return) { | |
434 DCHECK(request_base_url.is_valid()); | |
435 Parameters parameters(request_parameters); | |
436 bool is_signed = SignParameters(request_base_url, signature_method, | |
437 http_method, consumer_key, consumer_secret, | |
438 token_key, token_secret, ¶meters); | |
439 if (is_signed) { | |
440 std::string signed_text = "OAuth "; | |
441 bool first = true; | |
442 for (Parameters::const_iterator param = parameters.begin(); | |
443 param != parameters.end(); | |
444 ++param) { | |
445 if (first) | |
446 first = false; | |
447 else | |
448 signed_text += ", "; | |
449 signed_text += | |
450 StringPrintf("%s=\"%s\"", | |
451 OAuthRequestSigner::Encode(param->first).c_str(), | |
452 OAuthRequestSigner::Encode(param->second).c_str()); | |
453 } | |
454 *signed_text_return = signed_text; | |
455 } | |
456 return is_signed; | |
457 } | |
OLD | NEW |