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