blob: 6464c0747ff29e6ad055502c387a9013a23b7896 [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 Costinas41e06442020-03-09 09:41:51 +010020constexpr int kProxyPort = 3128;
21
Andreea Costinas942284d2020-01-28 16:28:40 +010022// Serializes |proto| to a vector of bytes.
23std::vector<uint8_t> SerializeProto(
24 const google::protobuf::MessageLite& proto) {
25 std::vector<uint8_t> proto_blob(proto.ByteSizeLong());
26 DCHECK(proto.SerializeToArray(proto_blob.data(), proto_blob.size()));
27 return proto_blob;
28}
29
30// Parses a proto from an array of bytes |proto_blob|. Returns
31// ERROR_PARSE_REQUEST_FAILED on error.
32std::string DeserializeProto(const base::Location& from_here,
33 google::protobuf::MessageLite* proto,
34 const std::vector<uint8_t>& proto_blob) {
35 if (!proto->ParseFromArray(proto_blob.data(), proto_blob.size())) {
36 const std::string error_message = "Failed to parse proto message.";
37 LOG(ERROR) << from_here.ToString() << error_message;
38 return error_message;
39 }
40 return "";
41}
42} // namespace
43
44SystemProxyAdaptor::SystemProxyAdaptor(
45 std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object)
46 : org::chromium::SystemProxyAdaptor(this),
Andreea Costinasc7d5ad02020-03-09 09:41:51 +010047 dbus_object_(std::move(dbus_object)),
48 weak_ptr_factory_(this) {}
Andreea Costinas942284d2020-01-28 16:28:40 +010049
50SystemProxyAdaptor::~SystemProxyAdaptor() = default;
51
52void SystemProxyAdaptor::RegisterAsync(
53 const brillo::dbus_utils::AsyncEventSequencer::CompletionAction&
54 completion_callback) {
55 RegisterWithDBusObject(dbus_object_.get());
56 dbus_object_->RegisterAsync(completion_callback);
57}
58
59std::vector<uint8_t> SystemProxyAdaptor::SetSystemTrafficCredentials(
60 const std::vector<uint8_t>& request_blob) {
61 LOG(INFO) << "Received set credentials request.";
Andreea Costinasc7d5ad02020-03-09 09:41:51 +010062
Andreea Costinas942284d2020-01-28 16:28:40 +010063 SetSystemTrafficCredentialsRequest request;
64 const std::string error_message =
65 DeserializeProto(FROM_HERE, &request, request_blob);
Andreea Costinasc7d5ad02020-03-09 09:41:51 +010066
Andreea Costinas942284d2020-01-28 16:28:40 +010067 SetSystemTrafficCredentialsResponse response;
Andreea Costinasc7d5ad02020-03-09 09:41:51 +010068 if (!error_message.empty()) {
Andreea Costinas942284d2020-01-28 16:28:40 +010069 response.set_error_message(error_message);
Andreea Costinasc7d5ad02020-03-09 09:41:51 +010070 return SerializeProto(response);
71 }
72
73 if (!request.has_system_services_username() ||
74 !request.has_system_services_password()) {
75 response.set_error_message("No credentials specified");
76 return SerializeProto(response);
77 }
78
79 if (!system_services_worker_) {
80 system_services_worker_ = CreateWorker();
81 StartWorker(system_services_worker_.get());
82 }
83
84 brillo::MessageLoop::current()->PostTask(
85 FROM_HERE,
86 base::Bind(&SystemProxyAdaptor::SetCredentialsTask,
87 weak_ptr_factory_.GetWeakPtr(), system_services_worker_.get(),
88 request.system_services_username(),
89 request.system_services_password()));
90
Andreea Costinas942284d2020-01-28 16:28:40 +010091 return SerializeProto(response);
92}
93
94std::vector<uint8_t> SystemProxyAdaptor::ShutDown() {
95 LOG(INFO) << "Received shutdown request.";
Andreea Costinasc7d5ad02020-03-09 09:41:51 +010096
97 std::string error_message;
98 if (system_services_worker_ && system_services_worker_->IsRunning()) {
99 if (!system_services_worker_->Stop())
100 error_message =
101 "Failure to terminate worker process for system services traffic.";
102 }
103
104 if (arc_worker_ && arc_worker_->IsRunning()) {
105 if (!arc_worker_->Stop())
106 error_message += "Failure to terminate worker process for arc traffic.";
107 }
108
Andreea Costinas942284d2020-01-28 16:28:40 +0100109 ShutDownResponse response;
Andreea Costinasc7d5ad02020-03-09 09:41:51 +0100110 if (!error_message.empty())
111 response.set_error_message(error_message);
112
113 brillo::MessageLoop::current()->PostTask(
114 FROM_HERE, base::Bind(&SystemProxyAdaptor::ShutDownTask,
115 weak_ptr_factory_.GetWeakPtr()));
116
Andreea Costinas942284d2020-01-28 16:28:40 +0100117 return SerializeProto(response);
118}
119
Andreea Costinas5862b102020-03-19 14:45:36 +0100120void SystemProxyAdaptor::GetChromeProxyServersAsync(
121 const std::string& target_url,
122 const brillo::http::GetChromeProxyServersCallback& callback) {
123 brillo::http::GetChromeProxyServersAsync(
124 dbus_object_->GetBus(), target_url,
125 move(callback));
126}
127
Andreea Costinasc7d5ad02020-03-09 09:41:51 +0100128std::unique_ptr<SandboxedWorker> SystemProxyAdaptor::CreateWorker() {
Andreea Costinas5862b102020-03-19 14:45:36 +0100129 return std::make_unique<SandboxedWorker>(weak_ptr_factory_.GetWeakPtr());
Andreea Costinasc7d5ad02020-03-09 09:41:51 +0100130}
131
132void SystemProxyAdaptor::SetCredentialsTask(SandboxedWorker* worker,
133 const std::string& username,
134 const std::string& password) {
135 DCHECK(worker);
Andreea Costinas41e06442020-03-09 09:41:51 +0100136 worker->SetUsernameAndPassword(username, password);
Andreea Costinasc7d5ad02020-03-09 09:41:51 +0100137}
138
139void SystemProxyAdaptor::ShutDownTask() {
140 brillo::MessageLoop::current()->BreakLoop();
141}
142
143void SystemProxyAdaptor::StartWorker(SandboxedWorker* worker) {
144 DCHECK(worker);
145 worker->Start();
146 if (!worker->IsRunning()) {
147 LOG(ERROR) << "Failed to start worker process";
148 return;
149 }
150 ConnectNamespace(worker);
151}
152
153void SystemProxyAdaptor::ConnectNamespace(SandboxedWorker* worker) {
154 // TODO(acostinas,b/147712924) Call the datapath service to setup routing and
155 // create a veth pair for the network namespace.
156}
157
158void SystemProxyAdaptor::OnConnectNamespace(
159 SandboxedWorker* worker, const patchpanel::IPv4Subnet& ipv4_subnet) {
Andreea Costinas41e06442020-03-09 09:41:51 +0100160 worker->SetListeningAddress(ipv4_subnet.base_addr(), kProxyPort);
Andreea Costinasc7d5ad02020-03-09 09:41:51 +0100161}
162
Andreea Costinas942284d2020-01-28 16:28:40 +0100163} // namespace system_proxy