blob: 96ad45843bffb679506ccf501560e65222929693 [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"
Harald Alvestrandac757782022-10-11 12:18:34 +000023#include "system_wrappers/include/metrics.h"
Yves Gerey3e707812018-11-28 16:47:49 +010024#include "test/gtest.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000025
26namespace cricket {
27
28class StunTest : public ::testing::Test {
29 protected:
Yves Gerey665174f2018-06-19 15:03:05 +020030 void CheckStunHeader(const StunMessage& msg,
31 StunMessageType expected_type,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000032 size_t expected_length) {
33 ASSERT_EQ(expected_type, msg.type());
34 ASSERT_EQ(expected_length, msg.length());
35 }
36
37 void CheckStunTransactionID(const StunMessage& msg,
Yves Gerey665174f2018-06-19 15:03:05 +020038 const unsigned char* expectedID,
39 size_t length) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000040 ASSERT_EQ(length, msg.transaction_id().size());
41 ASSERT_EQ(length == kStunTransactionIdLength + 4, msg.IsLegacy());
42 ASSERT_EQ(length == kStunTransactionIdLength, !msg.IsLegacy());
43 ASSERT_EQ(0, memcmp(msg.transaction_id().c_str(), expectedID, length));
44 }
45
46 void CheckStunAddressAttribute(const StunAddressAttribute* addr,
47 StunAddressFamily expected_family,
48 int expected_port,
Yves Gerey2257c082020-01-03 12:37:56 +010049 const rtc::IPAddress& expected_address) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000050 ASSERT_EQ(expected_family, addr->family());
51 ASSERT_EQ(expected_port, addr->port());
52
53 if (addr->family() == STUN_ADDRESS_IPV4) {
54 in_addr v4_address = expected_address.ipv4_address();
55 in_addr stun_address = addr->ipaddr().ipv4_address();
56 ASSERT_EQ(0, memcmp(&v4_address, &stun_address, sizeof(stun_address)));
57 } else if (addr->family() == STUN_ADDRESS_IPV6) {
58 in6_addr v6_address = expected_address.ipv6_address();
59 in6_addr stun_address = addr->ipaddr().ipv6_address();
60 ASSERT_EQ(0, memcmp(&v6_address, &stun_address, sizeof(stun_address)));
61 } else {
62 ASSERT_TRUE(addr->family() == STUN_ADDRESS_IPV6 ||
63 addr->family() == STUN_ADDRESS_IPV4);
64 }
65 }
66
67 size_t ReadStunMessageTestCase(StunMessage* msg,
68 const unsigned char* testcase,
69 size_t size) {
70 const char* input = reinterpret_cast<const char*>(testcase);
jbauchf1f87202016-03-30 06:43:37 -070071 rtc::ByteBufferReader buf(input, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000072 if (msg->Read(&buf)) {
73 // Returns the size the stun message should report itself as being
74 return (size - 20);
75 } else {
76 return 0;
77 }
78 }
79};
80
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000081// Sample STUN packets with various attributes
82// Gathered by wiresharking pjproject's pjnath test programs
83// pjproject available at www.pjsip.org
84
Yves Gerey665174f2018-06-19 15:03:05 +020085// clang-format off
86// clang formatting doesn't respect inline comments.
87
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000088static const unsigned char kStunMessageWithIPv6MappedAddress[] = {
89 0x00, 0x01, 0x00, 0x18, // message header
90 0x21, 0x12, 0xa4, 0x42, // transaction id
91 0x29, 0x1f, 0xcd, 0x7c,
92 0xba, 0x58, 0xab, 0xd7,
93 0xf2, 0x41, 0x01, 0x00,
94 0x00, 0x01, 0x00, 0x14, // Address type (mapped), length
95 0x00, 0x02, 0xb8, 0x81, // family (IPv6), port
96 0x24, 0x01, 0xfa, 0x00, // an IPv6 address
97 0x00, 0x04, 0x10, 0x00,
98 0xbe, 0x30, 0x5b, 0xff,
99 0xfe, 0xe5, 0x00, 0xc3
100};
101
102static const unsigned char kStunMessageWithIPv4MappedAddress[] = {
103 0x01, 0x01, 0x00, 0x0c, // binding response, length 12
104 0x21, 0x12, 0xa4, 0x42, // magic cookie
105 0x29, 0x1f, 0xcd, 0x7c, // transaction ID
106 0xba, 0x58, 0xab, 0xd7,
107 0xf2, 0x41, 0x01, 0x00,
108 0x00, 0x01, 0x00, 0x08, // Mapped, 8 byte length
109 0x00, 0x01, 0x9d, 0xfc, // AF_INET, unxor-ed port
110 0xac, 0x17, 0x44, 0xe6 // IPv4 address
111};
112
113// Test XOR-mapped IP addresses:
114static const unsigned char kStunMessageWithIPv6XorMappedAddress[] = {
115 0x01, 0x01, 0x00, 0x18, // message header (binding response)
116 0x21, 0x12, 0xa4, 0x42, // magic cookie (rfc5389)
117 0xe3, 0xa9, 0x46, 0xe1, // transaction ID
118 0x7c, 0x00, 0xc2, 0x62,
119 0x54, 0x08, 0x01, 0x00,
120 0x00, 0x20, 0x00, 0x14, // Address Type (XOR), length
121 0x00, 0x02, 0xcb, 0x5b, // family, XOR-ed port
122 0x05, 0x13, 0x5e, 0x42, // XOR-ed IPv6 address
123 0xe3, 0xad, 0x56, 0xe1,
124 0xc2, 0x30, 0x99, 0x9d,
125 0xaa, 0xed, 0x01, 0xc3
126};
127
128static const unsigned char kStunMessageWithIPv4XorMappedAddress[] = {
129 0x01, 0x01, 0x00, 0x0c, // message header (binding response)
130 0x21, 0x12, 0xa4, 0x42, // magic cookie
131 0x29, 0x1f, 0xcd, 0x7c, // transaction ID
132 0xba, 0x58, 0xab, 0xd7,
133 0xf2, 0x41, 0x01, 0x00,
134 0x00, 0x20, 0x00, 0x08, // address type (xor), length
135 0x00, 0x01, 0xfc, 0xb5, // family (AF_INET), XOR-ed port
136 0x8d, 0x05, 0xe0, 0xa4 // IPv4 address
137};
138
139// ByteString Attribute (username)
140static const unsigned char kStunMessageWithByteStringAttribute[] = {
141 0x00, 0x01, 0x00, 0x0c,
142 0x21, 0x12, 0xa4, 0x42,
143 0xe3, 0xa9, 0x46, 0xe1,
144 0x7c, 0x00, 0xc2, 0x62,
145 0x54, 0x08, 0x01, 0x00,
146 0x00, 0x06, 0x00, 0x08, // username attribute (length 8)
147 0x61, 0x62, 0x63, 0x64, // abcdefgh
148 0x65, 0x66, 0x67, 0x68
149};
150
151// Message with an unknown but comprehensible optional attribute.
152// Parsing should succeed despite this unknown attribute.
153static const unsigned char kStunMessageWithUnknownAttribute[] = {
154 0x00, 0x01, 0x00, 0x14,
155 0x21, 0x12, 0xa4, 0x42,
156 0xe3, 0xa9, 0x46, 0xe1,
157 0x7c, 0x00, 0xc2, 0x62,
158 0x54, 0x08, 0x01, 0x00,
159 0x00, 0xaa, 0x00, 0x07, // Unknown attribute, length 7 (needs padding!)
160 0x61, 0x62, 0x63, 0x64, // abcdefg + padding
161 0x65, 0x66, 0x67, 0x00,
162 0x00, 0x06, 0x00, 0x03, // Followed by a known attribute we can
163 0x61, 0x62, 0x63, 0x00 // check for (username of length 3)
164};
165
166// ByteString Attribute (username) with padding byte
167static const unsigned char kStunMessageWithPaddedByteStringAttribute[] = {
168 0x00, 0x01, 0x00, 0x08,
169 0x21, 0x12, 0xa4, 0x42,
170 0xe3, 0xa9, 0x46, 0xe1,
171 0x7c, 0x00, 0xc2, 0x62,
172 0x54, 0x08, 0x01, 0x00,
173 0x00, 0x06, 0x00, 0x03, // username attribute (length 3)
174 0x61, 0x62, 0x63, 0xcc // abc
175};
176
Peter Boström0c4e06b2015-10-07 12:23:21 +0200177// Message with an Unknown Attributes (uint16_t list) attribute.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000178static const unsigned char kStunMessageWithUInt16ListAttribute[] = {
179 0x00, 0x01, 0x00, 0x0c,
180 0x21, 0x12, 0xa4, 0x42,
181 0xe3, 0xa9, 0x46, 0xe1,
182 0x7c, 0x00, 0xc2, 0x62,
183 0x54, 0x08, 0x01, 0x00,
184 0x00, 0x0a, 0x00, 0x06, // username attribute (length 6)
185 0x00, 0x01, 0x10, 0x00, // three attributes plus padding
186 0xAB, 0xCU, 0xBE, 0xEF
187};
188
189// Error response message (unauthorized)
190static const unsigned char kStunMessageWithErrorAttribute[] = {
191 0x01, 0x11, 0x00, 0x14,
192 0x21, 0x12, 0xa4, 0x42,
193 0x29, 0x1f, 0xcd, 0x7c,
194 0xba, 0x58, 0xab, 0xd7,
195 0xf2, 0x41, 0x01, 0x00,
196 0x00, 0x09, 0x00, 0x10,
197 0x00, 0x00, 0x04, 0x01,
198 0x55, 0x6e, 0x61, 0x75,
199 0x74, 0x68, 0x6f, 0x72,
200 0x69, 0x7a, 0x65, 0x64
201};
202
203// Sample messages with an invalid length Field
204
205// The actual length in bytes of the invalid messages (including STUN header)
206static const int kRealLengthOfInvalidLengthTestCases = 32;
207
208static const unsigned char kStunMessageWithZeroLength[] = {
209 0x00, 0x01, 0x00, 0x00, // length of 0 (last 2 bytes)
210 0x21, 0x12, 0xA4, 0x42, // magic cookie
211 '0', '1', '2', '3', // transaction id
212 '4', '5', '6', '7',
213 '8', '9', 'a', 'b',
214 0x00, 0x20, 0x00, 0x08, // xor mapped address
215 0x00, 0x01, 0x21, 0x1F,
216 0x21, 0x12, 0xA4, 0x53,
217};
218
219static const unsigned char kStunMessageWithExcessLength[] = {
220 0x00, 0x01, 0x00, 0x55, // length of 85
221 0x21, 0x12, 0xA4, 0x42, // magic cookie
222 '0', '1', '2', '3', // transaction id
223 '4', '5', '6', '7',
224 '8', '9', 'a', 'b',
225 0x00, 0x20, 0x00, 0x08, // xor mapped address
226 0x00, 0x01, 0x21, 0x1F,
227 0x21, 0x12, 0xA4, 0x53,
228};
229
230static const unsigned char kStunMessageWithSmallLength[] = {
231 0x00, 0x01, 0x00, 0x03, // length of 3
232 0x21, 0x12, 0xA4, 0x42, // magic cookie
233 '0', '1', '2', '3', // transaction id
234 '4', '5', '6', '7',
235 '8', '9', 'a', 'b',
236 0x00, 0x20, 0x00, 0x08, // xor mapped address
237 0x00, 0x01, 0x21, 0x1F,
238 0x21, 0x12, 0xA4, 0x53,
239};
240
katrielc1a206102016-06-20 05:13:16 -0700241static const unsigned char kStunMessageWithBadHmacAtEnd[] = {
242 0x00, 0x01, 0x00, 0x14, // message length exactly 20
243 0x21, 0x12, 0xA4, 0x42, // magic cookie
244 '0', '1', '2', '3', // transaction ID
245 '4', '5', '6', '7',
246 '8', '9', 'a', 'b',
247 0x00, 0x08, 0x00, 0x14, // type=STUN_ATTR_MESSAGE_INTEGRITY, length=20
248 '0', '0', '0', '0', // We lied, there are only 16 bytes of HMAC.
249 '0', '0', '0', '0',
250 '0', '0', '0', '0',
251 '0', '0', '0', '0',
252};
253
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000254// RTCP packet, for testing we correctly ignore non stun packet types.
255// V=2, P=false, RC=0, Type=200, Len=6, Sender-SSRC=85, etc
256static const unsigned char kRtcpPacket[] = {
257 0x80, 0xc8, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55,
258 0xce, 0xa5, 0x18, 0x3a, 0x39, 0xcc, 0x7d, 0x09,
259 0x23, 0xed, 0x19, 0x07, 0x00, 0x00, 0x01, 0x56,
260 0x00, 0x03, 0x73, 0x50,
261};
262
Yves Gerey665174f2018-06-19 15:03:05 +0200263
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000264// RFC5769 Test Vectors
265// Software name (request): "STUN test client" (without quotes)
266// Software name (response): "test vector" (without quotes)
267// Username: "evtj:h6vY" (without quotes)
268// Password: "VOkJxbRl1RmTxUk/WvJxBt" (without quotes)
269static const unsigned char kRfc5769SampleMsgTransactionId[] = {
270 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae
271};
272static const char kRfc5769SampleMsgClientSoftware[] = "STUN test client";
273static const char kRfc5769SampleMsgServerSoftware[] = "test vector";
274static const char kRfc5769SampleMsgUsername[] = "evtj:h6vY";
275static const char kRfc5769SampleMsgPassword[] = "VOkJxbRl1RmTxUk/WvJxBt";
276static const rtc::SocketAddress kRfc5769SampleMsgMappedAddress(
277 "192.0.2.1", 32853);
278static const rtc::SocketAddress kRfc5769SampleMsgIPv6MappedAddress(
279 "2001:db8:1234:5678:11:2233:4455:6677", 32853);
280
281static const unsigned char kRfc5769SampleMsgWithAuthTransactionId[] = {
282 0x78, 0xad, 0x34, 0x33, 0xc6, 0xad, 0x72, 0xc0, 0x29, 0xda, 0x41, 0x2e
283};
284static const char kRfc5769SampleMsgWithAuthUsername[] =
285 "\xe3\x83\x9e\xe3\x83\x88\xe3\x83\xaa\xe3\x83\x83\xe3\x82\xaf\xe3\x82\xb9";
286static const char kRfc5769SampleMsgWithAuthPassword[] = "TheMatrIX";
287static const char kRfc5769SampleMsgWithAuthNonce[] =
288 "f//499k954d6OL34oL9FSTvy64sA";
289static const char kRfc5769SampleMsgWithAuthRealm[] = "example.org";
290
291// 2.1. Sample Request
292static const unsigned char kRfc5769SampleRequest[] = {
293 0x00, 0x01, 0x00, 0x58, // Request type and message length
294 0x21, 0x12, 0xa4, 0x42, // Magic cookie
295 0xb7, 0xe7, 0xa7, 0x01, // }
296 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
297 0xfa, 0x87, 0xdf, 0xae, // }
298 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
299 0x53, 0x54, 0x55, 0x4e, // }
300 0x20, 0x74, 0x65, 0x73, // } User-agent...
301 0x74, 0x20, 0x63, 0x6c, // } ...name
302 0x69, 0x65, 0x6e, 0x74, // }
303 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
304 0x6e, 0x00, 0x01, 0xff, // ICE priority value
305 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
306 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
307 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
308 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
309 0x65, 0x76, 0x74, 0x6a, // }
310 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
311 0x59, 0x20, 0x20, 0x20, // }
312 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
313 0x9a, 0xea, 0xa7, 0x0c, // }
314 0xbf, 0xd8, 0xcb, 0x56, // }
315 0x78, 0x1e, 0xf2, 0xb5, // } HMAC-SHA1 fingerprint
316 0xb2, 0xd3, 0xf2, 0x49, // }
317 0xc1, 0xb5, 0x71, 0xa2, // }
318 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
319 0xe5, 0x7a, 0x3b, 0xcf // CRC32 fingerprint
320};
321
Jonas Oreland63737a92019-11-21 15:12:14 +0100322// 2.1. Sample Request
323static const unsigned char kSampleRequestMI32[] = {
324 0x00, 0x01, 0x00, 0x48, // Request type and message length
325 0x21, 0x12, 0xa4, 0x42, // Magic cookie
326 0xb7, 0xe7, 0xa7, 0x01, // }
327 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
328 0xfa, 0x87, 0xdf, 0xae, // }
329 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
330 0x53, 0x54, 0x55, 0x4e, // }
331 0x20, 0x74, 0x65, 0x73, // } User-agent...
332 0x74, 0x20, 0x63, 0x6c, // } ...name
333 0x69, 0x65, 0x6e, 0x74, // }
334 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
335 0x6e, 0x00, 0x01, 0xff, // ICE priority value
336 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
337 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
338 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
339 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
340 0x65, 0x76, 0x74, 0x6a, // }
341 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
342 0x59, 0x20, 0x20, 0x20, // }
343 0xC0, 0x60, 0x00, 0x04, // MESSAGE-INTEGRITY-32 attribute header
344 0x45, 0x45, 0xce, 0x7c, // } HMAC-SHA1 fingerprint (first 32 bit)
345 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
346 0xe5, 0x7a, 0x3b, 0xcf // CRC32 fingerprint
347};
348
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000349// 2.2. Sample IPv4 Response
350static const unsigned char kRfc5769SampleResponse[] = {
351 0x01, 0x01, 0x00, 0x3c, // Response type and message length
352 0x21, 0x12, 0xa4, 0x42, // Magic cookie
353 0xb7, 0xe7, 0xa7, 0x01, // }
354 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
355 0xfa, 0x87, 0xdf, 0xae, // }
356 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
357 0x74, 0x65, 0x73, 0x74, // }
358 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
359 0x74, 0x6f, 0x72, 0x20, // }
360 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
361 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port
362 0xe1, 0x12, 0xa6, 0x43, // Xor'd mapped IPv4 address
363 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
364 0x2b, 0x91, 0xf5, 0x99, // }
365 0xfd, 0x9e, 0x90, 0xc3, // }
366 0x8c, 0x74, 0x89, 0xf9, // } HMAC-SHA1 fingerprint
367 0x2a, 0xf9, 0xba, 0x53, // }
368 0xf0, 0x6b, 0xe7, 0xd7, // }
369 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
370 0xc0, 0x7d, 0x4c, 0x96 // CRC32 fingerprint
371};
372
373// 2.3. Sample IPv6 Response
374static const unsigned char kRfc5769SampleResponseIPv6[] = {
375 0x01, 0x01, 0x00, 0x48, // Response type and message length
376 0x21, 0x12, 0xa4, 0x42, // Magic cookie
377 0xb7, 0xe7, 0xa7, 0x01, // }
378 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
379 0xfa, 0x87, 0xdf, 0xae, // }
380 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
381 0x74, 0x65, 0x73, 0x74, // }
382 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
383 0x74, 0x6f, 0x72, 0x20, // }
384 0x00, 0x20, 0x00, 0x14, // XOR-MAPPED-ADDRESS attribute header
385 0x00, 0x02, 0xa1, 0x47, // Address family (IPv6) and xor'd mapped port.
386 0x01, 0x13, 0xa9, 0xfa, // }
387 0xa5, 0xd3, 0xf1, 0x79, // } Xor'd mapped IPv6 address
388 0xbc, 0x25, 0xf4, 0xb5, // }
389 0xbe, 0xd2, 0xb9, 0xd9, // }
390 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
391 0xa3, 0x82, 0x95, 0x4e, // }
392 0x4b, 0xe6, 0x7b, 0xf1, // }
393 0x17, 0x84, 0xc9, 0x7c, // } HMAC-SHA1 fingerprint
394 0x82, 0x92, 0xc2, 0x75, // }
395 0xbf, 0xe3, 0xed, 0x41, // }
396 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
397 0xc8, 0xfb, 0x0b, 0x4c // CRC32 fingerprint
398};
399
400// 2.4. Sample Request with Long-Term Authentication
401static const unsigned char kRfc5769SampleRequestLongTermAuth[] = {
402 0x00, 0x01, 0x00, 0x60, // Request type and message length
403 0x21, 0x12, 0xa4, 0x42, // Magic cookie
404 0x78, 0xad, 0x34, 0x33, // }
405 0xc6, 0xad, 0x72, 0xc0, // } Transaction ID
406 0x29, 0xda, 0x41, 0x2e, // }
407 0x00, 0x06, 0x00, 0x12, // USERNAME attribute header
408 0xe3, 0x83, 0x9e, 0xe3, // }
409 0x83, 0x88, 0xe3, 0x83, // }
410 0xaa, 0xe3, 0x83, 0x83, // } Username value (18 bytes) and padding (2 bytes)
411 0xe3, 0x82, 0xaf, 0xe3, // }
412 0x82, 0xb9, 0x00, 0x00, // }
413 0x00, 0x15, 0x00, 0x1c, // NONCE attribute header
414 0x66, 0x2f, 0x2f, 0x34, // }
415 0x39, 0x39, 0x6b, 0x39, // }
416 0x35, 0x34, 0x64, 0x36, // }
417 0x4f, 0x4c, 0x33, 0x34, // } Nonce value
418 0x6f, 0x4c, 0x39, 0x46, // }
419 0x53, 0x54, 0x76, 0x79, // }
420 0x36, 0x34, 0x73, 0x41, // }
421 0x00, 0x14, 0x00, 0x0b, // REALM attribute header
422 0x65, 0x78, 0x61, 0x6d, // }
423 0x70, 0x6c, 0x65, 0x2e, // } Realm value (11 bytes) and padding (1 byte)
424 0x6f, 0x72, 0x67, 0x00, // }
425 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
426 0xf6, 0x70, 0x24, 0x65, // }
427 0x6d, 0xd6, 0x4a, 0x3e, // }
428 0x02, 0xb8, 0xe0, 0x71, // } HMAC-SHA1 fingerprint
429 0x2e, 0x85, 0xc9, 0xa2, // }
430 0x8c, 0xa8, 0x96, 0x66 // }
431};
432
433// Length parameter is changed to 0x38 from 0x58.
434// AddMessageIntegrity will add MI information and update the length param
435// accordingly.
436static const unsigned char kRfc5769SampleRequestWithoutMI[] = {
437 0x00, 0x01, 0x00, 0x38, // Request type and message length
438 0x21, 0x12, 0xa4, 0x42, // Magic cookie
439 0xb7, 0xe7, 0xa7, 0x01, // }
440 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
441 0xfa, 0x87, 0xdf, 0xae, // }
442 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
443 0x53, 0x54, 0x55, 0x4e, // }
444 0x20, 0x74, 0x65, 0x73, // } User-agent...
445 0x74, 0x20, 0x63, 0x6c, // } ...name
446 0x69, 0x65, 0x6e, 0x74, // }
447 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
448 0x6e, 0x00, 0x01, 0xff, // ICE priority value
449 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
450 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
451 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
452 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
453 0x65, 0x76, 0x74, 0x6a, // }
454 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
455 0x59, 0x20, 0x20, 0x20 // }
456};
457
458// This HMAC differs from the RFC 5769 SampleRequest message. This differs
459// because spec uses 0x20 for the padding where as our implementation uses 0.
460static const unsigned char kCalculatedHmac1[] = {
461 0x79, 0x07, 0xc2, 0xd2, // }
462 0xed, 0xbf, 0xea, 0x48, // }
463 0x0e, 0x4c, 0x76, 0xd8, // } HMAC-SHA1 fingerprint
464 0x29, 0x62, 0xd5, 0xc3, // }
465 0x74, 0x2a, 0xf9, 0xe3 // }
466};
467
Jonas Oreland63737a92019-11-21 15:12:14 +0100468// This truncated HMAC differs from kCalculatedHmac1
469// above since the sum is computed including header
470// and the header is different since the message is shorter
471// than when MESSAGE-INTEGRITY is used.
472static const unsigned char kCalculatedHmac1_32[] = {
473 0xda, 0x39, 0xde, 0x5d, // }
474};
475
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000476// Length parameter is changed to 0x1c from 0x3c.
477// AddMessageIntegrity will add MI information and update the length param
478// accordingly.
479static const unsigned char kRfc5769SampleResponseWithoutMI[] = {
480 0x01, 0x01, 0x00, 0x1c, // Response type and message length
481 0x21, 0x12, 0xa4, 0x42, // Magic cookie
482 0xb7, 0xe7, 0xa7, 0x01, // }
483 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
484 0xfa, 0x87, 0xdf, 0xae, // }
485 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
486 0x74, 0x65, 0x73, 0x74, // }
487 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
488 0x74, 0x6f, 0x72, 0x20, // }
489 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
490 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port
491 0xe1, 0x12, 0xa6, 0x43 // Xor'd mapped IPv4 address
492};
493
494// This HMAC differs from the RFC 5769 SampleResponse message. This differs
495// because spec uses 0x20 for the padding where as our implementation uses 0.
496static const unsigned char kCalculatedHmac2[] = {
497 0x5d, 0x6b, 0x58, 0xbe, // }
498 0xad, 0x94, 0xe0, 0x7e, // }
499 0xef, 0x0d, 0xfc, 0x12, // } HMAC-SHA1 fingerprint
500 0x82, 0xa2, 0xbd, 0x08, // }
501 0x43, 0x14, 0x10, 0x28 // }
502};
503
Jonas Oreland63737a92019-11-21 15:12:14 +0100504// This truncated HMAC differs from kCalculatedHmac2
505// above since the sum is computed including header
506// and the header is different since the message is shorter
507// than when MESSAGE-INTEGRITY is used.
508static const unsigned char kCalculatedHmac2_32[] = {
509 0xe7, 0x5c, 0xd3, 0x16, // }
510};
511
Yves Gerey665174f2018-06-19 15:03:05 +0200512// clang-format on
513
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000514// A transaction ID without the 'magic cookie' portion
515// pjnat's test programs use this transaction ID a lot.
Yves Gerey665174f2018-06-19 15:03:05 +0200516const unsigned char kTestTransactionId1[] = {0x029, 0x01f, 0x0cd, 0x07c,
517 0x0ba, 0x058, 0x0ab, 0x0d7,
518 0x0f2, 0x041, 0x001, 0x000};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000519
520// They use this one sometimes too.
Yves Gerey665174f2018-06-19 15:03:05 +0200521const unsigned char kTestTransactionId2[] = {0x0e3, 0x0a9, 0x046, 0x0e1,
522 0x07c, 0x000, 0x0c2, 0x062,
523 0x054, 0x008, 0x001, 0x000};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000524
Yves Gerey665174f2018-06-19 15:03:05 +0200525const in6_addr kIPv6TestAddress1 = {
526 {{0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, 0x10, 0x00, 0xbe, 0x30, 0x5b, 0xff,
527 0xfe, 0xe5, 0x00, 0xc3}}};
528const in6_addr kIPv6TestAddress2 = {
529 {{0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, 0x10, 0x12, 0x06, 0x0c, 0xce, 0xff,
530 0xfe, 0x1f, 0x61, 0xa4}}};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000531
532#ifdef WEBRTC_POSIX
Yves Gerey665174f2018-06-19 15:03:05 +0200533const in_addr kIPv4TestAddress1 = {0xe64417ac};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000534#elif defined WEBRTC_WIN
535// Windows in_addr has a union with a uchar[] array first.
Yves Gerey665174f2018-06-19 15:03:05 +0200536const in_addr kIPv4TestAddress1 = {{{0x0ac, 0x017, 0x044, 0x0e6}}};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000537#endif
538const char kTestUserName1[] = "abcdefgh";
539const char kTestUserName2[] = "abc";
540const char kTestErrorReason[] = "Unauthorized";
541const int kTestErrorClass = 4;
542const int kTestErrorNumber = 1;
543const int kTestErrorCode = 401;
544
545const int kTestMessagePort1 = 59977;
546const int kTestMessagePort2 = 47233;
547const int kTestMessagePort3 = 56743;
548const int kTestMessagePort4 = 40444;
549
550#define ReadStunMessage(X, Y) ReadStunMessageTestCase(X, Y, sizeof(Y));
551
552// Test that the GetStun*Type and IsStun*Type methods work as expected.
553TEST_F(StunTest, MessageTypes) {
554 EXPECT_EQ(STUN_BINDING_RESPONSE,
Yves Gerey665174f2018-06-19 15:03:05 +0200555 GetStunSuccessResponseType(STUN_BINDING_REQUEST));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000556 EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE,
Yves Gerey665174f2018-06-19 15:03:05 +0200557 GetStunErrorResponseType(STUN_BINDING_REQUEST));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000558 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_INDICATION));
559 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_RESPONSE));
560 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_ERROR_RESPONSE));
561 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_INDICATION));
562 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_RESPONSE));
563 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_ERROR_RESPONSE));
564
Yves Gerey665174f2018-06-19 15:03:05 +0200565 int types[] = {STUN_BINDING_REQUEST, STUN_BINDING_INDICATION,
566 STUN_BINDING_RESPONSE, STUN_BINDING_ERROR_RESPONSE};
tfarina5237aaf2015-11-10 23:44:30 -0800567 for (size_t i = 0; i < arraysize(types); ++i) {
568 EXPECT_EQ(i == 0U, IsStunRequestType(types[i]));
569 EXPECT_EQ(i == 1U, IsStunIndicationType(types[i]));
570 EXPECT_EQ(i == 2U, IsStunSuccessResponseType(types[i]));
571 EXPECT_EQ(i == 3U, IsStunErrorResponseType(types[i]));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000572 EXPECT_EQ(1, types[i] & 0xFEEF);
573 }
574}
575
576TEST_F(StunTest, ReadMessageWithIPv4AddressAttribute) {
577 StunMessage msg;
578 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4MappedAddress);
579 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
580 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
581
582 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
583 rtc::IPAddress test_address(kIPv4TestAddress1);
Yves Gerey665174f2018-06-19 15:03:05 +0200584 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort4,
585 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000586}
587
588TEST_F(StunTest, ReadMessageWithIPv4XorAddressAttribute) {
589 StunMessage msg;
590 StunMessage msg2;
591 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress);
592 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
593 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
594
595 const StunAddressAttribute* addr =
596 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
597 rtc::IPAddress test_address(kIPv4TestAddress1);
Yves Gerey665174f2018-06-19 15:03:05 +0200598 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort3,
599 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000600}
601
602TEST_F(StunTest, ReadMessageWithIPv6AddressAttribute) {
603 StunMessage msg;
604 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
605 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
606 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
607
608 rtc::IPAddress test_address(kIPv6TestAddress1);
609
610 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200611 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort2,
612 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000613}
614
615TEST_F(StunTest, ReadMessageWithInvalidAddressAttribute) {
616 StunMessage msg;
617 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
618 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
619 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
620
621 rtc::IPAddress test_address(kIPv6TestAddress1);
622
623 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200624 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort2,
625 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000626}
627
628TEST_F(StunTest, ReadMessageWithIPv6XorAddressAttribute) {
629 StunMessage msg;
630 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress);
631
632 rtc::IPAddress test_address(kIPv6TestAddress1);
633
634 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
635 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
636
637 const StunAddressAttribute* addr =
638 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200639 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort1,
640 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000641}
642
643// Read the RFC5389 fields from the RFC5769 sample STUN request.
644TEST_F(StunTest, ReadRfc5769RequestMessage) {
645 StunMessage msg;
646 size_t size = ReadStunMessage(&msg, kRfc5769SampleRequest);
647 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
648 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
649 kStunTransactionIdLength);
650
651 const StunByteStringAttribute* software =
652 msg.GetByteString(STUN_ATTR_SOFTWARE);
653 ASSERT_TRUE(software != NULL);
Tommie83500e2022-06-03 14:28:59 +0200654 EXPECT_EQ(kRfc5769SampleMsgClientSoftware, software->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000655
656 const StunByteStringAttribute* username =
657 msg.GetByteString(STUN_ATTR_USERNAME);
658 ASSERT_TRUE(username != NULL);
Tommie83500e2022-06-03 14:28:59 +0200659 EXPECT_EQ(kRfc5769SampleMsgUsername, username->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000660
661 // Actual M-I value checked in a later test.
662 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
663
664 // Fingerprint checked in a later test, but double-check the value here.
Yves Gerey665174f2018-06-19 15:03:05 +0200665 const StunUInt32Attribute* fingerprint = msg.GetUInt32(STUN_ATTR_FINGERPRINT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000666 ASSERT_TRUE(fingerprint != NULL);
667 EXPECT_EQ(0xe57a3bcf, fingerprint->value());
668}
669
670// Read the RFC5389 fields from the RFC5769 sample STUN response.
671TEST_F(StunTest, ReadRfc5769ResponseMessage) {
672 StunMessage msg;
673 size_t size = ReadStunMessage(&msg, kRfc5769SampleResponse);
674 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
675 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
676 kStunTransactionIdLength);
677
678 const StunByteStringAttribute* software =
679 msg.GetByteString(STUN_ATTR_SOFTWARE);
680 ASSERT_TRUE(software != NULL);
Tommie83500e2022-06-03 14:28:59 +0200681 EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000682
683 const StunAddressAttribute* mapped_address =
684 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
685 ASSERT_TRUE(mapped_address != NULL);
686 EXPECT_EQ(kRfc5769SampleMsgMappedAddress, mapped_address->GetAddress());
687
688 // Actual M-I and fingerprint checked in later tests.
689 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
690 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
691}
692
693// Read the RFC5389 fields from the RFC5769 sample STUN response for IPv6.
694TEST_F(StunTest, ReadRfc5769ResponseMessageIPv6) {
695 StunMessage msg;
696 size_t size = ReadStunMessage(&msg, kRfc5769SampleResponseIPv6);
697 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
698 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
699 kStunTransactionIdLength);
700
701 const StunByteStringAttribute* software =
702 msg.GetByteString(STUN_ATTR_SOFTWARE);
703 ASSERT_TRUE(software != NULL);
Tommie83500e2022-06-03 14:28:59 +0200704 EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000705
706 const StunAddressAttribute* mapped_address =
707 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
708 ASSERT_TRUE(mapped_address != NULL);
709 EXPECT_EQ(kRfc5769SampleMsgIPv6MappedAddress, mapped_address->GetAddress());
710
711 // Actual M-I and fingerprint checked in later tests.
712 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
713 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
714}
715
716// Read the RFC5389 fields from the RFC5769 sample STUN response with auth.
717TEST_F(StunTest, ReadRfc5769RequestMessageLongTermAuth) {
718 StunMessage msg;
719 size_t size = ReadStunMessage(&msg, kRfc5769SampleRequestLongTermAuth);
720 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
721 CheckStunTransactionID(msg, kRfc5769SampleMsgWithAuthTransactionId,
722 kStunTransactionIdLength);
723
724 const StunByteStringAttribute* username =
725 msg.GetByteString(STUN_ATTR_USERNAME);
726 ASSERT_TRUE(username != NULL);
Tommie83500e2022-06-03 14:28:59 +0200727 EXPECT_EQ(kRfc5769SampleMsgWithAuthUsername, username->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000728
Yves Gerey665174f2018-06-19 15:03:05 +0200729 const StunByteStringAttribute* nonce = msg.GetByteString(STUN_ATTR_NONCE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000730 ASSERT_TRUE(nonce != NULL);
Tommie83500e2022-06-03 14:28:59 +0200731 EXPECT_EQ(kRfc5769SampleMsgWithAuthNonce, nonce->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000732
Yves Gerey665174f2018-06-19 15:03:05 +0200733 const StunByteStringAttribute* realm = msg.GetByteString(STUN_ATTR_REALM);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000734 ASSERT_TRUE(realm != NULL);
Tommie83500e2022-06-03 14:28:59 +0200735 EXPECT_EQ(kRfc5769SampleMsgWithAuthRealm, realm->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000736
737 // No fingerprint, actual M-I checked in later tests.
738 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
739 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) == NULL);
740}
741
742// The RFC3489 packet in this test is the same as
743// kStunMessageWithIPv4MappedAddress, but with a different value where the
744// magic cookie was.
745TEST_F(StunTest, ReadLegacyMessage) {
746 unsigned char rfc3489_packet[sizeof(kStunMessageWithIPv4MappedAddress)];
747 memcpy(rfc3489_packet, kStunMessageWithIPv4MappedAddress,
Yves Gerey665174f2018-06-19 15:03:05 +0200748 sizeof(kStunMessageWithIPv4MappedAddress));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000749 // Overwrite the magic cookie here.
750 memcpy(&rfc3489_packet[4], "ABCD", 4);
751
752 StunMessage msg;
753 size_t size = ReadStunMessage(&msg, rfc3489_packet);
754 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
755 CheckStunTransactionID(msg, &rfc3489_packet[4], kStunTransactionIdLength + 4);
756
757 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
758 rtc::IPAddress test_address(kIPv4TestAddress1);
Yves Gerey665174f2018-06-19 15:03:05 +0200759 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort4,
760 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000761}
762
763TEST_F(StunTest, SetIPv6XorAddressAttributeOwner) {
764 StunMessage msg;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000765 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress);
766
767 rtc::IPAddress test_address(kIPv6TestAddress1);
768
769 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
770 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
771
772 const StunAddressAttribute* addr =
773 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200774 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort1,
775 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000776
777 // Owner with a different transaction ID.
Tommi408143d2022-06-01 15:29:31 +0200778 StunMessage msg2(STUN_INVALID_MESSAGE_TYPE, "ABCDABCDABCD");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000779 StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL);
780 addr2.SetIP(addr->ipaddr());
781 addr2.SetPort(addr->port());
782 addr2.SetOwner(&msg2);
783 // The internal IP address shouldn't change.
784 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
785
jbauchf1f87202016-03-30 06:43:37 -0700786 rtc::ByteBufferWriter correct_buf;
787 rtc::ByteBufferWriter wrong_buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000788 EXPECT_TRUE(addr->Write(&correct_buf));
789 EXPECT_TRUE(addr2.Write(&wrong_buf));
790 // But when written out, the buffers should look different.
791 ASSERT_NE(0,
792 memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
793 // And when reading a known good value, the address should be wrong.
jbauchf1f87202016-03-30 06:43:37 -0700794 rtc::ByteBufferReader read_buf(correct_buf);
795 addr2.Read(&read_buf);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000796 ASSERT_NE(addr->ipaddr(), addr2.ipaddr());
797 addr2.SetIP(addr->ipaddr());
798 addr2.SetPort(addr->port());
799 // Try writing with no owner at all, should fail and write nothing.
800 addr2.SetOwner(NULL);
801 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
jbauchf1f87202016-03-30 06:43:37 -0700802 wrong_buf.Clear();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000803 EXPECT_FALSE(addr2.Write(&wrong_buf));
804 ASSERT_EQ(0U, wrong_buf.Length());
805}
806
807TEST_F(StunTest, SetIPv4XorAddressAttributeOwner) {
808 // Unlike the IPv6XorAddressAttributeOwner test, IPv4 XOR address attributes
809 // should _not_ be affected by a change in owner. IPv4 XOR address uses the
810 // magic cookie value which is fixed.
811 StunMessage msg;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000812 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress);
813
814 rtc::IPAddress test_address(kIPv4TestAddress1);
815
816 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
817 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
818
819 const StunAddressAttribute* addr =
820 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200821 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort3,
822 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000823
824 // Owner with a different transaction ID.
Tommi408143d2022-06-01 15:29:31 +0200825 StunMessage msg2(STUN_INVALID_MESSAGE_TYPE, "ABCDABCDABCD");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000826 StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL);
827 addr2.SetIP(addr->ipaddr());
828 addr2.SetPort(addr->port());
829 addr2.SetOwner(&msg2);
830 // The internal IP address shouldn't change.
831 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
832
jbauchf1f87202016-03-30 06:43:37 -0700833 rtc::ByteBufferWriter correct_buf;
834 rtc::ByteBufferWriter wrong_buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000835 EXPECT_TRUE(addr->Write(&correct_buf));
836 EXPECT_TRUE(addr2.Write(&wrong_buf));
837 // The same address data should be written.
838 ASSERT_EQ(0,
839 memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
840 // And an attribute should be able to un-XOR an address belonging to a message
841 // with a different transaction ID.
jbauchf1f87202016-03-30 06:43:37 -0700842 rtc::ByteBufferReader read_buf(correct_buf);
843 EXPECT_TRUE(addr2.Read(&read_buf));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000844 ASSERT_EQ(addr->ipaddr(), addr2.ipaddr());
845
846 // However, no owner is still an error, should fail and write nothing.
847 addr2.SetOwner(NULL);
848 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
jbauchf1f87202016-03-30 06:43:37 -0700849 wrong_buf.Clear();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000850 EXPECT_FALSE(addr2.Write(&wrong_buf));
851}
852
853TEST_F(StunTest, CreateIPv6AddressAttribute) {
854 rtc::IPAddress test_ip(kIPv6TestAddress2);
855
zsteinf42cc9d2017-03-27 16:17:19 -0700856 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000857 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
858 addr->SetAddress(test_addr);
859
zsteinf42cc9d2017-03-27 16:17:19 -0700860 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6, kTestMessagePort2,
861 test_ip);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000862}
863
864TEST_F(StunTest, CreateIPv4AddressAttribute) {
865 struct in_addr test_in_addr;
866 test_in_addr.s_addr = 0xBEB0B0BE;
867 rtc::IPAddress test_ip(test_in_addr);
868
zsteinf42cc9d2017-03-27 16:17:19 -0700869 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000870 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
871 addr->SetAddress(test_addr);
872
zsteinf42cc9d2017-03-27 16:17:19 -0700873 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV4, kTestMessagePort2,
874 test_ip);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000875}
876
877// Test that we don't care what order we set the parts of an address
878TEST_F(StunTest, CreateAddressInArbitraryOrder) {
zsteinf42cc9d2017-03-27 16:17:19 -0700879 auto addr = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000880 // Port first
881 addr->SetPort(kTestMessagePort1);
882 addr->SetIP(rtc::IPAddress(kIPv4TestAddress1));
883 ASSERT_EQ(kTestMessagePort1, addr->port());
884 ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr->ipaddr());
885
zsteinf42cc9d2017-03-27 16:17:19 -0700886 auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000887 // IP first
888 addr2->SetIP(rtc::IPAddress(kIPv4TestAddress1));
889 addr2->SetPort(kTestMessagePort2);
890 ASSERT_EQ(kTestMessagePort2, addr2->port());
891 ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr2->ipaddr());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000892}
893
894TEST_F(StunTest, WriteMessageWithIPv6AddressAttribute) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000895 size_t size = sizeof(kStunMessageWithIPv6MappedAddress);
896
897 rtc::IPAddress test_ip(kIPv6TestAddress1);
898
Tommi408143d2022-06-01 15:29:31 +0200899 StunMessage msg(
900 STUN_BINDING_REQUEST,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000901 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
902 kStunTransactionIdLength));
903 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
904
zsteinf42cc9d2017-03-27 16:17:19 -0700905 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000906 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
907 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700908 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000909
910 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
911
jbauchf1f87202016-03-30 06:43:37 -0700912 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000913 EXPECT_TRUE(msg.Write(&out));
914 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6MappedAddress));
915 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700916 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000917 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700918 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000919 ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv6MappedAddress, len1));
920}
921
922TEST_F(StunTest, WriteMessageWithIPv4AddressAttribute) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000923 size_t size = sizeof(kStunMessageWithIPv4MappedAddress);
924
925 rtc::IPAddress test_ip(kIPv4TestAddress1);
926
Tommi408143d2022-06-01 15:29:31 +0200927 StunMessage msg(
928 STUN_BINDING_RESPONSE,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000929 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
930 kStunTransactionIdLength));
931 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
932
zsteinf42cc9d2017-03-27 16:17:19 -0700933 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000934 rtc::SocketAddress test_addr(test_ip, kTestMessagePort4);
935 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700936 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000937
938 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
939
jbauchf1f87202016-03-30 06:43:37 -0700940 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000941 EXPECT_TRUE(msg.Write(&out));
942 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4MappedAddress));
943 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700944 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000945 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700946 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000947 ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv4MappedAddress, len1));
948}
949
950TEST_F(StunTest, WriteMessageWithIPv6XorAddressAttribute) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000951 size_t size = sizeof(kStunMessageWithIPv6XorMappedAddress);
952
953 rtc::IPAddress test_ip(kIPv6TestAddress1);
954
Tommi408143d2022-06-01 15:29:31 +0200955 StunMessage msg(
956 STUN_BINDING_RESPONSE,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000957 std::string(reinterpret_cast<const char*>(kTestTransactionId2),
958 kStunTransactionIdLength));
959 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
960
zsteinf42cc9d2017-03-27 16:17:19 -0700961 auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000962 rtc::SocketAddress test_addr(test_ip, kTestMessagePort1);
963 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700964 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000965
966 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
967
jbauchf1f87202016-03-30 06:43:37 -0700968 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000969 EXPECT_TRUE(msg.Write(&out));
970 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6XorMappedAddress));
971 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700972 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000973 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700974 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000975 ASSERT_EQ(0,
976 memcmp(bytes.c_str(), kStunMessageWithIPv6XorMappedAddress, len1));
977}
978
979TEST_F(StunTest, WriteMessageWithIPv4XoreAddressAttribute) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000980 size_t size = sizeof(kStunMessageWithIPv4XorMappedAddress);
981
982 rtc::IPAddress test_ip(kIPv4TestAddress1);
983
Tommi408143d2022-06-01 15:29:31 +0200984 StunMessage msg(
985 STUN_BINDING_RESPONSE,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000986 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
987 kStunTransactionIdLength));
988 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
989
zsteinf42cc9d2017-03-27 16:17:19 -0700990 auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000991 rtc::SocketAddress test_addr(test_ip, kTestMessagePort3);
992 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700993 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000994
995 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
996
jbauchf1f87202016-03-30 06:43:37 -0700997 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000998 EXPECT_TRUE(msg.Write(&out));
999 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4XorMappedAddress));
1000 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -07001001 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001002 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -07001003 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001004 ASSERT_EQ(0,
1005 memcmp(bytes.c_str(), kStunMessageWithIPv4XorMappedAddress, len1));
1006}
1007
1008TEST_F(StunTest, ReadByteStringAttribute) {
1009 StunMessage msg;
1010 size_t size = ReadStunMessage(&msg, kStunMessageWithByteStringAttribute);
1011
1012 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1013 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
1014 const StunByteStringAttribute* username =
1015 msg.GetByteString(STUN_ATTR_USERNAME);
1016 ASSERT_TRUE(username != NULL);
Tommie83500e2022-06-03 14:28:59 +02001017 EXPECT_EQ(kTestUserName1, username->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001018}
1019
1020TEST_F(StunTest, ReadPaddedByteStringAttribute) {
1021 StunMessage msg;
Yves Gerey665174f2018-06-19 15:03:05 +02001022 size_t size =
1023 ReadStunMessage(&msg, kStunMessageWithPaddedByteStringAttribute);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001024 ASSERT_NE(0U, size);
1025 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1026 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
1027 const StunByteStringAttribute* username =
1028 msg.GetByteString(STUN_ATTR_USERNAME);
1029 ASSERT_TRUE(username != NULL);
Tommie83500e2022-06-03 14:28:59 +02001030 EXPECT_EQ(kTestUserName2, username->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001031}
1032
1033TEST_F(StunTest, ReadErrorCodeAttribute) {
1034 StunMessage msg;
1035 size_t size = ReadStunMessage(&msg, kStunMessageWithErrorAttribute);
1036
1037 CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, size);
1038 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
1039 const StunErrorCodeAttribute* errorcode = msg.GetErrorCode();
1040 ASSERT_TRUE(errorcode != NULL);
1041 EXPECT_EQ(kTestErrorClass, errorcode->eclass());
1042 EXPECT_EQ(kTestErrorNumber, errorcode->number());
1043 EXPECT_EQ(kTestErrorReason, errorcode->reason());
1044 EXPECT_EQ(kTestErrorCode, errorcode->code());
deadbeef996fc6b2017-04-26 09:21:22 -07001045 EXPECT_EQ(kTestErrorCode, msg.GetErrorCodeValue());
1046}
1047
1048// Test that GetErrorCodeValue returns STUN_ERROR_GLOBAL_FAILURE if the message
1049// in question doesn't have an error code attribute, rather than crashing.
1050TEST_F(StunTest, GetErrorCodeValueWithNoErrorAttribute) {
1051 StunMessage msg;
1052 ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
1053 EXPECT_EQ(STUN_ERROR_GLOBAL_FAILURE, msg.GetErrorCodeValue());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001054}
1055
1056TEST_F(StunTest, ReadMessageWithAUInt16ListAttribute) {
1057 StunMessage msg;
1058 size_t size = ReadStunMessage(&msg, kStunMessageWithUInt16ListAttribute);
1059 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1060 const StunUInt16ListAttribute* types = msg.GetUnknownAttributes();
1061 ASSERT_TRUE(types != NULL);
1062 EXPECT_EQ(3U, types->Size());
1063 EXPECT_EQ(0x1U, types->GetType(0));
1064 EXPECT_EQ(0x1000U, types->GetType(1));
1065 EXPECT_EQ(0xAB0CU, types->GetType(2));
1066}
1067
1068TEST_F(StunTest, ReadMessageWithAnUnknownAttribute) {
1069 StunMessage msg;
1070 size_t size = ReadStunMessage(&msg, kStunMessageWithUnknownAttribute);
1071 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1072
1073 // Parsing should have succeeded and there should be a USERNAME attribute
1074 const StunByteStringAttribute* username =
1075 msg.GetByteString(STUN_ATTR_USERNAME);
1076 ASSERT_TRUE(username != NULL);
Tommie83500e2022-06-03 14:28:59 +02001077 EXPECT_EQ(kTestUserName2, username->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001078}
1079
1080TEST_F(StunTest, WriteMessageWithAnErrorCodeAttribute) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001081 size_t size = sizeof(kStunMessageWithErrorAttribute);
1082
Tommi408143d2022-06-01 15:29:31 +02001083 StunMessage msg(
1084 STUN_BINDING_ERROR_RESPONSE,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001085 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
1086 kStunTransactionIdLength));
1087 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
zsteinf42cc9d2017-03-27 16:17:19 -07001088 auto errorcode = StunAttribute::CreateErrorCode();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001089 errorcode->SetCode(kTestErrorCode);
1090 errorcode->SetReason(kTestErrorReason);
zsteinf42cc9d2017-03-27 16:17:19 -07001091 msg.AddAttribute(std::move(errorcode));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001092 CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, (size - 20));
1093
jbauchf1f87202016-03-30 06:43:37 -07001094 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001095 EXPECT_TRUE(msg.Write(&out));
1096 ASSERT_EQ(size, out.Length());
1097 // No padding.
1098 ASSERT_EQ(0, memcmp(out.Data(), kStunMessageWithErrorAttribute, size));
1099}
1100
1101TEST_F(StunTest, WriteMessageWithAUInt16ListAttribute) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001102 size_t size = sizeof(kStunMessageWithUInt16ListAttribute);
1103
Tommi408143d2022-06-01 15:29:31 +02001104 StunMessage msg(
1105 STUN_BINDING_REQUEST,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001106 std::string(reinterpret_cast<const char*>(kTestTransactionId2),
1107 kStunTransactionIdLength));
1108 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
zsteinf42cc9d2017-03-27 16:17:19 -07001109 auto list = StunAttribute::CreateUnknownAttributes();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001110 list->AddType(0x1U);
1111 list->AddType(0x1000U);
1112 list->AddType(0xAB0CU);
zsteinf42cc9d2017-03-27 16:17:19 -07001113 msg.AddAttribute(std::move(list));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001114 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
1115
jbauchf1f87202016-03-30 06:43:37 -07001116 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001117 EXPECT_TRUE(msg.Write(&out));
1118 ASSERT_EQ(size, out.Length());
1119 // Check everything up to the padding.
1120 ASSERT_EQ(0,
1121 memcmp(out.Data(), kStunMessageWithUInt16ListAttribute, size - 2));
1122}
1123
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001124// Test that we fail to read messages with invalid lengths.
1125void CheckFailureToRead(const unsigned char* testcase, size_t length) {
1126 StunMessage msg;
1127 const char* input = reinterpret_cast<const char*>(testcase);
jbauchf1f87202016-03-30 06:43:37 -07001128 rtc::ByteBufferReader buf(input, length);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001129 ASSERT_FALSE(msg.Read(&buf));
1130}
1131
1132TEST_F(StunTest, FailToReadInvalidMessages) {
1133 CheckFailureToRead(kStunMessageWithZeroLength,
1134 kRealLengthOfInvalidLengthTestCases);
1135 CheckFailureToRead(kStunMessageWithSmallLength,
1136 kRealLengthOfInvalidLengthTestCases);
1137 CheckFailureToRead(kStunMessageWithExcessLength,
1138 kRealLengthOfInvalidLengthTestCases);
1139}
1140
1141// Test that we properly fail to read a non-STUN message.
1142TEST_F(StunTest, FailToReadRtcpPacket) {
1143 CheckFailureToRead(kRtcpPacket, sizeof(kRtcpPacket));
1144}
1145
1146// Check our STUN message validation code against the RFC5769 test messages.
1147TEST_F(StunTest, ValidateMessageIntegrity) {
1148 // Try the messages from RFC 5769.
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001149 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001150 reinterpret_cast<const char*>(kRfc5769SampleRequest),
Yves Gerey665174f2018-06-19 15:03:05 +02001151 sizeof(kRfc5769SampleRequest), kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001152 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001153 reinterpret_cast<const char*>(kRfc5769SampleRequest),
Yves Gerey665174f2018-06-19 15:03:05 +02001154 sizeof(kRfc5769SampleRequest), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001155
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001156 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001157 reinterpret_cast<const char*>(kRfc5769SampleResponse),
Yves Gerey665174f2018-06-19 15:03:05 +02001158 sizeof(kRfc5769SampleResponse), kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001159 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001160 reinterpret_cast<const char*>(kRfc5769SampleResponse),
Yves Gerey665174f2018-06-19 15:03:05 +02001161 sizeof(kRfc5769SampleResponse), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001162
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001163 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001164 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
Yves Gerey665174f2018-06-19 15:03:05 +02001165 sizeof(kRfc5769SampleResponseIPv6), kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001166 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001167 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
Yves Gerey665174f2018-06-19 15:03:05 +02001168 sizeof(kRfc5769SampleResponseIPv6), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001169
1170 // We first need to compute the key for the long-term authentication HMAC.
1171 std::string key;
1172 ComputeStunCredentialHash(kRfc5769SampleMsgWithAuthUsername,
Yves Gerey665174f2018-06-19 15:03:05 +02001173 kRfc5769SampleMsgWithAuthRealm,
1174 kRfc5769SampleMsgWithAuthPassword, &key);
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001175 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001176 reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth),
1177 sizeof(kRfc5769SampleRequestLongTermAuth), key));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001178 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001179 reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth),
Yves Gerey665174f2018-06-19 15:03:05 +02001180 sizeof(kRfc5769SampleRequestLongTermAuth), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001181
1182 // Try some edge cases.
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001183 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001184 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
Yves Gerey665174f2018-06-19 15:03:05 +02001185 sizeof(kStunMessageWithZeroLength), kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001186 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001187 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
Yves Gerey665174f2018-06-19 15:03:05 +02001188 sizeof(kStunMessageWithExcessLength), kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001189 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001190 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
Yves Gerey665174f2018-06-19 15:03:05 +02001191 sizeof(kStunMessageWithSmallLength), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001192
katrielc1a206102016-06-20 05:13:16 -07001193 // Again, but with the lengths matching what is claimed in the headers.
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001194 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
katrielc1a206102016-06-20 05:13:16 -07001195 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1196 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithZeroLength[2]),
1197 kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001198 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
katrielc1a206102016-06-20 05:13:16 -07001199 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1200 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithExcessLength[2]),
1201 kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001202 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
katrielc1a206102016-06-20 05:13:16 -07001203 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1204 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithSmallLength[2]),
1205 kRfc5769SampleMsgPassword));
1206
1207 // Check that a too-short HMAC doesn't cause buffer overflow.
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001208 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
katrielc1a206102016-06-20 05:13:16 -07001209 reinterpret_cast<const char*>(kStunMessageWithBadHmacAtEnd),
Yves Gerey665174f2018-06-19 15:03:05 +02001210 sizeof(kStunMessageWithBadHmacAtEnd), kRfc5769SampleMsgPassword));
katrielc1a206102016-06-20 05:13:16 -07001211
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001212 // Test that munging a single bit anywhere in the message causes the
1213 // message-integrity check to fail, unless it is after the M-I attribute.
1214 char buf[sizeof(kRfc5769SampleRequest)];
1215 memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest));
1216 for (size_t i = 0; i < sizeof(buf); ++i) {
1217 buf[i] ^= 0x01;
1218 if (i > 0)
1219 buf[i - 1] ^= 0x01;
Yves Gerey665174f2018-06-19 15:03:05 +02001220 EXPECT_EQ(i >= sizeof(buf) - 8,
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001221 StunMessage::ValidateMessageIntegrityForTesting(
1222 buf, sizeof(buf), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001223 }
1224}
1225
1226// Validate that we generate correct MESSAGE-INTEGRITY attributes.
1227// Note the use of IceMessage instead of StunMessage; this is necessary because
1228// the RFC5769 test messages used include attributes not found in basic STUN.
1229TEST_F(StunTest, AddMessageIntegrity) {
1230 IceMessage msg;
jbauchf1f87202016-03-30 06:43:37 -07001231 rtc::ByteBufferReader buf(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001232 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1233 sizeof(kRfc5769SampleRequestWithoutMI));
1234 EXPECT_TRUE(msg.Read(&buf));
1235 EXPECT_TRUE(msg.AddMessageIntegrity(kRfc5769SampleMsgPassword));
1236 const StunByteStringAttribute* mi_attr =
1237 msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
1238 EXPECT_EQ(20U, mi_attr->length());
Yves Gerey665174f2018-06-19 15:03:05 +02001239 EXPECT_EQ(
1240 0, memcmp(mi_attr->bytes(), kCalculatedHmac1, sizeof(kCalculatedHmac1)));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001241
jbauchf1f87202016-03-30 06:43:37 -07001242 rtc::ByteBufferWriter buf1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001243 EXPECT_TRUE(msg.Write(&buf1));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001244 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
Yves Gerey665174f2018-06-19 15:03:05 +02001245 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(),
1246 kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001247
1248 IceMessage msg2;
jbauchf1f87202016-03-30 06:43:37 -07001249 rtc::ByteBufferReader buf2(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001250 reinterpret_cast<const char*>(kRfc5769SampleResponseWithoutMI),
1251 sizeof(kRfc5769SampleResponseWithoutMI));
1252 EXPECT_TRUE(msg2.Read(&buf2));
1253 EXPECT_TRUE(msg2.AddMessageIntegrity(kRfc5769SampleMsgPassword));
1254 const StunByteStringAttribute* mi_attr2 =
1255 msg2.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
1256 EXPECT_EQ(20U, mi_attr2->length());
1257 EXPECT_EQ(
1258 0, memcmp(mi_attr2->bytes(), kCalculatedHmac2, sizeof(kCalculatedHmac2)));
1259
jbauchf1f87202016-03-30 06:43:37 -07001260 rtc::ByteBufferWriter buf3;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001261 EXPECT_TRUE(msg2.Write(&buf3));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001262 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
Yves Gerey665174f2018-06-19 15:03:05 +02001263 reinterpret_cast<const char*>(buf3.Data()), buf3.Length(),
1264 kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001265}
1266
1267// Check our STUN message validation code against the RFC5769 test messages.
Jonas Oreland63737a92019-11-21 15:12:14 +01001268TEST_F(StunTest, ValidateMessageIntegrity32) {
1269 // Try the messages from RFC 5769.
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001270 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001271 reinterpret_cast<const char*>(kSampleRequestMI32),
1272 sizeof(kSampleRequestMI32), kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001273 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001274 reinterpret_cast<const char*>(kSampleRequestMI32),
1275 sizeof(kSampleRequestMI32), "InvalidPassword"));
1276
1277 // Try some edge cases.
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001278 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001279 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1280 sizeof(kStunMessageWithZeroLength), kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001281 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001282 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1283 sizeof(kStunMessageWithExcessLength), kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001284 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001285 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1286 sizeof(kStunMessageWithSmallLength), kRfc5769SampleMsgPassword));
1287
1288 // Again, but with the lengths matching what is claimed in the headers.
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001289 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001290 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1291 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithZeroLength[2]),
1292 kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001293 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001294 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1295 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithExcessLength[2]),
1296 kRfc5769SampleMsgPassword));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001297 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001298 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1299 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithSmallLength[2]),
1300 kRfc5769SampleMsgPassword));
1301
1302 // Check that a too-short HMAC doesn't cause buffer overflow.
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001303 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001304 reinterpret_cast<const char*>(kStunMessageWithBadHmacAtEnd),
1305 sizeof(kStunMessageWithBadHmacAtEnd), kRfc5769SampleMsgPassword));
1306
1307 // Test that munging a single bit anywhere in the message causes the
1308 // message-integrity check to fail, unless it is after the M-I attribute.
1309 char buf[sizeof(kSampleRequestMI32)];
1310 memcpy(buf, kSampleRequestMI32, sizeof(kSampleRequestMI32));
1311 for (size_t i = 0; i < sizeof(buf); ++i) {
1312 buf[i] ^= 0x01;
1313 if (i > 0)
1314 buf[i - 1] ^= 0x01;
1315 EXPECT_EQ(i >= sizeof(buf) - 8,
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001316 StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001317 buf, sizeof(buf), kRfc5769SampleMsgPassword));
1318 }
1319}
1320
1321// Validate that we generate correct MESSAGE-INTEGRITY-32 attributes.
1322TEST_F(StunTest, AddMessageIntegrity32) {
1323 IceMessage msg;
1324 rtc::ByteBufferReader buf(
1325 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1326 sizeof(kRfc5769SampleRequestWithoutMI));
1327 EXPECT_TRUE(msg.Read(&buf));
1328 EXPECT_TRUE(msg.AddMessageIntegrity32(kRfc5769SampleMsgPassword));
1329 const StunByteStringAttribute* mi_attr =
1330 msg.GetByteString(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32);
1331 EXPECT_EQ(4U, mi_attr->length());
1332 EXPECT_EQ(0, memcmp(mi_attr->bytes(), kCalculatedHmac1_32,
1333 sizeof(kCalculatedHmac1_32)));
1334
1335 rtc::ByteBufferWriter buf1;
1336 EXPECT_TRUE(msg.Write(&buf1));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001337 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001338 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(),
1339 kRfc5769SampleMsgPassword));
1340
1341 IceMessage msg2;
1342 rtc::ByteBufferReader buf2(
1343 reinterpret_cast<const char*>(kRfc5769SampleResponseWithoutMI),
1344 sizeof(kRfc5769SampleResponseWithoutMI));
1345 EXPECT_TRUE(msg2.Read(&buf2));
1346 EXPECT_TRUE(msg2.AddMessageIntegrity32(kRfc5769SampleMsgPassword));
1347 const StunByteStringAttribute* mi_attr2 =
1348 msg2.GetByteString(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32);
1349 EXPECT_EQ(4U, mi_attr2->length());
1350 EXPECT_EQ(0, memcmp(mi_attr2->bytes(), kCalculatedHmac2_32,
1351 sizeof(kCalculatedHmac2_32)));
1352
1353 rtc::ByteBufferWriter buf3;
1354 EXPECT_TRUE(msg2.Write(&buf3));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001355 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001356 reinterpret_cast<const char*>(buf3.Data()), buf3.Length(),
1357 kRfc5769SampleMsgPassword));
1358}
1359
1360// Validate that the message validates if both MESSAGE-INTEGRITY-32 and
1361// MESSAGE-INTEGRITY are present in the message.
1362// This is not expected to be used, but is not forbidden.
1363TEST_F(StunTest, AddMessageIntegrity32AndMessageIntegrity) {
1364 IceMessage msg;
1365 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1366 attr->CopyBytes("keso", sizeof("keso"));
1367 msg.AddAttribute(std::move(attr));
1368 msg.AddMessageIntegrity32("password1");
1369 msg.AddMessageIntegrity("password2");
1370
1371 rtc::ByteBufferWriter buf1;
1372 EXPECT_TRUE(msg.Write(&buf1));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001373 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001374 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password1"));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001375 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001376 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password2"));
1377
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001378 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001379 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password2"));
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001380 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
Jonas Oreland63737a92019-11-21 15:12:14 +01001381 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password1"));
1382}
1383
1384// Check our STUN message validation code against the RFC5769 test messages.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001385TEST_F(StunTest, ValidateFingerprint) {
1386 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1387 reinterpret_cast<const char*>(kRfc5769SampleRequest),
1388 sizeof(kRfc5769SampleRequest)));
1389 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1390 reinterpret_cast<const char*>(kRfc5769SampleResponse),
1391 sizeof(kRfc5769SampleResponse)));
1392 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1393 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
1394 sizeof(kRfc5769SampleResponseIPv6)));
1395
1396 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1397 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1398 sizeof(kStunMessageWithZeroLength)));
1399 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1400 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1401 sizeof(kStunMessageWithExcessLength)));
1402 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1403 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1404 sizeof(kStunMessageWithSmallLength)));
1405
1406 // Test that munging a single bit anywhere in the message causes the
1407 // fingerprint check to fail.
1408 char buf[sizeof(kRfc5769SampleRequest)];
1409 memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest));
1410 for (size_t i = 0; i < sizeof(buf); ++i) {
1411 buf[i] ^= 0x01;
1412 if (i > 0)
1413 buf[i - 1] ^= 0x01;
1414 EXPECT_FALSE(StunMessage::ValidateFingerprint(buf, sizeof(buf)));
1415 }
1416 // Put them all back to normal and the check should pass again.
1417 buf[sizeof(buf) - 1] ^= 0x01;
1418 EXPECT_TRUE(StunMessage::ValidateFingerprint(buf, sizeof(buf)));
1419}
1420
1421TEST_F(StunTest, AddFingerprint) {
1422 IceMessage msg;
jbauchf1f87202016-03-30 06:43:37 -07001423 rtc::ByteBufferReader buf(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001424 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1425 sizeof(kRfc5769SampleRequestWithoutMI));
1426 EXPECT_TRUE(msg.Read(&buf));
1427 EXPECT_TRUE(msg.AddFingerprint());
1428
jbauchf1f87202016-03-30 06:43:37 -07001429 rtc::ByteBufferWriter buf1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001430 EXPECT_TRUE(msg.Write(&buf1));
1431 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1432 reinterpret_cast<const char*>(buf1.Data()), buf1.Length()));
1433}
1434
1435// Sample "GTURN" relay message.
Yves Gerey665174f2018-06-19 15:03:05 +02001436// clang-format off
1437// clang formatting doesn't respect inline comments.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001438static const unsigned char kRelayMessage[] = {
1439 0x00, 0x01, 0x00, 88, // message header
1440 0x21, 0x12, 0xA4, 0x42, // magic cookie
1441 '0', '1', '2', '3', // transaction id
1442 '4', '5', '6', '7',
1443 '8', '9', 'a', 'b',
1444 0x00, 0x01, 0x00, 8, // mapped address
1445 0x00, 0x01, 0x00, 13,
1446 0x00, 0x00, 0x00, 17,
1447 0x00, 0x06, 0x00, 12, // username
1448 'a', 'b', 'c', 'd',
1449 'e', 'f', 'g', 'h',
1450 'i', 'j', 'k', 'l',
1451 0x00, 0x0d, 0x00, 4, // lifetime
1452 0x00, 0x00, 0x00, 11,
1453 0x00, 0x0f, 0x00, 4, // magic cookie
1454 0x72, 0xc6, 0x4b, 0xc6,
1455 0x00, 0x10, 0x00, 4, // bandwidth
1456 0x00, 0x00, 0x00, 6,
1457 0x00, 0x11, 0x00, 8, // destination address
1458 0x00, 0x01, 0x00, 13,
1459 0x00, 0x00, 0x00, 17,
1460 0x00, 0x12, 0x00, 8, // source address 2
1461 0x00, 0x01, 0x00, 13,
1462 0x00, 0x00, 0x00, 17,
1463 0x00, 0x13, 0x00, 7, // data
1464 'a', 'b', 'c', 'd',
1465 'e', 'f', 'g', 0 // DATA must be padded per rfc5766.
1466};
Yves Gerey665174f2018-06-19 15:03:05 +02001467// clang-format on
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001468
1469// Test that we can read the GTURN-specific fields.
1470TEST_F(StunTest, ReadRelayMessage) {
Tommi408143d2022-06-01 15:29:31 +02001471 RelayMessage msg;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001472
1473 const char* input = reinterpret_cast<const char*>(kRelayMessage);
1474 size_t size = sizeof(kRelayMessage);
jbauchf1f87202016-03-30 06:43:37 -07001475 rtc::ByteBufferReader buf(input, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001476 EXPECT_TRUE(msg.Read(&buf));
1477
1478 EXPECT_EQ(STUN_BINDING_REQUEST, msg.type());
1479 EXPECT_EQ(size - 20, msg.length());
1480 EXPECT_EQ("0123456789ab", msg.transaction_id());
1481
Tommi408143d2022-06-01 15:29:31 +02001482 RelayMessage msg2(STUN_BINDING_REQUEST, "0123456789ab");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001483
1484 in_addr legacy_in_addr;
1485 legacy_in_addr.s_addr = htonl(17U);
1486 rtc::IPAddress legacy_ip(legacy_in_addr);
1487
1488 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
1489 ASSERT_TRUE(addr != NULL);
1490 EXPECT_EQ(1, addr->family());
1491 EXPECT_EQ(13, addr->port());
1492 EXPECT_EQ(legacy_ip, addr->ipaddr());
1493
zsteinf42cc9d2017-03-27 16:17:19 -07001494 auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001495 addr2->SetPort(13);
1496 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001497 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001498
1499 const StunByteStringAttribute* bytes = msg.GetByteString(STUN_ATTR_USERNAME);
1500 ASSERT_TRUE(bytes != NULL);
1501 EXPECT_EQ(12U, bytes->length());
Tommie83500e2022-06-03 14:28:59 +02001502 EXPECT_EQ("abcdefghijkl", bytes->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001503
zsteinf42cc9d2017-03-27 16:17:19 -07001504 auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001505 bytes2->CopyBytes("abcdefghijkl");
zsteinf42cc9d2017-03-27 16:17:19 -07001506 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001507
1508 const StunUInt32Attribute* uval = msg.GetUInt32(STUN_ATTR_LIFETIME);
1509 ASSERT_TRUE(uval != NULL);
1510 EXPECT_EQ(11U, uval->value());
1511
zsteinf42cc9d2017-03-27 16:17:19 -07001512 auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001513 uval2->SetValue(11);
zsteinf42cc9d2017-03-27 16:17:19 -07001514 msg2.AddAttribute(std::move(uval2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001515
1516 bytes = msg.GetByteString(STUN_ATTR_MAGIC_COOKIE);
1517 ASSERT_TRUE(bytes != NULL);
1518 EXPECT_EQ(4U, bytes->length());
Yves Gerey665174f2018-06-19 15:03:05 +02001519 EXPECT_EQ(0, memcmp(bytes->bytes(), TURN_MAGIC_COOKIE_VALUE,
1520 sizeof(TURN_MAGIC_COOKIE_VALUE)));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001521
1522 bytes2 = StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
1523 bytes2->CopyBytes(reinterpret_cast<const char*>(TURN_MAGIC_COOKIE_VALUE),
1524 sizeof(TURN_MAGIC_COOKIE_VALUE));
zsteinf42cc9d2017-03-27 16:17:19 -07001525 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001526
1527 uval = msg.GetUInt32(STUN_ATTR_BANDWIDTH);
1528 ASSERT_TRUE(uval != NULL);
1529 EXPECT_EQ(6U, uval->value());
1530
1531 uval2 = StunAttribute::CreateUInt32(STUN_ATTR_BANDWIDTH);
1532 uval2->SetValue(6);
zsteinf42cc9d2017-03-27 16:17:19 -07001533 msg2.AddAttribute(std::move(uval2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001534
1535 addr = msg.GetAddress(STUN_ATTR_DESTINATION_ADDRESS);
1536 ASSERT_TRUE(addr != NULL);
1537 EXPECT_EQ(1, addr->family());
1538 EXPECT_EQ(13, addr->port());
1539 EXPECT_EQ(legacy_ip, addr->ipaddr());
1540
1541 addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
1542 addr2->SetPort(13);
1543 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001544 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001545
1546 addr = msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2);
1547 ASSERT_TRUE(addr != NULL);
1548 EXPECT_EQ(1, addr->family());
1549 EXPECT_EQ(13, addr->port());
1550 EXPECT_EQ(legacy_ip, addr->ipaddr());
1551
1552 addr2 = StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2);
1553 addr2->SetPort(13);
1554 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001555 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001556
1557 bytes = msg.GetByteString(STUN_ATTR_DATA);
1558 ASSERT_TRUE(bytes != NULL);
1559 EXPECT_EQ(7U, bytes->length());
Tommie83500e2022-06-03 14:28:59 +02001560 EXPECT_EQ("abcdefg", bytes->string_view());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001561
1562 bytes2 = StunAttribute::CreateByteString(STUN_ATTR_DATA);
1563 bytes2->CopyBytes("abcdefg");
zsteinf42cc9d2017-03-27 16:17:19 -07001564 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001565
jbauchf1f87202016-03-30 06:43:37 -07001566 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001567 EXPECT_TRUE(msg.Write(&out));
1568 EXPECT_EQ(size, out.Length());
1569 size_t len1 = out.Length();
jbauchf1f87202016-03-30 06:43:37 -07001570 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001571 std::string outstring;
jbauchf1f87202016-03-30 06:43:37 -07001572 read_buf.ReadString(&outstring, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001573 EXPECT_EQ(0, memcmp(outstring.c_str(), input, len1));
1574
jbauchf1f87202016-03-30 06:43:37 -07001575 rtc::ByteBufferWriter out2;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001576 EXPECT_TRUE(msg2.Write(&out2));
1577 EXPECT_EQ(size, out2.Length());
1578 size_t len2 = out2.Length();
jbauchf1f87202016-03-30 06:43:37 -07001579 rtc::ByteBufferReader read_buf2(out2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001580 std::string outstring2;
jbauchf1f87202016-03-30 06:43:37 -07001581 read_buf2.ReadString(&outstring2, len2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001582 EXPECT_EQ(0, memcmp(outstring2.c_str(), input, len2));
1583}
1584
Jonas Oreland202994c2017-12-18 12:10:43 +01001585// Test that we can remove attribute from a message.
1586TEST_F(StunTest, RemoveAttribute) {
1587 StunMessage msg;
1588
1589 // Removing something that does exist should return nullptr.
1590 EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr);
1591
1592 {
1593 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1594 attr->CopyBytes("kes", sizeof("kes"));
1595 msg.AddAttribute(std::move(attr));
1596 }
1597
1598 size_t len = msg.length();
1599 {
1600 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1601 ASSERT_NE(attr, nullptr);
1602 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1603 EXPECT_STREQ("kes",
1604 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1605 EXPECT_LT(msg.length(), len);
1606 }
1607
1608 // Now add same attribute type twice.
1609 {
1610 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1611 attr->CopyBytes("kes", sizeof("kes"));
1612 msg.AddAttribute(std::move(attr));
1613 }
1614
1615 {
1616 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1617 attr->CopyBytes("kenta", sizeof("kenta"));
1618 msg.AddAttribute(std::move(attr));
1619 }
1620
1621 // Remove should remove the last added occurrence.
1622 {
1623 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1624 ASSERT_NE(attr, nullptr);
1625 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1626 EXPECT_STREQ("kenta",
1627 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1628 }
1629
1630 // Remove should remove the last added occurrence.
1631 {
1632 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1633 ASSERT_NE(attr, nullptr);
1634 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1635 EXPECT_STREQ("kes",
1636 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1637 }
1638
1639 // Removing something that does exist should return nullptr.
1640 EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr);
1641}
1642
Jonas Oreland63737a92019-11-21 15:12:14 +01001643// Test that we can remove attribute from a message.
1644TEST_F(StunTest, ClearAttributes) {
1645 StunMessage msg;
1646
1647 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1648 attr->CopyBytes("kes", sizeof("kes"));
1649 msg.AddAttribute(std::move(attr));
1650 size_t len = msg.length();
1651
1652 msg.ClearAttributes();
1653 EXPECT_EQ(msg.length(), len - /* 3 + 1 byte padding + header */ 8);
1654 EXPECT_EQ(nullptr, msg.GetByteString(STUN_ATTR_USERNAME));
1655}
1656
Jonas Oreland202994c2017-12-18 12:10:43 +01001657// Test CopyStunAttribute
1658TEST_F(StunTest, CopyAttribute) {
1659 rtc::ByteBufferWriter buf;
Yves Gerey665174f2018-06-19 15:03:05 +02001660 rtc::ByteBufferWriter* buffer_ptrs[] = {&buf, nullptr};
Jonas Oreland202994c2017-12-18 12:10:43 +01001661 // Test both with and without supplied ByteBufferWriter.
1662 for (auto buffer_ptr : buffer_ptrs) {
Yves Gerey665174f2018-06-19 15:03:05 +02001663 { // Test StunByteStringAttribute.
Jonas Oreland202994c2017-12-18 12:10:43 +01001664 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1665 attr->CopyBytes("kes", sizeof("kes"));
1666
1667 auto copy = CopyStunAttribute(*attr.get(), buffer_ptr);
1668 ASSERT_EQ(copy->value_type(), STUN_VALUE_BYTE_STRING);
1669 EXPECT_STREQ("kes",
1670 static_cast<StunByteStringAttribute*>(copy.get())->bytes());
1671 }
1672
Yves Gerey665174f2018-06-19 15:03:05 +02001673 { // Test StunAddressAttribute.
Jonas Oreland202994c2017-12-18 12:10:43 +01001674 rtc::IPAddress test_ip(kIPv6TestAddress2);
1675 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
1676 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
1677 addr->SetAddress(test_addr);
Yves Gerey665174f2018-06-19 15:03:05 +02001678 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6,
1679 kTestMessagePort2, test_ip);
Jonas Oreland202994c2017-12-18 12:10:43 +01001680
1681 auto copy = CopyStunAttribute(*addr.get(), buffer_ptr);
1682 ASSERT_EQ(copy->value_type(), STUN_VALUE_ADDRESS);
1683 CheckStunAddressAttribute(static_cast<StunAddressAttribute*>(copy.get()),
1684 STUN_ADDRESS_IPV6, kTestMessagePort2, test_ip);
1685 }
Jonas Oreland63737a92019-11-21 15:12:14 +01001686
1687 { // Test StunAddressAttribute.
1688 rtc::IPAddress test_ip(kIPv6TestAddress2);
1689 auto addr = StunAttribute::CreateAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
1690 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
1691 addr->SetAddress(test_addr);
1692 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6,
1693 kTestMessagePort2, test_ip);
1694
1695 auto copy = CopyStunAttribute(*addr.get(), buffer_ptr);
1696 ASSERT_EQ(copy->value_type(), STUN_VALUE_ADDRESS);
1697 CheckStunAddressAttribute(static_cast<StunAddressAttribute*>(copy.get()),
1698 STUN_ADDRESS_IPV6, kTestMessagePort2, test_ip);
1699 }
Jonas Oreland202994c2017-12-18 12:10:43 +01001700 }
1701}
1702
Jonas Oreland253d50f2019-11-28 17:08:07 +01001703// Test Clone
1704TEST_F(StunTest, Clone) {
Tommi408143d2022-06-01 15:29:31 +02001705 IceMessage msg(0, "0123456789ab");
Jonas Oreland253d50f2019-11-28 17:08:07 +01001706 {
1707 auto errorcode = StunAttribute::CreateErrorCode();
1708 errorcode->SetCode(kTestErrorCode);
1709 errorcode->SetReason(kTestErrorReason);
1710 msg.AddAttribute(std::move(errorcode));
1711 }
1712 {
1713 auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1714 bytes2->CopyBytes("abcdefghijkl");
1715 msg.AddAttribute(std::move(bytes2));
1716 }
1717 {
1718 auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_RETRANSMIT_COUNT);
1719 uval2->SetValue(11);
1720 msg.AddAttribute(std::move(uval2));
1721 }
1722 {
1723 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
1724 addr->SetIP(rtc::IPAddress(kIPv6TestAddress1));
1725 addr->SetPort(kTestMessagePort1);
1726 msg.AddAttribute(std::move(addr));
1727 }
1728 auto copy = msg.Clone();
1729 ASSERT_NE(nullptr, copy.get());
1730
Jonas Oreland253d50f2019-11-28 17:08:07 +01001731 rtc::ByteBufferWriter out1;
1732 EXPECT_TRUE(msg.Write(&out1));
1733 rtc::ByteBufferWriter out2;
1734 EXPECT_TRUE(copy->Write(&out2));
1735
1736 ASSERT_EQ(out1.Length(), out2.Length());
1737 EXPECT_EQ(0, memcmp(out1.Data(), out2.Data(), out1.Length()));
1738}
1739
1740// Test EqualAttributes
1741TEST_F(StunTest, EqualAttributes) {
1742 IceMessage msg;
1743 {
1744 auto errorcode = StunAttribute::CreateErrorCode();
1745 errorcode->SetCode(kTestErrorCode);
1746 errorcode->SetReason(kTestErrorReason);
1747 msg.AddAttribute(std::move(errorcode));
1748 }
1749 {
1750 auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1751 bytes2->CopyBytes("abcdefghijkl");
1752 msg.AddAttribute(std::move(bytes2));
1753 }
1754 {
1755 auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_RETRANSMIT_COUNT);
1756 uval2->SetValue(11);
1757 msg.AddAttribute(std::move(uval2));
1758 }
1759 {
1760 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
1761 addr->SetIP(rtc::IPAddress(kIPv6TestAddress1));
1762 addr->SetPort(kTestMessagePort1);
1763 msg.AddAttribute(std::move(addr));
1764 }
1765 auto copy = msg.Clone();
1766 ASSERT_NE(nullptr, copy.get());
1767
1768 EXPECT_TRUE(copy->EqualAttributes(&msg, [](int type) { return true; }));
1769
1770 {
1771 auto attr = StunAttribute::CreateByteString(STUN_ATTR_NONCE);
1772 attr->CopyBytes("keso");
1773 msg.AddAttribute(std::move(attr));
1774 EXPECT_FALSE(copy->EqualAttributes(&msg, [](int type) { return true; }));
1775 EXPECT_TRUE(copy->EqualAttributes(
1776 &msg, [](int type) { return type != STUN_ATTR_NONCE; }));
1777 }
1778
1779 {
1780 auto attr = StunAttribute::CreateByteString(STUN_ATTR_NONCE);
1781 attr->CopyBytes("keso");
1782 copy->AddAttribute(std::move(attr));
1783 EXPECT_TRUE(copy->EqualAttributes(&msg, [](int type) { return true; }));
1784 }
1785 {
1786 copy->RemoveAttribute(STUN_ATTR_NONCE);
1787 auto attr = StunAttribute::CreateByteString(STUN_ATTR_NONCE);
1788 attr->CopyBytes("kent");
1789 copy->AddAttribute(std::move(attr));
1790 EXPECT_FALSE(copy->EqualAttributes(&msg, [](int type) { return true; }));
1791 EXPECT_TRUE(copy->EqualAttributes(
1792 &msg, [](int type) { return type != STUN_ATTR_NONCE; }));
1793 }
1794
1795 {
1796 msg.RemoveAttribute(STUN_ATTR_NONCE);
1797 EXPECT_FALSE(copy->EqualAttributes(&msg, [](int type) { return true; }));
1798 EXPECT_TRUE(copy->EqualAttributes(
1799 &msg, [](int type) { return type != STUN_ATTR_NONCE; }));
1800 }
1801}
1802
Zach Steinff71a492018-12-07 11:25:12 -08001803TEST_F(StunTest, ReduceTransactionIdIsHostOrderIndependent) {
Tommi408143d2022-06-01 15:29:31 +02001804 const std::string transaction_id = "abcdefghijkl";
1805 StunMessage message(0, transaction_id);
Zach Steinff71a492018-12-07 11:25:12 -08001806 uint32_t reduced_transaction_id = message.reduced_transaction_id();
1807 EXPECT_EQ(reduced_transaction_id, 1835954016u);
1808}
1809
Jonas Oreland1721de12019-11-20 12:10:39 +01001810TEST_F(StunTest, GoogMiscInfo) {
Tommi408143d2022-06-01 15:29:31 +02001811 StunMessage msg(STUN_BINDING_REQUEST, "ABCDEFGHIJKL");
Jonas Oreland1721de12019-11-20 12:10:39 +01001812 const size_t size =
1813 /* msg header */ 20 +
1814 /* attr header */ 4 +
1815 /* 3 * 2 rounded to multiple of 4 */ 8;
Jonas Oreland1721de12019-11-20 12:10:39 +01001816 auto list =
1817 StunAttribute::CreateUInt16ListAttribute(STUN_ATTR_GOOG_MISC_INFO);
Jonas Oreland63737a92019-11-21 15:12:14 +01001818 list->AddTypeAtIndex(0, 0x1U);
1819 list->AddTypeAtIndex(3, 0x1000U);
1820 list->AddTypeAtIndex(2, 0xAB0CU);
Jonas Oreland1721de12019-11-20 12:10:39 +01001821 msg.AddAttribute(std::move(list));
1822 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
1823
1824 rtc::ByteBufferWriter out;
1825 EXPECT_TRUE(msg.Write(&out));
1826 ASSERT_EQ(size, out.Length());
1827
1828 size_t read_size = ReadStunMessageTestCase(
1829 &msg, reinterpret_cast<const unsigned char*>(out.Data()), out.Length());
1830 ASSERT_EQ(read_size + 20, size);
1831 CheckStunHeader(msg, STUN_BINDING_REQUEST, read_size);
1832 const StunUInt16ListAttribute* types =
1833 msg.GetUInt16List(STUN_ATTR_GOOG_MISC_INFO);
1834 ASSERT_TRUE(types != NULL);
Jonas Oreland63737a92019-11-21 15:12:14 +01001835 EXPECT_EQ(4U, types->Size());
Jonas Oreland1721de12019-11-20 12:10:39 +01001836 EXPECT_EQ(0x1U, types->GetType(0));
Jonas Oreland63737a92019-11-21 15:12:14 +01001837 EXPECT_EQ(0x0U, types->GetType(1));
1838 EXPECT_EQ(0x1000U, types->GetType(3));
Jonas Oreland1721de12019-11-20 12:10:39 +01001839 EXPECT_EQ(0xAB0CU, types->GetType(2));
1840}
1841
Jonas Oreland253d50f2019-11-28 17:08:07 +01001842TEST_F(StunTest, IsStunMethod) {
1843 int methods[] = {STUN_BINDING_REQUEST};
1844 EXPECT_TRUE(StunMessage::IsStunMethod(
1845 methods, reinterpret_cast<const char*>(kRfc5769SampleRequest),
1846 sizeof(kRfc5769SampleRequest)));
1847}
1848
Harald Alvestrandbee64082020-11-12 11:17:41 +00001849TEST_F(StunTest, SizeRestrictionOnAttributes) {
Tommi408143d2022-06-01 15:29:31 +02001850 StunMessage msg(STUN_BINDING_REQUEST, "ABCDEFGHIJKL");
Harald Alvestrandbee64082020-11-12 11:17:41 +00001851 auto long_username = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1852 std::string long_string(509, 'x');
1853 long_username->CopyBytes(long_string.c_str(), long_string.size());
1854 msg.AddAttribute(std::move(long_username));
1855 rtc::ByteBufferWriter out;
1856 ASSERT_FALSE(msg.Write(&out));
1857}
1858
Harald Alvestrandac757782022-10-11 12:18:34 +00001859TEST_F(StunTest, ValidateMessageIntegrityWithParser) {
1860 webrtc::metrics::Reset(); // Ensure counters start from zero.
1861 // Try the messages from RFC 5769.
1862 StunMessage message;
1863 rtc::ByteBufferReader reader(
1864 reinterpret_cast<const char*>(kRfc5769SampleRequest),
1865 sizeof(kRfc5769SampleRequest));
1866 EXPECT_TRUE(message.Read(&reader));
1867 EXPECT_EQ(message.ValidateMessageIntegrity(kRfc5769SampleMsgPassword),
1868 StunMessage::IntegrityStatus::kIntegrityOk);
1869 EXPECT_EQ(webrtc::metrics::NumEvents(
1870 "WebRTC.Stun.Integrity.Request",
1871 static_cast<int>(StunMessage::IntegrityStatus::kIntegrityOk)),
1872 1);
Harald Alvestrand47627622022-10-13 09:57:05 +00001873 EXPECT_EQ(message.RevalidateMessageIntegrity("Invalid password"),
Harald Alvestrandac757782022-10-11 12:18:34 +00001874 StunMessage::IntegrityStatus::kIntegrityBad);
1875 EXPECT_EQ(webrtc::metrics::NumEvents(
1876 "WebRTC.Stun.Integrity.Request",
1877 static_cast<int>(StunMessage::IntegrityStatus::kIntegrityBad)),
1878 1);
1879 EXPECT_EQ(webrtc::metrics::NumSamples("WebRTC.Stun.Integrity.Request"), 2);
1880}
1881
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001882} // namespace cricket