v2_authenticator.cc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // Copyright (c) 2012 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 "remoting/protocol/v2_authenticator.h"
  5. #include <utility>
  6. #include "base/base64.h"
  7. #include "base/logging.h"
  8. #include "base/memory/ptr_util.h"
  9. #include "remoting/base/constants.h"
  10. #include "remoting/base/rsa_key_pair.h"
  11. #include "remoting/protocol/ssl_hmac_channel_authenticator.h"
  12. #include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
  13. using crypto::P224EncryptedKeyExchange;
  14. namespace remoting {
  15. namespace protocol {
  16. namespace {
  17. const jingle_xmpp::StaticQName kEkeTag = { kChromotingXmlNamespace,
  18. "eke-message" };
  19. const jingle_xmpp::StaticQName kCertificateTag = { kChromotingXmlNamespace,
  20. "certificate" };
  21. } // namespace
  22. // static
  23. bool V2Authenticator::IsEkeMessage(const jingle_xmpp::XmlElement* message) {
  24. return message->FirstNamed(kEkeTag) != nullptr;
  25. }
  26. // static
  27. std::unique_ptr<Authenticator> V2Authenticator::CreateForClient(
  28. const std::string& shared_secret,
  29. Authenticator::State initial_state) {
  30. return base::WrapUnique(new V2Authenticator(
  31. P224EncryptedKeyExchange::kPeerTypeClient, shared_secret, initial_state));
  32. }
  33. // static
  34. std::unique_ptr<Authenticator> V2Authenticator::CreateForHost(
  35. const std::string& local_cert,
  36. scoped_refptr<RsaKeyPair> key_pair,
  37. const std::string& shared_secret,
  38. Authenticator::State initial_state) {
  39. std::unique_ptr<V2Authenticator> result(new V2Authenticator(
  40. P224EncryptedKeyExchange::kPeerTypeServer, shared_secret, initial_state));
  41. result->local_cert_ = local_cert;
  42. result->local_key_pair_ = key_pair;
  43. return std::move(result);
  44. }
  45. V2Authenticator::V2Authenticator(
  46. crypto::P224EncryptedKeyExchange::PeerType type,
  47. const std::string& shared_secret,
  48. Authenticator::State initial_state)
  49. : certificate_sent_(false),
  50. key_exchange_impl_(type, shared_secret),
  51. state_(initial_state),
  52. started_(false),
  53. rejection_reason_(RejectionReason::INVALID_CREDENTIALS) {
  54. pending_messages_.push(key_exchange_impl_.GetNextMessage());
  55. }
  56. V2Authenticator::~V2Authenticator() = default;
  57. Authenticator::State V2Authenticator::state() const {
  58. if (state_ == ACCEPTED && !pending_messages_.empty())
  59. return MESSAGE_READY;
  60. return state_;
  61. }
  62. bool V2Authenticator::started() const {
  63. return started_;
  64. }
  65. Authenticator::RejectionReason V2Authenticator::rejection_reason() const {
  66. DCHECK_EQ(state(), REJECTED);
  67. return rejection_reason_;
  68. }
  69. void V2Authenticator::ProcessMessage(const jingle_xmpp::XmlElement* message,
  70. base::OnceClosure resume_callback) {
  71. ProcessMessageInternal(message);
  72. std::move(resume_callback).Run();
  73. }
  74. void V2Authenticator::ProcessMessageInternal(const jingle_xmpp::XmlElement* message) {
  75. DCHECK_EQ(state(), WAITING_MESSAGE);
  76. // Parse the certificate.
  77. std::string base64_cert = message->TextNamed(kCertificateTag);
  78. if (!base64_cert.empty()) {
  79. if (!base::Base64Decode(base64_cert, &remote_cert_)) {
  80. LOG(WARNING) << "Failed to decode certificate received from the peer.";
  81. remote_cert_.clear();
  82. }
  83. }
  84. // Client always expect certificate in the first message.
  85. if (!is_host_side() && remote_cert_.empty()) {
  86. LOG(WARNING) << "No valid host certificate.";
  87. state_ = REJECTED;
  88. rejection_reason_ = RejectionReason::PROTOCOL_ERROR;
  89. return;
  90. }
  91. const jingle_xmpp::XmlElement* eke_element = message->FirstNamed(kEkeTag);
  92. if (!eke_element) {
  93. LOG(WARNING) << "No eke-message found.";
  94. state_ = REJECTED;
  95. rejection_reason_ = RejectionReason::PROTOCOL_ERROR;
  96. return;
  97. }
  98. for (; eke_element; eke_element = eke_element->NextNamed(kEkeTag)) {
  99. std::string base64_message = eke_element->BodyText();
  100. std::string spake_message;
  101. if (base64_message.empty() ||
  102. !base::Base64Decode(base64_message, &spake_message)) {
  103. LOG(WARNING) << "Failed to decode auth message received from the peer.";
  104. state_ = REJECTED;
  105. rejection_reason_ = RejectionReason::PROTOCOL_ERROR;
  106. return;
  107. }
  108. P224EncryptedKeyExchange::Result result =
  109. key_exchange_impl_.ProcessMessage(spake_message);
  110. started_ = true;
  111. switch (result) {
  112. case P224EncryptedKeyExchange::kResultPending:
  113. pending_messages_.push(key_exchange_impl_.GetNextMessage());
  114. break;
  115. case P224EncryptedKeyExchange::kResultFailed:
  116. state_ = REJECTED;
  117. rejection_reason_ = RejectionReason::INVALID_CREDENTIALS;
  118. return;
  119. case P224EncryptedKeyExchange::kResultSuccess:
  120. auth_key_ = key_exchange_impl_.GetKey();
  121. state_ = ACCEPTED;
  122. return;
  123. }
  124. }
  125. state_ = MESSAGE_READY;
  126. }
  127. std::unique_ptr<jingle_xmpp::XmlElement> V2Authenticator::GetNextMessage() {
  128. DCHECK_EQ(state(), MESSAGE_READY);
  129. std::unique_ptr<jingle_xmpp::XmlElement> message = CreateEmptyAuthenticatorMessage();
  130. DCHECK(!pending_messages_.empty());
  131. while (!pending_messages_.empty()) {
  132. const std::string& spake_message = pending_messages_.front();
  133. std::string base64_message;
  134. base::Base64Encode(spake_message, &base64_message);
  135. jingle_xmpp::XmlElement* eke_tag = new jingle_xmpp::XmlElement(kEkeTag);
  136. eke_tag->SetBodyText(base64_message);
  137. message->AddElement(eke_tag);
  138. pending_messages_.pop();
  139. }
  140. if (!local_cert_.empty() && !certificate_sent_) {
  141. jingle_xmpp::XmlElement* certificate_tag = new jingle_xmpp::XmlElement(kCertificateTag);
  142. std::string base64_cert;
  143. base::Base64Encode(local_cert_, &base64_cert);
  144. certificate_tag->SetBodyText(base64_cert);
  145. message->AddElement(certificate_tag);
  146. certificate_sent_ = true;
  147. }
  148. if (state_ != ACCEPTED) {
  149. state_ = WAITING_MESSAGE;
  150. }
  151. return message;
  152. }
  153. const std::string& V2Authenticator::GetAuthKey() const {
  154. return auth_key_;
  155. }
  156. std::unique_ptr<ChannelAuthenticator>
  157. V2Authenticator::CreateChannelAuthenticator() const {
  158. DCHECK_EQ(state(), ACCEPTED);
  159. CHECK(!auth_key_.empty());
  160. if (is_host_side()) {
  161. return SslHmacChannelAuthenticator::CreateForHost(
  162. local_cert_, local_key_pair_, auth_key_);
  163. } else {
  164. return SslHmacChannelAuthenticator::CreateForClient(
  165. remote_cert_, auth_key_);
  166. }
  167. }
  168. bool V2Authenticator::is_host_side() const {
  169. return local_key_pair_.get() != nullptr;
  170. }
  171. } // namespace protocol
  172. } // namespace remoting