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
3 // found in the LICENSE file.
4
5 #include "chromeos/dbus/permission_broker/permission_broker_client.h"
6
7 #include <stdint.h>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "base/macros.h"
13 #include "base/memory/weak_ptr.h"
14 #include "chromeos/dbus/permission_broker/fake_permission_broker_client.h"
15 #include "dbus/bus.h"
16 #include "dbus/message.h"
17 #include "dbus/object_proxy.h"
18 #include "third_party/cros_system_api/dbus/service_constants.h"
19
20 using permission_broker::kCheckPathAccess;
21 using permission_broker::kClaimDevicePath;
22 using permission_broker::kOpenPath;
23 using permission_broker::kPermissionBrokerInterface;
24 using permission_broker::kPermissionBrokerServiceName;
25 using permission_broker::kPermissionBrokerServicePath;
26 using permission_broker::kReleaseTcpPort;
27 using permission_broker::kReleaseTcpPortForward;
28 using permission_broker::kReleaseUdpPort;
29 using permission_broker::kReleaseUdpPortForward;
30 using permission_broker::kRequestTcpPortAccess;
31 using permission_broker::kRequestTcpPortForward;
32 using permission_broker::kRequestUdpPortAccess;
33 using permission_broker::kRequestUdpPortForward;
34
35 namespace chromeos {
36
37 namespace {
38
39 const char kNoResponseError[] = "org.chromium.Error.NoResponse";
40
41 PermissionBrokerClient* g_instance = nullptr;
42
43 } // namespace
44
45 class PermissionBrokerClientImpl : public PermissionBrokerClient {
46 public:
47 PermissionBrokerClientImpl() = default;
48 ~PermissionBrokerClientImpl() override = default;
49
CheckPathAccess(const std::string & path,ResultCallback callback)50 void CheckPathAccess(const std::string& path,
51 ResultCallback callback) override {
52 dbus::MethodCall method_call(kPermissionBrokerInterface, kCheckPathAccess);
53 dbus::MessageWriter writer(&method_call);
54 writer.AppendString(path);
55 proxy_->CallMethod(
56 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
57 base::BindOnce(&PermissionBrokerClientImpl::OnResponse,
58 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
59 }
60
OpenPath(const std::string & path,OpenPathCallback callback,ErrorCallback error_callback)61 void OpenPath(const std::string& path,
62 OpenPathCallback callback,
63 ErrorCallback error_callback) override {
64 dbus::MethodCall method_call(kPermissionBrokerInterface, kOpenPath);
65 dbus::MessageWriter writer(&method_call);
66 writer.AppendString(path);
67 proxy_->CallMethodWithErrorCallback(
68 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
69 base::BindOnce(&PermissionBrokerClientImpl::OnOpenPathResponse,
70 weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
71 base::BindOnce(&PermissionBrokerClientImpl::OnError,
72 weak_ptr_factory_.GetWeakPtr(),
73 std::move(error_callback)));
74 }
75
ClaimDevicePath(const std::string & path,uint32_t allowed_interfaces_mask,int lifeline_fd,OpenPathCallback callback,ErrorCallback error_callback)76 void ClaimDevicePath(const std::string& path,
77 uint32_t allowed_interfaces_mask,
78 int lifeline_fd,
79 OpenPathCallback callback,
80 ErrorCallback error_callback) override {
81 dbus::MethodCall method_call(kPermissionBrokerInterface, kClaimDevicePath);
82 dbus::MessageWriter writer(&method_call);
83 writer.AppendString(path);
84 writer.AppendUint32(allowed_interfaces_mask);
85 writer.AppendFileDescriptor(lifeline_fd);
86 proxy_->CallMethodWithErrorCallback(
87 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
88 base::BindOnce(&PermissionBrokerClientImpl::OnOpenPathResponse,
89 weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
90 base::BindOnce(&PermissionBrokerClientImpl::OnError,
91 weak_ptr_factory_.GetWeakPtr(),
92 std::move(error_callback)));
93 }
94
RequestTcpPortAccess(uint16_t port,const std::string & interface,int lifeline_fd,ResultCallback callback)95 void RequestTcpPortAccess(uint16_t port,
96 const std::string& interface,
97 int lifeline_fd,
98 ResultCallback callback) override {
99 dbus::MethodCall method_call(kPermissionBrokerInterface,
100 kRequestTcpPortAccess);
101 dbus::MessageWriter writer(&method_call);
102 writer.AppendUint16(port);
103 writer.AppendString(interface);
104 writer.AppendFileDescriptor(lifeline_fd);
105 proxy_->CallMethod(
106 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
107 base::BindOnce(&PermissionBrokerClientImpl::OnResponse,
108 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
109 }
110
RequestUdpPortAccess(uint16_t port,const std::string & interface,int lifeline_fd,ResultCallback callback)111 void RequestUdpPortAccess(uint16_t port,
112 const std::string& interface,
113 int lifeline_fd,
114 ResultCallback callback) override {
115 dbus::MethodCall method_call(kPermissionBrokerInterface,
116 kRequestUdpPortAccess);
117 dbus::MessageWriter writer(&method_call);
118 writer.AppendUint16(port);
119 writer.AppendString(interface);
120 writer.AppendFileDescriptor(lifeline_fd);
121 proxy_->CallMethod(
122 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
123 base::BindOnce(&PermissionBrokerClientImpl::OnResponse,
124 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
125 }
126
ReleaseTcpPort(uint16_t port,const std::string & interface,ResultCallback callback)127 void ReleaseTcpPort(uint16_t port,
128 const std::string& interface,
129 ResultCallback callback) override {
130 dbus::MethodCall method_call(kPermissionBrokerInterface, kReleaseTcpPort);
131 dbus::MessageWriter writer(&method_call);
132 writer.AppendUint16(port);
133 writer.AppendString(interface);
134 proxy_->CallMethod(
135 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
136 base::BindOnce(&PermissionBrokerClientImpl::OnResponse,
137 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
138 }
139
ReleaseUdpPort(uint16_t port,const std::string & interface,ResultCallback callback)140 void ReleaseUdpPort(uint16_t port,
141 const std::string& interface,
142 ResultCallback callback) override {
143 dbus::MethodCall method_call(kPermissionBrokerInterface, kReleaseUdpPort);
144 dbus::MessageWriter writer(&method_call);
145 writer.AppendUint16(port);
146 writer.AppendString(interface);
147 proxy_->CallMethod(
148 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
149 base::BindOnce(&PermissionBrokerClientImpl::OnResponse,
150 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
151 }
152
RequestTcpPortForward(uint16_t in_port,const std::string & in_interface,const std::string & dst_ip,uint16_t dst_port,int lifeline_fd,ResultCallback callback)153 void RequestTcpPortForward(uint16_t in_port,
154 const std::string& in_interface,
155 const std::string& dst_ip,
156 uint16_t dst_port,
157 int lifeline_fd,
158 ResultCallback callback) override {
159 dbus::MethodCall method_call(kPermissionBrokerInterface,
160 kRequestTcpPortForward);
161 dbus::MessageWriter writer(&method_call);
162 writer.AppendUint16(in_port);
163 writer.AppendString(in_interface);
164 writer.AppendString(dst_ip);
165 writer.AppendUint16(dst_port);
166 writer.AppendFileDescriptor(lifeline_fd);
167 proxy_->CallMethod(
168 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
169 base::BindOnce(&PermissionBrokerClientImpl::OnResponse,
170 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
171 }
172
RequestUdpPortForward(uint16_t in_port,const std::string & in_interface,const std::string & dst_ip,uint16_t dst_port,int lifeline_fd,ResultCallback callback)173 void RequestUdpPortForward(uint16_t in_port,
174 const std::string& in_interface,
175 const std::string& dst_ip,
176 uint16_t dst_port,
177 int lifeline_fd,
178 ResultCallback callback) override {
179 dbus::MethodCall method_call(kPermissionBrokerInterface,
180 kRequestUdpPortForward);
181 dbus::MessageWriter writer(&method_call);
182 writer.AppendUint16(in_port);
183 writer.AppendString(in_interface);
184 writer.AppendString(dst_ip);
185 writer.AppendUint16(dst_port);
186 writer.AppendFileDescriptor(lifeline_fd);
187 proxy_->CallMethod(
188 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
189 base::BindOnce(&PermissionBrokerClientImpl::OnResponse,
190 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
191 }
192
ReleaseTcpPortForward(uint16_t in_port,const std::string & in_interface,ResultCallback callback)193 void ReleaseTcpPortForward(uint16_t in_port,
194 const std::string& in_interface,
195 ResultCallback callback) override {
196 dbus::MethodCall method_call(kPermissionBrokerInterface,
197 kReleaseTcpPortForward);
198 dbus::MessageWriter writer(&method_call);
199 writer.AppendUint16(in_port);
200 writer.AppendString(in_interface);
201 proxy_->CallMethod(
202 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
203 base::BindOnce(&PermissionBrokerClientImpl::OnResponse,
204 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
205 }
206
ReleaseUdpPortForward(uint16_t in_port,const std::string & in_interface,ResultCallback callback)207 void ReleaseUdpPortForward(uint16_t in_port,
208 const std::string& in_interface,
209 ResultCallback callback) override {
210 dbus::MethodCall method_call(kPermissionBrokerInterface,
211 kReleaseUdpPortForward);
212 dbus::MessageWriter writer(&method_call);
213 writer.AppendUint16(in_port);
214 writer.AppendString(in_interface);
215 proxy_->CallMethod(
216 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
217 base::BindOnce(&PermissionBrokerClientImpl::OnResponse,
218 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
219 }
220
Init(dbus::Bus * bus)221 void Init(dbus::Bus* bus) {
222 proxy_ =
223 bus->GetObjectProxy(kPermissionBrokerServiceName,
224 dbus::ObjectPath(kPermissionBrokerServicePath));
225 }
226
227 private:
228 // Handle a DBus response from the permission broker, invoking the callback
229 // that the method was originally called with with the success response.
OnResponse(ResultCallback callback,dbus::Response * response)230 void OnResponse(ResultCallback callback, dbus::Response* response) {
231 if (!response) {
232 LOG(WARNING) << "Access request method call failed.";
233 std::move(callback).Run(false);
234 return;
235 }
236
237 bool result = false;
238 dbus::MessageReader reader(response);
239 if (!reader.PopBool(&result))
240 LOG(WARNING) << "Could not parse response: " << response->ToString();
241 std::move(callback).Run(result);
242 }
243
OnOpenPathResponse(OpenPathCallback callback,dbus::Response * response)244 void OnOpenPathResponse(OpenPathCallback callback, dbus::Response* response) {
245 base::ScopedFD fd;
246 dbus::MessageReader reader(response);
247 if (!reader.PopFileDescriptor(&fd))
248 LOG(WARNING) << "Could not parse response: " << response->ToString();
249 std::move(callback).Run(std::move(fd));
250 }
251
OnError(ErrorCallback callback,dbus::ErrorResponse * response)252 void OnError(ErrorCallback callback, dbus::ErrorResponse* response) {
253 std::string error_name;
254 std::string error_message;
255 if (response) {
256 dbus::MessageReader reader(response);
257 error_name = response->GetErrorName();
258 reader.PopString(&error_message);
259 } else {
260 error_name = kNoResponseError;
261 }
262 std::move(callback).Run(error_name, error_message);
263 }
264
265 dbus::ObjectProxy* proxy_ = nullptr;
266
267 // Note: This should remain the last member so that it will be destroyed
268 // first, invalidating its weak pointers, before the other members are
269 // destroyed.
270 base::WeakPtrFactory<PermissionBrokerClientImpl> weak_ptr_factory_{this};
271
272 DISALLOW_COPY_AND_ASSIGN(PermissionBrokerClientImpl);
273 };
274
PermissionBrokerClient()275 PermissionBrokerClient::PermissionBrokerClient() {
276 DCHECK(!g_instance);
277 g_instance = this;
278 }
279
~PermissionBrokerClient()280 PermissionBrokerClient::~PermissionBrokerClient() {
281 DCHECK_EQ(this, g_instance);
282 g_instance = nullptr;
283 }
284
285 // static
Initialize(dbus::Bus * bus)286 void PermissionBrokerClient::Initialize(dbus::Bus* bus) {
287 DCHECK(bus);
288 (new PermissionBrokerClientImpl())->Init(bus);
289 }
290
291 // static
InitializeFake()292 void PermissionBrokerClient::InitializeFake() {
293 new FakePermissionBrokerClient();
294 }
295
296 // static
Shutdown()297 void PermissionBrokerClient::Shutdown() {
298 DCHECK(g_instance);
299 delete g_instance;
300 }
301
302 // static
Get()303 PermissionBrokerClient* PermissionBrokerClient::Get() {
304 return g_instance;
305 }
306
307 } // namespace chromeos
308