blob: 54f91c522c8aefead261cc02dfc076212fdfe780 [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Patrik Höglund56d94522019-11-18 15:53:32 +010011#include "api/transport/stun.h"
Jonas Olssona4d87372019-07-05 19:08:33 +020012
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Mirko Bonadei317a1f02019-09-17 17:06:18 +020015#include <memory>
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000016#include <string>
Steve Anton6c38cc72017-11-29 10:25:58 -080017#include <utility>
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000018
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "rtc_base/arraysize.h"
Steve Anton10542f22019-01-11 09:11:00 -080020#include "rtc_base/byte_buffer.h"
21#include "rtc_base/byte_order.h"
22#include "rtc_base/socket_address.h"
Yves Gerey3e707812018-11-28 16:47:49 +010023#include "test/gtest.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000024
25namespace cricket {
26
27class StunTest : public ::testing::Test {
28 protected:
Yves Gerey665174f2018-06-19 15:03:05 +020029 void CheckStunHeader(const StunMessage& msg,
30 StunMessageType expected_type,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000031 size_t expected_length) {
32 ASSERT_EQ(expected_type, msg.type());
33 ASSERT_EQ(expected_length, msg.length());
34 }
35
36 void CheckStunTransactionID(const StunMessage& msg,
Yves Gerey665174f2018-06-19 15:03:05 +020037 const unsigned char* expectedID,
38 size_t length) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000039 ASSERT_EQ(length, msg.transaction_id().size());
40 ASSERT_EQ(length == kStunTransactionIdLength + 4, msg.IsLegacy());
41 ASSERT_EQ(length == kStunTransactionIdLength, !msg.IsLegacy());
42 ASSERT_EQ(0, memcmp(msg.transaction_id().c_str(), expectedID, length));
43 }
44
45 void CheckStunAddressAttribute(const StunAddressAttribute* addr,
46 StunAddressFamily expected_family,
47 int expected_port,
Yves Gerey2257c082020-01-03 12:37:56 +010048 const rtc::IPAddress& expected_address) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000049 ASSERT_EQ(expected_family, addr->family());
50 ASSERT_EQ(expected_port, addr->port());
51
52 if (addr->family() == STUN_ADDRESS_IPV4) {
53 in_addr v4_address = expected_address.ipv4_address();
54 in_addr stun_address = addr->ipaddr().ipv4_address();
55 ASSERT_EQ(0, memcmp(&v4_address, &stun_address, sizeof(stun_address)));
56 } else if (addr->family() == STUN_ADDRESS_IPV6) {
57 in6_addr v6_address = expected_address.ipv6_address();
58 in6_addr stun_address = addr->ipaddr().ipv6_address();
59 ASSERT_EQ(0, memcmp(&v6_address, &stun_address, sizeof(stun_address)));
60 } else {
61 ASSERT_TRUE(addr->family() == STUN_ADDRESS_IPV6 ||
62 addr->family() == STUN_ADDRESS_IPV4);
63 }
64 }
65
66 size_t ReadStunMessageTestCase(StunMessage* msg,
67 const unsigned char* testcase,
68 size_t size) {
69 const char* input = reinterpret_cast<const char*>(testcase);
jbauchf1f87202016-03-30 06:43:37 -070070 rtc::ByteBufferReader buf(input, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000071 if (msg->Read(&buf)) {
72 // Returns the size the stun message should report itself as being
73 return (size - 20);
74 } else {
75 return 0;
76 }
77 }
78};
79
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000080// Sample STUN packets with various attributes
81// Gathered by wiresharking pjproject's pjnath test programs
82// pjproject available at www.pjsip.org
83
Yves Gerey665174f2018-06-19 15:03:05 +020084// clang-format off
85// clang formatting doesn't respect inline comments.
86
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000087static const unsigned char kStunMessageWithIPv6MappedAddress[] = {
88 0x00, 0x01, 0x00, 0x18, // message header
89 0x21, 0x12, 0xa4, 0x42, // transaction id
90 0x29, 0x1f, 0xcd, 0x7c,
91 0xba, 0x58, 0xab, 0xd7,
92 0xf2, 0x41, 0x01, 0x00,
93 0x00, 0x01, 0x00, 0x14, // Address type (mapped), length
94 0x00, 0x02, 0xb8, 0x81, // family (IPv6), port
95 0x24, 0x01, 0xfa, 0x00, // an IPv6 address
96 0x00, 0x04, 0x10, 0x00,
97 0xbe, 0x30, 0x5b, 0xff,
98 0xfe, 0xe5, 0x00, 0xc3
99};
100
101static const unsigned char kStunMessageWithIPv4MappedAddress[] = {
102 0x01, 0x01, 0x00, 0x0c, // binding response, length 12
103 0x21, 0x12, 0xa4, 0x42, // magic cookie
104 0x29, 0x1f, 0xcd, 0x7c, // transaction ID
105 0xba, 0x58, 0xab, 0xd7,
106 0xf2, 0x41, 0x01, 0x00,
107 0x00, 0x01, 0x00, 0x08, // Mapped, 8 byte length
108 0x00, 0x01, 0x9d, 0xfc, // AF_INET, unxor-ed port
109 0xac, 0x17, 0x44, 0xe6 // IPv4 address
110};
111
112// Test XOR-mapped IP addresses:
113static const unsigned char kStunMessageWithIPv6XorMappedAddress[] = {
114 0x01, 0x01, 0x00, 0x18, // message header (binding response)
115 0x21, 0x12, 0xa4, 0x42, // magic cookie (rfc5389)
116 0xe3, 0xa9, 0x46, 0xe1, // transaction ID
117 0x7c, 0x00, 0xc2, 0x62,
118 0x54, 0x08, 0x01, 0x00,
119 0x00, 0x20, 0x00, 0x14, // Address Type (XOR), length
120 0x00, 0x02, 0xcb, 0x5b, // family, XOR-ed port
121 0x05, 0x13, 0x5e, 0x42, // XOR-ed IPv6 address
122 0xe3, 0xad, 0x56, 0xe1,
123 0xc2, 0x30, 0x99, 0x9d,
124 0xaa, 0xed, 0x01, 0xc3
125};
126
127static const unsigned char kStunMessageWithIPv4XorMappedAddress[] = {
128 0x01, 0x01, 0x00, 0x0c, // message header (binding response)
129 0x21, 0x12, 0xa4, 0x42, // magic cookie
130 0x29, 0x1f, 0xcd, 0x7c, // transaction ID
131 0xba, 0x58, 0xab, 0xd7,
132 0xf2, 0x41, 0x01, 0x00,
133 0x00, 0x20, 0x00, 0x08, // address type (xor), length
134 0x00, 0x01, 0xfc, 0xb5, // family (AF_INET), XOR-ed port
135 0x8d, 0x05, 0xe0, 0xa4 // IPv4 address
136};
137
138// ByteString Attribute (username)
139static const unsigned char kStunMessageWithByteStringAttribute[] = {
140 0x00, 0x01, 0x00, 0x0c,
141 0x21, 0x12, 0xa4, 0x42,
142 0xe3, 0xa9, 0x46, 0xe1,
143 0x7c, 0x00, 0xc2, 0x62,
144 0x54, 0x08, 0x01, 0x00,
145 0x00, 0x06, 0x00, 0x08, // username attribute (length 8)
146 0x61, 0x62, 0x63, 0x64, // abcdefgh
147 0x65, 0x66, 0x67, 0x68
148};
149
150// Message with an unknown but comprehensible optional attribute.
151// Parsing should succeed despite this unknown attribute.
152static const unsigned char kStunMessageWithUnknownAttribute[] = {
153 0x00, 0x01, 0x00, 0x14,
154 0x21, 0x12, 0xa4, 0x42,
155 0xe3, 0xa9, 0x46, 0xe1,
156 0x7c, 0x00, 0xc2, 0x62,
157 0x54, 0x08, 0x01, 0x00,
158 0x00, 0xaa, 0x00, 0x07, // Unknown attribute, length 7 (needs padding!)
159 0x61, 0x62, 0x63, 0x64, // abcdefg + padding
160 0x65, 0x66, 0x67, 0x00,
161 0x00, 0x06, 0x00, 0x03, // Followed by a known attribute we can
162 0x61, 0x62, 0x63, 0x00 // check for (username of length 3)
163};
164
165// ByteString Attribute (username) with padding byte
166static const unsigned char kStunMessageWithPaddedByteStringAttribute[] = {
167 0x00, 0x01, 0x00, 0x08,
168 0x21, 0x12, 0xa4, 0x42,
169 0xe3, 0xa9, 0x46, 0xe1,
170 0x7c, 0x00, 0xc2, 0x62,
171 0x54, 0x08, 0x01, 0x00,
172 0x00, 0x06, 0x00, 0x03, // username attribute (length 3)
173 0x61, 0x62, 0x63, 0xcc // abc
174};
175
Peter Boström0c4e06b2015-10-07 12:23:21 +0200176// Message with an Unknown Attributes (uint16_t list) attribute.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000177static const unsigned char kStunMessageWithUInt16ListAttribute[] = {
178 0x00, 0x01, 0x00, 0x0c,
179 0x21, 0x12, 0xa4, 0x42,
180 0xe3, 0xa9, 0x46, 0xe1,
181 0x7c, 0x00, 0xc2, 0x62,
182 0x54, 0x08, 0x01, 0x00,
183 0x00, 0x0a, 0x00, 0x06, // username attribute (length 6)
184 0x00, 0x01, 0x10, 0x00, // three attributes plus padding
185 0xAB, 0xCU, 0xBE, 0xEF
186};
187
188// Error response message (unauthorized)
189static const unsigned char kStunMessageWithErrorAttribute[] = {
190 0x01, 0x11, 0x00, 0x14,
191 0x21, 0x12, 0xa4, 0x42,
192 0x29, 0x1f, 0xcd, 0x7c,
193 0xba, 0x58, 0xab, 0xd7,
194 0xf2, 0x41, 0x01, 0x00,
195 0x00, 0x09, 0x00, 0x10,
196 0x00, 0x00, 0x04, 0x01,
197 0x55, 0x6e, 0x61, 0x75,
198 0x74, 0x68, 0x6f, 0x72,
199 0x69, 0x7a, 0x65, 0x64
200};
201
202// Sample messages with an invalid length Field
203
204// The actual length in bytes of the invalid messages (including STUN header)
205static const int kRealLengthOfInvalidLengthTestCases = 32;
206
207static const unsigned char kStunMessageWithZeroLength[] = {
208 0x00, 0x01, 0x00, 0x00, // length of 0 (last 2 bytes)
209 0x21, 0x12, 0xA4, 0x42, // magic cookie
210 '0', '1', '2', '3', // transaction id
211 '4', '5', '6', '7',
212 '8', '9', 'a', 'b',
213 0x00, 0x20, 0x00, 0x08, // xor mapped address
214 0x00, 0x01, 0x21, 0x1F,
215 0x21, 0x12, 0xA4, 0x53,
216};
217
218static const unsigned char kStunMessageWithExcessLength[] = {
219 0x00, 0x01, 0x00, 0x55, // length of 85
220 0x21, 0x12, 0xA4, 0x42, // magic cookie
221 '0', '1', '2', '3', // transaction id
222 '4', '5', '6', '7',
223 '8', '9', 'a', 'b',
224 0x00, 0x20, 0x00, 0x08, // xor mapped address
225 0x00, 0x01, 0x21, 0x1F,
226 0x21, 0x12, 0xA4, 0x53,
227};
228
229static const unsigned char kStunMessageWithSmallLength[] = {
230 0x00, 0x01, 0x00, 0x03, // length of 3
231 0x21, 0x12, 0xA4, 0x42, // magic cookie
232 '0', '1', '2', '3', // transaction id
233 '4', '5', '6', '7',
234 '8', '9', 'a', 'b',
235 0x00, 0x20, 0x00, 0x08, // xor mapped address
236 0x00, 0x01, 0x21, 0x1F,
237 0x21, 0x12, 0xA4, 0x53,
238};
239
katrielc1a206102016-06-20 05:13:16 -0700240static const unsigned char kStunMessageWithBadHmacAtEnd[] = {
241 0x00, 0x01, 0x00, 0x14, // message length exactly 20
242 0x21, 0x12, 0xA4, 0x42, // magic cookie
243 '0', '1', '2', '3', // transaction ID
244 '4', '5', '6', '7',
245 '8', '9', 'a', 'b',
246 0x00, 0x08, 0x00, 0x14, // type=STUN_ATTR_MESSAGE_INTEGRITY, length=20
247 '0', '0', '0', '0', // We lied, there are only 16 bytes of HMAC.
248 '0', '0', '0', '0',
249 '0', '0', '0', '0',
250 '0', '0', '0', '0',
251};
252
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000253// RTCP packet, for testing we correctly ignore non stun packet types.
254// V=2, P=false, RC=0, Type=200, Len=6, Sender-SSRC=85, etc
255static const unsigned char kRtcpPacket[] = {
256 0x80, 0xc8, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55,
257 0xce, 0xa5, 0x18, 0x3a, 0x39, 0xcc, 0x7d, 0x09,
258 0x23, 0xed, 0x19, 0x07, 0x00, 0x00, 0x01, 0x56,
259 0x00, 0x03, 0x73, 0x50,
260};
261
Yves Gerey665174f2018-06-19 15:03:05 +0200262
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000263// RFC5769 Test Vectors
264// Software name (request): "STUN test client" (without quotes)
265// Software name (response): "test vector" (without quotes)
266// Username: "evtj:h6vY" (without quotes)
267// Password: "VOkJxbRl1RmTxUk/WvJxBt" (without quotes)
268static const unsigned char kRfc5769SampleMsgTransactionId[] = {
269 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae
270};
271static const char kRfc5769SampleMsgClientSoftware[] = "STUN test client";
272static const char kRfc5769SampleMsgServerSoftware[] = "test vector";
273static const char kRfc5769SampleMsgUsername[] = "evtj:h6vY";
274static const char kRfc5769SampleMsgPassword[] = "VOkJxbRl1RmTxUk/WvJxBt";
275static const rtc::SocketAddress kRfc5769SampleMsgMappedAddress(
276 "192.0.2.1", 32853);
277static const rtc::SocketAddress kRfc5769SampleMsgIPv6MappedAddress(
278 "2001:db8:1234:5678:11:2233:4455:6677", 32853);
279
280static const unsigned char kRfc5769SampleMsgWithAuthTransactionId[] = {
281 0x78, 0xad, 0x34, 0x33, 0xc6, 0xad, 0x72, 0xc0, 0x29, 0xda, 0x41, 0x2e
282};
283static const char kRfc5769SampleMsgWithAuthUsername[] =
284 "\xe3\x83\x9e\xe3\x83\x88\xe3\x83\xaa\xe3\x83\x83\xe3\x82\xaf\xe3\x82\xb9";
285static const char kRfc5769SampleMsgWithAuthPassword[] = "TheMatrIX";
286static const char kRfc5769SampleMsgWithAuthNonce[] =
287 "f//499k954d6OL34oL9FSTvy64sA";
288static const char kRfc5769SampleMsgWithAuthRealm[] = "example.org";
289
290// 2.1. Sample Request
291static const unsigned char kRfc5769SampleRequest[] = {
292 0x00, 0x01, 0x00, 0x58, // Request type and message length
293 0x21, 0x12, 0xa4, 0x42, // Magic cookie
294 0xb7, 0xe7, 0xa7, 0x01, // }
295 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
296 0xfa, 0x87, 0xdf, 0xae, // }
297 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
298 0x53, 0x54, 0x55, 0x4e, // }
299 0x20, 0x74, 0x65, 0x73, // } User-agent...
300 0x74, 0x20, 0x63, 0x6c, // } ...name
301 0x69, 0x65, 0x6e, 0x74, // }
302 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
303 0x6e, 0x00, 0x01, 0xff, // ICE priority value
304 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
305 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
306 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
307 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
308 0x65, 0x76, 0x74, 0x6a, // }
309 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
310 0x59, 0x20, 0x20, 0x20, // }
311 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
312 0x9a, 0xea, 0xa7, 0x0c, // }
313 0xbf, 0xd8, 0xcb, 0x56, // }
314 0x78, 0x1e, 0xf2, 0xb5, // } HMAC-SHA1 fingerprint
315 0xb2, 0xd3, 0xf2, 0x49, // }
316 0xc1, 0xb5, 0x71, 0xa2, // }
317 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
318 0xe5, 0x7a, 0x3b, 0xcf // CRC32 fingerprint
319};
320
Jonas Oreland63737a92019-11-21 15:12:14 +0100321// 2.1. Sample Request
322static const unsigned char kSampleRequestMI32[] = {
323 0x00, 0x01, 0x00, 0x48, // Request type and message length
324 0x21, 0x12, 0xa4, 0x42, // Magic cookie
325 0xb7, 0xe7, 0xa7, 0x01, // }
326 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
327 0xfa, 0x87, 0xdf, 0xae, // }
328 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
329 0x53, 0x54, 0x55, 0x4e, // }
330 0x20, 0x74, 0x65, 0x73, // } User-agent...
331 0x74, 0x20, 0x63, 0x6c, // } ...name
332 0x69, 0x65, 0x6e, 0x74, // }
333 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
334 0x6e, 0x00, 0x01, 0xff, // ICE priority value
335 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
336 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
337 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
338 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
339 0x65, 0x76, 0x74, 0x6a, // }
340 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
341 0x59, 0x20, 0x20, 0x20, // }
342 0xC0, 0x60, 0x00, 0x04, // MESSAGE-INTEGRITY-32 attribute header
343 0x45, 0x45, 0xce, 0x7c, // } HMAC-SHA1 fingerprint (first 32 bit)
344 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
345 0xe5, 0x7a, 0x3b, 0xcf // CRC32 fingerprint
346};
347
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000348// 2.2. Sample IPv4 Response
349static const unsigned char kRfc5769SampleResponse[] = {
350 0x01, 0x01, 0x00, 0x3c, // Response type and message length
351 0x21, 0x12, 0xa4, 0x42, // Magic cookie
352 0xb7, 0xe7, 0xa7, 0x01, // }
353 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
354 0xfa, 0x87, 0xdf, 0xae, // }
355 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
356 0x74, 0x65, 0x73, 0x74, // }
357 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
358 0x74, 0x6f, 0x72, 0x20, // }
359 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
360 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port
361 0xe1, 0x12, 0xa6, 0x43, // Xor'd mapped IPv4 address
362 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
363 0x2b, 0x91, 0xf5, 0x99, // }
364 0xfd, 0x9e, 0x90, 0xc3, // }
365 0x8c, 0x74, 0x89, 0xf9, // } HMAC-SHA1 fingerprint
366 0x2a, 0xf9, 0xba, 0x53, // }
367 0xf0, 0x6b, 0xe7, 0xd7, // }
368 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
369 0xc0, 0x7d, 0x4c, 0x96 // CRC32 fingerprint
370};
371
372// 2.3. Sample IPv6 Response
373static const unsigned char kRfc5769SampleResponseIPv6[] = {
374 0x01, 0x01, 0x00, 0x48, // Response type and message length
375 0x21, 0x12, 0xa4, 0x42, // Magic cookie
376 0xb7, 0xe7, 0xa7, 0x01, // }
377 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
378 0xfa, 0x87, 0xdf, 0xae, // }
379 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
380 0x74, 0x65, 0x73, 0x74, // }
381 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
382 0x74, 0x6f, 0x72, 0x20, // }
383 0x00, 0x20, 0x00, 0x14, // XOR-MAPPED-ADDRESS attribute header
384 0x00, 0x02, 0xa1, 0x47, // Address family (IPv6) and xor'd mapped port.
385 0x01, 0x13, 0xa9, 0xfa, // }
386 0xa5, 0xd3, 0xf1, 0x79, // } Xor'd mapped IPv6 address
387 0xbc, 0x25, 0xf4, 0xb5, // }
388 0xbe, 0xd2, 0xb9, 0xd9, // }
389 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
390 0xa3, 0x82, 0x95, 0x4e, // }
391 0x4b, 0xe6, 0x7b, 0xf1, // }
392 0x17, 0x84, 0xc9, 0x7c, // } HMAC-SHA1 fingerprint
393 0x82, 0x92, 0xc2, 0x75, // }
394 0xbf, 0xe3, 0xed, 0x41, // }
395 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
396 0xc8, 0xfb, 0x0b, 0x4c // CRC32 fingerprint
397};
398
399// 2.4. Sample Request with Long-Term Authentication
400static const unsigned char kRfc5769SampleRequestLongTermAuth[] = {
401 0x00, 0x01, 0x00, 0x60, // Request type and message length
402 0x21, 0x12, 0xa4, 0x42, // Magic cookie
403 0x78, 0xad, 0x34, 0x33, // }
404 0xc6, 0xad, 0x72, 0xc0, // } Transaction ID
405 0x29, 0xda, 0x41, 0x2e, // }
406 0x00, 0x06, 0x00, 0x12, // USERNAME attribute header
407 0xe3, 0x83, 0x9e, 0xe3, // }
408 0x83, 0x88, 0xe3, 0x83, // }
409 0xaa, 0xe3, 0x83, 0x83, // } Username value (18 bytes) and padding (2 bytes)
410 0xe3, 0x82, 0xaf, 0xe3, // }
411 0x82, 0xb9, 0x00, 0x00, // }
412 0x00, 0x15, 0x00, 0x1c, // NONCE attribute header
413 0x66, 0x2f, 0x2f, 0x34, // }
414 0x39, 0x39, 0x6b, 0x39, // }
415 0x35, 0x34, 0x64, 0x36, // }
416 0x4f, 0x4c, 0x33, 0x34, // } Nonce value
417 0x6f, 0x4c, 0x39, 0x46, // }
418 0x53, 0x54, 0x76, 0x79, // }
419 0x36, 0x34, 0x73, 0x41, // }
420 0x00, 0x14, 0x00, 0x0b, // REALM attribute header
421 0x65, 0x78, 0x61, 0x6d, // }
422 0x70, 0x6c, 0x65, 0x2e, // } Realm value (11 bytes) and padding (1 byte)
423 0x6f, 0x72, 0x67, 0x00, // }
424 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
425 0xf6, 0x70, 0x24, 0x65, // }
426 0x6d, 0xd6, 0x4a, 0x3e, // }
427 0x02, 0xb8, 0xe0, 0x71, // } HMAC-SHA1 fingerprint
428 0x2e, 0x85, 0xc9, 0xa2, // }
429 0x8c, 0xa8, 0x96, 0x66 // }
430};
431
432// Length parameter is changed to 0x38 from 0x58.
433// AddMessageIntegrity will add MI information and update the length param
434// accordingly.
435static const unsigned char kRfc5769SampleRequestWithoutMI[] = {
436 0x00, 0x01, 0x00, 0x38, // Request type and message length
437 0x21, 0x12, 0xa4, 0x42, // Magic cookie
438 0xb7, 0xe7, 0xa7, 0x01, // }
439 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
440 0xfa, 0x87, 0xdf, 0xae, // }
441 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
442 0x53, 0x54, 0x55, 0x4e, // }
443 0x20, 0x74, 0x65, 0x73, // } User-agent...
444 0x74, 0x20, 0x63, 0x6c, // } ...name
445 0x69, 0x65, 0x6e, 0x74, // }
446 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
447 0x6e, 0x00, 0x01, 0xff, // ICE priority value
448 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
449 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
450 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
451 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
452 0x65, 0x76, 0x74, 0x6a, // }
453 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
454 0x59, 0x20, 0x20, 0x20 // }
455};
456
457// This HMAC differs from the RFC 5769 SampleRequest message. This differs
458// because spec uses 0x20 for the padding where as our implementation uses 0.
459static const unsigned char kCalculatedHmac1[] = {
460 0x79, 0x07, 0xc2, 0xd2, // }
461 0xed, 0xbf, 0xea, 0x48, // }
462 0x0e, 0x4c, 0x76, 0xd8, // } HMAC-SHA1 fingerprint
463 0x29, 0x62, 0xd5, 0xc3, // }
464 0x74, 0x2a, 0xf9, 0xe3 // }
465};
466
Jonas Oreland63737a92019-11-21 15:12:14 +0100467// This truncated HMAC differs from kCalculatedHmac1
468// above since the sum is computed including header
469// and the header is different since the message is shorter
470// than when MESSAGE-INTEGRITY is used.
471static const unsigned char kCalculatedHmac1_32[] = {
472 0xda, 0x39, 0xde, 0x5d, // }
473};
474
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000475// Length parameter is changed to 0x1c from 0x3c.
476// AddMessageIntegrity will add MI information and update the length param
477// accordingly.
478static const unsigned char kRfc5769SampleResponseWithoutMI[] = {
479 0x01, 0x01, 0x00, 0x1c, // Response type and message length
480 0x21, 0x12, 0xa4, 0x42, // Magic cookie
481 0xb7, 0xe7, 0xa7, 0x01, // }
482 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
483 0xfa, 0x87, 0xdf, 0xae, // }
484 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
485 0x74, 0x65, 0x73, 0x74, // }
486 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
487 0x74, 0x6f, 0x72, 0x20, // }
488 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
489 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port
490 0xe1, 0x12, 0xa6, 0x43 // Xor'd mapped IPv4 address
491};
492
493// This HMAC differs from the RFC 5769 SampleResponse message. This differs
494// because spec uses 0x20 for the padding where as our implementation uses 0.
495static const unsigned char kCalculatedHmac2[] = {
496 0x5d, 0x6b, 0x58, 0xbe, // }
497 0xad, 0x94, 0xe0, 0x7e, // }
498 0xef, 0x0d, 0xfc, 0x12, // } HMAC-SHA1 fingerprint
499 0x82, 0xa2, 0xbd, 0x08, // }
500 0x43, 0x14, 0x10, 0x28 // }
501};
502
Jonas Oreland63737a92019-11-21 15:12:14 +0100503// This truncated HMAC differs from kCalculatedHmac2
504// above since the sum is computed including header
505// and the header is different since the message is shorter
506// than when MESSAGE-INTEGRITY is used.
507static const unsigned char kCalculatedHmac2_32[] = {
508 0xe7, 0x5c, 0xd3, 0x16, // }
509};
510
Yves Gerey665174f2018-06-19 15:03:05 +0200511// clang-format on
512
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000513// A transaction ID without the 'magic cookie' portion
514// pjnat's test programs use this transaction ID a lot.
Yves Gerey665174f2018-06-19 15:03:05 +0200515const unsigned char kTestTransactionId1[] = {0x029, 0x01f, 0x0cd, 0x07c,
516 0x0ba, 0x058, 0x0ab, 0x0d7,
517 0x0f2, 0x041, 0x001, 0x000};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000518
519// They use this one sometimes too.
Yves Gerey665174f2018-06-19 15:03:05 +0200520const unsigned char kTestTransactionId2[] = {0x0e3, 0x0a9, 0x046, 0x0e1,
521 0x07c, 0x000, 0x0c2, 0x062,
522 0x054, 0x008, 0x001, 0x000};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000523
Yves Gerey665174f2018-06-19 15:03:05 +0200524const in6_addr kIPv6TestAddress1 = {
525 {{0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, 0x10, 0x00, 0xbe, 0x30, 0x5b, 0xff,
526 0xfe, 0xe5, 0x00, 0xc3}}};
527const in6_addr kIPv6TestAddress2 = {
528 {{0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, 0x10, 0x12, 0x06, 0x0c, 0xce, 0xff,
529 0xfe, 0x1f, 0x61, 0xa4}}};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000530
531#ifdef WEBRTC_POSIX
Yves Gerey665174f2018-06-19 15:03:05 +0200532const in_addr kIPv4TestAddress1 = {0xe64417ac};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000533#elif defined WEBRTC_WIN
534// Windows in_addr has a union with a uchar[] array first.
Yves Gerey665174f2018-06-19 15:03:05 +0200535const in_addr kIPv4TestAddress1 = {{{0x0ac, 0x017, 0x044, 0x0e6}}};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000536#endif
537const char kTestUserName1[] = "abcdefgh";
538const char kTestUserName2[] = "abc";
539const char kTestErrorReason[] = "Unauthorized";
540const int kTestErrorClass = 4;
541const int kTestErrorNumber = 1;
542const int kTestErrorCode = 401;
543
544const int kTestMessagePort1 = 59977;
545const int kTestMessagePort2 = 47233;
546const int kTestMessagePort3 = 56743;
547const int kTestMessagePort4 = 40444;
548
549#define ReadStunMessage(X, Y) ReadStunMessageTestCase(X, Y, sizeof(Y));
550
551// Test that the GetStun*Type and IsStun*Type methods work as expected.
552TEST_F(StunTest, MessageTypes) {
553 EXPECT_EQ(STUN_BINDING_RESPONSE,
Yves Gerey665174f2018-06-19 15:03:05 +0200554 GetStunSuccessResponseType(STUN_BINDING_REQUEST));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000555 EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE,
Yves Gerey665174f2018-06-19 15:03:05 +0200556 GetStunErrorResponseType(STUN_BINDING_REQUEST));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000557 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_INDICATION));
558 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_RESPONSE));
559 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_ERROR_RESPONSE));
560 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_INDICATION));
561 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_RESPONSE));
562 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_ERROR_RESPONSE));
563
Yves Gerey665174f2018-06-19 15:03:05 +0200564 int types[] = {STUN_BINDING_REQUEST, STUN_BINDING_INDICATION,
565 STUN_BINDING_RESPONSE, STUN_BINDING_ERROR_RESPONSE};
tfarina5237aaf2015-11-10 23:44:30 -0800566 for (size_t i = 0; i < arraysize(types); ++i) {
567 EXPECT_EQ(i == 0U, IsStunRequestType(types[i]));
568 EXPECT_EQ(i == 1U, IsStunIndicationType(types[i]));
569 EXPECT_EQ(i == 2U, IsStunSuccessResponseType(types[i]));
570 EXPECT_EQ(i == 3U, IsStunErrorResponseType(types[i]));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000571 EXPECT_EQ(1, types[i] & 0xFEEF);
572 }
573}
574
575TEST_F(StunTest, ReadMessageWithIPv4AddressAttribute) {
576 StunMessage msg;
577 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4MappedAddress);
578 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
579 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
580
581 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
582 rtc::IPAddress test_address(kIPv4TestAddress1);
Yves Gerey665174f2018-06-19 15:03:05 +0200583 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort4,
584 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000585}
586
587TEST_F(StunTest, ReadMessageWithIPv4XorAddressAttribute) {
588 StunMessage msg;
589 StunMessage msg2;
590 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress);
591 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
592 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
593
594 const StunAddressAttribute* addr =
595 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
596 rtc::IPAddress test_address(kIPv4TestAddress1);
Yves Gerey665174f2018-06-19 15:03:05 +0200597 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort3,
598 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000599}
600
601TEST_F(StunTest, ReadMessageWithIPv6AddressAttribute) {
602 StunMessage msg;
603 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
604 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
605 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
606
607 rtc::IPAddress test_address(kIPv6TestAddress1);
608
609 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200610 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort2,
611 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000612}
613
614TEST_F(StunTest, ReadMessageWithInvalidAddressAttribute) {
615 StunMessage msg;
616 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
617 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
618 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
619
620 rtc::IPAddress test_address(kIPv6TestAddress1);
621
622 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200623 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort2,
624 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000625}
626
627TEST_F(StunTest, ReadMessageWithIPv6XorAddressAttribute) {
628 StunMessage msg;
629 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress);
630
631 rtc::IPAddress test_address(kIPv6TestAddress1);
632
633 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
634 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
635
636 const StunAddressAttribute* addr =
637 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200638 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort1,
639 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000640}
641
642// Read the RFC5389 fields from the RFC5769 sample STUN request.
643TEST_F(StunTest, ReadRfc5769RequestMessage) {
644 StunMessage msg;
645 size_t size = ReadStunMessage(&msg, kRfc5769SampleRequest);
646 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
647 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
648 kStunTransactionIdLength);
649
650 const StunByteStringAttribute* software =
651 msg.GetByteString(STUN_ATTR_SOFTWARE);
652 ASSERT_TRUE(software != NULL);
Tommie83500e2022-06-03 14:28:59 +0200653 EXPECT_EQ(kRfc5769SampleMsgClientSoftware, software->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000654
655 const StunByteStringAttribute* username =
656 msg.GetByteString(STUN_ATTR_USERNAME);
657 ASSERT_TRUE(username != NULL);
Tommie83500e2022-06-03 14:28:59 +0200658 EXPECT_EQ(kRfc5769SampleMsgUsername, username->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000659
660 // Actual M-I value checked in a later test.
661 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
662
663 // Fingerprint checked in a later test, but double-check the value here.
Yves Gerey665174f2018-06-19 15:03:05 +0200664 const StunUInt32Attribute* fingerprint = msg.GetUInt32(STUN_ATTR_FINGERPRINT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000665 ASSERT_TRUE(fingerprint != NULL);
666 EXPECT_EQ(0xe57a3bcf, fingerprint->value());
667}
668
669// Read the RFC5389 fields from the RFC5769 sample STUN response.
670TEST_F(StunTest, ReadRfc5769ResponseMessage) {
671 StunMessage msg;
672 size_t size = ReadStunMessage(&msg, kRfc5769SampleResponse);
673 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
674 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
675 kStunTransactionIdLength);
676
677 const StunByteStringAttribute* software =
678 msg.GetByteString(STUN_ATTR_SOFTWARE);
679 ASSERT_TRUE(software != NULL);
Tommie83500e2022-06-03 14:28:59 +0200680 EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000681
682 const StunAddressAttribute* mapped_address =
683 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
684 ASSERT_TRUE(mapped_address != NULL);
685 EXPECT_EQ(kRfc5769SampleMsgMappedAddress, mapped_address->GetAddress());
686
687 // Actual M-I and fingerprint checked in later tests.
688 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
689 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
690}
691
692// Read the RFC5389 fields from the RFC5769 sample STUN response for IPv6.
693TEST_F(StunTest, ReadRfc5769ResponseMessageIPv6) {
694 StunMessage msg;
695 size_t size = ReadStunMessage(&msg, kRfc5769SampleResponseIPv6);
696 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
697 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
698 kStunTransactionIdLength);
699
700 const StunByteStringAttribute* software =
701 msg.GetByteString(STUN_ATTR_SOFTWARE);
702 ASSERT_TRUE(software != NULL);
Tommie83500e2022-06-03 14:28:59 +0200703 EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000704
705 const StunAddressAttribute* mapped_address =
706 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
707 ASSERT_TRUE(mapped_address != NULL);
708 EXPECT_EQ(kRfc5769SampleMsgIPv6MappedAddress, mapped_address->GetAddress());
709
710 // Actual M-I and fingerprint checked in later tests.
711 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
712 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
713}
714
715// Read the RFC5389 fields from the RFC5769 sample STUN response with auth.
716TEST_F(StunTest, ReadRfc5769RequestMessageLongTermAuth) {
717 StunMessage msg;
718 size_t size = ReadStunMessage(&msg, kRfc5769SampleRequestLongTermAuth);
719 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
720 CheckStunTransactionID(msg, kRfc5769SampleMsgWithAuthTransactionId,
721 kStunTransactionIdLength);
722
723 const StunByteStringAttribute* username =
724 msg.GetByteString(STUN_ATTR_USERNAME);
725 ASSERT_TRUE(username != NULL);
Tommie83500e2022-06-03 14:28:59 +0200726 EXPECT_EQ(kRfc5769SampleMsgWithAuthUsername, username->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000727
Yves Gerey665174f2018-06-19 15:03:05 +0200728 const StunByteStringAttribute* nonce = msg.GetByteString(STUN_ATTR_NONCE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000729 ASSERT_TRUE(nonce != NULL);
Tommie83500e2022-06-03 14:28:59 +0200730 EXPECT_EQ(kRfc5769SampleMsgWithAuthNonce, nonce->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000731
Yves Gerey665174f2018-06-19 15:03:05 +0200732 const StunByteStringAttribute* realm = msg.GetByteString(STUN_ATTR_REALM);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000733 ASSERT_TRUE(realm != NULL);
Tommie83500e2022-06-03 14:28:59 +0200734 EXPECT_EQ(kRfc5769SampleMsgWithAuthRealm, realm->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000735
736 // No fingerprint, actual M-I checked in later tests.
737 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
738 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) == NULL);
739}
740
741// The RFC3489 packet in this test is the same as
742// kStunMessageWithIPv4MappedAddress, but with a different value where the
743// magic cookie was.
744TEST_F(StunTest, ReadLegacyMessage) {
745 unsigned char rfc3489_packet[sizeof(kStunMessageWithIPv4MappedAddress)];
746 memcpy(rfc3489_packet, kStunMessageWithIPv4MappedAddress,
Yves Gerey665174f2018-06-19 15:03:05 +0200747 sizeof(kStunMessageWithIPv4MappedAddress));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000748 // Overwrite the magic cookie here.
749 memcpy(&rfc3489_packet[4], "ABCD", 4);
750
751 StunMessage msg;
752 size_t size = ReadStunMessage(&msg, rfc3489_packet);
753 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
754 CheckStunTransactionID(msg, &rfc3489_packet[4], kStunTransactionIdLength + 4);
755
756 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
757 rtc::IPAddress test_address(kIPv4TestAddress1);
Yves Gerey665174f2018-06-19 15:03:05 +0200758 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort4,
759 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000760}
761
762TEST_F(StunTest, SetIPv6XorAddressAttributeOwner) {
763 StunMessage msg;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000764 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress);
765
766 rtc::IPAddress test_address(kIPv6TestAddress1);
767
768 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
769 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
770
771 const StunAddressAttribute* addr =
772 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200773 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort1,
774 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000775
776 // Owner with a different transaction ID.
Tommi408143d2022-06-01 15:29:31 +0200777 StunMessage msg2(STUN_INVALID_MESSAGE_TYPE, "ABCDABCDABCD");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000778 StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL);
779 addr2.SetIP(addr->ipaddr());
780 addr2.SetPort(addr->port());
781 addr2.SetOwner(&msg2);
782 // The internal IP address shouldn't change.
783 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
784
jbauchf1f87202016-03-30 06:43:37 -0700785 rtc::ByteBufferWriter correct_buf;
786 rtc::ByteBufferWriter wrong_buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000787 EXPECT_TRUE(addr->Write(&correct_buf));
788 EXPECT_TRUE(addr2.Write(&wrong_buf));
789 // But when written out, the buffers should look different.
790 ASSERT_NE(0,
791 memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
792 // And when reading a known good value, the address should be wrong.
jbauchf1f87202016-03-30 06:43:37 -0700793 rtc::ByteBufferReader read_buf(correct_buf);
794 addr2.Read(&read_buf);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000795 ASSERT_NE(addr->ipaddr(), addr2.ipaddr());
796 addr2.SetIP(addr->ipaddr());
797 addr2.SetPort(addr->port());
798 // Try writing with no owner at all, should fail and write nothing.
799 addr2.SetOwner(NULL);
800 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
jbauchf1f87202016-03-30 06:43:37 -0700801 wrong_buf.Clear();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000802 EXPECT_FALSE(addr2.Write(&wrong_buf));
803 ASSERT_EQ(0U, wrong_buf.Length());
804}
805
806TEST_F(StunTest, SetIPv4XorAddressAttributeOwner) {
807 // Unlike the IPv6XorAddressAttributeOwner test, IPv4 XOR address attributes
808 // should _not_ be affected by a change in owner. IPv4 XOR address uses the
809 // magic cookie value which is fixed.
810 StunMessage msg;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000811 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress);
812
813 rtc::IPAddress test_address(kIPv4TestAddress1);
814
815 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
816 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
817
818 const StunAddressAttribute* addr =
819 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200820 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort3,
821 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000822
823 // Owner with a different transaction ID.
Tommi408143d2022-06-01 15:29:31 +0200824 StunMessage msg2(STUN_INVALID_MESSAGE_TYPE, "ABCDABCDABCD");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000825 StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL);
826 addr2.SetIP(addr->ipaddr());
827 addr2.SetPort(addr->port());
828 addr2.SetOwner(&msg2);
829 // The internal IP address shouldn't change.
830 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
831
jbauchf1f87202016-03-30 06:43:37 -0700832 rtc::ByteBufferWriter correct_buf;
833 rtc::ByteBufferWriter wrong_buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000834 EXPECT_TRUE(addr->Write(&correct_buf));
835 EXPECT_TRUE(addr2.Write(&wrong_buf));
836 // The same address data should be written.
837 ASSERT_EQ(0,
838 memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
839 // And an attribute should be able to un-XOR an address belonging to a message
840 // with a different transaction ID.
jbauchf1f87202016-03-30 06:43:37 -0700841 rtc::ByteBufferReader read_buf(correct_buf);
842 EXPECT_TRUE(addr2.Read(&read_buf));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000843 ASSERT_EQ(addr->ipaddr(), addr2.ipaddr());
844
845 // However, no owner is still an error, should fail and write nothing.
846 addr2.SetOwner(NULL);
847 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
jbauchf1f87202016-03-30 06:43:37 -0700848 wrong_buf.Clear();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000849 EXPECT_FALSE(addr2.Write(&wrong_buf));
850}
851
852TEST_F(StunTest, CreateIPv6AddressAttribute) {
853 rtc::IPAddress test_ip(kIPv6TestAddress2);
854
zsteinf42cc9d2017-03-27 16:17:19 -0700855 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000856 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
857 addr->SetAddress(test_addr);
858
zsteinf42cc9d2017-03-27 16:17:19 -0700859 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6, kTestMessagePort2,
860 test_ip);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000861}
862
863TEST_F(StunTest, CreateIPv4AddressAttribute) {
864 struct in_addr test_in_addr;
865 test_in_addr.s_addr = 0xBEB0B0BE;
866 rtc::IPAddress test_ip(test_in_addr);
867
zsteinf42cc9d2017-03-27 16:17:19 -0700868 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000869 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
870 addr->SetAddress(test_addr);
871
zsteinf42cc9d2017-03-27 16:17:19 -0700872 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV4, kTestMessagePort2,
873 test_ip);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000874}
875
876// Test that we don't care what order we set the parts of an address
877TEST_F(StunTest, CreateAddressInArbitraryOrder) {
zsteinf42cc9d2017-03-27 16:17:19 -0700878 auto addr = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000879 // Port first
880 addr->SetPort(kTestMessagePort1);
881 addr->SetIP(rtc::IPAddress(kIPv4TestAddress1));
882 ASSERT_EQ(kTestMessagePort1, addr->port());
883 ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr->ipaddr());
884
zsteinf42cc9d2017-03-27 16:17:19 -0700885 auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000886 // IP first
887 addr2->SetIP(rtc::IPAddress(kIPv4TestAddress1));
888 addr2->SetPort(kTestMessagePort2);
889 ASSERT_EQ(kTestMessagePort2, addr2->port());
890 ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr2->ipaddr());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000891}
892
893TEST_F(StunTest, WriteMessageWithIPv6AddressAttribute) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000894 size_t size = sizeof(kStunMessageWithIPv6MappedAddress);
895
896 rtc::IPAddress test_ip(kIPv6TestAddress1);
897
Tommi408143d2022-06-01 15:29:31 +0200898 StunMessage msg(
899 STUN_BINDING_REQUEST,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000900 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
901 kStunTransactionIdLength));
902 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
903
zsteinf42cc9d2017-03-27 16:17:19 -0700904 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000905 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
906 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700907 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000908
909 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
910
jbauchf1f87202016-03-30 06:43:37 -0700911 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000912 EXPECT_TRUE(msg.Write(&out));
913 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6MappedAddress));
914 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700915 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000916 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700917 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000918 ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv6MappedAddress, len1));
919}
920
921TEST_F(StunTest, WriteMessageWithIPv4AddressAttribute) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000922 size_t size = sizeof(kStunMessageWithIPv4MappedAddress);
923
924 rtc::IPAddress test_ip(kIPv4TestAddress1);
925
Tommi408143d2022-06-01 15:29:31 +0200926 StunMessage msg(
927 STUN_BINDING_RESPONSE,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000928 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
929 kStunTransactionIdLength));
930 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
931
zsteinf42cc9d2017-03-27 16:17:19 -0700932 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000933 rtc::SocketAddress test_addr(test_ip, kTestMessagePort4);
934 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700935 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000936
937 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
938
jbauchf1f87202016-03-30 06:43:37 -0700939 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000940 EXPECT_TRUE(msg.Write(&out));
941 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4MappedAddress));
942 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700943 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000944 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700945 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000946 ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv4MappedAddress, len1));
947}
948
949TEST_F(StunTest, WriteMessageWithIPv6XorAddressAttribute) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000950 size_t size = sizeof(kStunMessageWithIPv6XorMappedAddress);
951
952 rtc::IPAddress test_ip(kIPv6TestAddress1);
953
Tommi408143d2022-06-01 15:29:31 +0200954 StunMessage msg(
955 STUN_BINDING_RESPONSE,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000956 std::string(reinterpret_cast<const char*>(kTestTransactionId2),
957 kStunTransactionIdLength));
958 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
959
zsteinf42cc9d2017-03-27 16:17:19 -0700960 auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000961 rtc::SocketAddress test_addr(test_ip, kTestMessagePort1);
962 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700963 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000964
965 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
966
jbauchf1f87202016-03-30 06:43:37 -0700967 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000968 EXPECT_TRUE(msg.Write(&out));
969 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6XorMappedAddress));
970 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700971 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000972 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700973 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000974 ASSERT_EQ(0,
975 memcmp(bytes.c_str(), kStunMessageWithIPv6XorMappedAddress, len1));
976}
977
978TEST_F(StunTest, WriteMessageWithIPv4XoreAddressAttribute) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000979 size_t size = sizeof(kStunMessageWithIPv4XorMappedAddress);
980
981 rtc::IPAddress test_ip(kIPv4TestAddress1);
982
Tommi408143d2022-06-01 15:29:31 +0200983 StunMessage msg(
984 STUN_BINDING_RESPONSE,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000985 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
986 kStunTransactionIdLength));
987 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
988
zsteinf42cc9d2017-03-27 16:17:19 -0700989 auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000990 rtc::SocketAddress test_addr(test_ip, kTestMessagePort3);
991 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700992 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000993
994 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
995
jbauchf1f87202016-03-30 06:43:37 -0700996 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000997 EXPECT_TRUE(msg.Write(&out));
998 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4XorMappedAddress));
999 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -07001000 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001001 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -07001002 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001003 ASSERT_EQ(0,
1004 memcmp(bytes.c_str(), kStunMessageWithIPv4XorMappedAddress, len1));
1005}
1006
1007TEST_F(StunTest, ReadByteStringAttribute) {
1008 StunMessage msg;
1009 size_t size = ReadStunMessage(&msg, kStunMessageWithByteStringAttribute);
1010
1011 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1012 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
1013 const StunByteStringAttribute* username =
1014 msg.GetByteString(STUN_ATTR_USERNAME);
1015 ASSERT_TRUE(username != NULL);
Tommie83500e2022-06-03 14:28:59 +02001016 EXPECT_EQ(kTestUserName1, username->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001017}
1018
1019TEST_F(StunTest, ReadPaddedByteStringAttribute) {
1020 StunMessage msg;
Yves Gerey665174f2018-06-19 15:03:05 +02001021 size_t size =
1022 ReadStunMessage(&msg, kStunMessageWithPaddedByteStringAttribute);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001023 ASSERT_NE(0U, size);
1024 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1025 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
1026 const StunByteStringAttribute* username =
1027 msg.GetByteString(STUN_ATTR_USERNAME);
1028 ASSERT_TRUE(username != NULL);
Tommie83500e2022-06-03 14:28:59 +02001029 EXPECT_EQ(kTestUserName2, username->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001030}
1031
1032TEST_F(StunTest, ReadErrorCodeAttribute) {
1033 StunMessage msg;
1034 size_t size = ReadStunMessage(&msg, kStunMessageWithErrorAttribute);
1035
1036 CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, size);
1037 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
1038 const StunErrorCodeAttribute* errorcode = msg.GetErrorCode();
1039 ASSERT_TRUE(errorcode != NULL);
1040 EXPECT_EQ(kTestErrorClass, errorcode->eclass());
1041 EXPECT_EQ(kTestErrorNumber, errorcode->number());
1042 EXPECT_EQ(kTestErrorReason, errorcode->reason());
1043 EXPECT_EQ(kTestErrorCode, errorcode->code());
deadbeef996fc6b2017-04-26 09:21:22 -07001044 EXPECT_EQ(kTestErrorCode, msg.GetErrorCodeValue());
1045}
1046
1047// Test that GetErrorCodeValue returns STUN_ERROR_GLOBAL_FAILURE if the message
1048// in question doesn't have an error code attribute, rather than crashing.
1049TEST_F(StunTest, GetErrorCodeValueWithNoErrorAttribute) {
1050 StunMessage msg;
1051 ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
1052 EXPECT_EQ(STUN_ERROR_GLOBAL_FAILURE, msg.GetErrorCodeValue());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001053}
1054
1055TEST_F(StunTest, ReadMessageWithAUInt16ListAttribute) {
1056 StunMessage msg;
1057 size_t size = ReadStunMessage(&msg, kStunMessageWithUInt16ListAttribute);
1058 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1059 const StunUInt16ListAttribute* types = msg.GetUnknownAttributes();
1060 ASSERT_TRUE(types != NULL);
1061 EXPECT_EQ(3U, types->Size());
1062 EXPECT_EQ(0x1U, types->GetType(0));
1063 EXPECT_EQ(0x1000U, types->GetType(1));
1064 EXPECT_EQ(0xAB0CU, types->GetType(2));
1065}
1066
1067TEST_F(StunTest, ReadMessageWithAnUnknownAttribute) {
1068 StunMessage msg;
1069 size_t size = ReadStunMessage(&msg, kStunMessageWithUnknownAttribute);
1070 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1071
1072 // Parsing should have succeeded and there should be a USERNAME attribute
1073 const StunByteStringAttribute* username =
1074 msg.GetByteString(STUN_ATTR_USERNAME);
1075 ASSERT_TRUE(username != NULL);
Tommie83500e2022-06-03 14:28:59 +02001076 EXPECT_EQ(kTestUserName2, username->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001077}
1078
1079TEST_F(StunTest, WriteMessageWithAnErrorCodeAttribute) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001080 size_t size = sizeof(kStunMessageWithErrorAttribute);
1081
Tommi408143d2022-06-01 15:29:31 +02001082 StunMessage msg(
1083 STUN_BINDING_ERROR_RESPONSE,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001084 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
1085 kStunTransactionIdLength));
1086 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
zsteinf42cc9d2017-03-27 16:17:19 -07001087 auto errorcode = StunAttribute::CreateErrorCode();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001088 errorcode->SetCode(kTestErrorCode);
1089 errorcode->SetReason(kTestErrorReason);
zsteinf42cc9d2017-03-27 16:17:19 -07001090 msg.AddAttribute(std::move(errorcode));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001091 CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, (size - 20));
1092
jbauchf1f87202016-03-30 06:43:37 -07001093 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001094 EXPECT_TRUE(msg.Write(&out));
1095 ASSERT_EQ(size, out.Length());
1096 // No padding.
1097 ASSERT_EQ(0, memcmp(out.Data(), kStunMessageWithErrorAttribute, size));
1098}
1099
1100TEST_F(StunTest, WriteMessageWithAUInt16ListAttribute) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001101 size_t size = sizeof(kStunMessageWithUInt16ListAttribute);
1102
Tommi408143d2022-06-01 15:29:31 +02001103 StunMessage msg(
1104 STUN_BINDING_REQUEST,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001105 std::string(reinterpret_cast<const char*>(kTestTransactionId2),
1106 kStunTransactionIdLength));
1107 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
zsteinf42cc9d2017-03-27 16:17:19 -07001108 auto list = StunAttribute::CreateUnknownAttributes();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001109 list->AddType(0x1U);
1110 list->AddType(0x1000U);
1111 list->AddType(0xAB0CU);
zsteinf42cc9d2017-03-27 16:17:19 -07001112 msg.AddAttribute(std::move(list));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001113 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
1114
jbauchf1f87202016-03-30 06:43:37 -07001115 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001116 EXPECT_TRUE(msg.Write(&out));
1117 ASSERT_EQ(size, out.Length());
1118 // Check everything up to the padding.
1119 ASSERT_EQ(0,
1120 memcmp(out.Data(), kStunMessageWithUInt16ListAttribute, size - 2));
1121}
1122
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001123// Test that we fail to read messages with invalid lengths.
1124void CheckFailureToRead(const unsigned char* testcase, size_t length) {
1125 StunMessage msg;
1126 const char* input = reinterpret_cast<const char*>(testcase);
jbauchf1f87202016-03-30 06:43:37 -07001127 rtc::ByteBufferReader buf(input, length);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001128 ASSERT_FALSE(msg.Read(&buf));
1129}
1130
1131TEST_F(StunTest, FailToReadInvalidMessages) {
1132 CheckFailureToRead(kStunMessageWithZeroLength,
1133 kRealLengthOfInvalidLengthTestCases);
1134 CheckFailureToRead(kStunMessageWithSmallLength,
1135 kRealLengthOfInvalidLengthTestCases);
1136 CheckFailureToRead(kStunMessageWithExcessLength,
1137 kRealLengthOfInvalidLengthTestCases);
1138}
1139
1140// Test that we properly fail to read a non-STUN message.
1141TEST_F(StunTest, FailToReadRtcpPacket) {
1142 CheckFailureToRead(kRtcpPacket, sizeof(kRtcpPacket));
1143}
1144
1145// Check our STUN message validation code against the RFC5769 test messages.
1146TEST_F(StunTest, ValidateMessageIntegrity) {
1147 // Try the messages from RFC 5769.
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001148 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001149 reinterpret_cast<const char*>(kRfc5769SampleRequest),
Yves Gerey665174f2018-06-19 15:03:05 +02001150 sizeof(kRfc5769SampleRequest), kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001151 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001152 reinterpret_cast<const char*>(kRfc5769SampleRequest),
Yves Gerey665174f2018-06-19 15:03:05 +02001153 sizeof(kRfc5769SampleRequest), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001154
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001155 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001156 reinterpret_cast<const char*>(kRfc5769SampleResponse),
Yves Gerey665174f2018-06-19 15:03:05 +02001157 sizeof(kRfc5769SampleResponse), kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001158 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001159 reinterpret_cast<const char*>(kRfc5769SampleResponse),
Yves Gerey665174f2018-06-19 15:03:05 +02001160 sizeof(kRfc5769SampleResponse), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001161
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001162 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001163 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
Yves Gerey665174f2018-06-19 15:03:05 +02001164 sizeof(kRfc5769SampleResponseIPv6), kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001165 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001166 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
Yves Gerey665174f2018-06-19 15:03:05 +02001167 sizeof(kRfc5769SampleResponseIPv6), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001168
1169 // We first need to compute the key for the long-term authentication HMAC.
1170 std::string key;
1171 ComputeStunCredentialHash(kRfc5769SampleMsgWithAuthUsername,
Yves Gerey665174f2018-06-19 15:03:05 +02001172 kRfc5769SampleMsgWithAuthRealm,
1173 kRfc5769SampleMsgWithAuthPassword, &key);
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001174 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001175 reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth),
1176 sizeof(kRfc5769SampleRequestLongTermAuth), key));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001177 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001178 reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth),
Yves Gerey665174f2018-06-19 15:03:05 +02001179 sizeof(kRfc5769SampleRequestLongTermAuth), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001180
1181 // Try some edge cases.
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001182 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001183 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
Yves Gerey665174f2018-06-19 15:03:05 +02001184 sizeof(kStunMessageWithZeroLength), kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001185 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001186 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
Yves Gerey665174f2018-06-19 15:03:05 +02001187 sizeof(kStunMessageWithExcessLength), kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001188 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001189 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
Yves Gerey665174f2018-06-19 15:03:05 +02001190 sizeof(kStunMessageWithSmallLength), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001191
katrielc1a206102016-06-20 05:13:16 -07001192 // Again, but with the lengths matching what is claimed in the headers.
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001193 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
katrielc1a206102016-06-20 05:13:16 -07001194 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1195 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithZeroLength[2]),
1196 kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001197 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
katrielc1a206102016-06-20 05:13:16 -07001198 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1199 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithExcessLength[2]),
1200 kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001201 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
katrielc1a206102016-06-20 05:13:16 -07001202 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1203 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithSmallLength[2]),
1204 kRfc5769SampleMsgPassword));
1205
1206 // Check that a too-short HMAC doesn't cause buffer overflow.
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001207 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
katrielc1a206102016-06-20 05:13:16 -07001208 reinterpret_cast<const char*>(kStunMessageWithBadHmacAtEnd),
Yves Gerey665174f2018-06-19 15:03:05 +02001209 sizeof(kStunMessageWithBadHmacAtEnd), kRfc5769SampleMsgPassword));
katrielc1a206102016-06-20 05:13:16 -07001210
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001211 // Test that munging a single bit anywhere in the message causes the
1212 // message-integrity check to fail, unless it is after the M-I attribute.
1213 char buf[sizeof(kRfc5769SampleRequest)];
1214 memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest));
1215 for (size_t i = 0; i < sizeof(buf); ++i) {
1216 buf[i] ^= 0x01;
1217 if (i > 0)
1218 buf[i - 1] ^= 0x01;
Yves Gerey665174f2018-06-19 15:03:05 +02001219 EXPECT_EQ(i >= sizeof(buf) - 8,
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001220 StunMessage::ValidateMessageIntegrityForTesting(
1221 buf, sizeof(buf), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001222 }
1223}
1224
1225// Validate that we generate correct MESSAGE-INTEGRITY attributes.
1226// Note the use of IceMessage instead of StunMessage; this is necessary because
1227// the RFC5769 test messages used include attributes not found in basic STUN.
1228TEST_F(StunTest, AddMessageIntegrity) {
1229 IceMessage msg;
jbauchf1f87202016-03-30 06:43:37 -07001230 rtc::ByteBufferReader buf(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001231 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1232 sizeof(kRfc5769SampleRequestWithoutMI));
1233 EXPECT_TRUE(msg.Read(&buf));
1234 EXPECT_TRUE(msg.AddMessageIntegrity(kRfc5769SampleMsgPassword));
1235 const StunByteStringAttribute* mi_attr =
1236 msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
1237 EXPECT_EQ(20U, mi_attr->length());
Yves Gerey665174f2018-06-19 15:03:05 +02001238 EXPECT_EQ(
1239 0, memcmp(mi_attr->bytes(), kCalculatedHmac1, sizeof(kCalculatedHmac1)));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001240
jbauchf1f87202016-03-30 06:43:37 -07001241 rtc::ByteBufferWriter buf1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001242 EXPECT_TRUE(msg.Write(&buf1));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001243 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
Yves Gerey665174f2018-06-19 15:03:05 +02001244 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(),
1245 kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001246
1247 IceMessage msg2;
jbauchf1f87202016-03-30 06:43:37 -07001248 rtc::ByteBufferReader buf2(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001249 reinterpret_cast<const char*>(kRfc5769SampleResponseWithoutMI),
1250 sizeof(kRfc5769SampleResponseWithoutMI));
1251 EXPECT_TRUE(msg2.Read(&buf2));
1252 EXPECT_TRUE(msg2.AddMessageIntegrity(kRfc5769SampleMsgPassword));
1253 const StunByteStringAttribute* mi_attr2 =
1254 msg2.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
1255 EXPECT_EQ(20U, mi_attr2->length());
1256 EXPECT_EQ(
1257 0, memcmp(mi_attr2->bytes(), kCalculatedHmac2, sizeof(kCalculatedHmac2)));
1258
jbauchf1f87202016-03-30 06:43:37 -07001259 rtc::ByteBufferWriter buf3;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001260 EXPECT_TRUE(msg2.Write(&buf3));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001261 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
Yves Gerey665174f2018-06-19 15:03:05 +02001262 reinterpret_cast<const char*>(buf3.Data()), buf3.Length(),
1263 kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001264}
1265
1266// Check our STUN message validation code against the RFC5769 test messages.
Jonas Oreland63737a92019-11-21 15:12:14 +01001267TEST_F(StunTest, ValidateMessageIntegrity32) {
1268 // Try the messages from RFC 5769.
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001269 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001270 reinterpret_cast<const char*>(kSampleRequestMI32),
1271 sizeof(kSampleRequestMI32), kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001272 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001273 reinterpret_cast<const char*>(kSampleRequestMI32),
1274 sizeof(kSampleRequestMI32), "InvalidPassword"));
1275
1276 // Try some edge cases.
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001277 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001278 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1279 sizeof(kStunMessageWithZeroLength), kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001280 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001281 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1282 sizeof(kStunMessageWithExcessLength), kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001283 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001284 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1285 sizeof(kStunMessageWithSmallLength), kRfc5769SampleMsgPassword));
1286
1287 // Again, but with the lengths matching what is claimed in the headers.
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001288 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001289 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1290 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithZeroLength[2]),
1291 kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001292 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001293 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1294 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithExcessLength[2]),
1295 kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001296 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001297 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1298 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithSmallLength[2]),
1299 kRfc5769SampleMsgPassword));
1300
1301 // Check that a too-short HMAC doesn't cause buffer overflow.
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001302 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001303 reinterpret_cast<const char*>(kStunMessageWithBadHmacAtEnd),
1304 sizeof(kStunMessageWithBadHmacAtEnd), kRfc5769SampleMsgPassword));
1305
1306 // Test that munging a single bit anywhere in the message causes the
1307 // message-integrity check to fail, unless it is after the M-I attribute.
1308 char buf[sizeof(kSampleRequestMI32)];
1309 memcpy(buf, kSampleRequestMI32, sizeof(kSampleRequestMI32));
1310 for (size_t i = 0; i < sizeof(buf); ++i) {
1311 buf[i] ^= 0x01;
1312 if (i > 0)
1313 buf[i - 1] ^= 0x01;
1314 EXPECT_EQ(i >= sizeof(buf) - 8,
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001315 StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001316 buf, sizeof(buf), kRfc5769SampleMsgPassword));
1317 }
1318}
1319
1320// Validate that we generate correct MESSAGE-INTEGRITY-32 attributes.
1321TEST_F(StunTest, AddMessageIntegrity32) {
1322 IceMessage msg;
1323 rtc::ByteBufferReader buf(
1324 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1325 sizeof(kRfc5769SampleRequestWithoutMI));
1326 EXPECT_TRUE(msg.Read(&buf));
1327 EXPECT_TRUE(msg.AddMessageIntegrity32(kRfc5769SampleMsgPassword));
1328 const StunByteStringAttribute* mi_attr =
1329 msg.GetByteString(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32);
1330 EXPECT_EQ(4U, mi_attr->length());
1331 EXPECT_EQ(0, memcmp(mi_attr->bytes(), kCalculatedHmac1_32,
1332 sizeof(kCalculatedHmac1_32)));
1333
1334 rtc::ByteBufferWriter buf1;
1335 EXPECT_TRUE(msg.Write(&buf1));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001336 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001337 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(),
1338 kRfc5769SampleMsgPassword));
1339
1340 IceMessage msg2;
1341 rtc::ByteBufferReader buf2(
1342 reinterpret_cast<const char*>(kRfc5769SampleResponseWithoutMI),
1343 sizeof(kRfc5769SampleResponseWithoutMI));
1344 EXPECT_TRUE(msg2.Read(&buf2));
1345 EXPECT_TRUE(msg2.AddMessageIntegrity32(kRfc5769SampleMsgPassword));
1346 const StunByteStringAttribute* mi_attr2 =
1347 msg2.GetByteString(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32);
1348 EXPECT_EQ(4U, mi_attr2->length());
1349 EXPECT_EQ(0, memcmp(mi_attr2->bytes(), kCalculatedHmac2_32,
1350 sizeof(kCalculatedHmac2_32)));
1351
1352 rtc::ByteBufferWriter buf3;
1353 EXPECT_TRUE(msg2.Write(&buf3));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001354 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001355 reinterpret_cast<const char*>(buf3.Data()), buf3.Length(),
1356 kRfc5769SampleMsgPassword));
1357}
1358
1359// Validate that the message validates if both MESSAGE-INTEGRITY-32 and
1360// MESSAGE-INTEGRITY are present in the message.
1361// This is not expected to be used, but is not forbidden.
1362TEST_F(StunTest, AddMessageIntegrity32AndMessageIntegrity) {
1363 IceMessage msg;
1364 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1365 attr->CopyBytes("keso", sizeof("keso"));
1366 msg.AddAttribute(std::move(attr));
1367 msg.AddMessageIntegrity32("password1");
1368 msg.AddMessageIntegrity("password2");
1369
1370 rtc::ByteBufferWriter buf1;
1371 EXPECT_TRUE(msg.Write(&buf1));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001372 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001373 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password1"));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001374 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001375 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password2"));
1376
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001377 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001378 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password2"));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001379 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001380 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password1"));
1381}
1382
1383// Check our STUN message validation code against the RFC5769 test messages.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001384TEST_F(StunTest, ValidateFingerprint) {
1385 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1386 reinterpret_cast<const char*>(kRfc5769SampleRequest),
1387 sizeof(kRfc5769SampleRequest)));
1388 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1389 reinterpret_cast<const char*>(kRfc5769SampleResponse),
1390 sizeof(kRfc5769SampleResponse)));
1391 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1392 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
1393 sizeof(kRfc5769SampleResponseIPv6)));
1394
1395 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1396 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1397 sizeof(kStunMessageWithZeroLength)));
1398 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1399 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1400 sizeof(kStunMessageWithExcessLength)));
1401 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1402 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1403 sizeof(kStunMessageWithSmallLength)));
1404
1405 // Test that munging a single bit anywhere in the message causes the
1406 // fingerprint check to fail.
1407 char buf[sizeof(kRfc5769SampleRequest)];
1408 memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest));
1409 for (size_t i = 0; i < sizeof(buf); ++i) {
1410 buf[i] ^= 0x01;
1411 if (i > 0)
1412 buf[i - 1] ^= 0x01;
1413 EXPECT_FALSE(StunMessage::ValidateFingerprint(buf, sizeof(buf)));
1414 }
1415 // Put them all back to normal and the check should pass again.
1416 buf[sizeof(buf) - 1] ^= 0x01;
1417 EXPECT_TRUE(StunMessage::ValidateFingerprint(buf, sizeof(buf)));
1418}
1419
1420TEST_F(StunTest, AddFingerprint) {
1421 IceMessage msg;
jbauchf1f87202016-03-30 06:43:37 -07001422 rtc::ByteBufferReader buf(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001423 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1424 sizeof(kRfc5769SampleRequestWithoutMI));
1425 EXPECT_TRUE(msg.Read(&buf));
1426 EXPECT_TRUE(msg.AddFingerprint());
1427
jbauchf1f87202016-03-30 06:43:37 -07001428 rtc::ByteBufferWriter buf1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001429 EXPECT_TRUE(msg.Write(&buf1));
1430 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1431 reinterpret_cast<const char*>(buf1.Data()), buf1.Length()));
1432}
1433
1434// Sample "GTURN" relay message.
Yves Gerey665174f2018-06-19 15:03:05 +02001435// clang-format off
1436// clang formatting doesn't respect inline comments.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001437static const unsigned char kRelayMessage[] = {
1438 0x00, 0x01, 0x00, 88, // message header
1439 0x21, 0x12, 0xA4, 0x42, // magic cookie
1440 '0', '1', '2', '3', // transaction id
1441 '4', '5', '6', '7',
1442 '8', '9', 'a', 'b',
1443 0x00, 0x01, 0x00, 8, // mapped address
1444 0x00, 0x01, 0x00, 13,
1445 0x00, 0x00, 0x00, 17,
1446 0x00, 0x06, 0x00, 12, // username
1447 'a', 'b', 'c', 'd',
1448 'e', 'f', 'g', 'h',
1449 'i', 'j', 'k', 'l',
1450 0x00, 0x0d, 0x00, 4, // lifetime
1451 0x00, 0x00, 0x00, 11,
1452 0x00, 0x0f, 0x00, 4, // magic cookie
1453 0x72, 0xc6, 0x4b, 0xc6,
1454 0x00, 0x10, 0x00, 4, // bandwidth
1455 0x00, 0x00, 0x00, 6,
1456 0x00, 0x11, 0x00, 8, // destination address
1457 0x00, 0x01, 0x00, 13,
1458 0x00, 0x00, 0x00, 17,
1459 0x00, 0x12, 0x00, 8, // source address 2
1460 0x00, 0x01, 0x00, 13,
1461 0x00, 0x00, 0x00, 17,
1462 0x00, 0x13, 0x00, 7, // data
1463 'a', 'b', 'c', 'd',
1464 'e', 'f', 'g', 0 // DATA must be padded per rfc5766.
1465};
Yves Gerey665174f2018-06-19 15:03:05 +02001466// clang-format on
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001467
1468// Test that we can read the GTURN-specific fields.
1469TEST_F(StunTest, ReadRelayMessage) {
Tommi408143d2022-06-01 15:29:31 +02001470 RelayMessage msg;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001471
1472 const char* input = reinterpret_cast<const char*>(kRelayMessage);
1473 size_t size = sizeof(kRelayMessage);
jbauchf1f87202016-03-30 06:43:37 -07001474 rtc::ByteBufferReader buf(input, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001475 EXPECT_TRUE(msg.Read(&buf));
1476
1477 EXPECT_EQ(STUN_BINDING_REQUEST, msg.type());
1478 EXPECT_EQ(size - 20, msg.length());
1479 EXPECT_EQ("0123456789ab", msg.transaction_id());
1480
Tommi408143d2022-06-01 15:29:31 +02001481 RelayMessage msg2(STUN_BINDING_REQUEST, "0123456789ab");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001482
1483 in_addr legacy_in_addr;
1484 legacy_in_addr.s_addr = htonl(17U);
1485 rtc::IPAddress legacy_ip(legacy_in_addr);
1486
1487 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
1488 ASSERT_TRUE(addr != NULL);
1489 EXPECT_EQ(1, addr->family());
1490 EXPECT_EQ(13, addr->port());
1491 EXPECT_EQ(legacy_ip, addr->ipaddr());
1492
zsteinf42cc9d2017-03-27 16:17:19 -07001493 auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001494 addr2->SetPort(13);
1495 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001496 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001497
1498 const StunByteStringAttribute* bytes = msg.GetByteString(STUN_ATTR_USERNAME);
1499 ASSERT_TRUE(bytes != NULL);
1500 EXPECT_EQ(12U, bytes->length());
Tommie83500e2022-06-03 14:28:59 +02001501 EXPECT_EQ("abcdefghijkl", bytes->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001502
zsteinf42cc9d2017-03-27 16:17:19 -07001503 auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001504 bytes2->CopyBytes("abcdefghijkl");
zsteinf42cc9d2017-03-27 16:17:19 -07001505 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001506
1507 const StunUInt32Attribute* uval = msg.GetUInt32(STUN_ATTR_LIFETIME);
1508 ASSERT_TRUE(uval != NULL);
1509 EXPECT_EQ(11U, uval->value());
1510
zsteinf42cc9d2017-03-27 16:17:19 -07001511 auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001512 uval2->SetValue(11);
zsteinf42cc9d2017-03-27 16:17:19 -07001513 msg2.AddAttribute(std::move(uval2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001514
1515 bytes = msg.GetByteString(STUN_ATTR_MAGIC_COOKIE);
1516 ASSERT_TRUE(bytes != NULL);
1517 EXPECT_EQ(4U, bytes->length());
Yves Gerey665174f2018-06-19 15:03:05 +02001518 EXPECT_EQ(0, memcmp(bytes->bytes(), TURN_MAGIC_COOKIE_VALUE,
1519 sizeof(TURN_MAGIC_COOKIE_VALUE)));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001520
1521 bytes2 = StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
1522 bytes2->CopyBytes(reinterpret_cast<const char*>(TURN_MAGIC_COOKIE_VALUE),
1523 sizeof(TURN_MAGIC_COOKIE_VALUE));
zsteinf42cc9d2017-03-27 16:17:19 -07001524 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001525
1526 uval = msg.GetUInt32(STUN_ATTR_BANDWIDTH);
1527 ASSERT_TRUE(uval != NULL);
1528 EXPECT_EQ(6U, uval->value());
1529
1530 uval2 = StunAttribute::CreateUInt32(STUN_ATTR_BANDWIDTH);
1531 uval2->SetValue(6);
zsteinf42cc9d2017-03-27 16:17:19 -07001532 msg2.AddAttribute(std::move(uval2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001533
1534 addr = msg.GetAddress(STUN_ATTR_DESTINATION_ADDRESS);
1535 ASSERT_TRUE(addr != NULL);
1536 EXPECT_EQ(1, addr->family());
1537 EXPECT_EQ(13, addr->port());
1538 EXPECT_EQ(legacy_ip, addr->ipaddr());
1539
1540 addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
1541 addr2->SetPort(13);
1542 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001543 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001544
1545 addr = msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2);
1546 ASSERT_TRUE(addr != NULL);
1547 EXPECT_EQ(1, addr->family());
1548 EXPECT_EQ(13, addr->port());
1549 EXPECT_EQ(legacy_ip, addr->ipaddr());
1550
1551 addr2 = StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2);
1552 addr2->SetPort(13);
1553 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001554 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001555
1556 bytes = msg.GetByteString(STUN_ATTR_DATA);
1557 ASSERT_TRUE(bytes != NULL);
1558 EXPECT_EQ(7U, bytes->length());
Tommie83500e2022-06-03 14:28:59 +02001559 EXPECT_EQ("abcdefg", bytes->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001560
1561 bytes2 = StunAttribute::CreateByteString(STUN_ATTR_DATA);
1562 bytes2->CopyBytes("abcdefg");
zsteinf42cc9d2017-03-27 16:17:19 -07001563 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001564
jbauchf1f87202016-03-30 06:43:37 -07001565 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001566 EXPECT_TRUE(msg.Write(&out));
1567 EXPECT_EQ(size, out.Length());
1568 size_t len1 = out.Length();
jbauchf1f87202016-03-30 06:43:37 -07001569 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001570 std::string outstring;
jbauchf1f87202016-03-30 06:43:37 -07001571 read_buf.ReadString(&outstring, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001572 EXPECT_EQ(0, memcmp(outstring.c_str(), input, len1));
1573
jbauchf1f87202016-03-30 06:43:37 -07001574 rtc::ByteBufferWriter out2;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001575 EXPECT_TRUE(msg2.Write(&out2));
1576 EXPECT_EQ(size, out2.Length());
1577 size_t len2 = out2.Length();
jbauchf1f87202016-03-30 06:43:37 -07001578 rtc::ByteBufferReader read_buf2(out2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001579 std::string outstring2;
jbauchf1f87202016-03-30 06:43:37 -07001580 read_buf2.ReadString(&outstring2, len2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001581 EXPECT_EQ(0, memcmp(outstring2.c_str(), input, len2));
1582}
1583
Jonas Oreland202994c2017-12-18 12:10:43 +01001584// Test that we can remove attribute from a message.
1585TEST_F(StunTest, RemoveAttribute) {
1586 StunMessage msg;
1587
1588 // Removing something that does exist should return nullptr.
1589 EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr);
1590
1591 {
1592 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1593 attr->CopyBytes("kes", sizeof("kes"));
1594 msg.AddAttribute(std::move(attr));
1595 }
1596
1597 size_t len = msg.length();
1598 {
1599 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1600 ASSERT_NE(attr, nullptr);
1601 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1602 EXPECT_STREQ("kes",
1603 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1604 EXPECT_LT(msg.length(), len);
1605 }
1606
1607 // Now add same attribute type twice.
1608 {
1609 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1610 attr->CopyBytes("kes", sizeof("kes"));
1611 msg.AddAttribute(std::move(attr));
1612 }
1613
1614 {
1615 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1616 attr->CopyBytes("kenta", sizeof("kenta"));
1617 msg.AddAttribute(std::move(attr));
1618 }
1619
1620 // Remove should remove the last added occurrence.
1621 {
1622 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1623 ASSERT_NE(attr, nullptr);
1624 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1625 EXPECT_STREQ("kenta",
1626 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1627 }
1628
1629 // Remove should remove the last added occurrence.
1630 {
1631 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1632 ASSERT_NE(attr, nullptr);
1633 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1634 EXPECT_STREQ("kes",
1635 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1636 }
1637
1638 // Removing something that does exist should return nullptr.
1639 EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr);
1640}
1641
Jonas Oreland63737a92019-11-21 15:12:14 +01001642// Test that we can remove attribute from a message.
1643TEST_F(StunTest, ClearAttributes) {
1644 StunMessage msg;
1645
1646 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1647 attr->CopyBytes("kes", sizeof("kes"));
1648 msg.AddAttribute(std::move(attr));
1649 size_t len = msg.length();
1650
1651 msg.ClearAttributes();
1652 EXPECT_EQ(msg.length(), len - /* 3 + 1 byte padding + header */ 8);
1653 EXPECT_EQ(nullptr, msg.GetByteString(STUN_ATTR_USERNAME));
1654}
1655
Jonas Oreland202994c2017-12-18 12:10:43 +01001656// Test CopyStunAttribute
1657TEST_F(StunTest, CopyAttribute) {
1658 rtc::ByteBufferWriter buf;
Yves Gerey665174f2018-06-19 15:03:05 +02001659 rtc::ByteBufferWriter* buffer_ptrs[] = {&buf, nullptr};
Jonas Oreland202994c2017-12-18 12:10:43 +01001660 // Test both with and without supplied ByteBufferWriter.
1661 for (auto buffer_ptr : buffer_ptrs) {
Yves Gerey665174f2018-06-19 15:03:05 +02001662 { // Test StunByteStringAttribute.
Jonas Oreland202994c2017-12-18 12:10:43 +01001663 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1664 attr->CopyBytes("kes", sizeof("kes"));
1665
1666 auto copy = CopyStunAttribute(*attr.get(), buffer_ptr);
1667 ASSERT_EQ(copy->value_type(), STUN_VALUE_BYTE_STRING);
1668 EXPECT_STREQ("kes",
1669 static_cast<StunByteStringAttribute*>(copy.get())->bytes());
1670 }
1671
Yves Gerey665174f2018-06-19 15:03:05 +02001672 { // Test StunAddressAttribute.
Jonas Oreland202994c2017-12-18 12:10:43 +01001673 rtc::IPAddress test_ip(kIPv6TestAddress2);
1674 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
1675 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
1676 addr->SetAddress(test_addr);
Yves Gerey665174f2018-06-19 15:03:05 +02001677 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6,
1678 kTestMessagePort2, test_ip);
Jonas Oreland202994c2017-12-18 12:10:43 +01001679
1680 auto copy = CopyStunAttribute(*addr.get(), buffer_ptr);
1681 ASSERT_EQ(copy->value_type(), STUN_VALUE_ADDRESS);
1682 CheckStunAddressAttribute(static_cast<StunAddressAttribute*>(copy.get()),
1683 STUN_ADDRESS_IPV6, kTestMessagePort2, test_ip);
1684 }
Jonas Oreland63737a92019-11-21 15:12:14 +01001685
1686 { // Test StunAddressAttribute.
1687 rtc::IPAddress test_ip(kIPv6TestAddress2);
1688 auto addr = StunAttribute::CreateAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
1689 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
1690 addr->SetAddress(test_addr);
1691 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6,
1692 kTestMessagePort2, test_ip);
1693
1694 auto copy = CopyStunAttribute(*addr.get(), buffer_ptr);
1695 ASSERT_EQ(copy->value_type(), STUN_VALUE_ADDRESS);
1696 CheckStunAddressAttribute(static_cast<StunAddressAttribute*>(copy.get()),
1697 STUN_ADDRESS_IPV6, kTestMessagePort2, test_ip);
1698 }
Jonas Oreland202994c2017-12-18 12:10:43 +01001699 }
1700}
1701
Jonas Oreland253d50f2019-11-28 17:08:07 +01001702// Test Clone
1703TEST_F(StunTest, Clone) {
Tommi408143d2022-06-01 15:29:31 +02001704 IceMessage msg(0, "0123456789ab");
Jonas Oreland253d50f2019-11-28 17:08:07 +01001705 {
1706 auto errorcode = StunAttribute::CreateErrorCode();
1707 errorcode->SetCode(kTestErrorCode);
1708 errorcode->SetReason(kTestErrorReason);
1709 msg.AddAttribute(std::move(errorcode));
1710 }
1711 {
1712 auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1713 bytes2->CopyBytes("abcdefghijkl");
1714 msg.AddAttribute(std::move(bytes2));
1715 }
1716 {
1717 auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_RETRANSMIT_COUNT);
1718 uval2->SetValue(11);
1719 msg.AddAttribute(std::move(uval2));
1720 }
1721 {
1722 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
1723 addr->SetIP(rtc::IPAddress(kIPv6TestAddress1));
1724 addr->SetPort(kTestMessagePort1);
1725 msg.AddAttribute(std::move(addr));
1726 }
1727 auto copy = msg.Clone();
1728 ASSERT_NE(nullptr, copy.get());
1729
Jonas Oreland253d50f2019-11-28 17:08:07 +01001730 rtc::ByteBufferWriter out1;
1731 EXPECT_TRUE(msg.Write(&out1));
1732 rtc::ByteBufferWriter out2;
1733 EXPECT_TRUE(copy->Write(&out2));
1734
1735 ASSERT_EQ(out1.Length(), out2.Length());
1736 EXPECT_EQ(0, memcmp(out1.Data(), out2.Data(), out1.Length()));
1737}
1738
1739// Test EqualAttributes
1740TEST_F(StunTest, EqualAttributes) {
1741 IceMessage msg;
1742 {
1743 auto errorcode = StunAttribute::CreateErrorCode();
1744 errorcode->SetCode(kTestErrorCode);
1745 errorcode->SetReason(kTestErrorReason);
1746 msg.AddAttribute(std::move(errorcode));
1747 }
1748 {
1749 auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1750 bytes2->CopyBytes("abcdefghijkl");
1751 msg.AddAttribute(std::move(bytes2));
1752 }
1753 {
1754 auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_RETRANSMIT_COUNT);
1755 uval2->SetValue(11);
1756 msg.AddAttribute(std::move(uval2));
1757 }
1758 {
1759 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
1760 addr->SetIP(rtc::IPAddress(kIPv6TestAddress1));
1761 addr->SetPort(kTestMessagePort1);
1762 msg.AddAttribute(std::move(addr));
1763 }
1764 auto copy = msg.Clone();
1765 ASSERT_NE(nullptr, copy.get());
1766
1767 EXPECT_TRUE(copy->EqualAttributes(&msg, [](int type) { return true; }));
1768
1769 {
1770 auto attr = StunAttribute::CreateByteString(STUN_ATTR_NONCE);
1771 attr->CopyBytes("keso");
1772 msg.AddAttribute(std::move(attr));
1773 EXPECT_FALSE(copy->EqualAttributes(&msg, [](int type) { return true; }));
1774 EXPECT_TRUE(copy->EqualAttributes(
1775 &msg, [](int type) { return type != STUN_ATTR_NONCE; }));
1776 }
1777
1778 {
1779 auto attr = StunAttribute::CreateByteString(STUN_ATTR_NONCE);
1780 attr->CopyBytes("keso");
1781 copy->AddAttribute(std::move(attr));
1782 EXPECT_TRUE(copy->EqualAttributes(&msg, [](int type) { return true; }));
1783 }
1784 {
1785 copy->RemoveAttribute(STUN_ATTR_NONCE);
1786 auto attr = StunAttribute::CreateByteString(STUN_ATTR_NONCE);
1787 attr->CopyBytes("kent");
1788 copy->AddAttribute(std::move(attr));
1789 EXPECT_FALSE(copy->EqualAttributes(&msg, [](int type) { return true; }));
1790 EXPECT_TRUE(copy->EqualAttributes(
1791 &msg, [](int type) { return type != STUN_ATTR_NONCE; }));
1792 }
1793
1794 {
1795 msg.RemoveAttribute(STUN_ATTR_NONCE);
1796 EXPECT_FALSE(copy->EqualAttributes(&msg, [](int type) { return true; }));
1797 EXPECT_TRUE(copy->EqualAttributes(
1798 &msg, [](int type) { return type != STUN_ATTR_NONCE; }));
1799 }
1800}
1801
Zach Steinff71a492018-12-07 11:25:12 -08001802TEST_F(StunTest, ReduceTransactionIdIsHostOrderIndependent) {
Tommi408143d2022-06-01 15:29:31 +02001803 const std::string transaction_id = "abcdefghijkl";
1804 StunMessage message(0, transaction_id);
Zach Steinff71a492018-12-07 11:25:12 -08001805 uint32_t reduced_transaction_id = message.reduced_transaction_id();
1806 EXPECT_EQ(reduced_transaction_id, 1835954016u);
1807}
1808
Jonas Oreland1721de12019-11-20 12:10:39 +01001809TEST_F(StunTest, GoogMiscInfo) {
Tommi408143d2022-06-01 15:29:31 +02001810 StunMessage msg(STUN_BINDING_REQUEST, "ABCDEFGHIJKL");
Jonas Oreland1721de12019-11-20 12:10:39 +01001811 const size_t size =
1812 /* msg header */ 20 +
1813 /* attr header */ 4 +
1814 /* 3 * 2 rounded to multiple of 4 */ 8;
Jonas Oreland1721de12019-11-20 12:10:39 +01001815 auto list =
1816 StunAttribute::CreateUInt16ListAttribute(STUN_ATTR_GOOG_MISC_INFO);
Jonas Oreland63737a92019-11-21 15:12:14 +01001817 list->AddTypeAtIndex(0, 0x1U);
1818 list->AddTypeAtIndex(3, 0x1000U);
1819 list->AddTypeAtIndex(2, 0xAB0CU);
Jonas Oreland1721de12019-11-20 12:10:39 +01001820 msg.AddAttribute(std::move(list));
1821 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
1822
1823 rtc::ByteBufferWriter out;
1824 EXPECT_TRUE(msg.Write(&out));
1825 ASSERT_EQ(size, out.Length());
1826
1827 size_t read_size = ReadStunMessageTestCase(
1828 &msg, reinterpret_cast<const unsigned char*>(out.Data()), out.Length());
1829 ASSERT_EQ(read_size + 20, size);
1830 CheckStunHeader(msg, STUN_BINDING_REQUEST, read_size);
1831 const StunUInt16ListAttribute* types =
1832 msg.GetUInt16List(STUN_ATTR_GOOG_MISC_INFO);
1833 ASSERT_TRUE(types != NULL);
Jonas Oreland63737a92019-11-21 15:12:14 +01001834 EXPECT_EQ(4U, types->Size());
Jonas Oreland1721de12019-11-20 12:10:39 +01001835 EXPECT_EQ(0x1U, types->GetType(0));
Jonas Oreland63737a92019-11-21 15:12:14 +01001836 EXPECT_EQ(0x0U, types->GetType(1));
1837 EXPECT_EQ(0x1000U, types->GetType(3));
Jonas Oreland1721de12019-11-20 12:10:39 +01001838 EXPECT_EQ(0xAB0CU, types->GetType(2));
1839}
1840
Jonas Oreland253d50f2019-11-28 17:08:07 +01001841TEST_F(StunTest, IsStunMethod) {
1842 int methods[] = {STUN_BINDING_REQUEST};
1843 EXPECT_TRUE(StunMessage::IsStunMethod(
1844 methods, reinterpret_cast<const char*>(kRfc5769SampleRequest),
1845 sizeof(kRfc5769SampleRequest)));
1846}
1847
Harald Alvestrandbee64082020-11-12 11:17:41 +00001848TEST_F(StunTest, SizeRestrictionOnAttributes) {
Tommi408143d2022-06-01 15:29:31 +02001849 StunMessage msg(STUN_BINDING_REQUEST, "ABCDEFGHIJKL");
Harald Alvestrandbee64082020-11-12 11:17:41 +00001850 auto long_username = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1851 std::string long_string(509, 'x');
1852 long_username->CopyBytes(long_string.c_str(), long_string.size());
1853 msg.AddAttribute(std::move(long_username));
1854 rtc::ByteBufferWriter out;
1855 ASSERT_FALSE(msg.Write(&out));
1856}
1857
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001858} // namespace cricket