Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
chromium/net/base/port_util.cc
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
239 lines (209 sloc)
6.44 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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/containers/fixed_flat_map.h" | |
#include "base/lazy_instance.h" | |
#include "base/logging.h" | |
#include "base/metrics/histogram_functions.h" | |
#include "base/notreached.h" | |
#include "base/strings/string_number_conversions.h" | |
#include "base/strings/string_util.h" | |
#include "url/url_constants.h" | |
namespace net { | |
namespace { | |
// Records ports that may need blocking to mitigate the ALPACA vulnerability. | |
// See https://alpaca-attack.com/ and https://github.com/whatwg/fetch/pull/1250. | |
void LogAlpacaPort(int port) { | |
// Unlike the obsolete Net.Port.SlipStreamRestricted histogram, we don't | |
// record an "Other" category. Instead, historical data from | |
// Net.Port.SlipStreamRestricted can be used as a baseline for comparisons. | |
enum class AlpacaPort { | |
k26 = 0, | |
k989 = 1, | |
k990 = 2, | |
k2525 = 3, | |
kMaxValue = k2525, | |
}; | |
constexpr std::pair<int, AlpacaPort> kMap[] = { | |
{26, AlpacaPort::k26}, | |
{989, AlpacaPort::k989}, | |
{990, AlpacaPort::k990}, | |
{2525, AlpacaPort::k2525}, | |
}; | |
for (const auto& pair : kMap) { | |
if (pair.first == port) { | |
base::UmaHistogramEnumeration("Net.Port.Alpaca", pair.second); | |
return; | |
} | |
} | |
} | |
// The general list of blocked ports. Will be blocked unless a specific | |
// protocol overrides it. (Ex: ftp can use port 21) | |
// When adding a port to the list, consider also adding it to kAllowablePorts, | |
// below. | |
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 | |
69, // tftp | |
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 | |
137, // netbios | |
139, // netbios | |
143, // imap2 | |
161, // snmp | |
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) | |
554, // rtsp | |
556, // remotefs | |
563, // nntp+ssl | |
587, // smtp (rfc6409) | |
601, // syslog-conn (rfc3195) | |
636, // ldap+ssl | |
989, // ftps-data | |
990, // ftps | |
993, // ldap+ssl | |
995, // pop3+ssl | |
1719, // h323gatestat | |
1720, // h323hostcall | |
1723, // pptp | |
2049, // nfs | |
3659, // apple-sasl / PasswordServer | |
4045, // lockd | |
5060, // sip | |
5061, // sips | |
6000, // X11 | |
6566, // sane-port | |
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 | |
10080, // Amanda | |
}; | |
base::LazyInstance<std::multiset<int>>::Leaky g_explicitly_allowed_ports = | |
LAZY_INSTANCE_INITIALIZER; | |
// List of ports which are permitted to be reenabled despite being in | |
// kRestrictedList. When adding an port to this list you should also update the | |
// enterprise policy to document the fact that the value can be set. Ports | |
// should only remain in this list for about a year to give time for users to | |
// migrate off while stopping them from becoming permanent parts of the web | |
// platform. | |
constexpr int kAllowablePorts[] = { | |
// TODO(https://crbug.com/1199642) Remove port 554 around 2021/10/15. | |
554, | |
// TODO(https://crbug.com/1220079) Remove ports 989 and 990 around | |
// 2022/02/01. | |
989, | |
990, | |
// TODO(https://crbig.com/1210779) Remove port 6566 around 2021/08/12. | |
6566, | |
// TODO(https://crbug.com/1196846) Remove port 10080 around 2022/04/01. | |
10080, | |
}; | |
int g_scoped_allowable_port = 0; | |
} // 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, base::StringPiece url_scheme) { | |
// Reject invalid ports. | |
if (!IsPortValid(port)) | |
return false; | |
LogAlpacaPort(port); | |
// Allow explicitly allowed ports for any scheme. | |
if (g_explicitly_allowed_ports.Get().count(port) > 0) | |
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(base::span<const uint16_t> allowed_ports) { | |
std::multiset<int> ports(allowed_ports.begin(), allowed_ports.end()); | |
g_explicitly_allowed_ports.Get() = std::move(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(); | |
} | |
NET_EXPORT bool IsAllowablePort(int port) { | |
for (auto allowable_port : kAllowablePorts) { | |
if (port == allowable_port) { | |
return true; | |
} | |
} | |
if (port == g_scoped_allowable_port) | |
return true; | |
return false; | |
} | |
ScopedAllowablePortForTesting::ScopedAllowablePortForTesting(int port) { | |
DCHECK_EQ(g_scoped_allowable_port, 0); | |
g_scoped_allowable_port = port; | |
} | |
ScopedAllowablePortForTesting::~ScopedAllowablePortForTesting() { | |
g_scoped_allowable_port = 0; | |
} | |
} // namespace net |