messenger_impl.cc 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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
  3. // found in the LICENSE file.
  4. #include "ash/components/proximity_auth/messenger_impl.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "ash/components/multidevice/logging/logging.h"
  8. #include "ash/components/proximity_auth/messenger_observer.h"
  9. #include "ash/components/proximity_auth/remote_status_update.h"
  10. #include "base/base64url.h"
  11. #include "base/bind.h"
  12. #include "base/json/json_reader.h"
  13. #include "base/json/json_writer.h"
  14. #include "base/location.h"
  15. #include "base/threading/thread_task_runner_handle.h"
  16. namespace proximity_auth {
  17. namespace {
  18. // The key names of JSON fields for messages sent between the devices.
  19. const char kTypeKey[] = "type";
  20. const char kNameKey[] = "name";
  21. const char kDataKey[] = "data";
  22. const char kEncryptedDataKey[] = "encrypted_data";
  23. // The types of messages that can be sent and received.
  24. const char kMessageTypeLocalEvent[] = "event";
  25. const char kMessageTypeRemoteStatusUpdate[] = "status_update";
  26. const char kMessageTypeDecryptRequest[] = "decrypt_request";
  27. const char kMessageTypeDecryptResponse[] = "decrypt_response";
  28. const char kMessageTypeUnlockRequest[] = "unlock_request";
  29. const char kMessageTypeUnlockResponse[] = "unlock_response";
  30. // The name for an unlock event originating from the local device.
  31. const char kUnlockEventName[] = "easy_unlock";
  32. // Serializes the |value| to a JSON string and returns the result.
  33. std::string SerializeValueToJson(const base::Value::Dict& value) {
  34. std::string json;
  35. base::JSONWriter::Write(value, &json);
  36. return json;
  37. }
  38. // Returns the message type represented by the |message|. This is a convenience
  39. // wrapper that should only be called when the |message| is known to specify its
  40. // message type, i.e. this should not be called for untrusted input.
  41. std::string GetMessageType(const base::Value::Dict& message) {
  42. const std::string* type = message.FindString(kTypeKey);
  43. return type ? *type : std::string();
  44. }
  45. } // namespace
  46. MessengerImpl::MessengerImpl(
  47. std::unique_ptr<ash::secure_channel::ClientChannel> channel)
  48. : channel_(std::move(channel)) {
  49. DCHECK(!channel_->is_disconnected());
  50. channel_->AddObserver(this);
  51. }
  52. MessengerImpl::~MessengerImpl() {
  53. channel_->RemoveObserver(this);
  54. }
  55. void MessengerImpl::AddObserver(MessengerObserver* observer) {
  56. observers_.AddObserver(observer);
  57. }
  58. void MessengerImpl::RemoveObserver(MessengerObserver* observer) {
  59. observers_.RemoveObserver(observer);
  60. }
  61. void MessengerImpl::DispatchUnlockEvent() {
  62. base::Value::Dict message;
  63. message.Set(kTypeKey, kMessageTypeLocalEvent);
  64. message.Set(kNameKey, kUnlockEventName);
  65. queued_messages_.push_back(PendingMessage(message));
  66. ProcessMessageQueue();
  67. }
  68. void MessengerImpl::RequestDecryption(const std::string& challenge) {
  69. const std::string encrypted_message_data = challenge;
  70. std::string encrypted_message_data_base64;
  71. base::Base64UrlEncode(encrypted_message_data,
  72. base::Base64UrlEncodePolicy::INCLUDE_PADDING,
  73. &encrypted_message_data_base64);
  74. base::Value::Dict message;
  75. message.Set(kTypeKey, kMessageTypeDecryptRequest);
  76. message.Set(kEncryptedDataKey, encrypted_message_data_base64);
  77. queued_messages_.push_back(PendingMessage(message));
  78. ProcessMessageQueue();
  79. }
  80. void MessengerImpl::RequestUnlock() {
  81. base::Value::Dict message;
  82. message.Set(kTypeKey, kMessageTypeUnlockRequest);
  83. queued_messages_.push_back(PendingMessage(message));
  84. ProcessMessageQueue();
  85. }
  86. ash::secure_channel::ClientChannel* MessengerImpl::GetChannel() const {
  87. if (channel_->is_disconnected())
  88. return nullptr;
  89. return channel_.get();
  90. }
  91. MessengerImpl::PendingMessage::PendingMessage() = default;
  92. MessengerImpl::PendingMessage::~PendingMessage() = default;
  93. MessengerImpl::PendingMessage::PendingMessage(const base::Value::Dict& message)
  94. : json_message(SerializeValueToJson(message)),
  95. type(GetMessageType(message)) {}
  96. MessengerImpl::PendingMessage::PendingMessage(const std::string& message)
  97. : json_message(message), type(std::string()) {}
  98. void MessengerImpl::ProcessMessageQueue() {
  99. if (pending_message_ || queued_messages_.empty())
  100. return;
  101. if (channel_->is_disconnected())
  102. return;
  103. pending_message_ = std::make_unique<PendingMessage>(queued_messages_.front());
  104. queued_messages_.pop_front();
  105. channel_->SendMessage(
  106. pending_message_->json_message,
  107. base::BindOnce(&MessengerImpl::OnSendMessageResult,
  108. weak_ptr_factory_.GetWeakPtr(), true /* success */));
  109. }
  110. void MessengerImpl::HandleRemoteStatusUpdateMessage(
  111. const base::Value::Dict& message) {
  112. std::unique_ptr<RemoteStatusUpdate> status_update =
  113. RemoteStatusUpdate::Deserialize(message);
  114. if (!status_update) {
  115. PA_LOG(ERROR) << "Unexpected remote status update: " << message;
  116. return;
  117. }
  118. for (auto& observer : observers_)
  119. observer.OnRemoteStatusUpdate(*status_update);
  120. }
  121. void MessengerImpl::HandleDecryptResponseMessage(
  122. const base::Value::Dict& message) {
  123. const std::string* base64_data = message.FindString(kDataKey);
  124. std::string decrypted_data;
  125. if (!base64_data || base64_data->empty()) {
  126. PA_LOG(ERROR) << "Decrypt response missing '" << kDataKey << "' value.";
  127. } else if (!base::Base64UrlDecode(
  128. *base64_data, base::Base64UrlDecodePolicy::REQUIRE_PADDING,
  129. &decrypted_data)) {
  130. PA_LOG(ERROR) << "Unable to base64-decode decrypt response.";
  131. }
  132. for (auto& observer : observers_)
  133. observer.OnDecryptResponse(decrypted_data);
  134. }
  135. void MessengerImpl::HandleUnlockResponseMessage(
  136. const base::Value::Dict& message) {
  137. for (auto& observer : observers_)
  138. observer.OnUnlockResponse(true);
  139. }
  140. void MessengerImpl::OnDisconnected() {
  141. for (auto& observer : observers_)
  142. observer.OnDisconnected();
  143. }
  144. void MessengerImpl::OnMessageReceived(const std::string& payload) {
  145. HandleMessage(payload);
  146. }
  147. void MessengerImpl::HandleMessage(const std::string& message) {
  148. // The decoded message should be a JSON string.
  149. absl::optional<base::Value> message_value = base::JSONReader::Read(message);
  150. if (!message_value || !message_value->is_dict()) {
  151. PA_LOG(ERROR) << "Unable to parse message as JSON:\n" << message;
  152. return;
  153. }
  154. const base::Value::Dict& message_dictionary = message_value->GetDict();
  155. const std::string* type = message_dictionary.FindString(kTypeKey);
  156. if (!type) {
  157. PA_LOG(ERROR) << "Missing '" << kTypeKey << "' key in message:\n "
  158. << message;
  159. return;
  160. }
  161. // Remote status updates can be received out of the blue.
  162. if (*type == kMessageTypeRemoteStatusUpdate) {
  163. HandleRemoteStatusUpdateMessage(message_dictionary);
  164. return;
  165. }
  166. // All other messages should only be received in response to a message that
  167. // the messenger sent.
  168. if (!pending_message_) {
  169. PA_LOG(WARNING) << "Unexpected message received: " << message;
  170. return;
  171. }
  172. std::string expected_type;
  173. if (pending_message_->type == kMessageTypeDecryptRequest)
  174. expected_type = kMessageTypeDecryptResponse;
  175. else if (pending_message_->type == kMessageTypeUnlockRequest)
  176. expected_type = kMessageTypeUnlockResponse;
  177. else
  178. NOTREACHED(); // There are no other message types that expect a response.
  179. if (*type != expected_type) {
  180. PA_LOG(ERROR) << "Unexpected '" << kTypeKey << "' value in message. "
  181. << "Expected '" << expected_type << "' but received '"
  182. << *type << "'.";
  183. return;
  184. }
  185. if (*type == kMessageTypeDecryptResponse)
  186. HandleDecryptResponseMessage(message_dictionary);
  187. else if (*type == kMessageTypeUnlockResponse)
  188. HandleUnlockResponseMessage(message_dictionary);
  189. else
  190. NOTREACHED(); // There are no other message types that expect a response.
  191. pending_message_.reset();
  192. ProcessMessageQueue();
  193. }
  194. void MessengerImpl::OnSendMessageResult(bool success) {
  195. if (!pending_message_) {
  196. PA_LOG(ERROR) << "Unexpected message sent.";
  197. return;
  198. }
  199. // In the common case, wait for a response from the remote device.
  200. // Don't wait if the message could not be sent, as there won't ever be a
  201. // response in that case. Likewise, don't wait for a response to local
  202. // event messages, as there is no response for such messages.
  203. if (success && pending_message_->type != kMessageTypeLocalEvent)
  204. return;
  205. // Notify observer of failure if sending the message fails.
  206. // For local events, we don't expect a response, so on success, we
  207. // notify observers right away.
  208. if (pending_message_->type == kMessageTypeDecryptRequest) {
  209. for (auto& observer : observers_)
  210. observer.OnDecryptResponse(std::string());
  211. } else if (pending_message_->type == kMessageTypeUnlockRequest) {
  212. for (auto& observer : observers_)
  213. observer.OnUnlockResponse(false);
  214. } else if (pending_message_->type == kMessageTypeLocalEvent) {
  215. for (auto& observer : observers_)
  216. observer.OnUnlockEventSent(success);
  217. } else {
  218. PA_LOG(ERROR) << "Message of unknown type '" << pending_message_->type
  219. << "' sent.";
  220. }
  221. pending_message_.reset();
  222. ProcessMessageQueue();
  223. }
  224. } // namespace proximity_auth