blob: c75fb90500f5bf0d5cffb1e5460c78a4940c06eb [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Patrik Höglund56d94522019-11-18 15:53:32 +010011#include "api/transport/stun.h"
Jonas Olssona4d87372019-07-05 19:08:33 +020012
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Mirko Bonadei317a1f02019-09-17 17:06:18 +020015#include <memory>
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000016#include <string>
Steve Anton6c38cc72017-11-29 10:25:58 -080017#include <utility>
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000018
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "rtc_base/arraysize.h"
Steve Anton10542f22019-01-11 09:11:00 -080020#include "rtc_base/byte_buffer.h"
21#include "rtc_base/byte_order.h"
22#include "rtc_base/socket_address.h"
Yves Gerey3e707812018-11-28 16:47:49 +010023#include "test/gtest.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000024
25namespace cricket {
26
27class StunTest : public ::testing::Test {
28 protected:
Yves Gerey665174f2018-06-19 15:03:05 +020029 void CheckStunHeader(const StunMessage& msg,
30 StunMessageType expected_type,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000031 size_t expected_length) {
32 ASSERT_EQ(expected_type, msg.type());
33 ASSERT_EQ(expected_length, msg.length());
34 }
35
36 void CheckStunTransactionID(const StunMessage& msg,
Yves Gerey665174f2018-06-19 15:03:05 +020037 const unsigned char* expectedID,
38 size_t length) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000039 ASSERT_EQ(length, msg.transaction_id().size());
40 ASSERT_EQ(length == kStunTransactionIdLength + 4, msg.IsLegacy());
41 ASSERT_EQ(length == kStunTransactionIdLength, !msg.IsLegacy());
42 ASSERT_EQ(0, memcmp(msg.transaction_id().c_str(), expectedID, length));
43 }
44
45 void CheckStunAddressAttribute(const StunAddressAttribute* addr,
46 StunAddressFamily expected_family,
47 int expected_port,
48 rtc::IPAddress expected_address) {
49 ASSERT_EQ(expected_family, addr->family());
50 ASSERT_EQ(expected_port, addr->port());
51
52 if (addr->family() == STUN_ADDRESS_IPV4) {
53 in_addr v4_address = expected_address.ipv4_address();
54 in_addr stun_address = addr->ipaddr().ipv4_address();
55 ASSERT_EQ(0, memcmp(&v4_address, &stun_address, sizeof(stun_address)));
56 } else if (addr->family() == STUN_ADDRESS_IPV6) {
57 in6_addr v6_address = expected_address.ipv6_address();
58 in6_addr stun_address = addr->ipaddr().ipv6_address();
59 ASSERT_EQ(0, memcmp(&v6_address, &stun_address, sizeof(stun_address)));
60 } else {
61 ASSERT_TRUE(addr->family() == STUN_ADDRESS_IPV6 ||
62 addr->family() == STUN_ADDRESS_IPV4);
63 }
64 }
65
66 size_t ReadStunMessageTestCase(StunMessage* msg,
67 const unsigned char* testcase,
68 size_t size) {
69 const char* input = reinterpret_cast<const char*>(testcase);
jbauchf1f87202016-03-30 06:43:37 -070070 rtc::ByteBufferReader buf(input, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000071 if (msg->Read(&buf)) {
72 // Returns the size the stun message should report itself as being
73 return (size - 20);
74 } else {
75 return 0;
76 }
77 }
78};
79
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000080// Sample STUN packets with various attributes
81// Gathered by wiresharking pjproject's pjnath test programs
82// pjproject available at www.pjsip.org
83
Yves Gerey665174f2018-06-19 15:03:05 +020084// clang-format off
85// clang formatting doesn't respect inline comments.
86
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000087static const unsigned char kStunMessageWithIPv6MappedAddress[] = {
88 0x00, 0x01, 0x00, 0x18, // message header
89 0x21, 0x12, 0xa4, 0x42, // transaction id
90 0x29, 0x1f, 0xcd, 0x7c,
91 0xba, 0x58, 0xab, 0xd7,
92 0xf2, 0x41, 0x01, 0x00,
93 0x00, 0x01, 0x00, 0x14, // Address type (mapped), length
94 0x00, 0x02, 0xb8, 0x81, // family (IPv6), port
95 0x24, 0x01, 0xfa, 0x00, // an IPv6 address
96 0x00, 0x04, 0x10, 0x00,
97 0xbe, 0x30, 0x5b, 0xff,
98 0xfe, 0xe5, 0x00, 0xc3
99};
100
101static const unsigned char kStunMessageWithIPv4MappedAddress[] = {
102 0x01, 0x01, 0x00, 0x0c, // binding response, length 12
103 0x21, 0x12, 0xa4, 0x42, // magic cookie
104 0x29, 0x1f, 0xcd, 0x7c, // transaction ID
105 0xba, 0x58, 0xab, 0xd7,
106 0xf2, 0x41, 0x01, 0x00,
107 0x00, 0x01, 0x00, 0x08, // Mapped, 8 byte length
108 0x00, 0x01, 0x9d, 0xfc, // AF_INET, unxor-ed port
109 0xac, 0x17, 0x44, 0xe6 // IPv4 address
110};
111
112// Test XOR-mapped IP addresses:
113static const unsigned char kStunMessageWithIPv6XorMappedAddress[] = {
114 0x01, 0x01, 0x00, 0x18, // message header (binding response)
115 0x21, 0x12, 0xa4, 0x42, // magic cookie (rfc5389)
116 0xe3, 0xa9, 0x46, 0xe1, // transaction ID
117 0x7c, 0x00, 0xc2, 0x62,
118 0x54, 0x08, 0x01, 0x00,
119 0x00, 0x20, 0x00, 0x14, // Address Type (XOR), length
120 0x00, 0x02, 0xcb, 0x5b, // family, XOR-ed port
121 0x05, 0x13, 0x5e, 0x42, // XOR-ed IPv6 address
122 0xe3, 0xad, 0x56, 0xe1,
123 0xc2, 0x30, 0x99, 0x9d,
124 0xaa, 0xed, 0x01, 0xc3
125};
126
127static const unsigned char kStunMessageWithIPv4XorMappedAddress[] = {
128 0x01, 0x01, 0x00, 0x0c, // message header (binding response)
129 0x21, 0x12, 0xa4, 0x42, // magic cookie
130 0x29, 0x1f, 0xcd, 0x7c, // transaction ID
131 0xba, 0x58, 0xab, 0xd7,
132 0xf2, 0x41, 0x01, 0x00,
133 0x00, 0x20, 0x00, 0x08, // address type (xor), length
134 0x00, 0x01, 0xfc, 0xb5, // family (AF_INET), XOR-ed port
135 0x8d, 0x05, 0xe0, 0xa4 // IPv4 address
136};
137
138// ByteString Attribute (username)
139static const unsigned char kStunMessageWithByteStringAttribute[] = {
140 0x00, 0x01, 0x00, 0x0c,
141 0x21, 0x12, 0xa4, 0x42,
142 0xe3, 0xa9, 0x46, 0xe1,
143 0x7c, 0x00, 0xc2, 0x62,
144 0x54, 0x08, 0x01, 0x00,
145 0x00, 0x06, 0x00, 0x08, // username attribute (length 8)
146 0x61, 0x62, 0x63, 0x64, // abcdefgh
147 0x65, 0x66, 0x67, 0x68
148};
149
150// Message with an unknown but comprehensible optional attribute.
151// Parsing should succeed despite this unknown attribute.
152static const unsigned char kStunMessageWithUnknownAttribute[] = {
153 0x00, 0x01, 0x00, 0x14,
154 0x21, 0x12, 0xa4, 0x42,
155 0xe3, 0xa9, 0x46, 0xe1,
156 0x7c, 0x00, 0xc2, 0x62,
157 0x54, 0x08, 0x01, 0x00,
158 0x00, 0xaa, 0x00, 0x07, // Unknown attribute, length 7 (needs padding!)
159 0x61, 0x62, 0x63, 0x64, // abcdefg + padding
160 0x65, 0x66, 0x67, 0x00,
161 0x00, 0x06, 0x00, 0x03, // Followed by a known attribute we can
162 0x61, 0x62, 0x63, 0x00 // check for (username of length 3)
163};
164
165// ByteString Attribute (username) with padding byte
166static const unsigned char kStunMessageWithPaddedByteStringAttribute[] = {
167 0x00, 0x01, 0x00, 0x08,
168 0x21, 0x12, 0xa4, 0x42,
169 0xe3, 0xa9, 0x46, 0xe1,
170 0x7c, 0x00, 0xc2, 0x62,
171 0x54, 0x08, 0x01, 0x00,
172 0x00, 0x06, 0x00, 0x03, // username attribute (length 3)
173 0x61, 0x62, 0x63, 0xcc // abc
174};
175
Peter Boström0c4e06b2015-10-07 12:23:21 +0200176// Message with an Unknown Attributes (uint16_t list) attribute.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000177static const unsigned char kStunMessageWithUInt16ListAttribute[] = {
178 0x00, 0x01, 0x00, 0x0c,
179 0x21, 0x12, 0xa4, 0x42,
180 0xe3, 0xa9, 0x46, 0xe1,
181 0x7c, 0x00, 0xc2, 0x62,
182 0x54, 0x08, 0x01, 0x00,
183 0x00, 0x0a, 0x00, 0x06, // username attribute (length 6)
184 0x00, 0x01, 0x10, 0x00, // three attributes plus padding
185 0xAB, 0xCU, 0xBE, 0xEF
186};
187
188// Error response message (unauthorized)
189static const unsigned char kStunMessageWithErrorAttribute[] = {
190 0x01, 0x11, 0x00, 0x14,
191 0x21, 0x12, 0xa4, 0x42,
192 0x29, 0x1f, 0xcd, 0x7c,
193 0xba, 0x58, 0xab, 0xd7,
194 0xf2, 0x41, 0x01, 0x00,
195 0x00, 0x09, 0x00, 0x10,
196 0x00, 0x00, 0x04, 0x01,
197 0x55, 0x6e, 0x61, 0x75,
198 0x74, 0x68, 0x6f, 0x72,
199 0x69, 0x7a, 0x65, 0x64
200};
201
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000202static const unsigned char kStunMessageWithOriginAttribute[] = {
203 0x00, 0x01, 0x00, 0x18, // message header (binding request), length 24
204 0x21, 0x12, 0xA4, 0x42, // magic cookie
205 0x29, 0x1f, 0xcd, 0x7c, // transaction id
206 0xba, 0x58, 0xab, 0xd7,
207 0xf2, 0x41, 0x01, 0x00,
208 0x80, 0x2f, 0x00, 0x12, // origin attribute (length 18)
209 0x68, 0x74, 0x74, 0x70, // http://example.com
210 0x3A, 0x2F, 0x2F, 0x65,
211 0x78, 0x61, 0x6d, 0x70,
212 0x6c, 0x65, 0x2e, 0x63,
213 0x6f, 0x6d, 0x00, 0x00,
214};
215
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000216// Sample messages with an invalid length Field
217
218// The actual length in bytes of the invalid messages (including STUN header)
219static const int kRealLengthOfInvalidLengthTestCases = 32;
220
221static const unsigned char kStunMessageWithZeroLength[] = {
222 0x00, 0x01, 0x00, 0x00, // length of 0 (last 2 bytes)
223 0x21, 0x12, 0xA4, 0x42, // magic cookie
224 '0', '1', '2', '3', // transaction id
225 '4', '5', '6', '7',
226 '8', '9', 'a', 'b',
227 0x00, 0x20, 0x00, 0x08, // xor mapped address
228 0x00, 0x01, 0x21, 0x1F,
229 0x21, 0x12, 0xA4, 0x53,
230};
231
232static const unsigned char kStunMessageWithExcessLength[] = {
233 0x00, 0x01, 0x00, 0x55, // length of 85
234 0x21, 0x12, 0xA4, 0x42, // magic cookie
235 '0', '1', '2', '3', // transaction id
236 '4', '5', '6', '7',
237 '8', '9', 'a', 'b',
238 0x00, 0x20, 0x00, 0x08, // xor mapped address
239 0x00, 0x01, 0x21, 0x1F,
240 0x21, 0x12, 0xA4, 0x53,
241};
242
243static const unsigned char kStunMessageWithSmallLength[] = {
244 0x00, 0x01, 0x00, 0x03, // length of 3
245 0x21, 0x12, 0xA4, 0x42, // magic cookie
246 '0', '1', '2', '3', // transaction id
247 '4', '5', '6', '7',
248 '8', '9', 'a', 'b',
249 0x00, 0x20, 0x00, 0x08, // xor mapped address
250 0x00, 0x01, 0x21, 0x1F,
251 0x21, 0x12, 0xA4, 0x53,
252};
253
katrielc1a206102016-06-20 05:13:16 -0700254static const unsigned char kStunMessageWithBadHmacAtEnd[] = {
255 0x00, 0x01, 0x00, 0x14, // message length exactly 20
256 0x21, 0x12, 0xA4, 0x42, // magic cookie
257 '0', '1', '2', '3', // transaction ID
258 '4', '5', '6', '7',
259 '8', '9', 'a', 'b',
260 0x00, 0x08, 0x00, 0x14, // type=STUN_ATTR_MESSAGE_INTEGRITY, length=20
261 '0', '0', '0', '0', // We lied, there are only 16 bytes of HMAC.
262 '0', '0', '0', '0',
263 '0', '0', '0', '0',
264 '0', '0', '0', '0',
265};
266
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000267// RTCP packet, for testing we correctly ignore non stun packet types.
268// V=2, P=false, RC=0, Type=200, Len=6, Sender-SSRC=85, etc
269static const unsigned char kRtcpPacket[] = {
270 0x80, 0xc8, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55,
271 0xce, 0xa5, 0x18, 0x3a, 0x39, 0xcc, 0x7d, 0x09,
272 0x23, 0xed, 0x19, 0x07, 0x00, 0x00, 0x01, 0x56,
273 0x00, 0x03, 0x73, 0x50,
274};
275
Yves Gerey665174f2018-06-19 15:03:05 +0200276
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000277// RFC5769 Test Vectors
278// Software name (request): "STUN test client" (without quotes)
279// Software name (response): "test vector" (without quotes)
280// Username: "evtj:h6vY" (without quotes)
281// Password: "VOkJxbRl1RmTxUk/WvJxBt" (without quotes)
282static const unsigned char kRfc5769SampleMsgTransactionId[] = {
283 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae
284};
285static const char kRfc5769SampleMsgClientSoftware[] = "STUN test client";
286static const char kRfc5769SampleMsgServerSoftware[] = "test vector";
287static const char kRfc5769SampleMsgUsername[] = "evtj:h6vY";
288static const char kRfc5769SampleMsgPassword[] = "VOkJxbRl1RmTxUk/WvJxBt";
289static const rtc::SocketAddress kRfc5769SampleMsgMappedAddress(
290 "192.0.2.1", 32853);
291static const rtc::SocketAddress kRfc5769SampleMsgIPv6MappedAddress(
292 "2001:db8:1234:5678:11:2233:4455:6677", 32853);
293
294static const unsigned char kRfc5769SampleMsgWithAuthTransactionId[] = {
295 0x78, 0xad, 0x34, 0x33, 0xc6, 0xad, 0x72, 0xc0, 0x29, 0xda, 0x41, 0x2e
296};
297static const char kRfc5769SampleMsgWithAuthUsername[] =
298 "\xe3\x83\x9e\xe3\x83\x88\xe3\x83\xaa\xe3\x83\x83\xe3\x82\xaf\xe3\x82\xb9";
299static const char kRfc5769SampleMsgWithAuthPassword[] = "TheMatrIX";
300static const char kRfc5769SampleMsgWithAuthNonce[] =
301 "f//499k954d6OL34oL9FSTvy64sA";
302static const char kRfc5769SampleMsgWithAuthRealm[] = "example.org";
303
304// 2.1. Sample Request
305static const unsigned char kRfc5769SampleRequest[] = {
306 0x00, 0x01, 0x00, 0x58, // Request type and message length
307 0x21, 0x12, 0xa4, 0x42, // Magic cookie
308 0xb7, 0xe7, 0xa7, 0x01, // }
309 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
310 0xfa, 0x87, 0xdf, 0xae, // }
311 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
312 0x53, 0x54, 0x55, 0x4e, // }
313 0x20, 0x74, 0x65, 0x73, // } User-agent...
314 0x74, 0x20, 0x63, 0x6c, // } ...name
315 0x69, 0x65, 0x6e, 0x74, // }
316 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
317 0x6e, 0x00, 0x01, 0xff, // ICE priority value
318 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
319 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
320 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
321 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
322 0x65, 0x76, 0x74, 0x6a, // }
323 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
324 0x59, 0x20, 0x20, 0x20, // }
325 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
326 0x9a, 0xea, 0xa7, 0x0c, // }
327 0xbf, 0xd8, 0xcb, 0x56, // }
328 0x78, 0x1e, 0xf2, 0xb5, // } HMAC-SHA1 fingerprint
329 0xb2, 0xd3, 0xf2, 0x49, // }
330 0xc1, 0xb5, 0x71, 0xa2, // }
331 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
332 0xe5, 0x7a, 0x3b, 0xcf // CRC32 fingerprint
333};
334
Jonas Oreland63737a92019-11-21 15:12:14 +0100335// 2.1. Sample Request
336static const unsigned char kSampleRequestMI32[] = {
337 0x00, 0x01, 0x00, 0x48, // Request type and message length
338 0x21, 0x12, 0xa4, 0x42, // Magic cookie
339 0xb7, 0xe7, 0xa7, 0x01, // }
340 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
341 0xfa, 0x87, 0xdf, 0xae, // }
342 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
343 0x53, 0x54, 0x55, 0x4e, // }
344 0x20, 0x74, 0x65, 0x73, // } User-agent...
345 0x74, 0x20, 0x63, 0x6c, // } ...name
346 0x69, 0x65, 0x6e, 0x74, // }
347 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
348 0x6e, 0x00, 0x01, 0xff, // ICE priority value
349 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
350 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
351 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
352 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
353 0x65, 0x76, 0x74, 0x6a, // }
354 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
355 0x59, 0x20, 0x20, 0x20, // }
356 0xC0, 0x60, 0x00, 0x04, // MESSAGE-INTEGRITY-32 attribute header
357 0x45, 0x45, 0xce, 0x7c, // } HMAC-SHA1 fingerprint (first 32 bit)
358 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
359 0xe5, 0x7a, 0x3b, 0xcf // CRC32 fingerprint
360};
361
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000362// 2.2. Sample IPv4 Response
363static const unsigned char kRfc5769SampleResponse[] = {
364 0x01, 0x01, 0x00, 0x3c, // Response type and message length
365 0x21, 0x12, 0xa4, 0x42, // Magic cookie
366 0xb7, 0xe7, 0xa7, 0x01, // }
367 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
368 0xfa, 0x87, 0xdf, 0xae, // }
369 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
370 0x74, 0x65, 0x73, 0x74, // }
371 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
372 0x74, 0x6f, 0x72, 0x20, // }
373 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
374 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port
375 0xe1, 0x12, 0xa6, 0x43, // Xor'd mapped IPv4 address
376 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
377 0x2b, 0x91, 0xf5, 0x99, // }
378 0xfd, 0x9e, 0x90, 0xc3, // }
379 0x8c, 0x74, 0x89, 0xf9, // } HMAC-SHA1 fingerprint
380 0x2a, 0xf9, 0xba, 0x53, // }
381 0xf0, 0x6b, 0xe7, 0xd7, // }
382 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
383 0xc0, 0x7d, 0x4c, 0x96 // CRC32 fingerprint
384};
385
386// 2.3. Sample IPv6 Response
387static const unsigned char kRfc5769SampleResponseIPv6[] = {
388 0x01, 0x01, 0x00, 0x48, // Response type and message length
389 0x21, 0x12, 0xa4, 0x42, // Magic cookie
390 0xb7, 0xe7, 0xa7, 0x01, // }
391 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
392 0xfa, 0x87, 0xdf, 0xae, // }
393 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
394 0x74, 0x65, 0x73, 0x74, // }
395 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
396 0x74, 0x6f, 0x72, 0x20, // }
397 0x00, 0x20, 0x00, 0x14, // XOR-MAPPED-ADDRESS attribute header
398 0x00, 0x02, 0xa1, 0x47, // Address family (IPv6) and xor'd mapped port.
399 0x01, 0x13, 0xa9, 0xfa, // }
400 0xa5, 0xd3, 0xf1, 0x79, // } Xor'd mapped IPv6 address
401 0xbc, 0x25, 0xf4, 0xb5, // }
402 0xbe, 0xd2, 0xb9, 0xd9, // }
403 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
404 0xa3, 0x82, 0x95, 0x4e, // }
405 0x4b, 0xe6, 0x7b, 0xf1, // }
406 0x17, 0x84, 0xc9, 0x7c, // } HMAC-SHA1 fingerprint
407 0x82, 0x92, 0xc2, 0x75, // }
408 0xbf, 0xe3, 0xed, 0x41, // }
409 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
410 0xc8, 0xfb, 0x0b, 0x4c // CRC32 fingerprint
411};
412
413// 2.4. Sample Request with Long-Term Authentication
414static const unsigned char kRfc5769SampleRequestLongTermAuth[] = {
415 0x00, 0x01, 0x00, 0x60, // Request type and message length
416 0x21, 0x12, 0xa4, 0x42, // Magic cookie
417 0x78, 0xad, 0x34, 0x33, // }
418 0xc6, 0xad, 0x72, 0xc0, // } Transaction ID
419 0x29, 0xda, 0x41, 0x2e, // }
420 0x00, 0x06, 0x00, 0x12, // USERNAME attribute header
421 0xe3, 0x83, 0x9e, 0xe3, // }
422 0x83, 0x88, 0xe3, 0x83, // }
423 0xaa, 0xe3, 0x83, 0x83, // } Username value (18 bytes) and padding (2 bytes)
424 0xe3, 0x82, 0xaf, 0xe3, // }
425 0x82, 0xb9, 0x00, 0x00, // }
426 0x00, 0x15, 0x00, 0x1c, // NONCE attribute header
427 0x66, 0x2f, 0x2f, 0x34, // }
428 0x39, 0x39, 0x6b, 0x39, // }
429 0x35, 0x34, 0x64, 0x36, // }
430 0x4f, 0x4c, 0x33, 0x34, // } Nonce value
431 0x6f, 0x4c, 0x39, 0x46, // }
432 0x53, 0x54, 0x76, 0x79, // }
433 0x36, 0x34, 0x73, 0x41, // }
434 0x00, 0x14, 0x00, 0x0b, // REALM attribute header
435 0x65, 0x78, 0x61, 0x6d, // }
436 0x70, 0x6c, 0x65, 0x2e, // } Realm value (11 bytes) and padding (1 byte)
437 0x6f, 0x72, 0x67, 0x00, // }
438 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
439 0xf6, 0x70, 0x24, 0x65, // }
440 0x6d, 0xd6, 0x4a, 0x3e, // }
441 0x02, 0xb8, 0xe0, 0x71, // } HMAC-SHA1 fingerprint
442 0x2e, 0x85, 0xc9, 0xa2, // }
443 0x8c, 0xa8, 0x96, 0x66 // }
444};
445
446// Length parameter is changed to 0x38 from 0x58.
447// AddMessageIntegrity will add MI information and update the length param
448// accordingly.
449static const unsigned char kRfc5769SampleRequestWithoutMI[] = {
450 0x00, 0x01, 0x00, 0x38, // Request type and message length
451 0x21, 0x12, 0xa4, 0x42, // Magic cookie
452 0xb7, 0xe7, 0xa7, 0x01, // }
453 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
454 0xfa, 0x87, 0xdf, 0xae, // }
455 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
456 0x53, 0x54, 0x55, 0x4e, // }
457 0x20, 0x74, 0x65, 0x73, // } User-agent...
458 0x74, 0x20, 0x63, 0x6c, // } ...name
459 0x69, 0x65, 0x6e, 0x74, // }
460 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
461 0x6e, 0x00, 0x01, 0xff, // ICE priority value
462 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
463 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
464 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
465 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
466 0x65, 0x76, 0x74, 0x6a, // }
467 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
468 0x59, 0x20, 0x20, 0x20 // }
469};
470
471// This HMAC differs from the RFC 5769 SampleRequest message. This differs
472// because spec uses 0x20 for the padding where as our implementation uses 0.
473static const unsigned char kCalculatedHmac1[] = {
474 0x79, 0x07, 0xc2, 0xd2, // }
475 0xed, 0xbf, 0xea, 0x48, // }
476 0x0e, 0x4c, 0x76, 0xd8, // } HMAC-SHA1 fingerprint
477 0x29, 0x62, 0xd5, 0xc3, // }
478 0x74, 0x2a, 0xf9, 0xe3 // }
479};
480
Jonas Oreland63737a92019-11-21 15:12:14 +0100481// This truncated HMAC differs from kCalculatedHmac1
482// above since the sum is computed including header
483// and the header is different since the message is shorter
484// than when MESSAGE-INTEGRITY is used.
485static const unsigned char kCalculatedHmac1_32[] = {
486 0xda, 0x39, 0xde, 0x5d, // }
487};
488
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000489// Length parameter is changed to 0x1c from 0x3c.
490// AddMessageIntegrity will add MI information and update the length param
491// accordingly.
492static const unsigned char kRfc5769SampleResponseWithoutMI[] = {
493 0x01, 0x01, 0x00, 0x1c, // Response type and message length
494 0x21, 0x12, 0xa4, 0x42, // Magic cookie
495 0xb7, 0xe7, 0xa7, 0x01, // }
496 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
497 0xfa, 0x87, 0xdf, 0xae, // }
498 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
499 0x74, 0x65, 0x73, 0x74, // }
500 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
501 0x74, 0x6f, 0x72, 0x20, // }
502 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
503 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port
504 0xe1, 0x12, 0xa6, 0x43 // Xor'd mapped IPv4 address
505};
506
507// This HMAC differs from the RFC 5769 SampleResponse message. This differs
508// because spec uses 0x20 for the padding where as our implementation uses 0.
509static const unsigned char kCalculatedHmac2[] = {
510 0x5d, 0x6b, 0x58, 0xbe, // }
511 0xad, 0x94, 0xe0, 0x7e, // }
512 0xef, 0x0d, 0xfc, 0x12, // } HMAC-SHA1 fingerprint
513 0x82, 0xa2, 0xbd, 0x08, // }
514 0x43, 0x14, 0x10, 0x28 // }
515};
516
Jonas Oreland63737a92019-11-21 15:12:14 +0100517// This truncated HMAC differs from kCalculatedHmac2
518// above since the sum is computed including header
519// and the header is different since the message is shorter
520// than when MESSAGE-INTEGRITY is used.
521static const unsigned char kCalculatedHmac2_32[] = {
522 0xe7, 0x5c, 0xd3, 0x16, // }
523};
524
Yves Gerey665174f2018-06-19 15:03:05 +0200525// clang-format on
526
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000527// A transaction ID without the 'magic cookie' portion
528// pjnat's test programs use this transaction ID a lot.
Yves Gerey665174f2018-06-19 15:03:05 +0200529const unsigned char kTestTransactionId1[] = {0x029, 0x01f, 0x0cd, 0x07c,
530 0x0ba, 0x058, 0x0ab, 0x0d7,
531 0x0f2, 0x041, 0x001, 0x000};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000532
533// They use this one sometimes too.
Yves Gerey665174f2018-06-19 15:03:05 +0200534const unsigned char kTestTransactionId2[] = {0x0e3, 0x0a9, 0x046, 0x0e1,
535 0x07c, 0x000, 0x0c2, 0x062,
536 0x054, 0x008, 0x001, 0x000};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000537
Yves Gerey665174f2018-06-19 15:03:05 +0200538const in6_addr kIPv6TestAddress1 = {
539 {{0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, 0x10, 0x00, 0xbe, 0x30, 0x5b, 0xff,
540 0xfe, 0xe5, 0x00, 0xc3}}};
541const in6_addr kIPv6TestAddress2 = {
542 {{0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, 0x10, 0x12, 0x06, 0x0c, 0xce, 0xff,
543 0xfe, 0x1f, 0x61, 0xa4}}};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000544
545#ifdef WEBRTC_POSIX
Yves Gerey665174f2018-06-19 15:03:05 +0200546const in_addr kIPv4TestAddress1 = {0xe64417ac};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000547#elif defined WEBRTC_WIN
548// Windows in_addr has a union with a uchar[] array first.
Yves Gerey665174f2018-06-19 15:03:05 +0200549const in_addr kIPv4TestAddress1 = {{{0x0ac, 0x017, 0x044, 0x0e6}}};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000550#endif
551const char kTestUserName1[] = "abcdefgh";
552const char kTestUserName2[] = "abc";
553const char kTestErrorReason[] = "Unauthorized";
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000554const char kTestOrigin[] = "http://example.com";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000555const int kTestErrorClass = 4;
556const int kTestErrorNumber = 1;
557const int kTestErrorCode = 401;
558
559const int kTestMessagePort1 = 59977;
560const int kTestMessagePort2 = 47233;
561const int kTestMessagePort3 = 56743;
562const int kTestMessagePort4 = 40444;
563
564#define ReadStunMessage(X, Y) ReadStunMessageTestCase(X, Y, sizeof(Y));
565
566// Test that the GetStun*Type and IsStun*Type methods work as expected.
567TEST_F(StunTest, MessageTypes) {
568 EXPECT_EQ(STUN_BINDING_RESPONSE,
Yves Gerey665174f2018-06-19 15:03:05 +0200569 GetStunSuccessResponseType(STUN_BINDING_REQUEST));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000570 EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE,
Yves Gerey665174f2018-06-19 15:03:05 +0200571 GetStunErrorResponseType(STUN_BINDING_REQUEST));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000572 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_INDICATION));
573 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_RESPONSE));
574 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_ERROR_RESPONSE));
575 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_INDICATION));
576 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_RESPONSE));
577 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_ERROR_RESPONSE));
578
Yves Gerey665174f2018-06-19 15:03:05 +0200579 int types[] = {STUN_BINDING_REQUEST, STUN_BINDING_INDICATION,
580 STUN_BINDING_RESPONSE, STUN_BINDING_ERROR_RESPONSE};
tfarina5237aaf2015-11-10 23:44:30 -0800581 for (size_t i = 0; i < arraysize(types); ++i) {
582 EXPECT_EQ(i == 0U, IsStunRequestType(types[i]));
583 EXPECT_EQ(i == 1U, IsStunIndicationType(types[i]));
584 EXPECT_EQ(i == 2U, IsStunSuccessResponseType(types[i]));
585 EXPECT_EQ(i == 3U, IsStunErrorResponseType(types[i]));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000586 EXPECT_EQ(1, types[i] & 0xFEEF);
587 }
588}
589
590TEST_F(StunTest, ReadMessageWithIPv4AddressAttribute) {
591 StunMessage msg;
592 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4MappedAddress);
593 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
594 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
595
596 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
597 rtc::IPAddress test_address(kIPv4TestAddress1);
Yves Gerey665174f2018-06-19 15:03:05 +0200598 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort4,
599 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000600}
601
602TEST_F(StunTest, ReadMessageWithIPv4XorAddressAttribute) {
603 StunMessage msg;
604 StunMessage msg2;
605 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress);
606 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
607 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
608
609 const StunAddressAttribute* addr =
610 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
611 rtc::IPAddress test_address(kIPv4TestAddress1);
Yves Gerey665174f2018-06-19 15:03:05 +0200612 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort3,
613 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000614}
615
616TEST_F(StunTest, ReadMessageWithIPv6AddressAttribute) {
617 StunMessage msg;
618 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
619 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
620 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
621
622 rtc::IPAddress test_address(kIPv6TestAddress1);
623
624 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200625 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort2,
626 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000627}
628
629TEST_F(StunTest, ReadMessageWithInvalidAddressAttribute) {
630 StunMessage msg;
631 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
632 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
633 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
634
635 rtc::IPAddress test_address(kIPv6TestAddress1);
636
637 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200638 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort2,
639 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000640}
641
642TEST_F(StunTest, ReadMessageWithIPv6XorAddressAttribute) {
643 StunMessage msg;
644 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress);
645
646 rtc::IPAddress test_address(kIPv6TestAddress1);
647
648 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
649 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
650
651 const StunAddressAttribute* addr =
652 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200653 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort1,
654 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000655}
656
657// Read the RFC5389 fields from the RFC5769 sample STUN request.
658TEST_F(StunTest, ReadRfc5769RequestMessage) {
659 StunMessage msg;
660 size_t size = ReadStunMessage(&msg, kRfc5769SampleRequest);
661 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
662 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
663 kStunTransactionIdLength);
664
665 const StunByteStringAttribute* software =
666 msg.GetByteString(STUN_ATTR_SOFTWARE);
667 ASSERT_TRUE(software != NULL);
668 EXPECT_EQ(kRfc5769SampleMsgClientSoftware, software->GetString());
669
670 const StunByteStringAttribute* username =
671 msg.GetByteString(STUN_ATTR_USERNAME);
672 ASSERT_TRUE(username != NULL);
673 EXPECT_EQ(kRfc5769SampleMsgUsername, username->GetString());
674
675 // Actual M-I value checked in a later test.
676 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
677
678 // Fingerprint checked in a later test, but double-check the value here.
Yves Gerey665174f2018-06-19 15:03:05 +0200679 const StunUInt32Attribute* fingerprint = msg.GetUInt32(STUN_ATTR_FINGERPRINT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000680 ASSERT_TRUE(fingerprint != NULL);
681 EXPECT_EQ(0xe57a3bcf, fingerprint->value());
682}
683
684// Read the RFC5389 fields from the RFC5769 sample STUN response.
685TEST_F(StunTest, ReadRfc5769ResponseMessage) {
686 StunMessage msg;
687 size_t size = ReadStunMessage(&msg, kRfc5769SampleResponse);
688 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
689 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
690 kStunTransactionIdLength);
691
692 const StunByteStringAttribute* software =
693 msg.GetByteString(STUN_ATTR_SOFTWARE);
694 ASSERT_TRUE(software != NULL);
695 EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->GetString());
696
697 const StunAddressAttribute* mapped_address =
698 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
699 ASSERT_TRUE(mapped_address != NULL);
700 EXPECT_EQ(kRfc5769SampleMsgMappedAddress, mapped_address->GetAddress());
701
702 // Actual M-I and fingerprint checked in later tests.
703 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
704 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
705}
706
707// Read the RFC5389 fields from the RFC5769 sample STUN response for IPv6.
708TEST_F(StunTest, ReadRfc5769ResponseMessageIPv6) {
709 StunMessage msg;
710 size_t size = ReadStunMessage(&msg, kRfc5769SampleResponseIPv6);
711 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
712 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
713 kStunTransactionIdLength);
714
715 const StunByteStringAttribute* software =
716 msg.GetByteString(STUN_ATTR_SOFTWARE);
717 ASSERT_TRUE(software != NULL);
718 EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->GetString());
719
720 const StunAddressAttribute* mapped_address =
721 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
722 ASSERT_TRUE(mapped_address != NULL);
723 EXPECT_EQ(kRfc5769SampleMsgIPv6MappedAddress, mapped_address->GetAddress());
724
725 // Actual M-I and fingerprint checked in later tests.
726 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
727 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
728}
729
730// Read the RFC5389 fields from the RFC5769 sample STUN response with auth.
731TEST_F(StunTest, ReadRfc5769RequestMessageLongTermAuth) {
732 StunMessage msg;
733 size_t size = ReadStunMessage(&msg, kRfc5769SampleRequestLongTermAuth);
734 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
735 CheckStunTransactionID(msg, kRfc5769SampleMsgWithAuthTransactionId,
736 kStunTransactionIdLength);
737
738 const StunByteStringAttribute* username =
739 msg.GetByteString(STUN_ATTR_USERNAME);
740 ASSERT_TRUE(username != NULL);
741 EXPECT_EQ(kRfc5769SampleMsgWithAuthUsername, username->GetString());
742
Yves Gerey665174f2018-06-19 15:03:05 +0200743 const StunByteStringAttribute* nonce = msg.GetByteString(STUN_ATTR_NONCE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000744 ASSERT_TRUE(nonce != NULL);
745 EXPECT_EQ(kRfc5769SampleMsgWithAuthNonce, nonce->GetString());
746
Yves Gerey665174f2018-06-19 15:03:05 +0200747 const StunByteStringAttribute* realm = msg.GetByteString(STUN_ATTR_REALM);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000748 ASSERT_TRUE(realm != NULL);
749 EXPECT_EQ(kRfc5769SampleMsgWithAuthRealm, realm->GetString());
750
751 // No fingerprint, actual M-I checked in later tests.
752 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
753 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) == NULL);
754}
755
756// The RFC3489 packet in this test is the same as
757// kStunMessageWithIPv4MappedAddress, but with a different value where the
758// magic cookie was.
759TEST_F(StunTest, ReadLegacyMessage) {
760 unsigned char rfc3489_packet[sizeof(kStunMessageWithIPv4MappedAddress)];
761 memcpy(rfc3489_packet, kStunMessageWithIPv4MappedAddress,
Yves Gerey665174f2018-06-19 15:03:05 +0200762 sizeof(kStunMessageWithIPv4MappedAddress));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000763 // Overwrite the magic cookie here.
764 memcpy(&rfc3489_packet[4], "ABCD", 4);
765
766 StunMessage msg;
767 size_t size = ReadStunMessage(&msg, rfc3489_packet);
768 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
769 CheckStunTransactionID(msg, &rfc3489_packet[4], kStunTransactionIdLength + 4);
770
771 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
772 rtc::IPAddress test_address(kIPv4TestAddress1);
Yves Gerey665174f2018-06-19 15:03:05 +0200773 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort4,
774 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000775}
776
777TEST_F(StunTest, SetIPv6XorAddressAttributeOwner) {
778 StunMessage msg;
779 StunMessage msg2;
780 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress);
781
782 rtc::IPAddress test_address(kIPv6TestAddress1);
783
784 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
785 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
786
787 const StunAddressAttribute* addr =
788 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200789 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort1,
790 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000791
792 // Owner with a different transaction ID.
793 msg2.SetTransactionID("ABCDABCDABCD");
794 StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL);
795 addr2.SetIP(addr->ipaddr());
796 addr2.SetPort(addr->port());
797 addr2.SetOwner(&msg2);
798 // The internal IP address shouldn't change.
799 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
800
jbauchf1f87202016-03-30 06:43:37 -0700801 rtc::ByteBufferWriter correct_buf;
802 rtc::ByteBufferWriter wrong_buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000803 EXPECT_TRUE(addr->Write(&correct_buf));
804 EXPECT_TRUE(addr2.Write(&wrong_buf));
805 // But when written out, the buffers should look different.
806 ASSERT_NE(0,
807 memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
808 // And when reading a known good value, the address should be wrong.
jbauchf1f87202016-03-30 06:43:37 -0700809 rtc::ByteBufferReader read_buf(correct_buf);
810 addr2.Read(&read_buf);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000811 ASSERT_NE(addr->ipaddr(), addr2.ipaddr());
812 addr2.SetIP(addr->ipaddr());
813 addr2.SetPort(addr->port());
814 // Try writing with no owner at all, should fail and write nothing.
815 addr2.SetOwner(NULL);
816 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
jbauchf1f87202016-03-30 06:43:37 -0700817 wrong_buf.Clear();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000818 EXPECT_FALSE(addr2.Write(&wrong_buf));
819 ASSERT_EQ(0U, wrong_buf.Length());
820}
821
822TEST_F(StunTest, SetIPv4XorAddressAttributeOwner) {
823 // Unlike the IPv6XorAddressAttributeOwner test, IPv4 XOR address attributes
824 // should _not_ be affected by a change in owner. IPv4 XOR address uses the
825 // magic cookie value which is fixed.
826 StunMessage msg;
827 StunMessage msg2;
828 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress);
829
830 rtc::IPAddress test_address(kIPv4TestAddress1);
831
832 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
833 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
834
835 const StunAddressAttribute* addr =
836 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200837 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort3,
838 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000839
840 // Owner with a different transaction ID.
841 msg2.SetTransactionID("ABCDABCDABCD");
842 StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL);
843 addr2.SetIP(addr->ipaddr());
844 addr2.SetPort(addr->port());
845 addr2.SetOwner(&msg2);
846 // The internal IP address shouldn't change.
847 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
848
jbauchf1f87202016-03-30 06:43:37 -0700849 rtc::ByteBufferWriter correct_buf;
850 rtc::ByteBufferWriter wrong_buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000851 EXPECT_TRUE(addr->Write(&correct_buf));
852 EXPECT_TRUE(addr2.Write(&wrong_buf));
853 // The same address data should be written.
854 ASSERT_EQ(0,
855 memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
856 // And an attribute should be able to un-XOR an address belonging to a message
857 // with a different transaction ID.
jbauchf1f87202016-03-30 06:43:37 -0700858 rtc::ByteBufferReader read_buf(correct_buf);
859 EXPECT_TRUE(addr2.Read(&read_buf));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000860 ASSERT_EQ(addr->ipaddr(), addr2.ipaddr());
861
862 // However, no owner is still an error, should fail and write nothing.
863 addr2.SetOwner(NULL);
864 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
jbauchf1f87202016-03-30 06:43:37 -0700865 wrong_buf.Clear();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000866 EXPECT_FALSE(addr2.Write(&wrong_buf));
867}
868
869TEST_F(StunTest, CreateIPv6AddressAttribute) {
870 rtc::IPAddress test_ip(kIPv6TestAddress2);
871
zsteinf42cc9d2017-03-27 16:17:19 -0700872 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000873 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
874 addr->SetAddress(test_addr);
875
zsteinf42cc9d2017-03-27 16:17:19 -0700876 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6, kTestMessagePort2,
877 test_ip);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000878}
879
880TEST_F(StunTest, CreateIPv4AddressAttribute) {
881 struct in_addr test_in_addr;
882 test_in_addr.s_addr = 0xBEB0B0BE;
883 rtc::IPAddress test_ip(test_in_addr);
884
zsteinf42cc9d2017-03-27 16:17:19 -0700885 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000886 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
887 addr->SetAddress(test_addr);
888
zsteinf42cc9d2017-03-27 16:17:19 -0700889 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV4, kTestMessagePort2,
890 test_ip);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000891}
892
893// Test that we don't care what order we set the parts of an address
894TEST_F(StunTest, CreateAddressInArbitraryOrder) {
zsteinf42cc9d2017-03-27 16:17:19 -0700895 auto addr = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000896 // Port first
897 addr->SetPort(kTestMessagePort1);
898 addr->SetIP(rtc::IPAddress(kIPv4TestAddress1));
899 ASSERT_EQ(kTestMessagePort1, addr->port());
900 ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr->ipaddr());
901
zsteinf42cc9d2017-03-27 16:17:19 -0700902 auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000903 // IP first
904 addr2->SetIP(rtc::IPAddress(kIPv4TestAddress1));
905 addr2->SetPort(kTestMessagePort2);
906 ASSERT_EQ(kTestMessagePort2, addr2->port());
907 ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr2->ipaddr());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000908}
909
910TEST_F(StunTest, WriteMessageWithIPv6AddressAttribute) {
911 StunMessage msg;
912 size_t size = sizeof(kStunMessageWithIPv6MappedAddress);
913
914 rtc::IPAddress test_ip(kIPv6TestAddress1);
915
916 msg.SetType(STUN_BINDING_REQUEST);
917 msg.SetTransactionID(
918 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
919 kStunTransactionIdLength));
920 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
921
zsteinf42cc9d2017-03-27 16:17:19 -0700922 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000923 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
924 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700925 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000926
927 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
928
jbauchf1f87202016-03-30 06:43:37 -0700929 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000930 EXPECT_TRUE(msg.Write(&out));
931 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6MappedAddress));
932 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700933 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000934 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700935 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000936 ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv6MappedAddress, len1));
937}
938
939TEST_F(StunTest, WriteMessageWithIPv4AddressAttribute) {
940 StunMessage msg;
941 size_t size = sizeof(kStunMessageWithIPv4MappedAddress);
942
943 rtc::IPAddress test_ip(kIPv4TestAddress1);
944
945 msg.SetType(STUN_BINDING_RESPONSE);
946 msg.SetTransactionID(
947 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
948 kStunTransactionIdLength));
949 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
950
zsteinf42cc9d2017-03-27 16:17:19 -0700951 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000952 rtc::SocketAddress test_addr(test_ip, kTestMessagePort4);
953 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700954 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000955
956 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
957
jbauchf1f87202016-03-30 06:43:37 -0700958 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000959 EXPECT_TRUE(msg.Write(&out));
960 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4MappedAddress));
961 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700962 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000963 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700964 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000965 ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv4MappedAddress, len1));
966}
967
968TEST_F(StunTest, WriteMessageWithIPv6XorAddressAttribute) {
969 StunMessage msg;
970 size_t size = sizeof(kStunMessageWithIPv6XorMappedAddress);
971
972 rtc::IPAddress test_ip(kIPv6TestAddress1);
973
974 msg.SetType(STUN_BINDING_RESPONSE);
975 msg.SetTransactionID(
976 std::string(reinterpret_cast<const char*>(kTestTransactionId2),
977 kStunTransactionIdLength));
978 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
979
zsteinf42cc9d2017-03-27 16:17:19 -0700980 auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000981 rtc::SocketAddress test_addr(test_ip, kTestMessagePort1);
982 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700983 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000984
985 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
986
jbauchf1f87202016-03-30 06:43:37 -0700987 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000988 EXPECT_TRUE(msg.Write(&out));
989 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6XorMappedAddress));
990 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700991 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000992 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700993 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000994 ASSERT_EQ(0,
995 memcmp(bytes.c_str(), kStunMessageWithIPv6XorMappedAddress, len1));
996}
997
998TEST_F(StunTest, WriteMessageWithIPv4XoreAddressAttribute) {
999 StunMessage msg;
1000 size_t size = sizeof(kStunMessageWithIPv4XorMappedAddress);
1001
1002 rtc::IPAddress test_ip(kIPv4TestAddress1);
1003
1004 msg.SetType(STUN_BINDING_RESPONSE);
1005 msg.SetTransactionID(
1006 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
1007 kStunTransactionIdLength));
1008 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
1009
zsteinf42cc9d2017-03-27 16:17:19 -07001010 auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001011 rtc::SocketAddress test_addr(test_ip, kTestMessagePort3);
1012 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -07001013 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001014
1015 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
1016
jbauchf1f87202016-03-30 06:43:37 -07001017 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001018 EXPECT_TRUE(msg.Write(&out));
1019 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4XorMappedAddress));
1020 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -07001021 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001022 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -07001023 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001024 ASSERT_EQ(0,
1025 memcmp(bytes.c_str(), kStunMessageWithIPv4XorMappedAddress, len1));
1026}
1027
1028TEST_F(StunTest, ReadByteStringAttribute) {
1029 StunMessage msg;
1030 size_t size = ReadStunMessage(&msg, kStunMessageWithByteStringAttribute);
1031
1032 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1033 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
1034 const StunByteStringAttribute* username =
1035 msg.GetByteString(STUN_ATTR_USERNAME);
1036 ASSERT_TRUE(username != NULL);
1037 EXPECT_EQ(kTestUserName1, username->GetString());
1038}
1039
1040TEST_F(StunTest, ReadPaddedByteStringAttribute) {
1041 StunMessage msg;
Yves Gerey665174f2018-06-19 15:03:05 +02001042 size_t size =
1043 ReadStunMessage(&msg, kStunMessageWithPaddedByteStringAttribute);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001044 ASSERT_NE(0U, size);
1045 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1046 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
1047 const StunByteStringAttribute* username =
1048 msg.GetByteString(STUN_ATTR_USERNAME);
1049 ASSERT_TRUE(username != NULL);
1050 EXPECT_EQ(kTestUserName2, username->GetString());
1051}
1052
1053TEST_F(StunTest, ReadErrorCodeAttribute) {
1054 StunMessage msg;
1055 size_t size = ReadStunMessage(&msg, kStunMessageWithErrorAttribute);
1056
1057 CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, size);
1058 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
1059 const StunErrorCodeAttribute* errorcode = msg.GetErrorCode();
1060 ASSERT_TRUE(errorcode != NULL);
1061 EXPECT_EQ(kTestErrorClass, errorcode->eclass());
1062 EXPECT_EQ(kTestErrorNumber, errorcode->number());
1063 EXPECT_EQ(kTestErrorReason, errorcode->reason());
1064 EXPECT_EQ(kTestErrorCode, errorcode->code());
deadbeef996fc6b2017-04-26 09:21:22 -07001065 EXPECT_EQ(kTestErrorCode, msg.GetErrorCodeValue());
1066}
1067
1068// Test that GetErrorCodeValue returns STUN_ERROR_GLOBAL_FAILURE if the message
1069// in question doesn't have an error code attribute, rather than crashing.
1070TEST_F(StunTest, GetErrorCodeValueWithNoErrorAttribute) {
1071 StunMessage msg;
1072 ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
1073 EXPECT_EQ(STUN_ERROR_GLOBAL_FAILURE, msg.GetErrorCodeValue());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001074}
1075
1076TEST_F(StunTest, ReadMessageWithAUInt16ListAttribute) {
1077 StunMessage msg;
1078 size_t size = ReadStunMessage(&msg, kStunMessageWithUInt16ListAttribute);
1079 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1080 const StunUInt16ListAttribute* types = msg.GetUnknownAttributes();
1081 ASSERT_TRUE(types != NULL);
1082 EXPECT_EQ(3U, types->Size());
1083 EXPECT_EQ(0x1U, types->GetType(0));
1084 EXPECT_EQ(0x1000U, types->GetType(1));
1085 EXPECT_EQ(0xAB0CU, types->GetType(2));
1086}
1087
1088TEST_F(StunTest, ReadMessageWithAnUnknownAttribute) {
1089 StunMessage msg;
1090 size_t size = ReadStunMessage(&msg, kStunMessageWithUnknownAttribute);
1091 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1092
1093 // Parsing should have succeeded and there should be a USERNAME attribute
1094 const StunByteStringAttribute* username =
1095 msg.GetByteString(STUN_ATTR_USERNAME);
1096 ASSERT_TRUE(username != NULL);
1097 EXPECT_EQ(kTestUserName2, username->GetString());
1098}
1099
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001100TEST_F(StunTest, ReadMessageWithOriginAttribute) {
1101 StunMessage msg;
1102 size_t size = ReadStunMessage(&msg, kStunMessageWithOriginAttribute);
1103 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
Yves Gerey665174f2018-06-19 15:03:05 +02001104 const StunByteStringAttribute* origin = msg.GetByteString(STUN_ATTR_ORIGIN);
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001105 ASSERT_TRUE(origin != NULL);
1106 EXPECT_EQ(kTestOrigin, origin->GetString());
1107}
1108
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001109TEST_F(StunTest, WriteMessageWithAnErrorCodeAttribute) {
1110 StunMessage msg;
1111 size_t size = sizeof(kStunMessageWithErrorAttribute);
1112
1113 msg.SetType(STUN_BINDING_ERROR_RESPONSE);
1114 msg.SetTransactionID(
1115 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
1116 kStunTransactionIdLength));
1117 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
zsteinf42cc9d2017-03-27 16:17:19 -07001118 auto errorcode = StunAttribute::CreateErrorCode();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001119 errorcode->SetCode(kTestErrorCode);
1120 errorcode->SetReason(kTestErrorReason);
zsteinf42cc9d2017-03-27 16:17:19 -07001121 msg.AddAttribute(std::move(errorcode));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001122 CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, (size - 20));
1123
jbauchf1f87202016-03-30 06:43:37 -07001124 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001125 EXPECT_TRUE(msg.Write(&out));
1126 ASSERT_EQ(size, out.Length());
1127 // No padding.
1128 ASSERT_EQ(0, memcmp(out.Data(), kStunMessageWithErrorAttribute, size));
1129}
1130
1131TEST_F(StunTest, WriteMessageWithAUInt16ListAttribute) {
1132 StunMessage msg;
1133 size_t size = sizeof(kStunMessageWithUInt16ListAttribute);
1134
1135 msg.SetType(STUN_BINDING_REQUEST);
1136 msg.SetTransactionID(
1137 std::string(reinterpret_cast<const char*>(kTestTransactionId2),
1138 kStunTransactionIdLength));
1139 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
zsteinf42cc9d2017-03-27 16:17:19 -07001140 auto list = StunAttribute::CreateUnknownAttributes();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001141 list->AddType(0x1U);
1142 list->AddType(0x1000U);
1143 list->AddType(0xAB0CU);
zsteinf42cc9d2017-03-27 16:17:19 -07001144 msg.AddAttribute(std::move(list));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001145 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
1146
jbauchf1f87202016-03-30 06:43:37 -07001147 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001148 EXPECT_TRUE(msg.Write(&out));
1149 ASSERT_EQ(size, out.Length());
1150 // Check everything up to the padding.
1151 ASSERT_EQ(0,
1152 memcmp(out.Data(), kStunMessageWithUInt16ListAttribute, size - 2));
1153}
1154
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001155TEST_F(StunTest, WriteMessageWithOriginAttribute) {
1156 StunMessage msg;
1157 size_t size = sizeof(kStunMessageWithOriginAttribute);
1158
1159 msg.SetType(STUN_BINDING_REQUEST);
1160 msg.SetTransactionID(
1161 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
1162 kStunTransactionIdLength));
zsteinf42cc9d2017-03-27 16:17:19 -07001163 auto origin =
Mirko Bonadei317a1f02019-09-17 17:06:18 +02001164 std::make_unique<StunByteStringAttribute>(STUN_ATTR_ORIGIN, kTestOrigin);
zsteinf42cc9d2017-03-27 16:17:19 -07001165 msg.AddAttribute(std::move(origin));
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001166
jbauchf1f87202016-03-30 06:43:37 -07001167 rtc::ByteBufferWriter out;
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001168 EXPECT_TRUE(msg.Write(&out));
1169 ASSERT_EQ(size, out.Length());
1170 // Check everything up to the padding
1171 ASSERT_EQ(0, memcmp(out.Data(), kStunMessageWithOriginAttribute, size - 2));
1172}
1173
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001174// Test that we fail to read messages with invalid lengths.
1175void CheckFailureToRead(const unsigned char* testcase, size_t length) {
1176 StunMessage msg;
1177 const char* input = reinterpret_cast<const char*>(testcase);
jbauchf1f87202016-03-30 06:43:37 -07001178 rtc::ByteBufferReader buf(input, length);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001179 ASSERT_FALSE(msg.Read(&buf));
1180}
1181
1182TEST_F(StunTest, FailToReadInvalidMessages) {
1183 CheckFailureToRead(kStunMessageWithZeroLength,
1184 kRealLengthOfInvalidLengthTestCases);
1185 CheckFailureToRead(kStunMessageWithSmallLength,
1186 kRealLengthOfInvalidLengthTestCases);
1187 CheckFailureToRead(kStunMessageWithExcessLength,
1188 kRealLengthOfInvalidLengthTestCases);
1189}
1190
1191// Test that we properly fail to read a non-STUN message.
1192TEST_F(StunTest, FailToReadRtcpPacket) {
1193 CheckFailureToRead(kRtcpPacket, sizeof(kRtcpPacket));
1194}
1195
1196// Check our STUN message validation code against the RFC5769 test messages.
1197TEST_F(StunTest, ValidateMessageIntegrity) {
1198 // Try the messages from RFC 5769.
1199 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1200 reinterpret_cast<const char*>(kRfc5769SampleRequest),
Yves Gerey665174f2018-06-19 15:03:05 +02001201 sizeof(kRfc5769SampleRequest), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001202 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1203 reinterpret_cast<const char*>(kRfc5769SampleRequest),
Yves Gerey665174f2018-06-19 15:03:05 +02001204 sizeof(kRfc5769SampleRequest), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001205
1206 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1207 reinterpret_cast<const char*>(kRfc5769SampleResponse),
Yves Gerey665174f2018-06-19 15:03:05 +02001208 sizeof(kRfc5769SampleResponse), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001209 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1210 reinterpret_cast<const char*>(kRfc5769SampleResponse),
Yves Gerey665174f2018-06-19 15:03:05 +02001211 sizeof(kRfc5769SampleResponse), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001212
1213 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1214 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
Yves Gerey665174f2018-06-19 15:03:05 +02001215 sizeof(kRfc5769SampleResponseIPv6), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001216 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1217 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
Yves Gerey665174f2018-06-19 15:03:05 +02001218 sizeof(kRfc5769SampleResponseIPv6), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001219
1220 // We first need to compute the key for the long-term authentication HMAC.
1221 std::string key;
1222 ComputeStunCredentialHash(kRfc5769SampleMsgWithAuthUsername,
Yves Gerey665174f2018-06-19 15:03:05 +02001223 kRfc5769SampleMsgWithAuthRealm,
1224 kRfc5769SampleMsgWithAuthPassword, &key);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001225 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1226 reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth),
1227 sizeof(kRfc5769SampleRequestLongTermAuth), key));
1228 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1229 reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth),
Yves Gerey665174f2018-06-19 15:03:05 +02001230 sizeof(kRfc5769SampleRequestLongTermAuth), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001231
1232 // Try some edge cases.
1233 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1234 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
Yves Gerey665174f2018-06-19 15:03:05 +02001235 sizeof(kStunMessageWithZeroLength), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001236 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1237 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
Yves Gerey665174f2018-06-19 15:03:05 +02001238 sizeof(kStunMessageWithExcessLength), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001239 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1240 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
Yves Gerey665174f2018-06-19 15:03:05 +02001241 sizeof(kStunMessageWithSmallLength), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001242
katrielc1a206102016-06-20 05:13:16 -07001243 // Again, but with the lengths matching what is claimed in the headers.
1244 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1245 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1246 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithZeroLength[2]),
1247 kRfc5769SampleMsgPassword));
1248 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1249 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1250 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithExcessLength[2]),
1251 kRfc5769SampleMsgPassword));
1252 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1253 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1254 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithSmallLength[2]),
1255 kRfc5769SampleMsgPassword));
1256
1257 // Check that a too-short HMAC doesn't cause buffer overflow.
1258 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1259 reinterpret_cast<const char*>(kStunMessageWithBadHmacAtEnd),
Yves Gerey665174f2018-06-19 15:03:05 +02001260 sizeof(kStunMessageWithBadHmacAtEnd), kRfc5769SampleMsgPassword));
katrielc1a206102016-06-20 05:13:16 -07001261
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001262 // Test that munging a single bit anywhere in the message causes the
1263 // message-integrity check to fail, unless it is after the M-I attribute.
1264 char buf[sizeof(kRfc5769SampleRequest)];
1265 memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest));
1266 for (size_t i = 0; i < sizeof(buf); ++i) {
1267 buf[i] ^= 0x01;
1268 if (i > 0)
1269 buf[i - 1] ^= 0x01;
Yves Gerey665174f2018-06-19 15:03:05 +02001270 EXPECT_EQ(i >= sizeof(buf) - 8,
1271 StunMessage::ValidateMessageIntegrity(buf, sizeof(buf),
1272 kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001273 }
1274}
1275
1276// Validate that we generate correct MESSAGE-INTEGRITY attributes.
1277// Note the use of IceMessage instead of StunMessage; this is necessary because
1278// the RFC5769 test messages used include attributes not found in basic STUN.
1279TEST_F(StunTest, AddMessageIntegrity) {
1280 IceMessage msg;
jbauchf1f87202016-03-30 06:43:37 -07001281 rtc::ByteBufferReader buf(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001282 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1283 sizeof(kRfc5769SampleRequestWithoutMI));
1284 EXPECT_TRUE(msg.Read(&buf));
1285 EXPECT_TRUE(msg.AddMessageIntegrity(kRfc5769SampleMsgPassword));
1286 const StunByteStringAttribute* mi_attr =
1287 msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
1288 EXPECT_EQ(20U, mi_attr->length());
Yves Gerey665174f2018-06-19 15:03:05 +02001289 EXPECT_EQ(
1290 0, memcmp(mi_attr->bytes(), kCalculatedHmac1, sizeof(kCalculatedHmac1)));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001291
jbauchf1f87202016-03-30 06:43:37 -07001292 rtc::ByteBufferWriter buf1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001293 EXPECT_TRUE(msg.Write(&buf1));
1294 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
Yves Gerey665174f2018-06-19 15:03:05 +02001295 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(),
1296 kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001297
1298 IceMessage msg2;
jbauchf1f87202016-03-30 06:43:37 -07001299 rtc::ByteBufferReader buf2(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001300 reinterpret_cast<const char*>(kRfc5769SampleResponseWithoutMI),
1301 sizeof(kRfc5769SampleResponseWithoutMI));
1302 EXPECT_TRUE(msg2.Read(&buf2));
1303 EXPECT_TRUE(msg2.AddMessageIntegrity(kRfc5769SampleMsgPassword));
1304 const StunByteStringAttribute* mi_attr2 =
1305 msg2.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
1306 EXPECT_EQ(20U, mi_attr2->length());
1307 EXPECT_EQ(
1308 0, memcmp(mi_attr2->bytes(), kCalculatedHmac2, sizeof(kCalculatedHmac2)));
1309
jbauchf1f87202016-03-30 06:43:37 -07001310 rtc::ByteBufferWriter buf3;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001311 EXPECT_TRUE(msg2.Write(&buf3));
1312 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
Yves Gerey665174f2018-06-19 15:03:05 +02001313 reinterpret_cast<const char*>(buf3.Data()), buf3.Length(),
1314 kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001315}
1316
1317// Check our STUN message validation code against the RFC5769 test messages.
Jonas Oreland63737a92019-11-21 15:12:14 +01001318TEST_F(StunTest, ValidateMessageIntegrity32) {
1319 // Try the messages from RFC 5769.
1320 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32(
1321 reinterpret_cast<const char*>(kSampleRequestMI32),
1322 sizeof(kSampleRequestMI32), kRfc5769SampleMsgPassword));
1323 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32(
1324 reinterpret_cast<const char*>(kSampleRequestMI32),
1325 sizeof(kSampleRequestMI32), "InvalidPassword"));
1326
1327 // Try some edge cases.
1328 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32(
1329 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1330 sizeof(kStunMessageWithZeroLength), kRfc5769SampleMsgPassword));
1331 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32(
1332 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1333 sizeof(kStunMessageWithExcessLength), kRfc5769SampleMsgPassword));
1334 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32(
1335 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1336 sizeof(kStunMessageWithSmallLength), kRfc5769SampleMsgPassword));
1337
1338 // Again, but with the lengths matching what is claimed in the headers.
1339 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32(
1340 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1341 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithZeroLength[2]),
1342 kRfc5769SampleMsgPassword));
1343 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32(
1344 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1345 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithExcessLength[2]),
1346 kRfc5769SampleMsgPassword));
1347 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32(
1348 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1349 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithSmallLength[2]),
1350 kRfc5769SampleMsgPassword));
1351
1352 // Check that a too-short HMAC doesn't cause buffer overflow.
1353 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32(
1354 reinterpret_cast<const char*>(kStunMessageWithBadHmacAtEnd),
1355 sizeof(kStunMessageWithBadHmacAtEnd), kRfc5769SampleMsgPassword));
1356
1357 // Test that munging a single bit anywhere in the message causes the
1358 // message-integrity check to fail, unless it is after the M-I attribute.
1359 char buf[sizeof(kSampleRequestMI32)];
1360 memcpy(buf, kSampleRequestMI32, sizeof(kSampleRequestMI32));
1361 for (size_t i = 0; i < sizeof(buf); ++i) {
1362 buf[i] ^= 0x01;
1363 if (i > 0)
1364 buf[i - 1] ^= 0x01;
1365 EXPECT_EQ(i >= sizeof(buf) - 8,
1366 StunMessage::ValidateMessageIntegrity32(
1367 buf, sizeof(buf), kRfc5769SampleMsgPassword));
1368 }
1369}
1370
1371// Validate that we generate correct MESSAGE-INTEGRITY-32 attributes.
1372TEST_F(StunTest, AddMessageIntegrity32) {
1373 IceMessage msg;
1374 rtc::ByteBufferReader buf(
1375 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1376 sizeof(kRfc5769SampleRequestWithoutMI));
1377 EXPECT_TRUE(msg.Read(&buf));
1378 EXPECT_TRUE(msg.AddMessageIntegrity32(kRfc5769SampleMsgPassword));
1379 const StunByteStringAttribute* mi_attr =
1380 msg.GetByteString(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32);
1381 EXPECT_EQ(4U, mi_attr->length());
1382 EXPECT_EQ(0, memcmp(mi_attr->bytes(), kCalculatedHmac1_32,
1383 sizeof(kCalculatedHmac1_32)));
1384
1385 rtc::ByteBufferWriter buf1;
1386 EXPECT_TRUE(msg.Write(&buf1));
1387 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32(
1388 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(),
1389 kRfc5769SampleMsgPassword));
1390
1391 IceMessage msg2;
1392 rtc::ByteBufferReader buf2(
1393 reinterpret_cast<const char*>(kRfc5769SampleResponseWithoutMI),
1394 sizeof(kRfc5769SampleResponseWithoutMI));
1395 EXPECT_TRUE(msg2.Read(&buf2));
1396 EXPECT_TRUE(msg2.AddMessageIntegrity32(kRfc5769SampleMsgPassword));
1397 const StunByteStringAttribute* mi_attr2 =
1398 msg2.GetByteString(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32);
1399 EXPECT_EQ(4U, mi_attr2->length());
1400 EXPECT_EQ(0, memcmp(mi_attr2->bytes(), kCalculatedHmac2_32,
1401 sizeof(kCalculatedHmac2_32)));
1402
1403 rtc::ByteBufferWriter buf3;
1404 EXPECT_TRUE(msg2.Write(&buf3));
1405 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32(
1406 reinterpret_cast<const char*>(buf3.Data()), buf3.Length(),
1407 kRfc5769SampleMsgPassword));
1408}
1409
1410// Validate that the message validates if both MESSAGE-INTEGRITY-32 and
1411// MESSAGE-INTEGRITY are present in the message.
1412// This is not expected to be used, but is not forbidden.
1413TEST_F(StunTest, AddMessageIntegrity32AndMessageIntegrity) {
1414 IceMessage msg;
1415 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1416 attr->CopyBytes("keso", sizeof("keso"));
1417 msg.AddAttribute(std::move(attr));
1418 msg.AddMessageIntegrity32("password1");
1419 msg.AddMessageIntegrity("password2");
1420
1421 rtc::ByteBufferWriter buf1;
1422 EXPECT_TRUE(msg.Write(&buf1));
1423 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32(
1424 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password1"));
1425 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1426 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password2"));
1427
1428 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32(
1429 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password2"));
1430 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1431 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password1"));
1432}
1433
1434// Check our STUN message validation code against the RFC5769 test messages.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001435TEST_F(StunTest, ValidateFingerprint) {
1436 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1437 reinterpret_cast<const char*>(kRfc5769SampleRequest),
1438 sizeof(kRfc5769SampleRequest)));
1439 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1440 reinterpret_cast<const char*>(kRfc5769SampleResponse),
1441 sizeof(kRfc5769SampleResponse)));
1442 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1443 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
1444 sizeof(kRfc5769SampleResponseIPv6)));
1445
1446 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1447 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1448 sizeof(kStunMessageWithZeroLength)));
1449 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1450 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1451 sizeof(kStunMessageWithExcessLength)));
1452 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1453 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1454 sizeof(kStunMessageWithSmallLength)));
1455
1456 // Test that munging a single bit anywhere in the message causes the
1457 // fingerprint check to fail.
1458 char buf[sizeof(kRfc5769SampleRequest)];
1459 memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest));
1460 for (size_t i = 0; i < sizeof(buf); ++i) {
1461 buf[i] ^= 0x01;
1462 if (i > 0)
1463 buf[i - 1] ^= 0x01;
1464 EXPECT_FALSE(StunMessage::ValidateFingerprint(buf, sizeof(buf)));
1465 }
1466 // Put them all back to normal and the check should pass again.
1467 buf[sizeof(buf) - 1] ^= 0x01;
1468 EXPECT_TRUE(StunMessage::ValidateFingerprint(buf, sizeof(buf)));
1469}
1470
1471TEST_F(StunTest, AddFingerprint) {
1472 IceMessage msg;
jbauchf1f87202016-03-30 06:43:37 -07001473 rtc::ByteBufferReader buf(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001474 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1475 sizeof(kRfc5769SampleRequestWithoutMI));
1476 EXPECT_TRUE(msg.Read(&buf));
1477 EXPECT_TRUE(msg.AddFingerprint());
1478
jbauchf1f87202016-03-30 06:43:37 -07001479 rtc::ByteBufferWriter buf1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001480 EXPECT_TRUE(msg.Write(&buf1));
1481 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1482 reinterpret_cast<const char*>(buf1.Data()), buf1.Length()));
1483}
1484
1485// Sample "GTURN" relay message.
Yves Gerey665174f2018-06-19 15:03:05 +02001486// clang-format off
1487// clang formatting doesn't respect inline comments.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001488static const unsigned char kRelayMessage[] = {
1489 0x00, 0x01, 0x00, 88, // message header
1490 0x21, 0x12, 0xA4, 0x42, // magic cookie
1491 '0', '1', '2', '3', // transaction id
1492 '4', '5', '6', '7',
1493 '8', '9', 'a', 'b',
1494 0x00, 0x01, 0x00, 8, // mapped address
1495 0x00, 0x01, 0x00, 13,
1496 0x00, 0x00, 0x00, 17,
1497 0x00, 0x06, 0x00, 12, // username
1498 'a', 'b', 'c', 'd',
1499 'e', 'f', 'g', 'h',
1500 'i', 'j', 'k', 'l',
1501 0x00, 0x0d, 0x00, 4, // lifetime
1502 0x00, 0x00, 0x00, 11,
1503 0x00, 0x0f, 0x00, 4, // magic cookie
1504 0x72, 0xc6, 0x4b, 0xc6,
1505 0x00, 0x10, 0x00, 4, // bandwidth
1506 0x00, 0x00, 0x00, 6,
1507 0x00, 0x11, 0x00, 8, // destination address
1508 0x00, 0x01, 0x00, 13,
1509 0x00, 0x00, 0x00, 17,
1510 0x00, 0x12, 0x00, 8, // source address 2
1511 0x00, 0x01, 0x00, 13,
1512 0x00, 0x00, 0x00, 17,
1513 0x00, 0x13, 0x00, 7, // data
1514 'a', 'b', 'c', 'd',
1515 'e', 'f', 'g', 0 // DATA must be padded per rfc5766.
1516};
Yves Gerey665174f2018-06-19 15:03:05 +02001517// clang-format on
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001518
1519// Test that we can read the GTURN-specific fields.
1520TEST_F(StunTest, ReadRelayMessage) {
1521 RelayMessage msg, msg2;
1522
1523 const char* input = reinterpret_cast<const char*>(kRelayMessage);
1524 size_t size = sizeof(kRelayMessage);
jbauchf1f87202016-03-30 06:43:37 -07001525 rtc::ByteBufferReader buf(input, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001526 EXPECT_TRUE(msg.Read(&buf));
1527
1528 EXPECT_EQ(STUN_BINDING_REQUEST, msg.type());
1529 EXPECT_EQ(size - 20, msg.length());
1530 EXPECT_EQ("0123456789ab", msg.transaction_id());
1531
1532 msg2.SetType(STUN_BINDING_REQUEST);
1533 msg2.SetTransactionID("0123456789ab");
1534
1535 in_addr legacy_in_addr;
1536 legacy_in_addr.s_addr = htonl(17U);
1537 rtc::IPAddress legacy_ip(legacy_in_addr);
1538
1539 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
1540 ASSERT_TRUE(addr != NULL);
1541 EXPECT_EQ(1, addr->family());
1542 EXPECT_EQ(13, addr->port());
1543 EXPECT_EQ(legacy_ip, addr->ipaddr());
1544
zsteinf42cc9d2017-03-27 16:17:19 -07001545 auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001546 addr2->SetPort(13);
1547 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001548 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001549
1550 const StunByteStringAttribute* bytes = msg.GetByteString(STUN_ATTR_USERNAME);
1551 ASSERT_TRUE(bytes != NULL);
1552 EXPECT_EQ(12U, bytes->length());
1553 EXPECT_EQ("abcdefghijkl", bytes->GetString());
1554
zsteinf42cc9d2017-03-27 16:17:19 -07001555 auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001556 bytes2->CopyBytes("abcdefghijkl");
zsteinf42cc9d2017-03-27 16:17:19 -07001557 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001558
1559 const StunUInt32Attribute* uval = msg.GetUInt32(STUN_ATTR_LIFETIME);
1560 ASSERT_TRUE(uval != NULL);
1561 EXPECT_EQ(11U, uval->value());
1562
zsteinf42cc9d2017-03-27 16:17:19 -07001563 auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001564 uval2->SetValue(11);
zsteinf42cc9d2017-03-27 16:17:19 -07001565 msg2.AddAttribute(std::move(uval2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001566
1567 bytes = msg.GetByteString(STUN_ATTR_MAGIC_COOKIE);
1568 ASSERT_TRUE(bytes != NULL);
1569 EXPECT_EQ(4U, bytes->length());
Yves Gerey665174f2018-06-19 15:03:05 +02001570 EXPECT_EQ(0, memcmp(bytes->bytes(), TURN_MAGIC_COOKIE_VALUE,
1571 sizeof(TURN_MAGIC_COOKIE_VALUE)));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001572
1573 bytes2 = StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
1574 bytes2->CopyBytes(reinterpret_cast<const char*>(TURN_MAGIC_COOKIE_VALUE),
1575 sizeof(TURN_MAGIC_COOKIE_VALUE));
zsteinf42cc9d2017-03-27 16:17:19 -07001576 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001577
1578 uval = msg.GetUInt32(STUN_ATTR_BANDWIDTH);
1579 ASSERT_TRUE(uval != NULL);
1580 EXPECT_EQ(6U, uval->value());
1581
1582 uval2 = StunAttribute::CreateUInt32(STUN_ATTR_BANDWIDTH);
1583 uval2->SetValue(6);
zsteinf42cc9d2017-03-27 16:17:19 -07001584 msg2.AddAttribute(std::move(uval2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001585
1586 addr = msg.GetAddress(STUN_ATTR_DESTINATION_ADDRESS);
1587 ASSERT_TRUE(addr != NULL);
1588 EXPECT_EQ(1, addr->family());
1589 EXPECT_EQ(13, addr->port());
1590 EXPECT_EQ(legacy_ip, addr->ipaddr());
1591
1592 addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
1593 addr2->SetPort(13);
1594 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001595 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001596
1597 addr = msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2);
1598 ASSERT_TRUE(addr != NULL);
1599 EXPECT_EQ(1, addr->family());
1600 EXPECT_EQ(13, addr->port());
1601 EXPECT_EQ(legacy_ip, addr->ipaddr());
1602
1603 addr2 = StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2);
1604 addr2->SetPort(13);
1605 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001606 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001607
1608 bytes = msg.GetByteString(STUN_ATTR_DATA);
1609 ASSERT_TRUE(bytes != NULL);
1610 EXPECT_EQ(7U, bytes->length());
1611 EXPECT_EQ("abcdefg", bytes->GetString());
1612
1613 bytes2 = StunAttribute::CreateByteString(STUN_ATTR_DATA);
1614 bytes2->CopyBytes("abcdefg");
zsteinf42cc9d2017-03-27 16:17:19 -07001615 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001616
jbauchf1f87202016-03-30 06:43:37 -07001617 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001618 EXPECT_TRUE(msg.Write(&out));
1619 EXPECT_EQ(size, out.Length());
1620 size_t len1 = out.Length();
jbauchf1f87202016-03-30 06:43:37 -07001621 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001622 std::string outstring;
jbauchf1f87202016-03-30 06:43:37 -07001623 read_buf.ReadString(&outstring, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001624 EXPECT_EQ(0, memcmp(outstring.c_str(), input, len1));
1625
jbauchf1f87202016-03-30 06:43:37 -07001626 rtc::ByteBufferWriter out2;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001627 EXPECT_TRUE(msg2.Write(&out2));
1628 EXPECT_EQ(size, out2.Length());
1629 size_t len2 = out2.Length();
jbauchf1f87202016-03-30 06:43:37 -07001630 rtc::ByteBufferReader read_buf2(out2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001631 std::string outstring2;
jbauchf1f87202016-03-30 06:43:37 -07001632 read_buf2.ReadString(&outstring2, len2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001633 EXPECT_EQ(0, memcmp(outstring2.c_str(), input, len2));
1634}
1635
Jonas Oreland202994c2017-12-18 12:10:43 +01001636// Test that we can remove attribute from a message.
1637TEST_F(StunTest, RemoveAttribute) {
1638 StunMessage msg;
1639
1640 // Removing something that does exist should return nullptr.
1641 EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr);
1642
1643 {
1644 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1645 attr->CopyBytes("kes", sizeof("kes"));
1646 msg.AddAttribute(std::move(attr));
1647 }
1648
1649 size_t len = msg.length();
1650 {
1651 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1652 ASSERT_NE(attr, nullptr);
1653 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1654 EXPECT_STREQ("kes",
1655 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1656 EXPECT_LT(msg.length(), len);
1657 }
1658
1659 // Now add same attribute type twice.
1660 {
1661 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1662 attr->CopyBytes("kes", sizeof("kes"));
1663 msg.AddAttribute(std::move(attr));
1664 }
1665
1666 {
1667 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1668 attr->CopyBytes("kenta", sizeof("kenta"));
1669 msg.AddAttribute(std::move(attr));
1670 }
1671
1672 // Remove should remove the last added occurrence.
1673 {
1674 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1675 ASSERT_NE(attr, nullptr);
1676 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1677 EXPECT_STREQ("kenta",
1678 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1679 }
1680
1681 // Remove should remove the last added occurrence.
1682 {
1683 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1684 ASSERT_NE(attr, nullptr);
1685 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1686 EXPECT_STREQ("kes",
1687 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1688 }
1689
1690 // Removing something that does exist should return nullptr.
1691 EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr);
1692}
1693
Jonas Oreland63737a92019-11-21 15:12:14 +01001694// Test that we can remove attribute from a message.
1695TEST_F(StunTest, ClearAttributes) {
1696 StunMessage msg;
1697
1698 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1699 attr->CopyBytes("kes", sizeof("kes"));
1700 msg.AddAttribute(std::move(attr));
1701 size_t len = msg.length();
1702
1703 msg.ClearAttributes();
1704 EXPECT_EQ(msg.length(), len - /* 3 + 1 byte padding + header */ 8);
1705 EXPECT_EQ(nullptr, msg.GetByteString(STUN_ATTR_USERNAME));
1706}
1707
Jonas Oreland202994c2017-12-18 12:10:43 +01001708// Test CopyStunAttribute
1709TEST_F(StunTest, CopyAttribute) {
1710 rtc::ByteBufferWriter buf;
Yves Gerey665174f2018-06-19 15:03:05 +02001711 rtc::ByteBufferWriter* buffer_ptrs[] = {&buf, nullptr};
Jonas Oreland202994c2017-12-18 12:10:43 +01001712 // Test both with and without supplied ByteBufferWriter.
1713 for (auto buffer_ptr : buffer_ptrs) {
Yves Gerey665174f2018-06-19 15:03:05 +02001714 { // Test StunByteStringAttribute.
Jonas Oreland202994c2017-12-18 12:10:43 +01001715 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1716 attr->CopyBytes("kes", sizeof("kes"));
1717
1718 auto copy = CopyStunAttribute(*attr.get(), buffer_ptr);
1719 ASSERT_EQ(copy->value_type(), STUN_VALUE_BYTE_STRING);
1720 EXPECT_STREQ("kes",
1721 static_cast<StunByteStringAttribute*>(copy.get())->bytes());
1722 }
1723
Yves Gerey665174f2018-06-19 15:03:05 +02001724 { // Test StunAddressAttribute.
Jonas Oreland202994c2017-12-18 12:10:43 +01001725 rtc::IPAddress test_ip(kIPv6TestAddress2);
1726 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
1727 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
1728 addr->SetAddress(test_addr);
Yves Gerey665174f2018-06-19 15:03:05 +02001729 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6,
1730 kTestMessagePort2, test_ip);
Jonas Oreland202994c2017-12-18 12:10:43 +01001731
1732 auto copy = CopyStunAttribute(*addr.get(), buffer_ptr);
1733 ASSERT_EQ(copy->value_type(), STUN_VALUE_ADDRESS);
1734 CheckStunAddressAttribute(static_cast<StunAddressAttribute*>(copy.get()),
1735 STUN_ADDRESS_IPV6, kTestMessagePort2, test_ip);
1736 }
Jonas Oreland63737a92019-11-21 15:12:14 +01001737
1738 { // Test StunAddressAttribute.
1739 rtc::IPAddress test_ip(kIPv6TestAddress2);
1740 auto addr = StunAttribute::CreateAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
1741 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
1742 addr->SetAddress(test_addr);
1743 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6,
1744 kTestMessagePort2, test_ip);
1745
1746 auto copy = CopyStunAttribute(*addr.get(), buffer_ptr);
1747 ASSERT_EQ(copy->value_type(), STUN_VALUE_ADDRESS);
1748 CheckStunAddressAttribute(static_cast<StunAddressAttribute*>(copy.get()),
1749 STUN_ADDRESS_IPV6, kTestMessagePort2, test_ip);
1750 }
Jonas Oreland202994c2017-12-18 12:10:43 +01001751 }
1752}
1753
Zach Steinff71a492018-12-07 11:25:12 -08001754TEST_F(StunTest, ReduceTransactionIdIsHostOrderIndependent) {
1755 std::string transaction_id = "abcdefghijkl";
1756 StunMessage message;
1757 ASSERT_TRUE(message.SetTransactionID(transaction_id));
1758 uint32_t reduced_transaction_id = message.reduced_transaction_id();
1759 EXPECT_EQ(reduced_transaction_id, 1835954016u);
1760}
1761
Jonas Oreland1721de12019-11-20 12:10:39 +01001762TEST_F(StunTest, GoogMiscInfo) {
1763 StunMessage msg;
1764 const size_t size =
1765 /* msg header */ 20 +
1766 /* attr header */ 4 +
1767 /* 3 * 2 rounded to multiple of 4 */ 8;
1768 msg.SetType(STUN_BINDING_REQUEST);
1769 msg.SetTransactionID("ABCDEFGH");
1770 auto list =
1771 StunAttribute::CreateUInt16ListAttribute(STUN_ATTR_GOOG_MISC_INFO);
Jonas Oreland63737a92019-11-21 15:12:14 +01001772 list->AddTypeAtIndex(0, 0x1U);
1773 list->AddTypeAtIndex(3, 0x1000U);
1774 list->AddTypeAtIndex(2, 0xAB0CU);
Jonas Oreland1721de12019-11-20 12:10:39 +01001775 msg.AddAttribute(std::move(list));
1776 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
1777
1778 rtc::ByteBufferWriter out;
1779 EXPECT_TRUE(msg.Write(&out));
1780 ASSERT_EQ(size, out.Length());
1781
1782 size_t read_size = ReadStunMessageTestCase(
1783 &msg, reinterpret_cast<const unsigned char*>(out.Data()), out.Length());
1784 ASSERT_EQ(read_size + 20, size);
1785 CheckStunHeader(msg, STUN_BINDING_REQUEST, read_size);
1786 const StunUInt16ListAttribute* types =
1787 msg.GetUInt16List(STUN_ATTR_GOOG_MISC_INFO);
1788 ASSERT_TRUE(types != NULL);
Jonas Oreland63737a92019-11-21 15:12:14 +01001789 EXPECT_EQ(4U, types->Size());
Jonas Oreland1721de12019-11-20 12:10:39 +01001790 EXPECT_EQ(0x1U, types->GetType(0));
Jonas Oreland63737a92019-11-21 15:12:14 +01001791 EXPECT_EQ(0x0U, types->GetType(1));
1792 EXPECT_EQ(0x1000U, types->GetType(3));
Jonas Oreland1721de12019-11-20 12:10:39 +01001793 EXPECT_EQ(0xAB0CU, types->GetType(2));
1794}
1795
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001796} // namespace cricket