blob: e4dbd3a0f5521738e977ec30d0813b30570b9ba2 [file] [log] [blame]
deadbeef1dcb1642017-03-30 04:08:161/*
2 * Copyright 2012 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
Jonas Olssona4d87372019-07-05 17:08:3311#include "pc/ice_server_parsing.h"
12
deadbeef1dcb1642017-03-30 04:08:1613#include <string>
14#include <vector>
15
Steve Anton10542f22019-01-11 17:11:0016#include "p2p/base/port_interface.h"
Steve Anton10542f22019-01-11 17:11:0017#include "rtc_base/ip_address.h"
18#include "rtc_base/socket_address.h"
Yves Gerey3e707812018-11-28 15:47:4919#include "test/gtest.h"
deadbeef1dcb1642017-03-30 04:08:1620
21namespace webrtc {
22
Mirko Bonadei6a489f22019-04-09 13:11:1223class IceServerParsingTest : public ::testing::Test {
deadbeef1dcb1642017-03-30 04:08:1624 public:
25 // Convenience functions for parsing a single URL. Result is stored in
26 // |stun_servers_| and |turn_servers_|.
27 bool ParseUrl(const std::string& url) {
28 return ParseUrl(url, std::string(), std::string());
29 }
30
31 bool ParseTurnUrl(const std::string& url) {
32 return ParseUrl(url, "username", "password");
33 }
34
35 bool ParseUrl(const std::string& url,
36 const std::string& username,
37 const std::string& password) {
38 return ParseUrl(
39 url, username, password,
40 PeerConnectionInterface::TlsCertPolicy::kTlsCertPolicySecure);
41 }
42
43 bool ParseUrl(const std::string& url,
44 const std::string& username,
45 const std::string& password,
46 PeerConnectionInterface::TlsCertPolicy tls_certificate_policy) {
Emad Omaradab1d2d2017-06-16 22:43:1147 return ParseUrl(url, username, password, tls_certificate_policy, "");
48 }
49
50 bool ParseUrl(const std::string& url,
51 const std::string& username,
52 const std::string& password,
53 PeerConnectionInterface::TlsCertPolicy tls_certificate_policy,
54 const std::string& hostname) {
deadbeef1dcb1642017-03-30 04:08:1655 stun_servers_.clear();
56 turn_servers_.clear();
57 PeerConnectionInterface::IceServers servers;
58 PeerConnectionInterface::IceServer server;
59 server.urls.push_back(url);
60 server.username = username;
61 server.password = password;
62 server.tls_cert_policy = tls_certificate_policy;
Emad Omaradab1d2d2017-06-16 22:43:1163 server.hostname = hostname;
deadbeef1dcb1642017-03-30 04:08:1664 servers.push_back(server);
65 return webrtc::ParseIceServers(servers, &stun_servers_, &turn_servers_) ==
66 webrtc::RTCErrorType::NONE;
67 }
68
69 protected:
70 cricket::ServerAddresses stun_servers_;
71 std::vector<cricket::RelayServerConfig> turn_servers_;
72};
73
74// Make sure all STUN/TURN prefixes are parsed correctly.
75TEST_F(IceServerParsingTest, ParseStunPrefixes) {
76 EXPECT_TRUE(ParseUrl("stun:hostname"));
77 EXPECT_EQ(1U, stun_servers_.size());
78 EXPECT_EQ(0U, turn_servers_.size());
79
80 EXPECT_TRUE(ParseUrl("stuns:hostname"));
81 EXPECT_EQ(1U, stun_servers_.size());
82 EXPECT_EQ(0U, turn_servers_.size());
83
84 EXPECT_TRUE(ParseTurnUrl("turn:hostname"));
85 EXPECT_EQ(0U, stun_servers_.size());
86 EXPECT_EQ(1U, turn_servers_.size());
87 EXPECT_EQ(cricket::PROTO_UDP, turn_servers_[0].ports[0].proto);
88
89 EXPECT_TRUE(ParseTurnUrl("turns:hostname"));
90 EXPECT_EQ(0U, stun_servers_.size());
91 EXPECT_EQ(1U, turn_servers_.size());
92 EXPECT_EQ(cricket::PROTO_TLS, turn_servers_[0].ports[0].proto);
Sergey Silkin9c147dd2018-09-12 10:45:3893 EXPECT_TRUE(turn_servers_[0].tls_cert_policy ==
94 cricket::TlsCertPolicy::TLS_CERT_POLICY_SECURE);
deadbeef1dcb1642017-03-30 04:08:1695
96 EXPECT_TRUE(ParseUrl(
97 "turns:hostname", "username", "password",
98 PeerConnectionInterface::TlsCertPolicy::kTlsCertPolicyInsecureNoCheck));
99 EXPECT_EQ(0U, stun_servers_.size());
100 EXPECT_EQ(1U, turn_servers_.size());
Sergey Silkin9c147dd2018-09-12 10:45:38101 EXPECT_TRUE(turn_servers_[0].tls_cert_policy ==
102 cricket::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK);
deadbeef1dcb1642017-03-30 04:08:16103 EXPECT_EQ(cricket::PROTO_TLS, turn_servers_[0].ports[0].proto);
104
105 // invalid prefixes
106 EXPECT_FALSE(ParseUrl("stunn:hostname"));
107 EXPECT_FALSE(ParseUrl(":hostname"));
108 EXPECT_FALSE(ParseUrl(":"));
109 EXPECT_FALSE(ParseUrl(""));
110}
111
112TEST_F(IceServerParsingTest, VerifyDefaults) {
113 // TURNS defaults
114 EXPECT_TRUE(ParseTurnUrl("turns:hostname"));
115 EXPECT_EQ(1U, turn_servers_.size());
116 EXPECT_EQ(5349, turn_servers_[0].ports[0].address.port());
117 EXPECT_EQ(cricket::PROTO_TLS, turn_servers_[0].ports[0].proto);
118
119 // TURN defaults
120 EXPECT_TRUE(ParseTurnUrl("turn:hostname"));
121 EXPECT_EQ(1U, turn_servers_.size());
122 EXPECT_EQ(3478, turn_servers_[0].ports[0].address.port());
123 EXPECT_EQ(cricket::PROTO_UDP, turn_servers_[0].ports[0].proto);
124
125 // STUN defaults
126 EXPECT_TRUE(ParseUrl("stun:hostname"));
127 EXPECT_EQ(1U, stun_servers_.size());
128 EXPECT_EQ(3478, stun_servers_.begin()->port());
129}
130
131// Check that the 6 combinations of IPv4/IPv6/hostname and with/without port
132// can be parsed correctly.
133TEST_F(IceServerParsingTest, ParseHostnameAndPort) {
134 EXPECT_TRUE(ParseUrl("stun:1.2.3.4:1234"));
135 EXPECT_EQ(1U, stun_servers_.size());
136 EXPECT_EQ("1.2.3.4", stun_servers_.begin()->hostname());
137 EXPECT_EQ(1234, stun_servers_.begin()->port());
138
139 EXPECT_TRUE(ParseUrl("stun:[1:2:3:4:5:6:7:8]:4321"));
140 EXPECT_EQ(1U, stun_servers_.size());
141 EXPECT_EQ("1:2:3:4:5:6:7:8", stun_servers_.begin()->hostname());
142 EXPECT_EQ(4321, stun_servers_.begin()->port());
143
144 EXPECT_TRUE(ParseUrl("stun:hostname:9999"));
145 EXPECT_EQ(1U, stun_servers_.size());
146 EXPECT_EQ("hostname", stun_servers_.begin()->hostname());
147 EXPECT_EQ(9999, stun_servers_.begin()->port());
148
149 EXPECT_TRUE(ParseUrl("stun:1.2.3.4"));
150 EXPECT_EQ(1U, stun_servers_.size());
151 EXPECT_EQ("1.2.3.4", stun_servers_.begin()->hostname());
152 EXPECT_EQ(3478, stun_servers_.begin()->port());
153
154 EXPECT_TRUE(ParseUrl("stun:[1:2:3:4:5:6:7:8]"));
155 EXPECT_EQ(1U, stun_servers_.size());
156 EXPECT_EQ("1:2:3:4:5:6:7:8", stun_servers_.begin()->hostname());
157 EXPECT_EQ(3478, stun_servers_.begin()->port());
158
159 EXPECT_TRUE(ParseUrl("stun:hostname"));
160 EXPECT_EQ(1U, stun_servers_.size());
161 EXPECT_EQ("hostname", stun_servers_.begin()->hostname());
162 EXPECT_EQ(3478, stun_servers_.begin()->port());
163
Emad Omaradab1d2d2017-06-16 22:43:11164 // Both TURN IP and host exist
165 EXPECT_TRUE(
166 ParseUrl("turn:1.2.3.4:1234", "username", "password",
167 PeerConnectionInterface::TlsCertPolicy::kTlsCertPolicySecure,
168 "hostname"));
169 EXPECT_EQ(1U, turn_servers_.size());
170 rtc::SocketAddress address = turn_servers_[0].ports[0].address;
171 EXPECT_EQ("hostname", address.hostname());
172 EXPECT_EQ(1234, address.port());
173 EXPECT_FALSE(address.IsUnresolvedIP());
174 EXPECT_EQ("1.2.3.4", address.ipaddr().ToString());
175
deadbeef1dcb1642017-03-30 04:08:16176 // Try some invalid hostname:port strings.
177 EXPECT_FALSE(ParseUrl("stun:hostname:99a99"));
178 EXPECT_FALSE(ParseUrl("stun:hostname:-1"));
179 EXPECT_FALSE(ParseUrl("stun:hostname:port:more"));
180 EXPECT_FALSE(ParseUrl("stun:hostname:port more"));
181 EXPECT_FALSE(ParseUrl("stun:hostname:"));
182 EXPECT_FALSE(ParseUrl("stun:[1:2:3:4:5:6:7:8]junk:1000"));
183 EXPECT_FALSE(ParseUrl("stun::5555"));
184 EXPECT_FALSE(ParseUrl("stun:"));
Harald Alvestranda3dd7722020-11-27 08:05:42185 // Test illegal URLs according to RFC 3986 (URI generic syntax)
186 // and RFC 7064 (URI schemes for STUN and TURN)
187 EXPECT_FALSE(ParseUrl("stun:/hostname")); // / is not allowed
188 EXPECT_FALSE(ParseUrl("stun:?hostname")); // ? is not allowed
189 EXPECT_FALSE(ParseUrl("stun:#hostname")); // # is not allowed
deadbeef1dcb1642017-03-30 04:08:16190}
191
192// Test parsing the "?transport=xxx" part of the URL.
193TEST_F(IceServerParsingTest, ParseTransport) {
194 EXPECT_TRUE(ParseTurnUrl("turn:hostname:1234?transport=tcp"));
195 EXPECT_EQ(1U, turn_servers_.size());
196 EXPECT_EQ(cricket::PROTO_TCP, turn_servers_[0].ports[0].proto);
197
198 EXPECT_TRUE(ParseTurnUrl("turn:hostname?transport=udp"));
199 EXPECT_EQ(1U, turn_servers_.size());
200 EXPECT_EQ(cricket::PROTO_UDP, turn_servers_[0].ports[0].proto);
201
202 EXPECT_FALSE(ParseTurnUrl("turn:hostname?transport=invalid"));
203 EXPECT_FALSE(ParseTurnUrl("turn:hostname?transport="));
204 EXPECT_FALSE(ParseTurnUrl("turn:hostname?="));
205 EXPECT_FALSE(ParseTurnUrl("turn:hostname?"));
206 EXPECT_FALSE(ParseTurnUrl("?"));
207}
208
Niels Möllerdb4def92019-03-18 15:53:59209// Reject pre-RFC 7065 syntax with ICE username contained in URL.
210TEST_F(IceServerParsingTest, ParseRejectsUsername) {
211 EXPECT_FALSE(ParseTurnUrl("turn:user@hostname"));
deadbeef1dcb1642017-03-30 04:08:16212}
213
214// Test that username and password from IceServer is copied into the resulting
215// RelayServerConfig.
216TEST_F(IceServerParsingTest, CopyUsernameAndPasswordFromIceServer) {
217 EXPECT_TRUE(ParseUrl("turn:hostname", "username", "password"));
218 EXPECT_EQ(1U, turn_servers_.size());
219 EXPECT_EQ("username", turn_servers_[0].credentials.username);
220 EXPECT_EQ("password", turn_servers_[0].credentials.password);
221}
222
223// Ensure that if a server has multiple URLs, each one is parsed.
224TEST_F(IceServerParsingTest, ParseMultipleUrls) {
225 PeerConnectionInterface::IceServers servers;
226 PeerConnectionInterface::IceServer server;
227 server.urls.push_back("stun:hostname");
228 server.urls.push_back("turn:hostname");
229 server.username = "foo";
230 server.password = "bar";
231 servers.push_back(server);
232 EXPECT_EQ(webrtc::RTCErrorType::NONE,
233 webrtc::ParseIceServers(servers, &stun_servers_, &turn_servers_));
234 EXPECT_EQ(1U, stun_servers_.size());
235 EXPECT_EQ(1U, turn_servers_.size());
236}
237
238// Ensure that TURN servers are given unique priorities,
239// so that their resulting candidates have unique priorities.
240TEST_F(IceServerParsingTest, TurnServerPrioritiesUnique) {
241 PeerConnectionInterface::IceServers servers;
242 PeerConnectionInterface::IceServer server;
243 server.urls.push_back("turn:hostname");
244 server.urls.push_back("turn:hostname2");
245 server.username = "foo";
246 server.password = "bar";
247 servers.push_back(server);
248 EXPECT_EQ(webrtc::RTCErrorType::NONE,
249 webrtc::ParseIceServers(servers, &stun_servers_, &turn_servers_));
250 EXPECT_EQ(2U, turn_servers_.size());
251 EXPECT_NE(turn_servers_[0].priority, turn_servers_[1].priority);
252}
253
254} // namespace webrtc