| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/base/port_util.h" |
| |
| #include <limits> |
| #include <set> |
| |
| #include "base/lazy_instance.h" |
| #include "base/logging.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_util.h" |
| #include "url/url_constants.h" |
| |
| namespace net { |
| |
| namespace { |
| |
| // The general list of blocked ports. Will be blocked unless a specific |
| // protocol overrides it. (Ex: ftp can use ports 20 and 21) |
| const int kRestrictedPorts[] = { |
| 1, // tcpmux |
| 7, // echo |
| 9, // discard |
| 11, // systat |
| 13, // daytime |
| 15, // netstat |
| 17, // qotd |
| 19, // chargen |
| 20, // ftp data |
| 21, // ftp access |
| 22, // ssh |
| 23, // telnet |
| 25, // smtp |
| 37, // time |
| 42, // name |
| 43, // nicname |
| 53, // domain |
| 77, // priv-rjs |
| 79, // finger |
| 87, // ttylink |
| 95, // supdup |
| 101, // hostriame |
| 102, // iso-tsap |
| 103, // gppitnp |
| 104, // acr-nema |
| 109, // pop2 |
| 110, // pop3 |
| 111, // sunrpc |
| 113, // auth |
| 115, // sftp |
| 117, // uucp-path |
| 119, // nntp |
| 123, // NTP |
| 135, // loc-srv /epmap |
| 139, // netbios |
| 143, // imap2 |
| 179, // BGP |
| 389, // ldap |
| 427, // SLP (Also used by Apple Filing Protocol) |
| 465, // smtp+ssl |
| 512, // print / exec |
| 513, // login |
| 514, // shell |
| 515, // printer |
| 526, // tempo |
| 530, // courier |
| 531, // chat |
| 532, // netnews |
| 540, // uucp |
| 548, // AFP (Apple Filing Protocol) |
| 556, // remotefs |
| 563, // nntp+ssl |
| 587, // stmp? |
| 601, // ?? |
| 636, // ldap+ssl |
| 993, // ldap+ssl |
| 995, // pop3+ssl |
| 2049, // nfs |
| 3659, // apple-sasl / PasswordServer |
| 4045, // lockd |
| 6000, // X11 |
| 6665, // Alternate IRC [Apple addition] |
| 6666, // Alternate IRC [Apple addition] |
| 6667, // Standard IRC [Apple addition] |
| 6668, // Alternate IRC [Apple addition] |
| 6669, // Alternate IRC [Apple addition] |
| 6697, // IRC + TLS |
| }; |
| |
| // FTP overrides the following restricted port. |
| const int kAllowedFtpPorts[] = { |
| 21, // ftp data |
| }; |
| |
| base::LazyInstance<std::multiset<int>>::Leaky g_explicitly_allowed_ports = |
| LAZY_INSTANCE_INITIALIZER; |
| |
| } // namespace |
| |
| bool IsPortValid(int port) { |
| return port >= 0 && port <= std::numeric_limits<uint16_t>::max(); |
| } |
| |
| bool IsWellKnownPort(int port) { |
| return port >= 0 && port < 1024; |
| } |
| |
| bool IsPortAllowedForScheme(int port, const std::string& url_scheme) { |
| // Reject invalid ports. |
| if (!IsPortValid(port)) |
| return false; |
| |
| // Allow explitly allowed ports for any scheme. |
| if (g_explicitly_allowed_ports.Get().count(port) > 0) |
| return true; |
| |
| // FTP requests have an extra set of whitelisted schemes. |
| if (base::LowerCaseEqualsASCII(url_scheme, url::kFtpScheme)) { |
| for (int allowed_ftp_port : kAllowedFtpPorts) { |
| if (allowed_ftp_port == port) |
| return true; |
| } |
| } |
| |
| // Finally check against the generic list of restricted ports for all |
| // schemes. |
| for (int restricted_port : kRestrictedPorts) { |
| if (restricted_port == port) |
| return false; |
| } |
| |
| return true; |
| } |
| |
| size_t GetCountOfExplicitlyAllowedPorts() { |
| return g_explicitly_allowed_ports.Get().size(); |
| } |
| |
| // Specifies a comma separated list of port numbers that should be accepted |
| // despite bans. If the string is invalid no allowed ports are stored. |
| void SetExplicitlyAllowedPorts(const std::string& allowed_ports) { |
| if (allowed_ports.empty()) |
| return; |
| |
| std::multiset<int> ports; |
| size_t last = 0; |
| size_t size = allowed_ports.size(); |
| // The comma delimiter. |
| const std::string::value_type kComma = ','; |
| |
| // Overflow is still possible for evil user inputs. |
| for (size_t i = 0; i <= size; ++i) { |
| // The string should be composed of only digits and commas. |
| if (i != size && !base::IsAsciiDigit(allowed_ports[i]) && |
| (allowed_ports[i] != kComma)) |
| return; |
| if (i == size || allowed_ports[i] == kComma) { |
| if (i > last) { |
| int port; |
| base::StringToInt(base::StringPiece(allowed_ports.begin() + last, |
| allowed_ports.begin() + i), |
| &port); |
| ports.insert(port); |
| } |
| last = i + 1; |
| } |
| } |
| g_explicitly_allowed_ports.Get() = ports; |
| } |
| |
| ScopedPortException::ScopedPortException(int port) : port_(port) { |
| g_explicitly_allowed_ports.Get().insert(port); |
| } |
| |
| ScopedPortException::~ScopedPortException() { |
| auto it = g_explicitly_allowed_ports.Get().find(port_); |
| if (it != g_explicitly_allowed_ports.Get().end()) |
| g_explicitly_allowed_ports.Get().erase(it); |
| else |
| NOTREACHED(); |
| } |
| |
| } // namespace net |