1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/base/port_util.h"
9 #include "base/lazy_instance.h"
10 #include "base/logging.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h"
13 #include "url/url_constants.h"
19 // The general list of blocked ports. Will be blocked unless a specific
20 // protocol overrides it. (Ex: ftp can use ports 20 and 21)
21 const int kRestrictedPorts
[] = {
55 135, // loc-srv /epmap
78 3659, // apple-sasl / PasswordServer
81 6665, // Alternate IRC [Apple addition]
82 6666, // Alternate IRC [Apple addition]
83 6667, // Standard IRC [Apple addition]
84 6668, // Alternate IRC [Apple addition]
85 6669, // Alternate IRC [Apple addition]
86 0xFFFF, // Used to block all invalid port numbers (see
87 // third_party/WebKit/Source/platform/weborigin/KURL.cpp,
91 // FTP overrides the following restricted ports.
92 const int kAllowedFtpPorts
[] = {
97 base::LazyInstance
<std::multiset
<int>>::Leaky g_explicitly_allowed_ports
=
98 LAZY_INSTANCE_INITIALIZER
;
102 bool IsPortValid(int port
) {
103 return port
>= 0 && port
<= std::numeric_limits
<uint16_t>::max();
106 bool IsWellKnownPort(int port
) {
107 return port
>= 0 && port
< 1024;
110 bool IsPortAllowedForScheme(int port
, const std::string
& url_scheme
) {
111 // Reject invalid ports.
112 if (!IsPortValid(port
))
115 // Allow explitly allowed ports for any scheme.
116 if (g_explicitly_allowed_ports
.Get().count(port
) > 0)
119 // FTP requests have an extra set of whitelisted schemes.
120 if (base::LowerCaseEqualsASCII(url_scheme
, url::kFtpScheme
)) {
121 for (int allowed_ftp_port
: kAllowedFtpPorts
) {
122 if (allowed_ftp_port
== port
)
127 // Finally check against the generic list of restricted ports for all
129 for (int restricted_port
: kRestrictedPorts
) {
130 if (restricted_port
== port
)
137 size_t GetCountOfExplicitlyAllowedPorts() {
138 return g_explicitly_allowed_ports
.Get().size();
141 // Specifies a comma separated list of port numbers that should be accepted
142 // despite bans. If the string is invalid no allowed ports are stored.
143 void SetExplicitlyAllowedPorts(const std::string
& allowed_ports
) {
144 if (allowed_ports
.empty())
147 std::multiset
<int> ports
;
149 size_t size
= allowed_ports
.size();
150 // The comma delimiter.
151 const std::string::value_type kComma
= ',';
153 // Overflow is still possible for evil user inputs.
154 for (size_t i
= 0; i
<= size
; ++i
) {
155 // The string should be composed of only digits and commas.
156 if (i
!= size
&& !base::IsAsciiDigit(allowed_ports
[i
]) &&
157 (allowed_ports
[i
] != kComma
))
159 if (i
== size
|| allowed_ports
[i
] == kComma
) {
162 base::StringToInt(base::StringPiece(allowed_ports
.begin() + last
,
163 allowed_ports
.begin() + i
),
170 g_explicitly_allowed_ports
.Get() = ports
;
173 ScopedPortException::ScopedPortException(int port
) : port_(port
) {
174 g_explicitly_allowed_ports
.Get().insert(port
);
177 ScopedPortException::~ScopedPortException() {
178 std::multiset
<int>::iterator it
=
179 g_explicitly_allowed_ports
.Get().find(port_
);
180 if (it
!= g_explicitly_allowed_ports
.Get().end())
181 g_explicitly_allowed_ports
.Get().erase(it
);