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_utils.h"
6
7 #include <cstdint>
8 #include <cstring>
9 #include <ostream>
10 #include <string>
11 #include <utility>
12
13 #include "absl/strings/escaping.h"
14 #include "absl/strings/str_cat.h"
15 #include "absl/strings/string_view.h"
16 #include "quiche/quic/core/quic_config.h"
17 #include "quiche/quic/core/quic_data_writer.h"
18 #include "quiche/quic/core/quic_versions.h"
19 #include "quiche/quic/platform/api/quic_ip_address.h"
20 #include "quiche/quic/platform/api/quic_logging.h"
21 #include "quiche/common/platform/api/quiche_logging.h"
22
23 #if defined(__linux__)
24 #include <fcntl.h>
25 #include <linux/if.h>
26 #include <linux/if_tun.h>
27 #include <sys/ioctl.h>
28 #endif // defined(__linux__)
29
30 #include "absl/cleanup/cleanup.h"
31
32 namespace quic {
33
MasqueSupportedVersions()34 ParsedQuicVersionVector MasqueSupportedVersions() {
35 ParsedQuicVersionVector versions;
36 for (const ParsedQuicVersion& version : AllSupportedVersions()) {
37 // Use all versions that support IETF QUIC except QUICv2.
38 if (version.UsesHttp3() && !version.AlpnDeferToRFCv1()) {
39 QuicEnableVersion(version);
40 versions.push_back(version);
41 }
42 }
43 QUICHE_CHECK(!versions.empty());
44 return versions;
45 }
46
MasqueEncapsulatedConfig()47 QuicConfig MasqueEncapsulatedConfig() {
48 QuicConfig config;
49 config.SetMaxPacketSizeToSend(kMasqueMaxEncapsulatedPacketSize);
50 return config;
51 }
52
MasqueModeToString(MasqueMode masque_mode)53 std::string MasqueModeToString(MasqueMode masque_mode) {
54 switch (masque_mode) {
55 case MasqueMode::kInvalid:
56 return "Invalid";
57 case MasqueMode::kOpen:
58 return "Open";
59 case MasqueMode::kConnectIp:
60 return "CONNECT-IP";
61 case MasqueMode::kConnectEthernet:
62 return "CONNECT-ETHERNET";
63 }
64 return absl::StrCat("Unknown(", static_cast<int>(masque_mode), ")");
65 }
66
operator <<(std::ostream & os,const MasqueMode & masque_mode)67 std::ostream& operator<<(std::ostream& os, const MasqueMode& masque_mode) {
68 os << MasqueModeToString(masque_mode);
69 return os;
70 }
71
72 #if defined(__linux__)
CreateTunInterface(const QuicIpAddress & client_address,bool server)73 int CreateTunInterface(const QuicIpAddress& client_address, bool server) {
74 if (!client_address.IsIPv4()) {
75 QUIC_LOG(ERROR) << "CreateTunInterface currently only supports IPv4";
76 return -1;
77 }
78 // TODO(b/281517862): add test to validate O_NONBLOCK
79 int tun_fd = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
80 if (tun_fd < 0) {
81 QUIC_PLOG(ERROR) << "Failed to open clone device";
82 return -1;
83 }
84 absl::Cleanup tun_fd_closer = [tun_fd] { close(tun_fd); };
85
86 struct ifreq ifr = {};
87 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
88 // If we want to pick a specific device name, we can set it via
89 // ifr.ifr_name. Otherwise, the kernel will pick the next available tunX
90 // name.
91 int err = ioctl(tun_fd, TUNSETIFF, &ifr);
92 if (err < 0) {
93 QUIC_PLOG(ERROR) << "TUNSETIFF failed";
94 return -1;
95 }
96 int ip_fd = socket(AF_INET, SOCK_DGRAM, 0);
97 if (ip_fd < 0) {
98 QUIC_PLOG(ERROR) << "Failed to open IP configuration socket";
99 return -1;
100 }
101 absl::Cleanup ip_fd_closer = [ip_fd] { close(ip_fd); };
102
103 struct sockaddr_in addr = {};
104 addr.sin_family = AF_INET;
105 // Local address, unused but needs to be set. We use the same address as the
106 // client address, but with last byte set to 1.
107 addr.sin_addr = client_address.GetIPv4();
108 if (server) {
109 addr.sin_addr.s_addr &= htonl(0xffffff00);
110 addr.sin_addr.s_addr |= htonl(0x00000001);
111 }
112 memcpy(&ifr.ifr_addr, &addr, sizeof(addr));
113 err = ioctl(ip_fd, SIOCSIFADDR, &ifr);
114 if (err < 0) {
115 QUIC_PLOG(ERROR) << "SIOCSIFADDR failed";
116 return -1;
117 }
118 // Peer address, needs to match source IP address of sent packets.
119 addr.sin_addr = client_address.GetIPv4();
120 if (!server) {
121 addr.sin_addr.s_addr &= htonl(0xffffff00);
122 addr.sin_addr.s_addr |= htonl(0x00000001);
123 }
124 memcpy(&ifr.ifr_addr, &addr, sizeof(addr));
125 err = ioctl(ip_fd, SIOCSIFDSTADDR, &ifr);
126 if (err < 0) {
127 QUIC_PLOG(ERROR) << "SIOCSIFDSTADDR failed";
128 return -1;
129 }
130 if (!server) {
131 // Set MTU, to 1280 for now which should always fit (fingers crossed)
132 ifr.ifr_mtu = 1280;
133 err = ioctl(ip_fd, SIOCSIFMTU, &ifr);
134 if (err < 0) {
135 QUIC_PLOG(ERROR) << "SIOCSIFMTU failed";
136 return -1;
137 }
138 }
139
140 err = ioctl(ip_fd, SIOCGIFFLAGS, &ifr);
141 if (err < 0) {
142 QUIC_PLOG(ERROR) << "SIOCGIFFLAGS failed";
143 return -1;
144 }
145 ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
146 err = ioctl(ip_fd, SIOCSIFFLAGS, &ifr);
147 if (err < 0) {
148 QUIC_PLOG(ERROR) << "SIOCSIFFLAGS failed";
149 return -1;
150 }
151 close(ip_fd);
152 QUIC_DLOG(INFO) << "Successfully created TUN interface " << ifr.ifr_name
153 << " with fd " << tun_fd;
154 std::move(tun_fd_closer).Cancel();
155 return tun_fd;
156 }
157 #else
CreateTunInterface(const QuicIpAddress &,bool)158 int CreateTunInterface(const QuicIpAddress& /*client_address*/,
159 bool /*server*/) {
160 // Unsupported.
161 return -1;
162 }
163 #endif // defined(__linux__)
164
165 #if defined(__linux__)
CreateTapInterface()166 int CreateTapInterface() {
167 int tap_fd = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
168 if (tap_fd < 0) {
169 QUIC_PLOG(ERROR) << "Failed to open clone device";
170 return -1;
171 }
172 absl::Cleanup tap_fd_closer = [tap_fd] { close(tap_fd); };
173
174 struct ifreq ifr = {};
175 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
176 // If we want to pick a specific device name, we can set it via
177 // ifr.ifr_name. Otherwise, the kernel will pick the next available tapX
178 // name.
179 int err = ioctl(tap_fd, TUNSETIFF, &ifr);
180 if (err < 0) {
181 QUIC_PLOG(ERROR) << "TUNSETIFF failed";
182 return -1;
183 }
184
185 QUIC_DLOG(INFO) << "Successfully created TAP interface " << ifr.ifr_name
186 << " with fd " << tap_fd;
187
188 int sock_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
189 if (sock_fd < 0) {
190 QUIC_PLOG(ERROR) << "Error opening configuration socket";
191 return -1;
192 }
193 absl::Cleanup sock_fd_closer = [sock_fd] { close(sock_fd); };
194
195 ifr.ifr_mtu = 1280;
196 err = ioctl(sock_fd, SIOCSIFMTU, &ifr);
197 if (err < 0) {
198 QUIC_PLOG(ERROR) << "SIOCSIFMTU failed";
199 return -1;
200 }
201
202 err = ioctl(sock_fd, SIOCGIFFLAGS, &ifr);
203 if (err < 0) {
204 QUIC_PLOG(ERROR) << "SIOCGIFFLAGS failed";
205 return -1;
206 }
207 ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
208 err = ioctl(sock_fd, SIOCSIFFLAGS, &ifr);
209 if (err < 0) {
210 QUIC_PLOG(ERROR) << "SIOCSIFFLAGS failed";
211 return -1;
212 }
213 std::move(tap_fd_closer).Cancel();
214 return tap_fd;
215 }
216 #else
CreateTapInterface()217 int CreateTapInterface() {
218 // Unsupported.
219 return -1;
220 }
221 #endif // defined(__linux__)
222
ComputeSignatureAuthContext(uint16_t signature_scheme,absl::string_view key_id,absl::string_view public_key,absl::string_view scheme,absl::string_view host,uint16_t port,absl::string_view realm)223 std::string ComputeSignatureAuthContext(uint16_t signature_scheme,
224 absl::string_view key_id,
225 absl::string_view public_key,
226 absl::string_view scheme,
227 absl::string_view host, uint16_t port,
228 absl::string_view realm) {
229 QUIC_DVLOG(2) << "ComputeSignatureAuthContext: key_id=\"" << key_id
230 << "\" public_key=" << absl::WebSafeBase64Escape(public_key)
231 << " scheme=\"" << scheme << "\" host=\"" << host
232 << "\" port=" << port << " realm=\"" << realm << "\"";
233 std::string key_exporter_context;
234 key_exporter_context.resize(
235 sizeof(signature_scheme) + QuicDataWriter::GetVarInt62Len(key_id.size()) +
236 key_id.size() + QuicDataWriter::GetVarInt62Len(public_key.size()) +
237 public_key.size() + QuicDataWriter::GetVarInt62Len(scheme.size()) +
238 scheme.size() + QuicDataWriter::GetVarInt62Len(host.size()) +
239 host.size() + sizeof(port) +
240 QuicDataWriter::GetVarInt62Len(realm.size()) + realm.size());
241 QuicDataWriter writer(key_exporter_context.size(),
242 key_exporter_context.data());
243 if (!writer.WriteUInt16(signature_scheme) ||
244 !writer.WriteStringPieceVarInt62(key_id) ||
245 !writer.WriteStringPieceVarInt62(public_key) ||
246 !writer.WriteStringPieceVarInt62(scheme) ||
247 !writer.WriteStringPieceVarInt62(host) || !writer.WriteUInt16(port) ||
248 !writer.WriteStringPieceVarInt62(realm) || writer.remaining() != 0) {
249 QUIC_LOG(FATAL) << "ComputeSignatureAuthContext failed";
250 }
251 return key_exporter_context;
252 }
253
SignatureAuthDataCoveredBySignature(absl::string_view signature_input)254 std::string SignatureAuthDataCoveredBySignature(
255 absl::string_view signature_input) {
256 return absl::StrCat(std::string(64, 0x20), "HTTP Signature Authentication",
257 std::string(1, 0x00), signature_input);
258 }
259
260 } // namespace quic
261