| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/host/security_key/security_key_auth_handler.h" | 5 #include "remoting/host/security_key/security_key_auth_handler.h" |
| 6 | 6 |
| 7 #include <cstdint> | 7 #include <cstdint> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 #include "remoting/host/chromoting_messages.h" | 28 #include "remoting/host/chromoting_messages.h" |
| 29 #include "remoting/host/client_session_details.h" | 29 #include "remoting/host/client_session_details.h" |
| 30 #include "remoting/host/ipc_util.h" | 30 #include "remoting/host/ipc_util.h" |
| 31 #include "remoting/host/security_key/security_key_ipc_constants.h" | 31 #include "remoting/host/security_key/security_key_ipc_constants.h" |
| 32 #include "remoting/host/security_key/security_key_ipc_server.h" | 32 #include "remoting/host/security_key/security_key_ipc_server.h" |
| 33 | 33 |
| 34 namespace { | 34 namespace { |
| 35 | 35 |
| 36 // The timeout used to disconnect a client from the IPC Server channel if it | 36 // The timeout used to disconnect a client from the IPC Server channel if it |
| 37 // forgets to do so. This ensures the server channel is not blocked forever. | 37 // forgets to do so. This ensures the server channel is not blocked forever. |
| 38 const int kInitialRequestTimeoutSeconds = 5; | 38 constexpr base::TimeDelta kInitialRequestTimeout = |
| 39 base::TimeDelta::FromSeconds(5); |
| 39 | 40 |
| 40 // This value represents the amount of time to wait for a security key request | 41 // This value represents the amount of time to wait for a security key request |
| 41 // from the client before terminating the connection. | 42 // from the client before terminating the connection. |
| 42 const int kSecurityKeyRequestTimeoutSeconds = 60; | 43 constexpr base::TimeDelta kSecurityKeyRequestTimeout = |
| 44 base::TimeDelta::FromSeconds(60); |
| 43 | 45 |
| 44 } // namespace | 46 } // namespace |
| 45 | 47 |
| 46 namespace remoting { | 48 namespace remoting { |
| 47 | 49 |
| 48 // Creates an IPC server channel which services IPC clients that want to start | 50 // Creates an IPC server channel which services IPC clients that want to start |
| 49 // a security key forwarding session. Once an IPC Client connects to the | 51 // a security key forwarding session. Once an IPC Client connects to the |
| 50 // server, the SecurityKeyAuthHandlerWin class will create a new | 52 // server, the SecurityKeyAuthHandlerWin class will create a new |
| 51 // SecurityKeyIpcServer instance that will service that request. The new | 53 // SecurityKeyIpcServer instance that will service that request. The new |
| 52 // instance will exist for the lifetime of the security key request and will be | 54 // instance will exist for the lifetime of the security key request and will be |
| 53 // assigned a unique IPC channel name and connection id. The channel name is | 55 // assigned a unique IPC channel name and connection id. The channel name is |
| 54 // sent to the client which should disconnect the IPC server channel and | 56 // sent to the client which should disconnect the IPC server channel and |
| 55 // connect to the security key forwarding session IPC channel to send/receive | 57 // connect to the security key forwarding session IPC channel to send/receive |
| 56 // security key messages. The IPC server channel will then be reset so it can | 58 // security key messages. The IPC server channel will then be reset so it can |
| 57 // can service the next client/request. This system allows multiple security | 59 // can service the next client/request. This system allows multiple security |
| 58 // key forwarding sessions to occur concurrently. | 60 // key forwarding sessions to occur concurrently. |
| 59 // TODO(joedow): Update SecurityKeyAuthHandler impls to run on a separate IO | 61 // TODO(joedow): Update SecurityKeyAuthHandler impls to run on a separate IO |
| 60 // thread instead of the thread it was created on: crbug.com/591739 | 62 // thread instead of the thread it was created on: crbug.com/591739 |
| 61 class SecurityKeyAuthHandlerWin : public SecurityKeyAuthHandler, | 63 class SecurityKeyAuthHandlerWin : public SecurityKeyAuthHandler { |
| 62 public IPC::Listener { | |
| 63 public: | 64 public: |
| 64 explicit SecurityKeyAuthHandlerWin( | 65 explicit SecurityKeyAuthHandlerWin( |
| 65 ClientSessionDetails* client_session_details); | 66 ClientSessionDetails* client_session_details); |
| 66 ~SecurityKeyAuthHandlerWin() override; | 67 ~SecurityKeyAuthHandlerWin() override; |
| 67 | 68 |
| 68 private: | 69 private: |
| 69 typedef std::map<int, std::unique_ptr<SecurityKeyIpcServer>> ActiveChannels; | 70 typedef std::map<int, std::unique_ptr<SecurityKeyIpcServer>> ActiveChannels; |
| 70 | 71 |
| 71 // SecurityKeyAuthHandler interface. | 72 // SecurityKeyAuthHandler interface. |
| 72 void CreateSecurityKeyConnection() override; | 73 void CreateSecurityKeyConnection() override; |
| 73 bool IsValidConnectionId(int security_key_connection_id) const override; | 74 bool IsValidConnectionId(int security_key_connection_id) const override; |
| 74 void SendClientResponse(int security_key_connection_id, | 75 void SendClientResponse(int security_key_connection_id, |
| 75 const std::string& response) override; | 76 const std::string& response) override; |
| 76 void SendErrorAndCloseConnection(int security_key_connection_id) override; | 77 void SendErrorAndCloseConnection(int security_key_connection_id) override; |
| 77 void SetSendMessageCallback(const SendMessageCallback& callback) override; | 78 void SetSendMessageCallback(const SendMessageCallback& callback) override; |
| 78 size_t GetActiveConnectionCountForTest() const override; | 79 size_t GetActiveConnectionCountForTest() const override; |
| 79 void SetRequestTimeoutForTest(base::TimeDelta timeout) override; | 80 void SetRequestTimeoutForTest(base::TimeDelta timeout) override; |
| 80 | 81 |
| 81 // IPC::Listener implementation. | |
| 82 bool OnMessageReceived(const IPC::Message& message) override; | |
| 83 void OnChannelConnected(int32_t peer_pid) override; | |
| 84 void OnChannelError() override; | |
| 85 | |
| 86 // Creates the IPC server channel and waits for a connection using | 82 // Creates the IPC server channel and waits for a connection using |
| 87 // |ipc_server_channel_name_|. | 83 // |ipc_server_channel_name_|. |
| 88 void StartIpcServerChannel(); | 84 void StartIpcServerChannel(); |
| 89 | 85 |
| 90 // Restarts the IPC server channel to prepare for another connection. | |
| 91 void RecreateIpcServerChannel(); | |
| 92 | |
| 93 // Closes the IPC channel created for a security key forwarding session. | 86 // Closes the IPC channel created for a security key forwarding session. |
| 94 void CloseSecurityKeyRequestIpcChannel(int connection_id); | 87 void CloseSecurityKeyRequestIpcChannel(int connection_id); |
| 95 | 88 |
| 96 // Returns the IPC Channel instance created for |connection_id|. | 89 // Returns the IPC Channel instance created for |connection_id|. |
| 97 ActiveChannels::const_iterator GetChannelForConnectionId( | 90 ActiveChannels::const_iterator GetChannelForConnectionId( |
| 98 int connection_id) const; | 91 int connection_id) const; |
| 99 | 92 |
| 100 // Creates a unique name based on the well-known IPC channel name. | 93 void OnChannelConnected(); |
| 101 std::string GenerateUniqueChannelName(); | |
| 102 | 94 |
| 103 // Represents the last id assigned to a new security key request IPC channel. | 95 // Represents the last id assigned to a new security key request IPC channel. |
| 104 int last_connection_id_ = 0; | 96 int last_connection_id_ = 0; |
| 105 | 97 |
| 106 // Sends a security key extension message to the client when called. | 98 // Sends a security key extension message to the client when called. |
| 107 SendMessageCallback send_message_callback_; | 99 SendMessageCallback send_message_callback_; |
| 108 | 100 |
| 109 // Interface which provides details about the client session. | 101 // Interface which provides details about the client session. |
| 110 ClientSessionDetails* client_session_details_ = nullptr; | 102 ClientSessionDetails* client_session_details_ = nullptr; |
| 111 | 103 |
| 112 // Tracks the IPC channel created for each security key forwarding session. | 104 // Tracks the IPC channel created for each security key forwarding session. |
| 113 ActiveChannels active_channels_; | 105 ActiveChannels active_channels_; |
| 114 | 106 |
| 115 // The amount of time to wait for a client to process the connection details | 107 // The amount of time to wait for a client to process the connection details |
| 116 // message and disconnect from the IPC server channel before disconnecting it. | 108 // message and disconnect from the IPC server channel before disconnecting it. |
| 117 base::TimeDelta disconnect_timeout_; | 109 base::TimeDelta disconnect_timeout_; |
| 118 | 110 |
| 119 // Used to recreate the IPC server channel if a client forgets to disconnect. | |
| 120 base::OneShotTimer timer_; | |
| 121 | |
| 122 // IPC Clients connect to this channel first to receive their own IPC | |
| 123 // channel to start a security key forwarding session on. | |
| 124 std::unique_ptr<IPC::Channel> ipc_server_channel_; | |
| 125 | |
| 126 // Ensures SecurityKeyAuthHandlerWin methods are called on the same thread. | 111 // Ensures SecurityKeyAuthHandlerWin methods are called on the same thread. |
| 127 base::ThreadChecker thread_checker_; | 112 base::ThreadChecker thread_checker_; |
| 128 | 113 |
| 129 base::WeakPtrFactory<SecurityKeyAuthHandlerWin> weak_factory_; | 114 base::WeakPtrFactory<SecurityKeyAuthHandlerWin> weak_factory_; |
| 130 | 115 |
| 131 DISALLOW_COPY_AND_ASSIGN(SecurityKeyAuthHandlerWin); | 116 DISALLOW_COPY_AND_ASSIGN(SecurityKeyAuthHandlerWin); |
| 132 }; | 117 }; |
| 133 | 118 |
| 134 std::unique_ptr<SecurityKeyAuthHandler> SecurityKeyAuthHandler::Create( | 119 std::unique_ptr<SecurityKeyAuthHandler> SecurityKeyAuthHandler::Create( |
| 135 ClientSessionDetails* client_session_details, | 120 ClientSessionDetails* client_session_details, |
| 136 const SendMessageCallback& send_message_callback, | 121 const SendMessageCallback& send_message_callback, |
| 137 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) { | 122 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) { |
| 138 std::unique_ptr<SecurityKeyAuthHandler> auth_handler( | 123 std::unique_ptr<SecurityKeyAuthHandler> auth_handler( |
| 139 new SecurityKeyAuthHandlerWin(client_session_details)); | 124 new SecurityKeyAuthHandlerWin(client_session_details)); |
| 140 auth_handler->SetSendMessageCallback(send_message_callback); | 125 auth_handler->SetSendMessageCallback(send_message_callback); |
| 141 return auth_handler; | 126 return auth_handler; |
| 142 } | 127 } |
| 143 | 128 |
| 144 SecurityKeyAuthHandlerWin::SecurityKeyAuthHandlerWin( | 129 SecurityKeyAuthHandlerWin::SecurityKeyAuthHandlerWin( |
| 145 ClientSessionDetails* client_session_details) | 130 ClientSessionDetails* client_session_details) |
| 146 : client_session_details_(client_session_details), | 131 : client_session_details_(client_session_details), |
| 147 disconnect_timeout_( | 132 disconnect_timeout_(kInitialRequestTimeout), |
| 148 base::TimeDelta::FromSeconds(kInitialRequestTimeoutSeconds)), | |
| 149 weak_factory_(this) { | 133 weak_factory_(this) { |
| 150 DCHECK(client_session_details_); | 134 DCHECK(client_session_details_); |
| 151 } | 135 } |
| 152 | 136 |
| 153 SecurityKeyAuthHandlerWin::~SecurityKeyAuthHandlerWin() {} | 137 SecurityKeyAuthHandlerWin::~SecurityKeyAuthHandlerWin() {} |
| 154 | 138 |
| 155 void SecurityKeyAuthHandlerWin::CreateSecurityKeyConnection() { | 139 void SecurityKeyAuthHandlerWin::CreateSecurityKeyConnection() { |
| 156 DCHECK(thread_checker_.CalledOnValidThread()); | 140 DCHECK(thread_checker_.CalledOnValidThread()); |
| 157 StartIpcServerChannel(); | 141 StartIpcServerChannel(); |
| 158 } | 142 } |
| 159 | 143 |
| 160 bool SecurityKeyAuthHandlerWin::IsValidConnectionId(int connection_id) const { | 144 bool SecurityKeyAuthHandlerWin::IsValidConnectionId(int connection_id) const { |
| 161 DCHECK(thread_checker_.CalledOnValidThread()); | 145 DCHECK(thread_checker_.CalledOnValidThread()); |
| 162 return (GetChannelForConnectionId(connection_id) != active_channels_.end()); | 146 return connection_id != last_connection_id_ && |
| 147 (GetChannelForConnectionId(connection_id) != active_channels_.end()); |
| 163 } | 148 } |
| 164 | 149 |
| 165 void SecurityKeyAuthHandlerWin::SendClientResponse( | 150 void SecurityKeyAuthHandlerWin::SendClientResponse( |
| 166 int connection_id, | 151 int connection_id, |
| 167 const std::string& response_data) { | 152 const std::string& response_data) { |
| 168 DCHECK(thread_checker_.CalledOnValidThread()); | 153 DCHECK(thread_checker_.CalledOnValidThread()); |
| 169 | 154 |
| 170 ActiveChannels::const_iterator iter = | 155 ActiveChannels::const_iterator iter = |
| 171 GetChannelForConnectionId(connection_id); | 156 GetChannelForConnectionId(connection_id); |
| 172 if (iter == active_channels_.end()) { | 157 if (iter == active_channels_.end()) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 187 CloseSecurityKeyRequestIpcChannel(connection_id); | 172 CloseSecurityKeyRequestIpcChannel(connection_id); |
| 188 } | 173 } |
| 189 | 174 |
| 190 void SecurityKeyAuthHandlerWin::SetSendMessageCallback( | 175 void SecurityKeyAuthHandlerWin::SetSendMessageCallback( |
| 191 const SendMessageCallback& callback) { | 176 const SendMessageCallback& callback) { |
| 192 DCHECK(thread_checker_.CalledOnValidThread()); | 177 DCHECK(thread_checker_.CalledOnValidThread()); |
| 193 send_message_callback_ = callback; | 178 send_message_callback_ = callback; |
| 194 } | 179 } |
| 195 | 180 |
| 196 size_t SecurityKeyAuthHandlerWin::GetActiveConnectionCountForTest() const { | 181 size_t SecurityKeyAuthHandlerWin::GetActiveConnectionCountForTest() const { |
| 197 return active_channels_.size(); | 182 if (active_channels_.empty()) { |
| 183 return 0u; |
| 184 } |
| 185 // One channel is waiting for a connection. |
| 186 return active_channels_.size() - 1; |
| 198 } | 187 } |
| 199 | 188 |
| 200 void SecurityKeyAuthHandlerWin::SetRequestTimeoutForTest( | 189 void SecurityKeyAuthHandlerWin::SetRequestTimeoutForTest( |
| 201 base::TimeDelta timeout) { | 190 base::TimeDelta timeout) { |
| 202 disconnect_timeout_ = timeout; | 191 disconnect_timeout_ = timeout; |
| 203 } | 192 } |
| 204 | 193 |
| 205 void SecurityKeyAuthHandlerWin::StartIpcServerChannel() { | 194 void SecurityKeyAuthHandlerWin::StartIpcServerChannel() { |
| 206 DCHECK(thread_checker_.CalledOnValidThread()); | 195 DCHECK(thread_checker_.CalledOnValidThread()); |
| 207 | 196 |
| 208 // Create a named pipe owned by the current user (the LocalService account | 197 int new_connection_id = ++last_connection_id_; |
| 209 // (SID: S-1-5-19) when running in the network process) which is available to | 198 std::unique_ptr<SecurityKeyIpcServer> ipc_server(SecurityKeyIpcServer::Create( |
| 210 // all authenticated users. | 199 new_connection_id, client_session_details_, disconnect_timeout_, |
| 211 // presubmit: allow wstring | 200 send_message_callback_, |
| 212 std::wstring user_sid; | 201 base::Bind(&SecurityKeyAuthHandlerWin::OnChannelConnected, |
| 213 CHECK(base::win::GetUserSidString(&user_sid)); | 202 base::Unretained(this)), |
| 214 std::string user_sid_utf8 = base::WideToUTF8(user_sid); | 203 base::Bind(&SecurityKeyAuthHandlerWin::CloseSecurityKeyRequestIpcChannel, |
| 215 std::string security_descriptor = base::StringPrintf( | 204 base::Unretained(this), new_connection_id))); |
| 216 "O:%sG:%sD:(A;;GA;;;AU)", user_sid_utf8.c_str(), user_sid_utf8.c_str()); | 205 ipc_server->CreateChannel(remoting::GetSecurityKeyIpcChannel(), |
| 217 | 206 kSecurityKeyRequestTimeout); |
| 218 base::win::ScopedHandle pipe; | 207 active_channels_[new_connection_id] = std::move(ipc_server); |
| 219 CHECK(CreateIpcChannel(remoting::GetSecurityKeyIpcChannelName(), | |
| 220 security_descriptor, &pipe)); | |
| 221 ipc_server_channel_ = | |
| 222 IPC::Channel::CreateNamedServer(IPC::ChannelHandle(pipe.Get()), this); | |
| 223 CHECK(ipc_server_channel_->Connect()); | |
| 224 } | |
| 225 | |
| 226 void SecurityKeyAuthHandlerWin::RecreateIpcServerChannel() { | |
| 227 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 228 | |
| 229 timer_.Stop(); | |
| 230 ipc_server_channel_.reset(); | |
| 231 | |
| 232 StartIpcServerChannel(); | |
| 233 } | 208 } |
| 234 | 209 |
| 235 void SecurityKeyAuthHandlerWin::CloseSecurityKeyRequestIpcChannel( | 210 void SecurityKeyAuthHandlerWin::CloseSecurityKeyRequestIpcChannel( |
| 236 int connection_id) { | 211 int connection_id) { |
| 237 active_channels_.erase(connection_id); | 212 active_channels_.erase(connection_id); |
| 238 } | 213 } |
| 239 | 214 |
| 240 SecurityKeyAuthHandlerWin::ActiveChannels::const_iterator | 215 SecurityKeyAuthHandlerWin::ActiveChannels::const_iterator |
| 241 SecurityKeyAuthHandlerWin::GetChannelForConnectionId(int connection_id) const { | 216 SecurityKeyAuthHandlerWin::GetChannelForConnectionId(int connection_id) const { |
| 242 return active_channels_.find(connection_id); | 217 return active_channels_.find(connection_id); |
| 243 } | 218 } |
| 244 | 219 |
| 245 std::string SecurityKeyAuthHandlerWin::GenerateUniqueChannelName() { | 220 void SecurityKeyAuthHandlerWin::OnChannelConnected() { |
| 246 return GetSecurityKeyIpcChannelName() + "." + | 221 // Create another server to accept the next connection. |
| 247 IPC::Channel::GenerateUniqueRandomChannelID(); | 222 StartIpcServerChannel(); |
| 248 } | |
| 249 | |
| 250 bool SecurityKeyAuthHandlerWin::OnMessageReceived(const IPC::Message& message) { | |
| 251 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 252 // This class does handle any IPC messages sent by the client. | |
| 253 return false; | |
| 254 } | |
| 255 | |
| 256 void SecurityKeyAuthHandlerWin::OnChannelConnected(int32_t peer_pid) { | |
| 257 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 258 | |
| 259 timer_.Start(FROM_HERE, disconnect_timeout_, | |
| 260 base::Bind(&SecurityKeyAuthHandlerWin::OnChannelError, | |
| 261 base::Unretained(this))); | |
| 262 | |
| 263 // Verify the IPC connection attempt originated from the session we are | |
| 264 // currently remoting. We don't want to service requests from arbitrary | |
| 265 // Windows sessions. | |
| 266 bool close_connection = false; | |
| 267 DWORD peer_session_id; | |
| 268 if (!ProcessIdToSessionId(peer_pid, &peer_session_id)) { | |
| 269 PLOG(ERROR) << "ProcessIdToSessionId() failed"; | |
| 270 close_connection = true; | |
| 271 } else if (peer_session_id != client_session_details_->desktop_session_id()) { | |
| 272 LOG(INFO) << "Ignoring connection attempt from outside remoted session."; | |
| 273 close_connection = true; | |
| 274 } | |
| 275 if (close_connection) { | |
| 276 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 277 FROM_HERE, base::Bind(&SecurityKeyAuthHandlerWin::OnChannelError, | |
| 278 weak_factory_.GetWeakPtr())); | |
| 279 return; | |
| 280 } | |
| 281 | |
| 282 int new_connection_id = ++last_connection_id_; | |
| 283 std::unique_ptr<SecurityKeyIpcServer> ipc_server(SecurityKeyIpcServer::Create( | |
| 284 new_connection_id, client_session_details_, disconnect_timeout_, | |
| 285 send_message_callback_, | |
| 286 base::Bind(&SecurityKeyAuthHandlerWin::CloseSecurityKeyRequestIpcChannel, | |
| 287 base::Unretained(this), new_connection_id))); | |
| 288 | |
| 289 std::string unique_channel_name = GenerateUniqueChannelName(); | |
| 290 if (ipc_server->CreateChannel( | |
| 291 unique_channel_name, | |
| 292 base::TimeDelta::FromSeconds(kSecurityKeyRequestTimeoutSeconds))) { | |
| 293 active_channels_[new_connection_id] = std::move(ipc_server); | |
| 294 ipc_server_channel_->Send( | |
| 295 new ChromotingNetworkToRemoteSecurityKeyMsg_ConnectionDetails( | |
| 296 unique_channel_name)); | |
| 297 } | |
| 298 } | |
| 299 | |
| 300 void SecurityKeyAuthHandlerWin::OnChannelError() { | |
| 301 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 302 | |
| 303 // Could be an error, most likely the client disconnected though. Either way | |
| 304 // we should restart the server to prepare for the next connection. | |
| 305 RecreateIpcServerChannel(); | |
| 306 } | 223 } |
| 307 | 224 |
| 308 } // namespace remoting | 225 } // namespace remoting |
| OLD | NEW |