Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(581)

Side by Side Diff: remoting/host/security_key/security_key_auth_handler_linux.cc

Issue 2202733004: Renaming Linux security key auth handler (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "remoting/host/security_key/security_key_auth_handler.h"
6
7 #include <unistd.h>
8
9 #include <cstdint>
10 #include <map>
11 #include <memory>
12 #include <string>
13 #include <utility>
14
15 #include "base/bind.h"
16 #include "base/callback.h"
17 #include "base/files/file_path.h"
18 #include "base/files/file_util.h"
19 #include "base/lazy_instance.h"
20 #include "base/location.h"
21 #include "base/logging.h"
22 #include "base/memory/ptr_util.h"
23 #include "base/memory/ref_counted.h"
24 #include "base/memory/weak_ptr.h"
25 #include "base/single_thread_task_runner.h"
26 #include "base/threading/thread_checker.h"
27 #include "net/base/completion_callback.h"
28 #include "net/base/net_errors.h"
29 #include "net/socket/stream_socket.h"
30 #include "net/socket/unix_domain_server_socket_posix.h"
31 #include "remoting/base/logging.h"
32 #include "remoting/host/security_key/security_key_socket.h"
33
34 namespace {
35
36 const int64_t kDefaultRequestTimeoutSeconds = 60;
37
38 // The name of the socket to listen for security key requests on.
39 base::LazyInstance<base::FilePath>::Leaky g_security_key_socket_name =
40 LAZY_INSTANCE_INITIALIZER;
41
42 // Socket authentication function that only allows connections from callers with
43 // the current uid.
44 bool MatchUid(const net::UnixDomainServerSocket::Credentials& credentials) {
45 bool allowed = credentials.user_id == getuid();
46 if (!allowed)
47 HOST_LOG << "Refused socket connection from uid " << credentials.user_id;
48 return allowed;
49 }
50
51 // Returns the command code (the first byte of the data) if it exists, or -1 if
52 // the data is empty.
53 unsigned int GetCommandCode(const std::string& data) {
54 return data.empty() ? -1 : static_cast<unsigned int>(data[0]);
55 }
56
57 } // namespace
58
59 namespace remoting {
60
61 class SecurityKeyAuthHandlerLinux : public SecurityKeyAuthHandler {
62 public:
63 explicit SecurityKeyAuthHandlerLinux(
64 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner);
65 ~SecurityKeyAuthHandlerLinux() override;
66
67 private:
68 typedef std::map<int, std::unique_ptr<SecurityKeySocket>> ActiveSockets;
69
70 // SecurityKeyAuthHandler interface.
71 void CreateSecurityKeyConnection() override;
72 bool IsValidConnectionId(int security_key_connection_id) const override;
73 void SendClientResponse(int security_key_connection_id,
74 const std::string& response) override;
75 void SendErrorAndCloseConnection(int security_key_connection_id) override;
76 void SetSendMessageCallback(const SendMessageCallback& callback) override;
77 size_t GetActiveConnectionCountForTest() const override;
78 void SetRequestTimeoutForTest(base::TimeDelta timeout) override;
79
80 // Sets up the socket used for accepting new connections.
81 void CreateSocket();
82
83 // Starts listening for connection.
84 void DoAccept();
85
86 // Called when a connection is accepted.
87 void OnAccepted(int result);
88
89 // Called when a SecurityKeySocket has done reading.
90 void OnReadComplete(int security_key_connection_id);
91
92 // Gets an active socket iterator for |security_key_connection_id|.
93 ActiveSockets::const_iterator GetSocketForConnectionId(
94 int security_key_connection_id) const;
95
96 // Send an error and closes an active socket.
97 void SendErrorAndCloseActiveSocket(const ActiveSockets::const_iterator& iter);
98
99 // A request timed out.
100 void RequestTimedOut(int security_key_connection_id);
101
102 // Ensures SecurityKeyAuthHandlerLinux methods are called on the same thread.
103 base::ThreadChecker thread_checker_;
104
105 // Socket used to listen for authorization requests.
106 std::unique_ptr<net::UnixDomainServerSocket> auth_socket_;
107
108 // A temporary holder for an accepted connection.
109 std::unique_ptr<net::StreamSocket> accept_socket_;
110
111 // Used to pass security key extension messages to the client.
112 SendMessageCallback send_message_callback_;
113
114 // The last assigned security key connection id.
115 int last_connection_id_ = 0;
116
117 // Sockets by connection id used to process gnubbyd requests.
118 ActiveSockets active_sockets_;
119
120 // Used to perform blocking File IO.
121 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
122
123 // Timeout used for a request.
124 base::TimeDelta request_timeout_;
125
126 base::WeakPtrFactory<SecurityKeyAuthHandlerLinux> weak_factory_;
127
128 DISALLOW_COPY_AND_ASSIGN(SecurityKeyAuthHandlerLinux);
129 };
130
131 std::unique_ptr<SecurityKeyAuthHandler> SecurityKeyAuthHandler::Create(
132 ClientSessionDetails* client_session_details,
133 const SendMessageCallback& send_message_callback,
134 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) {
135 std::unique_ptr<SecurityKeyAuthHandler> auth_handler(
136 new SecurityKeyAuthHandlerLinux(file_task_runner));
137 auth_handler->SetSendMessageCallback(send_message_callback);
138 return auth_handler;
139 }
140
141 void SecurityKeyAuthHandler::SetSecurityKeySocketName(
142 const base::FilePath& security_key_socket_name) {
143 g_security_key_socket_name.Get() = security_key_socket_name;
144 }
145
146 SecurityKeyAuthHandlerLinux::SecurityKeyAuthHandlerLinux(
147 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner)
148 : file_task_runner_(file_task_runner),
149 request_timeout_(
150 base::TimeDelta::FromSeconds(kDefaultRequestTimeoutSeconds)),
151 weak_factory_(this) {}
152
153 SecurityKeyAuthHandlerLinux::~SecurityKeyAuthHandlerLinux() {}
154
155 void SecurityKeyAuthHandlerLinux::CreateSecurityKeyConnection() {
156 DCHECK(thread_checker_.CalledOnValidThread());
157 DCHECK(!g_security_key_socket_name.Get().empty());
158
159 // We need to run the DeleteFile method on |file_task_runner_| as it is a
160 // blocking function call which cannot be run on the main thread. Once
161 // that task has completed, the main thread will be called back and we will
162 // resume setting up our security key auth socket there.
163 file_task_runner_->PostTaskAndReply(
164 FROM_HERE, base::Bind(base::IgnoreResult(&base::DeleteFile),
165 g_security_key_socket_name.Get(), false),
166 base::Bind(&SecurityKeyAuthHandlerLinux::CreateSocket,
167 weak_factory_.GetWeakPtr()));
168 }
169
170 void SecurityKeyAuthHandlerLinux::CreateSocket() {
171 DCHECK(thread_checker_.CalledOnValidThread());
172 HOST_LOG << "Listening for security key requests on "
173 << g_security_key_socket_name.Get().value();
174
175 auth_socket_.reset(
176 new net::UnixDomainServerSocket(base::Bind(MatchUid), false));
177 int rv = auth_socket_->BindAndListen(g_security_key_socket_name.Get().value(),
178 /*backlog=*/1);
179 if (rv != net::OK) {
180 LOG(ERROR) << "Failed to open socket for auth requests: '" << rv << "'";
181 return;
182 }
183 DoAccept();
184 }
185
186 bool SecurityKeyAuthHandlerLinux::IsValidConnectionId(
187 int security_key_connection_id) const {
188 return GetSocketForConnectionId(security_key_connection_id) !=
189 active_sockets_.end();
190 }
191
192 void SecurityKeyAuthHandlerLinux::SendClientResponse(
193 int security_key_connection_id,
194 const std::string& response) {
195 ActiveSockets::const_iterator iter =
196 GetSocketForConnectionId(security_key_connection_id);
197 if (iter != active_sockets_.end()) {
198 iter->second->SendResponse(response);
199 } else {
200 LOG(WARNING) << "Unknown gnubby-auth data connection: '"
201 << security_key_connection_id << "'";
202 }
203 }
204
205 void SecurityKeyAuthHandlerLinux::SendErrorAndCloseConnection(
206 int security_key_connection_id) {
207 ActiveSockets::const_iterator iter =
208 GetSocketForConnectionId(security_key_connection_id);
209 if (iter != active_sockets_.end()) {
210 HOST_LOG << "Sending security key error";
211 SendErrorAndCloseActiveSocket(iter);
212 } else {
213 LOG(WARNING) << "Unknown gnubby-auth data connection: '"
214 << security_key_connection_id << "'";
215 }
216 }
217
218 void SecurityKeyAuthHandlerLinux::SetSendMessageCallback(
219 const SendMessageCallback& callback) {
220 send_message_callback_ = callback;
221 }
222
223 size_t SecurityKeyAuthHandlerLinux::GetActiveConnectionCountForTest() const {
224 return active_sockets_.size();
225 }
226
227 void SecurityKeyAuthHandlerLinux::SetRequestTimeoutForTest(
228 base::TimeDelta timeout) {
229 request_timeout_ = timeout;
230 }
231
232 void SecurityKeyAuthHandlerLinux::DoAccept() {
233 DCHECK(thread_checker_.CalledOnValidThread());
234 int result = auth_socket_->Accept(
235 &accept_socket_, base::Bind(&SecurityKeyAuthHandlerLinux::OnAccepted,
236 base::Unretained(this)));
237 if (result != net::ERR_IO_PENDING)
238 OnAccepted(result);
239 }
240
241 void SecurityKeyAuthHandlerLinux::OnAccepted(int result) {
242 DCHECK(thread_checker_.CalledOnValidThread());
243 DCHECK_NE(net::ERR_IO_PENDING, result);
244
245 if (result < 0) {
246 LOG(ERROR) << "Error in accepting a new connection";
247 return;
248 }
249
250 int security_key_connection_id = ++last_connection_id_;
251 SecurityKeySocket* socket = new SecurityKeySocket(
252 std::move(accept_socket_), request_timeout_,
253 base::Bind(&SecurityKeyAuthHandlerLinux::RequestTimedOut,
254 base::Unretained(this), security_key_connection_id));
255 active_sockets_[security_key_connection_id] = base::WrapUnique(socket);
256 socket->StartReadingRequest(
257 base::Bind(&SecurityKeyAuthHandlerLinux::OnReadComplete,
258 base::Unretained(this), security_key_connection_id));
259
260 // Continue accepting new connections.
261 DoAccept();
262 }
263
264 void SecurityKeyAuthHandlerLinux::OnReadComplete(
265 int security_key_connection_id) {
266 DCHECK(thread_checker_.CalledOnValidThread());
267
268 ActiveSockets::const_iterator iter =
269 active_sockets_.find(security_key_connection_id);
270 DCHECK(iter != active_sockets_.end());
271 std::string request_data;
272 if (!iter->second->GetAndClearRequestData(&request_data)) {
273 SendErrorAndCloseActiveSocket(iter);
274 return;
275 }
276
277 HOST_LOG << "Received security key request: " << GetCommandCode(request_data);
278 send_message_callback_.Run(security_key_connection_id, request_data);
279
280 iter->second->StartReadingRequest(
281 base::Bind(&SecurityKeyAuthHandlerLinux::OnReadComplete,
282 base::Unretained(this), security_key_connection_id));
283 }
284
285 SecurityKeyAuthHandlerLinux::ActiveSockets::const_iterator
286 SecurityKeyAuthHandlerLinux::GetSocketForConnectionId(
287 int security_key_connection_id) const {
288 return active_sockets_.find(security_key_connection_id);
289 }
290
291 void SecurityKeyAuthHandlerLinux::SendErrorAndCloseActiveSocket(
292 const ActiveSockets::const_iterator& iter) {
293 iter->second->SendSshError();
294 active_sockets_.erase(iter);
295 }
296
297 void SecurityKeyAuthHandlerLinux::RequestTimedOut(
298 int security_key_connection_id) {
299 HOST_LOG << "SecurityKey request timed out";
300 ActiveSockets::const_iterator iter =
301 active_sockets_.find(security_key_connection_id);
302 if (iter != active_sockets_.end())
303 SendErrorAndCloseActiveSocket(iter);
304 }
305
306 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698