Note: We no longer publish the latest version of our code here. We primarily use a kumc-bmi github organization. The heron ETL repository, in particular, is not public. Peers in the informatics community should see MultiSiteDev for details on requesting access.

source: webrtc/talk/p2p/base/stun_unittest.cc @ 0:4bda6873e34c

pub_scrub_3792 tip
Last change on this file since 0:4bda6873e34c was 0:4bda6873e34c, checked in by Michael Prittie <mprittie@…>, 6 years ago

Scrubbed password for publication.

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