Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(197)

Side by Side Diff: remoting/protocol/pairing_authenticator_base.cc

Issue 14793021: PairingAuthenticator implementation and plumbing. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Reviewer comments. Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "remoting/protocol/pairing_authenticator_base.h"
6
7 #include "base/bind.h"
8 #include "remoting/base/constants.h"
9 #include "remoting/protocol/channel_authenticator.h"
10
11 namespace remoting {
12 namespace protocol {
13
14 const buzz::StaticQName PairingAuthenticatorBase::kPairingInfoTag =
15 { kChromotingXmlNamespace, "pairing-info" };
16 const buzz::StaticQName PairingAuthenticatorBase::kClientIdAttribute =
17 { "", "client-id" };
18
19 namespace {
20 const buzz::StaticQName kPairingFailedTag =
21 { kChromotingXmlNamespace, "pairing-failed" };
22 const buzz::StaticQName kPairingErrorAttribute = { "", "error" };
23 } // namespace
24
Wez 2013/05/22 00:51:45 nit: Remove the extra blank line.
Jamie 2013/05/22 01:16:46 Done.
25
26 PairingAuthenticatorBase::PairingAuthenticatorBase()
27 : using_paired_secret_(false),
28 waiting_for_authenticator_(false),
29 weak_factory_(this) {
30 }
31
32 Authenticator::State PairingAuthenticatorBase::state() const {
33 if (waiting_for_authenticator_) {
34 return PROCESSING_MESSAGE;
35 }
36 return v2_authenticator_->state();
37 }
38
39 Authenticator::RejectionReason
40 PairingAuthenticatorBase::rejection_reason() const {
41 if (!v2_authenticator_) {
42 return PROTOCOL_ERROR;
43 }
44 return v2_authenticator_->rejection_reason();
45 }
46
47 void PairingAuthenticatorBase::ProcessMessage(
48 const buzz::XmlElement* message,
49 const base::Closure& resume_callback) {
50 DCHECK_EQ(state(), WAITING_MESSAGE);
51
52 // The client authenticator creates the underlying authenticator in the ctor
53 // and the host creates it in response to the first message before deferring
54 // to this class to process it. Either way, it should exist here.
55 DCHECK(v2_authenticator_);
56
57 // If pairing failed, and we haven't already done so, try again with the PIN.
58 if (using_paired_secret_ && HasErrorMessage(message)) {
59 using_paired_secret_ = false;
60 waiting_for_authenticator_ = true;
61 v2_authenticator_.reset();
62 SetAuthenticatorCallback set_authenticator = base::Bind(
63 &PairingAuthenticatorBase::SetAuthenticatorAndProcessMessage,
64 weak_factory_.GetWeakPtr(), base::Owned(new buzz::XmlElement(*message)),
65 resume_callback);
66 CreateV2AuthenticatorWithPIN(WAITING_MESSAGE, set_authenticator);
67 return;
68 }
69
70 // Pass the message to the underlying authenticator for processing, but
71 // check for a failed SPAKE exchange if we're using the paired secret. In
72 // this case the pairing protocol can continue by communicating the error
73 // to the peer and retrying with the PIN.
74 v2_authenticator_->ProcessMessage(
75 message,
76 base::Bind(&PairingAuthenticatorBase::CheckForFailedSpakeExchange,
77 weak_factory_.GetWeakPtr(), resume_callback));
78 }
79
80 scoped_ptr<buzz::XmlElement> PairingAuthenticatorBase::GetNextMessage() {
81 DCHECK_EQ(state(), MESSAGE_READY);
82 scoped_ptr<buzz::XmlElement> result = v2_authenticator_->GetNextMessage();
83 AddPairingElements(result.get());
84 MaybeAddErrorMessage(result.get());
85 return result.Pass();
86 }
87
88 scoped_ptr<ChannelAuthenticator>
89 PairingAuthenticatorBase::CreateChannelAuthenticator() const {
90 return v2_authenticator_->CreateChannelAuthenticator();
91 }
92
93 void PairingAuthenticatorBase::MaybeAddErrorMessage(buzz::XmlElement* message) {
94 if (!error_message_.empty()) {
95 buzz::XmlElement* pairing_failed_tag =
96 new buzz::XmlElement(kPairingFailedTag);
97 pairing_failed_tag->AddAttr(kPairingErrorAttribute, error_message_);
98 message->AddElement(pairing_failed_tag);
99 error_message_.clear();
100 }
101 }
102
103 bool PairingAuthenticatorBase::HasErrorMessage(
104 const buzz::XmlElement* message) const {
105 const buzz::XmlElement* pairing_failed_tag =
106 message->FirstNamed(kPairingFailedTag);
107 if (pairing_failed_tag) {
108 // If pairing failed, and we haven't already done so, prompt the
109 // user for the PIN and try again.
Wez 2013/05/22 00:51:45 This comment doesn't describe the code that follow
Jamie 2013/05/22 01:16:46 It's a remnant from where this code used to live.
110 std::string error = pairing_failed_tag->Attr(kPairingErrorAttribute);
111 LOG(INFO) << "Pairing failed: " << error;
112 }
113 return pairing_failed_tag != NULL;
114 }
115
116 void PairingAuthenticatorBase::CheckForFailedSpakeExchange(
117 const base::Closure& resume_callback) {
118 // If the SPAKE exchange failed due to invalid credentials, and those
119 // credentials were the paired secret, then notify the peer that the
120 // PIN-less connection failed and retry using the PIN.
121 if (v2_authenticator_->state() == REJECTED &&
122 v2_authenticator_->rejection_reason() == INVALID_CREDENTIALS &&
123 using_paired_secret_) {
124 using_paired_secret_ = false;
125 error_message_ = "invalid-shared-secret";
126 v2_authenticator_.reset();
127 SetAuthenticatorCallback set_authenticator = base::Bind(
128 &PairingAuthenticatorBase::SetAuthenticator,
129 weak_factory_.GetWeakPtr(), resume_callback);
130 CreateV2AuthenticatorWithPIN(MESSAGE_READY, set_authenticator);
131 return;
132 }
133
134 resume_callback.Run();
135 }
136
137 void PairingAuthenticatorBase::SetAuthenticator(
138 const base::Closure& resume_callback,
139 scoped_ptr<Authenticator> authenticator) {
140 DCHECK(!v2_authenticator_);
141 DCHECK(authenticator);
142 waiting_for_authenticator_ = false;
143 v2_authenticator_ = authenticator.Pass();
144 resume_callback.Run();
145 }
146
147 void PairingAuthenticatorBase::SetAuthenticatorAndProcessMessage(
Wez 2013/05/22 00:51:45 nit: Couldn't you fold this and SetAuthenticator t
Jamie 2013/05/22 01:16:46 Done.
148 const buzz::XmlElement* message,
149 const base::Closure& resume_callback,
150 scoped_ptr<Authenticator> authenticator) {
151 DCHECK(!v2_authenticator_);
152 DCHECK(authenticator);
153 waiting_for_authenticator_ = false;
154 v2_authenticator_ = authenticator.Pass();
155 ProcessMessage(message, resume_callback);
156 }
157
158 } // namespace protocol
159 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698