• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "sandboxed_api/sandbox2/network_proxy/server.h"
16 
17 #include <netinet/in.h>
18 #include <signal.h>
19 #include <sys/socket.h>
20 #include <sys/types.h>
21 
22 #include <atomic>
23 #include <cerrno>
24 #include <cstdint>
25 #include <memory>
26 #include <string>
27 #include <utility>
28 #include <vector>
29 
30 #include "absl/functional/any_invocable.h"
31 #include "absl/log/log.h"
32 #include "absl/status/status.h"
33 #include "absl/status/statusor.h"
34 #include "sandboxed_api/sandbox2/comms.h"
35 #include "sandboxed_api/sandbox2/network_proxy/filtering.h"
36 #include "sandboxed_api/util/fileops.h"
37 
38 namespace sandbox2 {
39 
40 namespace file_util = ::sapi::file_util;
41 
NetworkProxyServer(int fd,AllowedHosts * allowed_hosts,absl::AnyInvocable<void ()> notify_violation_fn)42 NetworkProxyServer::NetworkProxyServer(
43     int fd, AllowedHosts* allowed_hosts,
44     absl::AnyInvocable<void()> notify_violation_fn)
45     : violation_occurred_(false),
46       comms_(std::make_unique<Comms>(fd)),
47       fatal_error_(false),
48       notify_violation_fn_(std::move(notify_violation_fn)),
49       allowed_hosts_(allowed_hosts) {}
50 
ProcessConnectRequest()51 void NetworkProxyServer::ProcessConnectRequest() {
52   std::vector<uint8_t> addr;
53   if (!comms_->RecvBytes(&addr)) {
54     fatal_error_ = true;
55     return;
56   }
57 
58   const struct sockaddr* saddr = reinterpret_cast<const sockaddr*>(addr.data());
59 
60   // Only IPv4 TCP and IPv6 TCP are supported.
61   if (!((addr.size() == sizeof(sockaddr_in) && saddr->sa_family == AF_INET) ||
62         (addr.size() == sizeof(sockaddr_in6) &&
63          saddr->sa_family == AF_INET6))) {
64     SendError(EINVAL);
65     return;
66   }
67 
68   if (!allowed_hosts_->IsHostAllowed(saddr)) {
69     NotifyViolation(saddr);
70     return;
71   }
72 
73   int new_socket = socket(saddr->sa_family, SOCK_STREAM, 0);
74   if (new_socket < 0) {
75     SendError(errno);
76     return;
77   }
78 
79   file_util::fileops::FDCloser new_socket_closer(new_socket);
80 
81   int result = connect(
82       new_socket, reinterpret_cast<const sockaddr*>(addr.data()), addr.size());
83 
84   if (result < 0) {
85     SendError(errno);
86     return;
87   }
88 
89   NotifySuccess();
90   if (!fatal_error_ && !comms_->SendFD(new_socket)) {
91     fatal_error_ = true;
92     return;
93   }
94 }
95 
Run()96 void NetworkProxyServer::Run() {
97   while (!fatal_error_ &&
98          !violation_occurred_.load(std::memory_order_relaxed)) {
99     ProcessConnectRequest();
100   }
101   LOG(INFO)
102       << "Clean shutdown or error occurred, shutting down NetworkProxyServer";
103 }
104 
SendError(int saved_errno)105 void NetworkProxyServer::SendError(int saved_errno) {
106   if (!comms_->SendInt32(saved_errno)) {
107     fatal_error_ = true;
108   }
109 }
110 
NotifySuccess()111 void NetworkProxyServer::NotifySuccess() {
112   if (!comms_->SendInt32(0)) {
113     fatal_error_ = true;
114   }
115 }
116 
NotifyViolation(const struct sockaddr * saddr)117 void NetworkProxyServer::NotifyViolation(const struct sockaddr* saddr) {
118   if (absl::StatusOr<std::string> result = AddrToString(saddr); result.ok()) {
119     violation_msg_ = std::move(result).value();
120   } else {
121     violation_msg_ = std::string(result.status().message());
122   }
123   violation_occurred_.store(true, std::memory_order_release);
124   notify_violation_fn_();
125 }
126 
127 }  // namespace sandbox2
128