blob: b7d5f50fdb54eab652ebc6add2543d42cdf3d69c [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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "p2p/base/stun.h"
12
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000015#include <string>
Steve Anton6c38cc72017-11-29 10:25:58 -080016#include <utility>
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000017
Karl Wiberg918f50c2018-07-05 11:40:33 +020018#include "absl/memory/memory.h"
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
335// 2.2. Sample IPv4 Response
336static const unsigned char kRfc5769SampleResponse[] = {
337 0x01, 0x01, 0x00, 0x3c, // Response 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, 0x0b, // SOFTWARE attribute header
343 0x74, 0x65, 0x73, 0x74, // }
344 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
345 0x74, 0x6f, 0x72, 0x20, // }
346 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
347 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port
348 0xe1, 0x12, 0xa6, 0x43, // Xor'd mapped IPv4 address
349 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
350 0x2b, 0x91, 0xf5, 0x99, // }
351 0xfd, 0x9e, 0x90, 0xc3, // }
352 0x8c, 0x74, 0x89, 0xf9, // } HMAC-SHA1 fingerprint
353 0x2a, 0xf9, 0xba, 0x53, // }
354 0xf0, 0x6b, 0xe7, 0xd7, // }
355 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
356 0xc0, 0x7d, 0x4c, 0x96 // CRC32 fingerprint
357};
358
359// 2.3. Sample IPv6 Response
360static const unsigned char kRfc5769SampleResponseIPv6[] = {
361 0x01, 0x01, 0x00, 0x48, // Response type and message length
362 0x21, 0x12, 0xa4, 0x42, // Magic cookie
363 0xb7, 0xe7, 0xa7, 0x01, // }
364 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
365 0xfa, 0x87, 0xdf, 0xae, // }
366 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
367 0x74, 0x65, 0x73, 0x74, // }
368 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
369 0x74, 0x6f, 0x72, 0x20, // }
370 0x00, 0x20, 0x00, 0x14, // XOR-MAPPED-ADDRESS attribute header
371 0x00, 0x02, 0xa1, 0x47, // Address family (IPv6) and xor'd mapped port.
372 0x01, 0x13, 0xa9, 0xfa, // }
373 0xa5, 0xd3, 0xf1, 0x79, // } Xor'd mapped IPv6 address
374 0xbc, 0x25, 0xf4, 0xb5, // }
375 0xbe, 0xd2, 0xb9, 0xd9, // }
376 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
377 0xa3, 0x82, 0x95, 0x4e, // }
378 0x4b, 0xe6, 0x7b, 0xf1, // }
379 0x17, 0x84, 0xc9, 0x7c, // } HMAC-SHA1 fingerprint
380 0x82, 0x92, 0xc2, 0x75, // }
381 0xbf, 0xe3, 0xed, 0x41, // }
382 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
383 0xc8, 0xfb, 0x0b, 0x4c // CRC32 fingerprint
384};
385
386// 2.4. Sample Request with Long-Term Authentication
387static const unsigned char kRfc5769SampleRequestLongTermAuth[] = {
388 0x00, 0x01, 0x00, 0x60, // Request type and message length
389 0x21, 0x12, 0xa4, 0x42, // Magic cookie
390 0x78, 0xad, 0x34, 0x33, // }
391 0xc6, 0xad, 0x72, 0xc0, // } Transaction ID
392 0x29, 0xda, 0x41, 0x2e, // }
393 0x00, 0x06, 0x00, 0x12, // USERNAME attribute header
394 0xe3, 0x83, 0x9e, 0xe3, // }
395 0x83, 0x88, 0xe3, 0x83, // }
396 0xaa, 0xe3, 0x83, 0x83, // } Username value (18 bytes) and padding (2 bytes)
397 0xe3, 0x82, 0xaf, 0xe3, // }
398 0x82, 0xb9, 0x00, 0x00, // }
399 0x00, 0x15, 0x00, 0x1c, // NONCE attribute header
400 0x66, 0x2f, 0x2f, 0x34, // }
401 0x39, 0x39, 0x6b, 0x39, // }
402 0x35, 0x34, 0x64, 0x36, // }
403 0x4f, 0x4c, 0x33, 0x34, // } Nonce value
404 0x6f, 0x4c, 0x39, 0x46, // }
405 0x53, 0x54, 0x76, 0x79, // }
406 0x36, 0x34, 0x73, 0x41, // }
407 0x00, 0x14, 0x00, 0x0b, // REALM attribute header
408 0x65, 0x78, 0x61, 0x6d, // }
409 0x70, 0x6c, 0x65, 0x2e, // } Realm value (11 bytes) and padding (1 byte)
410 0x6f, 0x72, 0x67, 0x00, // }
411 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
412 0xf6, 0x70, 0x24, 0x65, // }
413 0x6d, 0xd6, 0x4a, 0x3e, // }
414 0x02, 0xb8, 0xe0, 0x71, // } HMAC-SHA1 fingerprint
415 0x2e, 0x85, 0xc9, 0xa2, // }
416 0x8c, 0xa8, 0x96, 0x66 // }
417};
418
419// Length parameter is changed to 0x38 from 0x58.
420// AddMessageIntegrity will add MI information and update the length param
421// accordingly.
422static const unsigned char kRfc5769SampleRequestWithoutMI[] = {
423 0x00, 0x01, 0x00, 0x38, // Request type and message length
424 0x21, 0x12, 0xa4, 0x42, // Magic cookie
425 0xb7, 0xe7, 0xa7, 0x01, // }
426 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
427 0xfa, 0x87, 0xdf, 0xae, // }
428 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
429 0x53, 0x54, 0x55, 0x4e, // }
430 0x20, 0x74, 0x65, 0x73, // } User-agent...
431 0x74, 0x20, 0x63, 0x6c, // } ...name
432 0x69, 0x65, 0x6e, 0x74, // }
433 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
434 0x6e, 0x00, 0x01, 0xff, // ICE priority value
435 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
436 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
437 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
438 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
439 0x65, 0x76, 0x74, 0x6a, // }
440 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
441 0x59, 0x20, 0x20, 0x20 // }
442};
443
444// This HMAC differs from the RFC 5769 SampleRequest message. This differs
445// because spec uses 0x20 for the padding where as our implementation uses 0.
446static const unsigned char kCalculatedHmac1[] = {
447 0x79, 0x07, 0xc2, 0xd2, // }
448 0xed, 0xbf, 0xea, 0x48, // }
449 0x0e, 0x4c, 0x76, 0xd8, // } HMAC-SHA1 fingerprint
450 0x29, 0x62, 0xd5, 0xc3, // }
451 0x74, 0x2a, 0xf9, 0xe3 // }
452};
453
454// Length parameter is changed to 0x1c from 0x3c.
455// AddMessageIntegrity will add MI information and update the length param
456// accordingly.
457static const unsigned char kRfc5769SampleResponseWithoutMI[] = {
458 0x01, 0x01, 0x00, 0x1c, // Response type and message length
459 0x21, 0x12, 0xa4, 0x42, // Magic cookie
460 0xb7, 0xe7, 0xa7, 0x01, // }
461 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
462 0xfa, 0x87, 0xdf, 0xae, // }
463 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
464 0x74, 0x65, 0x73, 0x74, // }
465 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
466 0x74, 0x6f, 0x72, 0x20, // }
467 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
468 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port
469 0xe1, 0x12, 0xa6, 0x43 // Xor'd mapped IPv4 address
470};
471
472// This HMAC differs from the RFC 5769 SampleResponse message. This differs
473// because spec uses 0x20 for the padding where as our implementation uses 0.
474static const unsigned char kCalculatedHmac2[] = {
475 0x5d, 0x6b, 0x58, 0xbe, // }
476 0xad, 0x94, 0xe0, 0x7e, // }
477 0xef, 0x0d, 0xfc, 0x12, // } HMAC-SHA1 fingerprint
478 0x82, 0xa2, 0xbd, 0x08, // }
479 0x43, 0x14, 0x10, 0x28 // }
480};
481
Yves Gerey665174f2018-06-19 15:03:05 +0200482// clang-format on
483
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000484// A transaction ID without the 'magic cookie' portion
485// pjnat's test programs use this transaction ID a lot.
Yves Gerey665174f2018-06-19 15:03:05 +0200486const unsigned char kTestTransactionId1[] = {0x029, 0x01f, 0x0cd, 0x07c,
487 0x0ba, 0x058, 0x0ab, 0x0d7,
488 0x0f2, 0x041, 0x001, 0x000};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000489
490// They use this one sometimes too.
Yves Gerey665174f2018-06-19 15:03:05 +0200491const unsigned char kTestTransactionId2[] = {0x0e3, 0x0a9, 0x046, 0x0e1,
492 0x07c, 0x000, 0x0c2, 0x062,
493 0x054, 0x008, 0x001, 0x000};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000494
Yves Gerey665174f2018-06-19 15:03:05 +0200495const in6_addr kIPv6TestAddress1 = {
496 {{0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, 0x10, 0x00, 0xbe, 0x30, 0x5b, 0xff,
497 0xfe, 0xe5, 0x00, 0xc3}}};
498const in6_addr kIPv6TestAddress2 = {
499 {{0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, 0x10, 0x12, 0x06, 0x0c, 0xce, 0xff,
500 0xfe, 0x1f, 0x61, 0xa4}}};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000501
502#ifdef WEBRTC_POSIX
Yves Gerey665174f2018-06-19 15:03:05 +0200503const in_addr kIPv4TestAddress1 = {0xe64417ac};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000504#elif defined WEBRTC_WIN
505// Windows in_addr has a union with a uchar[] array first.
Yves Gerey665174f2018-06-19 15:03:05 +0200506const in_addr kIPv4TestAddress1 = {{{0x0ac, 0x017, 0x044, 0x0e6}}};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000507#endif
508const char kTestUserName1[] = "abcdefgh";
509const char kTestUserName2[] = "abc";
510const char kTestErrorReason[] = "Unauthorized";
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000511const char kTestOrigin[] = "http://example.com";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000512const int kTestErrorClass = 4;
513const int kTestErrorNumber = 1;
514const int kTestErrorCode = 401;
515
516const int kTestMessagePort1 = 59977;
517const int kTestMessagePort2 = 47233;
518const int kTestMessagePort3 = 56743;
519const int kTestMessagePort4 = 40444;
520
521#define ReadStunMessage(X, Y) ReadStunMessageTestCase(X, Y, sizeof(Y));
522
523// Test that the GetStun*Type and IsStun*Type methods work as expected.
524TEST_F(StunTest, MessageTypes) {
525 EXPECT_EQ(STUN_BINDING_RESPONSE,
Yves Gerey665174f2018-06-19 15:03:05 +0200526 GetStunSuccessResponseType(STUN_BINDING_REQUEST));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000527 EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE,
Yves Gerey665174f2018-06-19 15:03:05 +0200528 GetStunErrorResponseType(STUN_BINDING_REQUEST));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000529 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_INDICATION));
530 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_RESPONSE));
531 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_ERROR_RESPONSE));
532 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_INDICATION));
533 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_RESPONSE));
534 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_ERROR_RESPONSE));
535
Yves Gerey665174f2018-06-19 15:03:05 +0200536 int types[] = {STUN_BINDING_REQUEST, STUN_BINDING_INDICATION,
537 STUN_BINDING_RESPONSE, STUN_BINDING_ERROR_RESPONSE};
tfarina5237aaf2015-11-10 23:44:30 -0800538 for (size_t i = 0; i < arraysize(types); ++i) {
539 EXPECT_EQ(i == 0U, IsStunRequestType(types[i]));
540 EXPECT_EQ(i == 1U, IsStunIndicationType(types[i]));
541 EXPECT_EQ(i == 2U, IsStunSuccessResponseType(types[i]));
542 EXPECT_EQ(i == 3U, IsStunErrorResponseType(types[i]));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000543 EXPECT_EQ(1, types[i] & 0xFEEF);
544 }
545}
546
547TEST_F(StunTest, ReadMessageWithIPv4AddressAttribute) {
548 StunMessage msg;
549 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4MappedAddress);
550 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
551 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
552
553 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
554 rtc::IPAddress test_address(kIPv4TestAddress1);
Yves Gerey665174f2018-06-19 15:03:05 +0200555 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort4,
556 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000557}
558
559TEST_F(StunTest, ReadMessageWithIPv4XorAddressAttribute) {
560 StunMessage msg;
561 StunMessage msg2;
562 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress);
563 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
564 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
565
566 const StunAddressAttribute* addr =
567 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
568 rtc::IPAddress test_address(kIPv4TestAddress1);
Yves Gerey665174f2018-06-19 15:03:05 +0200569 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort3,
570 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000571}
572
573TEST_F(StunTest, ReadMessageWithIPv6AddressAttribute) {
574 StunMessage msg;
575 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
576 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
577 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
578
579 rtc::IPAddress test_address(kIPv6TestAddress1);
580
581 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200582 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort2,
583 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000584}
585
586TEST_F(StunTest, ReadMessageWithInvalidAddressAttribute) {
587 StunMessage msg;
588 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
589 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
590 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
591
592 rtc::IPAddress test_address(kIPv6TestAddress1);
593
594 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200595 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort2,
596 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000597}
598
599TEST_F(StunTest, ReadMessageWithIPv6XorAddressAttribute) {
600 StunMessage msg;
601 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress);
602
603 rtc::IPAddress test_address(kIPv6TestAddress1);
604
605 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
606 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
607
608 const StunAddressAttribute* addr =
609 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200610 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort1,
611 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000612}
613
614// Read the RFC5389 fields from the RFC5769 sample STUN request.
615TEST_F(StunTest, ReadRfc5769RequestMessage) {
616 StunMessage msg;
617 size_t size = ReadStunMessage(&msg, kRfc5769SampleRequest);
618 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
619 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
620 kStunTransactionIdLength);
621
622 const StunByteStringAttribute* software =
623 msg.GetByteString(STUN_ATTR_SOFTWARE);
624 ASSERT_TRUE(software != NULL);
625 EXPECT_EQ(kRfc5769SampleMsgClientSoftware, software->GetString());
626
627 const StunByteStringAttribute* username =
628 msg.GetByteString(STUN_ATTR_USERNAME);
629 ASSERT_TRUE(username != NULL);
630 EXPECT_EQ(kRfc5769SampleMsgUsername, username->GetString());
631
632 // Actual M-I value checked in a later test.
633 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
634
635 // Fingerprint checked in a later test, but double-check the value here.
Yves Gerey665174f2018-06-19 15:03:05 +0200636 const StunUInt32Attribute* fingerprint = msg.GetUInt32(STUN_ATTR_FINGERPRINT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000637 ASSERT_TRUE(fingerprint != NULL);
638 EXPECT_EQ(0xe57a3bcf, fingerprint->value());
639}
640
641// Read the RFC5389 fields from the RFC5769 sample STUN response.
642TEST_F(StunTest, ReadRfc5769ResponseMessage) {
643 StunMessage msg;
644 size_t size = ReadStunMessage(&msg, kRfc5769SampleResponse);
645 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
646 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
647 kStunTransactionIdLength);
648
649 const StunByteStringAttribute* software =
650 msg.GetByteString(STUN_ATTR_SOFTWARE);
651 ASSERT_TRUE(software != NULL);
652 EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->GetString());
653
654 const StunAddressAttribute* mapped_address =
655 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
656 ASSERT_TRUE(mapped_address != NULL);
657 EXPECT_EQ(kRfc5769SampleMsgMappedAddress, mapped_address->GetAddress());
658
659 // Actual M-I and fingerprint checked in later tests.
660 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
661 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
662}
663
664// Read the RFC5389 fields from the RFC5769 sample STUN response for IPv6.
665TEST_F(StunTest, ReadRfc5769ResponseMessageIPv6) {
666 StunMessage msg;
667 size_t size = ReadStunMessage(&msg, kRfc5769SampleResponseIPv6);
668 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
669 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
670 kStunTransactionIdLength);
671
672 const StunByteStringAttribute* software =
673 msg.GetByteString(STUN_ATTR_SOFTWARE);
674 ASSERT_TRUE(software != NULL);
675 EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->GetString());
676
677 const StunAddressAttribute* mapped_address =
678 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
679 ASSERT_TRUE(mapped_address != NULL);
680 EXPECT_EQ(kRfc5769SampleMsgIPv6MappedAddress, mapped_address->GetAddress());
681
682 // Actual M-I and fingerprint checked in later tests.
683 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
684 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
685}
686
687// Read the RFC5389 fields from the RFC5769 sample STUN response with auth.
688TEST_F(StunTest, ReadRfc5769RequestMessageLongTermAuth) {
689 StunMessage msg;
690 size_t size = ReadStunMessage(&msg, kRfc5769SampleRequestLongTermAuth);
691 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
692 CheckStunTransactionID(msg, kRfc5769SampleMsgWithAuthTransactionId,
693 kStunTransactionIdLength);
694
695 const StunByteStringAttribute* username =
696 msg.GetByteString(STUN_ATTR_USERNAME);
697 ASSERT_TRUE(username != NULL);
698 EXPECT_EQ(kRfc5769SampleMsgWithAuthUsername, username->GetString());
699
Yves Gerey665174f2018-06-19 15:03:05 +0200700 const StunByteStringAttribute* nonce = msg.GetByteString(STUN_ATTR_NONCE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000701 ASSERT_TRUE(nonce != NULL);
702 EXPECT_EQ(kRfc5769SampleMsgWithAuthNonce, nonce->GetString());
703
Yves Gerey665174f2018-06-19 15:03:05 +0200704 const StunByteStringAttribute* realm = msg.GetByteString(STUN_ATTR_REALM);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000705 ASSERT_TRUE(realm != NULL);
706 EXPECT_EQ(kRfc5769SampleMsgWithAuthRealm, realm->GetString());
707
708 // No fingerprint, actual M-I checked in later tests.
709 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
710 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) == NULL);
711}
712
713// The RFC3489 packet in this test is the same as
714// kStunMessageWithIPv4MappedAddress, but with a different value where the
715// magic cookie was.
716TEST_F(StunTest, ReadLegacyMessage) {
717 unsigned char rfc3489_packet[sizeof(kStunMessageWithIPv4MappedAddress)];
718 memcpy(rfc3489_packet, kStunMessageWithIPv4MappedAddress,
Yves Gerey665174f2018-06-19 15:03:05 +0200719 sizeof(kStunMessageWithIPv4MappedAddress));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000720 // Overwrite the magic cookie here.
721 memcpy(&rfc3489_packet[4], "ABCD", 4);
722
723 StunMessage msg;
724 size_t size = ReadStunMessage(&msg, rfc3489_packet);
725 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
726 CheckStunTransactionID(msg, &rfc3489_packet[4], kStunTransactionIdLength + 4);
727
728 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
729 rtc::IPAddress test_address(kIPv4TestAddress1);
Yves Gerey665174f2018-06-19 15:03:05 +0200730 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort4,
731 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000732}
733
734TEST_F(StunTest, SetIPv6XorAddressAttributeOwner) {
735 StunMessage msg;
736 StunMessage msg2;
737 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress);
738
739 rtc::IPAddress test_address(kIPv6TestAddress1);
740
741 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
742 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
743
744 const StunAddressAttribute* addr =
745 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200746 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort1,
747 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000748
749 // Owner with a different transaction ID.
750 msg2.SetTransactionID("ABCDABCDABCD");
751 StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL);
752 addr2.SetIP(addr->ipaddr());
753 addr2.SetPort(addr->port());
754 addr2.SetOwner(&msg2);
755 // The internal IP address shouldn't change.
756 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
757
jbauchf1f87202016-03-30 06:43:37 -0700758 rtc::ByteBufferWriter correct_buf;
759 rtc::ByteBufferWriter wrong_buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000760 EXPECT_TRUE(addr->Write(&correct_buf));
761 EXPECT_TRUE(addr2.Write(&wrong_buf));
762 // But when written out, the buffers should look different.
763 ASSERT_NE(0,
764 memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
765 // And when reading a known good value, the address should be wrong.
jbauchf1f87202016-03-30 06:43:37 -0700766 rtc::ByteBufferReader read_buf(correct_buf);
767 addr2.Read(&read_buf);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000768 ASSERT_NE(addr->ipaddr(), addr2.ipaddr());
769 addr2.SetIP(addr->ipaddr());
770 addr2.SetPort(addr->port());
771 // Try writing with no owner at all, should fail and write nothing.
772 addr2.SetOwner(NULL);
773 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
jbauchf1f87202016-03-30 06:43:37 -0700774 wrong_buf.Clear();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000775 EXPECT_FALSE(addr2.Write(&wrong_buf));
776 ASSERT_EQ(0U, wrong_buf.Length());
777}
778
779TEST_F(StunTest, SetIPv4XorAddressAttributeOwner) {
780 // Unlike the IPv6XorAddressAttributeOwner test, IPv4 XOR address attributes
781 // should _not_ be affected by a change in owner. IPv4 XOR address uses the
782 // magic cookie value which is fixed.
783 StunMessage msg;
784 StunMessage msg2;
785 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress);
786
787 rtc::IPAddress test_address(kIPv4TestAddress1);
788
789 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
790 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
791
792 const StunAddressAttribute* addr =
793 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200794 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort3,
795 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000796
797 // Owner with a different transaction ID.
798 msg2.SetTransactionID("ABCDABCDABCD");
799 StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL);
800 addr2.SetIP(addr->ipaddr());
801 addr2.SetPort(addr->port());
802 addr2.SetOwner(&msg2);
803 // The internal IP address shouldn't change.
804 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
805
jbauchf1f87202016-03-30 06:43:37 -0700806 rtc::ByteBufferWriter correct_buf;
807 rtc::ByteBufferWriter wrong_buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000808 EXPECT_TRUE(addr->Write(&correct_buf));
809 EXPECT_TRUE(addr2.Write(&wrong_buf));
810 // The same address data should be written.
811 ASSERT_EQ(0,
812 memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
813 // And an attribute should be able to un-XOR an address belonging to a message
814 // with a different transaction ID.
jbauchf1f87202016-03-30 06:43:37 -0700815 rtc::ByteBufferReader read_buf(correct_buf);
816 EXPECT_TRUE(addr2.Read(&read_buf));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000817 ASSERT_EQ(addr->ipaddr(), addr2.ipaddr());
818
819 // However, no owner is still an error, should fail and write nothing.
820 addr2.SetOwner(NULL);
821 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
jbauchf1f87202016-03-30 06:43:37 -0700822 wrong_buf.Clear();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000823 EXPECT_FALSE(addr2.Write(&wrong_buf));
824}
825
826TEST_F(StunTest, CreateIPv6AddressAttribute) {
827 rtc::IPAddress test_ip(kIPv6TestAddress2);
828
zsteinf42cc9d2017-03-27 16:17:19 -0700829 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000830 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
831 addr->SetAddress(test_addr);
832
zsteinf42cc9d2017-03-27 16:17:19 -0700833 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6, kTestMessagePort2,
834 test_ip);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000835}
836
837TEST_F(StunTest, CreateIPv4AddressAttribute) {
838 struct in_addr test_in_addr;
839 test_in_addr.s_addr = 0xBEB0B0BE;
840 rtc::IPAddress test_ip(test_in_addr);
841
zsteinf42cc9d2017-03-27 16:17:19 -0700842 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000843 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
844 addr->SetAddress(test_addr);
845
zsteinf42cc9d2017-03-27 16:17:19 -0700846 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV4, kTestMessagePort2,
847 test_ip);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000848}
849
850// Test that we don't care what order we set the parts of an address
851TEST_F(StunTest, CreateAddressInArbitraryOrder) {
zsteinf42cc9d2017-03-27 16:17:19 -0700852 auto addr = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000853 // Port first
854 addr->SetPort(kTestMessagePort1);
855 addr->SetIP(rtc::IPAddress(kIPv4TestAddress1));
856 ASSERT_EQ(kTestMessagePort1, addr->port());
857 ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr->ipaddr());
858
zsteinf42cc9d2017-03-27 16:17:19 -0700859 auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000860 // IP first
861 addr2->SetIP(rtc::IPAddress(kIPv4TestAddress1));
862 addr2->SetPort(kTestMessagePort2);
863 ASSERT_EQ(kTestMessagePort2, addr2->port());
864 ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr2->ipaddr());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000865}
866
867TEST_F(StunTest, WriteMessageWithIPv6AddressAttribute) {
868 StunMessage msg;
869 size_t size = sizeof(kStunMessageWithIPv6MappedAddress);
870
871 rtc::IPAddress test_ip(kIPv6TestAddress1);
872
873 msg.SetType(STUN_BINDING_REQUEST);
874 msg.SetTransactionID(
875 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
876 kStunTransactionIdLength));
877 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
878
zsteinf42cc9d2017-03-27 16:17:19 -0700879 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000880 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
881 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700882 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000883
884 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
885
jbauchf1f87202016-03-30 06:43:37 -0700886 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000887 EXPECT_TRUE(msg.Write(&out));
888 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6MappedAddress));
889 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700890 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000891 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700892 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000893 ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv6MappedAddress, len1));
894}
895
896TEST_F(StunTest, WriteMessageWithIPv4AddressAttribute) {
897 StunMessage msg;
898 size_t size = sizeof(kStunMessageWithIPv4MappedAddress);
899
900 rtc::IPAddress test_ip(kIPv4TestAddress1);
901
902 msg.SetType(STUN_BINDING_RESPONSE);
903 msg.SetTransactionID(
904 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
905 kStunTransactionIdLength));
906 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
907
zsteinf42cc9d2017-03-27 16:17:19 -0700908 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000909 rtc::SocketAddress test_addr(test_ip, kTestMessagePort4);
910 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700911 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000912
913 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
914
jbauchf1f87202016-03-30 06:43:37 -0700915 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000916 EXPECT_TRUE(msg.Write(&out));
917 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4MappedAddress));
918 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700919 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000920 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700921 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000922 ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv4MappedAddress, len1));
923}
924
925TEST_F(StunTest, WriteMessageWithIPv6XorAddressAttribute) {
926 StunMessage msg;
927 size_t size = sizeof(kStunMessageWithIPv6XorMappedAddress);
928
929 rtc::IPAddress test_ip(kIPv6TestAddress1);
930
931 msg.SetType(STUN_BINDING_RESPONSE);
932 msg.SetTransactionID(
933 std::string(reinterpret_cast<const char*>(kTestTransactionId2),
934 kStunTransactionIdLength));
935 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
936
zsteinf42cc9d2017-03-27 16:17:19 -0700937 auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000938 rtc::SocketAddress test_addr(test_ip, kTestMessagePort1);
939 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700940 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000941
942 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
943
jbauchf1f87202016-03-30 06:43:37 -0700944 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000945 EXPECT_TRUE(msg.Write(&out));
946 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6XorMappedAddress));
947 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700948 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000949 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700950 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000951 ASSERT_EQ(0,
952 memcmp(bytes.c_str(), kStunMessageWithIPv6XorMappedAddress, len1));
953}
954
955TEST_F(StunTest, WriteMessageWithIPv4XoreAddressAttribute) {
956 StunMessage msg;
957 size_t size = sizeof(kStunMessageWithIPv4XorMappedAddress);
958
959 rtc::IPAddress test_ip(kIPv4TestAddress1);
960
961 msg.SetType(STUN_BINDING_RESPONSE);
962 msg.SetTransactionID(
963 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
964 kStunTransactionIdLength));
965 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
966
zsteinf42cc9d2017-03-27 16:17:19 -0700967 auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000968 rtc::SocketAddress test_addr(test_ip, kTestMessagePort3);
969 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700970 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000971
972 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
973
jbauchf1f87202016-03-30 06:43:37 -0700974 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000975 EXPECT_TRUE(msg.Write(&out));
976 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4XorMappedAddress));
977 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700978 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000979 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700980 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000981 ASSERT_EQ(0,
982 memcmp(bytes.c_str(), kStunMessageWithIPv4XorMappedAddress, len1));
983}
984
985TEST_F(StunTest, ReadByteStringAttribute) {
986 StunMessage msg;
987 size_t size = ReadStunMessage(&msg, kStunMessageWithByteStringAttribute);
988
989 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
990 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
991 const StunByteStringAttribute* username =
992 msg.GetByteString(STUN_ATTR_USERNAME);
993 ASSERT_TRUE(username != NULL);
994 EXPECT_EQ(kTestUserName1, username->GetString());
995}
996
997TEST_F(StunTest, ReadPaddedByteStringAttribute) {
998 StunMessage msg;
Yves Gerey665174f2018-06-19 15:03:05 +0200999 size_t size =
1000 ReadStunMessage(&msg, kStunMessageWithPaddedByteStringAttribute);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001001 ASSERT_NE(0U, size);
1002 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1003 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
1004 const StunByteStringAttribute* username =
1005 msg.GetByteString(STUN_ATTR_USERNAME);
1006 ASSERT_TRUE(username != NULL);
1007 EXPECT_EQ(kTestUserName2, username->GetString());
1008}
1009
1010TEST_F(StunTest, ReadErrorCodeAttribute) {
1011 StunMessage msg;
1012 size_t size = ReadStunMessage(&msg, kStunMessageWithErrorAttribute);
1013
1014 CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, size);
1015 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
1016 const StunErrorCodeAttribute* errorcode = msg.GetErrorCode();
1017 ASSERT_TRUE(errorcode != NULL);
1018 EXPECT_EQ(kTestErrorClass, errorcode->eclass());
1019 EXPECT_EQ(kTestErrorNumber, errorcode->number());
1020 EXPECT_EQ(kTestErrorReason, errorcode->reason());
1021 EXPECT_EQ(kTestErrorCode, errorcode->code());
deadbeef996fc6b2017-04-26 09:21:22 -07001022 EXPECT_EQ(kTestErrorCode, msg.GetErrorCodeValue());
1023}
1024
1025// Test that GetErrorCodeValue returns STUN_ERROR_GLOBAL_FAILURE if the message
1026// in question doesn't have an error code attribute, rather than crashing.
1027TEST_F(StunTest, GetErrorCodeValueWithNoErrorAttribute) {
1028 StunMessage msg;
1029 ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
1030 EXPECT_EQ(STUN_ERROR_GLOBAL_FAILURE, msg.GetErrorCodeValue());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001031}
1032
1033TEST_F(StunTest, ReadMessageWithAUInt16ListAttribute) {
1034 StunMessage msg;
1035 size_t size = ReadStunMessage(&msg, kStunMessageWithUInt16ListAttribute);
1036 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1037 const StunUInt16ListAttribute* types = msg.GetUnknownAttributes();
1038 ASSERT_TRUE(types != NULL);
1039 EXPECT_EQ(3U, types->Size());
1040 EXPECT_EQ(0x1U, types->GetType(0));
1041 EXPECT_EQ(0x1000U, types->GetType(1));
1042 EXPECT_EQ(0xAB0CU, types->GetType(2));
1043}
1044
1045TEST_F(StunTest, ReadMessageWithAnUnknownAttribute) {
1046 StunMessage msg;
1047 size_t size = ReadStunMessage(&msg, kStunMessageWithUnknownAttribute);
1048 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1049
1050 // Parsing should have succeeded and there should be a USERNAME attribute
1051 const StunByteStringAttribute* username =
1052 msg.GetByteString(STUN_ATTR_USERNAME);
1053 ASSERT_TRUE(username != NULL);
1054 EXPECT_EQ(kTestUserName2, username->GetString());
1055}
1056
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001057TEST_F(StunTest, ReadMessageWithOriginAttribute) {
1058 StunMessage msg;
1059 size_t size = ReadStunMessage(&msg, kStunMessageWithOriginAttribute);
1060 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
Yves Gerey665174f2018-06-19 15:03:05 +02001061 const StunByteStringAttribute* origin = msg.GetByteString(STUN_ATTR_ORIGIN);
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001062 ASSERT_TRUE(origin != NULL);
1063 EXPECT_EQ(kTestOrigin, origin->GetString());
1064}
1065
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001066TEST_F(StunTest, WriteMessageWithAnErrorCodeAttribute) {
1067 StunMessage msg;
1068 size_t size = sizeof(kStunMessageWithErrorAttribute);
1069
1070 msg.SetType(STUN_BINDING_ERROR_RESPONSE);
1071 msg.SetTransactionID(
1072 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
1073 kStunTransactionIdLength));
1074 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
zsteinf42cc9d2017-03-27 16:17:19 -07001075 auto errorcode = StunAttribute::CreateErrorCode();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001076 errorcode->SetCode(kTestErrorCode);
1077 errorcode->SetReason(kTestErrorReason);
zsteinf42cc9d2017-03-27 16:17:19 -07001078 msg.AddAttribute(std::move(errorcode));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001079 CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, (size - 20));
1080
jbauchf1f87202016-03-30 06:43:37 -07001081 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001082 EXPECT_TRUE(msg.Write(&out));
1083 ASSERT_EQ(size, out.Length());
1084 // No padding.
1085 ASSERT_EQ(0, memcmp(out.Data(), kStunMessageWithErrorAttribute, size));
1086}
1087
1088TEST_F(StunTest, WriteMessageWithAUInt16ListAttribute) {
1089 StunMessage msg;
1090 size_t size = sizeof(kStunMessageWithUInt16ListAttribute);
1091
1092 msg.SetType(STUN_BINDING_REQUEST);
1093 msg.SetTransactionID(
1094 std::string(reinterpret_cast<const char*>(kTestTransactionId2),
1095 kStunTransactionIdLength));
1096 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
zsteinf42cc9d2017-03-27 16:17:19 -07001097 auto list = StunAttribute::CreateUnknownAttributes();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001098 list->AddType(0x1U);
1099 list->AddType(0x1000U);
1100 list->AddType(0xAB0CU);
zsteinf42cc9d2017-03-27 16:17:19 -07001101 msg.AddAttribute(std::move(list));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001102 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
1103
jbauchf1f87202016-03-30 06:43:37 -07001104 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001105 EXPECT_TRUE(msg.Write(&out));
1106 ASSERT_EQ(size, out.Length());
1107 // Check everything up to the padding.
1108 ASSERT_EQ(0,
1109 memcmp(out.Data(), kStunMessageWithUInt16ListAttribute, size - 2));
1110}
1111
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001112TEST_F(StunTest, WriteMessageWithOriginAttribute) {
1113 StunMessage msg;
1114 size_t size = sizeof(kStunMessageWithOriginAttribute);
1115
1116 msg.SetType(STUN_BINDING_REQUEST);
1117 msg.SetTransactionID(
1118 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
1119 kStunTransactionIdLength));
zsteinf42cc9d2017-03-27 16:17:19 -07001120 auto origin =
Karl Wiberg918f50c2018-07-05 11:40:33 +02001121 absl::make_unique<StunByteStringAttribute>(STUN_ATTR_ORIGIN, kTestOrigin);
zsteinf42cc9d2017-03-27 16:17:19 -07001122 msg.AddAttribute(std::move(origin));
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001123
jbauchf1f87202016-03-30 06:43:37 -07001124 rtc::ByteBufferWriter out;
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001125 EXPECT_TRUE(msg.Write(&out));
1126 ASSERT_EQ(size, out.Length());
1127 // Check everything up to the padding
1128 ASSERT_EQ(0, memcmp(out.Data(), kStunMessageWithOriginAttribute, size - 2));
1129}
1130
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001131// Test that we fail to read messages with invalid lengths.
1132void CheckFailureToRead(const unsigned char* testcase, size_t length) {
1133 StunMessage msg;
1134 const char* input = reinterpret_cast<const char*>(testcase);
jbauchf1f87202016-03-30 06:43:37 -07001135 rtc::ByteBufferReader buf(input, length);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001136 ASSERT_FALSE(msg.Read(&buf));
1137}
1138
1139TEST_F(StunTest, FailToReadInvalidMessages) {
1140 CheckFailureToRead(kStunMessageWithZeroLength,
1141 kRealLengthOfInvalidLengthTestCases);
1142 CheckFailureToRead(kStunMessageWithSmallLength,
1143 kRealLengthOfInvalidLengthTestCases);
1144 CheckFailureToRead(kStunMessageWithExcessLength,
1145 kRealLengthOfInvalidLengthTestCases);
1146}
1147
1148// Test that we properly fail to read a non-STUN message.
1149TEST_F(StunTest, FailToReadRtcpPacket) {
1150 CheckFailureToRead(kRtcpPacket, sizeof(kRtcpPacket));
1151}
1152
1153// Check our STUN message validation code against the RFC5769 test messages.
1154TEST_F(StunTest, ValidateMessageIntegrity) {
1155 // Try the messages from RFC 5769.
1156 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1157 reinterpret_cast<const char*>(kRfc5769SampleRequest),
Yves Gerey665174f2018-06-19 15:03:05 +02001158 sizeof(kRfc5769SampleRequest), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001159 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1160 reinterpret_cast<const char*>(kRfc5769SampleRequest),
Yves Gerey665174f2018-06-19 15:03:05 +02001161 sizeof(kRfc5769SampleRequest), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001162
1163 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1164 reinterpret_cast<const char*>(kRfc5769SampleResponse),
Yves Gerey665174f2018-06-19 15:03:05 +02001165 sizeof(kRfc5769SampleResponse), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001166 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1167 reinterpret_cast<const char*>(kRfc5769SampleResponse),
Yves Gerey665174f2018-06-19 15:03:05 +02001168 sizeof(kRfc5769SampleResponse), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001169
1170 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1171 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
Yves Gerey665174f2018-06-19 15:03:05 +02001172 sizeof(kRfc5769SampleResponseIPv6), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001173 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1174 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
Yves Gerey665174f2018-06-19 15:03:05 +02001175 sizeof(kRfc5769SampleResponseIPv6), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001176
1177 // We first need to compute the key for the long-term authentication HMAC.
1178 std::string key;
1179 ComputeStunCredentialHash(kRfc5769SampleMsgWithAuthUsername,
Yves Gerey665174f2018-06-19 15:03:05 +02001180 kRfc5769SampleMsgWithAuthRealm,
1181 kRfc5769SampleMsgWithAuthPassword, &key);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001182 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1183 reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth),
1184 sizeof(kRfc5769SampleRequestLongTermAuth), key));
1185 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1186 reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth),
Yves Gerey665174f2018-06-19 15:03:05 +02001187 sizeof(kRfc5769SampleRequestLongTermAuth), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001188
1189 // Try some edge cases.
1190 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1191 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
Yves Gerey665174f2018-06-19 15:03:05 +02001192 sizeof(kStunMessageWithZeroLength), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001193 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1194 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
Yves Gerey665174f2018-06-19 15:03:05 +02001195 sizeof(kStunMessageWithExcessLength), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001196 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1197 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
Yves Gerey665174f2018-06-19 15:03:05 +02001198 sizeof(kStunMessageWithSmallLength), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001199
katrielc1a206102016-06-20 05:13:16 -07001200 // Again, but with the lengths matching what is claimed in the headers.
1201 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1202 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1203 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithZeroLength[2]),
1204 kRfc5769SampleMsgPassword));
1205 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1206 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1207 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithExcessLength[2]),
1208 kRfc5769SampleMsgPassword));
1209 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1210 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1211 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithSmallLength[2]),
1212 kRfc5769SampleMsgPassword));
1213
1214 // Check that a too-short HMAC doesn't cause buffer overflow.
1215 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1216 reinterpret_cast<const char*>(kStunMessageWithBadHmacAtEnd),
Yves Gerey665174f2018-06-19 15:03:05 +02001217 sizeof(kStunMessageWithBadHmacAtEnd), kRfc5769SampleMsgPassword));
katrielc1a206102016-06-20 05:13:16 -07001218
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001219 // Test that munging a single bit anywhere in the message causes the
1220 // message-integrity check to fail, unless it is after the M-I attribute.
1221 char buf[sizeof(kRfc5769SampleRequest)];
1222 memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest));
1223 for (size_t i = 0; i < sizeof(buf); ++i) {
1224 buf[i] ^= 0x01;
1225 if (i > 0)
1226 buf[i - 1] ^= 0x01;
Yves Gerey665174f2018-06-19 15:03:05 +02001227 EXPECT_EQ(i >= sizeof(buf) - 8,
1228 StunMessage::ValidateMessageIntegrity(buf, sizeof(buf),
1229 kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001230 }
1231}
1232
1233// Validate that we generate correct MESSAGE-INTEGRITY attributes.
1234// Note the use of IceMessage instead of StunMessage; this is necessary because
1235// the RFC5769 test messages used include attributes not found in basic STUN.
1236TEST_F(StunTest, AddMessageIntegrity) {
1237 IceMessage msg;
jbauchf1f87202016-03-30 06:43:37 -07001238 rtc::ByteBufferReader buf(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001239 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1240 sizeof(kRfc5769SampleRequestWithoutMI));
1241 EXPECT_TRUE(msg.Read(&buf));
1242 EXPECT_TRUE(msg.AddMessageIntegrity(kRfc5769SampleMsgPassword));
1243 const StunByteStringAttribute* mi_attr =
1244 msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
1245 EXPECT_EQ(20U, mi_attr->length());
Yves Gerey665174f2018-06-19 15:03:05 +02001246 EXPECT_EQ(
1247 0, memcmp(mi_attr->bytes(), kCalculatedHmac1, sizeof(kCalculatedHmac1)));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001248
jbauchf1f87202016-03-30 06:43:37 -07001249 rtc::ByteBufferWriter buf1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001250 EXPECT_TRUE(msg.Write(&buf1));
1251 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
Yves Gerey665174f2018-06-19 15:03:05 +02001252 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(),
1253 kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001254
1255 IceMessage msg2;
jbauchf1f87202016-03-30 06:43:37 -07001256 rtc::ByteBufferReader buf2(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001257 reinterpret_cast<const char*>(kRfc5769SampleResponseWithoutMI),
1258 sizeof(kRfc5769SampleResponseWithoutMI));
1259 EXPECT_TRUE(msg2.Read(&buf2));
1260 EXPECT_TRUE(msg2.AddMessageIntegrity(kRfc5769SampleMsgPassword));
1261 const StunByteStringAttribute* mi_attr2 =
1262 msg2.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
1263 EXPECT_EQ(20U, mi_attr2->length());
1264 EXPECT_EQ(
1265 0, memcmp(mi_attr2->bytes(), kCalculatedHmac2, sizeof(kCalculatedHmac2)));
1266
jbauchf1f87202016-03-30 06:43:37 -07001267 rtc::ByteBufferWriter buf3;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001268 EXPECT_TRUE(msg2.Write(&buf3));
1269 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
Yves Gerey665174f2018-06-19 15:03:05 +02001270 reinterpret_cast<const char*>(buf3.Data()), buf3.Length(),
1271 kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001272}
1273
1274// Check our STUN message validation code against the RFC5769 test messages.
1275TEST_F(StunTest, ValidateFingerprint) {
1276 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1277 reinterpret_cast<const char*>(kRfc5769SampleRequest),
1278 sizeof(kRfc5769SampleRequest)));
1279 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1280 reinterpret_cast<const char*>(kRfc5769SampleResponse),
1281 sizeof(kRfc5769SampleResponse)));
1282 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1283 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
1284 sizeof(kRfc5769SampleResponseIPv6)));
1285
1286 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1287 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1288 sizeof(kStunMessageWithZeroLength)));
1289 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1290 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1291 sizeof(kStunMessageWithExcessLength)));
1292 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1293 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1294 sizeof(kStunMessageWithSmallLength)));
1295
1296 // Test that munging a single bit anywhere in the message causes the
1297 // fingerprint check to fail.
1298 char buf[sizeof(kRfc5769SampleRequest)];
1299 memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest));
1300 for (size_t i = 0; i < sizeof(buf); ++i) {
1301 buf[i] ^= 0x01;
1302 if (i > 0)
1303 buf[i - 1] ^= 0x01;
1304 EXPECT_FALSE(StunMessage::ValidateFingerprint(buf, sizeof(buf)));
1305 }
1306 // Put them all back to normal and the check should pass again.
1307 buf[sizeof(buf) - 1] ^= 0x01;
1308 EXPECT_TRUE(StunMessage::ValidateFingerprint(buf, sizeof(buf)));
1309}
1310
1311TEST_F(StunTest, AddFingerprint) {
1312 IceMessage msg;
jbauchf1f87202016-03-30 06:43:37 -07001313 rtc::ByteBufferReader buf(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001314 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1315 sizeof(kRfc5769SampleRequestWithoutMI));
1316 EXPECT_TRUE(msg.Read(&buf));
1317 EXPECT_TRUE(msg.AddFingerprint());
1318
jbauchf1f87202016-03-30 06:43:37 -07001319 rtc::ByteBufferWriter buf1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001320 EXPECT_TRUE(msg.Write(&buf1));
1321 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1322 reinterpret_cast<const char*>(buf1.Data()), buf1.Length()));
1323}
1324
1325// Sample "GTURN" relay message.
Yves Gerey665174f2018-06-19 15:03:05 +02001326// clang-format off
1327// clang formatting doesn't respect inline comments.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001328static const unsigned char kRelayMessage[] = {
1329 0x00, 0x01, 0x00, 88, // message header
1330 0x21, 0x12, 0xA4, 0x42, // magic cookie
1331 '0', '1', '2', '3', // transaction id
1332 '4', '5', '6', '7',
1333 '8', '9', 'a', 'b',
1334 0x00, 0x01, 0x00, 8, // mapped address
1335 0x00, 0x01, 0x00, 13,
1336 0x00, 0x00, 0x00, 17,
1337 0x00, 0x06, 0x00, 12, // username
1338 'a', 'b', 'c', 'd',
1339 'e', 'f', 'g', 'h',
1340 'i', 'j', 'k', 'l',
1341 0x00, 0x0d, 0x00, 4, // lifetime
1342 0x00, 0x00, 0x00, 11,
1343 0x00, 0x0f, 0x00, 4, // magic cookie
1344 0x72, 0xc6, 0x4b, 0xc6,
1345 0x00, 0x10, 0x00, 4, // bandwidth
1346 0x00, 0x00, 0x00, 6,
1347 0x00, 0x11, 0x00, 8, // destination address
1348 0x00, 0x01, 0x00, 13,
1349 0x00, 0x00, 0x00, 17,
1350 0x00, 0x12, 0x00, 8, // source address 2
1351 0x00, 0x01, 0x00, 13,
1352 0x00, 0x00, 0x00, 17,
1353 0x00, 0x13, 0x00, 7, // data
1354 'a', 'b', 'c', 'd',
1355 'e', 'f', 'g', 0 // DATA must be padded per rfc5766.
1356};
Yves Gerey665174f2018-06-19 15:03:05 +02001357// clang-format on
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001358
1359// Test that we can read the GTURN-specific fields.
1360TEST_F(StunTest, ReadRelayMessage) {
1361 RelayMessage msg, msg2;
1362
1363 const char* input = reinterpret_cast<const char*>(kRelayMessage);
1364 size_t size = sizeof(kRelayMessage);
jbauchf1f87202016-03-30 06:43:37 -07001365 rtc::ByteBufferReader buf(input, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001366 EXPECT_TRUE(msg.Read(&buf));
1367
1368 EXPECT_EQ(STUN_BINDING_REQUEST, msg.type());
1369 EXPECT_EQ(size - 20, msg.length());
1370 EXPECT_EQ("0123456789ab", msg.transaction_id());
1371
1372 msg2.SetType(STUN_BINDING_REQUEST);
1373 msg2.SetTransactionID("0123456789ab");
1374
1375 in_addr legacy_in_addr;
1376 legacy_in_addr.s_addr = htonl(17U);
1377 rtc::IPAddress legacy_ip(legacy_in_addr);
1378
1379 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
1380 ASSERT_TRUE(addr != NULL);
1381 EXPECT_EQ(1, addr->family());
1382 EXPECT_EQ(13, addr->port());
1383 EXPECT_EQ(legacy_ip, addr->ipaddr());
1384
zsteinf42cc9d2017-03-27 16:17:19 -07001385 auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001386 addr2->SetPort(13);
1387 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001388 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001389
1390 const StunByteStringAttribute* bytes = msg.GetByteString(STUN_ATTR_USERNAME);
1391 ASSERT_TRUE(bytes != NULL);
1392 EXPECT_EQ(12U, bytes->length());
1393 EXPECT_EQ("abcdefghijkl", bytes->GetString());
1394
zsteinf42cc9d2017-03-27 16:17:19 -07001395 auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001396 bytes2->CopyBytes("abcdefghijkl");
zsteinf42cc9d2017-03-27 16:17:19 -07001397 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001398
1399 const StunUInt32Attribute* uval = msg.GetUInt32(STUN_ATTR_LIFETIME);
1400 ASSERT_TRUE(uval != NULL);
1401 EXPECT_EQ(11U, uval->value());
1402
zsteinf42cc9d2017-03-27 16:17:19 -07001403 auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001404 uval2->SetValue(11);
zsteinf42cc9d2017-03-27 16:17:19 -07001405 msg2.AddAttribute(std::move(uval2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001406
1407 bytes = msg.GetByteString(STUN_ATTR_MAGIC_COOKIE);
1408 ASSERT_TRUE(bytes != NULL);
1409 EXPECT_EQ(4U, bytes->length());
Yves Gerey665174f2018-06-19 15:03:05 +02001410 EXPECT_EQ(0, memcmp(bytes->bytes(), TURN_MAGIC_COOKIE_VALUE,
1411 sizeof(TURN_MAGIC_COOKIE_VALUE)));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001412
1413 bytes2 = StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
1414 bytes2->CopyBytes(reinterpret_cast<const char*>(TURN_MAGIC_COOKIE_VALUE),
1415 sizeof(TURN_MAGIC_COOKIE_VALUE));
zsteinf42cc9d2017-03-27 16:17:19 -07001416 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001417
1418 uval = msg.GetUInt32(STUN_ATTR_BANDWIDTH);
1419 ASSERT_TRUE(uval != NULL);
1420 EXPECT_EQ(6U, uval->value());
1421
1422 uval2 = StunAttribute::CreateUInt32(STUN_ATTR_BANDWIDTH);
1423 uval2->SetValue(6);
zsteinf42cc9d2017-03-27 16:17:19 -07001424 msg2.AddAttribute(std::move(uval2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001425
1426 addr = msg.GetAddress(STUN_ATTR_DESTINATION_ADDRESS);
1427 ASSERT_TRUE(addr != NULL);
1428 EXPECT_EQ(1, addr->family());
1429 EXPECT_EQ(13, addr->port());
1430 EXPECT_EQ(legacy_ip, addr->ipaddr());
1431
1432 addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
1433 addr2->SetPort(13);
1434 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001435 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001436
1437 addr = msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2);
1438 ASSERT_TRUE(addr != NULL);
1439 EXPECT_EQ(1, addr->family());
1440 EXPECT_EQ(13, addr->port());
1441 EXPECT_EQ(legacy_ip, addr->ipaddr());
1442
1443 addr2 = StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2);
1444 addr2->SetPort(13);
1445 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001446 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001447
1448 bytes = msg.GetByteString(STUN_ATTR_DATA);
1449 ASSERT_TRUE(bytes != NULL);
1450 EXPECT_EQ(7U, bytes->length());
1451 EXPECT_EQ("abcdefg", bytes->GetString());
1452
1453 bytes2 = StunAttribute::CreateByteString(STUN_ATTR_DATA);
1454 bytes2->CopyBytes("abcdefg");
zsteinf42cc9d2017-03-27 16:17:19 -07001455 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001456
jbauchf1f87202016-03-30 06:43:37 -07001457 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001458 EXPECT_TRUE(msg.Write(&out));
1459 EXPECT_EQ(size, out.Length());
1460 size_t len1 = out.Length();
jbauchf1f87202016-03-30 06:43:37 -07001461 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001462 std::string outstring;
jbauchf1f87202016-03-30 06:43:37 -07001463 read_buf.ReadString(&outstring, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001464 EXPECT_EQ(0, memcmp(outstring.c_str(), input, len1));
1465
jbauchf1f87202016-03-30 06:43:37 -07001466 rtc::ByteBufferWriter out2;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001467 EXPECT_TRUE(msg2.Write(&out2));
1468 EXPECT_EQ(size, out2.Length());
1469 size_t len2 = out2.Length();
jbauchf1f87202016-03-30 06:43:37 -07001470 rtc::ByteBufferReader read_buf2(out2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001471 std::string outstring2;
jbauchf1f87202016-03-30 06:43:37 -07001472 read_buf2.ReadString(&outstring2, len2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001473 EXPECT_EQ(0, memcmp(outstring2.c_str(), input, len2));
1474}
1475
Jonas Oreland202994c2017-12-18 12:10:43 +01001476// Test that we can remove attribute from a message.
1477TEST_F(StunTest, RemoveAttribute) {
1478 StunMessage msg;
1479
1480 // Removing something that does exist should return nullptr.
1481 EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr);
1482
1483 {
1484 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1485 attr->CopyBytes("kes", sizeof("kes"));
1486 msg.AddAttribute(std::move(attr));
1487 }
1488
1489 size_t len = msg.length();
1490 {
1491 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1492 ASSERT_NE(attr, nullptr);
1493 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1494 EXPECT_STREQ("kes",
1495 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1496 EXPECT_LT(msg.length(), len);
1497 }
1498
1499 // Now add same attribute type twice.
1500 {
1501 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1502 attr->CopyBytes("kes", sizeof("kes"));
1503 msg.AddAttribute(std::move(attr));
1504 }
1505
1506 {
1507 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1508 attr->CopyBytes("kenta", sizeof("kenta"));
1509 msg.AddAttribute(std::move(attr));
1510 }
1511
1512 // Remove should remove the last added occurrence.
1513 {
1514 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1515 ASSERT_NE(attr, nullptr);
1516 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1517 EXPECT_STREQ("kenta",
1518 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1519 }
1520
1521 // Remove should remove the last added occurrence.
1522 {
1523 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1524 ASSERT_NE(attr, nullptr);
1525 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1526 EXPECT_STREQ("kes",
1527 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1528 }
1529
1530 // Removing something that does exist should return nullptr.
1531 EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr);
1532}
1533
1534// Test CopyStunAttribute
1535TEST_F(StunTest, CopyAttribute) {
1536 rtc::ByteBufferWriter buf;
Yves Gerey665174f2018-06-19 15:03:05 +02001537 rtc::ByteBufferWriter* buffer_ptrs[] = {&buf, nullptr};
Jonas Oreland202994c2017-12-18 12:10:43 +01001538 // Test both with and without supplied ByteBufferWriter.
1539 for (auto buffer_ptr : buffer_ptrs) {
Yves Gerey665174f2018-06-19 15:03:05 +02001540 { // Test StunByteStringAttribute.
Jonas Oreland202994c2017-12-18 12:10:43 +01001541 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1542 attr->CopyBytes("kes", sizeof("kes"));
1543
1544 auto copy = CopyStunAttribute(*attr.get(), buffer_ptr);
1545 ASSERT_EQ(copy->value_type(), STUN_VALUE_BYTE_STRING);
1546 EXPECT_STREQ("kes",
1547 static_cast<StunByteStringAttribute*>(copy.get())->bytes());
1548 }
1549
Yves Gerey665174f2018-06-19 15:03:05 +02001550 { // Test StunAddressAttribute.
Jonas Oreland202994c2017-12-18 12:10:43 +01001551 rtc::IPAddress test_ip(kIPv6TestAddress2);
1552 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
1553 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
1554 addr->SetAddress(test_addr);
Yves Gerey665174f2018-06-19 15:03:05 +02001555 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6,
1556 kTestMessagePort2, test_ip);
Jonas Oreland202994c2017-12-18 12:10:43 +01001557
1558 auto copy = CopyStunAttribute(*addr.get(), buffer_ptr);
1559 ASSERT_EQ(copy->value_type(), STUN_VALUE_ADDRESS);
1560 CheckStunAddressAttribute(static_cast<StunAddressAttribute*>(copy.get()),
1561 STUN_ADDRESS_IPV6, kTestMessagePort2, test_ip);
1562 }
1563 }
1564}
1565
Zach Steinff71a492018-12-07 11:25:12 -08001566TEST_F(StunTest, ReduceTransactionIdIsHostOrderIndependent) {
1567 std::string transaction_id = "abcdefghijkl";
1568 StunMessage message;
1569 ASSERT_TRUE(message.SetTransactionID(transaction_id));
1570 uint32_t reduced_transaction_id = message.reduced_transaction_id();
1571 EXPECT_EQ(reduced_transaction_id, 1835954016u);
1572}
1573
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001574} // namespace cricket