1// 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 17#include "apmanager/dbus/permission_broker_dbus_proxy.h" 18 19#include <base/bind.h> 20#include <brillo/errors/error.h> 21 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; 74 brillo::ErrorPtr error; 75 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 97 brillo::ErrorPtr error; 98 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 137