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