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 |