1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/base/port_util.h"
6
7 #include <limits>
8 #include <set>
9
10 #include "base/containers/fixed_flat_map.h"
11 #include "base/lazy_instance.h"
12 #include "base/logging.h"
13 #include "base/metrics/histogram_functions.h"
14 #include "base/notreached.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_util.h"
17 #include "url/url_constants.h"
18
19 namespace net {
20
21 namespace {
22
23 // The general list of blocked ports. Will be blocked unless a specific
24 // protocol overrides it. (Ex: ftp can use port 21)
25 // When adding a port to the list, consider also adding it to kAllowablePorts,
26 // below. See <https://fetch.spec.whatwg.org/#port-blocking>.
27 const int kRestrictedPorts[] = {
28 1, // tcpmux
29 7, // echo
30 9, // discard
31 11, // systat
32 13, // daytime
33 15, // netstat
34 17, // qotd
35 19, // chargen
36 20, // ftp data
37 21, // ftp access
38 22, // ssh
39 23, // telnet
40 25, // smtp
41 37, // time
42 42, // name
43 43, // nicname
44 53, // domain
45 69, // tftp
46 77, // priv-rjs
47 79, // finger
48 87, // ttylink
49 95, // supdup
50 101, // hostriame
51 102, // iso-tsap
52 103, // gppitnp
53 104, // acr-nema
54 109, // pop2
55 110, // pop3
56 111, // sunrpc
57 113, // auth
58 115, // sftp
59 117, // uucp-path
60 119, // nntp
61 123, // NTP
62 135, // loc-srv /epmap
63 137, // netbios
64 139, // netbios
65 143, // imap2
66 161, // snmp
67 179, // BGP
68 389, // ldap
69 427, // SLP (Also used by Apple Filing Protocol)
70 465, // smtp+ssl
71 512, // print / exec
72 513, // login
73 514, // shell
74 515, // printer
75 526, // tempo
76 530, // courier
77 531, // chat
78 532, // netnews
79 540, // uucp
80 548, // AFP (Apple Filing Protocol)
81 554, // rtsp
82 556, // remotefs
83 563, // nntp+ssl
84 587, // smtp (rfc6409)
85 601, // syslog-conn (rfc3195)
86 636, // ldap+ssl
87 989, // ftps-data
88 990, // ftps
89 993, // ldap+ssl
90 995, // pop3+ssl
91 1719, // h323gatestat
92 1720, // h323hostcall
93 1723, // pptp
94 2049, // nfs
95 3659, // apple-sasl / PasswordServer
96 4045, // lockd
97 5060, // sip
98 5061, // sips
99 6000, // X11
100 6566, // sane-port
101 6665, // Alternate IRC [Apple addition]
102 6666, // Alternate IRC [Apple addition]
103 6667, // Standard IRC [Apple addition]
104 6668, // Alternate IRC [Apple addition]
105 6669, // Alternate IRC [Apple addition]
106 6697, // IRC + TLS
107 10080, // Amanda
108 };
109
110 base::LazyInstance<std::multiset<int>>::Leaky g_explicitly_allowed_ports =
111 LAZY_INSTANCE_INITIALIZER;
112
113 // List of ports which are permitted to be reenabled despite being in
114 // kRestrictedList. When adding an port to this list you should also update the
115 // enterprise policy to document the fact that the value can be set. Ports
116 // should only remain in this list for about a year to give time for users to
117 // migrate off while stopping them from becoming permanent parts of the web
118 // platform.
119 constexpr int kAllowablePorts[] = {};
120
121 int g_scoped_allowable_port = 0;
122
123 } // namespace
124
IsPortValid(int port)125 bool IsPortValid(int port) {
126 return port >= 0 && port <= std::numeric_limits<uint16_t>::max();
127 }
128
IsWellKnownPort(int port)129 bool IsWellKnownPort(int port) {
130 return port >= 0 && port < 1024;
131 }
132
IsPortAllowedForScheme(int port,std::string_view url_scheme)133 bool IsPortAllowedForScheme(int port, std::string_view url_scheme) {
134 // Reject invalid ports.
135 if (!IsPortValid(port))
136 return false;
137
138 // Allow explicitly allowed ports for any scheme.
139 if (g_explicitly_allowed_ports.Get().count(port) > 0)
140 return true;
141
142 // Finally check against the generic list of restricted ports for all
143 // schemes.
144 for (int restricted_port : kRestrictedPorts) {
145 if (restricted_port == port)
146 return false;
147 }
148
149 return true;
150 }
151
GetCountOfExplicitlyAllowedPorts()152 size_t GetCountOfExplicitlyAllowedPorts() {
153 return g_explicitly_allowed_ports.Get().size();
154 }
155
156 // Specifies a comma separated list of port numbers that should be accepted
157 // despite bans. If the string is invalid no allowed ports are stored.
SetExplicitlyAllowedPorts(base::span<const uint16_t> allowed_ports)158 void SetExplicitlyAllowedPorts(base::span<const uint16_t> allowed_ports) {
159 std::multiset<int> ports(allowed_ports.begin(), allowed_ports.end());
160 g_explicitly_allowed_ports.Get() = std::move(ports);
161 }
162
ScopedPortException(int port)163 ScopedPortException::ScopedPortException(int port) : port_(port) {
164 g_explicitly_allowed_ports.Get().insert(port);
165 }
166
~ScopedPortException()167 ScopedPortException::~ScopedPortException() {
168 auto it = g_explicitly_allowed_ports.Get().find(port_);
169 if (it != g_explicitly_allowed_ports.Get().end())
170 g_explicitly_allowed_ports.Get().erase(it);
171 else
172 NOTREACHED();
173 }
174
IsAllowablePort(int port)175 NET_EXPORT bool IsAllowablePort(int port) {
176 for (auto allowable_port : kAllowablePorts) {
177 if (port == allowable_port) {
178 return true;
179 }
180 }
181
182 if (port == g_scoped_allowable_port)
183 return true;
184
185 return false;
186 }
187
ScopedAllowablePortForTesting(int port)188 ScopedAllowablePortForTesting::ScopedAllowablePortForTesting(int port) {
189 DCHECK_EQ(g_scoped_allowable_port, 0);
190 g_scoped_allowable_port = port;
191 }
192
~ScopedAllowablePortForTesting()193 ScopedAllowablePortForTesting::~ScopedAllowablePortForTesting() {
194 g_scoped_allowable_port = 0;
195 }
196
197 } // namespace net
198