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