blob: 5c805dc77027dc0631c3561bf822f6ca0d80b73e [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>
Steve Anton6c38cc72017-11-29 10:25:58 -080012#include <utility>
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000013
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "p2p/base/stun.h"
15#include "rtc_base/arraysize.h"
16#include "rtc_base/bytebuffer.h"
17#include "rtc_base/gunit.h"
18#include "rtc_base/logging.h"
19#include "rtc_base/messagedigest.h"
20#include "rtc_base/ptr_util.h"
21#include "rtc_base/socketaddress.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000022
23namespace cricket {
24
25class StunTest : public ::testing::Test {
26 protected:
27 void CheckStunHeader(const StunMessage& msg, StunMessageType expected_type,
28 size_t expected_length) {
29 ASSERT_EQ(expected_type, msg.type());
30 ASSERT_EQ(expected_length, msg.length());
31 }
32
33 void CheckStunTransactionID(const StunMessage& msg,
34 const unsigned char* expectedID, size_t length) {
35 ASSERT_EQ(length, msg.transaction_id().size());
36 ASSERT_EQ(length == kStunTransactionIdLength + 4, msg.IsLegacy());
37 ASSERT_EQ(length == kStunTransactionIdLength, !msg.IsLegacy());
38 ASSERT_EQ(0, memcmp(msg.transaction_id().c_str(), expectedID, length));
39 }
40
41 void CheckStunAddressAttribute(const StunAddressAttribute* addr,
42 StunAddressFamily expected_family,
43 int expected_port,
44 rtc::IPAddress expected_address) {
45 ASSERT_EQ(expected_family, addr->family());
46 ASSERT_EQ(expected_port, addr->port());
47
48 if (addr->family() == STUN_ADDRESS_IPV4) {
49 in_addr v4_address = expected_address.ipv4_address();
50 in_addr stun_address = addr->ipaddr().ipv4_address();
51 ASSERT_EQ(0, memcmp(&v4_address, &stun_address, sizeof(stun_address)));
52 } else if (addr->family() == STUN_ADDRESS_IPV6) {
53 in6_addr v6_address = expected_address.ipv6_address();
54 in6_addr stun_address = addr->ipaddr().ipv6_address();
55 ASSERT_EQ(0, memcmp(&v6_address, &stun_address, sizeof(stun_address)));
56 } else {
57 ASSERT_TRUE(addr->family() == STUN_ADDRESS_IPV6 ||
58 addr->family() == STUN_ADDRESS_IPV4);
59 }
60 }
61
62 size_t ReadStunMessageTestCase(StunMessage* msg,
63 const unsigned char* testcase,
64 size_t size) {
65 const char* input = reinterpret_cast<const char*>(testcase);
jbauchf1f87202016-03-30 06:43:37 -070066 rtc::ByteBufferReader buf(input, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000067 if (msg->Read(&buf)) {
68 // Returns the size the stun message should report itself as being
69 return (size - 20);
70 } else {
71 return 0;
72 }
73 }
74};
75
76
77// Sample STUN packets with various attributes
78// Gathered by wiresharking pjproject's pjnath test programs
79// pjproject available at www.pjsip.org
80
81static const unsigned char kStunMessageWithIPv6MappedAddress[] = {
82 0x00, 0x01, 0x00, 0x18, // message header
83 0x21, 0x12, 0xa4, 0x42, // transaction id
84 0x29, 0x1f, 0xcd, 0x7c,
85 0xba, 0x58, 0xab, 0xd7,
86 0xf2, 0x41, 0x01, 0x00,
87 0x00, 0x01, 0x00, 0x14, // Address type (mapped), length
88 0x00, 0x02, 0xb8, 0x81, // family (IPv6), port
89 0x24, 0x01, 0xfa, 0x00, // an IPv6 address
90 0x00, 0x04, 0x10, 0x00,
91 0xbe, 0x30, 0x5b, 0xff,
92 0xfe, 0xe5, 0x00, 0xc3
93};
94
95static const unsigned char kStunMessageWithIPv4MappedAddress[] = {
96 0x01, 0x01, 0x00, 0x0c, // binding response, length 12
97 0x21, 0x12, 0xa4, 0x42, // magic cookie
98 0x29, 0x1f, 0xcd, 0x7c, // transaction ID
99 0xba, 0x58, 0xab, 0xd7,
100 0xf2, 0x41, 0x01, 0x00,
101 0x00, 0x01, 0x00, 0x08, // Mapped, 8 byte length
102 0x00, 0x01, 0x9d, 0xfc, // AF_INET, unxor-ed port
103 0xac, 0x17, 0x44, 0xe6 // IPv4 address
104};
105
106// Test XOR-mapped IP addresses:
107static const unsigned char kStunMessageWithIPv6XorMappedAddress[] = {
108 0x01, 0x01, 0x00, 0x18, // message header (binding response)
109 0x21, 0x12, 0xa4, 0x42, // magic cookie (rfc5389)
110 0xe3, 0xa9, 0x46, 0xe1, // transaction ID
111 0x7c, 0x00, 0xc2, 0x62,
112 0x54, 0x08, 0x01, 0x00,
113 0x00, 0x20, 0x00, 0x14, // Address Type (XOR), length
114 0x00, 0x02, 0xcb, 0x5b, // family, XOR-ed port
115 0x05, 0x13, 0x5e, 0x42, // XOR-ed IPv6 address
116 0xe3, 0xad, 0x56, 0xe1,
117 0xc2, 0x30, 0x99, 0x9d,
118 0xaa, 0xed, 0x01, 0xc3
119};
120
121static const unsigned char kStunMessageWithIPv4XorMappedAddress[] = {
122 0x01, 0x01, 0x00, 0x0c, // message header (binding response)
123 0x21, 0x12, 0xa4, 0x42, // magic cookie
124 0x29, 0x1f, 0xcd, 0x7c, // transaction ID
125 0xba, 0x58, 0xab, 0xd7,
126 0xf2, 0x41, 0x01, 0x00,
127 0x00, 0x20, 0x00, 0x08, // address type (xor), length
128 0x00, 0x01, 0xfc, 0xb5, // family (AF_INET), XOR-ed port
129 0x8d, 0x05, 0xe0, 0xa4 // IPv4 address
130};
131
132// ByteString Attribute (username)
133static const unsigned char kStunMessageWithByteStringAttribute[] = {
134 0x00, 0x01, 0x00, 0x0c,
135 0x21, 0x12, 0xa4, 0x42,
136 0xe3, 0xa9, 0x46, 0xe1,
137 0x7c, 0x00, 0xc2, 0x62,
138 0x54, 0x08, 0x01, 0x00,
139 0x00, 0x06, 0x00, 0x08, // username attribute (length 8)
140 0x61, 0x62, 0x63, 0x64, // abcdefgh
141 0x65, 0x66, 0x67, 0x68
142};
143
144// Message with an unknown but comprehensible optional attribute.
145// Parsing should succeed despite this unknown attribute.
146static const unsigned char kStunMessageWithUnknownAttribute[] = {
147 0x00, 0x01, 0x00, 0x14,
148 0x21, 0x12, 0xa4, 0x42,
149 0xe3, 0xa9, 0x46, 0xe1,
150 0x7c, 0x00, 0xc2, 0x62,
151 0x54, 0x08, 0x01, 0x00,
152 0x00, 0xaa, 0x00, 0x07, // Unknown attribute, length 7 (needs padding!)
153 0x61, 0x62, 0x63, 0x64, // abcdefg + padding
154 0x65, 0x66, 0x67, 0x00,
155 0x00, 0x06, 0x00, 0x03, // Followed by a known attribute we can
156 0x61, 0x62, 0x63, 0x00 // check for (username of length 3)
157};
158
159// ByteString Attribute (username) with padding byte
160static const unsigned char kStunMessageWithPaddedByteStringAttribute[] = {
161 0x00, 0x01, 0x00, 0x08,
162 0x21, 0x12, 0xa4, 0x42,
163 0xe3, 0xa9, 0x46, 0xe1,
164 0x7c, 0x00, 0xc2, 0x62,
165 0x54, 0x08, 0x01, 0x00,
166 0x00, 0x06, 0x00, 0x03, // username attribute (length 3)
167 0x61, 0x62, 0x63, 0xcc // abc
168};
169
Peter Boström0c4e06b2015-10-07 12:23:21 +0200170// Message with an Unknown Attributes (uint16_t list) attribute.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000171static const unsigned char kStunMessageWithUInt16ListAttribute[] = {
172 0x00, 0x01, 0x00, 0x0c,
173 0x21, 0x12, 0xa4, 0x42,
174 0xe3, 0xa9, 0x46, 0xe1,
175 0x7c, 0x00, 0xc2, 0x62,
176 0x54, 0x08, 0x01, 0x00,
177 0x00, 0x0a, 0x00, 0x06, // username attribute (length 6)
178 0x00, 0x01, 0x10, 0x00, // three attributes plus padding
179 0xAB, 0xCU, 0xBE, 0xEF
180};
181
182// Error response message (unauthorized)
183static const unsigned char kStunMessageWithErrorAttribute[] = {
184 0x01, 0x11, 0x00, 0x14,
185 0x21, 0x12, 0xa4, 0x42,
186 0x29, 0x1f, 0xcd, 0x7c,
187 0xba, 0x58, 0xab, 0xd7,
188 0xf2, 0x41, 0x01, 0x00,
189 0x00, 0x09, 0x00, 0x10,
190 0x00, 0x00, 0x04, 0x01,
191 0x55, 0x6e, 0x61, 0x75,
192 0x74, 0x68, 0x6f, 0x72,
193 0x69, 0x7a, 0x65, 0x64
194};
195
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000196static const unsigned char kStunMessageWithOriginAttribute[] = {
197 0x00, 0x01, 0x00, 0x18, // message header (binding request), length 24
198 0x21, 0x12, 0xA4, 0x42, // magic cookie
199 0x29, 0x1f, 0xcd, 0x7c, // transaction id
200 0xba, 0x58, 0xab, 0xd7,
201 0xf2, 0x41, 0x01, 0x00,
202 0x80, 0x2f, 0x00, 0x12, // origin attribute (length 18)
203 0x68, 0x74, 0x74, 0x70, // http://example.com
204 0x3A, 0x2F, 0x2F, 0x65,
205 0x78, 0x61, 0x6d, 0x70,
206 0x6c, 0x65, 0x2e, 0x63,
207 0x6f, 0x6d, 0x00, 0x00,
208};
209
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000210// Sample messages with an invalid length Field
211
212// The actual length in bytes of the invalid messages (including STUN header)
213static const int kRealLengthOfInvalidLengthTestCases = 32;
214
215static const unsigned char kStunMessageWithZeroLength[] = {
216 0x00, 0x01, 0x00, 0x00, // length of 0 (last 2 bytes)
217 0x21, 0x12, 0xA4, 0x42, // magic cookie
218 '0', '1', '2', '3', // transaction id
219 '4', '5', '6', '7',
220 '8', '9', 'a', 'b',
221 0x00, 0x20, 0x00, 0x08, // xor mapped address
222 0x00, 0x01, 0x21, 0x1F,
223 0x21, 0x12, 0xA4, 0x53,
224};
225
226static const unsigned char kStunMessageWithExcessLength[] = {
227 0x00, 0x01, 0x00, 0x55, // length of 85
228 0x21, 0x12, 0xA4, 0x42, // magic cookie
229 '0', '1', '2', '3', // transaction id
230 '4', '5', '6', '7',
231 '8', '9', 'a', 'b',
232 0x00, 0x20, 0x00, 0x08, // xor mapped address
233 0x00, 0x01, 0x21, 0x1F,
234 0x21, 0x12, 0xA4, 0x53,
235};
236
237static const unsigned char kStunMessageWithSmallLength[] = {
238 0x00, 0x01, 0x00, 0x03, // length of 3
239 0x21, 0x12, 0xA4, 0x42, // magic cookie
240 '0', '1', '2', '3', // transaction id
241 '4', '5', '6', '7',
242 '8', '9', 'a', 'b',
243 0x00, 0x20, 0x00, 0x08, // xor mapped address
244 0x00, 0x01, 0x21, 0x1F,
245 0x21, 0x12, 0xA4, 0x53,
246};
247
katrielc1a206102016-06-20 05:13:16 -0700248static const unsigned char kStunMessageWithBadHmacAtEnd[] = {
249 0x00, 0x01, 0x00, 0x14, // message length exactly 20
250 0x21, 0x12, 0xA4, 0x42, // magic cookie
251 '0', '1', '2', '3', // transaction ID
252 '4', '5', '6', '7',
253 '8', '9', 'a', 'b',
254 0x00, 0x08, 0x00, 0x14, // type=STUN_ATTR_MESSAGE_INTEGRITY, length=20
255 '0', '0', '0', '0', // We lied, there are only 16 bytes of HMAC.
256 '0', '0', '0', '0',
257 '0', '0', '0', '0',
258 '0', '0', '0', '0',
259};
260
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000261// RTCP packet, for testing we correctly ignore non stun packet types.
262// V=2, P=false, RC=0, Type=200, Len=6, Sender-SSRC=85, etc
263static const unsigned char kRtcpPacket[] = {
264 0x80, 0xc8, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55,
265 0xce, 0xa5, 0x18, 0x3a, 0x39, 0xcc, 0x7d, 0x09,
266 0x23, 0xed, 0x19, 0x07, 0x00, 0x00, 0x01, 0x56,
267 0x00, 0x03, 0x73, 0x50,
268};
269
270// RFC5769 Test Vectors
271// Software name (request): "STUN test client" (without quotes)
272// Software name (response): "test vector" (without quotes)
273// Username: "evtj:h6vY" (without quotes)
274// Password: "VOkJxbRl1RmTxUk/WvJxBt" (without quotes)
275static const unsigned char kRfc5769SampleMsgTransactionId[] = {
276 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae
277};
278static const char kRfc5769SampleMsgClientSoftware[] = "STUN test client";
279static const char kRfc5769SampleMsgServerSoftware[] = "test vector";
280static const char kRfc5769SampleMsgUsername[] = "evtj:h6vY";
281static const char kRfc5769SampleMsgPassword[] = "VOkJxbRl1RmTxUk/WvJxBt";
282static const rtc::SocketAddress kRfc5769SampleMsgMappedAddress(
283 "192.0.2.1", 32853);
284static const rtc::SocketAddress kRfc5769SampleMsgIPv6MappedAddress(
285 "2001:db8:1234:5678:11:2233:4455:6677", 32853);
286
287static const unsigned char kRfc5769SampleMsgWithAuthTransactionId[] = {
288 0x78, 0xad, 0x34, 0x33, 0xc6, 0xad, 0x72, 0xc0, 0x29, 0xda, 0x41, 0x2e
289};
290static const char kRfc5769SampleMsgWithAuthUsername[] =
291 "\xe3\x83\x9e\xe3\x83\x88\xe3\x83\xaa\xe3\x83\x83\xe3\x82\xaf\xe3\x82\xb9";
292static const char kRfc5769SampleMsgWithAuthPassword[] = "TheMatrIX";
293static const char kRfc5769SampleMsgWithAuthNonce[] =
294 "f//499k954d6OL34oL9FSTvy64sA";
295static const char kRfc5769SampleMsgWithAuthRealm[] = "example.org";
296
297// 2.1. Sample Request
298static const unsigned char kRfc5769SampleRequest[] = {
299 0x00, 0x01, 0x00, 0x58, // Request type and message length
300 0x21, 0x12, 0xa4, 0x42, // Magic cookie
301 0xb7, 0xe7, 0xa7, 0x01, // }
302 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
303 0xfa, 0x87, 0xdf, 0xae, // }
304 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
305 0x53, 0x54, 0x55, 0x4e, // }
306 0x20, 0x74, 0x65, 0x73, // } User-agent...
307 0x74, 0x20, 0x63, 0x6c, // } ...name
308 0x69, 0x65, 0x6e, 0x74, // }
309 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
310 0x6e, 0x00, 0x01, 0xff, // ICE priority value
311 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
312 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
313 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
314 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
315 0x65, 0x76, 0x74, 0x6a, // }
316 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
317 0x59, 0x20, 0x20, 0x20, // }
318 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
319 0x9a, 0xea, 0xa7, 0x0c, // }
320 0xbf, 0xd8, 0xcb, 0x56, // }
321 0x78, 0x1e, 0xf2, 0xb5, // } HMAC-SHA1 fingerprint
322 0xb2, 0xd3, 0xf2, 0x49, // }
323 0xc1, 0xb5, 0x71, 0xa2, // }
324 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
325 0xe5, 0x7a, 0x3b, 0xcf // CRC32 fingerprint
326};
327
328// 2.2. Sample IPv4 Response
329static const unsigned char kRfc5769SampleResponse[] = {
330 0x01, 0x01, 0x00, 0x3c, // Response type and message length
331 0x21, 0x12, 0xa4, 0x42, // Magic cookie
332 0xb7, 0xe7, 0xa7, 0x01, // }
333 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
334 0xfa, 0x87, 0xdf, 0xae, // }
335 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
336 0x74, 0x65, 0x73, 0x74, // }
337 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
338 0x74, 0x6f, 0x72, 0x20, // }
339 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
340 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port
341 0xe1, 0x12, 0xa6, 0x43, // Xor'd mapped IPv4 address
342 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
343 0x2b, 0x91, 0xf5, 0x99, // }
344 0xfd, 0x9e, 0x90, 0xc3, // }
345 0x8c, 0x74, 0x89, 0xf9, // } HMAC-SHA1 fingerprint
346 0x2a, 0xf9, 0xba, 0x53, // }
347 0xf0, 0x6b, 0xe7, 0xd7, // }
348 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
349 0xc0, 0x7d, 0x4c, 0x96 // CRC32 fingerprint
350};
351
352// 2.3. Sample IPv6 Response
353static const unsigned char kRfc5769SampleResponseIPv6[] = {
354 0x01, 0x01, 0x00, 0x48, // Response type and message length
355 0x21, 0x12, 0xa4, 0x42, // Magic cookie
356 0xb7, 0xe7, 0xa7, 0x01, // }
357 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
358 0xfa, 0x87, 0xdf, 0xae, // }
359 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
360 0x74, 0x65, 0x73, 0x74, // }
361 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
362 0x74, 0x6f, 0x72, 0x20, // }
363 0x00, 0x20, 0x00, 0x14, // XOR-MAPPED-ADDRESS attribute header
364 0x00, 0x02, 0xa1, 0x47, // Address family (IPv6) and xor'd mapped port.
365 0x01, 0x13, 0xa9, 0xfa, // }
366 0xa5, 0xd3, 0xf1, 0x79, // } Xor'd mapped IPv6 address
367 0xbc, 0x25, 0xf4, 0xb5, // }
368 0xbe, 0xd2, 0xb9, 0xd9, // }
369 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
370 0xa3, 0x82, 0x95, 0x4e, // }
371 0x4b, 0xe6, 0x7b, 0xf1, // }
372 0x17, 0x84, 0xc9, 0x7c, // } HMAC-SHA1 fingerprint
373 0x82, 0x92, 0xc2, 0x75, // }
374 0xbf, 0xe3, 0xed, 0x41, // }
375 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
376 0xc8, 0xfb, 0x0b, 0x4c // CRC32 fingerprint
377};
378
379// 2.4. Sample Request with Long-Term Authentication
380static const unsigned char kRfc5769SampleRequestLongTermAuth[] = {
381 0x00, 0x01, 0x00, 0x60, // Request type and message length
382 0x21, 0x12, 0xa4, 0x42, // Magic cookie
383 0x78, 0xad, 0x34, 0x33, // }
384 0xc6, 0xad, 0x72, 0xc0, // } Transaction ID
385 0x29, 0xda, 0x41, 0x2e, // }
386 0x00, 0x06, 0x00, 0x12, // USERNAME attribute header
387 0xe3, 0x83, 0x9e, 0xe3, // }
388 0x83, 0x88, 0xe3, 0x83, // }
389 0xaa, 0xe3, 0x83, 0x83, // } Username value (18 bytes) and padding (2 bytes)
390 0xe3, 0x82, 0xaf, 0xe3, // }
391 0x82, 0xb9, 0x00, 0x00, // }
392 0x00, 0x15, 0x00, 0x1c, // NONCE attribute header
393 0x66, 0x2f, 0x2f, 0x34, // }
394 0x39, 0x39, 0x6b, 0x39, // }
395 0x35, 0x34, 0x64, 0x36, // }
396 0x4f, 0x4c, 0x33, 0x34, // } Nonce value
397 0x6f, 0x4c, 0x39, 0x46, // }
398 0x53, 0x54, 0x76, 0x79, // }
399 0x36, 0x34, 0x73, 0x41, // }
400 0x00, 0x14, 0x00, 0x0b, // REALM attribute header
401 0x65, 0x78, 0x61, 0x6d, // }
402 0x70, 0x6c, 0x65, 0x2e, // } Realm value (11 bytes) and padding (1 byte)
403 0x6f, 0x72, 0x67, 0x00, // }
404 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
405 0xf6, 0x70, 0x24, 0x65, // }
406 0x6d, 0xd6, 0x4a, 0x3e, // }
407 0x02, 0xb8, 0xe0, 0x71, // } HMAC-SHA1 fingerprint
408 0x2e, 0x85, 0xc9, 0xa2, // }
409 0x8c, 0xa8, 0x96, 0x66 // }
410};
411
412// Length parameter is changed to 0x38 from 0x58.
413// AddMessageIntegrity will add MI information and update the length param
414// accordingly.
415static const unsigned char kRfc5769SampleRequestWithoutMI[] = {
416 0x00, 0x01, 0x00, 0x38, // Request type and message length
417 0x21, 0x12, 0xa4, 0x42, // Magic cookie
418 0xb7, 0xe7, 0xa7, 0x01, // }
419 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
420 0xfa, 0x87, 0xdf, 0xae, // }
421 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
422 0x53, 0x54, 0x55, 0x4e, // }
423 0x20, 0x74, 0x65, 0x73, // } User-agent...
424 0x74, 0x20, 0x63, 0x6c, // } ...name
425 0x69, 0x65, 0x6e, 0x74, // }
426 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
427 0x6e, 0x00, 0x01, 0xff, // ICE priority value
428 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
429 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
430 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
431 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
432 0x65, 0x76, 0x74, 0x6a, // }
433 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
434 0x59, 0x20, 0x20, 0x20 // }
435};
436
437// This HMAC differs from the RFC 5769 SampleRequest message. This differs
438// because spec uses 0x20 for the padding where as our implementation uses 0.
439static const unsigned char kCalculatedHmac1[] = {
440 0x79, 0x07, 0xc2, 0xd2, // }
441 0xed, 0xbf, 0xea, 0x48, // }
442 0x0e, 0x4c, 0x76, 0xd8, // } HMAC-SHA1 fingerprint
443 0x29, 0x62, 0xd5, 0xc3, // }
444 0x74, 0x2a, 0xf9, 0xe3 // }
445};
446
447// Length parameter is changed to 0x1c from 0x3c.
448// AddMessageIntegrity will add MI information and update the length param
449// accordingly.
450static const unsigned char kRfc5769SampleResponseWithoutMI[] = {
451 0x01, 0x01, 0x00, 0x1c, // Response type and message length
452 0x21, 0x12, 0xa4, 0x42, // Magic cookie
453 0xb7, 0xe7, 0xa7, 0x01, // }
454 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
455 0xfa, 0x87, 0xdf, 0xae, // }
456 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
457 0x74, 0x65, 0x73, 0x74, // }
458 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
459 0x74, 0x6f, 0x72, 0x20, // }
460 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
461 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port
462 0xe1, 0x12, 0xa6, 0x43 // Xor'd mapped IPv4 address
463};
464
465// This HMAC differs from the RFC 5769 SampleResponse message. This differs
466// because spec uses 0x20 for the padding where as our implementation uses 0.
467static const unsigned char kCalculatedHmac2[] = {
468 0x5d, 0x6b, 0x58, 0xbe, // }
469 0xad, 0x94, 0xe0, 0x7e, // }
470 0xef, 0x0d, 0xfc, 0x12, // } HMAC-SHA1 fingerprint
471 0x82, 0xa2, 0xbd, 0x08, // }
472 0x43, 0x14, 0x10, 0x28 // }
473};
474
475// A transaction ID without the 'magic cookie' portion
476// pjnat's test programs use this transaction ID a lot.
477const unsigned char kTestTransactionId1[] = { 0x029, 0x01f, 0x0cd, 0x07c,
478 0x0ba, 0x058, 0x0ab, 0x0d7,
479 0x0f2, 0x041, 0x001, 0x000 };
480
481// They use this one sometimes too.
482const unsigned char kTestTransactionId2[] = { 0x0e3, 0x0a9, 0x046, 0x0e1,
483 0x07c, 0x000, 0x0c2, 0x062,
484 0x054, 0x008, 0x001, 0x000 };
485
486const in6_addr kIPv6TestAddress1 = { { { 0x24, 0x01, 0xfa, 0x00,
487 0x00, 0x04, 0x10, 0x00,
488 0xbe, 0x30, 0x5b, 0xff,
489 0xfe, 0xe5, 0x00, 0xc3 } } };
490const in6_addr kIPv6TestAddress2 = { { { 0x24, 0x01, 0xfa, 0x00,
491 0x00, 0x04, 0x10, 0x12,
492 0x06, 0x0c, 0xce, 0xff,
493 0xfe, 0x1f, 0x61, 0xa4 } } };
494
495#ifdef WEBRTC_POSIX
496const in_addr kIPv4TestAddress1 = { 0xe64417ac };
497#elif defined WEBRTC_WIN
498// Windows in_addr has a union with a uchar[] array first.
ehmaldonadoda8dcfb2017-01-04 07:11:23 -0800499const in_addr kIPv4TestAddress1 = { { { 0x0ac, 0x017, 0x044, 0x0e6 } } };
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000500#endif
501const char kTestUserName1[] = "abcdefgh";
502const char kTestUserName2[] = "abc";
503const char kTestErrorReason[] = "Unauthorized";
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000504const char kTestOrigin[] = "http://example.com";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000505const int kTestErrorClass = 4;
506const int kTestErrorNumber = 1;
507const int kTestErrorCode = 401;
508
509const int kTestMessagePort1 = 59977;
510const int kTestMessagePort2 = 47233;
511const int kTestMessagePort3 = 56743;
512const int kTestMessagePort4 = 40444;
513
514#define ReadStunMessage(X, Y) ReadStunMessageTestCase(X, Y, sizeof(Y));
515
516// Test that the GetStun*Type and IsStun*Type methods work as expected.
517TEST_F(StunTest, MessageTypes) {
518 EXPECT_EQ(STUN_BINDING_RESPONSE,
519 GetStunSuccessResponseType(STUN_BINDING_REQUEST));
520 EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE,
521 GetStunErrorResponseType(STUN_BINDING_REQUEST));
522 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_INDICATION));
523 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_RESPONSE));
524 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_ERROR_RESPONSE));
525 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_INDICATION));
526 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_RESPONSE));
527 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_ERROR_RESPONSE));
528
529 int types[] = {
530 STUN_BINDING_REQUEST, STUN_BINDING_INDICATION,
531 STUN_BINDING_RESPONSE, STUN_BINDING_ERROR_RESPONSE
532 };
tfarina5237aaf2015-11-10 23:44:30 -0800533 for (size_t i = 0; i < arraysize(types); ++i) {
534 EXPECT_EQ(i == 0U, IsStunRequestType(types[i]));
535 EXPECT_EQ(i == 1U, IsStunIndicationType(types[i]));
536 EXPECT_EQ(i == 2U, IsStunSuccessResponseType(types[i]));
537 EXPECT_EQ(i == 3U, IsStunErrorResponseType(types[i]));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000538 EXPECT_EQ(1, types[i] & 0xFEEF);
539 }
540}
541
542TEST_F(StunTest, ReadMessageWithIPv4AddressAttribute) {
543 StunMessage msg;
544 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4MappedAddress);
545 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
546 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
547
548 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
549 rtc::IPAddress test_address(kIPv4TestAddress1);
550 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4,
551 kTestMessagePort4, test_address);
552}
553
554TEST_F(StunTest, ReadMessageWithIPv4XorAddressAttribute) {
555 StunMessage msg;
556 StunMessage msg2;
557 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress);
558 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
559 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
560
561 const StunAddressAttribute* addr =
562 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
563 rtc::IPAddress test_address(kIPv4TestAddress1);
564 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4,
565 kTestMessagePort3, test_address);
566}
567
568TEST_F(StunTest, ReadMessageWithIPv6AddressAttribute) {
569 StunMessage msg;
570 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
571 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
572 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
573
574 rtc::IPAddress test_address(kIPv6TestAddress1);
575
576 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
577 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6,
578 kTestMessagePort2, test_address);
579}
580
581TEST_F(StunTest, ReadMessageWithInvalidAddressAttribute) {
582 StunMessage msg;
583 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
584 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
585 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
586
587 rtc::IPAddress test_address(kIPv6TestAddress1);
588
589 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
590 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6,
591 kTestMessagePort2, test_address);
592}
593
594TEST_F(StunTest, ReadMessageWithIPv6XorAddressAttribute) {
595 StunMessage msg;
596 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress);
597
598 rtc::IPAddress test_address(kIPv6TestAddress1);
599
600 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
601 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
602
603 const StunAddressAttribute* addr =
604 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
605 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6,
606 kTestMessagePort1, test_address);
607}
608
609// Read the RFC5389 fields from the RFC5769 sample STUN request.
610TEST_F(StunTest, ReadRfc5769RequestMessage) {
611 StunMessage msg;
612 size_t size = ReadStunMessage(&msg, kRfc5769SampleRequest);
613 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
614 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
615 kStunTransactionIdLength);
616
617 const StunByteStringAttribute* software =
618 msg.GetByteString(STUN_ATTR_SOFTWARE);
619 ASSERT_TRUE(software != NULL);
620 EXPECT_EQ(kRfc5769SampleMsgClientSoftware, software->GetString());
621
622 const StunByteStringAttribute* username =
623 msg.GetByteString(STUN_ATTR_USERNAME);
624 ASSERT_TRUE(username != NULL);
625 EXPECT_EQ(kRfc5769SampleMsgUsername, username->GetString());
626
627 // Actual M-I value checked in a later test.
628 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
629
630 // Fingerprint checked in a later test, but double-check the value here.
631 const StunUInt32Attribute* fingerprint =
632 msg.GetUInt32(STUN_ATTR_FINGERPRINT);
633 ASSERT_TRUE(fingerprint != NULL);
634 EXPECT_EQ(0xe57a3bcf, fingerprint->value());
635}
636
637// Read the RFC5389 fields from the RFC5769 sample STUN response.
638TEST_F(StunTest, ReadRfc5769ResponseMessage) {
639 StunMessage msg;
640 size_t size = ReadStunMessage(&msg, kRfc5769SampleResponse);
641 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
642 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
643 kStunTransactionIdLength);
644
645 const StunByteStringAttribute* software =
646 msg.GetByteString(STUN_ATTR_SOFTWARE);
647 ASSERT_TRUE(software != NULL);
648 EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->GetString());
649
650 const StunAddressAttribute* mapped_address =
651 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
652 ASSERT_TRUE(mapped_address != NULL);
653 EXPECT_EQ(kRfc5769SampleMsgMappedAddress, mapped_address->GetAddress());
654
655 // Actual M-I and fingerprint checked in later tests.
656 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
657 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
658}
659
660// Read the RFC5389 fields from the RFC5769 sample STUN response for IPv6.
661TEST_F(StunTest, ReadRfc5769ResponseMessageIPv6) {
662 StunMessage msg;
663 size_t size = ReadStunMessage(&msg, kRfc5769SampleResponseIPv6);
664 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
665 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
666 kStunTransactionIdLength);
667
668 const StunByteStringAttribute* software =
669 msg.GetByteString(STUN_ATTR_SOFTWARE);
670 ASSERT_TRUE(software != NULL);
671 EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->GetString());
672
673 const StunAddressAttribute* mapped_address =
674 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
675 ASSERT_TRUE(mapped_address != NULL);
676 EXPECT_EQ(kRfc5769SampleMsgIPv6MappedAddress, mapped_address->GetAddress());
677
678 // Actual M-I and fingerprint checked in later tests.
679 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
680 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
681}
682
683// Read the RFC5389 fields from the RFC5769 sample STUN response with auth.
684TEST_F(StunTest, ReadRfc5769RequestMessageLongTermAuth) {
685 StunMessage msg;
686 size_t size = ReadStunMessage(&msg, kRfc5769SampleRequestLongTermAuth);
687 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
688 CheckStunTransactionID(msg, kRfc5769SampleMsgWithAuthTransactionId,
689 kStunTransactionIdLength);
690
691 const StunByteStringAttribute* username =
692 msg.GetByteString(STUN_ATTR_USERNAME);
693 ASSERT_TRUE(username != NULL);
694 EXPECT_EQ(kRfc5769SampleMsgWithAuthUsername, username->GetString());
695
696 const StunByteStringAttribute* nonce =
697 msg.GetByteString(STUN_ATTR_NONCE);
698 ASSERT_TRUE(nonce != NULL);
699 EXPECT_EQ(kRfc5769SampleMsgWithAuthNonce, nonce->GetString());
700
701 const StunByteStringAttribute* realm =
702 msg.GetByteString(STUN_ATTR_REALM);
703 ASSERT_TRUE(realm != NULL);
704 EXPECT_EQ(kRfc5769SampleMsgWithAuthRealm, realm->GetString());
705
706 // No fingerprint, actual M-I checked in later tests.
707 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
708 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) == NULL);
709}
710
711// The RFC3489 packet in this test is the same as
712// kStunMessageWithIPv4MappedAddress, but with a different value where the
713// magic cookie was.
714TEST_F(StunTest, ReadLegacyMessage) {
715 unsigned char rfc3489_packet[sizeof(kStunMessageWithIPv4MappedAddress)];
716 memcpy(rfc3489_packet, kStunMessageWithIPv4MappedAddress,
717 sizeof(kStunMessageWithIPv4MappedAddress));
718 // Overwrite the magic cookie here.
719 memcpy(&rfc3489_packet[4], "ABCD", 4);
720
721 StunMessage msg;
722 size_t size = ReadStunMessage(&msg, rfc3489_packet);
723 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
724 CheckStunTransactionID(msg, &rfc3489_packet[4], kStunTransactionIdLength + 4);
725
726 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
727 rtc::IPAddress test_address(kIPv4TestAddress1);
728 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4,
729 kTestMessagePort4, test_address);
730}
731
732TEST_F(StunTest, SetIPv6XorAddressAttributeOwner) {
733 StunMessage msg;
734 StunMessage msg2;
735 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress);
736
737 rtc::IPAddress test_address(kIPv6TestAddress1);
738
739 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
740 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
741
742 const StunAddressAttribute* addr =
743 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
744 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6,
745 kTestMessagePort1, test_address);
746
747 // Owner with a different transaction ID.
748 msg2.SetTransactionID("ABCDABCDABCD");
749 StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL);
750 addr2.SetIP(addr->ipaddr());
751 addr2.SetPort(addr->port());
752 addr2.SetOwner(&msg2);
753 // The internal IP address shouldn't change.
754 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
755
jbauchf1f87202016-03-30 06:43:37 -0700756 rtc::ByteBufferWriter correct_buf;
757 rtc::ByteBufferWriter wrong_buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000758 EXPECT_TRUE(addr->Write(&correct_buf));
759 EXPECT_TRUE(addr2.Write(&wrong_buf));
760 // But when written out, the buffers should look different.
761 ASSERT_NE(0,
762 memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
763 // And when reading a known good value, the address should be wrong.
jbauchf1f87202016-03-30 06:43:37 -0700764 rtc::ByteBufferReader read_buf(correct_buf);
765 addr2.Read(&read_buf);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000766 ASSERT_NE(addr->ipaddr(), addr2.ipaddr());
767 addr2.SetIP(addr->ipaddr());
768 addr2.SetPort(addr->port());
769 // Try writing with no owner at all, should fail and write nothing.
770 addr2.SetOwner(NULL);
771 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
jbauchf1f87202016-03-30 06:43:37 -0700772 wrong_buf.Clear();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000773 EXPECT_FALSE(addr2.Write(&wrong_buf));
774 ASSERT_EQ(0U, wrong_buf.Length());
775}
776
777TEST_F(StunTest, SetIPv4XorAddressAttributeOwner) {
778 // Unlike the IPv6XorAddressAttributeOwner test, IPv4 XOR address attributes
779 // should _not_ be affected by a change in owner. IPv4 XOR address uses the
780 // magic cookie value which is fixed.
781 StunMessage msg;
782 StunMessage msg2;
783 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress);
784
785 rtc::IPAddress test_address(kIPv4TestAddress1);
786
787 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
788 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
789
790 const StunAddressAttribute* addr =
791 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
792 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4,
793 kTestMessagePort3, test_address);
794
795 // Owner with a different transaction ID.
796 msg2.SetTransactionID("ABCDABCDABCD");
797 StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL);
798 addr2.SetIP(addr->ipaddr());
799 addr2.SetPort(addr->port());
800 addr2.SetOwner(&msg2);
801 // The internal IP address shouldn't change.
802 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
803
jbauchf1f87202016-03-30 06:43:37 -0700804 rtc::ByteBufferWriter correct_buf;
805 rtc::ByteBufferWriter wrong_buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000806 EXPECT_TRUE(addr->Write(&correct_buf));
807 EXPECT_TRUE(addr2.Write(&wrong_buf));
808 // The same address data should be written.
809 ASSERT_EQ(0,
810 memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
811 // And an attribute should be able to un-XOR an address belonging to a message
812 // with a different transaction ID.
jbauchf1f87202016-03-30 06:43:37 -0700813 rtc::ByteBufferReader read_buf(correct_buf);
814 EXPECT_TRUE(addr2.Read(&read_buf));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000815 ASSERT_EQ(addr->ipaddr(), addr2.ipaddr());
816
817 // However, no owner is still an error, should fail and write nothing.
818 addr2.SetOwner(NULL);
819 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
jbauchf1f87202016-03-30 06:43:37 -0700820 wrong_buf.Clear();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000821 EXPECT_FALSE(addr2.Write(&wrong_buf));
822}
823
824TEST_F(StunTest, CreateIPv6AddressAttribute) {
825 rtc::IPAddress test_ip(kIPv6TestAddress2);
826
zsteinf42cc9d2017-03-27 16:17:19 -0700827 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000828 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
829 addr->SetAddress(test_addr);
830
zsteinf42cc9d2017-03-27 16:17:19 -0700831 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6, kTestMessagePort2,
832 test_ip);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000833}
834
835TEST_F(StunTest, CreateIPv4AddressAttribute) {
836 struct in_addr test_in_addr;
837 test_in_addr.s_addr = 0xBEB0B0BE;
838 rtc::IPAddress test_ip(test_in_addr);
839
zsteinf42cc9d2017-03-27 16:17:19 -0700840 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000841 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
842 addr->SetAddress(test_addr);
843
zsteinf42cc9d2017-03-27 16:17:19 -0700844 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV4, kTestMessagePort2,
845 test_ip);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000846}
847
848// Test that we don't care what order we set the parts of an address
849TEST_F(StunTest, CreateAddressInArbitraryOrder) {
zsteinf42cc9d2017-03-27 16:17:19 -0700850 auto addr = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000851 // Port first
852 addr->SetPort(kTestMessagePort1);
853 addr->SetIP(rtc::IPAddress(kIPv4TestAddress1));
854 ASSERT_EQ(kTestMessagePort1, addr->port());
855 ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr->ipaddr());
856
zsteinf42cc9d2017-03-27 16:17:19 -0700857 auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000858 // IP first
859 addr2->SetIP(rtc::IPAddress(kIPv4TestAddress1));
860 addr2->SetPort(kTestMessagePort2);
861 ASSERT_EQ(kTestMessagePort2, addr2->port());
862 ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr2->ipaddr());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000863}
864
865TEST_F(StunTest, WriteMessageWithIPv6AddressAttribute) {
866 StunMessage msg;
867 size_t size = sizeof(kStunMessageWithIPv6MappedAddress);
868
869 rtc::IPAddress test_ip(kIPv6TestAddress1);
870
871 msg.SetType(STUN_BINDING_REQUEST);
872 msg.SetTransactionID(
873 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
874 kStunTransactionIdLength));
875 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
876
zsteinf42cc9d2017-03-27 16:17:19 -0700877 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000878 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
879 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700880 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000881
882 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
883
jbauchf1f87202016-03-30 06:43:37 -0700884 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000885 EXPECT_TRUE(msg.Write(&out));
886 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6MappedAddress));
887 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700888 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000889 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700890 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000891 ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv6MappedAddress, len1));
892}
893
894TEST_F(StunTest, WriteMessageWithIPv4AddressAttribute) {
895 StunMessage msg;
896 size_t size = sizeof(kStunMessageWithIPv4MappedAddress);
897
898 rtc::IPAddress test_ip(kIPv4TestAddress1);
899
900 msg.SetType(STUN_BINDING_RESPONSE);
901 msg.SetTransactionID(
902 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
903 kStunTransactionIdLength));
904 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
905
zsteinf42cc9d2017-03-27 16:17:19 -0700906 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000907 rtc::SocketAddress test_addr(test_ip, kTestMessagePort4);
908 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700909 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000910
911 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
912
jbauchf1f87202016-03-30 06:43:37 -0700913 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000914 EXPECT_TRUE(msg.Write(&out));
915 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4MappedAddress));
916 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700917 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000918 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700919 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000920 ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv4MappedAddress, len1));
921}
922
923TEST_F(StunTest, WriteMessageWithIPv6XorAddressAttribute) {
924 StunMessage msg;
925 size_t size = sizeof(kStunMessageWithIPv6XorMappedAddress);
926
927 rtc::IPAddress test_ip(kIPv6TestAddress1);
928
929 msg.SetType(STUN_BINDING_RESPONSE);
930 msg.SetTransactionID(
931 std::string(reinterpret_cast<const char*>(kTestTransactionId2),
932 kStunTransactionIdLength));
933 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
934
zsteinf42cc9d2017-03-27 16:17:19 -0700935 auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000936 rtc::SocketAddress test_addr(test_ip, kTestMessagePort1);
937 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700938 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000939
940 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
941
jbauchf1f87202016-03-30 06:43:37 -0700942 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000943 EXPECT_TRUE(msg.Write(&out));
944 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6XorMappedAddress));
945 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700946 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000947 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700948 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000949 ASSERT_EQ(0,
950 memcmp(bytes.c_str(), kStunMessageWithIPv6XorMappedAddress, len1));
951}
952
953TEST_F(StunTest, WriteMessageWithIPv4XoreAddressAttribute) {
954 StunMessage msg;
955 size_t size = sizeof(kStunMessageWithIPv4XorMappedAddress);
956
957 rtc::IPAddress test_ip(kIPv4TestAddress1);
958
959 msg.SetType(STUN_BINDING_RESPONSE);
960 msg.SetTransactionID(
961 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
962 kStunTransactionIdLength));
963 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
964
zsteinf42cc9d2017-03-27 16:17:19 -0700965 auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000966 rtc::SocketAddress test_addr(test_ip, kTestMessagePort3);
967 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700968 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000969
970 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
971
jbauchf1f87202016-03-30 06:43:37 -0700972 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000973 EXPECT_TRUE(msg.Write(&out));
974 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4XorMappedAddress));
975 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700976 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000977 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700978 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000979 ASSERT_EQ(0,
980 memcmp(bytes.c_str(), kStunMessageWithIPv4XorMappedAddress, len1));
981}
982
983TEST_F(StunTest, ReadByteStringAttribute) {
984 StunMessage msg;
985 size_t size = ReadStunMessage(&msg, kStunMessageWithByteStringAttribute);
986
987 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
988 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
989 const StunByteStringAttribute* username =
990 msg.GetByteString(STUN_ATTR_USERNAME);
991 ASSERT_TRUE(username != NULL);
992 EXPECT_EQ(kTestUserName1, username->GetString());
993}
994
995TEST_F(StunTest, ReadPaddedByteStringAttribute) {
996 StunMessage msg;
997 size_t size = ReadStunMessage(&msg,
998 kStunMessageWithPaddedByteStringAttribute);
999 ASSERT_NE(0U, size);
1000 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1001 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
1002 const StunByteStringAttribute* username =
1003 msg.GetByteString(STUN_ATTR_USERNAME);
1004 ASSERT_TRUE(username != NULL);
1005 EXPECT_EQ(kTestUserName2, username->GetString());
1006}
1007
1008TEST_F(StunTest, ReadErrorCodeAttribute) {
1009 StunMessage msg;
1010 size_t size = ReadStunMessage(&msg, kStunMessageWithErrorAttribute);
1011
1012 CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, size);
1013 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
1014 const StunErrorCodeAttribute* errorcode = msg.GetErrorCode();
1015 ASSERT_TRUE(errorcode != NULL);
1016 EXPECT_EQ(kTestErrorClass, errorcode->eclass());
1017 EXPECT_EQ(kTestErrorNumber, errorcode->number());
1018 EXPECT_EQ(kTestErrorReason, errorcode->reason());
1019 EXPECT_EQ(kTestErrorCode, errorcode->code());
deadbeef996fc6b2017-04-26 09:21:22 -07001020 EXPECT_EQ(kTestErrorCode, msg.GetErrorCodeValue());
1021}
1022
1023// Test that GetErrorCodeValue returns STUN_ERROR_GLOBAL_FAILURE if the message
1024// in question doesn't have an error code attribute, rather than crashing.
1025TEST_F(StunTest, GetErrorCodeValueWithNoErrorAttribute) {
1026 StunMessage msg;
1027 ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
1028 EXPECT_EQ(STUN_ERROR_GLOBAL_FAILURE, msg.GetErrorCodeValue());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001029}
1030
1031TEST_F(StunTest, ReadMessageWithAUInt16ListAttribute) {
1032 StunMessage msg;
1033 size_t size = ReadStunMessage(&msg, kStunMessageWithUInt16ListAttribute);
1034 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1035 const StunUInt16ListAttribute* types = msg.GetUnknownAttributes();
1036 ASSERT_TRUE(types != NULL);
1037 EXPECT_EQ(3U, types->Size());
1038 EXPECT_EQ(0x1U, types->GetType(0));
1039 EXPECT_EQ(0x1000U, types->GetType(1));
1040 EXPECT_EQ(0xAB0CU, types->GetType(2));
1041}
1042
1043TEST_F(StunTest, ReadMessageWithAnUnknownAttribute) {
1044 StunMessage msg;
1045 size_t size = ReadStunMessage(&msg, kStunMessageWithUnknownAttribute);
1046 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1047
1048 // Parsing should have succeeded and there should be a USERNAME attribute
1049 const StunByteStringAttribute* username =
1050 msg.GetByteString(STUN_ATTR_USERNAME);
1051 ASSERT_TRUE(username != NULL);
1052 EXPECT_EQ(kTestUserName2, username->GetString());
1053}
1054
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001055TEST_F(StunTest, ReadMessageWithOriginAttribute) {
1056 StunMessage msg;
1057 size_t size = ReadStunMessage(&msg, kStunMessageWithOriginAttribute);
1058 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1059 const StunByteStringAttribute* origin =
1060 msg.GetByteString(STUN_ATTR_ORIGIN);
1061 ASSERT_TRUE(origin != NULL);
1062 EXPECT_EQ(kTestOrigin, origin->GetString());
1063}
1064
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001065TEST_F(StunTest, WriteMessageWithAnErrorCodeAttribute) {
1066 StunMessage msg;
1067 size_t size = sizeof(kStunMessageWithErrorAttribute);
1068
1069 msg.SetType(STUN_BINDING_ERROR_RESPONSE);
1070 msg.SetTransactionID(
1071 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
1072 kStunTransactionIdLength));
1073 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
zsteinf42cc9d2017-03-27 16:17:19 -07001074 auto errorcode = StunAttribute::CreateErrorCode();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001075 errorcode->SetCode(kTestErrorCode);
1076 errorcode->SetReason(kTestErrorReason);
zsteinf42cc9d2017-03-27 16:17:19 -07001077 msg.AddAttribute(std::move(errorcode));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001078 CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, (size - 20));
1079
jbauchf1f87202016-03-30 06:43:37 -07001080 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001081 EXPECT_TRUE(msg.Write(&out));
1082 ASSERT_EQ(size, out.Length());
1083 // No padding.
1084 ASSERT_EQ(0, memcmp(out.Data(), kStunMessageWithErrorAttribute, size));
1085}
1086
1087TEST_F(StunTest, WriteMessageWithAUInt16ListAttribute) {
1088 StunMessage msg;
1089 size_t size = sizeof(kStunMessageWithUInt16ListAttribute);
1090
1091 msg.SetType(STUN_BINDING_REQUEST);
1092 msg.SetTransactionID(
1093 std::string(reinterpret_cast<const char*>(kTestTransactionId2),
1094 kStunTransactionIdLength));
1095 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
zsteinf42cc9d2017-03-27 16:17:19 -07001096 auto list = StunAttribute::CreateUnknownAttributes();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001097 list->AddType(0x1U);
1098 list->AddType(0x1000U);
1099 list->AddType(0xAB0CU);
zsteinf42cc9d2017-03-27 16:17:19 -07001100 msg.AddAttribute(std::move(list));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001101 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
1102
jbauchf1f87202016-03-30 06:43:37 -07001103 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001104 EXPECT_TRUE(msg.Write(&out));
1105 ASSERT_EQ(size, out.Length());
1106 // Check everything up to the padding.
1107 ASSERT_EQ(0,
1108 memcmp(out.Data(), kStunMessageWithUInt16ListAttribute, size - 2));
1109}
1110
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001111TEST_F(StunTest, WriteMessageWithOriginAttribute) {
1112 StunMessage msg;
1113 size_t size = sizeof(kStunMessageWithOriginAttribute);
1114
1115 msg.SetType(STUN_BINDING_REQUEST);
1116 msg.SetTransactionID(
1117 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
1118 kStunTransactionIdLength));
zsteinf42cc9d2017-03-27 16:17:19 -07001119 auto origin =
1120 rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_ORIGIN, kTestOrigin);
1121 msg.AddAttribute(std::move(origin));
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001122
jbauchf1f87202016-03-30 06:43:37 -07001123 rtc::ByteBufferWriter out;
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001124 EXPECT_TRUE(msg.Write(&out));
1125 ASSERT_EQ(size, out.Length());
1126 // Check everything up to the padding
1127 ASSERT_EQ(0, memcmp(out.Data(), kStunMessageWithOriginAttribute, size - 2));
1128}
1129
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001130// Test that we fail to read messages with invalid lengths.
1131void CheckFailureToRead(const unsigned char* testcase, size_t length) {
1132 StunMessage msg;
1133 const char* input = reinterpret_cast<const char*>(testcase);
jbauchf1f87202016-03-30 06:43:37 -07001134 rtc::ByteBufferReader buf(input, length);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001135 ASSERT_FALSE(msg.Read(&buf));
1136}
1137
1138TEST_F(StunTest, FailToReadInvalidMessages) {
1139 CheckFailureToRead(kStunMessageWithZeroLength,
1140 kRealLengthOfInvalidLengthTestCases);
1141 CheckFailureToRead(kStunMessageWithSmallLength,
1142 kRealLengthOfInvalidLengthTestCases);
1143 CheckFailureToRead(kStunMessageWithExcessLength,
1144 kRealLengthOfInvalidLengthTestCases);
1145}
1146
1147// Test that we properly fail to read a non-STUN message.
1148TEST_F(StunTest, FailToReadRtcpPacket) {
1149 CheckFailureToRead(kRtcpPacket, sizeof(kRtcpPacket));
1150}
1151
1152// Check our STUN message validation code against the RFC5769 test messages.
1153TEST_F(StunTest, ValidateMessageIntegrity) {
1154 // Try the messages from RFC 5769.
1155 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1156 reinterpret_cast<const char*>(kRfc5769SampleRequest),
1157 sizeof(kRfc5769SampleRequest),
1158 kRfc5769SampleMsgPassword));
1159 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1160 reinterpret_cast<const char*>(kRfc5769SampleRequest),
1161 sizeof(kRfc5769SampleRequest),
1162 "InvalidPassword"));
1163
1164 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1165 reinterpret_cast<const char*>(kRfc5769SampleResponse),
1166 sizeof(kRfc5769SampleResponse),
1167 kRfc5769SampleMsgPassword));
1168 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1169 reinterpret_cast<const char*>(kRfc5769SampleResponse),
1170 sizeof(kRfc5769SampleResponse),
1171 "InvalidPassword"));
1172
1173 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1174 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
1175 sizeof(kRfc5769SampleResponseIPv6),
1176 kRfc5769SampleMsgPassword));
1177 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1178 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
1179 sizeof(kRfc5769SampleResponseIPv6),
1180 "InvalidPassword"));
1181
1182 // We first need to compute the key for the long-term authentication HMAC.
1183 std::string key;
1184 ComputeStunCredentialHash(kRfc5769SampleMsgWithAuthUsername,
1185 kRfc5769SampleMsgWithAuthRealm, kRfc5769SampleMsgWithAuthPassword, &key);
1186 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1187 reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth),
1188 sizeof(kRfc5769SampleRequestLongTermAuth), key));
1189 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1190 reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth),
1191 sizeof(kRfc5769SampleRequestLongTermAuth),
1192 "InvalidPassword"));
1193
1194 // Try some edge cases.
1195 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1196 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1197 sizeof(kStunMessageWithZeroLength),
1198 kRfc5769SampleMsgPassword));
1199 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1200 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1201 sizeof(kStunMessageWithExcessLength),
1202 kRfc5769SampleMsgPassword));
1203 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1204 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1205 sizeof(kStunMessageWithSmallLength),
1206 kRfc5769SampleMsgPassword));
1207
katrielc1a206102016-06-20 05:13:16 -07001208 // Again, but with the lengths matching what is claimed in the headers.
1209 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1210 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1211 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithZeroLength[2]),
1212 kRfc5769SampleMsgPassword));
1213 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1214 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1215 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithExcessLength[2]),
1216 kRfc5769SampleMsgPassword));
1217 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1218 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1219 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithSmallLength[2]),
1220 kRfc5769SampleMsgPassword));
1221
1222 // Check that a too-short HMAC doesn't cause buffer overflow.
1223 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1224 reinterpret_cast<const char*>(kStunMessageWithBadHmacAtEnd),
1225 sizeof(kStunMessageWithBadHmacAtEnd),
1226 kRfc5769SampleMsgPassword));
1227
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001228 // Test that munging a single bit anywhere in the message causes the
1229 // message-integrity check to fail, unless it is after the M-I attribute.
1230 char buf[sizeof(kRfc5769SampleRequest)];
1231 memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest));
1232 for (size_t i = 0; i < sizeof(buf); ++i) {
1233 buf[i] ^= 0x01;
1234 if (i > 0)
1235 buf[i - 1] ^= 0x01;
1236 EXPECT_EQ(i >= sizeof(buf) - 8, StunMessage::ValidateMessageIntegrity(
1237 buf, sizeof(buf), kRfc5769SampleMsgPassword));
1238 }
1239}
1240
1241// Validate that we generate correct MESSAGE-INTEGRITY attributes.
1242// Note the use of IceMessage instead of StunMessage; this is necessary because
1243// the RFC5769 test messages used include attributes not found in basic STUN.
1244TEST_F(StunTest, AddMessageIntegrity) {
1245 IceMessage msg;
jbauchf1f87202016-03-30 06:43:37 -07001246 rtc::ByteBufferReader buf(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001247 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1248 sizeof(kRfc5769SampleRequestWithoutMI));
1249 EXPECT_TRUE(msg.Read(&buf));
1250 EXPECT_TRUE(msg.AddMessageIntegrity(kRfc5769SampleMsgPassword));
1251 const StunByteStringAttribute* mi_attr =
1252 msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
1253 EXPECT_EQ(20U, mi_attr->length());
1254 EXPECT_EQ(0, memcmp(
1255 mi_attr->bytes(), kCalculatedHmac1, sizeof(kCalculatedHmac1)));
1256
jbauchf1f87202016-03-30 06:43:37 -07001257 rtc::ByteBufferWriter buf1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001258 EXPECT_TRUE(msg.Write(&buf1));
1259 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1260 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(),
1261 kRfc5769SampleMsgPassword));
1262
1263 IceMessage msg2;
jbauchf1f87202016-03-30 06:43:37 -07001264 rtc::ByteBufferReader buf2(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001265 reinterpret_cast<const char*>(kRfc5769SampleResponseWithoutMI),
1266 sizeof(kRfc5769SampleResponseWithoutMI));
1267 EXPECT_TRUE(msg2.Read(&buf2));
1268 EXPECT_TRUE(msg2.AddMessageIntegrity(kRfc5769SampleMsgPassword));
1269 const StunByteStringAttribute* mi_attr2 =
1270 msg2.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
1271 EXPECT_EQ(20U, mi_attr2->length());
1272 EXPECT_EQ(
1273 0, memcmp(mi_attr2->bytes(), kCalculatedHmac2, sizeof(kCalculatedHmac2)));
1274
jbauchf1f87202016-03-30 06:43:37 -07001275 rtc::ByteBufferWriter buf3;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001276 EXPECT_TRUE(msg2.Write(&buf3));
1277 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1278 reinterpret_cast<const char*>(buf3.Data()), buf3.Length(),
1279 kRfc5769SampleMsgPassword));
1280}
1281
1282// Check our STUN message validation code against the RFC5769 test messages.
1283TEST_F(StunTest, ValidateFingerprint) {
1284 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1285 reinterpret_cast<const char*>(kRfc5769SampleRequest),
1286 sizeof(kRfc5769SampleRequest)));
1287 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1288 reinterpret_cast<const char*>(kRfc5769SampleResponse),
1289 sizeof(kRfc5769SampleResponse)));
1290 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1291 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
1292 sizeof(kRfc5769SampleResponseIPv6)));
1293
1294 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1295 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1296 sizeof(kStunMessageWithZeroLength)));
1297 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1298 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1299 sizeof(kStunMessageWithExcessLength)));
1300 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1301 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1302 sizeof(kStunMessageWithSmallLength)));
1303
1304 // Test that munging a single bit anywhere in the message causes the
1305 // fingerprint check to fail.
1306 char buf[sizeof(kRfc5769SampleRequest)];
1307 memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest));
1308 for (size_t i = 0; i < sizeof(buf); ++i) {
1309 buf[i] ^= 0x01;
1310 if (i > 0)
1311 buf[i - 1] ^= 0x01;
1312 EXPECT_FALSE(StunMessage::ValidateFingerprint(buf, sizeof(buf)));
1313 }
1314 // Put them all back to normal and the check should pass again.
1315 buf[sizeof(buf) - 1] ^= 0x01;
1316 EXPECT_TRUE(StunMessage::ValidateFingerprint(buf, sizeof(buf)));
1317}
1318
1319TEST_F(StunTest, AddFingerprint) {
1320 IceMessage msg;
jbauchf1f87202016-03-30 06:43:37 -07001321 rtc::ByteBufferReader buf(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001322 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1323 sizeof(kRfc5769SampleRequestWithoutMI));
1324 EXPECT_TRUE(msg.Read(&buf));
1325 EXPECT_TRUE(msg.AddFingerprint());
1326
jbauchf1f87202016-03-30 06:43:37 -07001327 rtc::ByteBufferWriter buf1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001328 EXPECT_TRUE(msg.Write(&buf1));
1329 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1330 reinterpret_cast<const char*>(buf1.Data()), buf1.Length()));
1331}
1332
1333// Sample "GTURN" relay message.
1334static const unsigned char kRelayMessage[] = {
1335 0x00, 0x01, 0x00, 88, // message header
1336 0x21, 0x12, 0xA4, 0x42, // magic cookie
1337 '0', '1', '2', '3', // transaction id
1338 '4', '5', '6', '7',
1339 '8', '9', 'a', 'b',
1340 0x00, 0x01, 0x00, 8, // mapped address
1341 0x00, 0x01, 0x00, 13,
1342 0x00, 0x00, 0x00, 17,
1343 0x00, 0x06, 0x00, 12, // username
1344 'a', 'b', 'c', 'd',
1345 'e', 'f', 'g', 'h',
1346 'i', 'j', 'k', 'l',
1347 0x00, 0x0d, 0x00, 4, // lifetime
1348 0x00, 0x00, 0x00, 11,
1349 0x00, 0x0f, 0x00, 4, // magic cookie
1350 0x72, 0xc6, 0x4b, 0xc6,
1351 0x00, 0x10, 0x00, 4, // bandwidth
1352 0x00, 0x00, 0x00, 6,
1353 0x00, 0x11, 0x00, 8, // destination address
1354 0x00, 0x01, 0x00, 13,
1355 0x00, 0x00, 0x00, 17,
1356 0x00, 0x12, 0x00, 8, // source address 2
1357 0x00, 0x01, 0x00, 13,
1358 0x00, 0x00, 0x00, 17,
1359 0x00, 0x13, 0x00, 7, // data
1360 'a', 'b', 'c', 'd',
1361 'e', 'f', 'g', 0 // DATA must be padded per rfc5766.
1362};
1363
1364// Test that we can read the GTURN-specific fields.
1365TEST_F(StunTest, ReadRelayMessage) {
1366 RelayMessage msg, msg2;
1367
1368 const char* input = reinterpret_cast<const char*>(kRelayMessage);
1369 size_t size = sizeof(kRelayMessage);
jbauchf1f87202016-03-30 06:43:37 -07001370 rtc::ByteBufferReader buf(input, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001371 EXPECT_TRUE(msg.Read(&buf));
1372
1373 EXPECT_EQ(STUN_BINDING_REQUEST, msg.type());
1374 EXPECT_EQ(size - 20, msg.length());
1375 EXPECT_EQ("0123456789ab", msg.transaction_id());
1376
1377 msg2.SetType(STUN_BINDING_REQUEST);
1378 msg2.SetTransactionID("0123456789ab");
1379
1380 in_addr legacy_in_addr;
1381 legacy_in_addr.s_addr = htonl(17U);
1382 rtc::IPAddress legacy_ip(legacy_in_addr);
1383
1384 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
1385 ASSERT_TRUE(addr != NULL);
1386 EXPECT_EQ(1, addr->family());
1387 EXPECT_EQ(13, addr->port());
1388 EXPECT_EQ(legacy_ip, addr->ipaddr());
1389
zsteinf42cc9d2017-03-27 16:17:19 -07001390 auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001391 addr2->SetPort(13);
1392 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001393 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001394
1395 const StunByteStringAttribute* bytes = msg.GetByteString(STUN_ATTR_USERNAME);
1396 ASSERT_TRUE(bytes != NULL);
1397 EXPECT_EQ(12U, bytes->length());
1398 EXPECT_EQ("abcdefghijkl", bytes->GetString());
1399
zsteinf42cc9d2017-03-27 16:17:19 -07001400 auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001401 bytes2->CopyBytes("abcdefghijkl");
zsteinf42cc9d2017-03-27 16:17:19 -07001402 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001403
1404 const StunUInt32Attribute* uval = msg.GetUInt32(STUN_ATTR_LIFETIME);
1405 ASSERT_TRUE(uval != NULL);
1406 EXPECT_EQ(11U, uval->value());
1407
zsteinf42cc9d2017-03-27 16:17:19 -07001408 auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001409 uval2->SetValue(11);
zsteinf42cc9d2017-03-27 16:17:19 -07001410 msg2.AddAttribute(std::move(uval2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001411
1412 bytes = msg.GetByteString(STUN_ATTR_MAGIC_COOKIE);
1413 ASSERT_TRUE(bytes != NULL);
1414 EXPECT_EQ(4U, bytes->length());
1415 EXPECT_EQ(0,
1416 memcmp(bytes->bytes(),
1417 TURN_MAGIC_COOKIE_VALUE,
1418 sizeof(TURN_MAGIC_COOKIE_VALUE)));
1419
1420 bytes2 = StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
1421 bytes2->CopyBytes(reinterpret_cast<const char*>(TURN_MAGIC_COOKIE_VALUE),
1422 sizeof(TURN_MAGIC_COOKIE_VALUE));
zsteinf42cc9d2017-03-27 16:17:19 -07001423 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001424
1425 uval = msg.GetUInt32(STUN_ATTR_BANDWIDTH);
1426 ASSERT_TRUE(uval != NULL);
1427 EXPECT_EQ(6U, uval->value());
1428
1429 uval2 = StunAttribute::CreateUInt32(STUN_ATTR_BANDWIDTH);
1430 uval2->SetValue(6);
zsteinf42cc9d2017-03-27 16:17:19 -07001431 msg2.AddAttribute(std::move(uval2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001432
1433 addr = msg.GetAddress(STUN_ATTR_DESTINATION_ADDRESS);
1434 ASSERT_TRUE(addr != NULL);
1435 EXPECT_EQ(1, addr->family());
1436 EXPECT_EQ(13, addr->port());
1437 EXPECT_EQ(legacy_ip, addr->ipaddr());
1438
1439 addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
1440 addr2->SetPort(13);
1441 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001442 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001443
1444 addr = msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2);
1445 ASSERT_TRUE(addr != NULL);
1446 EXPECT_EQ(1, addr->family());
1447 EXPECT_EQ(13, addr->port());
1448 EXPECT_EQ(legacy_ip, addr->ipaddr());
1449
1450 addr2 = StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2);
1451 addr2->SetPort(13);
1452 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001453 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001454
1455 bytes = msg.GetByteString(STUN_ATTR_DATA);
1456 ASSERT_TRUE(bytes != NULL);
1457 EXPECT_EQ(7U, bytes->length());
1458 EXPECT_EQ("abcdefg", bytes->GetString());
1459
1460 bytes2 = StunAttribute::CreateByteString(STUN_ATTR_DATA);
1461 bytes2->CopyBytes("abcdefg");
zsteinf42cc9d2017-03-27 16:17:19 -07001462 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001463
jbauchf1f87202016-03-30 06:43:37 -07001464 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001465 EXPECT_TRUE(msg.Write(&out));
1466 EXPECT_EQ(size, out.Length());
1467 size_t len1 = out.Length();
jbauchf1f87202016-03-30 06:43:37 -07001468 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001469 std::string outstring;
jbauchf1f87202016-03-30 06:43:37 -07001470 read_buf.ReadString(&outstring, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001471 EXPECT_EQ(0, memcmp(outstring.c_str(), input, len1));
1472
jbauchf1f87202016-03-30 06:43:37 -07001473 rtc::ByteBufferWriter out2;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001474 EXPECT_TRUE(msg2.Write(&out2));
1475 EXPECT_EQ(size, out2.Length());
1476 size_t len2 = out2.Length();
jbauchf1f87202016-03-30 06:43:37 -07001477 rtc::ByteBufferReader read_buf2(out2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001478 std::string outstring2;
jbauchf1f87202016-03-30 06:43:37 -07001479 read_buf2.ReadString(&outstring2, len2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001480 EXPECT_EQ(0, memcmp(outstring2.c_str(), input, len2));
1481}
1482
Jonas Oreland202994c2017-12-18 12:10:43 +01001483// Test that we can remove attribute from a message.
1484TEST_F(StunTest, RemoveAttribute) {
1485 StunMessage msg;
1486
1487 // Removing something that does exist should return nullptr.
1488 EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr);
1489
1490 {
1491 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1492 attr->CopyBytes("kes", sizeof("kes"));
1493 msg.AddAttribute(std::move(attr));
1494 }
1495
1496 size_t len = msg.length();
1497 {
1498 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1499 ASSERT_NE(attr, nullptr);
1500 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1501 EXPECT_STREQ("kes",
1502 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1503 EXPECT_LT(msg.length(), len);
1504 }
1505
1506 // Now add same attribute type twice.
1507 {
1508 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1509 attr->CopyBytes("kes", sizeof("kes"));
1510 msg.AddAttribute(std::move(attr));
1511 }
1512
1513 {
1514 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1515 attr->CopyBytes("kenta", sizeof("kenta"));
1516 msg.AddAttribute(std::move(attr));
1517 }
1518
1519 // Remove should remove the last added occurrence.
1520 {
1521 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1522 ASSERT_NE(attr, nullptr);
1523 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1524 EXPECT_STREQ("kenta",
1525 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1526 }
1527
1528 // Remove should remove the last added occurrence.
1529 {
1530 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1531 ASSERT_NE(attr, nullptr);
1532 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1533 EXPECT_STREQ("kes",
1534 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1535 }
1536
1537 // Removing something that does exist should return nullptr.
1538 EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr);
1539}
1540
1541// Test CopyStunAttribute
1542TEST_F(StunTest, CopyAttribute) {
1543 rtc::ByteBufferWriter buf;
1544 rtc::ByteBufferWriter* buffer_ptrs[] = { &buf, nullptr };
1545 // Test both with and without supplied ByteBufferWriter.
1546 for (auto buffer_ptr : buffer_ptrs) {
1547 { // Test StunByteStringAttribute.
1548 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1549 attr->CopyBytes("kes", sizeof("kes"));
1550
1551 auto copy = CopyStunAttribute(*attr.get(), buffer_ptr);
1552 ASSERT_EQ(copy->value_type(), STUN_VALUE_BYTE_STRING);
1553 EXPECT_STREQ("kes",
1554 static_cast<StunByteStringAttribute*>(copy.get())->bytes());
1555 }
1556
1557 { // Test StunAddressAttribute.
1558 rtc::IPAddress test_ip(kIPv6TestAddress2);
1559 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
1560 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
1561 addr->SetAddress(test_addr);
1562 CheckStunAddressAttribute(addr.get(),
1563 STUN_ADDRESS_IPV6, kTestMessagePort2, test_ip);
1564
1565 auto copy = CopyStunAttribute(*addr.get(), buffer_ptr);
1566 ASSERT_EQ(copy->value_type(), STUN_VALUE_ADDRESS);
1567 CheckStunAddressAttribute(static_cast<StunAddressAttribute*>(copy.get()),
1568 STUN_ADDRESS_IPV6, kTestMessagePort2, test_ip);
1569 }
1570 }
1571}
1572
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001573} // namespace cricket