Line data Source code
1 : // Copyright (c) 2009-2021 The Bitcoin Core developers
2 : // Distributed under the MIT software license, see the accompanying
3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 :
5 : #include <common/system.h>
6 : #include <net_permissions.h>
7 : #include <netbase.h>
8 : #include <util/error.h>
9 : #include <util/translation.h>
10 :
11 2 : const std::vector<std::string> NET_PERMISSIONS_DOC{
12 2 : "bloomfilter (allow requesting BIP37 filtered blocks and transactions)",
13 2 : "noban (do not ban for misbehavior; implies download)",
14 2 : "forcerelay (relay transactions that are already in the mempool; implies relay)",
15 2 : "relay (relay even in -blocksonly mode, and unlimited transaction announcements)",
16 2 : "mempool (allow requesting BIP35 mempool contents)",
17 2 : "download (allow getheaders during IBD, no disconnect after maxuploadtarget limit)",
18 2 : "addr (responses to GETADDR avoid hitting the cache and contain random records with the most up-to-date info)"
19 : };
20 :
21 : namespace {
22 :
23 : // Parse the following format: "perm1,perm2@xxxxxx"
24 0 : bool TryParsePermissionFlags(const std::string& str, NetPermissionFlags& output, size_t& readen, bilingual_str& error)
25 : {
26 0 : NetPermissionFlags flags = NetPermissionFlags::None;
27 0 : const auto atSeparator = str.find('@');
28 :
29 : // if '@' is not found (ie, "xxxxx"), the caller should apply implicit permissions
30 0 : if (atSeparator == std::string::npos) {
31 0 : NetPermissions::AddFlag(flags, NetPermissionFlags::Implicit);
32 0 : readen = 0;
33 0 : }
34 : // else (ie, "perm1,perm2@xxxxx"), let's enumerate the permissions by splitting by ',' and calculate the flags
35 : else {
36 0 : readen = 0;
37 : // permissions == perm1,perm2
38 0 : const auto permissions = str.substr(0, atSeparator);
39 0 : while (readen < permissions.length()) {
40 0 : const auto commaSeparator = permissions.find(',', readen);
41 0 : const auto len = commaSeparator == std::string::npos ? permissions.length() - readen : commaSeparator - readen;
42 : // permission == perm1
43 0 : const auto permission = permissions.substr(readen, len);
44 0 : readen += len; // We read "perm1"
45 0 : if (commaSeparator != std::string::npos) readen++; // We read ","
46 :
47 0 : if (permission == "bloomfilter" || permission == "bloom") NetPermissions::AddFlag(flags, NetPermissionFlags::BloomFilter);
48 0 : else if (permission == "noban") NetPermissions::AddFlag(flags, NetPermissionFlags::NoBan);
49 0 : else if (permission == "forcerelay") NetPermissions::AddFlag(flags, NetPermissionFlags::ForceRelay);
50 0 : else if (permission == "mempool") NetPermissions::AddFlag(flags, NetPermissionFlags::Mempool);
51 0 : else if (permission == "download") NetPermissions::AddFlag(flags, NetPermissionFlags::Download);
52 0 : else if (permission == "all") NetPermissions::AddFlag(flags, NetPermissionFlags::All);
53 0 : else if (permission == "relay") NetPermissions::AddFlag(flags, NetPermissionFlags::Relay);
54 0 : else if (permission == "addr") NetPermissions::AddFlag(flags, NetPermissionFlags::Addr);
55 0 : else if (permission.length() == 0); // Allow empty entries
56 : else {
57 0 : error = strprintf(_("Invalid P2P permission: '%s'"), permission);
58 0 : return false;
59 : }
60 0 : }
61 0 : readen++;
62 0 : }
63 :
64 0 : output = flags;
65 0 : error = Untranslated("");
66 0 : return true;
67 0 : }
68 :
69 : }
70 :
71 0 : std::vector<std::string> NetPermissions::ToStrings(NetPermissionFlags flags)
72 : {
73 0 : std::vector<std::string> strings;
74 2 : if (NetPermissions::HasFlag(flags, NetPermissionFlags::BloomFilter)) strings.push_back("bloomfilter");
75 0 : if (NetPermissions::HasFlag(flags, NetPermissionFlags::NoBan)) strings.push_back("noban");
76 0 : if (NetPermissions::HasFlag(flags, NetPermissionFlags::ForceRelay)) strings.push_back("forcerelay");
77 0 : if (NetPermissions::HasFlag(flags, NetPermissionFlags::Relay)) strings.push_back("relay");
78 0 : if (NetPermissions::HasFlag(flags, NetPermissionFlags::Mempool)) strings.push_back("mempool");
79 0 : if (NetPermissions::HasFlag(flags, NetPermissionFlags::Download)) strings.push_back("download");
80 0 : if (NetPermissions::HasFlag(flags, NetPermissionFlags::Addr)) strings.push_back("addr");
81 0 : return strings;
82 0 : }
83 :
84 0 : bool NetWhitebindPermissions::TryParse(const std::string& str, NetWhitebindPermissions& output, bilingual_str& error)
85 : {
86 : NetPermissionFlags flags;
87 : size_t offset;
88 0 : if (!TryParsePermissionFlags(str, flags, offset, error)) return false;
89 :
90 0 : const std::string strBind = str.substr(offset);
91 0 : const std::optional<CService> addrBind{Lookup(strBind, 0, false)};
92 0 : if (!addrBind.has_value()) {
93 0 : error = ResolveErrMsg("whitebind", strBind);
94 0 : return false;
95 : }
96 0 : if (addrBind.value().GetPort() == 0) {
97 0 : error = strprintf(_("Need to specify a port with -whitebind: '%s'"), strBind);
98 0 : return false;
99 : }
100 :
101 0 : output.m_flags = flags;
102 0 : output.m_service = addrBind.value();
103 0 : error = Untranslated("");
104 0 : return true;
105 0 : }
106 :
107 0 : bool NetWhitelistPermissions::TryParse(const std::string& str, NetWhitelistPermissions& output, bilingual_str& error)
108 : {
109 : NetPermissionFlags flags;
110 : size_t offset;
111 0 : if (!TryParsePermissionFlags(str, flags, offset, error)) return false;
112 :
113 0 : const std::string net = str.substr(offset);
114 0 : CSubNet subnet;
115 0 : LookupSubNet(net, subnet);
116 0 : if (!subnet.IsValid()) {
117 0 : error = strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net);
118 0 : return false;
119 : }
120 :
121 0 : output.m_flags = flags;
122 0 : output.m_subnet = subnet;
123 0 : error = Untranslated("");
124 0 : return true;
125 0 : }
|