blob: 38f29bbff81f81bba7acdf6f8d85217afc621075 [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
11#include <string>
12
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "p2p/base/stun.h"
14#include "rtc_base/arraysize.h"
15#include "rtc_base/bytebuffer.h"
16#include "rtc_base/gunit.h"
17#include "rtc_base/logging.h"
18#include "rtc_base/messagedigest.h"
19#include "rtc_base/ptr_util.h"
20#include "rtc_base/socketaddress.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000021
22namespace cricket {
23
24class StunTest : public ::testing::Test {
25 protected:
26 void CheckStunHeader(const StunMessage& msg, StunMessageType expected_type,
27 size_t expected_length) {
28 ASSERT_EQ(expected_type, msg.type());
29 ASSERT_EQ(expected_length, msg.length());
30 }
31
32 void CheckStunTransactionID(const StunMessage& msg,
33 const unsigned char* expectedID, size_t length) {
34 ASSERT_EQ(length, msg.transaction_id().size());
35 ASSERT_EQ(length == kStunTransactionIdLength + 4, msg.IsLegacy());
36 ASSERT_EQ(length == kStunTransactionIdLength, !msg.IsLegacy());
37 ASSERT_EQ(0, memcmp(msg.transaction_id().c_str(), expectedID, length));
38 }
39
40 void CheckStunAddressAttribute(const StunAddressAttribute* addr,
41 StunAddressFamily expected_family,
42 int expected_port,
43 rtc::IPAddress expected_address) {
44 ASSERT_EQ(expected_family, addr->family());
45 ASSERT_EQ(expected_port, addr->port());
46
47 if (addr->family() == STUN_ADDRESS_IPV4) {
48 in_addr v4_address = expected_address.ipv4_address();
49 in_addr stun_address = addr->ipaddr().ipv4_address();
50 ASSERT_EQ(0, memcmp(&v4_address, &stun_address, sizeof(stun_address)));
51 } else if (addr->family() == STUN_ADDRESS_IPV6) {
52 in6_addr v6_address = expected_address.ipv6_address();
53 in6_addr stun_address = addr->ipaddr().ipv6_address();
54 ASSERT_EQ(0, memcmp(&v6_address, &stun_address, sizeof(stun_address)));
55 } else {
56 ASSERT_TRUE(addr->family() == STUN_ADDRESS_IPV6 ||
57 addr->family() == STUN_ADDRESS_IPV4);
58 }
59 }
60
61 size_t ReadStunMessageTestCase(StunMessage* msg,
62 const unsigned char* testcase,
63 size_t size) {
64 const char* input = reinterpret_cast<const char*>(testcase);
jbauchf1f87202016-03-30 06:43:37 -070065 rtc::ByteBufferReader buf(input, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000066 if (msg->Read(&buf)) {
67 // Returns the size the stun message should report itself as being
68 return (size - 20);
69 } else {
70 return 0;
71 }
72 }
73};
74
75
76// Sample STUN packets with various attributes
77// Gathered by wiresharking pjproject's pjnath test programs
78// pjproject available at www.pjsip.org
79
80static const unsigned char kStunMessageWithIPv6MappedAddress[] = {
81 0x00, 0x01, 0x00, 0x18, // message header
82 0x21, 0x12, 0xa4, 0x42, // transaction id
83 0x29, 0x1f, 0xcd, 0x7c,
84 0xba, 0x58, 0xab, 0xd7,
85 0xf2, 0x41, 0x01, 0x00,
86 0x00, 0x01, 0x00, 0x14, // Address type (mapped), length
87 0x00, 0x02, 0xb8, 0x81, // family (IPv6), port
88 0x24, 0x01, 0xfa, 0x00, // an IPv6 address
89 0x00, 0x04, 0x10, 0x00,
90 0xbe, 0x30, 0x5b, 0xff,
91 0xfe, 0xe5, 0x00, 0xc3
92};
93
94static const unsigned char kStunMessageWithIPv4MappedAddress[] = {
95 0x01, 0x01, 0x00, 0x0c, // binding response, length 12
96 0x21, 0x12, 0xa4, 0x42, // magic cookie
97 0x29, 0x1f, 0xcd, 0x7c, // transaction ID
98 0xba, 0x58, 0xab, 0xd7,
99 0xf2, 0x41, 0x01, 0x00,
100 0x00, 0x01, 0x00, 0x08, // Mapped, 8 byte length
101 0x00, 0x01, 0x9d, 0xfc, // AF_INET, unxor-ed port
102 0xac, 0x17, 0x44, 0xe6 // IPv4 address
103};
104
105// Test XOR-mapped IP addresses:
106static const unsigned char kStunMessageWithIPv6XorMappedAddress[] = {
107 0x01, 0x01, 0x00, 0x18, // message header (binding response)
108 0x21, 0x12, 0xa4, 0x42, // magic cookie (rfc5389)
109 0xe3, 0xa9, 0x46, 0xe1, // transaction ID
110 0x7c, 0x00, 0xc2, 0x62,
111 0x54, 0x08, 0x01, 0x00,
112 0x00, 0x20, 0x00, 0x14, // Address Type (XOR), length
113 0x00, 0x02, 0xcb, 0x5b, // family, XOR-ed port
114 0x05, 0x13, 0x5e, 0x42, // XOR-ed IPv6 address
115 0xe3, 0xad, 0x56, 0xe1,
116 0xc2, 0x30, 0x99, 0x9d,
117 0xaa, 0xed, 0x01, 0xc3
118};
119
120static const unsigned char kStunMessageWithIPv4XorMappedAddress[] = {
121 0x01, 0x01, 0x00, 0x0c, // message header (binding response)
122 0x21, 0x12, 0xa4, 0x42, // magic cookie
123 0x29, 0x1f, 0xcd, 0x7c, // transaction ID
124 0xba, 0x58, 0xab, 0xd7,
125 0xf2, 0x41, 0x01, 0x00,
126 0x00, 0x20, 0x00, 0x08, // address type (xor), length
127 0x00, 0x01, 0xfc, 0xb5, // family (AF_INET), XOR-ed port
128 0x8d, 0x05, 0xe0, 0xa4 // IPv4 address
129};
130
131// ByteString Attribute (username)
132static const unsigned char kStunMessageWithByteStringAttribute[] = {
133 0x00, 0x01, 0x00, 0x0c,
134 0x21, 0x12, 0xa4, 0x42,
135 0xe3, 0xa9, 0x46, 0xe1,
136 0x7c, 0x00, 0xc2, 0x62,
137 0x54, 0x08, 0x01, 0x00,
138 0x00, 0x06, 0x00, 0x08, // username attribute (length 8)
139 0x61, 0x62, 0x63, 0x64, // abcdefgh
140 0x65, 0x66, 0x67, 0x68
141};
142
143// Message with an unknown but comprehensible optional attribute.
144// Parsing should succeed despite this unknown attribute.
145static const unsigned char kStunMessageWithUnknownAttribute[] = {
146 0x00, 0x01, 0x00, 0x14,
147 0x21, 0x12, 0xa4, 0x42,
148 0xe3, 0xa9, 0x46, 0xe1,
149 0x7c, 0x00, 0xc2, 0x62,
150 0x54, 0x08, 0x01, 0x00,
151 0x00, 0xaa, 0x00, 0x07, // Unknown attribute, length 7 (needs padding!)
152 0x61, 0x62, 0x63, 0x64, // abcdefg + padding
153 0x65, 0x66, 0x67, 0x00,
154 0x00, 0x06, 0x00, 0x03, // Followed by a known attribute we can
155 0x61, 0x62, 0x63, 0x00 // check for (username of length 3)
156};
157
158// ByteString Attribute (username) with padding byte
159static const unsigned char kStunMessageWithPaddedByteStringAttribute[] = {
160 0x00, 0x01, 0x00, 0x08,
161 0x21, 0x12, 0xa4, 0x42,
162 0xe3, 0xa9, 0x46, 0xe1,
163 0x7c, 0x00, 0xc2, 0x62,
164 0x54, 0x08, 0x01, 0x00,
165 0x00, 0x06, 0x00, 0x03, // username attribute (length 3)
166 0x61, 0x62, 0x63, 0xcc // abc
167};
168
Peter Boström0c4e06b2015-10-07 12:23:21 +0200169// Message with an Unknown Attributes (uint16_t list) attribute.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000170static const unsigned char kStunMessageWithUInt16ListAttribute[] = {
171 0x00, 0x01, 0x00, 0x0c,
172 0x21, 0x12, 0xa4, 0x42,
173 0xe3, 0xa9, 0x46, 0xe1,
174 0x7c, 0x00, 0xc2, 0x62,
175 0x54, 0x08, 0x01, 0x00,
176 0x00, 0x0a, 0x00, 0x06, // username attribute (length 6)
177 0x00, 0x01, 0x10, 0x00, // three attributes plus padding
178 0xAB, 0xCU, 0xBE, 0xEF
179};
180
181// Error response message (unauthorized)
182static const unsigned char kStunMessageWithErrorAttribute[] = {
183 0x01, 0x11, 0x00, 0x14,
184 0x21, 0x12, 0xa4, 0x42,
185 0x29, 0x1f, 0xcd, 0x7c,
186 0xba, 0x58, 0xab, 0xd7,
187 0xf2, 0x41, 0x01, 0x00,
188 0x00, 0x09, 0x00, 0x10,
189 0x00, 0x00, 0x04, 0x01,
190 0x55, 0x6e, 0x61, 0x75,
191 0x74, 0x68, 0x6f, 0x72,
192 0x69, 0x7a, 0x65, 0x64
193};
194
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000195static const unsigned char kStunMessageWithOriginAttribute[] = {
196 0x00, 0x01, 0x00, 0x18, // message header (binding request), length 24
197 0x21, 0x12, 0xA4, 0x42, // magic cookie
198 0x29, 0x1f, 0xcd, 0x7c, // transaction id
199 0xba, 0x58, 0xab, 0xd7,
200 0xf2, 0x41, 0x01, 0x00,
201 0x80, 0x2f, 0x00, 0x12, // origin attribute (length 18)
202 0x68, 0x74, 0x74, 0x70, // http://example.com
203 0x3A, 0x2F, 0x2F, 0x65,
204 0x78, 0x61, 0x6d, 0x70,
205 0x6c, 0x65, 0x2e, 0x63,
206 0x6f, 0x6d, 0x00, 0x00,
207};
208
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000209// Sample messages with an invalid length Field
210
211// The actual length in bytes of the invalid messages (including STUN header)
212static const int kRealLengthOfInvalidLengthTestCases = 32;
213
214static const unsigned char kStunMessageWithZeroLength[] = {
215 0x00, 0x01, 0x00, 0x00, // length of 0 (last 2 bytes)
216 0x21, 0x12, 0xA4, 0x42, // magic cookie
217 '0', '1', '2', '3', // transaction id
218 '4', '5', '6', '7',
219 '8', '9', 'a', 'b',
220 0x00, 0x20, 0x00, 0x08, // xor mapped address
221 0x00, 0x01, 0x21, 0x1F,
222 0x21, 0x12, 0xA4, 0x53,
223};
224
225static const unsigned char kStunMessageWithExcessLength[] = {
226 0x00, 0x01, 0x00, 0x55, // length of 85
227 0x21, 0x12, 0xA4, 0x42, // magic cookie
228 '0', '1', '2', '3', // transaction id
229 '4', '5', '6', '7',
230 '8', '9', 'a', 'b',
231 0x00, 0x20, 0x00, 0x08, // xor mapped address
232 0x00, 0x01, 0x21, 0x1F,
233 0x21, 0x12, 0xA4, 0x53,
234};
235
236static const unsigned char kStunMessageWithSmallLength[] = {
237 0x00, 0x01, 0x00, 0x03, // length of 3
238 0x21, 0x12, 0xA4, 0x42, // magic cookie
239 '0', '1', '2', '3', // transaction id
240 '4', '5', '6', '7',
241 '8', '9', 'a', 'b',
242 0x00, 0x20, 0x00, 0x08, // xor mapped address
243 0x00, 0x01, 0x21, 0x1F,
244 0x21, 0x12, 0xA4, 0x53,
245};
246
katrielc1a206102016-06-20 05:13:16 -0700247static const unsigned char kStunMessageWithBadHmacAtEnd[] = {
248 0x00, 0x01, 0x00, 0x14, // message length exactly 20
249 0x21, 0x12, 0xA4, 0x42, // magic cookie
250 '0', '1', '2', '3', // transaction ID
251 '4', '5', '6', '7',
252 '8', '9', 'a', 'b',
253 0x00, 0x08, 0x00, 0x14, // type=STUN_ATTR_MESSAGE_INTEGRITY, length=20
254 '0', '0', '0', '0', // We lied, there are only 16 bytes of HMAC.
255 '0', '0', '0', '0',
256 '0', '0', '0', '0',
257 '0', '0', '0', '0',
258};
259
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000260// RTCP packet, for testing we correctly ignore non stun packet types.
261// V=2, P=false, RC=0, Type=200, Len=6, Sender-SSRC=85, etc
262static const unsigned char kRtcpPacket[] = {
263 0x80, 0xc8, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55,
264 0xce, 0xa5, 0x18, 0x3a, 0x39, 0xcc, 0x7d, 0x09,
265 0x23, 0xed, 0x19, 0x07, 0x00, 0x00, 0x01, 0x56,
266 0x00, 0x03, 0x73, 0x50,
267};
268
269// RFC5769 Test Vectors
270// Software name (request): "STUN test client" (without quotes)
271// Software name (response): "test vector" (without quotes)
272// Username: "evtj:h6vY" (without quotes)
273// Password: "VOkJxbRl1RmTxUk/WvJxBt" (without quotes)
274static const unsigned char kRfc5769SampleMsgTransactionId[] = {
275 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae
276};
277static const char kRfc5769SampleMsgClientSoftware[] = "STUN test client";
278static const char kRfc5769SampleMsgServerSoftware[] = "test vector";
279static const char kRfc5769SampleMsgUsername[] = "evtj:h6vY";
280static const char kRfc5769SampleMsgPassword[] = "VOkJxbRl1RmTxUk/WvJxBt";
281static const rtc::SocketAddress kRfc5769SampleMsgMappedAddress(
282 "192.0.2.1", 32853);
283static const rtc::SocketAddress kRfc5769SampleMsgIPv6MappedAddress(
284 "2001:db8:1234:5678:11:2233:4455:6677", 32853);
285
286static const unsigned char kRfc5769SampleMsgWithAuthTransactionId[] = {
287 0x78, 0xad, 0x34, 0x33, 0xc6, 0xad, 0x72, 0xc0, 0x29, 0xda, 0x41, 0x2e
288};
289static const char kRfc5769SampleMsgWithAuthUsername[] =
290 "\xe3\x83\x9e\xe3\x83\x88\xe3\x83\xaa\xe3\x83\x83\xe3\x82\xaf\xe3\x82\xb9";
291static const char kRfc5769SampleMsgWithAuthPassword[] = "TheMatrIX";
292static const char kRfc5769SampleMsgWithAuthNonce[] =
293 "f//499k954d6OL34oL9FSTvy64sA";
294static const char kRfc5769SampleMsgWithAuthRealm[] = "example.org";
295
296// 2.1. Sample Request
297static const unsigned char kRfc5769SampleRequest[] = {
298 0x00, 0x01, 0x00, 0x58, // Request type and message length
299 0x21, 0x12, 0xa4, 0x42, // Magic cookie
300 0xb7, 0xe7, 0xa7, 0x01, // }
301 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
302 0xfa, 0x87, 0xdf, 0xae, // }
303 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
304 0x53, 0x54, 0x55, 0x4e, // }
305 0x20, 0x74, 0x65, 0x73, // } User-agent...
306 0x74, 0x20, 0x63, 0x6c, // } ...name
307 0x69, 0x65, 0x6e, 0x74, // }
308 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
309 0x6e, 0x00, 0x01, 0xff, // ICE priority value
310 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
311 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
312 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
313 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
314 0x65, 0x76, 0x74, 0x6a, // }
315 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
316 0x59, 0x20, 0x20, 0x20, // }
317 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
318 0x9a, 0xea, 0xa7, 0x0c, // }
319 0xbf, 0xd8, 0xcb, 0x56, // }
320 0x78, 0x1e, 0xf2, 0xb5, // } HMAC-SHA1 fingerprint
321 0xb2, 0xd3, 0xf2, 0x49, // }
322 0xc1, 0xb5, 0x71, 0xa2, // }
323 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
324 0xe5, 0x7a, 0x3b, 0xcf // CRC32 fingerprint
325};
326
327// 2.2. Sample IPv4 Response
328static const unsigned char kRfc5769SampleResponse[] = {
329 0x01, 0x01, 0x00, 0x3c, // Response type and message length
330 0x21, 0x12, 0xa4, 0x42, // Magic cookie
331 0xb7, 0xe7, 0xa7, 0x01, // }
332 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
333 0xfa, 0x87, 0xdf, 0xae, // }
334 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
335 0x74, 0x65, 0x73, 0x74, // }
336 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
337 0x74, 0x6f, 0x72, 0x20, // }
338 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
339 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port
340 0xe1, 0x12, 0xa6, 0x43, // Xor'd mapped IPv4 address
341 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
342 0x2b, 0x91, 0xf5, 0x99, // }
343 0xfd, 0x9e, 0x90, 0xc3, // }
344 0x8c, 0x74, 0x89, 0xf9, // } HMAC-SHA1 fingerprint
345 0x2a, 0xf9, 0xba, 0x53, // }
346 0xf0, 0x6b, 0xe7, 0xd7, // }
347 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
348 0xc0, 0x7d, 0x4c, 0x96 // CRC32 fingerprint
349};
350
351// 2.3. Sample IPv6 Response
352static const unsigned char kRfc5769SampleResponseIPv6[] = {
353 0x01, 0x01, 0x00, 0x48, // Response type and message length
354 0x21, 0x12, 0xa4, 0x42, // Magic cookie
355 0xb7, 0xe7, 0xa7, 0x01, // }
356 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
357 0xfa, 0x87, 0xdf, 0xae, // }
358 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
359 0x74, 0x65, 0x73, 0x74, // }
360 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
361 0x74, 0x6f, 0x72, 0x20, // }
362 0x00, 0x20, 0x00, 0x14, // XOR-MAPPED-ADDRESS attribute header
363 0x00, 0x02, 0xa1, 0x47, // Address family (IPv6) and xor'd mapped port.
364 0x01, 0x13, 0xa9, 0xfa, // }
365 0xa5, 0xd3, 0xf1, 0x79, // } Xor'd mapped IPv6 address
366 0xbc, 0x25, 0xf4, 0xb5, // }
367 0xbe, 0xd2, 0xb9, 0xd9, // }
368 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
369 0xa3, 0x82, 0x95, 0x4e, // }
370 0x4b, 0xe6, 0x7b, 0xf1, // }
371 0x17, 0x84, 0xc9, 0x7c, // } HMAC-SHA1 fingerprint
372 0x82, 0x92, 0xc2, 0x75, // }
373 0xbf, 0xe3, 0xed, 0x41, // }
374 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
375 0xc8, 0xfb, 0x0b, 0x4c // CRC32 fingerprint
376};
377
378// 2.4. Sample Request with Long-Term Authentication
379static const unsigned char kRfc5769SampleRequestLongTermAuth[] = {
380 0x00, 0x01, 0x00, 0x60, // Request type and message length
381 0x21, 0x12, 0xa4, 0x42, // Magic cookie
382 0x78, 0xad, 0x34, 0x33, // }
383 0xc6, 0xad, 0x72, 0xc0, // } Transaction ID
384 0x29, 0xda, 0x41, 0x2e, // }
385 0x00, 0x06, 0x00, 0x12, // USERNAME attribute header
386 0xe3, 0x83, 0x9e, 0xe3, // }
387 0x83, 0x88, 0xe3, 0x83, // }
388 0xaa, 0xe3, 0x83, 0x83, // } Username value (18 bytes) and padding (2 bytes)
389 0xe3, 0x82, 0xaf, 0xe3, // }
390 0x82, 0xb9, 0x00, 0x00, // }
391 0x00, 0x15, 0x00, 0x1c, // NONCE attribute header
392 0x66, 0x2f, 0x2f, 0x34, // }
393 0x39, 0x39, 0x6b, 0x39, // }
394 0x35, 0x34, 0x64, 0x36, // }
395 0x4f, 0x4c, 0x33, 0x34, // } Nonce value
396 0x6f, 0x4c, 0x39, 0x46, // }
397 0x53, 0x54, 0x76, 0x79, // }
398 0x36, 0x34, 0x73, 0x41, // }
399 0x00, 0x14, 0x00, 0x0b, // REALM attribute header
400 0x65, 0x78, 0x61, 0x6d, // }
401 0x70, 0x6c, 0x65, 0x2e, // } Realm value (11 bytes) and padding (1 byte)
402 0x6f, 0x72, 0x67, 0x00, // }
403 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
404 0xf6, 0x70, 0x24, 0x65, // }
405 0x6d, 0xd6, 0x4a, 0x3e, // }
406 0x02, 0xb8, 0xe0, 0x71, // } HMAC-SHA1 fingerprint
407 0x2e, 0x85, 0xc9, 0xa2, // }
408 0x8c, 0xa8, 0x96, 0x66 // }
409};
410
411// Length parameter is changed to 0x38 from 0x58.
412// AddMessageIntegrity will add MI information and update the length param
413// accordingly.
414static const unsigned char kRfc5769SampleRequestWithoutMI[] = {
415 0x00, 0x01, 0x00, 0x38, // Request type and message length
416 0x21, 0x12, 0xa4, 0x42, // Magic cookie
417 0xb7, 0xe7, 0xa7, 0x01, // }
418 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
419 0xfa, 0x87, 0xdf, 0xae, // }
420 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
421 0x53, 0x54, 0x55, 0x4e, // }
422 0x20, 0x74, 0x65, 0x73, // } User-agent...
423 0x74, 0x20, 0x63, 0x6c, // } ...name
424 0x69, 0x65, 0x6e, 0x74, // }
425 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
426 0x6e, 0x00, 0x01, 0xff, // ICE priority value
427 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
428 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
429 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
430 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
431 0x65, 0x76, 0x74, 0x6a, // }
432 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
433 0x59, 0x20, 0x20, 0x20 // }
434};
435
436// This HMAC differs from the RFC 5769 SampleRequest message. This differs
437// because spec uses 0x20 for the padding where as our implementation uses 0.
438static const unsigned char kCalculatedHmac1[] = {
439 0x79, 0x07, 0xc2, 0xd2, // }
440 0xed, 0xbf, 0xea, 0x48, // }
441 0x0e, 0x4c, 0x76, 0xd8, // } HMAC-SHA1 fingerprint
442 0x29, 0x62, 0xd5, 0xc3, // }
443 0x74, 0x2a, 0xf9, 0xe3 // }
444};
445
446// Length parameter is changed to 0x1c from 0x3c.
447// AddMessageIntegrity will add MI information and update the length param
448// accordingly.
449static const unsigned char kRfc5769SampleResponseWithoutMI[] = {
450 0x01, 0x01, 0x00, 0x1c, // Response 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, 0x0b, // SOFTWARE attribute header
456 0x74, 0x65, 0x73, 0x74, // }
457 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
458 0x74, 0x6f, 0x72, 0x20, // }
459 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
460 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port
461 0xe1, 0x12, 0xa6, 0x43 // Xor'd mapped IPv4 address
462};
463
464// This HMAC differs from the RFC 5769 SampleResponse message. This differs
465// because spec uses 0x20 for the padding where as our implementation uses 0.
466static const unsigned char kCalculatedHmac2[] = {
467 0x5d, 0x6b, 0x58, 0xbe, // }
468 0xad, 0x94, 0xe0, 0x7e, // }
469 0xef, 0x0d, 0xfc, 0x12, // } HMAC-SHA1 fingerprint
470 0x82, 0xa2, 0xbd, 0x08, // }
471 0x43, 0x14, 0x10, 0x28 // }
472};
473
474// A transaction ID without the 'magic cookie' portion
475// pjnat's test programs use this transaction ID a lot.
476const unsigned char kTestTransactionId1[] = { 0x029, 0x01f, 0x0cd, 0x07c,
477 0x0ba, 0x058, 0x0ab, 0x0d7,
478 0x0f2, 0x041, 0x001, 0x000 };
479
480// They use this one sometimes too.
481const unsigned char kTestTransactionId2[] = { 0x0e3, 0x0a9, 0x046, 0x0e1,
482 0x07c, 0x000, 0x0c2, 0x062,
483 0x054, 0x008, 0x001, 0x000 };
484
485const in6_addr kIPv6TestAddress1 = { { { 0x24, 0x01, 0xfa, 0x00,
486 0x00, 0x04, 0x10, 0x00,
487 0xbe, 0x30, 0x5b, 0xff,
488 0xfe, 0xe5, 0x00, 0xc3 } } };
489const in6_addr kIPv6TestAddress2 = { { { 0x24, 0x01, 0xfa, 0x00,
490 0x00, 0x04, 0x10, 0x12,
491 0x06, 0x0c, 0xce, 0xff,
492 0xfe, 0x1f, 0x61, 0xa4 } } };
493
494#ifdef WEBRTC_POSIX
495const in_addr kIPv4TestAddress1 = { 0xe64417ac };
496#elif defined WEBRTC_WIN
497// Windows in_addr has a union with a uchar[] array first.
ehmaldonadoda8dcfb2017-01-04 07:11:23 -0800498const in_addr kIPv4TestAddress1 = { { { 0x0ac, 0x017, 0x044, 0x0e6 } } };
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000499#endif
500const char kTestUserName1[] = "abcdefgh";
501const char kTestUserName2[] = "abc";
502const char kTestErrorReason[] = "Unauthorized";
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000503const char kTestOrigin[] = "http://example.com";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000504const int kTestErrorClass = 4;
505const int kTestErrorNumber = 1;
506const int kTestErrorCode = 401;
507
508const int kTestMessagePort1 = 59977;
509const int kTestMessagePort2 = 47233;
510const int kTestMessagePort3 = 56743;
511const int kTestMessagePort4 = 40444;
512
513#define ReadStunMessage(X, Y) ReadStunMessageTestCase(X, Y, sizeof(Y));
514
515// Test that the GetStun*Type and IsStun*Type methods work as expected.
516TEST_F(StunTest, MessageTypes) {
517 EXPECT_EQ(STUN_BINDING_RESPONSE,
518 GetStunSuccessResponseType(STUN_BINDING_REQUEST));
519 EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE,
520 GetStunErrorResponseType(STUN_BINDING_REQUEST));
521 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_INDICATION));
522 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_RESPONSE));
523 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_ERROR_RESPONSE));
524 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_INDICATION));
525 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_RESPONSE));
526 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_ERROR_RESPONSE));
527
528 int types[] = {
529 STUN_BINDING_REQUEST, STUN_BINDING_INDICATION,
530 STUN_BINDING_RESPONSE, STUN_BINDING_ERROR_RESPONSE
531 };
tfarina5237aaf2015-11-10 23:44:30 -0800532 for (size_t i = 0; i < arraysize(types); ++i) {
533 EXPECT_EQ(i == 0U, IsStunRequestType(types[i]));
534 EXPECT_EQ(i == 1U, IsStunIndicationType(types[i]));
535 EXPECT_EQ(i == 2U, IsStunSuccessResponseType(types[i]));
536 EXPECT_EQ(i == 3U, IsStunErrorResponseType(types[i]));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000537 EXPECT_EQ(1, types[i] & 0xFEEF);
538 }
539}
540
541TEST_F(StunTest, ReadMessageWithIPv4AddressAttribute) {
542 StunMessage msg;
543 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4MappedAddress);
544 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
545 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
546
547 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
548 rtc::IPAddress test_address(kIPv4TestAddress1);
549 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4,
550 kTestMessagePort4, test_address);
551}
552
553TEST_F(StunTest, ReadMessageWithIPv4XorAddressAttribute) {
554 StunMessage msg;
555 StunMessage msg2;
556 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress);
557 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
558 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
559
560 const StunAddressAttribute* addr =
561 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
562 rtc::IPAddress test_address(kIPv4TestAddress1);
563 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4,
564 kTestMessagePort3, test_address);
565}
566
567TEST_F(StunTest, ReadMessageWithIPv6AddressAttribute) {
568 StunMessage msg;
569 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
570 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
571 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
572
573 rtc::IPAddress test_address(kIPv6TestAddress1);
574
575 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
576 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6,
577 kTestMessagePort2, test_address);
578}
579
580TEST_F(StunTest, ReadMessageWithInvalidAddressAttribute) {
581 StunMessage msg;
582 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
583 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
584 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
585
586 rtc::IPAddress test_address(kIPv6TestAddress1);
587
588 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
589 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6,
590 kTestMessagePort2, test_address);
591}
592
593TEST_F(StunTest, ReadMessageWithIPv6XorAddressAttribute) {
594 StunMessage msg;
595 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress);
596
597 rtc::IPAddress test_address(kIPv6TestAddress1);
598
599 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
600 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
601
602 const StunAddressAttribute* addr =
603 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
604 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6,
605 kTestMessagePort1, test_address);
606}
607
608// Read the RFC5389 fields from the RFC5769 sample STUN request.
609TEST_F(StunTest, ReadRfc5769RequestMessage) {
610 StunMessage msg;
611 size_t size = ReadStunMessage(&msg, kRfc5769SampleRequest);
612 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
613 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
614 kStunTransactionIdLength);
615
616 const StunByteStringAttribute* software =
617 msg.GetByteString(STUN_ATTR_SOFTWARE);
618 ASSERT_TRUE(software != NULL);
619 EXPECT_EQ(kRfc5769SampleMsgClientSoftware, software->GetString());
620
621 const StunByteStringAttribute* username =
622 msg.GetByteString(STUN_ATTR_USERNAME);
623 ASSERT_TRUE(username != NULL);
624 EXPECT_EQ(kRfc5769SampleMsgUsername, username->GetString());
625
626 // Actual M-I value checked in a later test.
627 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
628
629 // Fingerprint checked in a later test, but double-check the value here.
630 const StunUInt32Attribute* fingerprint =
631 msg.GetUInt32(STUN_ATTR_FINGERPRINT);
632 ASSERT_TRUE(fingerprint != NULL);
633 EXPECT_EQ(0xe57a3bcf, fingerprint->value());
634}
635
636// Read the RFC5389 fields from the RFC5769 sample STUN response.
637TEST_F(StunTest, ReadRfc5769ResponseMessage) {
638 StunMessage msg;
639 size_t size = ReadStunMessage(&msg, kRfc5769SampleResponse);
640 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
641 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
642 kStunTransactionIdLength);
643
644 const StunByteStringAttribute* software =
645 msg.GetByteString(STUN_ATTR_SOFTWARE);
646 ASSERT_TRUE(software != NULL);
647 EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->GetString());
648
649 const StunAddressAttribute* mapped_address =
650 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
651 ASSERT_TRUE(mapped_address != NULL);
652 EXPECT_EQ(kRfc5769SampleMsgMappedAddress, mapped_address->GetAddress());
653
654 // Actual M-I and fingerprint checked in later tests.
655 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
656 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
657}
658
659// Read the RFC5389 fields from the RFC5769 sample STUN response for IPv6.
660TEST_F(StunTest, ReadRfc5769ResponseMessageIPv6) {
661 StunMessage msg;
662 size_t size = ReadStunMessage(&msg, kRfc5769SampleResponseIPv6);
663 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
664 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
665 kStunTransactionIdLength);
666
667 const StunByteStringAttribute* software =
668 msg.GetByteString(STUN_ATTR_SOFTWARE);
669 ASSERT_TRUE(software != NULL);
670 EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->GetString());
671
672 const StunAddressAttribute* mapped_address =
673 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
674 ASSERT_TRUE(mapped_address != NULL);
675 EXPECT_EQ(kRfc5769SampleMsgIPv6MappedAddress, mapped_address->GetAddress());
676
677 // Actual M-I and fingerprint checked in later tests.
678 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
679 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
680}
681
682// Read the RFC5389 fields from the RFC5769 sample STUN response with auth.
683TEST_F(StunTest, ReadRfc5769RequestMessageLongTermAuth) {
684 StunMessage msg;
685 size_t size = ReadStunMessage(&msg, kRfc5769SampleRequestLongTermAuth);
686 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
687 CheckStunTransactionID(msg, kRfc5769SampleMsgWithAuthTransactionId,
688 kStunTransactionIdLength);
689
690 const StunByteStringAttribute* username =
691 msg.GetByteString(STUN_ATTR_USERNAME);
692 ASSERT_TRUE(username != NULL);
693 EXPECT_EQ(kRfc5769SampleMsgWithAuthUsername, username->GetString());
694
695 const StunByteStringAttribute* nonce =
696 msg.GetByteString(STUN_ATTR_NONCE);
697 ASSERT_TRUE(nonce != NULL);
698 EXPECT_EQ(kRfc5769SampleMsgWithAuthNonce, nonce->GetString());
699
700 const StunByteStringAttribute* realm =
701 msg.GetByteString(STUN_ATTR_REALM);
702 ASSERT_TRUE(realm != NULL);
703 EXPECT_EQ(kRfc5769SampleMsgWithAuthRealm, realm->GetString());
704
705 // No fingerprint, actual M-I checked in later tests.
706 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
707 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) == NULL);
708}
709
710// The RFC3489 packet in this test is the same as
711// kStunMessageWithIPv4MappedAddress, but with a different value where the
712// magic cookie was.
713TEST_F(StunTest, ReadLegacyMessage) {
714 unsigned char rfc3489_packet[sizeof(kStunMessageWithIPv4MappedAddress)];
715 memcpy(rfc3489_packet, kStunMessageWithIPv4MappedAddress,
716 sizeof(kStunMessageWithIPv4MappedAddress));
717 // Overwrite the magic cookie here.
718 memcpy(&rfc3489_packet[4], "ABCD", 4);
719
720 StunMessage msg;
721 size_t size = ReadStunMessage(&msg, rfc3489_packet);
722 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
723 CheckStunTransactionID(msg, &rfc3489_packet[4], kStunTransactionIdLength + 4);
724
725 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
726 rtc::IPAddress test_address(kIPv4TestAddress1);
727 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4,
728 kTestMessagePort4, test_address);
729}
730
731TEST_F(StunTest, SetIPv6XorAddressAttributeOwner) {
732 StunMessage msg;
733 StunMessage msg2;
734 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress);
735
736 rtc::IPAddress test_address(kIPv6TestAddress1);
737
738 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
739 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
740
741 const StunAddressAttribute* addr =
742 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
743 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6,
744 kTestMessagePort1, test_address);
745
746 // Owner with a different transaction ID.
747 msg2.SetTransactionID("ABCDABCDABCD");
748 StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL);
749 addr2.SetIP(addr->ipaddr());
750 addr2.SetPort(addr->port());
751 addr2.SetOwner(&msg2);
752 // The internal IP address shouldn't change.
753 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
754
jbauchf1f87202016-03-30 06:43:37 -0700755 rtc::ByteBufferWriter correct_buf;
756 rtc::ByteBufferWriter wrong_buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000757 EXPECT_TRUE(addr->Write(&correct_buf));
758 EXPECT_TRUE(addr2.Write(&wrong_buf));
759 // But when written out, the buffers should look different.
760 ASSERT_NE(0,
761 memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
762 // And when reading a known good value, the address should be wrong.
jbauchf1f87202016-03-30 06:43:37 -0700763 rtc::ByteBufferReader read_buf(correct_buf);
764 addr2.Read(&read_buf);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000765 ASSERT_NE(addr->ipaddr(), addr2.ipaddr());
766 addr2.SetIP(addr->ipaddr());
767 addr2.SetPort(addr->port());
768 // Try writing with no owner at all, should fail and write nothing.
769 addr2.SetOwner(NULL);
770 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
jbauchf1f87202016-03-30 06:43:37 -0700771 wrong_buf.Clear();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000772 EXPECT_FALSE(addr2.Write(&wrong_buf));
773 ASSERT_EQ(0U, wrong_buf.Length());
774}
775
776TEST_F(StunTest, SetIPv4XorAddressAttributeOwner) {
777 // Unlike the IPv6XorAddressAttributeOwner test, IPv4 XOR address attributes
778 // should _not_ be affected by a change in owner. IPv4 XOR address uses the
779 // magic cookie value which is fixed.
780 StunMessage msg;
781 StunMessage msg2;
782 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress);
783
784 rtc::IPAddress test_address(kIPv4TestAddress1);
785
786 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
787 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
788
789 const StunAddressAttribute* addr =
790 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
791 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4,
792 kTestMessagePort3, test_address);
793
794 // Owner with a different transaction ID.
795 msg2.SetTransactionID("ABCDABCDABCD");
796 StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL);
797 addr2.SetIP(addr->ipaddr());
798 addr2.SetPort(addr->port());
799 addr2.SetOwner(&msg2);
800 // The internal IP address shouldn't change.
801 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
802
jbauchf1f87202016-03-30 06:43:37 -0700803 rtc::ByteBufferWriter correct_buf;
804 rtc::ByteBufferWriter wrong_buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000805 EXPECT_TRUE(addr->Write(&correct_buf));
806 EXPECT_TRUE(addr2.Write(&wrong_buf));
807 // The same address data should be written.
808 ASSERT_EQ(0,
809 memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
810 // And an attribute should be able to un-XOR an address belonging to a message
811 // with a different transaction ID.
jbauchf1f87202016-03-30 06:43:37 -0700812 rtc::ByteBufferReader read_buf(correct_buf);
813 EXPECT_TRUE(addr2.Read(&read_buf));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000814 ASSERT_EQ(addr->ipaddr(), addr2.ipaddr());
815
816 // However, no owner is still an error, should fail and write nothing.
817 addr2.SetOwner(NULL);
818 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
jbauchf1f87202016-03-30 06:43:37 -0700819 wrong_buf.Clear();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000820 EXPECT_FALSE(addr2.Write(&wrong_buf));
821}
822
823TEST_F(StunTest, CreateIPv6AddressAttribute) {
824 rtc::IPAddress test_ip(kIPv6TestAddress2);
825
zsteinf42cc9d2017-03-27 16:17:19 -0700826 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000827 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
828 addr->SetAddress(test_addr);
829
zsteinf42cc9d2017-03-27 16:17:19 -0700830 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6, kTestMessagePort2,
831 test_ip);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000832}
833
834TEST_F(StunTest, CreateIPv4AddressAttribute) {
835 struct in_addr test_in_addr;
836 test_in_addr.s_addr = 0xBEB0B0BE;
837 rtc::IPAddress test_ip(test_in_addr);
838
zsteinf42cc9d2017-03-27 16:17:19 -0700839 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000840 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
841 addr->SetAddress(test_addr);
842
zsteinf42cc9d2017-03-27 16:17:19 -0700843 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV4, kTestMessagePort2,
844 test_ip);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000845}
846
847// Test that we don't care what order we set the parts of an address
848TEST_F(StunTest, CreateAddressInArbitraryOrder) {
zsteinf42cc9d2017-03-27 16:17:19 -0700849 auto addr = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000850 // Port first
851 addr->SetPort(kTestMessagePort1);
852 addr->SetIP(rtc::IPAddress(kIPv4TestAddress1));
853 ASSERT_EQ(kTestMessagePort1, addr->port());
854 ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr->ipaddr());
855
zsteinf42cc9d2017-03-27 16:17:19 -0700856 auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000857 // IP first
858 addr2->SetIP(rtc::IPAddress(kIPv4TestAddress1));
859 addr2->SetPort(kTestMessagePort2);
860 ASSERT_EQ(kTestMessagePort2, addr2->port());
861 ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr2->ipaddr());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000862}
863
864TEST_F(StunTest, WriteMessageWithIPv6AddressAttribute) {
865 StunMessage msg;
866 size_t size = sizeof(kStunMessageWithIPv6MappedAddress);
867
868 rtc::IPAddress test_ip(kIPv6TestAddress1);
869
870 msg.SetType(STUN_BINDING_REQUEST);
871 msg.SetTransactionID(
872 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
873 kStunTransactionIdLength));
874 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
875
zsteinf42cc9d2017-03-27 16:17:19 -0700876 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000877 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
878 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700879 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000880
881 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
882
jbauchf1f87202016-03-30 06:43:37 -0700883 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000884 EXPECT_TRUE(msg.Write(&out));
885 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6MappedAddress));
886 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700887 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000888 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700889 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000890 ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv6MappedAddress, len1));
891}
892
893TEST_F(StunTest, WriteMessageWithIPv4AddressAttribute) {
894 StunMessage msg;
895 size_t size = sizeof(kStunMessageWithIPv4MappedAddress);
896
897 rtc::IPAddress test_ip(kIPv4TestAddress1);
898
899 msg.SetType(STUN_BINDING_RESPONSE);
900 msg.SetTransactionID(
901 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
902 kStunTransactionIdLength));
903 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
904
zsteinf42cc9d2017-03-27 16:17:19 -0700905 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000906 rtc::SocketAddress test_addr(test_ip, kTestMessagePort4);
907 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700908 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000909
910 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
911
jbauchf1f87202016-03-30 06:43:37 -0700912 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000913 EXPECT_TRUE(msg.Write(&out));
914 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4MappedAddress));
915 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700916 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000917 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700918 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000919 ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv4MappedAddress, len1));
920}
921
922TEST_F(StunTest, WriteMessageWithIPv6XorAddressAttribute) {
923 StunMessage msg;
924 size_t size = sizeof(kStunMessageWithIPv6XorMappedAddress);
925
926 rtc::IPAddress test_ip(kIPv6TestAddress1);
927
928 msg.SetType(STUN_BINDING_RESPONSE);
929 msg.SetTransactionID(
930 std::string(reinterpret_cast<const char*>(kTestTransactionId2),
931 kStunTransactionIdLength));
932 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
933
zsteinf42cc9d2017-03-27 16:17:19 -0700934 auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000935 rtc::SocketAddress test_addr(test_ip, kTestMessagePort1);
936 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700937 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000938
939 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
940
jbauchf1f87202016-03-30 06:43:37 -0700941 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000942 EXPECT_TRUE(msg.Write(&out));
943 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6XorMappedAddress));
944 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700945 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000946 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700947 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000948 ASSERT_EQ(0,
949 memcmp(bytes.c_str(), kStunMessageWithIPv6XorMappedAddress, len1));
950}
951
952TEST_F(StunTest, WriteMessageWithIPv4XoreAddressAttribute) {
953 StunMessage msg;
954 size_t size = sizeof(kStunMessageWithIPv4XorMappedAddress);
955
956 rtc::IPAddress test_ip(kIPv4TestAddress1);
957
958 msg.SetType(STUN_BINDING_RESPONSE);
959 msg.SetTransactionID(
960 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
961 kStunTransactionIdLength));
962 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
963
zsteinf42cc9d2017-03-27 16:17:19 -0700964 auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000965 rtc::SocketAddress test_addr(test_ip, kTestMessagePort3);
966 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700967 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000968
969 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
970
jbauchf1f87202016-03-30 06:43:37 -0700971 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000972 EXPECT_TRUE(msg.Write(&out));
973 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4XorMappedAddress));
974 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700975 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000976 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700977 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000978 ASSERT_EQ(0,
979 memcmp(bytes.c_str(), kStunMessageWithIPv4XorMappedAddress, len1));
980}
981
982TEST_F(StunTest, ReadByteStringAttribute) {
983 StunMessage msg;
984 size_t size = ReadStunMessage(&msg, kStunMessageWithByteStringAttribute);
985
986 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
987 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
988 const StunByteStringAttribute* username =
989 msg.GetByteString(STUN_ATTR_USERNAME);
990 ASSERT_TRUE(username != NULL);
991 EXPECT_EQ(kTestUserName1, username->GetString());
992}
993
994TEST_F(StunTest, ReadPaddedByteStringAttribute) {
995 StunMessage msg;
996 size_t size = ReadStunMessage(&msg,
997 kStunMessageWithPaddedByteStringAttribute);
998 ASSERT_NE(0U, size);
999 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1000 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
1001 const StunByteStringAttribute* username =
1002 msg.GetByteString(STUN_ATTR_USERNAME);
1003 ASSERT_TRUE(username != NULL);
1004 EXPECT_EQ(kTestUserName2, username->GetString());
1005}
1006
1007TEST_F(StunTest, ReadErrorCodeAttribute) {
1008 StunMessage msg;
1009 size_t size = ReadStunMessage(&msg, kStunMessageWithErrorAttribute);
1010
1011 CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, size);
1012 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
1013 const StunErrorCodeAttribute* errorcode = msg.GetErrorCode();
1014 ASSERT_TRUE(errorcode != NULL);
1015 EXPECT_EQ(kTestErrorClass, errorcode->eclass());
1016 EXPECT_EQ(kTestErrorNumber, errorcode->number());
1017 EXPECT_EQ(kTestErrorReason, errorcode->reason());
1018 EXPECT_EQ(kTestErrorCode, errorcode->code());
deadbeef996fc6b2017-04-26 09:21:22 -07001019 EXPECT_EQ(kTestErrorCode, msg.GetErrorCodeValue());
1020}
1021
1022// Test that GetErrorCodeValue returns STUN_ERROR_GLOBAL_FAILURE if the message
1023// in question doesn't have an error code attribute, rather than crashing.
1024TEST_F(StunTest, GetErrorCodeValueWithNoErrorAttribute) {
1025 StunMessage msg;
1026 ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
1027 EXPECT_EQ(STUN_ERROR_GLOBAL_FAILURE, msg.GetErrorCodeValue());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001028}
1029
1030TEST_F(StunTest, ReadMessageWithAUInt16ListAttribute) {
1031 StunMessage msg;
1032 size_t size = ReadStunMessage(&msg, kStunMessageWithUInt16ListAttribute);
1033 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1034 const StunUInt16ListAttribute* types = msg.GetUnknownAttributes();
1035 ASSERT_TRUE(types != NULL);
1036 EXPECT_EQ(3U, types->Size());
1037 EXPECT_EQ(0x1U, types->GetType(0));
1038 EXPECT_EQ(0x1000U, types->GetType(1));
1039 EXPECT_EQ(0xAB0CU, types->GetType(2));
1040}
1041
1042TEST_F(StunTest, ReadMessageWithAnUnknownAttribute) {
1043 StunMessage msg;
1044 size_t size = ReadStunMessage(&msg, kStunMessageWithUnknownAttribute);
1045 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1046
1047 // Parsing should have succeeded and there should be a USERNAME attribute
1048 const StunByteStringAttribute* username =
1049 msg.GetByteString(STUN_ATTR_USERNAME);
1050 ASSERT_TRUE(username != NULL);
1051 EXPECT_EQ(kTestUserName2, username->GetString());
1052}
1053
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001054TEST_F(StunTest, ReadMessageWithOriginAttribute) {
1055 StunMessage msg;
1056 size_t size = ReadStunMessage(&msg, kStunMessageWithOriginAttribute);
1057 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1058 const StunByteStringAttribute* origin =
1059 msg.GetByteString(STUN_ATTR_ORIGIN);
1060 ASSERT_TRUE(origin != NULL);
1061 EXPECT_EQ(kTestOrigin, origin->GetString());
1062}
1063
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001064TEST_F(StunTest, WriteMessageWithAnErrorCodeAttribute) {
1065 StunMessage msg;
1066 size_t size = sizeof(kStunMessageWithErrorAttribute);
1067
1068 msg.SetType(STUN_BINDING_ERROR_RESPONSE);
1069 msg.SetTransactionID(
1070 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
1071 kStunTransactionIdLength));
1072 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
zsteinf42cc9d2017-03-27 16:17:19 -07001073 auto errorcode = StunAttribute::CreateErrorCode();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001074 errorcode->SetCode(kTestErrorCode);
1075 errorcode->SetReason(kTestErrorReason);
zsteinf42cc9d2017-03-27 16:17:19 -07001076 msg.AddAttribute(std::move(errorcode));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001077 CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, (size - 20));
1078
jbauchf1f87202016-03-30 06:43:37 -07001079 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001080 EXPECT_TRUE(msg.Write(&out));
1081 ASSERT_EQ(size, out.Length());
1082 // No padding.
1083 ASSERT_EQ(0, memcmp(out.Data(), kStunMessageWithErrorAttribute, size));
1084}
1085
1086TEST_F(StunTest, WriteMessageWithAUInt16ListAttribute) {
1087 StunMessage msg;
1088 size_t size = sizeof(kStunMessageWithUInt16ListAttribute);
1089
1090 msg.SetType(STUN_BINDING_REQUEST);
1091 msg.SetTransactionID(
1092 std::string(reinterpret_cast<const char*>(kTestTransactionId2),
1093 kStunTransactionIdLength));
1094 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
zsteinf42cc9d2017-03-27 16:17:19 -07001095 auto list = StunAttribute::CreateUnknownAttributes();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001096 list->AddType(0x1U);
1097 list->AddType(0x1000U);
1098 list->AddType(0xAB0CU);
zsteinf42cc9d2017-03-27 16:17:19 -07001099 msg.AddAttribute(std::move(list));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001100 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
1101
jbauchf1f87202016-03-30 06:43:37 -07001102 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001103 EXPECT_TRUE(msg.Write(&out));
1104 ASSERT_EQ(size, out.Length());
1105 // Check everything up to the padding.
1106 ASSERT_EQ(0,
1107 memcmp(out.Data(), kStunMessageWithUInt16ListAttribute, size - 2));
1108}
1109
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001110TEST_F(StunTest, WriteMessageWithOriginAttribute) {
1111 StunMessage msg;
1112 size_t size = sizeof(kStunMessageWithOriginAttribute);
1113
1114 msg.SetType(STUN_BINDING_REQUEST);
1115 msg.SetTransactionID(
1116 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
1117 kStunTransactionIdLength));
zsteinf42cc9d2017-03-27 16:17:19 -07001118 auto origin =
1119 rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_ORIGIN, kTestOrigin);
1120 msg.AddAttribute(std::move(origin));
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001121
jbauchf1f87202016-03-30 06:43:37 -07001122 rtc::ByteBufferWriter out;
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001123 EXPECT_TRUE(msg.Write(&out));
1124 ASSERT_EQ(size, out.Length());
1125 // Check everything up to the padding
1126 ASSERT_EQ(0, memcmp(out.Data(), kStunMessageWithOriginAttribute, size - 2));
1127}
1128
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001129// Test that we fail to read messages with invalid lengths.
1130void CheckFailureToRead(const unsigned char* testcase, size_t length) {
1131 StunMessage msg;
1132 const char* input = reinterpret_cast<const char*>(testcase);
jbauchf1f87202016-03-30 06:43:37 -07001133 rtc::ByteBufferReader buf(input, length);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001134 ASSERT_FALSE(msg.Read(&buf));
1135}
1136
1137TEST_F(StunTest, FailToReadInvalidMessages) {
1138 CheckFailureToRead(kStunMessageWithZeroLength,
1139 kRealLengthOfInvalidLengthTestCases);
1140 CheckFailureToRead(kStunMessageWithSmallLength,
1141 kRealLengthOfInvalidLengthTestCases);
1142 CheckFailureToRead(kStunMessageWithExcessLength,
1143 kRealLengthOfInvalidLengthTestCases);
1144}
1145
1146// Test that we properly fail to read a non-STUN message.
1147TEST_F(StunTest, FailToReadRtcpPacket) {
1148 CheckFailureToRead(kRtcpPacket, sizeof(kRtcpPacket));
1149}
1150
1151// Check our STUN message validation code against the RFC5769 test messages.
1152TEST_F(StunTest, ValidateMessageIntegrity) {
1153 // Try the messages from RFC 5769.
1154 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1155 reinterpret_cast<const char*>(kRfc5769SampleRequest),
1156 sizeof(kRfc5769SampleRequest),
1157 kRfc5769SampleMsgPassword));
1158 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1159 reinterpret_cast<const char*>(kRfc5769SampleRequest),
1160 sizeof(kRfc5769SampleRequest),
1161 "InvalidPassword"));
1162
1163 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1164 reinterpret_cast<const char*>(kRfc5769SampleResponse),
1165 sizeof(kRfc5769SampleResponse),
1166 kRfc5769SampleMsgPassword));
1167 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1168 reinterpret_cast<const char*>(kRfc5769SampleResponse),
1169 sizeof(kRfc5769SampleResponse),
1170 "InvalidPassword"));
1171
1172 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1173 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
1174 sizeof(kRfc5769SampleResponseIPv6),
1175 kRfc5769SampleMsgPassword));
1176 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1177 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
1178 sizeof(kRfc5769SampleResponseIPv6),
1179 "InvalidPassword"));
1180
1181 // We first need to compute the key for the long-term authentication HMAC.
1182 std::string key;
1183 ComputeStunCredentialHash(kRfc5769SampleMsgWithAuthUsername,
1184 kRfc5769SampleMsgWithAuthRealm, kRfc5769SampleMsgWithAuthPassword, &key);
1185 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1186 reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth),
1187 sizeof(kRfc5769SampleRequestLongTermAuth), key));
1188 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1189 reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth),
1190 sizeof(kRfc5769SampleRequestLongTermAuth),
1191 "InvalidPassword"));
1192
1193 // Try some edge cases.
1194 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1195 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1196 sizeof(kStunMessageWithZeroLength),
1197 kRfc5769SampleMsgPassword));
1198 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1199 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1200 sizeof(kStunMessageWithExcessLength),
1201 kRfc5769SampleMsgPassword));
1202 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1203 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1204 sizeof(kStunMessageWithSmallLength),
1205 kRfc5769SampleMsgPassword));
1206
katrielc1a206102016-06-20 05:13:16 -07001207 // Again, but with the lengths matching what is claimed in the headers.
1208 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1209 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1210 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithZeroLength[2]),
1211 kRfc5769SampleMsgPassword));
1212 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1213 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1214 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithExcessLength[2]),
1215 kRfc5769SampleMsgPassword));
1216 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1217 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1218 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithSmallLength[2]),
1219 kRfc5769SampleMsgPassword));
1220
1221 // Check that a too-short HMAC doesn't cause buffer overflow.
1222 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1223 reinterpret_cast<const char*>(kStunMessageWithBadHmacAtEnd),
1224 sizeof(kStunMessageWithBadHmacAtEnd),
1225 kRfc5769SampleMsgPassword));
1226
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001227 // Test that munging a single bit anywhere in the message causes the
1228 // message-integrity check to fail, unless it is after the M-I attribute.
1229 char buf[sizeof(kRfc5769SampleRequest)];
1230 memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest));
1231 for (size_t i = 0; i < sizeof(buf); ++i) {
1232 buf[i] ^= 0x01;
1233 if (i > 0)
1234 buf[i - 1] ^= 0x01;
1235 EXPECT_EQ(i >= sizeof(buf) - 8, StunMessage::ValidateMessageIntegrity(
1236 buf, sizeof(buf), kRfc5769SampleMsgPassword));
1237 }
1238}
1239
1240// Validate that we generate correct MESSAGE-INTEGRITY attributes.
1241// Note the use of IceMessage instead of StunMessage; this is necessary because
1242// the RFC5769 test messages used include attributes not found in basic STUN.
1243TEST_F(StunTest, AddMessageIntegrity) {
1244 IceMessage msg;
jbauchf1f87202016-03-30 06:43:37 -07001245 rtc::ByteBufferReader buf(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001246 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1247 sizeof(kRfc5769SampleRequestWithoutMI));
1248 EXPECT_TRUE(msg.Read(&buf));
1249 EXPECT_TRUE(msg.AddMessageIntegrity(kRfc5769SampleMsgPassword));
1250 const StunByteStringAttribute* mi_attr =
1251 msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
1252 EXPECT_EQ(20U, mi_attr->length());
1253 EXPECT_EQ(0, memcmp(
1254 mi_attr->bytes(), kCalculatedHmac1, sizeof(kCalculatedHmac1)));
1255
jbauchf1f87202016-03-30 06:43:37 -07001256 rtc::ByteBufferWriter buf1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001257 EXPECT_TRUE(msg.Write(&buf1));
1258 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1259 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(),
1260 kRfc5769SampleMsgPassword));
1261
1262 IceMessage msg2;
jbauchf1f87202016-03-30 06:43:37 -07001263 rtc::ByteBufferReader buf2(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001264 reinterpret_cast<const char*>(kRfc5769SampleResponseWithoutMI),
1265 sizeof(kRfc5769SampleResponseWithoutMI));
1266 EXPECT_TRUE(msg2.Read(&buf2));
1267 EXPECT_TRUE(msg2.AddMessageIntegrity(kRfc5769SampleMsgPassword));
1268 const StunByteStringAttribute* mi_attr2 =
1269 msg2.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
1270 EXPECT_EQ(20U, mi_attr2->length());
1271 EXPECT_EQ(
1272 0, memcmp(mi_attr2->bytes(), kCalculatedHmac2, sizeof(kCalculatedHmac2)));
1273
jbauchf1f87202016-03-30 06:43:37 -07001274 rtc::ByteBufferWriter buf3;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001275 EXPECT_TRUE(msg2.Write(&buf3));
1276 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1277 reinterpret_cast<const char*>(buf3.Data()), buf3.Length(),
1278 kRfc5769SampleMsgPassword));
1279}
1280
1281// Check our STUN message validation code against the RFC5769 test messages.
1282TEST_F(StunTest, ValidateFingerprint) {
1283 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1284 reinterpret_cast<const char*>(kRfc5769SampleRequest),
1285 sizeof(kRfc5769SampleRequest)));
1286 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1287 reinterpret_cast<const char*>(kRfc5769SampleResponse),
1288 sizeof(kRfc5769SampleResponse)));
1289 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1290 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
1291 sizeof(kRfc5769SampleResponseIPv6)));
1292
1293 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1294 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1295 sizeof(kStunMessageWithZeroLength)));
1296 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1297 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1298 sizeof(kStunMessageWithExcessLength)));
1299 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1300 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1301 sizeof(kStunMessageWithSmallLength)));
1302
1303 // Test that munging a single bit anywhere in the message causes the
1304 // fingerprint check to fail.
1305 char buf[sizeof(kRfc5769SampleRequest)];
1306 memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest));
1307 for (size_t i = 0; i < sizeof(buf); ++i) {
1308 buf[i] ^= 0x01;
1309 if (i > 0)
1310 buf[i - 1] ^= 0x01;
1311 EXPECT_FALSE(StunMessage::ValidateFingerprint(buf, sizeof(buf)));
1312 }
1313 // Put them all back to normal and the check should pass again.
1314 buf[sizeof(buf) - 1] ^= 0x01;
1315 EXPECT_TRUE(StunMessage::ValidateFingerprint(buf, sizeof(buf)));
1316}
1317
1318TEST_F(StunTest, AddFingerprint) {
1319 IceMessage msg;
jbauchf1f87202016-03-30 06:43:37 -07001320 rtc::ByteBufferReader buf(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001321 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1322 sizeof(kRfc5769SampleRequestWithoutMI));
1323 EXPECT_TRUE(msg.Read(&buf));
1324 EXPECT_TRUE(msg.AddFingerprint());
1325
jbauchf1f87202016-03-30 06:43:37 -07001326 rtc::ByteBufferWriter buf1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001327 EXPECT_TRUE(msg.Write(&buf1));
1328 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1329 reinterpret_cast<const char*>(buf1.Data()), buf1.Length()));
1330}
1331
1332// Sample "GTURN" relay message.
1333static const unsigned char kRelayMessage[] = {
1334 0x00, 0x01, 0x00, 88, // message header
1335 0x21, 0x12, 0xA4, 0x42, // magic cookie
1336 '0', '1', '2', '3', // transaction id
1337 '4', '5', '6', '7',
1338 '8', '9', 'a', 'b',
1339 0x00, 0x01, 0x00, 8, // mapped address
1340 0x00, 0x01, 0x00, 13,
1341 0x00, 0x00, 0x00, 17,
1342 0x00, 0x06, 0x00, 12, // username
1343 'a', 'b', 'c', 'd',
1344 'e', 'f', 'g', 'h',
1345 'i', 'j', 'k', 'l',
1346 0x00, 0x0d, 0x00, 4, // lifetime
1347 0x00, 0x00, 0x00, 11,
1348 0x00, 0x0f, 0x00, 4, // magic cookie
1349 0x72, 0xc6, 0x4b, 0xc6,
1350 0x00, 0x10, 0x00, 4, // bandwidth
1351 0x00, 0x00, 0x00, 6,
1352 0x00, 0x11, 0x00, 8, // destination address
1353 0x00, 0x01, 0x00, 13,
1354 0x00, 0x00, 0x00, 17,
1355 0x00, 0x12, 0x00, 8, // source address 2
1356 0x00, 0x01, 0x00, 13,
1357 0x00, 0x00, 0x00, 17,
1358 0x00, 0x13, 0x00, 7, // data
1359 'a', 'b', 'c', 'd',
1360 'e', 'f', 'g', 0 // DATA must be padded per rfc5766.
1361};
1362
1363// Test that we can read the GTURN-specific fields.
1364TEST_F(StunTest, ReadRelayMessage) {
1365 RelayMessage msg, msg2;
1366
1367 const char* input = reinterpret_cast<const char*>(kRelayMessage);
1368 size_t size = sizeof(kRelayMessage);
jbauchf1f87202016-03-30 06:43:37 -07001369 rtc::ByteBufferReader buf(input, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001370 EXPECT_TRUE(msg.Read(&buf));
1371
1372 EXPECT_EQ(STUN_BINDING_REQUEST, msg.type());
1373 EXPECT_EQ(size - 20, msg.length());
1374 EXPECT_EQ("0123456789ab", msg.transaction_id());
1375
1376 msg2.SetType(STUN_BINDING_REQUEST);
1377 msg2.SetTransactionID("0123456789ab");
1378
1379 in_addr legacy_in_addr;
1380 legacy_in_addr.s_addr = htonl(17U);
1381 rtc::IPAddress legacy_ip(legacy_in_addr);
1382
1383 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
1384 ASSERT_TRUE(addr != NULL);
1385 EXPECT_EQ(1, addr->family());
1386 EXPECT_EQ(13, addr->port());
1387 EXPECT_EQ(legacy_ip, addr->ipaddr());
1388
zsteinf42cc9d2017-03-27 16:17:19 -07001389 auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001390 addr2->SetPort(13);
1391 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001392 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001393
1394 const StunByteStringAttribute* bytes = msg.GetByteString(STUN_ATTR_USERNAME);
1395 ASSERT_TRUE(bytes != NULL);
1396 EXPECT_EQ(12U, bytes->length());
1397 EXPECT_EQ("abcdefghijkl", bytes->GetString());
1398
zsteinf42cc9d2017-03-27 16:17:19 -07001399 auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001400 bytes2->CopyBytes("abcdefghijkl");
zsteinf42cc9d2017-03-27 16:17:19 -07001401 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001402
1403 const StunUInt32Attribute* uval = msg.GetUInt32(STUN_ATTR_LIFETIME);
1404 ASSERT_TRUE(uval != NULL);
1405 EXPECT_EQ(11U, uval->value());
1406
zsteinf42cc9d2017-03-27 16:17:19 -07001407 auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001408 uval2->SetValue(11);
zsteinf42cc9d2017-03-27 16:17:19 -07001409 msg2.AddAttribute(std::move(uval2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001410
1411 bytes = msg.GetByteString(STUN_ATTR_MAGIC_COOKIE);
1412 ASSERT_TRUE(bytes != NULL);
1413 EXPECT_EQ(4U, bytes->length());
1414 EXPECT_EQ(0,
1415 memcmp(bytes->bytes(),
1416 TURN_MAGIC_COOKIE_VALUE,
1417 sizeof(TURN_MAGIC_COOKIE_VALUE)));
1418
1419 bytes2 = StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
1420 bytes2->CopyBytes(reinterpret_cast<const char*>(TURN_MAGIC_COOKIE_VALUE),
1421 sizeof(TURN_MAGIC_COOKIE_VALUE));
zsteinf42cc9d2017-03-27 16:17:19 -07001422 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001423
1424 uval = msg.GetUInt32(STUN_ATTR_BANDWIDTH);
1425 ASSERT_TRUE(uval != NULL);
1426 EXPECT_EQ(6U, uval->value());
1427
1428 uval2 = StunAttribute::CreateUInt32(STUN_ATTR_BANDWIDTH);
1429 uval2->SetValue(6);
zsteinf42cc9d2017-03-27 16:17:19 -07001430 msg2.AddAttribute(std::move(uval2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001431
1432 addr = msg.GetAddress(STUN_ATTR_DESTINATION_ADDRESS);
1433 ASSERT_TRUE(addr != NULL);
1434 EXPECT_EQ(1, addr->family());
1435 EXPECT_EQ(13, addr->port());
1436 EXPECT_EQ(legacy_ip, addr->ipaddr());
1437
1438 addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
1439 addr2->SetPort(13);
1440 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001441 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001442
1443 addr = msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2);
1444 ASSERT_TRUE(addr != NULL);
1445 EXPECT_EQ(1, addr->family());
1446 EXPECT_EQ(13, addr->port());
1447 EXPECT_EQ(legacy_ip, addr->ipaddr());
1448
1449 addr2 = StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2);
1450 addr2->SetPort(13);
1451 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001452 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001453
1454 bytes = msg.GetByteString(STUN_ATTR_DATA);
1455 ASSERT_TRUE(bytes != NULL);
1456 EXPECT_EQ(7U, bytes->length());
1457 EXPECT_EQ("abcdefg", bytes->GetString());
1458
1459 bytes2 = StunAttribute::CreateByteString(STUN_ATTR_DATA);
1460 bytes2->CopyBytes("abcdefg");
zsteinf42cc9d2017-03-27 16:17:19 -07001461 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001462
jbauchf1f87202016-03-30 06:43:37 -07001463 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001464 EXPECT_TRUE(msg.Write(&out));
1465 EXPECT_EQ(size, out.Length());
1466 size_t len1 = out.Length();
jbauchf1f87202016-03-30 06:43:37 -07001467 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001468 std::string outstring;
jbauchf1f87202016-03-30 06:43:37 -07001469 read_buf.ReadString(&outstring, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001470 EXPECT_EQ(0, memcmp(outstring.c_str(), input, len1));
1471
jbauchf1f87202016-03-30 06:43:37 -07001472 rtc::ByteBufferWriter out2;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001473 EXPECT_TRUE(msg2.Write(&out2));
1474 EXPECT_EQ(size, out2.Length());
1475 size_t len2 = out2.Length();
jbauchf1f87202016-03-30 06:43:37 -07001476 rtc::ByteBufferReader read_buf2(out2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001477 std::string outstring2;
jbauchf1f87202016-03-30 06:43:37 -07001478 read_buf2.ReadString(&outstring2, len2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001479 EXPECT_EQ(0, memcmp(outstring2.c_str(), input, len2));
1480}
1481
1482} // namespace cricket