xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 #include "quiche/quic/masque/masque_server_backend.h"
6 
7 #include <cstdint>
8 #include <cstring>
9 #include <memory>
10 #include <string>
11 #include <utility>
12 #include <vector>
13 
14 #include "absl/strings/escaping.h"
15 #include "absl/strings/str_split.h"
16 #include "absl/strings/string_view.h"
17 #include "openssl/curve25519.h"
18 #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"
28 
29 namespace quic {
30 
MasqueServerBackend(MasqueMode,const std::string & server_authority,const std::string & cache_directory)31 MasqueServerBackend::MasqueServerBackend(MasqueMode /*masque_mode*/,
32                                          const std::string& server_authority,
33                                          const std::string& cache_directory)
34     : server_authority_(server_authority) {
35   // 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 
41   if (!cache_directory.empty()) {
42     QuicMemoryCacheBackend::InitializeBackend(cache_directory);
43   }
44 
45   // We don't currently use `masque_mode_` but will in the future. To silence
46   // clang's `-Wunused-private-field` warning for this when building QUICHE for
47   // Chrome, add a use of it here.
48   (void)masque_mode_;
49 }
50 
MaybeHandleMasqueRequest(const spdy::Http2HeaderBlock & request_headers,QuicSimpleServerBackend::RequestHandler * request_handler)51 bool MasqueServerBackend::MaybeHandleMasqueRequest(
52     const spdy::Http2HeaderBlock& request_headers,
53     QuicSimpleServerBackend::RequestHandler* request_handler) {
54   auto method_pair = request_headers.find(":method");
55   if (method_pair == request_headers.end()) {
56     // Request is missing a method.
57     return false;
58   }
59   absl::string_view method = method_pair->second;
60   std::string masque_path = "";
61   auto protocol_pair = request_headers.find(":protocol");
62   if (method != "CONNECT" || protocol_pair == request_headers.end() ||
63       (protocol_pair->second != "connect-udp" &&
64        protocol_pair->second != "connect-ip" &&
65        protocol_pair->second != "connect-ethernet")) {
66     // This is not a MASQUE request.
67     if (!signature_auth_on_all_requests_) {
68       return false;
69     }
70   }
71 
72   if (!server_authority_.empty()) {
73     auto authority_pair = request_headers.find(":authority");
74     if (authority_pair == request_headers.end()) {
75       // Cannot enforce missing authority.
76       return false;
77     }
78     absl::string_view authority = authority_pair->second;
79     if (server_authority_ != authority) {
80       // This request does not match server_authority.
81       return false;
82     }
83   }
84 
85   auto it = backend_client_states_.find(request_handler->connection_id());
86   if (it == backend_client_states_.end()) {
87     QUIC_LOG(ERROR) << "Could not find backend client for " << masque_path
88                     << request_headers.DebugString();
89     return false;
90   }
91 
92   BackendClient* backend_client = it->second.backend_client;
93 
94   std::unique_ptr<QuicBackendResponse> response =
95       backend_client->HandleMasqueRequest(request_headers, request_handler);
96   if (response == nullptr) {
97     QUIC_LOG(ERROR) << "Backend client did not process request for "
98                     << masque_path << request_headers.DebugString();
99     return false;
100   }
101 
102   QUIC_DLOG(INFO) << "Sending MASQUE response for "
103                   << request_headers.DebugString();
104 
105   request_handler->OnResponseBackendComplete(response.get());
106   it->second.responses.emplace_back(std::move(response));
107 
108   return true;
109 }
110 
FetchResponseFromBackend(const spdy::Http2HeaderBlock & request_headers,const std::string & request_body,QuicSimpleServerBackend::RequestHandler * request_handler)111 void MasqueServerBackend::FetchResponseFromBackend(
112     const spdy::Http2HeaderBlock& request_headers,
113     const std::string& request_body,
114     QuicSimpleServerBackend::RequestHandler* request_handler) {
115   if (MaybeHandleMasqueRequest(request_headers, request_handler)) {
116     // Request was handled as a MASQUE request.
117     return;
118   }
119   QUIC_DLOG(INFO) << "Fetching non-MASQUE response for "
120                   << request_headers.DebugString();
121   QuicMemoryCacheBackend::FetchResponseFromBackend(
122       request_headers, request_body, request_handler);
123 }
124 
HandleConnectHeaders(const spdy::Http2HeaderBlock & request_headers,RequestHandler * request_handler)125 void MasqueServerBackend::HandleConnectHeaders(
126     const spdy::Http2HeaderBlock& request_headers,
127     RequestHandler* request_handler) {
128   if (MaybeHandleMasqueRequest(request_headers, request_handler)) {
129     // Request was handled as a MASQUE request.
130     return;
131   }
132   QUIC_DLOG(INFO) << "Fetching non-MASQUE CONNECT response for "
133                   << request_headers.DebugString();
134   QuicMemoryCacheBackend::HandleConnectHeaders(request_headers,
135                                                request_handler);
136 }
137 
CloseBackendResponseStream(QuicSimpleServerBackend::RequestHandler * request_handler)138 void MasqueServerBackend::CloseBackendResponseStream(
139     QuicSimpleServerBackend::RequestHandler* request_handler) {
140   QUIC_DLOG(INFO) << "Closing response stream";
141   QuicMemoryCacheBackend::CloseBackendResponseStream(request_handler);
142 }
143 
RegisterBackendClient(QuicConnectionId connection_id,BackendClient * backend_client)144 void MasqueServerBackend::RegisterBackendClient(QuicConnectionId connection_id,
145                                                 BackendClient* backend_client) {
146   QUIC_DLOG(INFO) << "Registering backend client for " << connection_id;
147   QUIC_BUG_IF(quic_bug_12005_1, backend_client_states_.find(connection_id) !=
148                                     backend_client_states_.end())
149       << connection_id << " already in backend clients map";
150   backend_client_states_[connection_id] =
151       BackendClientState{backend_client, {}};
152 }
153 
RemoveBackendClient(QuicConnectionId connection_id)154 void MasqueServerBackend::RemoveBackendClient(QuicConnectionId connection_id) {
155   QUIC_DLOG(INFO) << "Removing backend client for " << connection_id;
156   backend_client_states_.erase(connection_id);
157 }
158 
GetNextClientIpAddress()159 QuicIpAddress MasqueServerBackend::GetNextClientIpAddress() {
160   // Makes sure all addresses are in 10.(1-254).(1-254).(2-254)
161   QuicIpAddress address;
162   address.FromPackedString(
163       reinterpret_cast<char*>(&connect_ip_next_client_ip_[0]),
164       sizeof(connect_ip_next_client_ip_));
165   connect_ip_next_client_ip_[3]++;
166   if (connect_ip_next_client_ip_[3] >= 255) {
167     connect_ip_next_client_ip_[3] = 2;
168     connect_ip_next_client_ip_[2]++;
169     if (connect_ip_next_client_ip_[2] >= 255) {
170       connect_ip_next_client_ip_[2] = 1;
171       connect_ip_next_client_ip_[1]++;
172       if (connect_ip_next_client_ip_[1] >= 255) {
173         QUIC_LOG(FATAL) << "Ran out of IP addresses, restarting process.";
174       }
175     }
176   }
177   return address;
178 }
179 
SetSignatureAuth(absl::string_view signature_auth)180 void MasqueServerBackend::SetSignatureAuth(absl::string_view signature_auth) {
181   signature_auth_credentials_.clear();
182   if (signature_auth.empty()) {
183     return;
184   }
185   for (absl::string_view sp : absl::StrSplit(signature_auth, ';')) {
186     quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&sp);
187     if (sp.empty()) {
188       continue;
189     }
190     std::vector<absl::string_view> kv =
191         absl::StrSplit(sp, absl::MaxSplits(':', 1));
192     quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[0]);
193     quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[1]);
194     SignatureAuthCredential credential;
195     credential.key_id = std::string(kv[0]);
196     std::string public_key;
197     if (!absl::HexStringToBytes(kv[1], &public_key)) {
198       QUIC_LOG(FATAL) << "Invalid signature auth public key hex " << kv[1];
199     }
200     if (public_key.size() != sizeof(credential.public_key)) {
201       QUIC_LOG(FATAL) << "Invalid signature auth public key length "
202                       << public_key.size();
203     }
204     memcpy(credential.public_key, public_key.data(),
205            sizeof(credential.public_key));
206     signature_auth_credentials_.push_back(credential);
207   }
208 }
209 
GetSignatureAuthKeyForId(absl::string_view key_id,uint8_t out_public_key[ED25519_PUBLIC_KEY_LEN]) const210 bool MasqueServerBackend::GetSignatureAuthKeyForId(
211     absl::string_view key_id,
212     uint8_t out_public_key[ED25519_PUBLIC_KEY_LEN]) const {
213   for (const auto& credential : signature_auth_credentials_) {
214     if (credential.key_id == key_id) {
215       memcpy(out_public_key, credential.public_key,
216              sizeof(credential.public_key));
217       return true;
218     }
219   }
220   return false;
221 }
222 
223 }  // namespace quic
224