negotiating_authenticator_base.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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/negotiating_authenticator_base.h"
  5. #include <algorithm>
  6. #include <sstream>
  7. #include <utility>
  8. #include "base/bind.h"
  9. #include "base/callback.h"
  10. #include "base/check_op.h"
  11. #include "base/strings/string_split.h"
  12. #include "remoting/base/constants.h"
  13. #include "remoting/base/name_value_map.h"
  14. #include "remoting/base/rsa_key_pair.h"
  15. #include "remoting/protocol/channel_authenticator.h"
  16. #include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
  17. namespace remoting {
  18. namespace protocol {
  19. namespace {
  20. const NameMapElement<NegotiatingAuthenticatorBase::Method>
  21. kAuthenticationMethodStrings[] = {
  22. {NegotiatingAuthenticatorBase::Method::SHARED_SECRET_PLAIN_SPAKE2_P224,
  23. "spake2_plain"},
  24. {NegotiatingAuthenticatorBase::Method::SHARED_SECRET_SPAKE2_P224,
  25. "spake2_hmac"},
  26. {NegotiatingAuthenticatorBase::Method::SHARED_SECRET_SPAKE2_CURVE25519,
  27. "spake2_curve25519"},
  28. {NegotiatingAuthenticatorBase::Method::PAIRED_SPAKE2_P224,
  29. "spake2_pair"},
  30. {NegotiatingAuthenticatorBase::Method::PAIRED_SPAKE2_CURVE25519,
  31. "pair_spake2_curve25519"},
  32. {NegotiatingAuthenticatorBase::Method::THIRD_PARTY_SPAKE2_P224,
  33. "third_party"},
  34. {NegotiatingAuthenticatorBase::Method::THIRD_PARTY_SPAKE2_CURVE25519,
  35. "third_party_spake2_curve25519"},
  36. };
  37. } // namespace
  38. const jingle_xmpp::StaticQName NegotiatingAuthenticatorBase::kMethodAttributeQName = {
  39. "", "method"};
  40. const jingle_xmpp::StaticQName
  41. NegotiatingAuthenticatorBase::kSupportedMethodsAttributeQName = {
  42. "", "supported-methods"};
  43. const char NegotiatingAuthenticatorBase::kSupportedMethodsSeparator = ',';
  44. const jingle_xmpp::StaticQName NegotiatingAuthenticatorBase::kPairingInfoTag = {
  45. kChromotingXmlNamespace, "pairing-info"};
  46. const jingle_xmpp::StaticQName NegotiatingAuthenticatorBase::kClientIdAttribute = {
  47. "", "client-id"};
  48. NegotiatingAuthenticatorBase::NegotiatingAuthenticatorBase(
  49. Authenticator::State initial_state)
  50. : state_(initial_state) {}
  51. NegotiatingAuthenticatorBase::~NegotiatingAuthenticatorBase() = default;
  52. Authenticator::State NegotiatingAuthenticatorBase::state() const {
  53. return state_;
  54. }
  55. bool NegotiatingAuthenticatorBase::started() const {
  56. if (!current_authenticator_) {
  57. return false;
  58. }
  59. return current_authenticator_->started();
  60. }
  61. Authenticator::RejectionReason
  62. NegotiatingAuthenticatorBase::rejection_reason() const {
  63. return rejection_reason_;
  64. }
  65. // static
  66. NegotiatingAuthenticatorBase::Method
  67. NegotiatingAuthenticatorBase::ParseMethodString(const std::string& value) {
  68. Method result;
  69. if (!NameToValue(kAuthenticationMethodStrings, value, &result))
  70. return Method::INVALID;
  71. return result;
  72. }
  73. // static
  74. std::string NegotiatingAuthenticatorBase::MethodToString(Method method) {
  75. return ValueToName(kAuthenticationMethodStrings, method);
  76. }
  77. void NegotiatingAuthenticatorBase::ProcessMessageInternal(
  78. const jingle_xmpp::XmlElement* message,
  79. base::OnceClosure resume_callback) {
  80. DCHECK_EQ(state_, PROCESSING_MESSAGE);
  81. if (current_authenticator_->state() == WAITING_MESSAGE) {
  82. // If the message was not discarded and the authenticator is waiting for it,
  83. // give it to the underlying authenticator to process.
  84. // |current_authenticator_| is owned, so Unretained() is safe here.
  85. current_authenticator_->ProcessMessage(
  86. message,
  87. base::BindOnce(&NegotiatingAuthenticatorBase::UpdateState,
  88. base::Unretained(this), std::move(resume_callback)));
  89. } else {
  90. // Otherwise, just discard the message.
  91. UpdateState(std::move(resume_callback));
  92. }
  93. }
  94. void NegotiatingAuthenticatorBase::UpdateState(
  95. base::OnceClosure resume_callback) {
  96. DCHECK_EQ(state_, PROCESSING_MESSAGE);
  97. // After the underlying authenticator finishes processing the message, the
  98. // NegotiatingAuthenticatorBase must update its own state before running the
  99. // |resume_callback| to resume the session negotiation.
  100. state_ = current_authenticator_->state();
  101. // Verify that this is a valid state transition.
  102. DCHECK(state_ == MESSAGE_READY || state_ == ACCEPTED || state_ == REJECTED)
  103. << "State: " << state_;
  104. if (state_ == REJECTED)
  105. rejection_reason_ = current_authenticator_->rejection_reason();
  106. std::move(resume_callback).Run();
  107. }
  108. std::unique_ptr<jingle_xmpp::XmlElement>
  109. NegotiatingAuthenticatorBase::GetNextMessageInternal() {
  110. DCHECK_EQ(state(), MESSAGE_READY);
  111. DCHECK(current_method_ != Method::INVALID);
  112. std::unique_ptr<jingle_xmpp::XmlElement> result;
  113. if (current_authenticator_->state() == MESSAGE_READY) {
  114. result = current_authenticator_->GetNextMessage();
  115. } else {
  116. result = CreateEmptyAuthenticatorMessage();
  117. }
  118. state_ = current_authenticator_->state();
  119. DCHECK(state_ == ACCEPTED || state_ == WAITING_MESSAGE);
  120. result->AddAttr(kMethodAttributeQName, MethodToString(current_method_));
  121. return result;
  122. }
  123. void NegotiatingAuthenticatorBase::AddMethod(Method method) {
  124. DCHECK(method != Method::INVALID);
  125. methods_.push_back(method);
  126. }
  127. const std::string& NegotiatingAuthenticatorBase::GetAuthKey() const {
  128. DCHECK_EQ(state(), ACCEPTED);
  129. return current_authenticator_->GetAuthKey();
  130. }
  131. std::unique_ptr<ChannelAuthenticator>
  132. NegotiatingAuthenticatorBase::CreateChannelAuthenticator() const {
  133. DCHECK_EQ(state(), ACCEPTED);
  134. return current_authenticator_->CreateChannelAuthenticator();
  135. }
  136. } // namespace protocol
  137. } // namespace remoting