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

Side by Side Diff: remoting/protocol/pairing_host_authenticator.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_host_authenticator.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "remoting/base/constants.h"
10 #include "remoting/base/rsa_key_pair.h"
11 #include "remoting/protocol/channel_authenticator.h"
12 #include "remoting/protocol/pairing_registry.h"
13 #include "remoting/protocol/v2_authenticator.h"
14 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
15
16 namespace remoting {
17 namespace protocol {
18
19 namespace {
20 // These definitions must be kept in sync with pairing_client_authenticator.cc.
21 const buzz::StaticQName kPairingInfoTag =
22 { kChromotingXmlNamespace, "pairing-info" };
23 const buzz::StaticQName kClientIdAttribute =
24 { "", "client-id" };
25 const buzz::StaticQName kPairingFailedTag =
26 { kChromotingXmlNamespace, "pairing-failed" };
27 const buzz::StaticQName kPairingErrorAttribute =
28 { "", "error" };
29 } // namespace
30
31 PairingHostAuthenticator::PairingHostAuthenticator(
32 scoped_refptr<PairingRegistry> pairing_registry,
33 const std::string& local_cert,
34 scoped_refptr<RsaKeyPair> key_pair,
35 const std::string& pin,
36 State initial_state)
37 : pairing_registry_(pairing_registry),
38 local_cert_(local_cert),
39 key_pair_(key_pair),
40 pin_(pin),
41 protocol_error_(false),
42 using_paired_secret_(false),
43 weak_factory_(this) {
44 // If the client didn't specify an initial message, use the PIN as the shared
45 // secret. If it did, the authenticator will be created in ProcessMessage with
46 // the appropriate paired secret from the pairing registry.
47 if (initial_state != WAITING_MESSAGE) {
48 DCHECK_EQ(initial_state, MESSAGE_READY);
49 CreateV2AuthenticatorWithPIN();
50 }
51 }
52
53 Authenticator::State PairingHostAuthenticator::state() const {
54 if (protocol_error_) {
55 return REJECTED;
56 } else if (v2_authenticator_) {
57 return v2_authenticator_->state();
58 } else {
59 return WAITING_MESSAGE;
60 }
61 }
62
63 Authenticator::RejectionReason
64 PairingHostAuthenticator::rejection_reason() const {
65 if (protocol_error_) {
66 return PROTOCOL_ERROR;
67 }
68 DCHECK(v2_authenticator_);
69 return v2_authenticator_->rejection_reason();
70 }
71
72 void PairingHostAuthenticator::ProcessMessage(
73 const buzz::XmlElement* message,
74 const base::Closure& resume_callback) {
75 DCHECK_EQ(state(), WAITING_MESSAGE);
76
77 // If there's already an underlying authenticator, defer to it, but check
78 // for a failed SPAKE exchange if we're using the paired secret. In this
79 // case the pairing protocol can continue after the client has prompted
80 // the user to enter the PIN.
81 if (v2_authenticator_) {
82 DCHECK_EQ(v2_authenticator_->state(), WAITING_MESSAGE);
83 v2_authenticator_->ProcessMessage(
84 message,
85 base::Bind(&PairingHostAuthenticator::CheckForFailedSpakeExchange,
86 weak_factory_.GetWeakPtr(), resume_callback));
87 return;
88 }
89
90 // If not, then create one based on the contents of the first message.
91 std::string client_id;
92 const buzz::XmlElement* pairing_tag = message->FirstNamed(kPairingInfoTag);
93 if (pairing_tag) {
94 client_id = pairing_tag->Attr(kClientIdAttribute);
95 }
96 if (client_id.empty()) {
97 LOG(ERROR) << "No client id specified.";
98 protocol_error_ = true;
99 resume_callback.Run();
100 return;
101 }
102
103 std::string paired_secret = pairing_registry_->GetSecret(client_id);
104
105 if (paired_secret.empty()) {
106 LOG(INFO) << "Unknown client id";
107 error_message_ = "unknown-client-id";
108 CreateV2AuthenticatorWithPIN();
109 resume_callback.Run();
110 return;
111 }
112
113 v2_authenticator_ = V2Authenticator::CreateForHost(
114 local_cert_, key_pair_, paired_secret, MESSAGE_READY);
115 using_paired_secret_ = true;
116
117 resume_callback.Run();
118 }
119
120 scoped_ptr<buzz::XmlElement> PairingHostAuthenticator::GetNextMessage() {
121 DCHECK_EQ(state(), MESSAGE_READY);
122
123 DCHECK(v2_authenticator_);
124 scoped_ptr<buzz::XmlElement> result = v2_authenticator_->GetNextMessage();
125
126 if (!error_message_.empty()) {
127 buzz::XmlElement* pairing_failed_tag =
128 new buzz::XmlElement(kPairingFailedTag);
129 pairing_failed_tag->AddAttr(kPairingErrorAttribute, error_message_);
130 result->AddElement(pairing_failed_tag);
131 error_message_.clear();
132 }
133
134 return result.Pass();
135 }
136
137 scoped_ptr<ChannelAuthenticator>
138 PairingHostAuthenticator::CreateChannelAuthenticator() const {
139 DCHECK(v2_authenticator_);
140 return v2_authenticator_->CreateChannelAuthenticator();
141 }
142
143 void PairingHostAuthenticator::CreateV2AuthenticatorWithPIN() {
144 DCHECK(!v2_authenticator_);
145 v2_authenticator_ = V2Authenticator::CreateForHost(
146 local_cert_, key_pair_, pin_, MESSAGE_READY);
147 using_paired_secret_ = false;
148 }
149
150 void PairingHostAuthenticator::CheckForFailedSpakeExchange(
151 const base::Closure& resume_callback) {
152 DCHECK(v2_authenticator_);
153 State v2_state = v2_authenticator_->state();
154 // If the SPAKE exchange failed due to invalid credentials, and those
155 // credentials were the paired secret, then notify the client that the
156 // PIN-less connection failed, causing it to prompt the user for the PIN.
157 if (v2_state == REJECTED &&
158 v2_authenticator_->rejection_reason() == INVALID_CREDENTIALS &&
159 using_paired_secret_) {
160 error_message_ = "invalid-shared-secret";
161 v2_authenticator_.reset();
162 CreateV2AuthenticatorWithPIN();
163 }
164 resume_callback.Run();
165 }
166
167 } // namespace protocol
168 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698