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