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 |
237 } // namespace | 294 } // namespace |
238 | 295 |
239 // static | 296 // static |
240 bool OAuthRequestSigner::Decode(const std::string& text, | 297 bool OAuthRequestSigner::Decode(const std::string& text, |
241 std::string* decoded_text) { | 298 std::string* decoded_text) { |
242 std::string accumulator = ""; | 299 std::string accumulator = ""; |
243 std::string::const_iterator cursor; | 300 std::string::const_iterator cursor; |
244 std::string::const_iterator limit; | 301 std::string::const_iterator limit; |
245 for (limit = text.end(), cursor = text.begin(); cursor != limit; ++cursor) { | 302 for (limit = text.end(), cursor = text.begin(); cursor != limit; ++cursor) { |
246 char character = *cursor; | 303 char character = *cursor; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 if (!query.empty()) { | 375 if (!query.empty()) { |
319 if (!ParseQuery(query, ¶meters)) | 376 if (!ParseQuery(query, ¶meters)) |
320 return false; | 377 return false; |
321 } | 378 } |
322 } | 379 } |
323 std::string spec = request_url_with_parameters.spec(); | 380 std::string spec = request_url_with_parameters.spec(); |
324 std::string url_without_parameters = spec; | 381 std::string url_without_parameters = spec; |
325 std::string::size_type question = spec.find("?"); | 382 std::string::size_type question = spec.find("?"); |
326 if (question != std::string::npos) | 383 if (question != std::string::npos) |
327 url_without_parameters = spec.substr(0,question); | 384 url_without_parameters = spec.substr(0,question); |
328 return Sign (GURL(url_without_parameters), parameters, signature_method, | 385 return SignURL(GURL(url_without_parameters), parameters, signature_method, |
329 http_method, consumer_key, consumer_secret, token_key, | 386 http_method, consumer_key, consumer_secret, token_key, |
330 token_secret, result); | 387 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; | |
355 } | 388 } |
356 | 389 |
357 // static | 390 // static |
358 bool OAuthRequestSigner::Sign( | 391 bool OAuthRequestSigner::SignURL( |
359 const GURL& request_base_url, | 392 const GURL& request_base_url, |
360 const Parameters& request_parameters, | 393 const Parameters& request_parameters, |
361 SignatureMethod signature_method, | 394 SignatureMethod signature_method, |
362 HttpMethod http_method, | 395 HttpMethod http_method, |
363 const std::string& consumer_key, | 396 const std::string& consumer_key, |
364 const std::string& consumer_secret, | 397 const std::string& consumer_secret, |
365 const std::string& token_key, | 398 const std::string& token_key, |
366 const std::string& token_secret, | 399 const std::string& token_secret, |
367 std::string* signed_text_return) { | 400 std::string* signed_text_return) { |
368 DCHECK(request_base_url.is_valid()); | 401 DCHECK(request_base_url.is_valid()); |
369 Parameters parameters = PrepareParameters(request_parameters, | 402 Parameters parameters(request_parameters); |
370 signature_method, | 403 bool is_signed = SignParameters(request_base_url, signature_method, |
371 http_method, | 404 http_method, consumer_key, consumer_secret, |
372 consumer_key, | 405 token_key, token_secret, ¶meters); |
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 } | |
394 if (is_signed) { | 406 if (is_signed) { |
395 std::string signed_text; | 407 std::string signed_text; |
396 switch (http_method) { | 408 switch (http_method) { |
397 case GET_METHOD: | 409 case GET_METHOD: |
398 signed_text = request_base_url.spec() + '?'; | 410 signed_text = request_base_url.spec() + '?'; |
399 // Intentionally falling through | 411 // Intentionally falling through |
400 case POST_METHOD: | 412 case POST_METHOD: |
401 signed_text += base_parameters + '&' + kOAuthSignatureLabel + '=' + | 413 signed_text += BuildBaseStringParameters(parameters); |
402 Encode(signature); | |
403 break; | 414 break; |
404 default: | 415 default: |
405 NOTREACHED(); | 416 NOTREACHED(); |
406 } | 417 } |
407 *signed_text_return = signed_text; | 418 *signed_text_return = signed_text; |
408 } | 419 } |
409 return is_signed; | 420 return is_signed; |
410 } | 421 } |
| 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 |