blob: 9b75bcd54a3489dd7a1fb4147a02b8dd1ed8cc66 [file] [log] [blame]
Bence Békybac04052022-04-07 15:44:29 -04001// 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#include "quiche/quic/masque/masque_server_backend.h"
bncced09502022-04-13 08:33:10 -07006
asedeno99be9062024-01-10 11:54:52 -08007#include <cstdint>
8#include <cstring>
9#include <memory>
10#include <string>
11#include <utility>
12#include <vector>
13
14#include "absl/strings/escaping.h"
dschinazia8489d22024-01-10 07:00:12 -080015#include "absl/strings/str_split.h"
Bence Békybac04052022-04-07 15:44:29 -040016#include "absl/strings/string_view.h"
dschinazia8489d22024-01-10 07:00:12 -080017#include "openssl/curve25519.h"
asedeno99be9062024-01-10 11:54:52 -080018#include "quiche/quic/core/quic_connection_id.h"
19#include "quiche/quic/masque/masque_utils.h"
20#include "quiche/quic/platform/api/quic_bug_tracker.h"
21#include "quiche/quic/platform/api/quic_ip_address.h"
22#include "quiche/quic/platform/api/quic_logging.h"
23#include "quiche/quic/tools/quic_backend_response.h"
24#include "quiche/quic/tools/quic_memory_cache_backend.h"
25#include "quiche/quic/tools/quic_simple_server_backend.h"
26#include "quiche/common/quiche_text_utils.h"
27#include "quiche/spdy/core/http2_header_block.h"
Bence Békybac04052022-04-07 15:44:29 -040028
29namespace quic {
30
31MasqueServerBackend::MasqueServerBackend(MasqueMode masque_mode,
32 const std::string& server_authority,
33 const std::string& cache_directory)
34 : masque_mode_(masque_mode), server_authority_(server_authority) {
dschinazi425f03b2022-11-02 07:29:15 -070035 // Start with client IP 10.1.1.2.
36 connect_ip_next_client_ip_[0] = 10;
37 connect_ip_next_client_ip_[1] = 1;
38 connect_ip_next_client_ip_[2] = 1;
39 connect_ip_next_client_ip_[3] = 2;
40
Bence Békybac04052022-04-07 15:44:29 -040041 if (!cache_directory.empty()) {
42 QuicMemoryCacheBackend::InitializeBackend(cache_directory);
43 }
44}
45
46bool MasqueServerBackend::MaybeHandleMasqueRequest(
47 const spdy::Http2HeaderBlock& request_headers,
Bence Békybac04052022-04-07 15:44:29 -040048 QuicSimpleServerBackend::RequestHandler* request_handler) {
49 auto method_pair = request_headers.find(":method");
50 if (method_pair == request_headers.end()) {
51 // Request is missing a method.
52 return false;
53 }
54 absl::string_view method = method_pair->second;
55 std::string masque_path = "";
dschinazia85581e2022-04-17 08:09:44 -070056 auto protocol_pair = request_headers.find(":protocol");
57 if (method != "CONNECT" || protocol_pair == request_headers.end() ||
dschinazi425f03b2022-11-02 07:29:15 -070058 (protocol_pair->second != "connect-udp" &&
asedeno92bbf022023-07-23 11:23:45 -070059 protocol_pair->second != "connect-ip" &&
60 protocol_pair->second != "connect-ethernet")) {
dschinazia85581e2022-04-17 08:09:44 -070061 // This is not a MASQUE request.
dschinazi0e39ce02024-01-20 15:21:42 -080062 if (!signature_auth_on_all_requests_) {
63 return false;
64 }
Bence Békybac04052022-04-07 15:44:29 -040065 }
66
67 if (!server_authority_.empty()) {
68 auto authority_pair = request_headers.find(":authority");
69 if (authority_pair == request_headers.end()) {
70 // Cannot enforce missing authority.
71 return false;
72 }
73 absl::string_view authority = authority_pair->second;
74 if (server_authority_ != authority) {
75 // This request does not match server_authority.
76 return false;
77 }
78 }
79
80 auto it = backend_client_states_.find(request_handler->connection_id());
81 if (it == backend_client_states_.end()) {
bncced09502022-04-13 08:33:10 -070082 QUIC_LOG(ERROR) << "Could not find backend client for " << masque_path
83 << request_headers.DebugString();
Bence Békybac04052022-04-07 15:44:29 -040084 return false;
85 }
86
87 BackendClient* backend_client = it->second.backend_client;
88
89 std::unique_ptr<QuicBackendResponse> response =
dschinazia85581e2022-04-17 08:09:44 -070090 backend_client->HandleMasqueRequest(request_headers, request_handler);
Bence Békybac04052022-04-07 15:44:29 -040091 if (response == nullptr) {
92 QUIC_LOG(ERROR) << "Backend client did not process request for "
93 << masque_path << request_headers.DebugString();
94 return false;
95 }
96
97 QUIC_DLOG(INFO) << "Sending MASQUE response for "
98 << request_headers.DebugString();
99
100 request_handler->OnResponseBackendComplete(response.get());
101 it->second.responses.emplace_back(std::move(response));
102
103 return true;
104}
105
106void MasqueServerBackend::FetchResponseFromBackend(
107 const spdy::Http2HeaderBlock& request_headers,
108 const std::string& request_body,
109 QuicSimpleServerBackend::RequestHandler* request_handler) {
dschinazia85581e2022-04-17 08:09:44 -0700110 if (MaybeHandleMasqueRequest(request_headers, request_handler)) {
Bence Békybac04052022-04-07 15:44:29 -0400111 // Request was handled as a MASQUE request.
112 return;
113 }
114 QUIC_DLOG(INFO) << "Fetching non-MASQUE response for "
115 << request_headers.DebugString();
116 QuicMemoryCacheBackend::FetchResponseFromBackend(
117 request_headers, request_body, request_handler);
118}
119
dschinazi96f83d32022-05-17 11:18:35 -0700120void MasqueServerBackend::HandleConnectHeaders(
121 const spdy::Http2HeaderBlock& request_headers,
122 RequestHandler* request_handler) {
123 if (MaybeHandleMasqueRequest(request_headers, request_handler)) {
124 // Request was handled as a MASQUE request.
125 return;
126 }
127 QUIC_DLOG(INFO) << "Fetching non-MASQUE CONNECT response for "
128 << request_headers.DebugString();
129 QuicMemoryCacheBackend::HandleConnectHeaders(request_headers,
130 request_handler);
131}
132
Bence Békybac04052022-04-07 15:44:29 -0400133void MasqueServerBackend::CloseBackendResponseStream(
134 QuicSimpleServerBackend::RequestHandler* request_handler) {
135 QUIC_DLOG(INFO) << "Closing response stream";
136 QuicMemoryCacheBackend::CloseBackendResponseStream(request_handler);
137}
138
139void MasqueServerBackend::RegisterBackendClient(QuicConnectionId connection_id,
140 BackendClient* backend_client) {
141 QUIC_DLOG(INFO) << "Registering backend client for " << connection_id;
142 QUIC_BUG_IF(quic_bug_12005_1, backend_client_states_.find(connection_id) !=
143 backend_client_states_.end())
144 << connection_id << " already in backend clients map";
145 backend_client_states_[connection_id] =
146 BackendClientState{backend_client, {}};
147}
148
149void MasqueServerBackend::RemoveBackendClient(QuicConnectionId connection_id) {
150 QUIC_DLOG(INFO) << "Removing backend client for " << connection_id;
151 backend_client_states_.erase(connection_id);
152}
153
dschinazi425f03b2022-11-02 07:29:15 -0700154QuicIpAddress MasqueServerBackend::GetNextClientIpAddress() {
155 // Makes sure all addresses are in 10.(1-254).(1-254).(2-254)
156 QuicIpAddress address;
157 address.FromPackedString(
158 reinterpret_cast<char*>(&connect_ip_next_client_ip_[0]),
159 sizeof(connect_ip_next_client_ip_));
160 connect_ip_next_client_ip_[3]++;
161 if (connect_ip_next_client_ip_[3] >= 255) {
162 connect_ip_next_client_ip_[3] = 2;
163 connect_ip_next_client_ip_[2]++;
164 if (connect_ip_next_client_ip_[2] >= 255) {
165 connect_ip_next_client_ip_[2] = 1;
166 connect_ip_next_client_ip_[1]++;
167 if (connect_ip_next_client_ip_[1] >= 255) {
168 QUIC_LOG(FATAL) << "Ran out of IP addresses, restarting process.";
169 }
170 }
171 }
172 return address;
173}
174
dschinazia8489d22024-01-10 07:00:12 -0800175void MasqueServerBackend::SetSignatureAuth(absl::string_view signature_auth) {
176 signature_auth_credentials_.clear();
177 if (signature_auth.empty()) {
178 return;
179 }
180 for (absl::string_view sp : absl::StrSplit(signature_auth, ';')) {
181 quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&sp);
182 if (sp.empty()) {
183 continue;
184 }
185 std::vector<absl::string_view> kv =
186 absl::StrSplit(sp, absl::MaxSplits(':', 1));
187 quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[0]);
188 quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[1]);
189 SignatureAuthCredential credential;
190 credential.key_id = std::string(kv[0]);
191 std::string public_key = absl::HexStringToBytes(kv[1]);
192 if (public_key.size() != sizeof(credential.public_key)) {
193 QUIC_LOG(FATAL) << "Invalid signature auth public key length "
194 << public_key.size();
195 }
196 memcpy(credential.public_key, public_key.data(),
197 sizeof(credential.public_key));
198 signature_auth_credentials_.push_back(credential);
199 }
200}
201
202bool MasqueServerBackend::GetSignatureAuthKeyForId(
203 absl::string_view key_id,
204 uint8_t out_public_key[ED25519_PUBLIC_KEY_LEN]) const {
205 for (const auto& credential : signature_auth_credentials_) {
206 if (credential.key_id == key_id) {
207 memcpy(out_public_key, credential.public_key,
208 sizeof(credential.public_key));
209 return true;
210 }
211 }
212 return false;
213}
214
Bence Békybac04052022-04-07 15:44:29 -0400215} // namespace quic