| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/protocol/me2me_host_authenticator_factory.h" | 5 #include "remoting/protocol/me2me_host_authenticator_factory.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| 11 #include "remoting/base/rsa_key_pair.h" | 11 #include "remoting/base/rsa_key_pair.h" |
| 12 #include "remoting/protocol/channel_authenticator.h" | 12 #include "remoting/protocol/channel_authenticator.h" |
| 13 #include "remoting/protocol/negotiating_host_authenticator.h" | 13 #include "remoting/protocol/negotiating_host_authenticator.h" |
| 14 #include "remoting/protocol/rejecting_authenticator.h" |
| 14 #include "remoting/protocol/token_validator.h" | 15 #include "remoting/protocol/token_validator.h" |
| 15 #include "remoting/signaling/jid_util.h" | 16 #include "remoting/signaling/jid_util.h" |
| 16 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" | 17 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" |
| 17 | 18 |
| 18 namespace remoting { | 19 namespace remoting { |
| 19 namespace protocol { | 20 namespace protocol { |
| 20 | 21 |
| 21 namespace { | |
| 22 | |
| 23 // Authenticator that accepts one message and rejects connection after that. | |
| 24 class RejectingAuthenticator : public Authenticator { | |
| 25 public: | |
| 26 RejectingAuthenticator() | |
| 27 : state_(WAITING_MESSAGE) { | |
| 28 } | |
| 29 ~RejectingAuthenticator() override {} | |
| 30 | |
| 31 State state() const override { return state_; } | |
| 32 | |
| 33 bool started() const override { return true; } | |
| 34 | |
| 35 RejectionReason rejection_reason() const override { | |
| 36 DCHECK_EQ(state_, REJECTED); | |
| 37 return INVALID_CREDENTIALS; | |
| 38 } | |
| 39 | |
| 40 void ProcessMessage(const buzz::XmlElement* message, | |
| 41 const base::Closure& resume_callback) override { | |
| 42 DCHECK_EQ(state_, WAITING_MESSAGE); | |
| 43 state_ = REJECTED; | |
| 44 resume_callback.Run(); | |
| 45 } | |
| 46 | |
| 47 scoped_ptr<buzz::XmlElement> GetNextMessage() override { | |
| 48 NOTREACHED(); | |
| 49 return nullptr; | |
| 50 } | |
| 51 | |
| 52 const std::string& GetAuthKey() const override { | |
| 53 NOTREACHED(); | |
| 54 return auth_key_; | |
| 55 }; | |
| 56 | |
| 57 scoped_ptr<ChannelAuthenticator> CreateChannelAuthenticator() const override { | |
| 58 NOTREACHED(); | |
| 59 return nullptr; | |
| 60 } | |
| 61 | |
| 62 protected: | |
| 63 State state_; | |
| 64 std::string auth_key_; | |
| 65 }; | |
| 66 | |
| 67 } // namespace | |
| 68 | |
| 69 // static | 22 // static |
| 70 scoped_ptr<AuthenticatorFactory> | 23 scoped_ptr<AuthenticatorFactory> |
| 71 Me2MeHostAuthenticatorFactory::CreateWithSharedSecret( | 24 Me2MeHostAuthenticatorFactory::CreateWithSharedSecret( |
| 72 bool use_service_account, | 25 bool use_service_account, |
| 73 const std::string& host_owner, | 26 const std::string& host_owner, |
| 74 const std::string& local_cert, | 27 const std::string& local_cert, |
| 75 scoped_refptr<RsaKeyPair> key_pair, | 28 scoped_refptr<RsaKeyPair> key_pair, |
| 29 const std::string& required_client_domain, |
| 76 const SharedSecretHash& shared_secret_hash, | 30 const SharedSecretHash& shared_secret_hash, |
| 77 scoped_refptr<PairingRegistry> pairing_registry) { | 31 scoped_refptr<PairingRegistry> pairing_registry) { |
| 78 scoped_ptr<Me2MeHostAuthenticatorFactory> result( | 32 scoped_ptr<Me2MeHostAuthenticatorFactory> result( |
| 79 new Me2MeHostAuthenticatorFactory()); | 33 new Me2MeHostAuthenticatorFactory()); |
| 80 result->use_service_account_ = use_service_account; | 34 result->use_service_account_ = use_service_account; |
| 81 result->host_owner_ = host_owner; | 35 result->host_owner_ = host_owner; |
| 82 result->local_cert_ = local_cert; | 36 result->local_cert_ = local_cert; |
| 83 result->key_pair_ = key_pair; | 37 result->key_pair_ = key_pair; |
| 38 result->required_client_domain_ = required_client_domain; |
| 84 result->shared_secret_hash_ = shared_secret_hash; | 39 result->shared_secret_hash_ = shared_secret_hash; |
| 85 result->pairing_registry_ = pairing_registry; | 40 result->pairing_registry_ = pairing_registry; |
| 86 return std::move(result); | 41 return std::move(result); |
| 87 } | 42 } |
| 88 | 43 |
| 89 | 44 |
| 90 // static | 45 // static |
| 91 scoped_ptr<AuthenticatorFactory> | 46 scoped_ptr<AuthenticatorFactory> |
| 92 Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth( | 47 Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth( |
| 93 bool use_service_account, | 48 bool use_service_account, |
| 94 const std::string& host_owner, | 49 const std::string& host_owner, |
| 95 const std::string& local_cert, | 50 const std::string& local_cert, |
| 96 scoped_refptr<RsaKeyPair> key_pair, | 51 scoped_refptr<RsaKeyPair> key_pair, |
| 52 const std::string& required_client_domain, |
| 97 scoped_ptr<TokenValidatorFactory> | 53 scoped_ptr<TokenValidatorFactory> |
| 98 token_validator_factory) { | 54 token_validator_factory) { |
| 99 scoped_ptr<Me2MeHostAuthenticatorFactory> result( | 55 scoped_ptr<Me2MeHostAuthenticatorFactory> result( |
| 100 new Me2MeHostAuthenticatorFactory()); | 56 new Me2MeHostAuthenticatorFactory()); |
| 101 result->use_service_account_ = use_service_account; | 57 result->use_service_account_ = use_service_account; |
| 102 result->host_owner_ = host_owner; | 58 result->host_owner_ = host_owner; |
| 103 result->local_cert_ = local_cert; | 59 result->local_cert_ = local_cert; |
| 104 result->key_pair_ = key_pair; | 60 result->key_pair_ = key_pair; |
| 61 result->required_client_domain_ = required_client_domain; |
| 105 result->token_validator_factory_ = std::move(token_validator_factory); | 62 result->token_validator_factory_ = std::move(token_validator_factory); |
| 106 return std::move(result); | 63 return std::move(result); |
| 107 } | 64 } |
| 108 | 65 |
| 109 Me2MeHostAuthenticatorFactory::Me2MeHostAuthenticatorFactory() { | 66 Me2MeHostAuthenticatorFactory::Me2MeHostAuthenticatorFactory() { |
| 110 } | 67 } |
| 111 | 68 |
| 112 Me2MeHostAuthenticatorFactory::~Me2MeHostAuthenticatorFactory() { | 69 Me2MeHostAuthenticatorFactory::~Me2MeHostAuthenticatorFactory() { |
| 113 } | 70 } |
| 114 | 71 |
| 115 scoped_ptr<Authenticator> Me2MeHostAuthenticatorFactory::CreateAuthenticator( | 72 scoped_ptr<Authenticator> Me2MeHostAuthenticatorFactory::CreateAuthenticator( |
| 116 const std::string& local_jid, | 73 const std::string& local_jid, |
| 117 const std::string& remote_jid, | 74 const std::string& remote_jid, |
| 118 const buzz::XmlElement* first_message) { | 75 const buzz::XmlElement* first_message) { |
| 119 | 76 |
| 120 std::string remote_jid_prefix; | 77 std::string remote_jid_prefix; |
| 121 | 78 |
| 122 if (!use_service_account_) { | 79 if (!use_service_account_) { |
| 123 // JID prefixes may not match the host owner email, for example, in cases | 80 // JID prefixes may not match the host owner email, for example, in cases |
| 124 // where the host owner account does not have an email associated with it. | 81 // where the host owner account does not have an email associated with it. |
| 125 // In those cases, the only guarantee we have is that JIDs for the same | 82 // In those cases, the only guarantee we have is that JIDs for the same |
| 126 // account will have the same prefix. | 83 // account will have the same prefix. |
| 127 if (!SplitJidResource(local_jid, &remote_jid_prefix, nullptr)) { | 84 if (!SplitJidResource(local_jid, &remote_jid_prefix, nullptr)) { |
| 128 LOG(DFATAL) << "Invalid local JID:" << local_jid; | 85 LOG(DFATAL) << "Invalid local JID:" << local_jid; |
| 129 return make_scoped_ptr(new RejectingAuthenticator()); | 86 return make_scoped_ptr( |
| 87 new RejectingAuthenticator(Authenticator::INVALID_CREDENTIALS)); |
| 130 } | 88 } |
| 131 } else { | 89 } else { |
| 132 // TODO(rmsousa): This only works for cases where the JID prefix matches | 90 // TODO(rmsousa): This only works for cases where the JID prefix matches |
| 133 // the host owner email. Figure out a way to verify the JID in other cases. | 91 // the host owner email. Figure out a way to verify the JID in other cases. |
| 134 remote_jid_prefix = host_owner_; | 92 remote_jid_prefix = host_owner_; |
| 135 } | 93 } |
| 136 | 94 |
| 137 // Verify that the client's jid is an ASCII string, and then check that the | 95 // Verify that the client's jid is an ASCII string, and then check that the |
| 138 // client JID has the expected prefix. Comparison is case insensitive. | 96 // client JID has the expected prefix. Comparison is case insensitive. |
| 139 if (!base::IsStringASCII(remote_jid) || | 97 if (!base::IsStringASCII(remote_jid) || |
| 140 !base::StartsWith(remote_jid, remote_jid_prefix + '/', | 98 !base::StartsWith(remote_jid, remote_jid_prefix + '/', |
| 141 base::CompareCase::INSENSITIVE_ASCII)) { | 99 base::CompareCase::INSENSITIVE_ASCII)) { |
| 142 LOG(ERROR) << "Rejecting incoming connection from " << remote_jid; | 100 LOG(ERROR) << "Rejecting incoming connection from " << remote_jid |
| 143 return make_scoped_ptr(new RejectingAuthenticator()); | 101 << ": Prefix mismatch."; |
| 102 return make_scoped_ptr( |
| 103 new RejectingAuthenticator(Authenticator::INVALID_CREDENTIALS)); |
| 104 } |
| 105 |
| 106 // If necessary, verify that the client's jid belongs to the correct domain. |
| 107 if (!required_client_domain_.empty()) { |
| 108 std::string client_username = remote_jid; |
| 109 size_t pos = client_username.find('/'); |
| 110 if (pos != std::string::npos) { |
| 111 client_username.replace(pos, std::string::npos, ""); |
| 112 } |
| 113 if (!base::EndsWith(client_username, |
| 114 std::string("@") + required_client_domain_, |
| 115 base::CompareCase::INSENSITIVE_ASCII)) { |
| 116 LOG(ERROR) << "Rejecting incoming connection from " << remote_jid |
| 117 << ": Domain mismatch."; |
| 118 return make_scoped_ptr( |
| 119 new RejectingAuthenticator(Authenticator::INVALID_CREDENTIALS)); |
| 120 } |
| 144 } | 121 } |
| 145 | 122 |
| 146 if (!local_cert_.empty() && key_pair_.get()) { | 123 if (!local_cert_.empty() && key_pair_.get()) { |
| 147 if (token_validator_factory_) { | 124 if (token_validator_factory_) { |
| 148 return NegotiatingHostAuthenticator::CreateWithThirdPartyAuth( | 125 return NegotiatingHostAuthenticator::CreateWithThirdPartyAuth( |
| 149 local_cert_, key_pair_, | 126 local_cert_, key_pair_, |
| 150 token_validator_factory_->CreateTokenValidator( | 127 token_validator_factory_->CreateTokenValidator( |
| 151 local_jid, remote_jid)); | 128 local_jid, remote_jid)); |
| 152 } | 129 } |
| 153 | 130 |
| 154 return NegotiatingHostAuthenticator::CreateWithSharedSecret( | 131 return NegotiatingHostAuthenticator::CreateWithSharedSecret( |
| 155 local_cert_, key_pair_, shared_secret_hash_.value, | 132 local_cert_, key_pair_, shared_secret_hash_.value, |
| 156 shared_secret_hash_.hash_function, pairing_registry_); | 133 shared_secret_hash_.hash_function, pairing_registry_); |
| 157 } | 134 } |
| 158 | 135 |
| 159 return make_scoped_ptr(new RejectingAuthenticator()); | 136 return make_scoped_ptr( |
| 137 new RejectingAuthenticator(Authenticator::INVALID_CREDENTIALS)); |
| 160 } | 138 } |
| 161 | 139 |
| 162 } // namespace protocol | 140 } // namespace protocol |
| 163 } // namespace remoting | 141 } // namespace remoting |
| OLD | NEW |