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 "remoting/signaling/jid_util.h"
14 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
21 // Authenticator that accepts one message and rejects connection after that.
22 class RejectingAuthenticator
: public Authenticator
{
24 RejectingAuthenticator()
25 : state_(WAITING_MESSAGE
) {
27 ~RejectingAuthenticator() override
{}
29 State
state() const override
{ return state_
; }
31 bool started() const override
{ return true; }
33 RejectionReason
rejection_reason() const override
{
34 DCHECK_EQ(state_
, REJECTED
);
35 return INVALID_CREDENTIALS
;
38 void ProcessMessage(const buzz::XmlElement
* message
,
39 const base::Closure
& resume_callback
) override
{
40 DCHECK_EQ(state_
, WAITING_MESSAGE
);
42 resume_callback
.Run();
45 scoped_ptr
<buzz::XmlElement
> GetNextMessage() override
{
50 scoped_ptr
<ChannelAuthenticator
> CreateChannelAuthenticator() const override
{
62 scoped_ptr
<AuthenticatorFactory
>
63 Me2MeHostAuthenticatorFactory::CreateWithSharedSecret(
64 bool use_service_account
,
65 const std::string
& host_owner
,
66 const std::string
& local_cert
,
67 scoped_refptr
<RsaKeyPair
> key_pair
,
68 const SharedSecretHash
& shared_secret_hash
,
69 scoped_refptr
<PairingRegistry
> pairing_registry
) {
70 scoped_ptr
<Me2MeHostAuthenticatorFactory
> result(
71 new Me2MeHostAuthenticatorFactory());
72 result
->use_service_account_
= use_service_account
;
73 result
->host_owner_
= host_owner
;
74 result
->local_cert_
= local_cert
;
75 result
->key_pair_
= key_pair
;
76 result
->shared_secret_hash_
= shared_secret_hash
;
77 result
->pairing_registry_
= pairing_registry
;
83 scoped_ptr
<AuthenticatorFactory
>
84 Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth(
85 bool use_service_account
,
86 const std::string
& host_owner
,
87 const std::string
& local_cert
,
88 scoped_refptr
<RsaKeyPair
> key_pair
,
89 scoped_ptr
<TokenValidatorFactory
>
90 token_validator_factory
) {
91 scoped_ptr
<Me2MeHostAuthenticatorFactory
> result(
92 new Me2MeHostAuthenticatorFactory());
93 result
->use_service_account_
= use_service_account
;
94 result
->host_owner_
= host_owner
;
95 result
->local_cert_
= local_cert
;
96 result
->key_pair_
= key_pair
;
97 result
->token_validator_factory_
= token_validator_factory
.Pass();
101 Me2MeHostAuthenticatorFactory::Me2MeHostAuthenticatorFactory() {
104 Me2MeHostAuthenticatorFactory::~Me2MeHostAuthenticatorFactory() {
107 scoped_ptr
<Authenticator
> Me2MeHostAuthenticatorFactory::CreateAuthenticator(
108 const std::string
& local_jid
,
109 const std::string
& remote_jid
,
110 const buzz::XmlElement
* first_message
) {
112 std::string remote_jid_prefix
;
114 if (!use_service_account_
) {
115 // JID prefixes may not match the host owner email, for example, in cases
116 // where the host owner account does not have an email associated with it.
117 // In those cases, the only guarantee we have is that JIDs for the same
118 // account will have the same prefix.
119 if (!SplitJidResource(local_jid
, &remote_jid_prefix
, nullptr)) {
120 LOG(DFATAL
) << "Invalid local JID:" << local_jid
;
121 return make_scoped_ptr(new RejectingAuthenticator());
124 // TODO(rmsousa): This only works for cases where the JID prefix matches
125 // the host owner email. Figure out a way to verify the JID in other cases.
126 remote_jid_prefix
= host_owner_
;
129 // Verify that the client's jid is an ASCII string, and then check that the
130 // client JID has the expected prefix. Comparison is case insensitive.
131 if (!base::IsStringASCII(remote_jid
) ||
132 !base::StartsWith(remote_jid
, remote_jid_prefix
+ '/',
133 base::CompareCase::INSENSITIVE_ASCII
)) {
134 LOG(ERROR
) << "Rejecting incoming connection from " << remote_jid
;
135 return make_scoped_ptr(new RejectingAuthenticator());
138 if (!local_cert_
.empty() && key_pair_
.get()) {
139 if (token_validator_factory_
) {
140 return NegotiatingHostAuthenticator::CreateWithThirdPartyAuth(
141 local_cert_
, key_pair_
,
142 token_validator_factory_
->CreateTokenValidator(
143 local_jid
, remote_jid
));
146 return NegotiatingHostAuthenticator::CreateWithSharedSecret(
147 local_cert_
, key_pair_
, shared_secret_hash_
.value
,
148 shared_secret_hash_
.hash_function
, pairing_registry_
);
151 return make_scoped_ptr(new RejectingAuthenticator());
154 } // namespace protocol
155 } // namespace remoting