OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "remoting/protocol/negotiating_client_authenticator.h" | 5 #include "remoting/protocol/negotiating_client_authenticator.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <sstream> | 8 #include <sstream> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
44 | 44 |
45 NegotiatingClientAuthenticator::~NegotiatingClientAuthenticator() { | 45 NegotiatingClientAuthenticator::~NegotiatingClientAuthenticator() { |
46 } | 46 } |
47 | 47 |
48 void NegotiatingClientAuthenticator::ProcessMessage( | 48 void NegotiatingClientAuthenticator::ProcessMessage( |
49 const buzz::XmlElement* message, | 49 const buzz::XmlElement* message, |
50 const base::Closure& resume_callback) { | 50 const base::Closure& resume_callback) { |
51 DCHECK_EQ(state(), WAITING_MESSAGE); | 51 DCHECK_EQ(state(), WAITING_MESSAGE); |
52 | 52 |
53 std::string method_attr = message->Attr(kMethodAttributeQName); | 53 std::string method_attr = message->Attr(kMethodAttributeQName); |
54 AuthenticationMethod method = AuthenticationMethod::FromString(method_attr); | 54 AuthenticationMethod method = ParseAuthenticationMethodString(method_attr); |
55 | 55 |
56 // The host picked a method different from the one the client had selected. | 56 // The host picked a method different from the one the client had selected. |
57 if (method != current_method_) { | 57 if (method != current_method_) { |
58 // The host must pick a method that is valid and supported by the client, | 58 // The host must pick a method that is valid and supported by the client, |
59 // and it must not change methods after it has picked one. | 59 // and it must not change methods after it has picked one. |
60 if (method_set_by_host_ || !method.is_valid() || | 60 if (method_set_by_host_ || method == AuthenticationMethod::INVALID || |
61 std::find(methods_.begin(), methods_.end(), method) == methods_.end()) { | 61 std::find(methods_.begin(), methods_.end(), method) == methods_.end()) { |
62 state_ = REJECTED; | 62 state_ = REJECTED; |
63 rejection_reason_ = PROTOCOL_ERROR; | 63 rejection_reason_ = PROTOCOL_ERROR; |
64 resume_callback.Run(); | 64 resume_callback.Run(); |
65 return; | 65 return; |
66 } | 66 } |
67 | 67 |
68 current_method_ = method; | 68 current_method_ = method; |
69 method_set_by_host_ = true; | 69 method_set_by_host_ = true; |
70 state_ = PROCESSING_MESSAGE; | 70 state_ = PROCESSING_MESSAGE; |
71 | 71 |
72 // Copy the message since the authenticator may process it asynchronously. | 72 // Copy the message since the authenticator may process it asynchronously. |
73 base::Closure callback = base::Bind( | 73 base::Closure callback = base::Bind( |
74 &NegotiatingAuthenticatorBase::ProcessMessageInternal, | 74 &NegotiatingAuthenticatorBase::ProcessMessageInternal, |
75 base::Unretained(this), base::Owned(new buzz::XmlElement(*message)), | 75 base::Unretained(this), base::Owned(new buzz::XmlElement(*message)), |
76 resume_callback); | 76 resume_callback); |
77 CreateAuthenticatorForCurrentMethod(WAITING_MESSAGE, callback); | 77 CreateAuthenticatorForCurrentMethod(WAITING_MESSAGE, callback); |
78 return; | 78 return; |
79 } | 79 } |
80 ProcessMessageInternal(message, resume_callback); | 80 ProcessMessageInternal(message, resume_callback); |
81 } | 81 } |
82 | 82 |
83 scoped_ptr<buzz::XmlElement> NegotiatingClientAuthenticator::GetNextMessage() { | 83 scoped_ptr<buzz::XmlElement> NegotiatingClientAuthenticator::GetNextMessage() { |
84 DCHECK_EQ(state(), MESSAGE_READY); | 84 DCHECK_EQ(state(), MESSAGE_READY); |
85 | 85 |
86 // This is the first message to the host, send a list of supported methods. | 86 // This is the first message to the host, send a list of supported methods. |
87 if (!current_method_.is_valid()) { | 87 if (current_method_ == AuthenticationMethod::INVALID) { |
88 // If no authentication method has been chosen, see if we can optimistically | 88 // If no authentication method has been chosen, see if we can optimistically |
89 // choose one. | 89 // choose one. |
90 scoped_ptr<buzz::XmlElement> result; | 90 scoped_ptr<buzz::XmlElement> result; |
91 CreatePreferredAuthenticator(); | 91 CreatePreferredAuthenticator(); |
92 if (current_authenticator_) { | 92 if (current_authenticator_) { |
93 DCHECK(current_authenticator_->state() == MESSAGE_READY); | 93 DCHECK(current_authenticator_->state() == MESSAGE_READY); |
94 result = GetNextMessageInternal(); | 94 result = GetNextMessageInternal(); |
95 } else { | 95 } else { |
96 result = CreateEmptyAuthenticatorMessage(); | 96 result = CreateEmptyAuthenticatorMessage(); |
97 } | 97 } |
98 | 98 |
99 // Include a list of supported methods. | 99 // Include a list of supported methods. |
100 std::stringstream supported_methods(std::stringstream::out); | 100 std::string supported_methods; |
kelvinp
2016/03/04 18:40:54
Out of curiosity, why do we switch from stringstre
Sergey Ulanov
2016/03/04 20:48:51
I don't know why thought it was a good idea when I
| |
101 for (std::vector<AuthenticationMethod>::iterator it = methods_.begin(); | 101 for (AuthenticationMethod method : methods_) { |
102 it != methods_.end(); ++it) { | 102 if (!supported_methods.empty()) |
103 if (it != methods_.begin()) | 103 supported_methods += kSupportedMethodsSeparator; |
104 supported_methods << kSupportedMethodsSeparator; | 104 supported_methods += AuthenticationMethodToString(method); |
105 supported_methods << it->ToString(); | |
106 } | 105 } |
107 result->AddAttr(kSupportedMethodsAttributeQName, supported_methods.str()); | 106 result->AddAttr(kSupportedMethodsAttributeQName, supported_methods); |
108 state_ = WAITING_MESSAGE; | 107 state_ = WAITING_MESSAGE; |
109 return result; | 108 return result; |
110 } | 109 } |
111 return GetNextMessageInternal(); | 110 return GetNextMessageInternal(); |
112 } | 111 } |
113 | 112 |
114 void NegotiatingClientAuthenticator::CreateAuthenticatorForCurrentMethod( | 113 void NegotiatingClientAuthenticator::CreateAuthenticatorForCurrentMethod( |
115 Authenticator::State preferred_initial_state, | 114 Authenticator::State preferred_initial_state, |
116 const base::Closure& resume_callback) { | 115 const base::Closure& resume_callback) { |
117 DCHECK(current_method_.is_valid()); | 116 DCHECK(current_method_ != AuthenticationMethod::INVALID); |
118 if (current_method_.type() == AuthenticationMethod::THIRD_PARTY) { | 117 if (current_method_ == AuthenticationMethod::THIRD_PARTY) { |
119 // |ThirdPartyClientAuthenticator| takes ownership of |token_fetcher_|. | 118 // |ThirdPartyClientAuthenticator| takes ownership of |token_fetcher_|. |
120 // The authentication method negotiation logic should guarantee that only | 119 // The authentication method negotiation logic should guarantee that only |
121 // one |ThirdPartyClientAuthenticator| will need to be created per session. | 120 // one |ThirdPartyClientAuthenticator| will need to be created per session. |
122 DCHECK(token_fetcher_); | 121 DCHECK(token_fetcher_); |
123 current_authenticator_.reset(new ThirdPartyClientAuthenticator( | 122 current_authenticator_.reset(new ThirdPartyClientAuthenticator( |
124 std::move(token_fetcher_))); | 123 std::move(token_fetcher_))); |
125 resume_callback.Run(); | 124 resume_callback.Run(); |
126 } else { | 125 } else { |
127 DCHECK(current_method_.type() == AuthenticationMethod::SPAKE2 || | 126 DCHECK(current_method_ == |
128 current_method_.type() == AuthenticationMethod::SPAKE2_PAIR); | 127 AuthenticationMethod::SPAKE2_SHARED_SECRET_PLAIN || |
128 current_method_ == AuthenticationMethod::SPAKE2_SHARED_SECRET_HMAC || | |
129 current_method_ == AuthenticationMethod::SPAKE2_PAIR); | |
129 bool pairing_supported = | 130 bool pairing_supported = |
130 (current_method_.type() == AuthenticationMethod::SPAKE2_PAIR); | 131 (current_method_ == AuthenticationMethod::SPAKE2_PAIR); |
131 SecretFetchedCallback callback = base::Bind( | 132 SecretFetchedCallback callback = base::Bind( |
132 &NegotiatingClientAuthenticator::CreateV2AuthenticatorWithSecret, | 133 &NegotiatingClientAuthenticator::CreateV2AuthenticatorWithSecret, |
133 weak_factory_.GetWeakPtr(), preferred_initial_state, resume_callback); | 134 weak_factory_.GetWeakPtr(), preferred_initial_state, resume_callback); |
134 fetch_secret_callback_.Run(pairing_supported, callback); | 135 fetch_secret_callback_.Run(pairing_supported, callback); |
135 } | 136 } |
136 } | 137 } |
137 | 138 |
138 void NegotiatingClientAuthenticator::CreatePreferredAuthenticator() { | 139 void NegotiatingClientAuthenticator::CreatePreferredAuthenticator() { |
139 if (!client_pairing_id_.empty() && !shared_secret_.empty() && | 140 if (!client_pairing_id_.empty() && !shared_secret_.empty() && |
140 std::find(methods_.begin(), methods_.end(), | 141 std::find(methods_.begin(), methods_.end(), |
141 AuthenticationMethod::Spake2Pair()) != methods_.end()) { | 142 AuthenticationMethod::SPAKE2_PAIR) != methods_.end()) { |
142 // If the client specified a pairing id and shared secret, then create a | 143 // If the client specified a pairing id and shared secret, then create a |
143 // PairingAuthenticator. | 144 // PairingAuthenticator. |
144 current_authenticator_.reset(new PairingClientAuthenticator( | 145 current_authenticator_.reset(new PairingClientAuthenticator( |
145 client_pairing_id_, shared_secret_, fetch_secret_callback_, | 146 client_pairing_id_, shared_secret_, fetch_secret_callback_, |
146 authentication_tag_)); | 147 authentication_tag_)); |
147 current_method_ = AuthenticationMethod::Spake2Pair(); | 148 current_method_ = AuthenticationMethod::SPAKE2_PAIR; |
148 } | 149 } |
149 } | 150 } |
150 | 151 |
151 void NegotiatingClientAuthenticator::CreateV2AuthenticatorWithSecret( | 152 void NegotiatingClientAuthenticator::CreateV2AuthenticatorWithSecret( |
152 Authenticator::State initial_state, | 153 Authenticator::State initial_state, |
153 const base::Closure& resume_callback, | 154 const base::Closure& resume_callback, |
154 const std::string& shared_secret) { | 155 const std::string& shared_secret) { |
155 current_authenticator_ = V2Authenticator::CreateForClient( | 156 current_authenticator_ = V2Authenticator::CreateForClient( |
156 AuthenticationMethod::ApplyHashFunction( | 157 ApplySharedSecretHashFunction( |
157 current_method_.hash_function(), authentication_tag_, shared_secret), | 158 GetHashFunctionForAuthenticationMethod(current_method_), |
159 authentication_tag_, shared_secret), | |
158 initial_state); | 160 initial_state); |
159 resume_callback.Run(); | 161 resume_callback.Run(); |
160 } | 162 } |
161 | 163 |
162 } // namespace protocol | 164 } // namespace protocol |
163 } // namespace remoting | 165 } // namespace remoting |
OLD | NEW |