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: 23 RejectingAuthenticator() 24 : state_(WAITING_MESSAGE) { 25 } 26 virtual ~RejectingAuthenticator() { 27 } 28 29 virtual State state() const OVERRIDE { 30 return state_; 31 } 32 33 virtual bool started() const OVERRIDE { 34 return true; 35 } 36 37 virtual RejectionReason rejection_reason() const OVERRIDE { 38 DCHECK_EQ(state_, REJECTED); 39 return INVALID_CREDENTIALS; 40 } 41 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 49 virtual scoped_ptr<buzz::XmlElement> GetNextMessage() OVERRIDE { 50 NOTREACHED(); 51 return scoped_ptr<buzz::XmlElement>(); 52 } 53 54 virtual scoped_ptr<ChannelAuthenticator> 55 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> 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> 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> 108 Me2MeHostAuthenticatorFactory::CreateRejecting() { 109 return scoped_ptr<AuthenticatorFactory>(new Me2MeHostAuthenticatorFactory()); 110 } 111 112 Me2MeHostAuthenticatorFactory::Me2MeHostAuthenticatorFactory() { 113 } 114 115 Me2MeHostAuthenticatorFactory::~Me2MeHostAuthenticatorFactory() { 116 } 117 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