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/me2me_host_authenticator_factory.h"
6
7 #include <utility>
8
9 #include "base/base64.h"
10 #include "base/logging.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/strings/string_util.h"
13 #include "remoting/base/rsa_key_pair.h"
14 #include "remoting/protocol/channel_authenticator.h"
15 #include "remoting/protocol/negotiating_host_authenticator.h"
16 #include "remoting/protocol/rejecting_authenticator.h"
17 #include "remoting/protocol/token_validator.h"
18 #include "remoting/signaling/signaling_address.h"
19 #include "remoting/signaling/signaling_id_util.h"
20 #include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
21
22 namespace remoting {
23 namespace protocol {
24
25 // static
26 std::unique_ptr<AuthenticatorFactory>
CreateWithPin(const std::string & host_owner,const std::string & local_cert,scoped_refptr<RsaKeyPair> key_pair,std::vector<std::string> required_client_domain_list,const std::string & pin_hash,scoped_refptr<PairingRegistry> pairing_registry)27 Me2MeHostAuthenticatorFactory::CreateWithPin(
28 const std::string& host_owner,
29 const std::string& local_cert,
30 scoped_refptr<RsaKeyPair> key_pair,
31 std::vector<std::string> required_client_domain_list,
32 const std::string& pin_hash,
33 scoped_refptr<PairingRegistry> pairing_registry) {
34 std::unique_ptr<Me2MeHostAuthenticatorFactory> result(
35 new Me2MeHostAuthenticatorFactory());
36 result->canonical_host_owner_email_ = GetCanonicalEmail(host_owner);
37 result->local_cert_ = local_cert;
38 result->key_pair_ = key_pair;
39 result->required_client_domain_list_ = std::move(required_client_domain_list);
40 result->pin_hash_ = pin_hash;
41 result->pairing_registry_ = pairing_registry;
42 return std::move(result);
43 }
44
45 // static
46 std::unique_ptr<AuthenticatorFactory>
CreateWithThirdPartyAuth(const std::string & host_owner,const std::string & local_cert,scoped_refptr<RsaKeyPair> key_pair,std::vector<std::string> required_client_domain_list,scoped_refptr<TokenValidatorFactory> token_validator_factory)47 Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth(
48 const std::string& host_owner,
49 const std::string& local_cert,
50 scoped_refptr<RsaKeyPair> key_pair,
51 std::vector<std::string> required_client_domain_list,
52 scoped_refptr<TokenValidatorFactory> token_validator_factory) {
53 std::unique_ptr<Me2MeHostAuthenticatorFactory> result(
54 new Me2MeHostAuthenticatorFactory());
55 result->canonical_host_owner_email_ = GetCanonicalEmail(host_owner);
56 result->local_cert_ = local_cert;
57 result->key_pair_ = key_pair;
58 result->required_client_domain_list_ = std::move(required_client_domain_list);
59 result->token_validator_factory_ = token_validator_factory;
60 return std::move(result);
61 }
62
63 Me2MeHostAuthenticatorFactory::Me2MeHostAuthenticatorFactory() = default;
64
65 Me2MeHostAuthenticatorFactory::~Me2MeHostAuthenticatorFactory() = default;
66
67 std::unique_ptr<Authenticator>
CreateAuthenticator(const std::string & original_local_jid,const std::string & original_remote_jid)68 Me2MeHostAuthenticatorFactory::CreateAuthenticator(
69 const std::string& original_local_jid,
70 const std::string& original_remote_jid) {
71 std::string local_jid = NormalizeSignalingId(original_local_jid);
72 std::string remote_jid = NormalizeSignalingId(original_remote_jid);
73
74 // Verify that the client's jid is an ASCII string, and then check that the
75 // client JID has the expected prefix. Comparison is case insensitive.
76 if (!base::IsStringASCII(remote_jid) ||
77 !base::StartsWith(remote_jid, canonical_host_owner_email_ + '/',
78 base::CompareCase::INSENSITIVE_ASCII)) {
79 LOG(ERROR) << "Rejecting incoming connection from " << remote_jid
80 << ": Prefix mismatch. Expected: "
81 << canonical_host_owner_email_;
82 return base::WrapUnique(
83 new RejectingAuthenticator(Authenticator::INVALID_CREDENTIALS));
84 }
85
86 // If necessary, verify that the client's jid belongs to the correct domain.
87 if (!required_client_domain_list_.empty()) {
88 std::string client_username = remote_jid;
89 size_t pos = client_username.find('/');
90 if (pos != std::string::npos) {
91 client_username.replace(pos, std::string::npos, "");
92 }
93 bool matched = false;
94 for (const std::string& domain : required_client_domain_list_) {
95 if (base::EndsWith(client_username, std::string("@") + domain,
96 base::CompareCase::INSENSITIVE_ASCII)) {
97 matched = true;
98 break;
99 }
100 }
101 if (!matched) {
102 LOG(ERROR) << "Rejecting incoming connection from " << remote_jid
103 << ": Domain not allowed.";
104 return std::make_unique<RejectingAuthenticator>(
105 Authenticator::INVALID_ACCOUNT);
106 }
107 }
108
109 if (!local_cert_.empty() && key_pair_.get()) {
110 std::string normalized_local_jid = NormalizeSignalingId(local_jid);
111 std::string normalized_remote_jid = NormalizeSignalingId(remote_jid);
112
113 if (token_validator_factory_) {
114 return NegotiatingHostAuthenticator::CreateWithThirdPartyAuth(
115 normalized_local_jid, normalized_remote_jid, local_cert_, key_pair_,
116 token_validator_factory_);
117 }
118
119 return NegotiatingHostAuthenticator::CreateWithSharedSecret(
120 normalized_local_jid, normalized_remote_jid, local_cert_, key_pair_,
121 pin_hash_, pairing_registry_);
122 }
123
124 return base::WrapUnique(
125 new RejectingAuthenticator(Authenticator::INVALID_CREDENTIALS));
126 }
127
128 } // namespace protocol
129 } // namespace remoting
130