OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/browser/local_discovery/privetv3_session.h" | 5 #include "chrome/browser/local_discovery/privetv3_session.h" |
6 | 6 |
7 #include "base/base64.h" | 7 #include "base/base64.h" |
8 #include "base/json/json_writer.h" | 8 #include "base/json/json_writer.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
11 #include "chrome/browser/local_discovery/privet_constants.h" | 11 #include "chrome/browser/local_discovery/privet_constants.h" |
12 #include "chrome/browser/local_discovery/privet_http.h" | 12 #include "chrome/browser/local_discovery/privet_http.h" |
13 #include "chrome/browser/local_discovery/privet_url_fetcher.h" | 13 #include "chrome/browser/local_discovery/privet_url_fetcher.h" |
14 #include "chrome/common/cloud_print/cloud_print_constants.h" | 14 #include "chrome/common/cloud_print/cloud_print_constants.h" |
15 #include "crypto/hmac.h" | 15 #include "crypto/hmac.h" |
16 #include "crypto/p224_spake.h" | 16 #include "crypto/p224_spake.h" |
17 #include "url/gurl.h" | 17 #include "url/gurl.h" |
18 | 18 |
19 namespace local_discovery { | 19 namespace local_discovery { |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
23 const char kPrivetV3AuthAnonymous[] = "Privet anonymous"; | 23 const char kPrivetV3AuthAnonymous[] = "Privet anonymous"; |
24 const char kPrivetV3CryptoP224Spake2[] = "p224_spake2"; | 24 const char kPrivetV3CryptoP224Spake2[] = "p224_spake2"; |
| 25 const char kPrivetV3Auto[] = "auto"; |
25 | 26 |
26 const char kPrivetV3InfoKeyAuth[] = "authentication"; | 27 const char kPrivetV3InfoKeyAuth[] = "authentication"; |
27 const char kPrivetV3InfoKeyVersion[] = "version"; | 28 const char kPrivetV3InfoKeyVersion[] = "version"; |
28 const char kPrivetV3InfoVersion[] = "3.0"; | 29 const char kPrivetV3InfoVersion[] = "3.0"; |
29 | 30 |
| 31 const char kPrivetV3KeyAccessToken[] = "accessToken"; |
| 32 const char kPrivetV3KeyAuthCode[] = "authCode"; |
30 const char kPrivetV3KeyCertFingerprint[] = "certFingerprint"; | 33 const char kPrivetV3KeyCertFingerprint[] = "certFingerprint"; |
31 const char kPrivetV3KeyCertSignature[] = "certSignature"; | 34 const char kPrivetV3KeyCertSignature[] = "certSignature"; |
32 const char kPrivetV3KeyClientCommitment[] = "clientCommitment"; | 35 const char kPrivetV3KeyClientCommitment[] = "clientCommitment"; |
33 const char kPrivetV3KeyCrypto[] = "crypto"; | 36 const char kPrivetV3KeyCrypto[] = "crypto"; |
34 const char kPrivetV3KeyDeviceCommitment[] = "deviceCommitment"; | 37 const char kPrivetV3KeyDeviceCommitment[] = "deviceCommitment"; |
35 const char kPrivetV3KeyMode[] = "mode"; | 38 const char kPrivetV3KeyMode[] = "mode"; |
36 const char kPrivetV3KeyPairing[] = "pairing"; | 39 const char kPrivetV3KeyPairing[] = "pairing"; |
| 40 const char kPrivetV3KeyRequestedScope[] = "requestedScope"; |
| 41 const char kPrivetV3KeyScope[] = "scope"; |
37 const char kPrivetV3KeySessionId[] = "sessionId"; | 42 const char kPrivetV3KeySessionId[] = "sessionId"; |
| 43 const char kPrivetV3KeyTokenType[] = "tokenType"; |
38 | 44 |
| 45 const char kPrivetV3PairingStartPath[] = "/privet/v3/pairing/start"; |
39 const char kPrivetV3PairingConfirmPath[] = "/privet/v3/pairing/confirm"; | 46 const char kPrivetV3PairingConfirmPath[] = "/privet/v3/pairing/confirm"; |
40 const char kPrivetV3PairingStartPath[] = "/privet/v3/pairing/start"; | 47 const char kPrivetV3AuthPath[] = "/privet/v3/auth"; |
41 | 48 |
42 const char kUrlPlaceHolder[] = "http://host/"; | 49 const char kUrlPlaceHolder[] = "http://host/"; |
43 | 50 |
44 GURL CreatePrivetURL(const std::string& path) { | 51 GURL CreatePrivetURL(const std::string& path) { |
45 GURL url(kUrlPlaceHolder); | 52 GURL url(kUrlPlaceHolder); |
46 GURL::Replacements replacements; | 53 GURL::Replacements replacements; |
47 replacements.SetPathStr(path); | 54 replacements.SetPathStr(path); |
48 return url.ReplaceComponents(replacements); | 55 return url.ReplaceComponents(replacements); |
49 } | 56 } |
50 | 57 |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 | 345 |
339 crypto::HMAC hmac(crypto::HMAC::SHA256); | 346 crypto::HMAC hmac(crypto::HMAC::SHA256); |
340 // Key will be verified below, using HMAC. | 347 // Key will be verified below, using HMAC. |
341 const std::string& key = spake_->GetUnverifiedKey(); | 348 const std::string& key = spake_->GetUnverifiedKey(); |
342 if (!hmac.Init(reinterpret_cast<const unsigned char*>(key.c_str()), | 349 if (!hmac.Init(reinterpret_cast<const unsigned char*>(key.c_str()), |
343 key.size()) || | 350 key.size()) || |
344 !hmac.Verify(fingerprint, signature)) { | 351 !hmac.Verify(fingerprint, signature)) { |
345 return callback.Run(Result::STATUS_SESSIONERROR); | 352 return callback.Run(Result::STATUS_SESSIONERROR); |
346 } | 353 } |
347 | 354 |
| 355 std::string auth_code(hmac.DigestLength(), ' '); |
| 356 if (!hmac.Sign(session_id_, |
| 357 reinterpret_cast<unsigned char*>(string_as_array(&auth_code)), |
| 358 auth_code.size())) { |
| 359 NOTREACHED(); |
| 360 return callback.Run(Result::STATUS_SESSIONERROR); |
| 361 } |
| 362 // From now this is expected certificate. |
| 363 fingerprint_ = fingerprint; |
| 364 |
| 365 std::string auth_code_base64; |
| 366 base::Base64Encode(auth_code, &auth_code_base64); |
| 367 |
| 368 base::DictionaryValue input; |
| 369 input.SetString(kPrivetV3KeyAuthCode, auth_code_base64); |
| 370 input.SetString(kPrivetV3KeyMode, kPrivetV3KeyPairing); |
| 371 input.SetString(kPrivetV3KeyRequestedScope, kPrivetV3Auto); |
| 372 |
| 373 // Now we can use SendMessage with certificate validateion. |
| 374 SendMessage(kPrivetV3AuthPath, input, |
| 375 base::Bind(&PrivetV3Session::OnAuthenticateDone, |
| 376 weak_ptr_factory_.GetWeakPtr(), callback)); |
| 377 } |
| 378 |
| 379 void PrivetV3Session::OnAuthenticateDone( |
| 380 const ResultCallback& callback, |
| 381 Result result, |
| 382 const base::DictionaryValue& response) { |
| 383 if (result != Result::STATUS_SUCCESS) |
| 384 return callback.Run(result); |
| 385 |
| 386 std::string access_token; |
| 387 std::string token_type; |
| 388 std::string scope; |
| 389 if (!response.GetString(kPrivetV3KeyAccessToken, &access_token) || |
| 390 !response.GetString(kPrivetV3KeyTokenType, &token_type) || |
| 391 !response.GetString(kPrivetV3KeyScope, &scope)) { |
| 392 return callback.Run(Result::STATUS_SESSIONERROR); |
| 393 } |
| 394 |
| 395 privet_auth_token_ = token_type + " " + access_token; |
| 396 |
348 return callback.Run(Result::STATUS_SUCCESS); | 397 return callback.Run(Result::STATUS_SUCCESS); |
349 } | 398 } |
350 | 399 |
351 void PrivetV3Session::SendMessage(const std::string& api, | 400 void PrivetV3Session::SendMessage(const std::string& api, |
352 const base::DictionaryValue& input, | 401 const base::DictionaryValue& input, |
353 const MessageCallback& callback) { | 402 const MessageCallback& callback) { |
354 // TODO(vitalybuka): Implement validating HTTPS certificate using | 403 // TODO(vitalybuka): Implement validating HTTPS certificate using |
355 // fingerprint_. | 404 // fingerprint_. |
356 if (fingerprint_.empty()) | 405 if (fingerprint_.empty()) |
357 return callback.Run(Result::STATUS_SESSIONERROR, base::DictionaryValue()); | 406 return callback.Run(Result::STATUS_SESSIONERROR, base::DictionaryValue()); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 fetchers_.push_back(new FetcherDelegate(weak_ptr_factory_.GetWeakPtr(), | 438 fetchers_.push_back(new FetcherDelegate(weak_ptr_factory_.GetWeakPtr(), |
390 privet_auth_token_, callback)); | 439 privet_auth_token_, callback)); |
391 return fetchers_.back()->CreateURLFetcher(CreatePrivetURL(api), request_type); | 440 return fetchers_.back()->CreateURLFetcher(CreatePrivetURL(api), request_type); |
392 } | 441 } |
393 | 442 |
394 void PrivetV3Session::DeleteFetcher(const FetcherDelegate* fetcher) { | 443 void PrivetV3Session::DeleteFetcher(const FetcherDelegate* fetcher) { |
395 fetchers_.erase(std::find(fetchers_.begin(), fetchers_.end(), fetcher)); | 444 fetchers_.erase(std::find(fetchers_.begin(), fetchers_.end(), fetcher)); |
396 } | 445 } |
397 | 446 |
398 } // namespace local_discovery | 447 } // namespace local_discovery |
OLD | NEW |