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