blob: ac7e47abe0080d23ca13e29f198a623c80b41868 [file] [log] [blame]
Andreea Costinas942284d2020-01-28 16:28:40 +01001// Copyright 2020 The Chromium OS 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#include "system-proxy/system_proxy_adaptor.h"
5
6#include <string>
7#include <utility>
8#include <vector>
9
10#include <base/location.h>
11#include <brillo/dbus/dbus_object.h>
Andreea Costinasc7d5ad02020-03-09 09:41:51 +010012#include <brillo/message_loops/message_loop.h>
Andreea Costinas942284d2020-01-28 16:28:40 +010013
14#include "system_proxy/proto_bindings/system_proxy_service.pb.h"
Andreea Costinasc7d5ad02020-03-09 09:41:51 +010015#include "system-proxy/sandboxed_worker.h"
Andreea Costinas942284d2020-01-28 16:28:40 +010016
17namespace system_proxy {
18namespace {
Andreea Costinasc7d5ad02020-03-09 09:41:51 +010019
Andreea Costinas942284d2020-01-28 16:28:40 +010020// Serializes |proto| to a vector of bytes.
21std::vector<uint8_t> SerializeProto(
22 const google::protobuf::MessageLite& proto) {
23 std::vector<uint8_t> proto_blob(proto.ByteSizeLong());
24 DCHECK(proto.SerializeToArray(proto_blob.data(), proto_blob.size()));
25 return proto_blob;
26}
27
28// Parses a proto from an array of bytes |proto_blob|. Returns
29// ERROR_PARSE_REQUEST_FAILED on error.
30std::string DeserializeProto(const base::Location& from_here,
31 google::protobuf::MessageLite* proto,
32 const std::vector<uint8_t>& proto_blob) {
33 if (!proto->ParseFromArray(proto_blob.data(), proto_blob.size())) {
34 const std::string error_message = "Failed to parse proto message.";
35 LOG(ERROR) << from_here.ToString() << error_message;
36 return error_message;
37 }
38 return "";
39}
40} // namespace
41
42SystemProxyAdaptor::SystemProxyAdaptor(
43 std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object)
44 : org::chromium::SystemProxyAdaptor(this),
Andreea Costinasc7d5ad02020-03-09 09:41:51 +010045 dbus_object_(std::move(dbus_object)),
46 weak_ptr_factory_(this) {}
Andreea Costinas942284d2020-01-28 16:28:40 +010047
48SystemProxyAdaptor::~SystemProxyAdaptor() = default;
49
50void SystemProxyAdaptor::RegisterAsync(
51 const brillo::dbus_utils::AsyncEventSequencer::CompletionAction&
52 completion_callback) {
53 RegisterWithDBusObject(dbus_object_.get());
54 dbus_object_->RegisterAsync(completion_callback);
55}
56
57std::vector<uint8_t> SystemProxyAdaptor::SetSystemTrafficCredentials(
58 const std::vector<uint8_t>& request_blob) {
59 LOG(INFO) << "Received set credentials request.";
Andreea Costinasc7d5ad02020-03-09 09:41:51 +010060
Andreea Costinas942284d2020-01-28 16:28:40 +010061 SetSystemTrafficCredentialsRequest request;
62 const std::string error_message =
63 DeserializeProto(FROM_HERE, &request, request_blob);
Andreea Costinasc7d5ad02020-03-09 09:41:51 +010064
Andreea Costinas942284d2020-01-28 16:28:40 +010065 SetSystemTrafficCredentialsResponse response;
Andreea Costinasc7d5ad02020-03-09 09:41:51 +010066 if (!error_message.empty()) {
Andreea Costinas942284d2020-01-28 16:28:40 +010067 response.set_error_message(error_message);
Andreea Costinasc7d5ad02020-03-09 09:41:51 +010068 return SerializeProto(response);
69 }
70
71 if (!request.has_system_services_username() ||
72 !request.has_system_services_password()) {
73 response.set_error_message("No credentials specified");
74 return SerializeProto(response);
75 }
76
77 if (!system_services_worker_) {
78 system_services_worker_ = CreateWorker();
Andreea Costinasc9defae2020-04-22 10:28:35 +020079 if (!StartWorker(system_services_worker_.get())) {
80 system_services_worker_->Stop();
81 system_services_worker_.reset();
82 response.set_error_message("Failed to start worker process");
83 return SerializeProto(response);
84 }
Andreea Costinasc7d5ad02020-03-09 09:41:51 +010085 }
86
87 brillo::MessageLoop::current()->PostTask(
88 FROM_HERE,
89 base::Bind(&SystemProxyAdaptor::SetCredentialsTask,
90 weak_ptr_factory_.GetWeakPtr(), system_services_worker_.get(),
91 request.system_services_username(),
92 request.system_services_password()));
93
Andreea Costinas942284d2020-01-28 16:28:40 +010094 return SerializeProto(response);
95}
96
97std::vector<uint8_t> SystemProxyAdaptor::ShutDown() {
98 LOG(INFO) << "Received shutdown request.";
Andreea Costinasc7d5ad02020-03-09 09:41:51 +010099
100 std::string error_message;
101 if (system_services_worker_ && system_services_worker_->IsRunning()) {
102 if (!system_services_worker_->Stop())
103 error_message =
104 "Failure to terminate worker process for system services traffic.";
105 }
106
107 if (arc_worker_ && arc_worker_->IsRunning()) {
108 if (!arc_worker_->Stop())
109 error_message += "Failure to terminate worker process for arc traffic.";
110 }
111
Andreea Costinas942284d2020-01-28 16:28:40 +0100112 ShutDownResponse response;
Andreea Costinasc7d5ad02020-03-09 09:41:51 +0100113 if (!error_message.empty())
114 response.set_error_message(error_message);
115
116 brillo::MessageLoop::current()->PostTask(
117 FROM_HERE, base::Bind(&SystemProxyAdaptor::ShutDownTask,
118 weak_ptr_factory_.GetWeakPtr()));
119
Andreea Costinas942284d2020-01-28 16:28:40 +0100120 return SerializeProto(response);
121}
122
Andreea Costinas5862b102020-03-19 14:45:36 +0100123void SystemProxyAdaptor::GetChromeProxyServersAsync(
124 const std::string& target_url,
125 const brillo::http::GetChromeProxyServersCallback& callback) {
Andreea Costinasc9defae2020-04-22 10:28:35 +0200126 brillo::http::GetChromeProxyServersAsync(dbus_object_->GetBus(), target_url,
127 move(callback));
Andreea Costinas5862b102020-03-19 14:45:36 +0100128}
129
Andreea Costinasc7d5ad02020-03-09 09:41:51 +0100130std::unique_ptr<SandboxedWorker> SystemProxyAdaptor::CreateWorker() {
Andreea Costinas5862b102020-03-19 14:45:36 +0100131 return std::make_unique<SandboxedWorker>(weak_ptr_factory_.GetWeakPtr());
Andreea Costinasc7d5ad02020-03-09 09:41:51 +0100132}
133
134void SystemProxyAdaptor::SetCredentialsTask(SandboxedWorker* worker,
135 const std::string& username,
136 const std::string& password) {
137 DCHECK(worker);
Andreea Costinas41e06442020-03-09 09:41:51 +0100138 worker->SetUsernameAndPassword(username, password);
Andreea Costinasc7d5ad02020-03-09 09:41:51 +0100139}
140
141void SystemProxyAdaptor::ShutDownTask() {
142 brillo::MessageLoop::current()->BreakLoop();
143}
144
Andreea Costinasc9defae2020-04-22 10:28:35 +0200145bool SystemProxyAdaptor::StartWorker(SandboxedWorker* worker) {
Andreea Costinasc7d5ad02020-03-09 09:41:51 +0100146 DCHECK(worker);
Andreea Costinasc9defae2020-04-22 10:28:35 +0200147 return worker->Start() && ConnectNamespace(worker);
Andreea Costinasc7d5ad02020-03-09 09:41:51 +0100148}
149
Andreea Costinasc9defae2020-04-22 10:28:35 +0200150bool SystemProxyAdaptor::ConnectNamespace(SandboxedWorker* worker) {
Andreea Costinasc7d5ad02020-03-09 09:41:51 +0100151 // TODO(acostinas,b/147712924) Call the datapath service to setup routing and
152 // create a veth pair for the network namespace.
Andreea Costinasc9defae2020-04-22 10:28:35 +0200153 return true;
Andreea Costinasc7d5ad02020-03-09 09:41:51 +0100154}
155
Andreea Costinas942284d2020-01-28 16:28:40 +0100156} // namespace system_proxy