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.
5 #include "remoting/protocol/me2me_host_authenticator_factory.h"
7 #include "base/base64.h"
8 #include "base/strings/string_util.h"
9 #include "remoting/base/rsa_key_pair.h"
10 #include "remoting/protocol/channel_authenticator.h"
11 #include "remoting/protocol/negotiating_host_authenticator.h"
12 #include "remoting/protocol/token_validator.h"
13 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
20 // Authenticator that accepts one message and rejects connection after that.
21 class RejectingAuthenticator
: public Authenticator
{
23 RejectingAuthenticator()
24 : state_(WAITING_MESSAGE
) {
26 virtual ~RejectingAuthenticator() {
29 virtual State
state() const OVERRIDE
{
33 virtual bool started() const OVERRIDE
{
37 virtual RejectionReason
rejection_reason() const OVERRIDE
{
38 DCHECK_EQ(state_
, REJECTED
);
39 return INVALID_CREDENTIALS
;
42 virtual void ProcessMessage(const buzz::XmlElement
* message
,
43 const base::Closure
& resume_callback
) OVERRIDE
{
44 DCHECK_EQ(state_
, WAITING_MESSAGE
);
46 resume_callback
.Run();
49 virtual scoped_ptr
<buzz::XmlElement
> GetNextMessage() OVERRIDE
{
51 return scoped_ptr
<buzz::XmlElement
>();
54 virtual scoped_ptr
<ChannelAuthenticator
>
55 CreateChannelAuthenticator() const OVERRIDE
{
57 return scoped_ptr
<ChannelAuthenticator
>();
67 scoped_ptr
<AuthenticatorFactory
>
68 Me2MeHostAuthenticatorFactory::CreateWithSharedSecret(
69 bool use_service_account
,
70 const std::string
& host_owner
,
71 const std::string
& local_cert
,
72 scoped_refptr
<RsaKeyPair
> key_pair
,
73 const SharedSecretHash
& shared_secret_hash
,
74 scoped_refptr
<PairingRegistry
> pairing_registry
) {
75 scoped_ptr
<Me2MeHostAuthenticatorFactory
> result(
76 new Me2MeHostAuthenticatorFactory());
77 result
->use_service_account_
= use_service_account
;
78 result
->host_owner_
= host_owner
;
79 result
->local_cert_
= local_cert
;
80 result
->key_pair_
= key_pair
;
81 result
->shared_secret_hash_
= shared_secret_hash
;
82 result
->pairing_registry_
= pairing_registry
;
83 return scoped_ptr
<AuthenticatorFactory
>(result
.Pass());
88 scoped_ptr
<AuthenticatorFactory
>
89 Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth(
90 bool use_service_account
,
91 const std::string
& host_owner
,
92 const std::string
& local_cert
,
93 scoped_refptr
<RsaKeyPair
> key_pair
,
94 scoped_ptr
<TokenValidatorFactory
>
95 token_validator_factory
) {
96 scoped_ptr
<Me2MeHostAuthenticatorFactory
> result(
97 new Me2MeHostAuthenticatorFactory());
98 result
->use_service_account_
= use_service_account
;
99 result
->host_owner_
= host_owner
;
100 result
->local_cert_
= local_cert
;
101 result
->key_pair_
= key_pair
;
102 result
->token_validator_factory_
= token_validator_factory
.Pass();
103 return scoped_ptr
<AuthenticatorFactory
>(result
.Pass());
107 scoped_ptr
<AuthenticatorFactory
>
108 Me2MeHostAuthenticatorFactory::CreateRejecting() {
109 return scoped_ptr
<AuthenticatorFactory
>(new Me2MeHostAuthenticatorFactory());
112 Me2MeHostAuthenticatorFactory::Me2MeHostAuthenticatorFactory() {
115 Me2MeHostAuthenticatorFactory::~Me2MeHostAuthenticatorFactory() {
118 scoped_ptr
<Authenticator
> Me2MeHostAuthenticatorFactory::CreateAuthenticator(
119 const std::string
& local_jid
,
120 const std::string
& remote_jid
,
121 const buzz::XmlElement
* first_message
) {
123 std::string remote_jid_prefix
;
125 if (!use_service_account_
) {
126 // JID prefixes may not match the host owner email, for example, in cases
127 // where the host owner account does not have an email associated with it.
128 // In those cases, the only guarantee we have is that JIDs for the same
129 // account will have the same prefix.
130 size_t slash_pos
= local_jid
.find('/');
131 if (slash_pos
== std::string::npos
) {
132 LOG(DFATAL
) << "Invalid local JID:" << local_jid
;
133 return scoped_ptr
<Authenticator
>(new RejectingAuthenticator());
135 remote_jid_prefix
= local_jid
.substr(0, slash_pos
);
137 // TODO(rmsousa): This only works for cases where the JID prefix matches
138 // the host owner email. Figure out a way to verify the JID in other cases.
139 remote_jid_prefix
= host_owner_
;
142 // Verify that the client's jid is an ASCII string, and then check that the
143 // client JID has the expected prefix. Comparison is case insensitive.
144 if (!base::IsStringASCII(remote_jid
) ||
145 !StartsWithASCII(remote_jid
, remote_jid_prefix
+ '/', false)) {
146 LOG(ERROR
) << "Rejecting incoming connection from " << remote_jid
;
147 return scoped_ptr
<Authenticator
>(new RejectingAuthenticator());
150 if (!local_cert_
.empty() && key_pair_
.get()) {
151 if (token_validator_factory_
) {
152 return NegotiatingHostAuthenticator::CreateWithThirdPartyAuth(
153 local_cert_
, key_pair_
,
154 token_validator_factory_
->CreateTokenValidator(
155 local_jid
, remote_jid
));
158 return NegotiatingHostAuthenticator::CreateWithSharedSecret(
159 local_cert_
, key_pair_
, shared_secret_hash_
.value
,
160 shared_secret_hash_
.hash_function
, pairing_registry_
);
163 return scoped_ptr
<Authenticator
>(new RejectingAuthenticator());
166 } // namespace protocol
167 } // namespace remoting