blob: 6d9510882d1d41e643ac3da61c0305624f7fb018 [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include <string>
Steve Anton6c38cc72017-11-29 10:25:58 -080012#include <utility>
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000013
Karl Wiberg918f50c2018-07-05 11:40:33 +020014#include "absl/memory/memory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "p2p/base/stun.h"
16#include "rtc_base/arraysize.h"
17#include "rtc_base/bytebuffer.h"
18#include "rtc_base/gunit.h"
19#include "rtc_base/logging.h"
20#include "rtc_base/messagedigest.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "rtc_base/socketaddress.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000022
23namespace cricket {
24
25class StunTest : public ::testing::Test {
26 protected:
Yves Gerey665174f2018-06-19 15:03:05 +020027 void CheckStunHeader(const StunMessage& msg,
28 StunMessageType expected_type,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000029 size_t expected_length) {
30 ASSERT_EQ(expected_type, msg.type());
31 ASSERT_EQ(expected_length, msg.length());
32 }
33
34 void CheckStunTransactionID(const StunMessage& msg,
Yves Gerey665174f2018-06-19 15:03:05 +020035 const unsigned char* expectedID,
36 size_t length) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000037 ASSERT_EQ(length, msg.transaction_id().size());
38 ASSERT_EQ(length == kStunTransactionIdLength + 4, msg.IsLegacy());
39 ASSERT_EQ(length == kStunTransactionIdLength, !msg.IsLegacy());
40 ASSERT_EQ(0, memcmp(msg.transaction_id().c_str(), expectedID, length));
41 }
42
43 void CheckStunAddressAttribute(const StunAddressAttribute* addr,
44 StunAddressFamily expected_family,
45 int expected_port,
46 rtc::IPAddress expected_address) {
47 ASSERT_EQ(expected_family, addr->family());
48 ASSERT_EQ(expected_port, addr->port());
49
50 if (addr->family() == STUN_ADDRESS_IPV4) {
51 in_addr v4_address = expected_address.ipv4_address();
52 in_addr stun_address = addr->ipaddr().ipv4_address();
53 ASSERT_EQ(0, memcmp(&v4_address, &stun_address, sizeof(stun_address)));
54 } else if (addr->family() == STUN_ADDRESS_IPV6) {
55 in6_addr v6_address = expected_address.ipv6_address();
56 in6_addr stun_address = addr->ipaddr().ipv6_address();
57 ASSERT_EQ(0, memcmp(&v6_address, &stun_address, sizeof(stun_address)));
58 } else {
59 ASSERT_TRUE(addr->family() == STUN_ADDRESS_IPV6 ||
60 addr->family() == STUN_ADDRESS_IPV4);
61 }
62 }
63
64 size_t ReadStunMessageTestCase(StunMessage* msg,
65 const unsigned char* testcase,
66 size_t size) {
67 const char* input = reinterpret_cast<const char*>(testcase);
jbauchf1f87202016-03-30 06:43:37 -070068 rtc::ByteBufferReader buf(input, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000069 if (msg->Read(&buf)) {
70 // Returns the size the stun message should report itself as being
71 return (size - 20);
72 } else {
73 return 0;
74 }
75 }
76};
77
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000078// Sample STUN packets with various attributes
79// Gathered by wiresharking pjproject's pjnath test programs
80// pjproject available at www.pjsip.org
81
Yves Gerey665174f2018-06-19 15:03:05 +020082// clang-format off
83// clang formatting doesn't respect inline comments.
84
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000085static const unsigned char kStunMessageWithIPv6MappedAddress[] = {
86 0x00, 0x01, 0x00, 0x18, // message header
87 0x21, 0x12, 0xa4, 0x42, // transaction id
88 0x29, 0x1f, 0xcd, 0x7c,
89 0xba, 0x58, 0xab, 0xd7,
90 0xf2, 0x41, 0x01, 0x00,
91 0x00, 0x01, 0x00, 0x14, // Address type (mapped), length
92 0x00, 0x02, 0xb8, 0x81, // family (IPv6), port
93 0x24, 0x01, 0xfa, 0x00, // an IPv6 address
94 0x00, 0x04, 0x10, 0x00,
95 0xbe, 0x30, 0x5b, 0xff,
96 0xfe, 0xe5, 0x00, 0xc3
97};
98
99static const unsigned char kStunMessageWithIPv4MappedAddress[] = {
100 0x01, 0x01, 0x00, 0x0c, // binding response, length 12
101 0x21, 0x12, 0xa4, 0x42, // magic cookie
102 0x29, 0x1f, 0xcd, 0x7c, // transaction ID
103 0xba, 0x58, 0xab, 0xd7,
104 0xf2, 0x41, 0x01, 0x00,
105 0x00, 0x01, 0x00, 0x08, // Mapped, 8 byte length
106 0x00, 0x01, 0x9d, 0xfc, // AF_INET, unxor-ed port
107 0xac, 0x17, 0x44, 0xe6 // IPv4 address
108};
109
110// Test XOR-mapped IP addresses:
111static const unsigned char kStunMessageWithIPv6XorMappedAddress[] = {
112 0x01, 0x01, 0x00, 0x18, // message header (binding response)
113 0x21, 0x12, 0xa4, 0x42, // magic cookie (rfc5389)
114 0xe3, 0xa9, 0x46, 0xe1, // transaction ID
115 0x7c, 0x00, 0xc2, 0x62,
116 0x54, 0x08, 0x01, 0x00,
117 0x00, 0x20, 0x00, 0x14, // Address Type (XOR), length
118 0x00, 0x02, 0xcb, 0x5b, // family, XOR-ed port
119 0x05, 0x13, 0x5e, 0x42, // XOR-ed IPv6 address
120 0xe3, 0xad, 0x56, 0xe1,
121 0xc2, 0x30, 0x99, 0x9d,
122 0xaa, 0xed, 0x01, 0xc3
123};
124
125static const unsigned char kStunMessageWithIPv4XorMappedAddress[] = {
126 0x01, 0x01, 0x00, 0x0c, // message header (binding response)
127 0x21, 0x12, 0xa4, 0x42, // magic cookie
128 0x29, 0x1f, 0xcd, 0x7c, // transaction ID
129 0xba, 0x58, 0xab, 0xd7,
130 0xf2, 0x41, 0x01, 0x00,
131 0x00, 0x20, 0x00, 0x08, // address type (xor), length
132 0x00, 0x01, 0xfc, 0xb5, // family (AF_INET), XOR-ed port
133 0x8d, 0x05, 0xe0, 0xa4 // IPv4 address
134};
135
136// ByteString Attribute (username)
137static const unsigned char kStunMessageWithByteStringAttribute[] = {
138 0x00, 0x01, 0x00, 0x0c,
139 0x21, 0x12, 0xa4, 0x42,
140 0xe3, 0xa9, 0x46, 0xe1,
141 0x7c, 0x00, 0xc2, 0x62,
142 0x54, 0x08, 0x01, 0x00,
143 0x00, 0x06, 0x00, 0x08, // username attribute (length 8)
144 0x61, 0x62, 0x63, 0x64, // abcdefgh
145 0x65, 0x66, 0x67, 0x68
146};
147
148// Message with an unknown but comprehensible optional attribute.
149// Parsing should succeed despite this unknown attribute.
150static const unsigned char kStunMessageWithUnknownAttribute[] = {
151 0x00, 0x01, 0x00, 0x14,
152 0x21, 0x12, 0xa4, 0x42,
153 0xe3, 0xa9, 0x46, 0xe1,
154 0x7c, 0x00, 0xc2, 0x62,
155 0x54, 0x08, 0x01, 0x00,
156 0x00, 0xaa, 0x00, 0x07, // Unknown attribute, length 7 (needs padding!)
157 0x61, 0x62, 0x63, 0x64, // abcdefg + padding
158 0x65, 0x66, 0x67, 0x00,
159 0x00, 0x06, 0x00, 0x03, // Followed by a known attribute we can
160 0x61, 0x62, 0x63, 0x00 // check for (username of length 3)
161};
162
163// ByteString Attribute (username) with padding byte
164static const unsigned char kStunMessageWithPaddedByteStringAttribute[] = {
165 0x00, 0x01, 0x00, 0x08,
166 0x21, 0x12, 0xa4, 0x42,
167 0xe3, 0xa9, 0x46, 0xe1,
168 0x7c, 0x00, 0xc2, 0x62,
169 0x54, 0x08, 0x01, 0x00,
170 0x00, 0x06, 0x00, 0x03, // username attribute (length 3)
171 0x61, 0x62, 0x63, 0xcc // abc
172};
173
Peter Boström0c4e06b2015-10-07 12:23:21 +0200174// Message with an Unknown Attributes (uint16_t list) attribute.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000175static const unsigned char kStunMessageWithUInt16ListAttribute[] = {
176 0x00, 0x01, 0x00, 0x0c,
177 0x21, 0x12, 0xa4, 0x42,
178 0xe3, 0xa9, 0x46, 0xe1,
179 0x7c, 0x00, 0xc2, 0x62,
180 0x54, 0x08, 0x01, 0x00,
181 0x00, 0x0a, 0x00, 0x06, // username attribute (length 6)
182 0x00, 0x01, 0x10, 0x00, // three attributes plus padding
183 0xAB, 0xCU, 0xBE, 0xEF
184};
185
186// Error response message (unauthorized)
187static const unsigned char kStunMessageWithErrorAttribute[] = {
188 0x01, 0x11, 0x00, 0x14,
189 0x21, 0x12, 0xa4, 0x42,
190 0x29, 0x1f, 0xcd, 0x7c,
191 0xba, 0x58, 0xab, 0xd7,
192 0xf2, 0x41, 0x01, 0x00,
193 0x00, 0x09, 0x00, 0x10,
194 0x00, 0x00, 0x04, 0x01,
195 0x55, 0x6e, 0x61, 0x75,
196 0x74, 0x68, 0x6f, 0x72,
197 0x69, 0x7a, 0x65, 0x64
198};
199
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000200static const unsigned char kStunMessageWithOriginAttribute[] = {
201 0x00, 0x01, 0x00, 0x18, // message header (binding request), length 24
202 0x21, 0x12, 0xA4, 0x42, // magic cookie
203 0x29, 0x1f, 0xcd, 0x7c, // transaction id
204 0xba, 0x58, 0xab, 0xd7,
205 0xf2, 0x41, 0x01, 0x00,
206 0x80, 0x2f, 0x00, 0x12, // origin attribute (length 18)
207 0x68, 0x74, 0x74, 0x70, // http://example.com
208 0x3A, 0x2F, 0x2F, 0x65,
209 0x78, 0x61, 0x6d, 0x70,
210 0x6c, 0x65, 0x2e, 0x63,
211 0x6f, 0x6d, 0x00, 0x00,
212};
213
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000214// Sample messages with an invalid length Field
215
216// The actual length in bytes of the invalid messages (including STUN header)
217static const int kRealLengthOfInvalidLengthTestCases = 32;
218
219static const unsigned char kStunMessageWithZeroLength[] = {
220 0x00, 0x01, 0x00, 0x00, // length of 0 (last 2 bytes)
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
230static const unsigned char kStunMessageWithExcessLength[] = {
231 0x00, 0x01, 0x00, 0x55, // length of 85
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
241static const unsigned char kStunMessageWithSmallLength[] = {
242 0x00, 0x01, 0x00, 0x03, // length of 3
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, 0x20, 0x00, 0x08, // xor mapped address
248 0x00, 0x01, 0x21, 0x1F,
249 0x21, 0x12, 0xA4, 0x53,
250};
251
katrielc1a206102016-06-20 05:13:16 -0700252static const unsigned char kStunMessageWithBadHmacAtEnd[] = {
253 0x00, 0x01, 0x00, 0x14, // message length exactly 20
254 0x21, 0x12, 0xA4, 0x42, // magic cookie
255 '0', '1', '2', '3', // transaction ID
256 '4', '5', '6', '7',
257 '8', '9', 'a', 'b',
258 0x00, 0x08, 0x00, 0x14, // type=STUN_ATTR_MESSAGE_INTEGRITY, length=20
259 '0', '0', '0', '0', // We lied, there are only 16 bytes of HMAC.
260 '0', '0', '0', '0',
261 '0', '0', '0', '0',
262 '0', '0', '0', '0',
263};
264
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000265// RTCP packet, for testing we correctly ignore non stun packet types.
266// V=2, P=false, RC=0, Type=200, Len=6, Sender-SSRC=85, etc
267static const unsigned char kRtcpPacket[] = {
268 0x80, 0xc8, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55,
269 0xce, 0xa5, 0x18, 0x3a, 0x39, 0xcc, 0x7d, 0x09,
270 0x23, 0xed, 0x19, 0x07, 0x00, 0x00, 0x01, 0x56,
271 0x00, 0x03, 0x73, 0x50,
272};
273
Yves Gerey665174f2018-06-19 15:03:05 +0200274
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000275// RFC5769 Test Vectors
276// Software name (request): "STUN test client" (without quotes)
277// Software name (response): "test vector" (without quotes)
278// Username: "evtj:h6vY" (without quotes)
279// Password: "VOkJxbRl1RmTxUk/WvJxBt" (without quotes)
280static const unsigned char kRfc5769SampleMsgTransactionId[] = {
281 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae
282};
283static const char kRfc5769SampleMsgClientSoftware[] = "STUN test client";
284static const char kRfc5769SampleMsgServerSoftware[] = "test vector";
285static const char kRfc5769SampleMsgUsername[] = "evtj:h6vY";
286static const char kRfc5769SampleMsgPassword[] = "VOkJxbRl1RmTxUk/WvJxBt";
287static const rtc::SocketAddress kRfc5769SampleMsgMappedAddress(
288 "192.0.2.1", 32853);
289static const rtc::SocketAddress kRfc5769SampleMsgIPv6MappedAddress(
290 "2001:db8:1234:5678:11:2233:4455:6677", 32853);
291
292static const unsigned char kRfc5769SampleMsgWithAuthTransactionId[] = {
293 0x78, 0xad, 0x34, 0x33, 0xc6, 0xad, 0x72, 0xc0, 0x29, 0xda, 0x41, 0x2e
294};
295static const char kRfc5769SampleMsgWithAuthUsername[] =
296 "\xe3\x83\x9e\xe3\x83\x88\xe3\x83\xaa\xe3\x83\x83\xe3\x82\xaf\xe3\x82\xb9";
297static const char kRfc5769SampleMsgWithAuthPassword[] = "TheMatrIX";
298static const char kRfc5769SampleMsgWithAuthNonce[] =
299 "f//499k954d6OL34oL9FSTvy64sA";
300static const char kRfc5769SampleMsgWithAuthRealm[] = "example.org";
301
302// 2.1. Sample Request
303static const unsigned char kRfc5769SampleRequest[] = {
304 0x00, 0x01, 0x00, 0x58, // Request type and message length
305 0x21, 0x12, 0xa4, 0x42, // Magic cookie
306 0xb7, 0xe7, 0xa7, 0x01, // }
307 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
308 0xfa, 0x87, 0xdf, 0xae, // }
309 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
310 0x53, 0x54, 0x55, 0x4e, // }
311 0x20, 0x74, 0x65, 0x73, // } User-agent...
312 0x74, 0x20, 0x63, 0x6c, // } ...name
313 0x69, 0x65, 0x6e, 0x74, // }
314 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
315 0x6e, 0x00, 0x01, 0xff, // ICE priority value
316 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
317 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
318 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
319 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
320 0x65, 0x76, 0x74, 0x6a, // }
321 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
322 0x59, 0x20, 0x20, 0x20, // }
323 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
324 0x9a, 0xea, 0xa7, 0x0c, // }
325 0xbf, 0xd8, 0xcb, 0x56, // }
326 0x78, 0x1e, 0xf2, 0xb5, // } HMAC-SHA1 fingerprint
327 0xb2, 0xd3, 0xf2, 0x49, // }
328 0xc1, 0xb5, 0x71, 0xa2, // }
329 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
330 0xe5, 0x7a, 0x3b, 0xcf // CRC32 fingerprint
331};
332
333// 2.2. Sample IPv4 Response
334static const unsigned char kRfc5769SampleResponse[] = {
335 0x01, 0x01, 0x00, 0x3c, // Response type and message length
336 0x21, 0x12, 0xa4, 0x42, // Magic cookie
337 0xb7, 0xe7, 0xa7, 0x01, // }
338 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
339 0xfa, 0x87, 0xdf, 0xae, // }
340 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
341 0x74, 0x65, 0x73, 0x74, // }
342 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
343 0x74, 0x6f, 0x72, 0x20, // }
344 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
345 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port
346 0xe1, 0x12, 0xa6, 0x43, // Xor'd mapped IPv4 address
347 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
348 0x2b, 0x91, 0xf5, 0x99, // }
349 0xfd, 0x9e, 0x90, 0xc3, // }
350 0x8c, 0x74, 0x89, 0xf9, // } HMAC-SHA1 fingerprint
351 0x2a, 0xf9, 0xba, 0x53, // }
352 0xf0, 0x6b, 0xe7, 0xd7, // }
353 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
354 0xc0, 0x7d, 0x4c, 0x96 // CRC32 fingerprint
355};
356
357// 2.3. Sample IPv6 Response
358static const unsigned char kRfc5769SampleResponseIPv6[] = {
359 0x01, 0x01, 0x00, 0x48, // Response type and message length
360 0x21, 0x12, 0xa4, 0x42, // Magic cookie
361 0xb7, 0xe7, 0xa7, 0x01, // }
362 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
363 0xfa, 0x87, 0xdf, 0xae, // }
364 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
365 0x74, 0x65, 0x73, 0x74, // }
366 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
367 0x74, 0x6f, 0x72, 0x20, // }
368 0x00, 0x20, 0x00, 0x14, // XOR-MAPPED-ADDRESS attribute header
369 0x00, 0x02, 0xa1, 0x47, // Address family (IPv6) and xor'd mapped port.
370 0x01, 0x13, 0xa9, 0xfa, // }
371 0xa5, 0xd3, 0xf1, 0x79, // } Xor'd mapped IPv6 address
372 0xbc, 0x25, 0xf4, 0xb5, // }
373 0xbe, 0xd2, 0xb9, 0xd9, // }
374 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
375 0xa3, 0x82, 0x95, 0x4e, // }
376 0x4b, 0xe6, 0x7b, 0xf1, // }
377 0x17, 0x84, 0xc9, 0x7c, // } HMAC-SHA1 fingerprint
378 0x82, 0x92, 0xc2, 0x75, // }
379 0xbf, 0xe3, 0xed, 0x41, // }
380 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header
381 0xc8, 0xfb, 0x0b, 0x4c // CRC32 fingerprint
382};
383
384// 2.4. Sample Request with Long-Term Authentication
385static const unsigned char kRfc5769SampleRequestLongTermAuth[] = {
386 0x00, 0x01, 0x00, 0x60, // Request type and message length
387 0x21, 0x12, 0xa4, 0x42, // Magic cookie
388 0x78, 0xad, 0x34, 0x33, // }
389 0xc6, 0xad, 0x72, 0xc0, // } Transaction ID
390 0x29, 0xda, 0x41, 0x2e, // }
391 0x00, 0x06, 0x00, 0x12, // USERNAME attribute header
392 0xe3, 0x83, 0x9e, 0xe3, // }
393 0x83, 0x88, 0xe3, 0x83, // }
394 0xaa, 0xe3, 0x83, 0x83, // } Username value (18 bytes) and padding (2 bytes)
395 0xe3, 0x82, 0xaf, 0xe3, // }
396 0x82, 0xb9, 0x00, 0x00, // }
397 0x00, 0x15, 0x00, 0x1c, // NONCE attribute header
398 0x66, 0x2f, 0x2f, 0x34, // }
399 0x39, 0x39, 0x6b, 0x39, // }
400 0x35, 0x34, 0x64, 0x36, // }
401 0x4f, 0x4c, 0x33, 0x34, // } Nonce value
402 0x6f, 0x4c, 0x39, 0x46, // }
403 0x53, 0x54, 0x76, 0x79, // }
404 0x36, 0x34, 0x73, 0x41, // }
405 0x00, 0x14, 0x00, 0x0b, // REALM attribute header
406 0x65, 0x78, 0x61, 0x6d, // }
407 0x70, 0x6c, 0x65, 0x2e, // } Realm value (11 bytes) and padding (1 byte)
408 0x6f, 0x72, 0x67, 0x00, // }
409 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header
410 0xf6, 0x70, 0x24, 0x65, // }
411 0x6d, 0xd6, 0x4a, 0x3e, // }
412 0x02, 0xb8, 0xe0, 0x71, // } HMAC-SHA1 fingerprint
413 0x2e, 0x85, 0xc9, 0xa2, // }
414 0x8c, 0xa8, 0x96, 0x66 // }
415};
416
417// Length parameter is changed to 0x38 from 0x58.
418// AddMessageIntegrity will add MI information and update the length param
419// accordingly.
420static const unsigned char kRfc5769SampleRequestWithoutMI[] = {
421 0x00, 0x01, 0x00, 0x38, // Request type and message length
422 0x21, 0x12, 0xa4, 0x42, // Magic cookie
423 0xb7, 0xe7, 0xa7, 0x01, // }
424 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
425 0xfa, 0x87, 0xdf, 0xae, // }
426 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header
427 0x53, 0x54, 0x55, 0x4e, // }
428 0x20, 0x74, 0x65, 0x73, // } User-agent...
429 0x74, 0x20, 0x63, 0x6c, // } ...name
430 0x69, 0x65, 0x6e, 0x74, // }
431 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header
432 0x6e, 0x00, 0x01, 0xff, // ICE priority value
433 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header
434 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker...
435 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control
436 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header
437 0x65, 0x76, 0x74, 0x6a, // }
438 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes)
439 0x59, 0x20, 0x20, 0x20 // }
440};
441
442// This HMAC differs from the RFC 5769 SampleRequest message. This differs
443// because spec uses 0x20 for the padding where as our implementation uses 0.
444static const unsigned char kCalculatedHmac1[] = {
445 0x79, 0x07, 0xc2, 0xd2, // }
446 0xed, 0xbf, 0xea, 0x48, // }
447 0x0e, 0x4c, 0x76, 0xd8, // } HMAC-SHA1 fingerprint
448 0x29, 0x62, 0xd5, 0xc3, // }
449 0x74, 0x2a, 0xf9, 0xe3 // }
450};
451
452// Length parameter is changed to 0x1c from 0x3c.
453// AddMessageIntegrity will add MI information and update the length param
454// accordingly.
455static const unsigned char kRfc5769SampleResponseWithoutMI[] = {
456 0x01, 0x01, 0x00, 0x1c, // Response type and message length
457 0x21, 0x12, 0xa4, 0x42, // Magic cookie
458 0xb7, 0xe7, 0xa7, 0x01, // }
459 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
460 0xfa, 0x87, 0xdf, 0xae, // }
461 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
462 0x74, 0x65, 0x73, 0x74, // }
463 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name
464 0x74, 0x6f, 0x72, 0x20, // }
465 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
466 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port
467 0xe1, 0x12, 0xa6, 0x43 // Xor'd mapped IPv4 address
468};
469
470// This HMAC differs from the RFC 5769 SampleResponse message. This differs
471// because spec uses 0x20 for the padding where as our implementation uses 0.
472static const unsigned char kCalculatedHmac2[] = {
473 0x5d, 0x6b, 0x58, 0xbe, // }
474 0xad, 0x94, 0xe0, 0x7e, // }
475 0xef, 0x0d, 0xfc, 0x12, // } HMAC-SHA1 fingerprint
476 0x82, 0xa2, 0xbd, 0x08, // }
477 0x43, 0x14, 0x10, 0x28 // }
478};
479
Yves Gerey665174f2018-06-19 15:03:05 +0200480// clang-format on
481
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000482// A transaction ID without the 'magic cookie' portion
483// pjnat's test programs use this transaction ID a lot.
Yves Gerey665174f2018-06-19 15:03:05 +0200484const unsigned char kTestTransactionId1[] = {0x029, 0x01f, 0x0cd, 0x07c,
485 0x0ba, 0x058, 0x0ab, 0x0d7,
486 0x0f2, 0x041, 0x001, 0x000};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000487
488// They use this one sometimes too.
Yves Gerey665174f2018-06-19 15:03:05 +0200489const unsigned char kTestTransactionId2[] = {0x0e3, 0x0a9, 0x046, 0x0e1,
490 0x07c, 0x000, 0x0c2, 0x062,
491 0x054, 0x008, 0x001, 0x000};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000492
Yves Gerey665174f2018-06-19 15:03:05 +0200493const in6_addr kIPv6TestAddress1 = {
494 {{0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, 0x10, 0x00, 0xbe, 0x30, 0x5b, 0xff,
495 0xfe, 0xe5, 0x00, 0xc3}}};
496const in6_addr kIPv6TestAddress2 = {
497 {{0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, 0x10, 0x12, 0x06, 0x0c, 0xce, 0xff,
498 0xfe, 0x1f, 0x61, 0xa4}}};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000499
500#ifdef WEBRTC_POSIX
Yves Gerey665174f2018-06-19 15:03:05 +0200501const in_addr kIPv4TestAddress1 = {0xe64417ac};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000502#elif defined WEBRTC_WIN
503// Windows in_addr has a union with a uchar[] array first.
Yves Gerey665174f2018-06-19 15:03:05 +0200504const in_addr kIPv4TestAddress1 = {{{0x0ac, 0x017, 0x044, 0x0e6}}};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000505#endif
506const char kTestUserName1[] = "abcdefgh";
507const char kTestUserName2[] = "abc";
508const char kTestErrorReason[] = "Unauthorized";
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000509const char kTestOrigin[] = "http://example.com";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000510const int kTestErrorClass = 4;
511const int kTestErrorNumber = 1;
512const int kTestErrorCode = 401;
513
514const int kTestMessagePort1 = 59977;
515const int kTestMessagePort2 = 47233;
516const int kTestMessagePort3 = 56743;
517const int kTestMessagePort4 = 40444;
518
519#define ReadStunMessage(X, Y) ReadStunMessageTestCase(X, Y, sizeof(Y));
520
521// Test that the GetStun*Type and IsStun*Type methods work as expected.
522TEST_F(StunTest, MessageTypes) {
523 EXPECT_EQ(STUN_BINDING_RESPONSE,
Yves Gerey665174f2018-06-19 15:03:05 +0200524 GetStunSuccessResponseType(STUN_BINDING_REQUEST));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000525 EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE,
Yves Gerey665174f2018-06-19 15:03:05 +0200526 GetStunErrorResponseType(STUN_BINDING_REQUEST));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000527 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_INDICATION));
528 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_RESPONSE));
529 EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_ERROR_RESPONSE));
530 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_INDICATION));
531 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_RESPONSE));
532 EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_ERROR_RESPONSE));
533
Yves Gerey665174f2018-06-19 15:03:05 +0200534 int types[] = {STUN_BINDING_REQUEST, STUN_BINDING_INDICATION,
535 STUN_BINDING_RESPONSE, STUN_BINDING_ERROR_RESPONSE};
tfarina5237aaf2015-11-10 23:44:30 -0800536 for (size_t i = 0; i < arraysize(types); ++i) {
537 EXPECT_EQ(i == 0U, IsStunRequestType(types[i]));
538 EXPECT_EQ(i == 1U, IsStunIndicationType(types[i]));
539 EXPECT_EQ(i == 2U, IsStunSuccessResponseType(types[i]));
540 EXPECT_EQ(i == 3U, IsStunErrorResponseType(types[i]));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000541 EXPECT_EQ(1, types[i] & 0xFEEF);
542 }
543}
544
545TEST_F(StunTest, ReadMessageWithIPv4AddressAttribute) {
546 StunMessage msg;
547 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4MappedAddress);
548 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
549 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
550
551 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
552 rtc::IPAddress test_address(kIPv4TestAddress1);
Yves Gerey665174f2018-06-19 15:03:05 +0200553 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort4,
554 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000555}
556
557TEST_F(StunTest, ReadMessageWithIPv4XorAddressAttribute) {
558 StunMessage msg;
559 StunMessage msg2;
560 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress);
561 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
562 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
563
564 const StunAddressAttribute* addr =
565 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
566 rtc::IPAddress test_address(kIPv4TestAddress1);
Yves Gerey665174f2018-06-19 15:03:05 +0200567 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort3,
568 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000569}
570
571TEST_F(StunTest, ReadMessageWithIPv6AddressAttribute) {
572 StunMessage msg;
573 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
574 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
575 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
576
577 rtc::IPAddress test_address(kIPv6TestAddress1);
578
579 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200580 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort2,
581 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000582}
583
584TEST_F(StunTest, ReadMessageWithInvalidAddressAttribute) {
585 StunMessage msg;
586 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
587 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
588 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
589
590 rtc::IPAddress test_address(kIPv6TestAddress1);
591
592 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200593 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort2,
594 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000595}
596
597TEST_F(StunTest, ReadMessageWithIPv6XorAddressAttribute) {
598 StunMessage msg;
599 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress);
600
601 rtc::IPAddress test_address(kIPv6TestAddress1);
602
603 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
604 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
605
606 const StunAddressAttribute* addr =
607 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200608 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort1,
609 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000610}
611
612// Read the RFC5389 fields from the RFC5769 sample STUN request.
613TEST_F(StunTest, ReadRfc5769RequestMessage) {
614 StunMessage msg;
615 size_t size = ReadStunMessage(&msg, kRfc5769SampleRequest);
616 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
617 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
618 kStunTransactionIdLength);
619
620 const StunByteStringAttribute* software =
621 msg.GetByteString(STUN_ATTR_SOFTWARE);
622 ASSERT_TRUE(software != NULL);
623 EXPECT_EQ(kRfc5769SampleMsgClientSoftware, software->GetString());
624
625 const StunByteStringAttribute* username =
626 msg.GetByteString(STUN_ATTR_USERNAME);
627 ASSERT_TRUE(username != NULL);
628 EXPECT_EQ(kRfc5769SampleMsgUsername, username->GetString());
629
630 // Actual M-I value checked in a later test.
631 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
632
633 // Fingerprint checked in a later test, but double-check the value here.
Yves Gerey665174f2018-06-19 15:03:05 +0200634 const StunUInt32Attribute* fingerprint = msg.GetUInt32(STUN_ATTR_FINGERPRINT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000635 ASSERT_TRUE(fingerprint != NULL);
636 EXPECT_EQ(0xe57a3bcf, fingerprint->value());
637}
638
639// Read the RFC5389 fields from the RFC5769 sample STUN response.
640TEST_F(StunTest, ReadRfc5769ResponseMessage) {
641 StunMessage msg;
642 size_t size = ReadStunMessage(&msg, kRfc5769SampleResponse);
643 CheckStunHeader(msg, STUN_BINDING_RESPONSE, 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(kRfc5769SampleMsgServerSoftware, software->GetString());
651
652 const StunAddressAttribute* mapped_address =
653 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
654 ASSERT_TRUE(mapped_address != NULL);
655 EXPECT_EQ(kRfc5769SampleMsgMappedAddress, mapped_address->GetAddress());
656
657 // Actual M-I and fingerprint checked in later tests.
658 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
659 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
660}
661
662// Read the RFC5389 fields from the RFC5769 sample STUN response for IPv6.
663TEST_F(StunTest, ReadRfc5769ResponseMessageIPv6) {
664 StunMessage msg;
665 size_t size = ReadStunMessage(&msg, kRfc5769SampleResponseIPv6);
666 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
667 CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId,
668 kStunTransactionIdLength);
669
670 const StunByteStringAttribute* software =
671 msg.GetByteString(STUN_ATTR_SOFTWARE);
672 ASSERT_TRUE(software != NULL);
673 EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->GetString());
674
675 const StunAddressAttribute* mapped_address =
676 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
677 ASSERT_TRUE(mapped_address != NULL);
678 EXPECT_EQ(kRfc5769SampleMsgIPv6MappedAddress, mapped_address->GetAddress());
679
680 // Actual M-I and fingerprint checked in later tests.
681 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
682 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
683}
684
685// Read the RFC5389 fields from the RFC5769 sample STUN response with auth.
686TEST_F(StunTest, ReadRfc5769RequestMessageLongTermAuth) {
687 StunMessage msg;
688 size_t size = ReadStunMessage(&msg, kRfc5769SampleRequestLongTermAuth);
689 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
690 CheckStunTransactionID(msg, kRfc5769SampleMsgWithAuthTransactionId,
691 kStunTransactionIdLength);
692
693 const StunByteStringAttribute* username =
694 msg.GetByteString(STUN_ATTR_USERNAME);
695 ASSERT_TRUE(username != NULL);
696 EXPECT_EQ(kRfc5769SampleMsgWithAuthUsername, username->GetString());
697
Yves Gerey665174f2018-06-19 15:03:05 +0200698 const StunByteStringAttribute* nonce = msg.GetByteString(STUN_ATTR_NONCE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000699 ASSERT_TRUE(nonce != NULL);
700 EXPECT_EQ(kRfc5769SampleMsgWithAuthNonce, nonce->GetString());
701
Yves Gerey665174f2018-06-19 15:03:05 +0200702 const StunByteStringAttribute* realm = msg.GetByteString(STUN_ATTR_REALM);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000703 ASSERT_TRUE(realm != NULL);
704 EXPECT_EQ(kRfc5769SampleMsgWithAuthRealm, realm->GetString());
705
706 // No fingerprint, actual M-I checked in later tests.
707 ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
708 ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) == NULL);
709}
710
711// The RFC3489 packet in this test is the same as
712// kStunMessageWithIPv4MappedAddress, but with a different value where the
713// magic cookie was.
714TEST_F(StunTest, ReadLegacyMessage) {
715 unsigned char rfc3489_packet[sizeof(kStunMessageWithIPv4MappedAddress)];
716 memcpy(rfc3489_packet, kStunMessageWithIPv4MappedAddress,
Yves Gerey665174f2018-06-19 15:03:05 +0200717 sizeof(kStunMessageWithIPv4MappedAddress));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000718 // Overwrite the magic cookie here.
719 memcpy(&rfc3489_packet[4], "ABCD", 4);
720
721 StunMessage msg;
722 size_t size = ReadStunMessage(&msg, rfc3489_packet);
723 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
724 CheckStunTransactionID(msg, &rfc3489_packet[4], kStunTransactionIdLength + 4);
725
726 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
727 rtc::IPAddress test_address(kIPv4TestAddress1);
Yves Gerey665174f2018-06-19 15:03:05 +0200728 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort4,
729 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000730}
731
732TEST_F(StunTest, SetIPv6XorAddressAttributeOwner) {
733 StunMessage msg;
734 StunMessage msg2;
735 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress);
736
737 rtc::IPAddress test_address(kIPv6TestAddress1);
738
739 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
740 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
741
742 const StunAddressAttribute* addr =
743 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200744 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort1,
745 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000746
747 // Owner with a different transaction ID.
748 msg2.SetTransactionID("ABCDABCDABCD");
749 StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL);
750 addr2.SetIP(addr->ipaddr());
751 addr2.SetPort(addr->port());
752 addr2.SetOwner(&msg2);
753 // The internal IP address shouldn't change.
754 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
755
jbauchf1f87202016-03-30 06:43:37 -0700756 rtc::ByteBufferWriter correct_buf;
757 rtc::ByteBufferWriter wrong_buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000758 EXPECT_TRUE(addr->Write(&correct_buf));
759 EXPECT_TRUE(addr2.Write(&wrong_buf));
760 // But when written out, the buffers should look different.
761 ASSERT_NE(0,
762 memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
763 // And when reading a known good value, the address should be wrong.
jbauchf1f87202016-03-30 06:43:37 -0700764 rtc::ByteBufferReader read_buf(correct_buf);
765 addr2.Read(&read_buf);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000766 ASSERT_NE(addr->ipaddr(), addr2.ipaddr());
767 addr2.SetIP(addr->ipaddr());
768 addr2.SetPort(addr->port());
769 // Try writing with no owner at all, should fail and write nothing.
770 addr2.SetOwner(NULL);
771 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
jbauchf1f87202016-03-30 06:43:37 -0700772 wrong_buf.Clear();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000773 EXPECT_FALSE(addr2.Write(&wrong_buf));
774 ASSERT_EQ(0U, wrong_buf.Length());
775}
776
777TEST_F(StunTest, SetIPv4XorAddressAttributeOwner) {
778 // Unlike the IPv6XorAddressAttributeOwner test, IPv4 XOR address attributes
779 // should _not_ be affected by a change in owner. IPv4 XOR address uses the
780 // magic cookie value which is fixed.
781 StunMessage msg;
782 StunMessage msg2;
783 size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress);
784
785 rtc::IPAddress test_address(kIPv4TestAddress1);
786
787 CheckStunHeader(msg, STUN_BINDING_RESPONSE, size);
788 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
789
790 const StunAddressAttribute* addr =
791 msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
Yves Gerey665174f2018-06-19 15:03:05 +0200792 CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort3,
793 test_address);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000794
795 // Owner with a different transaction ID.
796 msg2.SetTransactionID("ABCDABCDABCD");
797 StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL);
798 addr2.SetIP(addr->ipaddr());
799 addr2.SetPort(addr->port());
800 addr2.SetOwner(&msg2);
801 // The internal IP address shouldn't change.
802 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
803
jbauchf1f87202016-03-30 06:43:37 -0700804 rtc::ByteBufferWriter correct_buf;
805 rtc::ByteBufferWriter wrong_buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000806 EXPECT_TRUE(addr->Write(&correct_buf));
807 EXPECT_TRUE(addr2.Write(&wrong_buf));
808 // The same address data should be written.
809 ASSERT_EQ(0,
810 memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length()));
811 // And an attribute should be able to un-XOR an address belonging to a message
812 // with a different transaction ID.
jbauchf1f87202016-03-30 06:43:37 -0700813 rtc::ByteBufferReader read_buf(correct_buf);
814 EXPECT_TRUE(addr2.Read(&read_buf));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000815 ASSERT_EQ(addr->ipaddr(), addr2.ipaddr());
816
817 // However, no owner is still an error, should fail and write nothing.
818 addr2.SetOwner(NULL);
819 ASSERT_EQ(addr2.ipaddr(), addr->ipaddr());
jbauchf1f87202016-03-30 06:43:37 -0700820 wrong_buf.Clear();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000821 EXPECT_FALSE(addr2.Write(&wrong_buf));
822}
823
824TEST_F(StunTest, CreateIPv6AddressAttribute) {
825 rtc::IPAddress test_ip(kIPv6TestAddress2);
826
zsteinf42cc9d2017-03-27 16:17:19 -0700827 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000828 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
829 addr->SetAddress(test_addr);
830
zsteinf42cc9d2017-03-27 16:17:19 -0700831 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6, kTestMessagePort2,
832 test_ip);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000833}
834
835TEST_F(StunTest, CreateIPv4AddressAttribute) {
836 struct in_addr test_in_addr;
837 test_in_addr.s_addr = 0xBEB0B0BE;
838 rtc::IPAddress test_ip(test_in_addr);
839
zsteinf42cc9d2017-03-27 16:17:19 -0700840 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000841 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
842 addr->SetAddress(test_addr);
843
zsteinf42cc9d2017-03-27 16:17:19 -0700844 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV4, kTestMessagePort2,
845 test_ip);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000846}
847
848// Test that we don't care what order we set the parts of an address
849TEST_F(StunTest, CreateAddressInArbitraryOrder) {
zsteinf42cc9d2017-03-27 16:17:19 -0700850 auto addr = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000851 // Port first
852 addr->SetPort(kTestMessagePort1);
853 addr->SetIP(rtc::IPAddress(kIPv4TestAddress1));
854 ASSERT_EQ(kTestMessagePort1, addr->port());
855 ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr->ipaddr());
856
zsteinf42cc9d2017-03-27 16:17:19 -0700857 auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000858 // IP first
859 addr2->SetIP(rtc::IPAddress(kIPv4TestAddress1));
860 addr2->SetPort(kTestMessagePort2);
861 ASSERT_EQ(kTestMessagePort2, addr2->port());
862 ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr2->ipaddr());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000863}
864
865TEST_F(StunTest, WriteMessageWithIPv6AddressAttribute) {
866 StunMessage msg;
867 size_t size = sizeof(kStunMessageWithIPv6MappedAddress);
868
869 rtc::IPAddress test_ip(kIPv6TestAddress1);
870
871 msg.SetType(STUN_BINDING_REQUEST);
872 msg.SetTransactionID(
873 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
874 kStunTransactionIdLength));
875 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
876
zsteinf42cc9d2017-03-27 16:17:19 -0700877 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000878 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
879 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700880 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000881
882 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
883
jbauchf1f87202016-03-30 06:43:37 -0700884 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000885 EXPECT_TRUE(msg.Write(&out));
886 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6MappedAddress));
887 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700888 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000889 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700890 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000891 ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv6MappedAddress, len1));
892}
893
894TEST_F(StunTest, WriteMessageWithIPv4AddressAttribute) {
895 StunMessage msg;
896 size_t size = sizeof(kStunMessageWithIPv4MappedAddress);
897
898 rtc::IPAddress test_ip(kIPv4TestAddress1);
899
900 msg.SetType(STUN_BINDING_RESPONSE);
901 msg.SetTransactionID(
902 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
903 kStunTransactionIdLength));
904 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
905
zsteinf42cc9d2017-03-27 16:17:19 -0700906 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000907 rtc::SocketAddress test_addr(test_ip, kTestMessagePort4);
908 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700909 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000910
911 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
912
jbauchf1f87202016-03-30 06:43:37 -0700913 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000914 EXPECT_TRUE(msg.Write(&out));
915 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4MappedAddress));
916 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700917 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000918 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700919 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000920 ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv4MappedAddress, len1));
921}
922
923TEST_F(StunTest, WriteMessageWithIPv6XorAddressAttribute) {
924 StunMessage msg;
925 size_t size = sizeof(kStunMessageWithIPv6XorMappedAddress);
926
927 rtc::IPAddress test_ip(kIPv6TestAddress1);
928
929 msg.SetType(STUN_BINDING_RESPONSE);
930 msg.SetTransactionID(
931 std::string(reinterpret_cast<const char*>(kTestTransactionId2),
932 kStunTransactionIdLength));
933 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
934
zsteinf42cc9d2017-03-27 16:17:19 -0700935 auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000936 rtc::SocketAddress test_addr(test_ip, kTestMessagePort1);
937 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700938 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000939
940 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
941
jbauchf1f87202016-03-30 06:43:37 -0700942 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000943 EXPECT_TRUE(msg.Write(&out));
944 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6XorMappedAddress));
945 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700946 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000947 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700948 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000949 ASSERT_EQ(0,
950 memcmp(bytes.c_str(), kStunMessageWithIPv6XorMappedAddress, len1));
951}
952
953TEST_F(StunTest, WriteMessageWithIPv4XoreAddressAttribute) {
954 StunMessage msg;
955 size_t size = sizeof(kStunMessageWithIPv4XorMappedAddress);
956
957 rtc::IPAddress test_ip(kIPv4TestAddress1);
958
959 msg.SetType(STUN_BINDING_RESPONSE);
960 msg.SetTransactionID(
961 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
962 kStunTransactionIdLength));
963 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
964
zsteinf42cc9d2017-03-27 16:17:19 -0700965 auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000966 rtc::SocketAddress test_addr(test_ip, kTestMessagePort3);
967 addr->SetAddress(test_addr);
zsteinf42cc9d2017-03-27 16:17:19 -0700968 msg.AddAttribute(std::move(addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000969
970 CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20));
971
jbauchf1f87202016-03-30 06:43:37 -0700972 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000973 EXPECT_TRUE(msg.Write(&out));
974 ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4XorMappedAddress));
975 int len1 = static_cast<int>(out.Length());
jbauchf1f87202016-03-30 06:43:37 -0700976 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000977 std::string bytes;
jbauchf1f87202016-03-30 06:43:37 -0700978 read_buf.ReadString(&bytes, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000979 ASSERT_EQ(0,
980 memcmp(bytes.c_str(), kStunMessageWithIPv4XorMappedAddress, len1));
981}
982
983TEST_F(StunTest, ReadByteStringAttribute) {
984 StunMessage msg;
985 size_t size = ReadStunMessage(&msg, kStunMessageWithByteStringAttribute);
986
987 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
988 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
989 const StunByteStringAttribute* username =
990 msg.GetByteString(STUN_ATTR_USERNAME);
991 ASSERT_TRUE(username != NULL);
992 EXPECT_EQ(kTestUserName1, username->GetString());
993}
994
995TEST_F(StunTest, ReadPaddedByteStringAttribute) {
996 StunMessage msg;
Yves Gerey665174f2018-06-19 15:03:05 +0200997 size_t size =
998 ReadStunMessage(&msg, kStunMessageWithPaddedByteStringAttribute);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000999 ASSERT_NE(0U, size);
1000 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1001 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
1002 const StunByteStringAttribute* username =
1003 msg.GetByteString(STUN_ATTR_USERNAME);
1004 ASSERT_TRUE(username != NULL);
1005 EXPECT_EQ(kTestUserName2, username->GetString());
1006}
1007
1008TEST_F(StunTest, ReadErrorCodeAttribute) {
1009 StunMessage msg;
1010 size_t size = ReadStunMessage(&msg, kStunMessageWithErrorAttribute);
1011
1012 CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, size);
1013 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
1014 const StunErrorCodeAttribute* errorcode = msg.GetErrorCode();
1015 ASSERT_TRUE(errorcode != NULL);
1016 EXPECT_EQ(kTestErrorClass, errorcode->eclass());
1017 EXPECT_EQ(kTestErrorNumber, errorcode->number());
1018 EXPECT_EQ(kTestErrorReason, errorcode->reason());
1019 EXPECT_EQ(kTestErrorCode, errorcode->code());
deadbeef996fc6b2017-04-26 09:21:22 -07001020 EXPECT_EQ(kTestErrorCode, msg.GetErrorCodeValue());
1021}
1022
1023// Test that GetErrorCodeValue returns STUN_ERROR_GLOBAL_FAILURE if the message
1024// in question doesn't have an error code attribute, rather than crashing.
1025TEST_F(StunTest, GetErrorCodeValueWithNoErrorAttribute) {
1026 StunMessage msg;
1027 ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
1028 EXPECT_EQ(STUN_ERROR_GLOBAL_FAILURE, msg.GetErrorCodeValue());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001029}
1030
1031TEST_F(StunTest, ReadMessageWithAUInt16ListAttribute) {
1032 StunMessage msg;
1033 size_t size = ReadStunMessage(&msg, kStunMessageWithUInt16ListAttribute);
1034 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1035 const StunUInt16ListAttribute* types = msg.GetUnknownAttributes();
1036 ASSERT_TRUE(types != NULL);
1037 EXPECT_EQ(3U, types->Size());
1038 EXPECT_EQ(0x1U, types->GetType(0));
1039 EXPECT_EQ(0x1000U, types->GetType(1));
1040 EXPECT_EQ(0xAB0CU, types->GetType(2));
1041}
1042
1043TEST_F(StunTest, ReadMessageWithAnUnknownAttribute) {
1044 StunMessage msg;
1045 size_t size = ReadStunMessage(&msg, kStunMessageWithUnknownAttribute);
1046 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1047
1048 // Parsing should have succeeded and there should be a USERNAME attribute
1049 const StunByteStringAttribute* username =
1050 msg.GetByteString(STUN_ATTR_USERNAME);
1051 ASSERT_TRUE(username != NULL);
1052 EXPECT_EQ(kTestUserName2, username->GetString());
1053}
1054
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001055TEST_F(StunTest, ReadMessageWithOriginAttribute) {
1056 StunMessage msg;
1057 size_t size = ReadStunMessage(&msg, kStunMessageWithOriginAttribute);
1058 CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
Yves Gerey665174f2018-06-19 15:03:05 +02001059 const StunByteStringAttribute* origin = msg.GetByteString(STUN_ATTR_ORIGIN);
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001060 ASSERT_TRUE(origin != NULL);
1061 EXPECT_EQ(kTestOrigin, origin->GetString());
1062}
1063
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001064TEST_F(StunTest, WriteMessageWithAnErrorCodeAttribute) {
1065 StunMessage msg;
1066 size_t size = sizeof(kStunMessageWithErrorAttribute);
1067
1068 msg.SetType(STUN_BINDING_ERROR_RESPONSE);
1069 msg.SetTransactionID(
1070 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
1071 kStunTransactionIdLength));
1072 CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength);
zsteinf42cc9d2017-03-27 16:17:19 -07001073 auto errorcode = StunAttribute::CreateErrorCode();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001074 errorcode->SetCode(kTestErrorCode);
1075 errorcode->SetReason(kTestErrorReason);
zsteinf42cc9d2017-03-27 16:17:19 -07001076 msg.AddAttribute(std::move(errorcode));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001077 CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, (size - 20));
1078
jbauchf1f87202016-03-30 06:43:37 -07001079 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001080 EXPECT_TRUE(msg.Write(&out));
1081 ASSERT_EQ(size, out.Length());
1082 // No padding.
1083 ASSERT_EQ(0, memcmp(out.Data(), kStunMessageWithErrorAttribute, size));
1084}
1085
1086TEST_F(StunTest, WriteMessageWithAUInt16ListAttribute) {
1087 StunMessage msg;
1088 size_t size = sizeof(kStunMessageWithUInt16ListAttribute);
1089
1090 msg.SetType(STUN_BINDING_REQUEST);
1091 msg.SetTransactionID(
1092 std::string(reinterpret_cast<const char*>(kTestTransactionId2),
1093 kStunTransactionIdLength));
1094 CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength);
zsteinf42cc9d2017-03-27 16:17:19 -07001095 auto list = StunAttribute::CreateUnknownAttributes();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001096 list->AddType(0x1U);
1097 list->AddType(0x1000U);
1098 list->AddType(0xAB0CU);
zsteinf42cc9d2017-03-27 16:17:19 -07001099 msg.AddAttribute(std::move(list));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001100 CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20));
1101
jbauchf1f87202016-03-30 06:43:37 -07001102 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001103 EXPECT_TRUE(msg.Write(&out));
1104 ASSERT_EQ(size, out.Length());
1105 // Check everything up to the padding.
1106 ASSERT_EQ(0,
1107 memcmp(out.Data(), kStunMessageWithUInt16ListAttribute, size - 2));
1108}
1109
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001110TEST_F(StunTest, WriteMessageWithOriginAttribute) {
1111 StunMessage msg;
1112 size_t size = sizeof(kStunMessageWithOriginAttribute);
1113
1114 msg.SetType(STUN_BINDING_REQUEST);
1115 msg.SetTransactionID(
1116 std::string(reinterpret_cast<const char*>(kTestTransactionId1),
1117 kStunTransactionIdLength));
zsteinf42cc9d2017-03-27 16:17:19 -07001118 auto origin =
Karl Wiberg918f50c2018-07-05 11:40:33 +02001119 absl::make_unique<StunByteStringAttribute>(STUN_ATTR_ORIGIN, kTestOrigin);
zsteinf42cc9d2017-03-27 16:17:19 -07001120 msg.AddAttribute(std::move(origin));
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001121
jbauchf1f87202016-03-30 06:43:37 -07001122 rtc::ByteBufferWriter out;
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001123 EXPECT_TRUE(msg.Write(&out));
1124 ASSERT_EQ(size, out.Length());
1125 // Check everything up to the padding
1126 ASSERT_EQ(0, memcmp(out.Data(), kStunMessageWithOriginAttribute, size - 2));
1127}
1128
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001129// Test that we fail to read messages with invalid lengths.
1130void CheckFailureToRead(const unsigned char* testcase, size_t length) {
1131 StunMessage msg;
1132 const char* input = reinterpret_cast<const char*>(testcase);
jbauchf1f87202016-03-30 06:43:37 -07001133 rtc::ByteBufferReader buf(input, length);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001134 ASSERT_FALSE(msg.Read(&buf));
1135}
1136
1137TEST_F(StunTest, FailToReadInvalidMessages) {
1138 CheckFailureToRead(kStunMessageWithZeroLength,
1139 kRealLengthOfInvalidLengthTestCases);
1140 CheckFailureToRead(kStunMessageWithSmallLength,
1141 kRealLengthOfInvalidLengthTestCases);
1142 CheckFailureToRead(kStunMessageWithExcessLength,
1143 kRealLengthOfInvalidLengthTestCases);
1144}
1145
1146// Test that we properly fail to read a non-STUN message.
1147TEST_F(StunTest, FailToReadRtcpPacket) {
1148 CheckFailureToRead(kRtcpPacket, sizeof(kRtcpPacket));
1149}
1150
1151// Check our STUN message validation code against the RFC5769 test messages.
1152TEST_F(StunTest, ValidateMessageIntegrity) {
1153 // Try the messages from RFC 5769.
1154 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1155 reinterpret_cast<const char*>(kRfc5769SampleRequest),
Yves Gerey665174f2018-06-19 15:03:05 +02001156 sizeof(kRfc5769SampleRequest), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001157 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1158 reinterpret_cast<const char*>(kRfc5769SampleRequest),
Yves Gerey665174f2018-06-19 15:03:05 +02001159 sizeof(kRfc5769SampleRequest), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001160
1161 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1162 reinterpret_cast<const char*>(kRfc5769SampleResponse),
Yves Gerey665174f2018-06-19 15:03:05 +02001163 sizeof(kRfc5769SampleResponse), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001164 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1165 reinterpret_cast<const char*>(kRfc5769SampleResponse),
Yves Gerey665174f2018-06-19 15:03:05 +02001166 sizeof(kRfc5769SampleResponse), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001167
1168 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1169 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
Yves Gerey665174f2018-06-19 15:03:05 +02001170 sizeof(kRfc5769SampleResponseIPv6), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001171 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1172 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
Yves Gerey665174f2018-06-19 15:03:05 +02001173 sizeof(kRfc5769SampleResponseIPv6), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001174
1175 // We first need to compute the key for the long-term authentication HMAC.
1176 std::string key;
1177 ComputeStunCredentialHash(kRfc5769SampleMsgWithAuthUsername,
Yves Gerey665174f2018-06-19 15:03:05 +02001178 kRfc5769SampleMsgWithAuthRealm,
1179 kRfc5769SampleMsgWithAuthPassword, &key);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001180 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1181 reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth),
1182 sizeof(kRfc5769SampleRequestLongTermAuth), key));
1183 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1184 reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth),
Yves Gerey665174f2018-06-19 15:03:05 +02001185 sizeof(kRfc5769SampleRequestLongTermAuth), "InvalidPassword"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001186
1187 // Try some edge cases.
1188 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1189 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
Yves Gerey665174f2018-06-19 15:03:05 +02001190 sizeof(kStunMessageWithZeroLength), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001191 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1192 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
Yves Gerey665174f2018-06-19 15:03:05 +02001193 sizeof(kStunMessageWithExcessLength), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001194 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1195 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
Yves Gerey665174f2018-06-19 15:03:05 +02001196 sizeof(kStunMessageWithSmallLength), kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001197
katrielc1a206102016-06-20 05:13:16 -07001198 // Again, but with the lengths matching what is claimed in the headers.
1199 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1200 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1201 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithZeroLength[2]),
1202 kRfc5769SampleMsgPassword));
1203 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1204 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1205 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithExcessLength[2]),
1206 kRfc5769SampleMsgPassword));
1207 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1208 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1209 kStunHeaderSize + rtc::GetBE16(&kStunMessageWithSmallLength[2]),
1210 kRfc5769SampleMsgPassword));
1211
1212 // Check that a too-short HMAC doesn't cause buffer overflow.
1213 EXPECT_FALSE(StunMessage::ValidateMessageIntegrity(
1214 reinterpret_cast<const char*>(kStunMessageWithBadHmacAtEnd),
Yves Gerey665174f2018-06-19 15:03:05 +02001215 sizeof(kStunMessageWithBadHmacAtEnd), kRfc5769SampleMsgPassword));
katrielc1a206102016-06-20 05:13:16 -07001216
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001217 // Test that munging a single bit anywhere in the message causes the
1218 // message-integrity check to fail, unless it is after the M-I attribute.
1219 char buf[sizeof(kRfc5769SampleRequest)];
1220 memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest));
1221 for (size_t i = 0; i < sizeof(buf); ++i) {
1222 buf[i] ^= 0x01;
1223 if (i > 0)
1224 buf[i - 1] ^= 0x01;
Yves Gerey665174f2018-06-19 15:03:05 +02001225 EXPECT_EQ(i >= sizeof(buf) - 8,
1226 StunMessage::ValidateMessageIntegrity(buf, sizeof(buf),
1227 kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001228 }
1229}
1230
1231// Validate that we generate correct MESSAGE-INTEGRITY attributes.
1232// Note the use of IceMessage instead of StunMessage; this is necessary because
1233// the RFC5769 test messages used include attributes not found in basic STUN.
1234TEST_F(StunTest, AddMessageIntegrity) {
1235 IceMessage msg;
jbauchf1f87202016-03-30 06:43:37 -07001236 rtc::ByteBufferReader buf(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001237 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1238 sizeof(kRfc5769SampleRequestWithoutMI));
1239 EXPECT_TRUE(msg.Read(&buf));
1240 EXPECT_TRUE(msg.AddMessageIntegrity(kRfc5769SampleMsgPassword));
1241 const StunByteStringAttribute* mi_attr =
1242 msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
1243 EXPECT_EQ(20U, mi_attr->length());
Yves Gerey665174f2018-06-19 15:03:05 +02001244 EXPECT_EQ(
1245 0, memcmp(mi_attr->bytes(), kCalculatedHmac1, sizeof(kCalculatedHmac1)));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001246
jbauchf1f87202016-03-30 06:43:37 -07001247 rtc::ByteBufferWriter buf1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001248 EXPECT_TRUE(msg.Write(&buf1));
1249 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
Yves Gerey665174f2018-06-19 15:03:05 +02001250 reinterpret_cast<const char*>(buf1.Data()), buf1.Length(),
1251 kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001252
1253 IceMessage msg2;
jbauchf1f87202016-03-30 06:43:37 -07001254 rtc::ByteBufferReader buf2(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001255 reinterpret_cast<const char*>(kRfc5769SampleResponseWithoutMI),
1256 sizeof(kRfc5769SampleResponseWithoutMI));
1257 EXPECT_TRUE(msg2.Read(&buf2));
1258 EXPECT_TRUE(msg2.AddMessageIntegrity(kRfc5769SampleMsgPassword));
1259 const StunByteStringAttribute* mi_attr2 =
1260 msg2.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
1261 EXPECT_EQ(20U, mi_attr2->length());
1262 EXPECT_EQ(
1263 0, memcmp(mi_attr2->bytes(), kCalculatedHmac2, sizeof(kCalculatedHmac2)));
1264
jbauchf1f87202016-03-30 06:43:37 -07001265 rtc::ByteBufferWriter buf3;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001266 EXPECT_TRUE(msg2.Write(&buf3));
1267 EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
Yves Gerey665174f2018-06-19 15:03:05 +02001268 reinterpret_cast<const char*>(buf3.Data()), buf3.Length(),
1269 kRfc5769SampleMsgPassword));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001270}
1271
1272// Check our STUN message validation code against the RFC5769 test messages.
1273TEST_F(StunTest, ValidateFingerprint) {
1274 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1275 reinterpret_cast<const char*>(kRfc5769SampleRequest),
1276 sizeof(kRfc5769SampleRequest)));
1277 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1278 reinterpret_cast<const char*>(kRfc5769SampleResponse),
1279 sizeof(kRfc5769SampleResponse)));
1280 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1281 reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6),
1282 sizeof(kRfc5769SampleResponseIPv6)));
1283
1284 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1285 reinterpret_cast<const char*>(kStunMessageWithZeroLength),
1286 sizeof(kStunMessageWithZeroLength)));
1287 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1288 reinterpret_cast<const char*>(kStunMessageWithExcessLength),
1289 sizeof(kStunMessageWithExcessLength)));
1290 EXPECT_FALSE(StunMessage::ValidateFingerprint(
1291 reinterpret_cast<const char*>(kStunMessageWithSmallLength),
1292 sizeof(kStunMessageWithSmallLength)));
1293
1294 // Test that munging a single bit anywhere in the message causes the
1295 // fingerprint check to fail.
1296 char buf[sizeof(kRfc5769SampleRequest)];
1297 memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest));
1298 for (size_t i = 0; i < sizeof(buf); ++i) {
1299 buf[i] ^= 0x01;
1300 if (i > 0)
1301 buf[i - 1] ^= 0x01;
1302 EXPECT_FALSE(StunMessage::ValidateFingerprint(buf, sizeof(buf)));
1303 }
1304 // Put them all back to normal and the check should pass again.
1305 buf[sizeof(buf) - 1] ^= 0x01;
1306 EXPECT_TRUE(StunMessage::ValidateFingerprint(buf, sizeof(buf)));
1307}
1308
1309TEST_F(StunTest, AddFingerprint) {
1310 IceMessage msg;
jbauchf1f87202016-03-30 06:43:37 -07001311 rtc::ByteBufferReader buf(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001312 reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI),
1313 sizeof(kRfc5769SampleRequestWithoutMI));
1314 EXPECT_TRUE(msg.Read(&buf));
1315 EXPECT_TRUE(msg.AddFingerprint());
1316
jbauchf1f87202016-03-30 06:43:37 -07001317 rtc::ByteBufferWriter buf1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001318 EXPECT_TRUE(msg.Write(&buf1));
1319 EXPECT_TRUE(StunMessage::ValidateFingerprint(
1320 reinterpret_cast<const char*>(buf1.Data()), buf1.Length()));
1321}
1322
1323// Sample "GTURN" relay message.
Yves Gerey665174f2018-06-19 15:03:05 +02001324// clang-format off
1325// clang formatting doesn't respect inline comments.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001326static const unsigned char kRelayMessage[] = {
1327 0x00, 0x01, 0x00, 88, // message header
1328 0x21, 0x12, 0xA4, 0x42, // magic cookie
1329 '0', '1', '2', '3', // transaction id
1330 '4', '5', '6', '7',
1331 '8', '9', 'a', 'b',
1332 0x00, 0x01, 0x00, 8, // mapped address
1333 0x00, 0x01, 0x00, 13,
1334 0x00, 0x00, 0x00, 17,
1335 0x00, 0x06, 0x00, 12, // username
1336 'a', 'b', 'c', 'd',
1337 'e', 'f', 'g', 'h',
1338 'i', 'j', 'k', 'l',
1339 0x00, 0x0d, 0x00, 4, // lifetime
1340 0x00, 0x00, 0x00, 11,
1341 0x00, 0x0f, 0x00, 4, // magic cookie
1342 0x72, 0xc6, 0x4b, 0xc6,
1343 0x00, 0x10, 0x00, 4, // bandwidth
1344 0x00, 0x00, 0x00, 6,
1345 0x00, 0x11, 0x00, 8, // destination address
1346 0x00, 0x01, 0x00, 13,
1347 0x00, 0x00, 0x00, 17,
1348 0x00, 0x12, 0x00, 8, // source address 2
1349 0x00, 0x01, 0x00, 13,
1350 0x00, 0x00, 0x00, 17,
1351 0x00, 0x13, 0x00, 7, // data
1352 'a', 'b', 'c', 'd',
1353 'e', 'f', 'g', 0 // DATA must be padded per rfc5766.
1354};
Yves Gerey665174f2018-06-19 15:03:05 +02001355// clang-format on
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001356
1357// Test that we can read the GTURN-specific fields.
1358TEST_F(StunTest, ReadRelayMessage) {
1359 RelayMessage msg, msg2;
1360
1361 const char* input = reinterpret_cast<const char*>(kRelayMessage);
1362 size_t size = sizeof(kRelayMessage);
jbauchf1f87202016-03-30 06:43:37 -07001363 rtc::ByteBufferReader buf(input, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001364 EXPECT_TRUE(msg.Read(&buf));
1365
1366 EXPECT_EQ(STUN_BINDING_REQUEST, msg.type());
1367 EXPECT_EQ(size - 20, msg.length());
1368 EXPECT_EQ("0123456789ab", msg.transaction_id());
1369
1370 msg2.SetType(STUN_BINDING_REQUEST);
1371 msg2.SetTransactionID("0123456789ab");
1372
1373 in_addr legacy_in_addr;
1374 legacy_in_addr.s_addr = htonl(17U);
1375 rtc::IPAddress legacy_ip(legacy_in_addr);
1376
1377 const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS);
1378 ASSERT_TRUE(addr != NULL);
1379 EXPECT_EQ(1, addr->family());
1380 EXPECT_EQ(13, addr->port());
1381 EXPECT_EQ(legacy_ip, addr->ipaddr());
1382
zsteinf42cc9d2017-03-27 16:17:19 -07001383 auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001384 addr2->SetPort(13);
1385 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001386 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001387
1388 const StunByteStringAttribute* bytes = msg.GetByteString(STUN_ATTR_USERNAME);
1389 ASSERT_TRUE(bytes != NULL);
1390 EXPECT_EQ(12U, bytes->length());
1391 EXPECT_EQ("abcdefghijkl", bytes->GetString());
1392
zsteinf42cc9d2017-03-27 16:17:19 -07001393 auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001394 bytes2->CopyBytes("abcdefghijkl");
zsteinf42cc9d2017-03-27 16:17:19 -07001395 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001396
1397 const StunUInt32Attribute* uval = msg.GetUInt32(STUN_ATTR_LIFETIME);
1398 ASSERT_TRUE(uval != NULL);
1399 EXPECT_EQ(11U, uval->value());
1400
zsteinf42cc9d2017-03-27 16:17:19 -07001401 auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001402 uval2->SetValue(11);
zsteinf42cc9d2017-03-27 16:17:19 -07001403 msg2.AddAttribute(std::move(uval2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001404
1405 bytes = msg.GetByteString(STUN_ATTR_MAGIC_COOKIE);
1406 ASSERT_TRUE(bytes != NULL);
1407 EXPECT_EQ(4U, bytes->length());
Yves Gerey665174f2018-06-19 15:03:05 +02001408 EXPECT_EQ(0, memcmp(bytes->bytes(), TURN_MAGIC_COOKIE_VALUE,
1409 sizeof(TURN_MAGIC_COOKIE_VALUE)));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001410
1411 bytes2 = StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
1412 bytes2->CopyBytes(reinterpret_cast<const char*>(TURN_MAGIC_COOKIE_VALUE),
1413 sizeof(TURN_MAGIC_COOKIE_VALUE));
zsteinf42cc9d2017-03-27 16:17:19 -07001414 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001415
1416 uval = msg.GetUInt32(STUN_ATTR_BANDWIDTH);
1417 ASSERT_TRUE(uval != NULL);
1418 EXPECT_EQ(6U, uval->value());
1419
1420 uval2 = StunAttribute::CreateUInt32(STUN_ATTR_BANDWIDTH);
1421 uval2->SetValue(6);
zsteinf42cc9d2017-03-27 16:17:19 -07001422 msg2.AddAttribute(std::move(uval2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001423
1424 addr = msg.GetAddress(STUN_ATTR_DESTINATION_ADDRESS);
1425 ASSERT_TRUE(addr != NULL);
1426 EXPECT_EQ(1, addr->family());
1427 EXPECT_EQ(13, addr->port());
1428 EXPECT_EQ(legacy_ip, addr->ipaddr());
1429
1430 addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
1431 addr2->SetPort(13);
1432 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001433 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001434
1435 addr = msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2);
1436 ASSERT_TRUE(addr != NULL);
1437 EXPECT_EQ(1, addr->family());
1438 EXPECT_EQ(13, addr->port());
1439 EXPECT_EQ(legacy_ip, addr->ipaddr());
1440
1441 addr2 = StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2);
1442 addr2->SetPort(13);
1443 addr2->SetIP(legacy_ip);
zsteinf42cc9d2017-03-27 16:17:19 -07001444 msg2.AddAttribute(std::move(addr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001445
1446 bytes = msg.GetByteString(STUN_ATTR_DATA);
1447 ASSERT_TRUE(bytes != NULL);
1448 EXPECT_EQ(7U, bytes->length());
1449 EXPECT_EQ("abcdefg", bytes->GetString());
1450
1451 bytes2 = StunAttribute::CreateByteString(STUN_ATTR_DATA);
1452 bytes2->CopyBytes("abcdefg");
zsteinf42cc9d2017-03-27 16:17:19 -07001453 msg2.AddAttribute(std::move(bytes2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001454
jbauchf1f87202016-03-30 06:43:37 -07001455 rtc::ByteBufferWriter out;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001456 EXPECT_TRUE(msg.Write(&out));
1457 EXPECT_EQ(size, out.Length());
1458 size_t len1 = out.Length();
jbauchf1f87202016-03-30 06:43:37 -07001459 rtc::ByteBufferReader read_buf(out);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001460 std::string outstring;
jbauchf1f87202016-03-30 06:43:37 -07001461 read_buf.ReadString(&outstring, len1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001462 EXPECT_EQ(0, memcmp(outstring.c_str(), input, len1));
1463
jbauchf1f87202016-03-30 06:43:37 -07001464 rtc::ByteBufferWriter out2;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001465 EXPECT_TRUE(msg2.Write(&out2));
1466 EXPECT_EQ(size, out2.Length());
1467 size_t len2 = out2.Length();
jbauchf1f87202016-03-30 06:43:37 -07001468 rtc::ByteBufferReader read_buf2(out2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001469 std::string outstring2;
jbauchf1f87202016-03-30 06:43:37 -07001470 read_buf2.ReadString(&outstring2, len2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001471 EXPECT_EQ(0, memcmp(outstring2.c_str(), input, len2));
1472}
1473
Jonas Oreland202994c2017-12-18 12:10:43 +01001474// Test that we can remove attribute from a message.
1475TEST_F(StunTest, RemoveAttribute) {
1476 StunMessage msg;
1477
1478 // Removing something that does exist should return nullptr.
1479 EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr);
1480
1481 {
1482 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1483 attr->CopyBytes("kes", sizeof("kes"));
1484 msg.AddAttribute(std::move(attr));
1485 }
1486
1487 size_t len = msg.length();
1488 {
1489 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1490 ASSERT_NE(attr, nullptr);
1491 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1492 EXPECT_STREQ("kes",
1493 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1494 EXPECT_LT(msg.length(), len);
1495 }
1496
1497 // Now add same attribute type twice.
1498 {
1499 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1500 attr->CopyBytes("kes", sizeof("kes"));
1501 msg.AddAttribute(std::move(attr));
1502 }
1503
1504 {
1505 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1506 attr->CopyBytes("kenta", sizeof("kenta"));
1507 msg.AddAttribute(std::move(attr));
1508 }
1509
1510 // Remove should remove the last added occurrence.
1511 {
1512 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1513 ASSERT_NE(attr, nullptr);
1514 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1515 EXPECT_STREQ("kenta",
1516 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1517 }
1518
1519 // Remove should remove the last added occurrence.
1520 {
1521 auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME);
1522 ASSERT_NE(attr, nullptr);
1523 EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME);
1524 EXPECT_STREQ("kes",
1525 static_cast<StunByteStringAttribute*>(attr.get())->bytes());
1526 }
1527
1528 // Removing something that does exist should return nullptr.
1529 EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr);
1530}
1531
1532// Test CopyStunAttribute
1533TEST_F(StunTest, CopyAttribute) {
1534 rtc::ByteBufferWriter buf;
Yves Gerey665174f2018-06-19 15:03:05 +02001535 rtc::ByteBufferWriter* buffer_ptrs[] = {&buf, nullptr};
Jonas Oreland202994c2017-12-18 12:10:43 +01001536 // Test both with and without supplied ByteBufferWriter.
1537 for (auto buffer_ptr : buffer_ptrs) {
Yves Gerey665174f2018-06-19 15:03:05 +02001538 { // Test StunByteStringAttribute.
Jonas Oreland202994c2017-12-18 12:10:43 +01001539 auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
1540 attr->CopyBytes("kes", sizeof("kes"));
1541
1542 auto copy = CopyStunAttribute(*attr.get(), buffer_ptr);
1543 ASSERT_EQ(copy->value_type(), STUN_VALUE_BYTE_STRING);
1544 EXPECT_STREQ("kes",
1545 static_cast<StunByteStringAttribute*>(copy.get())->bytes());
1546 }
1547
Yves Gerey665174f2018-06-19 15:03:05 +02001548 { // Test StunAddressAttribute.
Jonas Oreland202994c2017-12-18 12:10:43 +01001549 rtc::IPAddress test_ip(kIPv6TestAddress2);
1550 auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
1551 rtc::SocketAddress test_addr(test_ip, kTestMessagePort2);
1552 addr->SetAddress(test_addr);
Yves Gerey665174f2018-06-19 15:03:05 +02001553 CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6,
1554 kTestMessagePort2, test_ip);
Jonas Oreland202994c2017-12-18 12:10:43 +01001555
1556 auto copy = CopyStunAttribute(*addr.get(), buffer_ptr);
1557 ASSERT_EQ(copy->value_type(), STUN_VALUE_ADDRESS);
1558 CheckStunAddressAttribute(static_cast<StunAddressAttribute*>(copy.get()),
1559 STUN_ADDRESS_IPV6, kTestMessagePort2, test_ip);
1560 }
1561 }
1562}
1563
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001564} // namespace cricket