1 /*
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 "api/transport/stun.h"
12
13 #include <string.h>
14
15 #include <memory>
16 #include <string>
17 #include <utility>
18
19 #include "rtc_base/arraysize.h"
20 #include "rtc_base/byte_buffer.h"
21 #include "rtc_base/byte_order.h"
22 #include "rtc_base/socket_address.h"
23 #include "system_wrappers/include/metrics.h"
24 #include "test/gtest.h"
25
26 namespace cricket {
27
28 class StunTest : public ::testing::Test {
29 protected:
CheckStunHeader(const StunMessage & msg,StunMessageType expected_type,size_t expected_length)30 void CheckStunHeader(const StunMessage& msg,
31 StunMessageType expected_type,
32 size_t expected_length) {
33 ASSERT_EQ(expected_type, msg.type());
34 ASSERT_EQ(expected_length, msg.length());
35 }
36
CheckStunTransactionID(const StunMessage & msg,const unsigned char * expectedID,size_t length)37 void CheckStunTransactionID(const StunMessage& msg,
38 const unsigned char* expectedID,
39 size_t length) {
40 ASSERT_EQ(length, msg.transaction_id().size());
41 ASSERT_EQ(length == kStunTransactionIdLength + 4, msg.IsLegacy());
42 ASSERT_EQ(length == kStunTransactionIdLength, !msg.IsLegacy());
43 ASSERT_EQ(0, memcmp(msg.transaction_id().c_str(), expectedID, length));
44 }
45
CheckStunAddressAttribute(const StunAddressAttribute * addr,StunAddressFamily expected_family,int expected_port,const rtc::IPAddress & expected_address)46 void CheckStunAddressAttribute(const StunAddressAttribute* addr,
47 StunAddressFamily expected_family,
48 int expected_port,
49 const rtc::IPAddress& expected_address) {
50 ASSERT_EQ(expected_family, addr->family());
51 ASSERT_EQ(expected_port, addr->port());
52
53 if (addr->family() == STUN_ADDRESS_IPV4) {
54 in_addr v4_address = expected_address.ipv4_address();
55 in_addr stun_address = addr->ipaddr().ipv4_address();
56 ASSERT_EQ(0, memcmp(&v4_address, &stun_address, sizeof(stun_address)));
57 } else if (addr->family() == STUN_ADDRESS_IPV6) {
58 in6_addr v6_address = expected_address.ipv6_address();
59 in6_addr stun_address = addr->ipaddr().ipv6_address();
60 ASSERT_EQ(0, memcmp(&v6_address, &stun_address, sizeof(stun_address)));
61 } else {
62 ASSERT_TRUE(addr->family() == STUN_ADDRESS_IPV6 ||
63 addr->family() == STUN_ADDRESS_IPV4);
64 }
65 }
66
ReadStunMessageTestCase(StunMessage * msg,const unsigned char * testcase,size_t size)67 size_t ReadStunMessageTestCase(StunMessage* msg,
68 const unsigned char* testcase,
69 size_t size) {
70 const char* input = reinterpret_cast<const char*>(testcase);
71 rtc::ByteBufferReader buf(input, size);
72 if (msg->Read(&buf)) {
73 // Returns the size the stun message should report itself as being
74 return (size - 20);
75 } else {
76 return 0;
77 }
78 }
79 };
80
81 // Sample STUN packets with various attributes
82 // Gathered by wiresharking pjproject's pjnath test programs
83 // pjproject available at www.pjsip.org
84
85 // clang-format off
86 // clang formatting doesn't respect inline comments.
87
88 static const unsigned char kStunMessageWithIPv6MappedAddress[] = {
89 0x00, 0x01, 0x00, 0x18, // message header
90 0x21, 0x12, 0xa4, 0x42, // transaction id
91 0x29, 0x1f, 0xcd, 0x7c,
92 0xba, 0x58, 0xab, 0xd7,
93 0xf2, 0x41, 0x01, 0x00,
94 0x00, 0x01, 0x00, 0x14, // Address type (mapped), length
95 0x00, 0x02, 0xb8, 0x81, // family (IPv6), port
96 0x24, 0x01, 0xfa, 0x00, // an IPv6 address
97 0x00, 0x04, 0x10, 0x00,
98 0xbe, 0x30, 0x5b, 0xff,
99 0xfe, 0xe5, 0x00, 0xc3
100 };
101
102 static const unsigned char kStunMessageWithIPv4MappedAddress[] = {
103 0x01, 0x01, 0x00, 0x0c, // binding response, length 12
104 0x21, 0x12, 0xa4, 0x42, // magic cookie
105 0x29, 0x1f, 0xcd, 0x7c, // transaction ID
106 0xba, 0x58, 0xab, 0xd7,
107 0xf2, 0x41, 0x01, 0x00,
108 0x00, 0x01, 0x00, 0x08, // Mapped, 8 byte length
109 0x00, 0x01, 0x9d, 0xfc, // AF_INET, unxor-ed port
110 0xac, 0x17, 0x44, 0xe6 // IPv4 address
111 };
112
113 // Test XOR-mapped IP addresses:
114 static const unsigned char kStunMessageWithIPv6XorMappedAddress[] = {
115 0x01, 0x01, 0x00, 0x18, // message header (binding response)
116 0x21, 0x12, 0xa4, 0x42, // magic cookie (rfc5389)
117 0xe3, 0xa9, 0x46, 0xe1, // transaction ID
118 0x7c, 0x00, 0xc2, 0x62,
119 0x54, 0x08, 0x01, 0x00,
120 0x00, 0x20, 0x00, 0x14, // Address Type (XOR), length
121 0x00, 0x02, 0xcb, 0x5b, // family, XOR-ed port
122 0x05, 0x13, 0x5e, 0x42, // XOR-ed IPv6 address
123 0xe3, 0xad, 0x56, 0xe1,
124 0xc2, 0x30, 0x99, 0x9d,
125 0xaa, 0xed, 0x01, 0xc3
126 };
127
128 static const unsigned char kStunMessageWithIPv4XorMappedAddress[] = {
129 0x01, 0x01, 0x00, 0x0c, // message header (binding response)
130 0x21, 0x12, 0xa4, 0x42, // magic cookie
131 0x29, 0x1f, 0xcd, 0x7c, // transaction ID
132 0xba, 0x58, 0xab, 0xd7,
133 0xf2, 0x41, 0x01, 0x00,
134 0x00, 0x20, 0x00, 0x08, // address type (xor), length
135 0x00, 0x01, 0xfc, 0xb5, // family (AF_INET), XOR-ed port
136 0x8d, 0x05, 0xe0, 0xa4 // IPv4 address
137 };
138
139 // ByteString Attribute (username)
140 static const unsigned char kStunMessageWithByteStringAttribute[] = {
141 0x00, 0x01, 0x00, 0x0c,
142 0x21, 0x12, 0xa4, 0x42,
143 0xe3, 0xa9, 0x46, 0xe1,
144 0x7c, 0x00, 0xc2, 0x62,
145 0x54, 0x08, 0x01, 0x00,
146 0x00, 0x06, 0x00, 0x08, // username attribute (length 8)
147 0x61, 0x62, 0x63, 0x64, // abcdefgh
148 0x65, 0x66, 0x67, 0x68
149 };
150
151 // Message with an unknown but comprehensible optional attribute.
152 // Parsing should succeed despite this unknown attribute.
153 static const unsigned char kStunMessageWithUnknownAttribute[] = {
154 0x00, 0x01, 0x00, 0x14,
155 0x21, 0x12, 0xa4, 0x42,
156 0xe3, 0xa9, 0x46, 0xe1,
157 0x7c, 0x00, 0xc2, 0x62,
158 0x54, 0x08, 0x01, 0x00,
159 0x00, 0xaa, 0x00, 0x07, // Unknown attribute, length 7 (needs padding!)
160 0x61, 0x62, 0x63, 0x64, // abcdefg + padding
161 0x65, 0x66, 0x67, 0x00,
162 0x00, 0x06, 0x00, 0x03, // Followed by a known attribute we can
163 0x61, 0x62, 0x63, 0x00 // check for (username of length 3)
164 };
165
166 // ByteString Attribute (username) with padding byte
167 static const unsigned char kStunMessageWithPaddedByteStringAttribute[] = {
168 0x00, 0x01, 0x00, 0x08,
169 0x21, 0x12, 0xa4, 0x42,
170 0xe3, 0xa9, 0x46, 0xe1,
171 0x7c, 0x00, 0xc2, 0x62,
172 0x54, 0x08, 0x01, 0x00,
173 0x00, 0x06, 0x00, 0x03, // username attribute (length 3)
174 0x61, 0x62, 0x63, 0xcc // abc
175 };
176
177 // Message with an Unknown Attributes (uint16_t list) attribute.
178 static const unsigned char kStunMessageWithUInt16ListAttribute[] = {
179 0x00, 0x01, 0x00, 0x0c,
180 0x21, 0x12, 0xa4, 0x42,
181 0xe3, 0xa9, 0x46, 0xe1,
182 0x7c, 0x00, 0xc2, 0x62,
183 0x54, 0x08, 0x01, 0x00,
184 0x00, 0x0a, 0x00, 0x06, // username attribute (length 6)
185 0x00, 0x01, 0x10, 0x00, // three attributes plus padding
186 0xAB, 0xCU, 0xBE, 0xEF
187 };
188
189 // Error response message (unauthorized)
190 static const unsigned char kStunMessageWithErrorAttribute[] = {
191 0x01, 0x11, 0x00, 0x14,
192 0x21, 0x12, 0xa4, 0x42,
193 0x29, 0x1f, 0xcd, 0x7c,
194 0xba, 0x58, 0xab, 0xd7,
195 0xf2, 0x41, 0x01, 0x00,
196 0x00, 0x09, 0x00, 0x10,
197 0x00, 0x00, 0x04, 0x01,
198 0x55, 0x6e, 0x61, 0x75,
199 0x74, 0x68, 0x6f, 0x72,
200 0x69, 0x7a, 0x65, 0x64
201 };
202
203 // Sample messages with an invalid length Field
204
205 // The actual length in bytes of the invalid messages (including STUN header)
206 static const int kRealLengthOfInvalidLengthTestCases = 32;
207
208 static const unsigned char kStunMessageWithZeroLength[] = {
209 0x00, 0x01, 0x00, 0x00, // length of 0 (last 2 bytes)
210 0x21, 0x12, 0xA4, 0x42, // magic cookie
211 '0', '1', '2', '3', // transaction id
212 '4', '5', '6', '7',
213 '8', '9', 'a', 'b',
214 0x00, 0x20, 0x00, 0x08, // xor mapped address
215 0x00, 0x01, 0x21, 0x1F,
216 0x21, 0x12, 0xA4, 0x53,
217 };
218
219 static const unsigned char kStunMessageWithExcessLength[] = {
220 0x00, 0x01, 0x00, 0x55, // length of 85
221 0x21, 0x12, 0xA4, 0x42, // magic cookie
222 '0', '1', '2', '3', // transaction id
223 '4', '5', '6', '7',
224 '8', '9', 'a', 'b',
225 0x00, 0x20, 0x00, 0x08, // xor mapped address
226 0x00, 0x01, 0x21, 0x1F,
227 0x21, 0x12, 0xA4, 0x53,
228 };
229
230 static const unsigned char kStunMessageWithSmallLength[] = {
231 0x00, 0x01, 0x00, 0x03, // length of 3
232 0x21, 0x12, 0xA4, 0x42, // magic cookie
233 '0', '1', '2', '3', // transaction id
234 '4', '5', '6', '7',
235 '8', '9', 'a', 'b',
236 0x00, 0x20, 0x00, 0x08, // xor mapped address
237 0x00, 0x01, 0x21, 0x1F,
238 0x21, 0x12, 0xA4, 0x53,
239 };
240
241 static const unsigned char kStunMessageWithBadHmacAtEnd[] = {
242 0x00, 0x01, 0x00, 0x14, // message length exactly 20
243 0x21, 0x12, 0xA4, 0x42, // magic cookie
244 '0', '1', '2', '3', // transaction ID
245 '4', '5', '6', '7',
246 '8', '9', 'a', 'b',
247 0x00, 0x08, 0x00, 0x14, // type=STUN_ATTR_MESSAGE_INTEGRITY, length=20
248 '0', '0', '0', '0', // We lied, there are only 16 bytes of HMAC.
249 '0', '0', '0', '0',
250 '0', '0', '0', '0',
251 '0', '0', '0', '0',
252 };
253
254 // RTCP packet, for testing we correctly ignore non stun packet types.
255 // V=2, P=false, RC=0, Type=200, Len=6, Sender-SSRC=85, etc
256 static const unsigned char kRtcpPacket[] = {
257 0x80, 0xc8, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55,
258 0xce, 0xa5, 0x18, 0x3a, 0x39, 0xcc, 0x7d, 0x09,
259 0x23, 0xed, 0x19, 0x07, 0x00, 0x00, 0x01, 0x56,
260 0x00, 0x03, 0x73, 0x50,
261 };
262
263
264 // RFC5769 Test Vectors
265 // Software name (request): "STUN test client" (without quotes)
266 // Software name (response): "test vector" (without quotes)
267 // Username: "evtj:h6vY" (without quotes)
268 // Password: "VOkJxbRl1RmTxUk/WvJxBt" (without quotes)
269 static const unsigned char kRfc5769SampleMsgTransactionId[] = {
270 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae
271 };
272 static const char kRfc5769SampleMsgClientSoftware[] = "STUN test client";
273 static const char kRfc5769SampleMsgServerSoftware[] = "test vector";
274 static const char kRfc5769SampleMsgUsername[] = "evtj:h6vY";
275 static const char kRfc5769SampleMsgPassword[] = "VOkJxbRl1RmTxUk/WvJxBt";
276 static const rtc::SocketAddress kRfc5769SampleMsgMappedAddress(
277 "192.0.2.1", 32853);
278 static const rtc::SocketAddress kRfc5769SampleMsgIPv6MappedAddress(
279 "2001:db8:1234:5678:11:2233:4455:6677", 32853);
280
281 static const unsigned char kRfc5769SampleMsgWithAuthTransactionId[] = {
282 0x78, 0xad, 0x34, 0x33, 0xc6, 0xad, 0x72, 0xc0, 0x29, 0xda, 0x41, 0x2e
283 };
284 static const char kRfc5769SampleMsgWithAuthUsername[] =
285 "\xe3\x83\x9e\xe3\x83\x88\xe3\x83\xaa\xe3\x83\x83\xe3\x82\xaf\xe3\x82\xb9";
286 static const char kRfc5769SampleMsgWithAuthPassword[] = "TheMatrIX";
287 static const char kRfc5769SampleMsgWithAuthNonce[] =
288 "f//499k954d6OL34oL9FSTvy64sA";
289 static const char kRfc5769SampleMsgWithAuthRealm[] = "example.org";
290
291 // 2.1. Sample Request
292 static const unsigned char kRfc5769SampleRequest[] = {
293 0x00, 0x01, 0x00, 0x58, // Request type and message length
294 0x21, 0x12, 0xa4, 0x42, // Magic cookie
295 0xb7, 0xe7, 0xa7, 0x01, // }
296 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
297 0xfa, 0x87, 0xdf, 0xae, // }
298 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
299 0x53, 0x54, 0x55, 0x4e, // }
300 0x20, 0x74, 0x65, 0x73, // } User-agent...
301 0x74, 0x20, 0x63, 0x6c, // } ...name
302 0x69, 0x65, 0x6e, 0x74, // }
303 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
304 0x6e, 0x00, 0x01, 0xff, // ICE priority value
305 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
306 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
307 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
308 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
309 0x65, 0x76, 0x74, 0x6a, // }
310 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
311 0x59, 0x20, 0x20, 0x20, // }
312 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
313 0x9a, 0xea, 0xa7, 0x0c, // }
314 0xbf, 0xd8, 0xcb, 0x56, // }
315 0x78, 0x1e, 0xf2, 0xb5, // } HMAC-SHA1 fingerprint
316 0xb2, 0xd3, 0xf2, 0x49, // }
317 0xc1, 0xb5, 0x71, 0xa2, // }
318 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
319 0xe5, 0x7a, 0x3b, 0xcf // CRC32 fingerprint
320 };
321
322 // 2.1. Sample Request
323 static const unsigned char kSampleRequestMI32[] = {
324 0x00, 0x01, 0x00, 0x48, // Request type and message length
325 0x21, 0x12, 0xa4, 0x42, // Magic cookie
326 0xb7, 0xe7, 0xa7, 0x01, // }
327 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
328 0xfa, 0x87, 0xdf, 0xae, // }
329 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
330 0x53, 0x54, 0x55, 0x4e, // }
331 0x20, 0x74, 0x65, 0x73, // } User-agent...
332 0x74, 0x20, 0x63, 0x6c, // } ...name
333 0x69, 0x65, 0x6e, 0x74, // }
334 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
335 0x6e, 0x00, 0x01, 0xff, // ICE priority value
336 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
337 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
338 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
339 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
340 0x65, 0x76, 0x74, 0x6a, // }
341 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
342 0x59, 0x20, 0x20, 0x20, // }
343 0xC0, 0x60, 0x00, 0x04, // MESSAGE-INTEGRITY-32 attribute header
344 0x45, 0x45, 0xce, 0x7c, // } HMAC-SHA1 fingerprint (first 32 bit)
345 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
346 0xe5, 0x7a, 0x3b, 0xcf // CRC32 fingerprint
347 };
348
349 // 2.2. Sample IPv4 Response
350 static const unsigned char kRfc5769SampleResponse[] = {
351 0x01, 0x01, 0x00, 0x3c, // Response type and message length
352 0x21, 0x12, 0xa4, 0x42, // Magic cookie
353 0xb7, 0xe7, 0xa7, 0x01, // }
354 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
355 0xfa, 0x87, 0xdf, 0xae, // }
356 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
357 0x74, 0x65, 0x73, 0x74, // }
358 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
359 0x74, 0x6f, 0x72, 0x20, // }
360 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
361 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port
362 0xe1, 0x12, 0xa6, 0x43, // Xor'd mapped IPv4 address
363 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
364 0x2b, 0x91, 0xf5, 0x99, // }
365 0xfd, 0x9e, 0x90, 0xc3, // }
366 0x8c, 0x74, 0x89, 0xf9, // } HMAC-SHA1 fingerprint
367 0x2a, 0xf9, 0xba, 0x53, // }
368 0xf0, 0x6b, 0xe7, 0xd7, // }
369 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
370 0xc0, 0x7d, 0x4c, 0x96 // CRC32 fingerprint
371 };
372
373 // 2.3. Sample IPv6 Response
374 static const unsigned char kRfc5769SampleResponseIPv6[] = {
375 0x01, 0x01, 0x00, 0x48, // Response type and message length
376 0x21, 0x12, 0xa4, 0x42, // Magic cookie
377 0xb7, 0xe7, 0xa7, 0x01, // }
378 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
379 0xfa, 0x87, 0xdf, 0xae, // }
380 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
381 0x74, 0x65, 0x73, 0x74, // }
382 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
383 0x74, 0x6f, 0x72, 0x20, // }
384 0x00, 0x20, 0x00, 0x14, // XOR-MAPPED-ADDRESS attribute header
385 0x00, 0x02, 0xa1, 0x47, // Address family (IPv6) and xor'd mapped port.
386 0x01, 0x13, 0xa9, 0xfa, // }
387 0xa5, 0xd3, 0xf1, 0x79, // } Xor'd mapped IPv6 address
388 0xbc, 0x25, 0xf4, 0xb5, // }
389 0xbe, 0xd2, 0xb9, 0xd9, // }
390 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
391 0xa3, 0x82, 0x95, 0x4e, // }
392 0x4b, 0xe6, 0x7b, 0xf1, // }
393 0x17, 0x84, 0xc9, 0x7c, // } HMAC-SHA1 fingerprint
394 0x82, 0x92, 0xc2, 0x75, // }
395 0xbf, 0xe3, 0xed, 0x41, // }
396 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
397 0xc8, 0xfb, 0x0b, 0x4c // CRC32 fingerprint
398 };
399
400 // 2.4. Sample Request with Long-Term Authentication
401 static const unsigned char kRfc5769SampleRequestLongTermAuth[] = {
402 0x00, 0x01, 0x00, 0x60, // Request type and message length
403 0x21, 0x12, 0xa4, 0x42, // Magic cookie
404 0x78, 0xad, 0x34, 0x33, // }
405 0xc6, 0xad, 0x72, 0xc0, // } Transaction ID
406 0x29, 0xda, 0x41, 0x2e, // }
407 0x00, 0x06, 0x00, 0x12, // USERNAME attribute header
408 0xe3, 0x83, 0x9e, 0xe3, // }
409 0x83, 0x88, 0xe3, 0x83, // }
410 0xaa, 0xe3, 0x83, 0x83, // } Username value (18 bytes) and padding (2 bytes)
411 0xe3, 0x82, 0xaf, 0xe3, // }
412 0x82, 0xb9, 0x00, 0x00, // }
413 0x00, 0x15, 0x00, 0x1c, // NONCE attribute header
414 0x66, 0x2f, 0x2f, 0x34, // }
415 0x39, 0x39, 0x6b, 0x39, // }
416 0x35, 0x34, 0x64, 0x36, // }
417 0x4f, 0x4c, 0x33, 0x34, // } Nonce value
418 0x6f, 0x4c, 0x39, 0x46, // }
419 0x53, 0x54, 0x76, 0x79, // }
420 0x36, 0x34, 0x73, 0x41, // }
421 0x00, 0x14, 0x00, 0x0b, // REALM attribute header
422 0x65, 0x78, 0x61, 0x6d, // }
423 0x70, 0x6c, 0x65, 0x2e, // } Realm value (11 bytes) and padding (1 byte)
424 0x6f, 0x72, 0x67, 0x00, // }
425 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
426 0xf6, 0x70, 0x24, 0x65, // }
427 0x6d, 0xd6, 0x4a, 0x3e, // }
428 0x02, 0xb8, 0xe0, 0x71, // } HMAC-SHA1 fingerprint
429 0x2e, 0x85, 0xc9, 0xa2, // }
430 0x8c, 0xa8, 0x96, 0x66 // }
431 };
432
433 // Length parameter is changed to 0x38 from 0x58.
434 // AddMessageIntegrity will add MI information and update the length param
435 // accordingly.
436 static const unsigned char kRfc5769SampleRequestWithoutMI[] = {
437 0x00, 0x01, 0x00, 0x38, // Request type and message length
438 0x21, 0x12, 0xa4, 0x42, // Magic cookie
439 0xb7, 0xe7, 0xa7, 0x01, // }
440 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
441 0xfa, 0x87, 0xdf, 0xae, // }
442 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
443 0x53, 0x54, 0x55, 0x4e, // }
444 0x20, 0x74, 0x65, 0x73, // } User-agent...
445 0x74, 0x20, 0x63, 0x6c, // } ...name
446 0x69, 0x65, 0x6e, 0x74, // }
447 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
448 0x6e, 0x00, 0x01, 0xff, // ICE priority value
449 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
450 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
451 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
452 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
453 0x65, 0x76, 0x74, 0x6a, // }
454 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
455 0x59, 0x20, 0x20, 0x20 // }
456 };
457
458 // This HMAC differs from the RFC 5769 SampleRequest message. This differs
459 // because spec uses 0x20 for the padding where as our implementation uses 0.
460 static const unsigned char kCalculatedHmac1[] = {
461 0x79, 0x07, 0xc2, 0xd2, // }
462 0xed, 0xbf, 0xea, 0x48, // }
463 0x0e, 0x4c, 0x76, 0xd8, // } HMAC-SHA1 fingerprint
464 0x29, 0x62, 0xd5, 0xc3, // }
465 0x74, 0x2a, 0xf9, 0xe3 // }
466 };
467
468 // This truncated HMAC differs from kCalculatedHmac1
469 // above since the sum is computed including header
470 // and the header is different since the message is shorter
471 // than when MESSAGE-INTEGRITY is used.
472 static const unsigned char kCalculatedHmac1_32[] = {
473 0xda, 0x39, 0xde, 0x5d, // }
474 };
475
476 // Length parameter is changed to 0x1c from 0x3c.
477 // AddMessageIntegrity will add MI information and update the length param
478 // accordingly.
479 static const unsigned char kRfc5769SampleResponseWithoutMI[] = {
480 0x01, 0x01, 0x00, 0x1c, // Response type and message length
481 0x21, 0x12, 0xa4, 0x42, // Magic cookie
482 0xb7, 0xe7, 0xa7, 0x01, // }
483 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
484 0xfa, 0x87, 0xdf, 0xae, // }
485 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
486 0x74, 0x65, 0x73, 0x74, // }
487 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
488 0x74, 0x6f, 0x72, 0x20, // }
489 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
490 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port
491 0xe1, 0x12, 0xa6, 0x43 // Xor'd mapped IPv4 address
492 };
493
494 // This HMAC differs from the RFC 5769 SampleResponse message. This differs
495 // because spec uses 0x20 for the padding where as our implementation uses 0.
496 static const unsigned char kCalculatedHmac2[] = {
497 0x5d, 0x6b, 0x58, 0xbe, // }
498 0xad, 0x94, 0xe0, 0x7e, // }
499 0xef, 0x0d, 0xfc, 0x12, // } HMAC-SHA1 fingerprint
500 0x82, 0xa2, 0xbd, 0x08, // }
501 0x43, 0x14, 0x10, 0x28 // }
502 };
503
504 // This truncated HMAC differs from kCalculatedHmac2
505 // above since the sum is computed including header
506 // and the header is different since the message is shorter
507 // than when MESSAGE-INTEGRITY is used.
508 static const unsigned char kCalculatedHmac2_32[] = {
509 0xe7, 0x5c, 0xd3, 0x16, // }
510 };
511
512 // clang-format on
513
514 // A transaction ID without the 'magic cookie' portion
515 // pjnat's test programs use this transaction ID a lot.
516 const unsigned char kTestTransactionId1[] = {0x029, 0x01f, 0x0cd, 0x07c,
517 0x0ba, 0x058, 0x0ab, 0x0d7,
518 0x0f2, 0x041, 0x001, 0x000};
519
520 // They use this one sometimes too.
521 const unsigned char kTestTransactionId2[] = {0x0e3, 0x0a9, 0x046, 0x0e1,
522 0x07c, 0x000, 0x0c2, 0x062,
523 0x054, 0x008, 0x001, 0x000};
524
525 const in6_addr kIPv6TestAddress1 = {
526 {{0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, 0x10, 0x00, 0xbe, 0x30, 0x5b, 0xff,
527 0xfe, 0xe5, 0x00, 0xc3}}};
528 const in6_addr kIPv6TestAddress2 = {
529 {{0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, 0x10, 0x12, 0x06, 0x0c, 0xce, 0xff,
530 0xfe, 0x1f, 0x61, 0xa4}}};
531
532 #ifdef WEBRTC_POSIX
533 const in_addr kIPv4TestAddress1 = {0xe64417ac};
534 #elif defined WEBRTC_WIN
535 // Windows in_addr has a union with a uchar[] array first.
536 const in_addr kIPv4TestAddress1 = {{{0x0ac, 0x017, 0x044, 0x0e6}}};
537 #endif
538 const char kTestUserName1[] = "abcdefgh";
539 const char kTestUserName2[] = "abc";
540 const char kTestErrorReason[] = "Unauthorized";
541 const int kTestErrorClass = 4;
542 const int kTestErrorNumber = 1;
543 const int kTestErrorCode = 401;
544
545 const int kTestMessagePort1 = 59977;
546 const int kTestMessagePort2 = 47233;
547 const int kTestMessagePort3 = 56743;
548 const int kTestMessagePort4 = 40444;
549
550 #define ReadStunMessage(X, Y) ReadStunMessageTestCase(X, Y, sizeof(Y));
551
552 // Test that the GetStun*Type and IsStun*Type methods work as expected.
TEST_F(StunTest,MessageTypes)553 TEST_F(StunTest, MessageTypes) {
554 EXPECT_EQ(STUN_BINDING_RESPONSE,
555 GetStunSuccessResponseType(STUN_BINDING_REQUEST));
556 EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE,
557 GetStunErrorResponseType(STUN_BINDING_REQUEST));
558 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_INDICATION));
559 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_RESPONSE));
560 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_ERROR_RESPONSE));
561 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_INDICATION));
562 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_RESPONSE));
563 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_ERROR_RESPONSE));
564
565 int types[] = {STUN_BINDING_REQUEST, STUN_BINDING_INDICATION,
566 STUN_BINDING_RESPONSE, STUN_BINDING_ERROR_RESPONSE};
567 for (size_t i = 0; i < arraysize(types); ++i) {
568 EXPECT_EQ(i == 0U, IsStunRequestType(types[i]));
569 EXPECT_EQ(i == 1U, IsStunIndicationType(types[i]));
570 EXPECT_EQ(i == 2U, IsStunSuccessResponseType(types[i]));
571 EXPECT_EQ(i == 3U, IsStunErrorResponseType(types[i]));
572 EXPECT_EQ(1, types[i] & 0xFEEF);
573 }
574 }
575
TEST_F(StunTest,ReadMessageWithIPv4AddressAttribute)576 TEST_F(StunTest, ReadMessageWithIPv4AddressAttribute) {
577 StunMessage msg;
578 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4MappedAddress);
579 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
580 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
581
582 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
583 rtc::IPAddress test_address(kIPv4TestAddress1);
584 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort4,
585 test_address);
586 }
587
TEST_F(StunTest,ReadMessageWithIPv4XorAddressAttribute)588 TEST_F(StunTest, ReadMessageWithIPv4XorAddressAttribute) {
589 StunMessage msg;
590 StunMessage msg2;
591 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress);
592 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
593 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
594
595 const StunAddressAttribute* addr =
596 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
597 rtc::IPAddress test_address(kIPv4TestAddress1);
598 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort3,
599 test_address);
600 }
601
TEST_F(StunTest,ReadMessageWithIPv6AddressAttribute)602 TEST_F(StunTest, ReadMessageWithIPv6AddressAttribute) {
603 StunMessage msg;
604 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
605 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
606 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
607
608 rtc::IPAddress test_address(kIPv6TestAddress1);
609
610 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
611 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort2,
612 test_address);
613 }
614
TEST_F(StunTest,ReadMessageWithInvalidAddressAttribute)615 TEST_F(StunTest, ReadMessageWithInvalidAddressAttribute) {
616 StunMessage msg;
617 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
618 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
619 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
620
621 rtc::IPAddress test_address(kIPv6TestAddress1);
622
623 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
624 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort2,
625 test_address);
626 }
627
TEST_F(StunTest,ReadMessageWithIPv6XorAddressAttribute)628 TEST_F(StunTest, ReadMessageWithIPv6XorAddressAttribute) {
629 StunMessage msg;
630 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress);
631
632 rtc::IPAddress test_address(kIPv6TestAddress1);
633
634 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
635 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
636
637 const StunAddressAttribute* addr =
638 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
639 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort1,
640 test_address);
641 }
642
643 // Read the RFC5389 fields from the RFC5769 sample STUN request.
TEST_F(StunTest,ReadRfc5769RequestMessage)644 TEST_F(StunTest, ReadRfc5769RequestMessage) {
645 StunMessage msg;
646 size_t size = ReadStunMessage(&msg, kRfc5769SampleRequest);
647 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
648 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
649 kStunTransactionIdLength);
650
651 const StunByteStringAttribute* software =
652 msg.GetByteString(STUN_ATTR_SOFTWARE);
653 ASSERT_TRUE(software != NULL);
654 EXPECT_EQ(kRfc5769SampleMsgClientSoftware, software->string_view());
655
656 const StunByteStringAttribute* username =
657 msg.GetByteString(STUN_ATTR_USERNAME);
658 ASSERT_TRUE(username != NULL);
659 EXPECT_EQ(kRfc5769SampleMsgUsername, username->string_view());
660
661 // Actual M-I value checked in a later test.
662 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
663
664 // Fingerprint checked in a later test, but double-check the value here.
665 const StunUInt32Attribute* fingerprint = msg.GetUInt32(STUN_ATTR_FINGERPRINT);
666 ASSERT_TRUE(fingerprint != NULL);
667 EXPECT_EQ(0xe57a3bcf, fingerprint->value());
668 }
669
670 // Read the RFC5389 fields from the RFC5769 sample STUN response.
TEST_F(StunTest,ReadRfc5769ResponseMessage)671 TEST_F(StunTest, ReadRfc5769ResponseMessage) {
672 StunMessage msg;
673 size_t size = ReadStunMessage(&msg, kRfc5769SampleResponse);
674 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
675 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
676 kStunTransactionIdLength);
677
678 const StunByteStringAttribute* software =
679 msg.GetByteString(STUN_ATTR_SOFTWARE);
680 ASSERT_TRUE(software != NULL);
681 EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->string_view());
682
683 const StunAddressAttribute* mapped_address =
684 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
685 ASSERT_TRUE(mapped_address != NULL);
686 EXPECT_EQ(kRfc5769SampleMsgMappedAddress, mapped_address->GetAddress());
687
688 // Actual M-I and fingerprint checked in later tests.
689 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
690 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
691 }
692
693 // Read the RFC5389 fields from the RFC5769 sample STUN response for IPv6.
TEST_F(StunTest,ReadRfc5769ResponseMessageIPv6)694 TEST_F(StunTest, ReadRfc5769ResponseMessageIPv6) {
695 StunMessage msg;
696 size_t size = ReadStunMessage(&msg, kRfc5769SampleResponseIPv6);
697 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
698 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
699 kStunTransactionIdLength);
700
701 const StunByteStringAttribute* software =
702 msg.GetByteString(STUN_ATTR_SOFTWARE);
703 ASSERT_TRUE(software != NULL);
704 EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->string_view());
705
706 const StunAddressAttribute* mapped_address =
707 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
708 ASSERT_TRUE(mapped_address != NULL);
709 EXPECT_EQ(kRfc5769SampleMsgIPv6MappedAddress, mapped_address->GetAddress());
710
711 // Actual M-I and fingerprint checked in later tests.
712 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
713 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
714 }
715
716 // Read the RFC5389 fields from the RFC5769 sample STUN response with auth.
TEST_F(StunTest,ReadRfc5769RequestMessageLongTermAuth)717 TEST_F(StunTest, ReadRfc5769RequestMessageLongTermAuth) {
718 StunMessage msg;
719 size_t size = ReadStunMessage(&msg, kRfc5769SampleRequestLongTermAuth);
720 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
721 CheckStunTransactionID(msg, kRfc5769SampleMsgWithAuthTransactionId,
722 kStunTransactionIdLength);
723
724 const StunByteStringAttribute* username =
725 msg.GetByteString(STUN_ATTR_USERNAME);
726 ASSERT_TRUE(username != NULL);
727 EXPECT_EQ(kRfc5769SampleMsgWithAuthUsername, username->string_view());
728
729 const StunByteStringAttribute* nonce = msg.GetByteString(STUN_ATTR_NONCE);
730 ASSERT_TRUE(nonce != NULL);
731 EXPECT_EQ(kRfc5769SampleMsgWithAuthNonce, nonce->string_view());
732
733 const StunByteStringAttribute* realm = msg.GetByteString(STUN_ATTR_REALM);
734 ASSERT_TRUE(realm != NULL);
735 EXPECT_EQ(kRfc5769SampleMsgWithAuthRealm, realm->string_view());
736
737 // No fingerprint, actual M-I checked in later tests.
738 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
739 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) == NULL);
740 }
741
742 // The RFC3489 packet in this test is the same as
743 // kStunMessageWithIPv4MappedAddress, but with a different value where the
744 // magic cookie was.
TEST_F(StunTest,ReadLegacyMessage)745 TEST_F(StunTest, ReadLegacyMessage) {
746 unsigned char rfc3489_packet[sizeof(kStunMessageWithIPv4MappedAddress)];
747 memcpy(rfc3489_packet, kStunMessageWithIPv4MappedAddress,
748 sizeof(kStunMessageWithIPv4MappedAddress));
749 // Overwrite the magic cookie here.
750 memcpy(&rfc3489_packet[4], "ABCD", 4);
751
752 StunMessage msg;
753 size_t size = ReadStunMessage(&msg, rfc3489_packet);
754 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
755 CheckStunTransactionID(msg, &rfc3489_packet[4], kStunTransactionIdLength + 4);
756
757 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
758 rtc::IPAddress test_address(kIPv4TestAddress1);
759 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort4,
760 test_address);
761 }
762
TEST_F(StunTest,SetIPv6XorAddressAttributeOwner)763 TEST_F(StunTest, SetIPv6XorAddressAttributeOwner) {
764 StunMessage msg;
765 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress);
766
767 rtc::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, kTestMessagePort1,
775 test_address);
776
777 // Owner with a different transaction ID.
778 StunMessage msg2(STUN_INVALID_MESSAGE_TYPE, "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 rtc::ByteBufferWriter correct_buf;
787 rtc::ByteBufferWriter 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,
792 memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
793 // And when reading a known good value, the address should be wrong.
794 rtc::ByteBufferReader read_buf(correct_buf);
795 addr2.Read(&read_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.Clear();
803 EXPECT_FALSE(addr2.Write(&wrong_buf));
804 ASSERT_EQ(0U, wrong_buf.Length());
805 }
806
TEST_F(StunTest,SetIPv4XorAddressAttributeOwner)807 TEST_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 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress);
813
814 rtc::IPAddress test_address(kIPv4TestAddress1);
815
816 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
817 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
818
819 const StunAddressAttribute* addr =
820 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
821 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort3,
822 test_address);
823
824 // Owner with a different transaction ID.
825 StunMessage msg2(STUN_INVALID_MESSAGE_TYPE, "ABCDABCDABCD");
826 StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL);
827 addr2.SetIP(addr->ipaddr());
828 addr2.SetPort(addr->port());
829 addr2.SetOwner(&msg2);
830 // The internal IP address shouldn't change.
831 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
832
833 rtc::ByteBufferWriter correct_buf;
834 rtc::ByteBufferWriter wrong_buf;
835 EXPECT_TRUE(addr->Write(&correct_buf));
836 EXPECT_TRUE(addr2.Write(&wrong_buf));
837 // The same address data should be written.
838 ASSERT_EQ(0,
839 memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
840 // And an attribute should be able to un-XOR an address belonging to a message
841 // with a different transaction ID.
842 rtc::ByteBufferReader read_buf(correct_buf);
843 EXPECT_TRUE(addr2.Read(&read_buf));
844 ASSERT_EQ(addr->ipaddr(), addr2.ipaddr());
845
846 // However, no owner is still an error, should fail and write nothing.
847 addr2.SetOwner(NULL);
848 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
849 wrong_buf.Clear();
850 EXPECT_FALSE(addr2.Write(&wrong_buf));
851 }
852
TEST_F(StunTest,CreateIPv6AddressAttribute)853 TEST_F(StunTest, CreateIPv6AddressAttribute) {
854 rtc::IPAddress test_ip(kIPv6TestAddress2);
855
856 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
857 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
858 addr->SetAddress(test_addr);
859
860 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6, kTestMessagePort2,
861 test_ip);
862 }
863
TEST_F(StunTest,CreateIPv4AddressAttribute)864 TEST_F(StunTest, CreateIPv4AddressAttribute) {
865 struct in_addr test_in_addr;
866 test_in_addr.s_addr = 0xBEB0B0BE;
867 rtc::IPAddress test_ip(test_in_addr);
868
869 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
870 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
871 addr->SetAddress(test_addr);
872
873 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV4, kTestMessagePort2,
874 test_ip);
875 }
876
877 // Test that we don't care what order we set the parts of an address
TEST_F(StunTest,CreateAddressInArbitraryOrder)878 TEST_F(StunTest, CreateAddressInArbitraryOrder) {
879 auto addr = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
880 // Port first
881 addr->SetPort(kTestMessagePort1);
882 addr->SetIP(rtc::IPAddress(kIPv4TestAddress1));
883 ASSERT_EQ(kTestMessagePort1, addr->port());
884 ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr->ipaddr());
885
886 auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
887 // IP first
888 addr2->SetIP(rtc::IPAddress(kIPv4TestAddress1));
889 addr2->SetPort(kTestMessagePort2);
890 ASSERT_EQ(kTestMessagePort2, addr2->port());
891 ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr2->ipaddr());
892 }
893
TEST_F(StunTest,WriteMessageWithIPv6AddressAttribute)894 TEST_F(StunTest, WriteMessageWithIPv6AddressAttribute) {
895 size_t size = sizeof(kStunMessageWithIPv6MappedAddress);
896
897 rtc::IPAddress test_ip(kIPv6TestAddress1);
898
899 StunMessage msg(
900 STUN_BINDING_REQUEST,
901 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
902 kStunTransactionIdLength));
903 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
904
905 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
906 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
907 addr->SetAddress(test_addr);
908 msg.AddAttribute(std::move(addr));
909
910 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
911
912 rtc::ByteBufferWriter out;
913 EXPECT_TRUE(msg.Write(&out));
914 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6MappedAddress));
915 int len1 = static_cast<int>(out.Length());
916 rtc::ByteBufferReader read_buf(out);
917 std::string bytes;
918 read_buf.ReadString(&bytes, len1);
919 ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv6MappedAddress, len1));
920 }
921
TEST_F(StunTest,WriteMessageWithIPv4AddressAttribute)922 TEST_F(StunTest, WriteMessageWithIPv4AddressAttribute) {
923 size_t size = sizeof(kStunMessageWithIPv4MappedAddress);
924
925 rtc::IPAddress test_ip(kIPv4TestAddress1);
926
927 StunMessage msg(
928 STUN_BINDING_RESPONSE,
929 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
930 kStunTransactionIdLength));
931 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
932
933 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
934 rtc::SocketAddress test_addr(test_ip, kTestMessagePort4);
935 addr->SetAddress(test_addr);
936 msg.AddAttribute(std::move(addr));
937
938 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
939
940 rtc::ByteBufferWriter out;
941 EXPECT_TRUE(msg.Write(&out));
942 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4MappedAddress));
943 int len1 = static_cast<int>(out.Length());
944 rtc::ByteBufferReader read_buf(out);
945 std::string bytes;
946 read_buf.ReadString(&bytes, len1);
947 ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv4MappedAddress, len1));
948 }
949
TEST_F(StunTest,WriteMessageWithIPv6XorAddressAttribute)950 TEST_F(StunTest, WriteMessageWithIPv6XorAddressAttribute) {
951 size_t size = sizeof(kStunMessageWithIPv6XorMappedAddress);
952
953 rtc::IPAddress test_ip(kIPv6TestAddress1);
954
955 StunMessage msg(
956 STUN_BINDING_RESPONSE,
957 std::string(reinterpret_cast<const char*>(kTestTransactionId2),
958 kStunTransactionIdLength));
959 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
960
961 auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
962 rtc::SocketAddress test_addr(test_ip, kTestMessagePort1);
963 addr->SetAddress(test_addr);
964 msg.AddAttribute(std::move(addr));
965
966 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
967
968 rtc::ByteBufferWriter out;
969 EXPECT_TRUE(msg.Write(&out));
970 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6XorMappedAddress));
971 int len1 = static_cast<int>(out.Length());
972 rtc::ByteBufferReader read_buf(out);
973 std::string bytes;
974 read_buf.ReadString(&bytes, len1);
975 ASSERT_EQ(0,
976 memcmp(bytes.c_str(), kStunMessageWithIPv6XorMappedAddress, len1));
977 }
978
TEST_F(StunTest,WriteMessageWithIPv4XoreAddressAttribute)979 TEST_F(StunTest, WriteMessageWithIPv4XoreAddressAttribute) {
980 size_t size = sizeof(kStunMessageWithIPv4XorMappedAddress);
981
982 rtc::IPAddress test_ip(kIPv4TestAddress1);
983
984 StunMessage msg(
985 STUN_BINDING_RESPONSE,
986 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
987 kStunTransactionIdLength));
988 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
989
990 auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
991 rtc::SocketAddress test_addr(test_ip, kTestMessagePort3);
992 addr->SetAddress(test_addr);
993 msg.AddAttribute(std::move(addr));
994
995 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
996
997 rtc::ByteBufferWriter out;
998 EXPECT_TRUE(msg.Write(&out));
999 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4XorMappedAddress));
1000 int len1 = static_cast<int>(out.Length());
1001 rtc::ByteBufferReader read_buf(out);
1002 std::string bytes;
1003 read_buf.ReadString(&bytes, len1);
1004 ASSERT_EQ(0,
1005 memcmp(bytes.c_str(), kStunMessageWithIPv4XorMappedAddress, len1));
1006 }
1007
TEST_F(StunTest,ReadByteStringAttribute)1008 TEST_F(StunTest, ReadByteStringAttribute) {
1009 StunMessage msg;
1010 size_t size = ReadStunMessage(&msg, kStunMessageWithByteStringAttribute);
1011
1012 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1013 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
1014 const StunByteStringAttribute* username =
1015 msg.GetByteString(STUN_ATTR_USERNAME);
1016 ASSERT_TRUE(username != NULL);
1017 EXPECT_EQ(kTestUserName1, username->string_view());
1018 }
1019
TEST_F(StunTest,ReadPaddedByteStringAttribute)1020 TEST_F(StunTest, ReadPaddedByteStringAttribute) {
1021 StunMessage msg;
1022 size_t size =
1023 ReadStunMessage(&msg, kStunMessageWithPaddedByteStringAttribute);
1024 ASSERT_NE(0U, size);
1025 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1026 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
1027 const StunByteStringAttribute* username =
1028 msg.GetByteString(STUN_ATTR_USERNAME);
1029 ASSERT_TRUE(username != NULL);
1030 EXPECT_EQ(kTestUserName2, username->string_view());
1031 }
1032
TEST_F(StunTest,ReadErrorCodeAttribute)1033 TEST_F(StunTest, ReadErrorCodeAttribute) {
1034 StunMessage msg;
1035 size_t size = ReadStunMessage(&msg, kStunMessageWithErrorAttribute);
1036
1037 CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, size);
1038 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
1039 const StunErrorCodeAttribute* errorcode = msg.GetErrorCode();
1040 ASSERT_TRUE(errorcode != NULL);
1041 EXPECT_EQ(kTestErrorClass, errorcode->eclass());
1042 EXPECT_EQ(kTestErrorNumber, errorcode->number());
1043 EXPECT_EQ(kTestErrorReason, errorcode->reason());
1044 EXPECT_EQ(kTestErrorCode, errorcode->code());
1045 EXPECT_EQ(kTestErrorCode, msg.GetErrorCodeValue());
1046 }
1047
1048 // Test that GetErrorCodeValue returns STUN_ERROR_GLOBAL_FAILURE if the message
1049 // in question doesn't have an error code attribute, rather than crashing.
TEST_F(StunTest,GetErrorCodeValueWithNoErrorAttribute)1050 TEST_F(StunTest, GetErrorCodeValueWithNoErrorAttribute) {
1051 StunMessage msg;
1052 ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
1053 EXPECT_EQ(STUN_ERROR_GLOBAL_FAILURE, msg.GetErrorCodeValue());
1054 }
1055
TEST_F(StunTest,ReadMessageWithAUInt16ListAttribute)1056 TEST_F(StunTest, ReadMessageWithAUInt16ListAttribute) {
1057 StunMessage msg;
1058 size_t size = ReadStunMessage(&msg, kStunMessageWithUInt16ListAttribute);
1059 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1060 const StunUInt16ListAttribute* types = msg.GetUnknownAttributes();
1061 ASSERT_TRUE(types != NULL);
1062 EXPECT_EQ(3U, types->Size());
1063 EXPECT_EQ(0x1U, types->GetType(0));
1064 EXPECT_EQ(0x1000U, types->GetType(1));
1065 EXPECT_EQ(0xAB0CU, types->GetType(2));
1066 }
1067
TEST_F(StunTest,ReadMessageWithAnUnknownAttribute)1068 TEST_F(StunTest, ReadMessageWithAnUnknownAttribute) {
1069 StunMessage msg;
1070 size_t size = ReadStunMessage(&msg, kStunMessageWithUnknownAttribute);
1071 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1072
1073 // Parsing should have succeeded and there should be a USERNAME attribute
1074 const StunByteStringAttribute* username =
1075 msg.GetByteString(STUN_ATTR_USERNAME);
1076 ASSERT_TRUE(username != NULL);
1077 EXPECT_EQ(kTestUserName2, username->string_view());
1078 }
1079
TEST_F(StunTest,WriteMessageWithAnErrorCodeAttribute)1080 TEST_F(StunTest, WriteMessageWithAnErrorCodeAttribute) {
1081 size_t size = sizeof(kStunMessageWithErrorAttribute);
1082
1083 StunMessage msg(
1084 STUN_BINDING_ERROR_RESPONSE,
1085 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
1086 kStunTransactionIdLength));
1087 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
1088 auto errorcode = StunAttribute::CreateErrorCode();
1089 errorcode->SetCode(kTestErrorCode);
1090 errorcode->SetReason(kTestErrorReason);
1091 msg.AddAttribute(std::move(errorcode));
1092 CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, (size - 20));
1093
1094 rtc::ByteBufferWriter out;
1095 EXPECT_TRUE(msg.Write(&out));
1096 ASSERT_EQ(size, out.Length());
1097 // No padding.
1098 ASSERT_EQ(0, memcmp(out.Data(), kStunMessageWithErrorAttribute, size));
1099 }
1100
TEST_F(StunTest,WriteMessageWithAUInt16ListAttribute)1101 TEST_F(StunTest, WriteMessageWithAUInt16ListAttribute) {
1102 size_t size = sizeof(kStunMessageWithUInt16ListAttribute);
1103
1104 StunMessage msg(
1105 STUN_BINDING_REQUEST,
1106 std::string(reinterpret_cast<const char*>(kTestTransactionId2),
1107 kStunTransactionIdLength));
1108 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
1109 auto list = StunAttribute::CreateUnknownAttributes();
1110 list->AddType(0x1U);
1111 list->AddType(0x1000U);
1112 list->AddType(0xAB0CU);
1113 msg.AddAttribute(std::move(list));
1114 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
1115
1116 rtc::ByteBufferWriter out;
1117 EXPECT_TRUE(msg.Write(&out));
1118 ASSERT_EQ(size, out.Length());
1119 // Check everything up to the padding.
1120 ASSERT_EQ(0,
1121 memcmp(out.Data(), kStunMessageWithUInt16ListAttribute, size - 2));
1122 }
1123
1124 // Test that we fail to read messages with invalid lengths.
CheckFailureToRead(const unsigned char * testcase,size_t length)1125 void CheckFailureToRead(const unsigned char* testcase, size_t length) {
1126 StunMessage msg;
1127 const char* input = reinterpret_cast<const char*>(testcase);
1128 rtc::ByteBufferReader buf(input, length);
1129 ASSERT_FALSE(msg.Read(&buf));
1130 }
1131
TEST_F(StunTest,FailToReadInvalidMessages)1132 TEST_F(StunTest, FailToReadInvalidMessages) {
1133 CheckFailureToRead(kStunMessageWithZeroLength,
1134 kRealLengthOfInvalidLengthTestCases);
1135 CheckFailureToRead(kStunMessageWithSmallLength,
1136 kRealLengthOfInvalidLengthTestCases);
1137 CheckFailureToRead(kStunMessageWithExcessLength,
1138 kRealLengthOfInvalidLengthTestCases);
1139 }
1140
1141 // Test that we properly fail to read a non-STUN message.
TEST_F(StunTest,FailToReadRtcpPacket)1142 TEST_F(StunTest, FailToReadRtcpPacket) {
1143 CheckFailureToRead(kRtcpPacket, sizeof(kRtcpPacket));
1144 }
1145
1146 // Check our STUN message validation code against the RFC5769 test messages.
TEST_F(StunTest,ValidateMessageIntegrity)1147 TEST_F(StunTest, ValidateMessageIntegrity) {
1148 // Try the messages from RFC 5769.
1149 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
1150 reinterpret_cast<const char*>(kRfc5769SampleRequest),
1151 sizeof(kRfc5769SampleRequest), kRfc5769SampleMsgPassword));
1152 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
1153 reinterpret_cast<const char*>(kRfc5769SampleRequest),
1154 sizeof(kRfc5769SampleRequest), "InvalidPassword"));
1155
1156 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
1157 reinterpret_cast<const char*>(kRfc5769SampleResponse),
1158 sizeof(kRfc5769SampleResponse), kRfc5769SampleMsgPassword));
1159 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
1160 reinterpret_cast<const char*>(kRfc5769SampleResponse),
1161 sizeof(kRfc5769SampleResponse), "InvalidPassword"));
1162
1163 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
1164 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
1165 sizeof(kRfc5769SampleResponseIPv6), kRfc5769SampleMsgPassword));
1166 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
1167 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
1168 sizeof(kRfc5769SampleResponseIPv6), "InvalidPassword"));
1169
1170 // We first need to compute the key for the long-term authentication HMAC.
1171 std::string key;
1172 ComputeStunCredentialHash(kRfc5769SampleMsgWithAuthUsername,
1173 kRfc5769SampleMsgWithAuthRealm,
1174 kRfc5769SampleMsgWithAuthPassword, &key);
1175 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
1176 reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth),
1177 sizeof(kRfc5769SampleRequestLongTermAuth), key));
1178 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
1179 reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth),
1180 sizeof(kRfc5769SampleRequestLongTermAuth), "InvalidPassword"));
1181
1182 // Try some edge cases.
1183 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
1184 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1185 sizeof(kStunMessageWithZeroLength), kRfc5769SampleMsgPassword));
1186 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
1187 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1188 sizeof(kStunMessageWithExcessLength), kRfc5769SampleMsgPassword));
1189 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
1190 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1191 sizeof(kStunMessageWithSmallLength), kRfc5769SampleMsgPassword));
1192
1193 // Again, but with the lengths matching what is claimed in the headers.
1194 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
1195 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1196 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithZeroLength[2]),
1197 kRfc5769SampleMsgPassword));
1198 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
1199 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1200 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithExcessLength[2]),
1201 kRfc5769SampleMsgPassword));
1202 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
1203 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1204 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithSmallLength[2]),
1205 kRfc5769SampleMsgPassword));
1206
1207 // Check that a too-short HMAC doesn't cause buffer overflow.
1208 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
1209 reinterpret_cast<const char*>(kStunMessageWithBadHmacAtEnd),
1210 sizeof(kStunMessageWithBadHmacAtEnd), kRfc5769SampleMsgPassword));
1211
1212 // Test that munging a single bit anywhere in the message causes the
1213 // message-integrity check to fail, unless it is after the M-I attribute.
1214 char buf[sizeof(kRfc5769SampleRequest)];
1215 memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest));
1216 for (size_t i = 0; i < sizeof(buf); ++i) {
1217 buf[i] ^= 0x01;
1218 if (i > 0)
1219 buf[i - 1] ^= 0x01;
1220 EXPECT_EQ(i >= sizeof(buf) - 8,
1221 StunMessage::ValidateMessageIntegrityForTesting(
1222 buf, sizeof(buf), kRfc5769SampleMsgPassword));
1223 }
1224 }
1225
1226 // Validate that we generate correct MESSAGE-INTEGRITY attributes.
1227 // Note the use of IceMessage instead of StunMessage; this is necessary because
1228 // the RFC5769 test messages used include attributes not found in basic STUN.
TEST_F(StunTest,AddMessageIntegrity)1229 TEST_F(StunTest, AddMessageIntegrity) {
1230 IceMessage msg;
1231 rtc::ByteBufferReader buf(
1232 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1233 sizeof(kRfc5769SampleRequestWithoutMI));
1234 EXPECT_TRUE(msg.Read(&buf));
1235 EXPECT_TRUE(msg.AddMessageIntegrity(kRfc5769SampleMsgPassword));
1236 const StunByteStringAttribute* mi_attr =
1237 msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
1238 EXPECT_EQ(20U, mi_attr->length());
1239 EXPECT_EQ(
1240 0, memcmp(mi_attr->bytes(), kCalculatedHmac1, sizeof(kCalculatedHmac1)));
1241
1242 rtc::ByteBufferWriter buf1;
1243 EXPECT_TRUE(msg.Write(&buf1));
1244 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
1245 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(),
1246 kRfc5769SampleMsgPassword));
1247
1248 IceMessage msg2;
1249 rtc::ByteBufferReader buf2(
1250 reinterpret_cast<const char*>(kRfc5769SampleResponseWithoutMI),
1251 sizeof(kRfc5769SampleResponseWithoutMI));
1252 EXPECT_TRUE(msg2.Read(&buf2));
1253 EXPECT_TRUE(msg2.AddMessageIntegrity(kRfc5769SampleMsgPassword));
1254 const StunByteStringAttribute* mi_attr2 =
1255 msg2.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
1256 EXPECT_EQ(20U, mi_attr2->length());
1257 EXPECT_EQ(
1258 0, memcmp(mi_attr2->bytes(), kCalculatedHmac2, sizeof(kCalculatedHmac2)));
1259
1260 rtc::ByteBufferWriter buf3;
1261 EXPECT_TRUE(msg2.Write(&buf3));
1262 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
1263 reinterpret_cast<const char*>(buf3.Data()), buf3.Length(),
1264 kRfc5769SampleMsgPassword));
1265 }
1266
1267 // Check our STUN message validation code against the RFC5769 test messages.
TEST_F(StunTest,ValidateMessageIntegrity32)1268 TEST_F(StunTest, ValidateMessageIntegrity32) {
1269 // Try the messages from RFC 5769.
1270 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32ForTesting(
1271 reinterpret_cast<const char*>(kSampleRequestMI32),
1272 sizeof(kSampleRequestMI32), kRfc5769SampleMsgPassword));
1273 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
1274 reinterpret_cast<const char*>(kSampleRequestMI32),
1275 sizeof(kSampleRequestMI32), "InvalidPassword"));
1276
1277 // Try some edge cases.
1278 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
1279 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1280 sizeof(kStunMessageWithZeroLength), kRfc5769SampleMsgPassword));
1281 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
1282 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1283 sizeof(kStunMessageWithExcessLength), kRfc5769SampleMsgPassword));
1284 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
1285 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1286 sizeof(kStunMessageWithSmallLength), kRfc5769SampleMsgPassword));
1287
1288 // Again, but with the lengths matching what is claimed in the headers.
1289 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
1290 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1291 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithZeroLength[2]),
1292 kRfc5769SampleMsgPassword));
1293 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
1294 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1295 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithExcessLength[2]),
1296 kRfc5769SampleMsgPassword));
1297 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
1298 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1299 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithSmallLength[2]),
1300 kRfc5769SampleMsgPassword));
1301
1302 // Check that a too-short HMAC doesn't cause buffer overflow.
1303 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
1304 reinterpret_cast<const char*>(kStunMessageWithBadHmacAtEnd),
1305 sizeof(kStunMessageWithBadHmacAtEnd), kRfc5769SampleMsgPassword));
1306
1307 // Test that munging a single bit anywhere in the message causes the
1308 // message-integrity check to fail, unless it is after the M-I attribute.
1309 char buf[sizeof(kSampleRequestMI32)];
1310 memcpy(buf, kSampleRequestMI32, sizeof(kSampleRequestMI32));
1311 for (size_t i = 0; i < sizeof(buf); ++i) {
1312 buf[i] ^= 0x01;
1313 if (i > 0)
1314 buf[i - 1] ^= 0x01;
1315 EXPECT_EQ(i >= sizeof(buf) - 8,
1316 StunMessage::ValidateMessageIntegrity32ForTesting(
1317 buf, sizeof(buf), kRfc5769SampleMsgPassword));
1318 }
1319 }
1320
1321 // Validate that we generate correct MESSAGE-INTEGRITY-32 attributes.
TEST_F(StunTest,AddMessageIntegrity32)1322 TEST_F(StunTest, AddMessageIntegrity32) {
1323 IceMessage msg;
1324 rtc::ByteBufferReader buf(
1325 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1326 sizeof(kRfc5769SampleRequestWithoutMI));
1327 EXPECT_TRUE(msg.Read(&buf));
1328 EXPECT_TRUE(msg.AddMessageIntegrity32(kRfc5769SampleMsgPassword));
1329 const StunByteStringAttribute* mi_attr =
1330 msg.GetByteString(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32);
1331 EXPECT_EQ(4U, mi_attr->length());
1332 EXPECT_EQ(0, memcmp(mi_attr->bytes(), kCalculatedHmac1_32,
1333 sizeof(kCalculatedHmac1_32)));
1334
1335 rtc::ByteBufferWriter buf1;
1336 EXPECT_TRUE(msg.Write(&buf1));
1337 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32ForTesting(
1338 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(),
1339 kRfc5769SampleMsgPassword));
1340
1341 IceMessage msg2;
1342 rtc::ByteBufferReader buf2(
1343 reinterpret_cast<const char*>(kRfc5769SampleResponseWithoutMI),
1344 sizeof(kRfc5769SampleResponseWithoutMI));
1345 EXPECT_TRUE(msg2.Read(&buf2));
1346 EXPECT_TRUE(msg2.AddMessageIntegrity32(kRfc5769SampleMsgPassword));
1347 const StunByteStringAttribute* mi_attr2 =
1348 msg2.GetByteString(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32);
1349 EXPECT_EQ(4U, mi_attr2->length());
1350 EXPECT_EQ(0, memcmp(mi_attr2->bytes(), kCalculatedHmac2_32,
1351 sizeof(kCalculatedHmac2_32)));
1352
1353 rtc::ByteBufferWriter buf3;
1354 EXPECT_TRUE(msg2.Write(&buf3));
1355 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32ForTesting(
1356 reinterpret_cast<const char*>(buf3.Data()), buf3.Length(),
1357 kRfc5769SampleMsgPassword));
1358 }
1359
1360 // Validate that the message validates if both MESSAGE-INTEGRITY-32 and
1361 // MESSAGE-INTEGRITY are present in the message.
1362 // This is not expected to be used, but is not forbidden.
TEST_F(StunTest,AddMessageIntegrity32AndMessageIntegrity)1363 TEST_F(StunTest, AddMessageIntegrity32AndMessageIntegrity) {
1364 IceMessage msg;
1365 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1366 attr->CopyBytes("keso", sizeof("keso"));
1367 msg.AddAttribute(std::move(attr));
1368 msg.AddMessageIntegrity32("password1");
1369 msg.AddMessageIntegrity("password2");
1370
1371 rtc::ByteBufferWriter buf1;
1372 EXPECT_TRUE(msg.Write(&buf1));
1373 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32ForTesting(
1374 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password1"));
1375 EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting(
1376 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password2"));
1377
1378 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting(
1379 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password2"));
1380 EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting(
1381 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password1"));
1382 }
1383
1384 // Check our STUN message validation code against the RFC5769 test messages.
TEST_F(StunTest,ValidateFingerprint)1385 TEST_F(StunTest, ValidateFingerprint) {
1386 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1387 reinterpret_cast<const char*>(kRfc5769SampleRequest),
1388 sizeof(kRfc5769SampleRequest)));
1389 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1390 reinterpret_cast<const char*>(kRfc5769SampleResponse),
1391 sizeof(kRfc5769SampleResponse)));
1392 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1393 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
1394 sizeof(kRfc5769SampleResponseIPv6)));
1395
1396 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1397 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1398 sizeof(kStunMessageWithZeroLength)));
1399 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1400 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1401 sizeof(kStunMessageWithExcessLength)));
1402 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1403 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1404 sizeof(kStunMessageWithSmallLength)));
1405
1406 // Test that munging a single bit anywhere in the message causes the
1407 // fingerprint check to fail.
1408 char buf[sizeof(kRfc5769SampleRequest)];
1409 memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest));
1410 for (size_t i = 0; i < sizeof(buf); ++i) {
1411 buf[i] ^= 0x01;
1412 if (i > 0)
1413 buf[i - 1] ^= 0x01;
1414 EXPECT_FALSE(StunMessage::ValidateFingerprint(buf, sizeof(buf)));
1415 }
1416 // Put them all back to normal and the check should pass again.
1417 buf[sizeof(buf) - 1] ^= 0x01;
1418 EXPECT_TRUE(StunMessage::ValidateFingerprint(buf, sizeof(buf)));
1419 }
1420
TEST_F(StunTest,AddFingerprint)1421 TEST_F(StunTest, AddFingerprint) {
1422 IceMessage msg;
1423 rtc::ByteBufferReader buf(
1424 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1425 sizeof(kRfc5769SampleRequestWithoutMI));
1426 EXPECT_TRUE(msg.Read(&buf));
1427 EXPECT_TRUE(msg.AddFingerprint());
1428
1429 rtc::ByteBufferWriter buf1;
1430 EXPECT_TRUE(msg.Write(&buf1));
1431 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1432 reinterpret_cast<const char*>(buf1.Data()), buf1.Length()));
1433 }
1434
1435 // Sample "GTURN" relay message.
1436 // clang-format off
1437 // clang formatting doesn't respect inline comments.
1438 static const unsigned char kRelayMessage[] = {
1439 0x00, 0x01, 0x00, 88, // message header
1440 0x21, 0x12, 0xA4, 0x42, // magic cookie
1441 '0', '1', '2', '3', // transaction id
1442 '4', '5', '6', '7',
1443 '8', '9', 'a', 'b',
1444 0x00, 0x01, 0x00, 8, // mapped address
1445 0x00, 0x01, 0x00, 13,
1446 0x00, 0x00, 0x00, 17,
1447 0x00, 0x06, 0x00, 12, // username
1448 'a', 'b', 'c', 'd',
1449 'e', 'f', 'g', 'h',
1450 'i', 'j', 'k', 'l',
1451 0x00, 0x0d, 0x00, 4, // lifetime
1452 0x00, 0x00, 0x00, 11,
1453 0x00, 0x0f, 0x00, 4, // magic cookie
1454 0x72, 0xc6, 0x4b, 0xc6,
1455 0x00, 0x10, 0x00, 4, // bandwidth
1456 0x00, 0x00, 0x00, 6,
1457 0x00, 0x11, 0x00, 8, // destination address
1458 0x00, 0x01, 0x00, 13,
1459 0x00, 0x00, 0x00, 17,
1460 0x00, 0x12, 0x00, 8, // source address 2
1461 0x00, 0x01, 0x00, 13,
1462 0x00, 0x00, 0x00, 17,
1463 0x00, 0x13, 0x00, 7, // data
1464 'a', 'b', 'c', 'd',
1465 'e', 'f', 'g', 0 // DATA must be padded per rfc5766.
1466 };
1467 // clang-format on
1468
1469 // Test that we can read the GTURN-specific fields.
TEST_F(StunTest,ReadRelayMessage)1470 TEST_F(StunTest, ReadRelayMessage) {
1471 RelayMessage msg;
1472
1473 const char* input = reinterpret_cast<const char*>(kRelayMessage);
1474 size_t size = sizeof(kRelayMessage);
1475 rtc::ByteBufferReader buf(input, size);
1476 EXPECT_TRUE(msg.Read(&buf));
1477
1478 EXPECT_EQ(STUN_BINDING_REQUEST, msg.type());
1479 EXPECT_EQ(size - 20, msg.length());
1480 EXPECT_EQ("0123456789ab", msg.transaction_id());
1481
1482 RelayMessage msg2(STUN_BINDING_REQUEST, "0123456789ab");
1483
1484 in_addr legacy_in_addr;
1485 legacy_in_addr.s_addr = htonl(17U);
1486 rtc::IPAddress legacy_ip(legacy_in_addr);
1487
1488 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
1489 ASSERT_TRUE(addr != NULL);
1490 EXPECT_EQ(1, addr->family());
1491 EXPECT_EQ(13, addr->port());
1492 EXPECT_EQ(legacy_ip, addr->ipaddr());
1493
1494 auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
1495 addr2->SetPort(13);
1496 addr2->SetIP(legacy_ip);
1497 msg2.AddAttribute(std::move(addr2));
1498
1499 const StunByteStringAttribute* bytes = msg.GetByteString(STUN_ATTR_USERNAME);
1500 ASSERT_TRUE(bytes != NULL);
1501 EXPECT_EQ(12U, bytes->length());
1502 EXPECT_EQ("abcdefghijkl", bytes->string_view());
1503
1504 auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1505 bytes2->CopyBytes("abcdefghijkl");
1506 msg2.AddAttribute(std::move(bytes2));
1507
1508 const StunUInt32Attribute* uval = msg.GetUInt32(STUN_ATTR_LIFETIME);
1509 ASSERT_TRUE(uval != NULL);
1510 EXPECT_EQ(11U, uval->value());
1511
1512 auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
1513 uval2->SetValue(11);
1514 msg2.AddAttribute(std::move(uval2));
1515
1516 bytes = msg.GetByteString(STUN_ATTR_MAGIC_COOKIE);
1517 ASSERT_TRUE(bytes != NULL);
1518 EXPECT_EQ(4U, bytes->length());
1519 EXPECT_EQ(0, memcmp(bytes->bytes(), TURN_MAGIC_COOKIE_VALUE,
1520 sizeof(TURN_MAGIC_COOKIE_VALUE)));
1521
1522 bytes2 = StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
1523 bytes2->CopyBytes(reinterpret_cast<const char*>(TURN_MAGIC_COOKIE_VALUE),
1524 sizeof(TURN_MAGIC_COOKIE_VALUE));
1525 msg2.AddAttribute(std::move(bytes2));
1526
1527 uval = msg.GetUInt32(STUN_ATTR_BANDWIDTH);
1528 ASSERT_TRUE(uval != NULL);
1529 EXPECT_EQ(6U, uval->value());
1530
1531 uval2 = StunAttribute::CreateUInt32(STUN_ATTR_BANDWIDTH);
1532 uval2->SetValue(6);
1533 msg2.AddAttribute(std::move(uval2));
1534
1535 addr = msg.GetAddress(STUN_ATTR_DESTINATION_ADDRESS);
1536 ASSERT_TRUE(addr != NULL);
1537 EXPECT_EQ(1, addr->family());
1538 EXPECT_EQ(13, addr->port());
1539 EXPECT_EQ(legacy_ip, addr->ipaddr());
1540
1541 addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
1542 addr2->SetPort(13);
1543 addr2->SetIP(legacy_ip);
1544 msg2.AddAttribute(std::move(addr2));
1545
1546 addr = msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2);
1547 ASSERT_TRUE(addr != NULL);
1548 EXPECT_EQ(1, addr->family());
1549 EXPECT_EQ(13, addr->port());
1550 EXPECT_EQ(legacy_ip, addr->ipaddr());
1551
1552 addr2 = StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2);
1553 addr2->SetPort(13);
1554 addr2->SetIP(legacy_ip);
1555 msg2.AddAttribute(std::move(addr2));
1556
1557 bytes = msg.GetByteString(STUN_ATTR_DATA);
1558 ASSERT_TRUE(bytes != NULL);
1559 EXPECT_EQ(7U, bytes->length());
1560 EXPECT_EQ("abcdefg", bytes->string_view());
1561
1562 bytes2 = StunAttribute::CreateByteString(STUN_ATTR_DATA);
1563 bytes2->CopyBytes("abcdefg");
1564 msg2.AddAttribute(std::move(bytes2));
1565
1566 rtc::ByteBufferWriter out;
1567 EXPECT_TRUE(msg.Write(&out));
1568 EXPECT_EQ(size, out.Length());
1569 size_t len1 = out.Length();
1570 rtc::ByteBufferReader read_buf(out);
1571 std::string outstring;
1572 read_buf.ReadString(&outstring, len1);
1573 EXPECT_EQ(0, memcmp(outstring.c_str(), input, len1));
1574
1575 rtc::ByteBufferWriter out2;
1576 EXPECT_TRUE(msg2.Write(&out2));
1577 EXPECT_EQ(size, out2.Length());
1578 size_t len2 = out2.Length();
1579 rtc::ByteBufferReader read_buf2(out2);
1580 std::string outstring2;
1581 read_buf2.ReadString(&outstring2, len2);
1582 EXPECT_EQ(0, memcmp(outstring2.c_str(), input, len2));
1583 }
1584
1585 // Test that we can remove attribute from a message.
TEST_F(StunTest,RemoveAttribute)1586 TEST_F(StunTest, RemoveAttribute) {
1587 StunMessage msg;
1588
1589 // Removing something that does exist should return nullptr.
1590 EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr);
1591
1592 {
1593 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1594 attr->CopyBytes("kes", sizeof("kes"));
1595 msg.AddAttribute(std::move(attr));
1596 }
1597
1598 size_t len = msg.length();
1599 {
1600 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1601 ASSERT_NE(attr, nullptr);
1602 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1603 EXPECT_STREQ("kes",
1604 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1605 EXPECT_LT(msg.length(), len);
1606 }
1607
1608 // Now add same attribute type twice.
1609 {
1610 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1611 attr->CopyBytes("kes", sizeof("kes"));
1612 msg.AddAttribute(std::move(attr));
1613 }
1614
1615 {
1616 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1617 attr->CopyBytes("kenta", sizeof("kenta"));
1618 msg.AddAttribute(std::move(attr));
1619 }
1620
1621 // Remove should remove the last added occurrence.
1622 {
1623 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1624 ASSERT_NE(attr, nullptr);
1625 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1626 EXPECT_STREQ("kenta",
1627 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1628 }
1629
1630 // Remove should remove the last added occurrence.
1631 {
1632 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1633 ASSERT_NE(attr, nullptr);
1634 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1635 EXPECT_STREQ("kes",
1636 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1637 }
1638
1639 // Removing something that does exist should return nullptr.
1640 EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr);
1641 }
1642
1643 // Test that we can remove attribute from a message.
TEST_F(StunTest,ClearAttributes)1644 TEST_F(StunTest, ClearAttributes) {
1645 StunMessage msg;
1646
1647 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1648 attr->CopyBytes("kes", sizeof("kes"));
1649 msg.AddAttribute(std::move(attr));
1650 size_t len = msg.length();
1651
1652 msg.ClearAttributes();
1653 EXPECT_EQ(msg.length(), len - /* 3 + 1 byte padding + header */ 8);
1654 EXPECT_EQ(nullptr, msg.GetByteString(STUN_ATTR_USERNAME));
1655 }
1656
1657 // Test CopyStunAttribute
TEST_F(StunTest,CopyAttribute)1658 TEST_F(StunTest, CopyAttribute) {
1659 rtc::ByteBufferWriter buf;
1660 rtc::ByteBufferWriter* buffer_ptrs[] = {&buf, nullptr};
1661 // Test both with and without supplied ByteBufferWriter.
1662 for (auto buffer_ptr : buffer_ptrs) {
1663 { // Test StunByteStringAttribute.
1664 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1665 attr->CopyBytes("kes", sizeof("kes"));
1666
1667 auto copy = CopyStunAttribute(*attr.get(), buffer_ptr);
1668 ASSERT_EQ(copy->value_type(), STUN_VALUE_BYTE_STRING);
1669 EXPECT_STREQ("kes",
1670 static_cast<StunByteStringAttribute*>(copy.get())->bytes());
1671 }
1672
1673 { // Test StunAddressAttribute.
1674 rtc::IPAddress test_ip(kIPv6TestAddress2);
1675 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
1676 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
1677 addr->SetAddress(test_addr);
1678 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6,
1679 kTestMessagePort2, test_ip);
1680
1681 auto copy = CopyStunAttribute(*addr.get(), buffer_ptr);
1682 ASSERT_EQ(copy->value_type(), STUN_VALUE_ADDRESS);
1683 CheckStunAddressAttribute(static_cast<StunAddressAttribute*>(copy.get()),
1684 STUN_ADDRESS_IPV6, kTestMessagePort2, test_ip);
1685 }
1686
1687 { // Test StunAddressAttribute.
1688 rtc::IPAddress test_ip(kIPv6TestAddress2);
1689 auto addr = StunAttribute::CreateAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
1690 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
1691 addr->SetAddress(test_addr);
1692 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6,
1693 kTestMessagePort2, test_ip);
1694
1695 auto copy = CopyStunAttribute(*addr.get(), buffer_ptr);
1696 ASSERT_EQ(copy->value_type(), STUN_VALUE_ADDRESS);
1697 CheckStunAddressAttribute(static_cast<StunAddressAttribute*>(copy.get()),
1698 STUN_ADDRESS_IPV6, kTestMessagePort2, test_ip);
1699 }
1700 }
1701 }
1702
1703 // Test Clone
TEST_F(StunTest,Clone)1704 TEST_F(StunTest, Clone) {
1705 IceMessage msg(0, "0123456789ab");
1706 {
1707 auto errorcode = StunAttribute::CreateErrorCode();
1708 errorcode->SetCode(kTestErrorCode);
1709 errorcode->SetReason(kTestErrorReason);
1710 msg.AddAttribute(std::move(errorcode));
1711 }
1712 {
1713 auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1714 bytes2->CopyBytes("abcdefghijkl");
1715 msg.AddAttribute(std::move(bytes2));
1716 }
1717 {
1718 auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_RETRANSMIT_COUNT);
1719 uval2->SetValue(11);
1720 msg.AddAttribute(std::move(uval2));
1721 }
1722 {
1723 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
1724 addr->SetIP(rtc::IPAddress(kIPv6TestAddress1));
1725 addr->SetPort(kTestMessagePort1);
1726 msg.AddAttribute(std::move(addr));
1727 }
1728 auto copy = msg.Clone();
1729 ASSERT_NE(nullptr, copy.get());
1730
1731 rtc::ByteBufferWriter out1;
1732 EXPECT_TRUE(msg.Write(&out1));
1733 rtc::ByteBufferWriter out2;
1734 EXPECT_TRUE(copy->Write(&out2));
1735
1736 ASSERT_EQ(out1.Length(), out2.Length());
1737 EXPECT_EQ(0, memcmp(out1.Data(), out2.Data(), out1.Length()));
1738 }
1739
1740 // Test EqualAttributes
TEST_F(StunTest,EqualAttributes)1741 TEST_F(StunTest, EqualAttributes) {
1742 IceMessage msg;
1743 {
1744 auto errorcode = StunAttribute::CreateErrorCode();
1745 errorcode->SetCode(kTestErrorCode);
1746 errorcode->SetReason(kTestErrorReason);
1747 msg.AddAttribute(std::move(errorcode));
1748 }
1749 {
1750 auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1751 bytes2->CopyBytes("abcdefghijkl");
1752 msg.AddAttribute(std::move(bytes2));
1753 }
1754 {
1755 auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_RETRANSMIT_COUNT);
1756 uval2->SetValue(11);
1757 msg.AddAttribute(std::move(uval2));
1758 }
1759 {
1760 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
1761 addr->SetIP(rtc::IPAddress(kIPv6TestAddress1));
1762 addr->SetPort(kTestMessagePort1);
1763 msg.AddAttribute(std::move(addr));
1764 }
1765 auto copy = msg.Clone();
1766 ASSERT_NE(nullptr, copy.get());
1767
1768 EXPECT_TRUE(copy->EqualAttributes(&msg, [](int type) { return true; }));
1769
1770 {
1771 auto attr = StunAttribute::CreateByteString(STUN_ATTR_NONCE);
1772 attr->CopyBytes("keso");
1773 msg.AddAttribute(std::move(attr));
1774 EXPECT_FALSE(copy->EqualAttributes(&msg, [](int type) { return true; }));
1775 EXPECT_TRUE(copy->EqualAttributes(
1776 &msg, [](int type) { return type != STUN_ATTR_NONCE; }));
1777 }
1778
1779 {
1780 auto attr = StunAttribute::CreateByteString(STUN_ATTR_NONCE);
1781 attr->CopyBytes("keso");
1782 copy->AddAttribute(std::move(attr));
1783 EXPECT_TRUE(copy->EqualAttributes(&msg, [](int type) { return true; }));
1784 }
1785 {
1786 copy->RemoveAttribute(STUN_ATTR_NONCE);
1787 auto attr = StunAttribute::CreateByteString(STUN_ATTR_NONCE);
1788 attr->CopyBytes("kent");
1789 copy->AddAttribute(std::move(attr));
1790 EXPECT_FALSE(copy->EqualAttributes(&msg, [](int type) { return true; }));
1791 EXPECT_TRUE(copy->EqualAttributes(
1792 &msg, [](int type) { return type != STUN_ATTR_NONCE; }));
1793 }
1794
1795 {
1796 msg.RemoveAttribute(STUN_ATTR_NONCE);
1797 EXPECT_FALSE(copy->EqualAttributes(&msg, [](int type) { return true; }));
1798 EXPECT_TRUE(copy->EqualAttributes(
1799 &msg, [](int type) { return type != STUN_ATTR_NONCE; }));
1800 }
1801 }
1802
TEST_F(StunTest,ReduceTransactionIdIsHostOrderIndependent)1803 TEST_F(StunTest, ReduceTransactionIdIsHostOrderIndependent) {
1804 const std::string transaction_id = "abcdefghijkl";
1805 StunMessage message(0, transaction_id);
1806 uint32_t reduced_transaction_id = message.reduced_transaction_id();
1807 EXPECT_EQ(reduced_transaction_id, 1835954016u);
1808 }
1809
TEST_F(StunTest,GoogMiscInfo)1810 TEST_F(StunTest, GoogMiscInfo) {
1811 StunMessage msg(STUN_BINDING_REQUEST, "ABCDEFGHIJKL");
1812 const size_t size =
1813 /* msg header */ 20 +
1814 /* attr header */ 4 +
1815 /* 3 * 2 rounded to multiple of 4 */ 8;
1816 auto list =
1817 StunAttribute::CreateUInt16ListAttribute(STUN_ATTR_GOOG_MISC_INFO);
1818 list->AddTypeAtIndex(0, 0x1U);
1819 list->AddTypeAtIndex(3, 0x1000U);
1820 list->AddTypeAtIndex(2, 0xAB0CU);
1821 msg.AddAttribute(std::move(list));
1822 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
1823
1824 rtc::ByteBufferWriter out;
1825 EXPECT_TRUE(msg.Write(&out));
1826 ASSERT_EQ(size, out.Length());
1827
1828 size_t read_size = ReadStunMessageTestCase(
1829 &msg, reinterpret_cast<const unsigned char*>(out.Data()), out.Length());
1830 ASSERT_EQ(read_size + 20, size);
1831 CheckStunHeader(msg, STUN_BINDING_REQUEST, read_size);
1832 const StunUInt16ListAttribute* types =
1833 msg.GetUInt16List(STUN_ATTR_GOOG_MISC_INFO);
1834 ASSERT_TRUE(types != NULL);
1835 EXPECT_EQ(4U, types->Size());
1836 EXPECT_EQ(0x1U, types->GetType(0));
1837 EXPECT_EQ(0x0U, types->GetType(1));
1838 EXPECT_EQ(0x1000U, types->GetType(3));
1839 EXPECT_EQ(0xAB0CU, types->GetType(2));
1840 }
1841
TEST_F(StunTest,IsStunMethod)1842 TEST_F(StunTest, IsStunMethod) {
1843 int methods[] = {STUN_BINDING_REQUEST};
1844 EXPECT_TRUE(StunMessage::IsStunMethod(
1845 methods, reinterpret_cast<const char*>(kRfc5769SampleRequest),
1846 sizeof(kRfc5769SampleRequest)));
1847 }
1848
TEST_F(StunTest,SizeRestrictionOnAttributes)1849 TEST_F(StunTest, SizeRestrictionOnAttributes) {
1850 StunMessage msg(STUN_BINDING_REQUEST, "ABCDEFGHIJKL");
1851 auto long_username = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1852 std::string long_string(509, 'x');
1853 long_username->CopyBytes(long_string.c_str(), long_string.size());
1854 msg.AddAttribute(std::move(long_username));
1855 rtc::ByteBufferWriter out;
1856 ASSERT_FALSE(msg.Write(&out));
1857 }
1858
TEST_F(StunTest,ValidateMessageIntegrityWithParser)1859 TEST_F(StunTest, ValidateMessageIntegrityWithParser) {
1860 webrtc::metrics::Reset(); // Ensure counters start from zero.
1861 // Try the messages from RFC 5769.
1862 StunMessage message;
1863 rtc::ByteBufferReader reader(
1864 reinterpret_cast<const char*>(kRfc5769SampleRequest),
1865 sizeof(kRfc5769SampleRequest));
1866 EXPECT_TRUE(message.Read(&reader));
1867 EXPECT_EQ(message.ValidateMessageIntegrity(kRfc5769SampleMsgPassword),
1868 StunMessage::IntegrityStatus::kIntegrityOk);
1869 EXPECT_EQ(webrtc::metrics::NumEvents(
1870 "WebRTC.Stun.Integrity.Request",
1871 static_cast<int>(StunMessage::IntegrityStatus::kIntegrityOk)),
1872 1);
1873 EXPECT_EQ(message.RevalidateMessageIntegrity("Invalid password"),
1874 StunMessage::IntegrityStatus::kIntegrityBad);
1875 EXPECT_EQ(webrtc::metrics::NumEvents(
1876 "WebRTC.Stun.Integrity.Request",
1877 static_cast<int>(StunMessage::IntegrityStatus::kIntegrityBad)),
1878 1);
1879 EXPECT_EQ(webrtc::metrics::NumSamples("WebRTC.Stun.Integrity.Request"), 2);
1880 }
1881
1882 } // namespace cricket
1883