OLD | NEW |
| (Empty) |
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 | |
5 #include "remoting/protocol/v1_authenticator.h" | |
6 | |
7 #include "base/base64.h" | |
8 #include "base/logging.h" | |
9 #include "crypto/rsa_private_key.h" | |
10 #include "remoting/base/constants.h" | |
11 #include "remoting/protocol/auth_util.h" | |
12 #include "remoting/protocol/ssl_hmac_channel_authenticator.h" | |
13 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" | |
14 | |
15 using buzz::QName; | |
16 using buzz::XmlElement; | |
17 | |
18 namespace remoting { | |
19 namespace protocol { | |
20 | |
21 namespace { | |
22 const char kAuthTokenTag[] = "auth-token"; | |
23 const char kCertificateTag[] = "certificate"; | |
24 } // namespace | |
25 | |
26 V1ClientAuthenticator::V1ClientAuthenticator( | |
27 const std::string& local_jid, | |
28 const std::string& shared_secret) | |
29 : local_jid_(local_jid), | |
30 shared_secret_(shared_secret), | |
31 state_(MESSAGE_READY), | |
32 rejection_reason_(INVALID_CREDENTIALS) { | |
33 } | |
34 | |
35 V1ClientAuthenticator::~V1ClientAuthenticator() { | |
36 } | |
37 | |
38 Authenticator::State V1ClientAuthenticator::state() const { | |
39 return state_; | |
40 } | |
41 | |
42 Authenticator::RejectionReason V1ClientAuthenticator::rejection_reason() const { | |
43 DCHECK_EQ(state_, REJECTED); | |
44 return rejection_reason_; | |
45 } | |
46 | |
47 void V1ClientAuthenticator::ProcessMessage(const XmlElement* message) { | |
48 DCHECK_EQ(state_, WAITING_MESSAGE); | |
49 | |
50 // Parse the certificate. | |
51 const XmlElement* cert_tag = | |
52 message->FirstNamed(QName(kChromotingXmlNamespace, kCertificateTag)); | |
53 if (cert_tag) { | |
54 std::string base64_cert = cert_tag->BodyText(); | |
55 if (!base::Base64Decode(base64_cert, &remote_cert_)) { | |
56 LOG(ERROR) << "Failed to decode certificate received from the peer."; | |
57 remote_cert_.clear(); | |
58 } | |
59 } | |
60 | |
61 if (remote_cert_.empty()) { | |
62 state_ = REJECTED; | |
63 rejection_reason_ = PROTOCOL_ERROR; | |
64 } else { | |
65 state_ = ACCEPTED; | |
66 } | |
67 } | |
68 | |
69 scoped_ptr<XmlElement> V1ClientAuthenticator::GetNextMessage() { | |
70 DCHECK_EQ(state_, MESSAGE_READY); | |
71 | |
72 scoped_ptr<XmlElement> message = CreateEmptyAuthenticatorMessage(); | |
73 std::string token = | |
74 protocol::GenerateSupportAuthToken(local_jid_, shared_secret_); | |
75 XmlElement* auth_token_tag = new XmlElement( | |
76 QName(kChromotingXmlNamespace, kAuthTokenTag)); | |
77 auth_token_tag->SetBodyText(token); | |
78 message->AddElement(auth_token_tag); | |
79 | |
80 state_ = WAITING_MESSAGE; | |
81 return message.Pass(); | |
82 } | |
83 | |
84 scoped_ptr<ChannelAuthenticator> | |
85 V1ClientAuthenticator::CreateChannelAuthenticator() const { | |
86 DCHECK_EQ(state_, ACCEPTED); | |
87 scoped_ptr<SslHmacChannelAuthenticator> result = | |
88 SslHmacChannelAuthenticator::CreateForClient( | |
89 remote_cert_, shared_secret_); | |
90 result->SetLegacyOneWayMode(SslHmacChannelAuthenticator::SEND_ONLY); | |
91 return result.PassAs<ChannelAuthenticator>(); | |
92 }; | |
93 | |
94 V1HostAuthenticator::V1HostAuthenticator( | |
95 const std::string& local_cert, | |
96 const crypto::RSAPrivateKey& local_private_key, | |
97 const std::string& shared_secret, | |
98 const std::string& remote_jid) | |
99 : local_cert_(local_cert), | |
100 local_private_key_(local_private_key.Copy()), | |
101 shared_secret_(shared_secret), | |
102 remote_jid_(remote_jid), | |
103 state_(WAITING_MESSAGE), | |
104 rejection_reason_(INVALID_CREDENTIALS) { | |
105 } | |
106 | |
107 V1HostAuthenticator::~V1HostAuthenticator() { | |
108 } | |
109 | |
110 Authenticator::State V1HostAuthenticator::state() const { | |
111 return state_; | |
112 } | |
113 | |
114 Authenticator::RejectionReason V1HostAuthenticator::rejection_reason() const { | |
115 DCHECK_EQ(state_, REJECTED); | |
116 return rejection_reason_; | |
117 } | |
118 | |
119 void V1HostAuthenticator::ProcessMessage(const XmlElement* message) { | |
120 DCHECK_EQ(state_, WAITING_MESSAGE); | |
121 | |
122 std::string auth_token = | |
123 message->TextNamed(buzz::QName(kChromotingXmlNamespace, kAuthTokenTag)); | |
124 | |
125 if (auth_token.empty()) { | |
126 state_ = REJECTED; | |
127 rejection_reason_ = PROTOCOL_ERROR; | |
128 return; | |
129 } | |
130 | |
131 if (!protocol::VerifySupportAuthToken( | |
132 remote_jid_, shared_secret_, auth_token)) { | |
133 state_ = REJECTED; | |
134 rejection_reason_ = INVALID_CREDENTIALS; | |
135 } else { | |
136 state_ = MESSAGE_READY; | |
137 } | |
138 } | |
139 | |
140 scoped_ptr<XmlElement> V1HostAuthenticator::GetNextMessage() { | |
141 DCHECK_EQ(state_, MESSAGE_READY); | |
142 | |
143 scoped_ptr<XmlElement> message = CreateEmptyAuthenticatorMessage(); | |
144 buzz::XmlElement* certificate_tag = new XmlElement( | |
145 buzz::QName(kChromotingXmlNamespace, kCertificateTag)); | |
146 std::string base64_cert; | |
147 if (!base::Base64Encode(local_cert_, &base64_cert)) { | |
148 LOG(DFATAL) << "Cannot perform base64 encode on certificate"; | |
149 } | |
150 certificate_tag->SetBodyText(base64_cert); | |
151 message->AddElement(certificate_tag); | |
152 | |
153 state_ = ACCEPTED; | |
154 return message.Pass(); | |
155 } | |
156 | |
157 scoped_ptr<ChannelAuthenticator> | |
158 V1HostAuthenticator::CreateChannelAuthenticator() const { | |
159 DCHECK_EQ(state_, ACCEPTED); | |
160 scoped_ptr<SslHmacChannelAuthenticator> result = | |
161 SslHmacChannelAuthenticator::CreateForHost( | |
162 local_cert_, local_private_key_.get(), shared_secret_); | |
163 result->SetLegacyOneWayMode(SslHmacChannelAuthenticator::RECEIVE_ONLY); | |
164 return result.PassAs<ChannelAuthenticator>(); | |
165 }; | |
166 | |
167 } // namespace remoting | |
168 } // namespace protocol | |
OLD | NEW |