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