blob: 53b75caed7a6fc8438f3479619fb01e1f2078fb0 [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>&)>;
Andreea Costinased9e6122020-08-12 12:06:19 +020029using OnAuthAcquiredCallback =
30 base::RepeatingCallback<void(const std::string&)>;
Andreea Costinase45d54b2020-03-10 09:21:14 +010031
32class ProxyConnectJob;
33
Andreea Costinas41e06442020-03-09 09:41:51 +010034// ServerProxy listens for connections from the host (system services, ARC++
35// apps) and sets-up connections to the remote server.
Andreea Costinas44cefa22020-03-09 09:07:39 +010036// Note: System-proxy only supports proxying over IPv4 networks.
Andreea Costinas41e06442020-03-09 09:41:51 +010037class ServerProxy {
38 public:
39 explicit ServerProxy(base::OnceClosure quit_closure);
40 ServerProxy(const ServerProxy&) = delete;
41 ServerProxy& operator=(const ServerProxy&) = delete;
Andreea Costinas44cefa22020-03-09 09:07:39 +010042 virtual ~ServerProxy();
Andreea Costinas41e06442020-03-09 09:41:51 +010043
44 void Init();
45
Andreea Costinase45d54b2020-03-10 09:21:14 +010046 // Creates a proxy resolution request that is forwarded to the parent process
47 // trough the standard output. When the request is resolved, the parent
48 // process will send the result trough the standard input.
49 // |callback| will be called when the proxy is resolved, with the list of
50 // proxy servers as parameter ,or in case of failure, with a list containing
51 // only the direct proxy.
52 void ResolveProxy(const std::string& target_url,
53 OnProxyResolvedCallback callback);
Andreea Costinasbb2aa022020-06-13 00:03:23 +020054 // Creates an authentication required request that is forwarded to the parent
55 // process trough the standard output. When the request is resolved, the
56 // parent process will send the result trough the standard input. |callback|
57 // will be called when the credentials associated to the protection space
58 // given by the input parameters, or empty strings in case of failure or
Andreea Costinased9e6122020-08-12 12:06:19 +020059 // missing credentials. |bad_cached_credentials| are the incorrect credentials
60 // previously used for authentication; can be an empty string if no
61 // credentials were used in the initial request.
Andreea Costinasbb2aa022020-06-13 00:03:23 +020062 void AuthenticationRequired(const std::string& proxy_url,
63 const std::string& scheme,
64 const std::string& realm,
Andreea Costinased9e6122020-08-12 12:06:19 +020065 const std::string& bad_cached_credentials,
Andreea Costinasbb2aa022020-06-13 00:03:23 +020066 OnAuthAcquiredCallback callback);
Andreea Costinase45d54b2020-03-10 09:21:14 +010067
Andreea Costinas44cefa22020-03-09 09:07:39 +010068 protected:
69 virtual int GetStdinPipe();
Andreea Costinas5862b102020-03-19 14:45:36 +010070 virtual int GetStdoutPipe();
Andreea Costinasb715eef2020-05-26 09:14:32 +020071 virtual void HandleStdinReadable();
Andreea Costinas82a604e2021-04-09 13:19:19 +020072 virtual void OnConnectionAccept();
Andreea Costinas44cefa22020-03-09 09:07:39 +010073
Andreea Costinas41e06442020-03-09 09:41:51 +010074 private:
Andreea Costinas44cefa22020-03-09 09:07:39 +010075 friend class ServerProxyTest;
76 FRIEND_TEST(ServerProxyTest, FetchCredentials);
77 FRIEND_TEST(ServerProxyTest, FetchListeningAddress);
Andreea Costinase45d54b2020-03-10 09:21:14 +010078 FRIEND_TEST(ServerProxyTest, HandleConnectRequest);
79 FRIEND_TEST(ServerProxyTest, HandlePendingJobs);
Andreea Costinas5862b102020-03-19 14:45:36 +010080 FRIEND_TEST(ServerProxyTest, SetupConnection);
Andreea Costinas833eb7c2020-06-12 11:09:15 +020081 FRIEND_TEST(ServerProxyTest, HandleCanceledJobWhilePendingProxyResolution);
Andreea Costinasdb2cbee2020-06-15 11:43:44 +020082 FRIEND_TEST(ServerProxyTest, HandlePendingAuthRequests);
83 FRIEND_TEST(ServerProxyTest, HandlePendingAuthRequestsCachedCredentials);
84 FRIEND_TEST(ServerProxyTest, HandlePendingAuthRequestsNoCredentials);
Andreea Costinase9c73592020-07-17 15:27:54 +020085 FRIEND_TEST(ServerProxyTest, ClearUserCredentials);
Andreea Costinased9e6122020-08-12 12:06:19 +020086 FRIEND_TEST(ServerProxyTest, AuthRequestsBadCachedCredentials);
Andreea Costinas44cefa22020-03-09 09:07:39 +010087
Andreea Costinas41e06442020-03-09 09:41:51 +010088 bool HandleSignal(const struct signalfd_siginfo& siginfo);
89
Andreea Costinas44cefa22020-03-09 09:07:39 +010090 void CreateListeningSocket();
Andreea Costinase45d54b2020-03-10 09:21:14 +010091
92 // Called by |ProxyConnectJob| after setting up the connection with the remote
93 // server via the remote proxy server. If the connection is successful, |fwd|
94 // corresponds to the tunnel between the client and the server that has
95 // started to forward data. In case of failure, |fwd| is empty.
96 void OnConnectionSetupFinished(
Garrick Evans3388a032020-03-24 11:25:55 +090097 std::unique_ptr<patchpanel::SocketForwarder> fwd,
Andreea Costinase45d54b2020-03-10 09:21:14 +010098 ProxyConnectJob* connect_job);
Andreea Costinas44cefa22020-03-09 09:07:39 +010099
Andreea Costinas5862b102020-03-19 14:45:36 +0100100 // Called when the proxy resolution result for |target_url| is received via
101 // the standard input (see |ResolveProxy| method). |proxy_servers| will always
102 // contain at least one entry, the direct proxy.
103 void OnProxyResolved(const std::string& target_url,
104 const std::list<std::string>& proxy_servers);
105
Andreea Costinasbb2aa022020-06-13 00:03:23 +0200106 void OnCredentialsReceived();
107
Andreea Costinas922fbaf2020-05-28 11:55:22 +0200108 // Sets the environment variables for kerberos authentication.
109 void SetKerberosEnv(bool kerberos_enabled);
110
Andreea Costinasdb2cbee2020-06-15 11:43:44 +0200111 // Notifies proxy connect jobs which are pending authentication that
112 // credentials were provided for the protection space identified by
113 // |auth_credentials_key|. Called when the parent process sends credentials
114 // along with the associated protection space via the standard input.
115 void AuthCredentialsProvided(const std::string& auth_credentials_key,
116 const std::string& credentials);
117
Andreea Costinas44cefa22020-03-09 09:07:39 +0100118 // The proxy listening address in network-byte order.
119 uint32_t listening_addr_ = 0;
120 int listening_port_;
121
Andreea Costinase45d54b2020-03-10 09:21:14 +0100122 // The user name and password to use for proxy authentication in the format
123 // compatible with libcurl's CURLOPT_USERPWD: both user name and password URL
Andreea Costinasdb2cbee2020-06-15 11:43:44 +0200124 // encoded and separated by colon. Only set for system traffic. If set, the
125 // credentials will be applied to any connection, regardless of the remote
126 // proxy it's connecting to or the challenge response.
Andreea Costinasbb2aa022020-06-13 00:03:23 +0200127 std::string system_credentials_;
Andreea Costinas5862b102020-03-19 14:45:36 +0100128
Andreea Costinascc4d54e2020-10-19 15:46:25 +0200129 // Curl compatible bit-mask list of proxy authenticated schemes that can be
130 // used with the policy set credentials.
131 int64_t system_credentials_auth_schemes_ = 0;
132
Garrick Evans3388a032020-03-24 11:25:55 +0900133 std::unique_ptr<patchpanel::Socket> listening_fd_;
Andreea Costinas44cefa22020-03-09 09:07:39 +0100134
Andreea Costinase45d54b2020-03-10 09:21:14 +0100135 // List of SocketForwarders that corresponds to the TCP tunnel between the
Andreea Costinasdb2cbee2020-06-15 11:43:44 +0200136 // local client and the remote proxy, forwarding data between the TCP
Andreea Costinase45d54b2020-03-10 09:21:14 +0100137 // connection initiated by the local client to the local proxy and the TCP
138 // connection initiated by the local proxy to the remote proxy.
Garrick Evans3388a032020-03-24 11:25:55 +0900139 std::list<std::unique_ptr<patchpanel::SocketForwarder>> forwarders_;
Andreea Costinase45d54b2020-03-10 09:21:14 +0100140
141 std::map<ProxyConnectJob*, std::unique_ptr<ProxyConnectJob>>
142 pending_connect_jobs_;
143
Andreea Costinas5862b102020-03-19 14:45:36 +0100144 // Collection of ongoing proxy resolution requests. The key represents the
145 // target url to be resolved and it's mapped to a list of callbaks to pending
146 // connect jobs that are connecting to the same target url.
147 std::map<std::string, std::list<OnProxyResolvedCallback>>
148 pending_proxy_resolution_requests_;
149
Andreea Costinasdb2cbee2020-06-15 11:43:44 +0200150 // Collection of ongoing authentication requests. The key represents the
151 // ProtectionSpace proto message (proxy url, scheme and realm) associated with
152 // the request, serialized as a string. The value is a list of callbaks to
153 // pending connect jobs that are awaiting authentication and have received a
154 // challenge with the same scheme and realm from the same proxy server.
155 std::map<std::string, std::list<OnAuthAcquiredCallback>>
156 pending_auth_required_requests_;
157
158 // Stores HTTP authentication identities acquired from the user and challenge
159 // info. The credentials are mapped by the protection space (origin, realm,
160 // scheme) and can only be used in response to challenges corresponding to
161 // this specific triple, as opposed to |system_credentials_| which, if set,
162 // can be used for any protection space.
163 std::map<std::string, std::string> auth_cache_;
164
Andreea Costinas41e06442020-03-09 09:41:51 +0100165 base::OnceClosure quit_closure_;
166 std::unique_ptr<base::FileDescriptorWatcher::Controller> stdin_watcher_;
Andreea Costinas44cefa22020-03-09 09:07:39 +0100167 std::unique_ptr<base::FileDescriptorWatcher::Controller> fd_watcher_;
Andreea Costinas41e06442020-03-09 09:41:51 +0100168 brillo::AsynchronousSignalHandler signal_handler_;
Andreea Costinase45d54b2020-03-10 09:21:14 +0100169
170 base::WeakPtrFactory<ServerProxy> weak_ptr_factory_;
Andreea Costinas41e06442020-03-09 09:41:51 +0100171};
172} // namespace system_proxy
173
174#endif // SYSTEM_PROXY_SERVER_PROXY_H_