• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "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"
14 
15 namespace remoting {
16 namespace protocol {
17 
18 namespace {
19 
20 // Authenticator that accepts one message and rejects connection after that.
21 class RejectingAuthenticator : public Authenticator {
22  public:
RejectingAuthenticator()23   RejectingAuthenticator()
24       : state_(WAITING_MESSAGE) {
25   }
~RejectingAuthenticator()26   virtual ~RejectingAuthenticator() {
27   }
28 
state() const29   virtual State state() const OVERRIDE {
30     return state_;
31   }
32 
started() const33   virtual bool started() const OVERRIDE {
34     return true;
35   }
36 
rejection_reason() const37   virtual RejectionReason rejection_reason() const OVERRIDE {
38     DCHECK_EQ(state_, REJECTED);
39     return INVALID_CREDENTIALS;
40   }
41 
ProcessMessage(const buzz::XmlElement * message,const base::Closure & resume_callback)42   virtual void ProcessMessage(const buzz::XmlElement* message,
43                               const base::Closure& resume_callback) OVERRIDE {
44     DCHECK_EQ(state_, WAITING_MESSAGE);
45     state_ = REJECTED;
46     resume_callback.Run();
47   }
48 
GetNextMessage()49   virtual scoped_ptr<buzz::XmlElement> GetNextMessage() OVERRIDE {
50     NOTREACHED();
51     return scoped_ptr<buzz::XmlElement>();
52   }
53 
54   virtual scoped_ptr<ChannelAuthenticator>
CreateChannelAuthenticator() const55   CreateChannelAuthenticator() const OVERRIDE {
56     NOTREACHED();
57     return scoped_ptr<ChannelAuthenticator>();
58   }
59 
60  protected:
61   State state_;
62 };
63 
64 }  // namespace
65 
66 // static
67 scoped_ptr<AuthenticatorFactory>
CreateWithSharedSecret(bool use_service_account,const std::string & host_owner,const std::string & local_cert,scoped_refptr<RsaKeyPair> key_pair,const SharedSecretHash & shared_secret_hash,scoped_refptr<PairingRegistry> pairing_registry)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());
84 }
85 
86 
87 // static
88 scoped_ptr<AuthenticatorFactory>
CreateWithThirdPartyAuth(bool use_service_account,const std::string & host_owner,const std::string & local_cert,scoped_refptr<RsaKeyPair> key_pair,scoped_ptr<TokenValidatorFactory> token_validator_factory)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());
104 }
105 
106 // static
107 scoped_ptr<AuthenticatorFactory>
CreateRejecting()108     Me2MeHostAuthenticatorFactory::CreateRejecting() {
109   return scoped_ptr<AuthenticatorFactory>(new Me2MeHostAuthenticatorFactory());
110 }
111 
Me2MeHostAuthenticatorFactory()112 Me2MeHostAuthenticatorFactory::Me2MeHostAuthenticatorFactory() {
113 }
114 
~Me2MeHostAuthenticatorFactory()115 Me2MeHostAuthenticatorFactory::~Me2MeHostAuthenticatorFactory() {
116 }
117 
CreateAuthenticator(const std::string & local_jid,const std::string & remote_jid,const buzz::XmlElement * first_message)118 scoped_ptr<Authenticator> Me2MeHostAuthenticatorFactory::CreateAuthenticator(
119     const std::string& local_jid,
120     const std::string& remote_jid,
121     const buzz::XmlElement* first_message) {
122 
123   std::string remote_jid_prefix;
124 
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());
134     }
135     remote_jid_prefix = local_jid.substr(0, slash_pos);
136   } else {
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_;
140   }
141 
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());
148   }
149 
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));
156     }
157 
158     return NegotiatingHostAuthenticator::CreateWithSharedSecret(
159         local_cert_, key_pair_, shared_secret_hash_.value,
160         shared_secret_hash_.hash_function, pairing_registry_);
161   }
162 
163   return scoped_ptr<Authenticator>(new RejectingAuthenticator());
164 }
165 
166 }  // namespace protocol
167 }  // namespace remoting
168