blob: 7a257b426b75f8c9e9988021f6ffaccc03ee4053 [file] [log] [blame]
Andreea Costinas41e06442020-03-09 09:41:51 +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#ifndef SYSTEM_PROXY_SERVER_PROXY_H_
5#define SYSTEM_PROXY_SERVER_PROXY_H_
6
Andreea Costinase45d54b2020-03-10 09:21:14 +01007#include <list>
8#include <map>
Andreea Costinas41e06442020-03-09 09:41:51 +01009#include <memory>
Andreea Costinas44cefa22020-03-09 09:07:39 +010010#include <string>
Andreea Costinase45d54b2020-03-10 09:21:14 +010011#include <vector>
Andreea Costinas41e06442020-03-09 09:41:51 +010012
13#include <base/callback_forward.h>
14#include <base/files/file_descriptor_watcher_posix.h>
Andreea Costinase45d54b2020-03-10 09:21:14 +010015#include <base/files/scoped_file.h>
16#include <base/memory/weak_ptr.h>
Andreea Costinas41e06442020-03-09 09:41:51 +010017#include <brillo/asynchronous_signal_handler.h>
Andreea Costinas44cefa22020-03-09 09:07:39 +010018#include <gtest/gtest_prod.h> // for FRIEND_TEST
Andreea Costinas41e06442020-03-09 09:41:51 +010019
Garrick Evans3388a032020-03-24 11:25:55 +090020namespace patchpanel {
Andreea Costinase45d54b2020-03-10 09:21:14 +010021class Socket;
22class SocketForwarder;
Garrick Evans3388a032020-03-24 11:25:55 +090023} // namespace patchpanel
Andreea Costinase45d54b2020-03-10 09:21:14 +010024
Andreea Costinas41e06442020-03-09 09:41:51 +010025namespace system_proxy {
26
Andreea Costinase45d54b2020-03-10 09:21:14 +010027using OnProxyResolvedCallback =
28 base::OnceCallback<void(const std::list<std::string>&)>;
29
30class ProxyConnectJob;
31
Andreea Costinas41e06442020-03-09 09:41:51 +010032// ServerProxy listens for connections from the host (system services, ARC++
33// apps) and sets-up connections to the remote server.
Andreea Costinas44cefa22020-03-09 09:07:39 +010034// Note: System-proxy only supports proxying over IPv4 networks.
Andreea Costinas41e06442020-03-09 09:41:51 +010035class ServerProxy {
36 public:
37 explicit ServerProxy(base::OnceClosure quit_closure);
38 ServerProxy(const ServerProxy&) = delete;
39 ServerProxy& operator=(const ServerProxy&) = delete;
Andreea Costinas44cefa22020-03-09 09:07:39 +010040 virtual ~ServerProxy();
Andreea Costinas41e06442020-03-09 09:41:51 +010041
42 void Init();
43
Andreea Costinase45d54b2020-03-10 09:21:14 +010044 // Creates a proxy resolution request that is forwarded to the parent process
45 // trough the standard output. When the request is resolved, the parent
46 // process will send the result trough the standard input.
47 // |callback| will be called when the proxy is resolved, with the list of
48 // proxy servers as parameter ,or in case of failure, with a list containing
49 // only the direct proxy.
50 void ResolveProxy(const std::string& target_url,
51 OnProxyResolvedCallback callback);
52
Andreea Costinas44cefa22020-03-09 09:07:39 +010053 protected:
54 virtual int GetStdinPipe();
Andreea Costinas5862b102020-03-19 14:45:36 +010055 virtual int GetStdoutPipe();
Andreea Costinasb715eef2020-05-26 09:14:32 +020056 virtual void HandleStdinReadable();
Andreea Costinas44cefa22020-03-09 09:07:39 +010057
Andreea Costinas41e06442020-03-09 09:41:51 +010058 private:
Andreea Costinas44cefa22020-03-09 09:07:39 +010059 friend class ServerProxyTest;
60 FRIEND_TEST(ServerProxyTest, FetchCredentials);
61 FRIEND_TEST(ServerProxyTest, FetchListeningAddress);
Andreea Costinase45d54b2020-03-10 09:21:14 +010062 FRIEND_TEST(ServerProxyTest, HandleConnectRequest);
63 FRIEND_TEST(ServerProxyTest, HandlePendingJobs);
Andreea Costinas5862b102020-03-19 14:45:36 +010064 FRIEND_TEST(ServerProxyTest, SetupConnection);
Andreea Costinas833eb7c2020-06-12 11:09:15 +020065 FRIEND_TEST(ServerProxyTest, HandleCanceledJobWhilePendingProxyResolution);
Andreea Costinas44cefa22020-03-09 09:07:39 +010066
Andreea Costinas41e06442020-03-09 09:41:51 +010067 bool HandleSignal(const struct signalfd_siginfo& siginfo);
68
Andreea Costinas44cefa22020-03-09 09:07:39 +010069 void CreateListeningSocket();
Andreea Costinase45d54b2020-03-10 09:21:14 +010070 void OnConnectionAccept();
71
72 // Called by |ProxyConnectJob| after setting up the connection with the remote
73 // server via the remote proxy server. If the connection is successful, |fwd|
74 // corresponds to the tunnel between the client and the server that has
75 // started to forward data. In case of failure, |fwd| is empty.
76 void OnConnectionSetupFinished(
Garrick Evans3388a032020-03-24 11:25:55 +090077 std::unique_ptr<patchpanel::SocketForwarder> fwd,
Andreea Costinase45d54b2020-03-10 09:21:14 +010078 ProxyConnectJob* connect_job);
Andreea Costinas44cefa22020-03-09 09:07:39 +010079
Andreea Costinas5862b102020-03-19 14:45:36 +010080 // Called when the proxy resolution result for |target_url| is received via
81 // the standard input (see |ResolveProxy| method). |proxy_servers| will always
82 // contain at least one entry, the direct proxy.
83 void OnProxyResolved(const std::string& target_url,
84 const std::list<std::string>& proxy_servers);
85
Andreea Costinas922fbaf2020-05-28 11:55:22 +020086 // Sets the environment variables for kerberos authentication.
87 void SetKerberosEnv(bool kerberos_enabled);
88
Andreea Costinas44cefa22020-03-09 09:07:39 +010089 // The proxy listening address in network-byte order.
90 uint32_t listening_addr_ = 0;
91 int listening_port_;
92
Andreea Costinase45d54b2020-03-10 09:21:14 +010093 // The user name and password to use for proxy authentication in the format
94 // compatible with libcurl's CURLOPT_USERPWD: both user name and password URL
95 // encoded and separated by colon.
Andreea Costinas922fbaf2020-05-28 11:55:22 +020096 std::string credentials_ = ":";
Andreea Costinas5862b102020-03-19 14:45:36 +010097
Garrick Evans3388a032020-03-24 11:25:55 +090098 std::unique_ptr<patchpanel::Socket> listening_fd_;
Andreea Costinas44cefa22020-03-09 09:07:39 +010099
Andreea Costinase45d54b2020-03-10 09:21:14 +0100100 // List of SocketForwarders that corresponds to the TCP tunnel between the
101 // local client and the remote proxy, forwarding data between the TCP
102 // connection initiated by the local client to the local proxy and the TCP
103 // connection initiated by the local proxy to the remote proxy.
Garrick Evans3388a032020-03-24 11:25:55 +0900104 std::list<std::unique_ptr<patchpanel::SocketForwarder>> forwarders_;
Andreea Costinase45d54b2020-03-10 09:21:14 +0100105
106 std::map<ProxyConnectJob*, std::unique_ptr<ProxyConnectJob>>
107 pending_connect_jobs_;
108
Andreea Costinas5862b102020-03-19 14:45:36 +0100109 // Collection of ongoing proxy resolution requests. The key represents the
110 // target url to be resolved and it's mapped to a list of callbaks to pending
111 // connect jobs that are connecting to the same target url.
112 std::map<std::string, std::list<OnProxyResolvedCallback>>
113 pending_proxy_resolution_requests_;
114
Andreea Costinas41e06442020-03-09 09:41:51 +0100115 base::OnceClosure quit_closure_;
116 std::unique_ptr<base::FileDescriptorWatcher::Controller> stdin_watcher_;
Andreea Costinas44cefa22020-03-09 09:07:39 +0100117 std::unique_ptr<base::FileDescriptorWatcher::Controller> fd_watcher_;
Andreea Costinas41e06442020-03-09 09:41:51 +0100118 brillo::AsynchronousSignalHandler signal_handler_;
Andreea Costinase45d54b2020-03-10 09:21:14 +0100119
120 base::WeakPtrFactory<ServerProxy> weak_ptr_factory_;
Andreea Costinas41e06442020-03-09 09:41:51 +0100121};
122} // namespace system_proxy
123
124#endif // SYSTEM_PROXY_SERVER_PROXY_H_