1 // Copyright 2019 The Chromium 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 5 #ifndef QUICHE_QUIC_MASQUE_MASQUE_CLIENT_SESSION_H_ 6 #define QUICHE_QUIC_MASQUE_MASQUE_CLIENT_SESSION_H_ 7 8 #include <list> 9 #include <optional> 10 #include <string> 11 12 #include "absl/container/flat_hash_map.h" 13 #include "absl/strings/string_view.h" 14 #include "quiche/quic/core/crypto/quic_crypto_client_config.h" 15 #include "quiche/quic/core/frames/quic_connection_close_frame.h" 16 #include "quiche/quic/core/http/http_frames.h" 17 #include "quiche/quic/core/http/quic_spdy_client_session.h" 18 #include "quiche/quic/core/http/quic_spdy_client_stream.h" 19 #include "quiche/quic/core/http/quic_spdy_session.h" 20 #include "quiche/quic/core/http/quic_spdy_stream.h" 21 #include "quiche/quic/core/quic_config.h" 22 #include "quiche/quic/core/quic_error_codes.h" 23 #include "quiche/quic/core/quic_time.h" 24 #include "quiche/quic/core/quic_types.h" 25 #include "quiche/quic/core/quic_versions.h" 26 #include "quiche/quic/masque/masque_utils.h" 27 #include "quiche/quic/platform/api/quic_export.h" 28 #include "quiche/quic/platform/api/quic_socket_address.h" 29 #include "quiche/quic/tools/quic_url.h" 30 #include "quiche/common/capsule.h" 31 #include "quiche/common/quiche_ip_address.h" 32 #include "quiche/spdy/core/http2_header_block.h" 33 34 namespace quic { 35 36 // QUIC client session for connection to MASQUE proxy. This session establishes 37 // a connection to a MASQUE proxy and handles sending and receiving DATAGRAM 38 // frames for operation of the MASQUE protocol. Multiple end-to-end encapsulated 39 // sessions can then coexist inside this session. Once these are created, they 40 // need to be registered with this session. 41 class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession, 42 public QuicSpdyStream::Visitor { 43 public: 44 // Interface meant to be implemented by the owner of the 45 // MasqueClientSession instance. 46 class QUIC_NO_EXPORT Owner { 47 public: ~Owner()48 virtual ~Owner() {} 49 50 // Notifies the owner that a settings frame has been received. 51 virtual void OnSettingsReceived() = 0; 52 }; 53 54 // Interface meant to be implemented by client sessions encapsulated inside 55 // CONNECT-UDP, i.e. the end-to-end QUIC client sessions that run inside 56 // CONNECT-UDP encapsulation. 57 class QUIC_NO_EXPORT EncapsulatedClientSession { 58 public: ~EncapsulatedClientSession()59 virtual ~EncapsulatedClientSession() {} 60 61 // Process UDP packet that was just decapsulated. |packet| contains the UDP 62 // payload. 63 virtual void ProcessPacket(absl::string_view packet, 64 QuicSocketAddress target_server_address) = 0; 65 66 // Close the encapsulated connection. 67 virtual void CloseConnection( 68 QuicErrorCode error, const std::string& details, 69 ConnectionCloseBehavior connection_close_behavior) = 0; 70 }; 71 72 // Interface meant to be implemented by client sessions encapsulated inside 73 // CONNECT-IP, i.e. the end-to-end QUIC client sessions that run inside 74 // CONNECT-IP encapsulation. 75 class QUIC_NO_EXPORT EncapsulatedIpSession { 76 public: ~EncapsulatedIpSession()77 virtual ~EncapsulatedIpSession() {} 78 79 // Process packet that was just decapsulated. |packet| contains the IP 80 // header and payload. 81 virtual void ProcessIpPacket(absl::string_view packet) = 0; 82 83 // Close the encapsulated connection. 84 virtual void CloseIpSession(const std::string& details) = 0; 85 86 virtual bool OnAddressAssignCapsule( 87 const quiche::AddressAssignCapsule& capsule) = 0; 88 virtual bool OnAddressRequestCapsule( 89 const quiche::AddressRequestCapsule& capsule) = 0; 90 virtual bool OnRouteAdvertisementCapsule( 91 const quiche::RouteAdvertisementCapsule& capsule) = 0; 92 }; 93 94 // CONNECT-ETHERNET. 95 class QUIC_NO_EXPORT EncapsulatedEthernetSession { 96 public: ~EncapsulatedEthernetSession()97 virtual ~EncapsulatedEthernetSession() {} 98 99 // Process packet that was just decapsulated. |frame| contains the 100 // Ethernet header and payload. 101 virtual void ProcessEthernetFrame(absl::string_view frame) = 0; 102 103 // Close the encapsulated connection. 104 virtual void CloseEthernetSession(const std::string& details) = 0; 105 }; 106 107 // Takes ownership of |connection|, but not of |crypto_config| or |owner|. 108 // All pointers must be non-null. Caller must ensure that |owner| stays valid 109 // for the lifetime of the newly created MasqueClientSession. 110 MasqueClientSession(MasqueMode masque_mode, const std::string& uri_template, 111 const QuicConfig& config, 112 const ParsedQuicVersionVector& supported_versions, 113 QuicConnection* connection, const QuicServerId& server_id, 114 QuicCryptoClientConfig* crypto_config, Owner* owner); 115 116 // Disallow copy and assign. 117 MasqueClientSession(const MasqueClientSession&) = delete; 118 MasqueClientSession& operator=(const MasqueClientSession&) = delete; 119 120 // From QuicSession. 121 void OnMessageAcked(QuicMessageId message_id, 122 QuicTime receive_timestamp) override; 123 void OnMessageLost(QuicMessageId message_id) override; 124 void OnConnectionClosed(const QuicConnectionCloseFrame& frame, 125 ConnectionCloseSource source) override; 126 void OnStreamClosed(QuicStreamId stream_id) override; 127 128 // From QuicSpdySession. 129 bool OnSettingsFrame(const SettingsFrame& frame) override; 130 131 // Send encapsulated UDP packet. |packet| contains the UDP payload. 132 void SendPacket(absl::string_view packet, 133 const QuicSocketAddress& target_server_address, 134 EncapsulatedClientSession* encapsulated_client_session); 135 136 // Send encapsulated IP packet. |packet| contains the IP header and payload. 137 void SendIpPacket(absl::string_view packet, 138 EncapsulatedIpSession* encapsulated_ip_session); 139 140 // Send encapsulated Ethernet frame. |frame| contains the Ethernet 141 // header and payload. 142 void SendEthernetFrame( 143 absl::string_view frame, 144 EncapsulatedEthernetSession* encapsulated_ethernet_session); 145 146 // Close CONNECT-UDP stream tied to this encapsulated client session. 147 void CloseConnectUdpStream( 148 EncapsulatedClientSession* encapsulated_client_session); 149 150 // Close CONNECT-IP stream tied to this encapsulated client session. 151 void CloseConnectIpStream(EncapsulatedIpSession* encapsulated_ip_session); 152 153 // Close CONNECT-ETHERNET stream tied to this encapsulated client session. 154 void CloseConnectEthernetStream( 155 EncapsulatedEthernetSession* encapsulated_ethernet_session); 156 157 // Generate a random Unique Local Address and register a mapping from 158 // that address to the corresponding hostname. The returned address should be 159 // removed by calling RemoveFakeAddress() once it is no longer needed. 160 quiche::QuicheIpAddress GetFakeAddress(absl::string_view hostname); 161 162 // Removes a fake address that was previously created by GetFakeAddress(). 163 void RemoveFakeAddress(const quiche::QuicheIpAddress& fake_address); 164 165 // Set additional HTTP headers that will be sent on all requests to the MASQUE 166 // proxy. Separated with colons and semicolons. 167 // For example: "name1:value1;name2:value2". set_additional_headers(absl::string_view additional_headers)168 void set_additional_headers(absl::string_view additional_headers) { 169 additional_headers_ = additional_headers; 170 } 171 172 // Send a GET request to the MASQUE proxy itself. 173 QuicSpdyClientStream* SendGetRequest(absl::string_view path); 174 175 // QuicSpdyStream::Visitor 176 void OnClose(QuicSpdyStream* stream) override; 177 178 // Set the signature auth key ID and private key. key_id MUST be non-empty, 179 // private_key MUST be ED25519_PRIVATE_KEY_LEN bytes long and public_key MUST 180 // be ED25519_PUBLIC_KEY_LEN bytes long. 181 void EnableSignatureAuth(absl::string_view key_id, 182 absl::string_view private_key, 183 absl::string_view public_key); 184 185 private: 186 // State that the MasqueClientSession keeps for each CONNECT-UDP request. 187 class QUIC_NO_EXPORT ConnectUdpClientState 188 : public QuicSpdyStream::Http3DatagramVisitor { 189 public: 190 // |stream| and |encapsulated_client_session| must be valid for the lifetime 191 // of the ConnectUdpClientState. 192 explicit ConnectUdpClientState( 193 QuicSpdyClientStream* stream, 194 EncapsulatedClientSession* encapsulated_client_session, 195 MasqueClientSession* masque_session, 196 const QuicSocketAddress& target_server_address); 197 198 ~ConnectUdpClientState(); 199 200 // Disallow copy but allow move. 201 ConnectUdpClientState(const ConnectUdpClientState&) = delete; 202 ConnectUdpClientState(ConnectUdpClientState&&); 203 ConnectUdpClientState& operator=(const ConnectUdpClientState&) = delete; 204 ConnectUdpClientState& operator=(ConnectUdpClientState&&); 205 stream()206 QuicSpdyClientStream* stream() const { return stream_; } encapsulated_client_session()207 EncapsulatedClientSession* encapsulated_client_session() const { 208 return encapsulated_client_session_; 209 } target_server_address()210 const QuicSocketAddress& target_server_address() const { 211 return target_server_address_; 212 } 213 214 // From QuicSpdyStream::Http3DatagramVisitor. 215 void OnHttp3Datagram(QuicStreamId stream_id, 216 absl::string_view payload) override; OnUnknownCapsule(QuicStreamId,const quiche::UnknownCapsule &)217 void OnUnknownCapsule(QuicStreamId /*stream_id*/, 218 const quiche::UnknownCapsule& /*capsule*/) override {} 219 220 private: 221 QuicSpdyClientStream* stream_; // Unowned. 222 EncapsulatedClientSession* encapsulated_client_session_; // Unowned. 223 MasqueClientSession* masque_session_; // Unowned. 224 QuicSocketAddress target_server_address_; 225 }; 226 227 // State that the MasqueClientSession keeps for each CONNECT-IP request. 228 class QUIC_NO_EXPORT ConnectIpClientState 229 : public QuicSpdyStream::Http3DatagramVisitor, 230 public QuicSpdyStream::ConnectIpVisitor { 231 public: 232 // |stream| and |encapsulated_client_session| must be valid for the lifetime 233 // of the ConnectUdpClientState. 234 explicit ConnectIpClientState( 235 QuicSpdyClientStream* stream, 236 EncapsulatedIpSession* encapsulated_ip_session, 237 MasqueClientSession* masque_session); 238 239 ~ConnectIpClientState(); 240 241 // Disallow copy but allow move. 242 ConnectIpClientState(const ConnectIpClientState&) = delete; 243 ConnectIpClientState(ConnectIpClientState&&); 244 ConnectIpClientState& operator=(const ConnectIpClientState&) = delete; 245 ConnectIpClientState& operator=(ConnectIpClientState&&); 246 stream()247 QuicSpdyClientStream* stream() const { return stream_; } encapsulated_ip_session()248 EncapsulatedIpSession* encapsulated_ip_session() const { 249 return encapsulated_ip_session_; 250 } 251 252 // From QuicSpdyStream::Http3DatagramVisitor. 253 void OnHttp3Datagram(QuicStreamId stream_id, 254 absl::string_view payload) override; OnUnknownCapsule(QuicStreamId,const quiche::UnknownCapsule &)255 void OnUnknownCapsule(QuicStreamId /*stream_id*/, 256 const quiche::UnknownCapsule& /*capsule*/) override {} 257 258 // From QuicSpdyStream::ConnectIpVisitor. 259 bool OnAddressAssignCapsule( 260 const quiche::AddressAssignCapsule& capsule) override; 261 bool OnAddressRequestCapsule( 262 const quiche::AddressRequestCapsule& capsule) override; 263 bool OnRouteAdvertisementCapsule( 264 const quiche::RouteAdvertisementCapsule& capsule) override; 265 void OnHeadersWritten() override; 266 267 private: 268 QuicSpdyClientStream* stream_; // Unowned. 269 EncapsulatedIpSession* encapsulated_ip_session_; // Unowned. 270 MasqueClientSession* masque_session_; // Unowned. 271 }; 272 273 // State that the MasqueClientSession keeps for each CONNECT-ETHERNET request. 274 class QUIC_NO_EXPORT ConnectEthernetClientState 275 : public QuicSpdyStream::Http3DatagramVisitor { 276 public: 277 // |stream| and |encapsulated_client_session| must be valid for the lifetime 278 // of the ConnectUdpClientState. 279 explicit ConnectEthernetClientState( 280 QuicSpdyClientStream* stream, 281 EncapsulatedEthernetSession* encapsulated_ethernet_session, 282 MasqueClientSession* masque_session); 283 284 ~ConnectEthernetClientState(); 285 286 // Disallow copy but allow move. 287 ConnectEthernetClientState(const ConnectEthernetClientState&) = delete; 288 ConnectEthernetClientState(ConnectEthernetClientState&&); 289 ConnectEthernetClientState& operator=(const ConnectEthernetClientState&) = 290 delete; 291 ConnectEthernetClientState& operator=(ConnectEthernetClientState&&); 292 stream()293 QuicSpdyClientStream* stream() const { return stream_; } encapsulated_ethernet_session()294 EncapsulatedEthernetSession* encapsulated_ethernet_session() const { 295 return encapsulated_ethernet_session_; 296 } 297 298 // From QuicSpdyStream::Http3DatagramVisitor. 299 void OnHttp3Datagram(QuicStreamId stream_id, 300 absl::string_view payload) override; OnUnknownCapsule(QuicStreamId,const quiche::UnknownCapsule &)301 void OnUnknownCapsule(QuicStreamId /*stream_id*/, 302 const quiche::UnknownCapsule& /*capsule*/) override {} 303 304 private: 305 QuicSpdyClientStream* stream_; // Unowned. 306 EncapsulatedEthernetSession* encapsulated_ethernet_session_; // Unowned. 307 MasqueClientSession* masque_session_; // Unowned. 308 }; 309 LocalHttpDatagramSupport()310 HttpDatagramSupport LocalHttpDatagramSupport() override { 311 return HttpDatagramSupport::kRfc; 312 } 313 314 const ConnectUdpClientState* GetOrCreateConnectUdpClientState( 315 const QuicSocketAddress& target_server_address, 316 EncapsulatedClientSession* encapsulated_client_session); 317 318 const ConnectIpClientState* GetOrCreateConnectIpClientState( 319 EncapsulatedIpSession* encapsulated_ip_session); 320 321 const ConnectEthernetClientState* GetOrCreateConnectEthernetClientState( 322 EncapsulatedEthernetSession* encapsulated_ethernet_session); 323 324 std::optional<std::string> ComputeSignatureAuthHeader(const QuicUrl& url); 325 void AddAdditionalHeaders(spdy::Http2HeaderBlock& headers, 326 const QuicUrl& url); 327 328 MasqueMode masque_mode_; 329 std::string uri_template_; 330 std::string additional_headers_; 331 std::string signature_auth_key_id_; 332 std::string signature_auth_private_key_; 333 std::string signature_auth_public_key_; 334 std::list<ConnectUdpClientState> connect_udp_client_states_; 335 std::list<ConnectIpClientState> connect_ip_client_states_; 336 std::list<ConnectEthernetClientState> connect_ethernet_client_states_; 337 // Maps fake addresses generated by GetFakeAddress() to their corresponding 338 // hostnames. 339 absl::flat_hash_map<std::string, std::string> fake_addresses_; 340 Owner* owner_; // Unowned; 341 }; 342 343 } // namespace quic 344 345 #endif // QUICHE_QUIC_MASQUE_MASQUE_CLIENT_SESSION_H_ 346