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

Side by Side Diff: remoting/host/gnubby_auth_handler_posix.cc

Issue 138753005: Add gnubby authentication to remoting host (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Change JSON parsing and some log levels Created 6 years, 10 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 2014 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/gnubby_auth_handler_posix.h"
6
7 #include <unistd.h>
8 #include <utility>
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/file_util.h"
13 #include "base/lazy_instance.h"
14 #include "base/stl_util.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_split.h"
17 #include "base/values.h"
18 #include "net/socket/unix_domain_socket_posix.h"
19 #include "remoting/base/logging.h"
20 #include "remoting/host/gnubby_util.h"
21 #include "remoting/proto/control.pb.h"
22 #include "remoting/protocol/client_stub.h"
23
24 namespace remoting {
25
26 namespace {
27
28 // The name of the socket to listen for gnubby requests on.
29 base::LazyInstance<base::FilePath>::Leaky g_gnubby_socket_name =
30 LAZY_INSTANCE_INITIALIZER;
31
32 // STL predicate to match by a StreamListenSocket pointer.
33 class CompareSocket {
34 public:
35 explicit CompareSocket(net::StreamListenSocket* socket) : socket_(socket) {}
36
37 bool operator()(const std::pair<int, net::StreamListenSocket*> element)
38 const {
39 return socket_ == element.second;
40 }
41
42 private:
43 net::StreamListenSocket* socket_;
44 };
45
46 // Socket authentication function that only allows connections from callers with
47 // the current uid.
48 bool MatchUid(uid_t user_id, gid_t) {
49 bool allowed = user_id == getuid();
50 if (!allowed)
51 HOST_LOG << "Refused socket connection from uid " << user_id;
52 return allowed;
53 }
54
55 // Returns true if the request data is complete (has at least as many bytes as
56 // indicated by the size in the first four bytes plus four for the first bytes).
57 bool IsRequestComplete(const char* data, int data_len) {
58 if (data_len < 4)
59 return false;
60 int expected_length = ((data[0] & 255) << 24) + ((data[1] & 255) << 16) +
61 ((data[2] & 255) << 8) + (data[3] & 255) + 4;
62 return expected_length <= data_len;
63 }
64
65 } // namespace
66
67 GnubbyAuthHandlerPosix::GnubbyAuthHandlerPosix(
68 protocol::ClientStub* client_stub)
69 : client_stub_(client_stub), last_connection_id_(0) {
70 DCHECK(client_stub_);
71 }
72
73 GnubbyAuthHandlerPosix::~GnubbyAuthHandlerPosix() {
74 STLDeleteValues(&active_sockets_);
75 }
76
77 // static
78 scoped_ptr<GnubbyAuthHandler> GnubbyAuthHandler::Create(
79 protocol::ClientStub* client_stub) {
80 return scoped_ptr<GnubbyAuthHandler>(new GnubbyAuthHandlerPosix(client_stub));
81 }
82
83 // static
84 void GnubbyAuthHandler::SetGnubbySocketName(
85 const base::FilePath& gnubby_socket_name) {
86 g_gnubby_socket_name.Get() = gnubby_socket_name;
87 }
88
89 void GnubbyAuthHandlerPosix::DeliverClientMessage(const std::string& message) {
90 DCHECK(CalledOnValidThread());
91
92 std::vector<std::string> values;
93 base::SplitString(message, ' ', &values);
Sergey Ulanov 2014/02/14 07:31:59 This will also split the third component that is i
psj 2014/02/15 00:01:34 Done.
94
95 if (values[0] == "control") {
96 if (values[1] == "auth-v1") {
97 CreateAuthorizationSocket();
98 }
99 } else if (values[0] == "data") {
100 int connection_id = 0;
101 base::StringToInt(values[1], &connection_id);
102
103 ActiveSockets::iterator iter = active_sockets_.find(connection_id);
104 if (iter != active_sockets_.end()) {
105 HOST_LOG << "Sending gnubby response";
106
107 std::string reply;
108 GetGnubbyResponseFromJson(values[2], &reply);
Sergey Ulanov 2014/02/14 07:31:59 You need to verify that |values| contains at least
psj 2014/02/15 00:01:34 Ack
109
110 iter->second->Send(reply);
111 }
112 }
113 }
114
115 void GnubbyAuthHandlerPosix::DeliverHostDataMessage(int connection_id,
116 const std::string& data)
117 const {
118 DCHECK(CalledOnValidThread());
119
120 protocol::ExtensionMessage message;
121 message.set_type("gnubby-auth");
122 message.set_data("data " + base::IntToString(connection_id) + " " + data);
123
124 client_stub_->DeliverHostMessage(message);
125 }
126
127 bool GnubbyAuthHandlerPosix::HasActiveSocketForTesting(
128 net::StreamListenSocket* socket) const {
129 return std::find_if(active_sockets_.begin(),
130 active_sockets_.end(),
131 CompareSocket(socket)) != active_sockets_.end();
132 }
133
134 void GnubbyAuthHandlerPosix::DidAccept(
135 net::StreamListenSocket* server,
136 scoped_ptr<net::StreamListenSocket> socket) {
137 DCHECK(CalledOnValidThread());
138
139 active_sockets_[++last_connection_id_] = socket.release();
140 }
141
142 void GnubbyAuthHandlerPosix::DidRead(net::StreamListenSocket* socket,
143 const char* data,
144 int len) {
145 DCHECK(CalledOnValidThread());
146
147 ActiveSockets::iterator socket_iter = std::find_if(
148 active_sockets_.begin(), active_sockets_.end(), CompareSocket(socket));
149 if (socket_iter != active_sockets_.end()) {
150 int connection_id = socket_iter->first;
151
152 ActiveRequests::iterator request_iter =
153 active_requests_.find(connection_id);
154 if (request_iter != active_requests_.end()) {
155 std::vector<char>& saved_vector = request_iter->second;
156 saved_vector.insert(saved_vector.end(), data, data + len);
157
158 if (IsRequestComplete(saved_vector.data(), saved_vector.size())) {
159 ProcessGnubbyRequest(
160 connection_id, saved_vector.data(), saved_vector.size());
161 active_requests_.erase(request_iter);
162 }
163 } else if (IsRequestComplete(data, len)) {
164 ProcessGnubbyRequest(connection_id, data, len);
165 } else {
166 active_requests_[connection_id] = std::vector<char>(data, data + len);
167 }
168 }
169 }
170
171 void GnubbyAuthHandlerPosix::DidClose(net::StreamListenSocket* socket) {
172 DCHECK(CalledOnValidThread());
173
174 ActiveSockets::iterator iter = std::find_if(
175 active_sockets_.begin(), active_sockets_.end(), CompareSocket(socket));
176 if (iter != active_sockets_.end()) {
177 active_requests_.erase(iter->first);
178
179 delete iter->second;
180 active_sockets_.erase(iter);
181 }
182 }
183
184 void GnubbyAuthHandlerPosix::CreateAuthorizationSocket() {
185 DCHECK(CalledOnValidThread());
186
187 if (!g_gnubby_socket_name.Get().empty()) {
188 // If the file already exists, a socket in use error is returned.
189 base::DeleteFile(g_gnubby_socket_name.Get(), false);
190
191 HOST_LOG << "Listening for gnubby requests on "
192 << g_gnubby_socket_name.Get().value();
193
194 auth_socket_ = net::UnixDomainSocket::CreateAndListen(
195 g_gnubby_socket_name.Get().value(), this, base::Bind(MatchUid));
196 if (!auth_socket_.get()) {
197 LOG(ERROR) << "Failed to open socket for gnubby requests";
198 }
199 } else {
200 HOST_LOG << "No gnubby socket name specified";
201 }
202 }
203
204 void GnubbyAuthHandlerPosix::ProcessGnubbyRequest(int connection_id,
205 const char* data,
206 int data_len) {
207 std::string json;
208 if (GetJsonFromGnubbyRequest(data, data_len, &json)) {
209 HOST_LOG << "Received gnubby request";
210 DeliverHostDataMessage(connection_id, json);
211 } else {
212 LOG(ERROR) << "Could not decode gnubby request";
213 }
214 }
215
216 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698