xref: /aosp_15_r20/external/cronet/net/base/port_util.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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