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