blob: 7451d4cb4ced2532932709ecd5701a57d615e8bf [file] [log] [blame]
Peter Qiu9b2ecc42015-09-17 14:37:22 -07001//
2// Copyright (C) 2015 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
Peter Qiu58083962015-11-05 14:29:50 -080017#include "apmanager/dbus/permission_broker_dbus_proxy.h"
Peter Qiu9b2ecc42015-09-17 14:37:22 -070018
19#include <base/bind.h>
Alex Vakulenko8d0c31b2015-10-13 09:14:24 -070020#include <brillo/errors/error.h>
Peter Qiu9b2ecc42015-09-17 14:37:22 -070021
22#include "apmanager/event_dispatcher.h"
23
24using std::string;
25
26namespace apmanager {
27
28PermissionBrokerDBusProxy::PermissionBrokerDBusProxy(
29 const scoped_refptr<dbus::Bus>& bus,
30 const base::Closure& service_appeared_callback,
31 const base::Closure& service_vanished_callback)
32 : proxy_(new org::chromium::PermissionBrokerProxy(bus)),
33 dispatcher_(EventDispatcher::GetInstance()),
34 service_appeared_callback_(service_appeared_callback),
35 service_vanished_callback_(service_vanished_callback),
36 service_available_(false) {
37 // Monitor service owner changes. This callback lives for the lifetime of
38 // the ObjectProxy.
39 proxy_->GetObjectProxy()->SetNameOwnerChangedCallback(
40 base::Bind(&PermissionBrokerDBusProxy::OnServiceOwnerChanged,
41 weak_factory_.GetWeakPtr()));
42
43 // One time callback when service becomes available.
44 proxy_->GetObjectProxy()->WaitForServiceToBeAvailable(
45 base::Bind(&PermissionBrokerDBusProxy::OnServiceAvailable,
46 weak_factory_.GetWeakPtr()));
47
48 // Setup lifeline pipe to allow permission_broker to monitor this process,
49 // so it can automatically remove the firewall rules when this process
50 // crashed.
51 int fds[2];
52 CHECK(pipe(fds) == 0) << "Failed to create lifeline pipe";
53 lifeline_read_fd_ = fds[0];
54 lifeline_write_fd_ = fds[1];
55}
56
57PermissionBrokerDBusProxy::~PermissionBrokerDBusProxy() {
58 close(lifeline_read_fd_);
59 close(lifeline_write_fd_);
60}
61
62bool PermissionBrokerDBusProxy::RequestUdpPortAccess(const string& interface,
63 uint16_t port) {
64 if (!service_available_) {
65 LOG(ERROR) << "permission_broker service not available";
66 return false;
67 }
68
69 // Pass the read end of the pipe to permission_broker, to allow it to
70 // monitor on this process.
71 dbus::FileDescriptor fd(lifeline_read_fd_);
72 fd.CheckValidity();
73 bool allowed = false;
Alex Vakulenko8d0c31b2015-10-13 09:14:24 -070074 brillo::ErrorPtr error;
Peter Qiu9b2ecc42015-09-17 14:37:22 -070075 if (!proxy_->RequestUdpPortAccess(port, interface, fd, &allowed, &error)) {
76 LOG(ERROR) << "Failed to request UDP port access: "
77 << error->GetCode() << " " << error->GetMessage();
78 return false;
79 }
80 if (!allowed) {
81 LOG(ERROR) << "Access request for UDP port " << port
82 << " on interface " << interface << " is denied";
83 return false;
84 }
85 LOG(INFO) << "Access granted for UDP port " << port
86 << " on interface " << interface;
87 return true;
88}
89
90bool PermissionBrokerDBusProxy::ReleaseUdpPortAccess(const string& interface,
91 uint16_t port) {
92 if (!service_available_) {
93 LOG(ERROR) << "permission_broker service not available";
94 return false;
95 }
96
Alex Vakulenko8d0c31b2015-10-13 09:14:24 -070097 brillo::ErrorPtr error;
Peter Qiu9b2ecc42015-09-17 14:37:22 -070098 bool success;
99 if (!proxy_->ReleaseUdpPort(port, interface, &success, &error)) {
100 LOG(ERROR) << "Failed to release UDP port access: "
101 << error->GetCode() << " " << error->GetMessage();
102 return false;
103 }
104 if (!success) {
105 LOG(ERROR) << "Release request for UDP port " << port
106 << " on interface " << interface << " is denied";
107 return false;
108 }
109 LOG(INFO) << "Access released for UDP port " << port
110 << " on interface " << interface;
111 return true;
112}
113
114void PermissionBrokerDBusProxy::OnServiceAvailable(bool available) {
115 LOG(INFO) << __func__ << ": " << available;
116 // The callback might invoke calls to the ObjectProxy, so defer the callback
117 // to event loop.
118 if (available && !service_appeared_callback_.is_null()) {
119 dispatcher_->PostTask(service_appeared_callback_);
120 } else if (!available && !service_vanished_callback_.is_null()) {
121 dispatcher_->PostTask(service_vanished_callback_);
122 }
123 service_available_ = available;
124}
125
126void PermissionBrokerDBusProxy::OnServiceOwnerChanged(const string& old_owner,
127 const string& new_owner) {
128 LOG(INFO) << __func__ << " old: " << old_owner << " new: " << new_owner;
129 if (new_owner.empty()) {
130 OnServiceAvailable(false);
131 } else {
132 OnServiceAvailable(true);
133 }
134}
135
136} // namespace apmanager