Branch data 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 [ + - # # ]: 173 : const std::vector<std::string> NET_PERMISSIONS_DOC{
12 [ + - ]: 173 : "bloomfilter (allow requesting BIP37 filtered blocks and transactions)",
13 [ + - ]: 173 : "noban (do not ban for misbehavior; implies download)",
14 [ + - ]: 173 : "forcerelay (relay transactions that are already in the mempool; implies relay)",
15 [ + - ]: 173 : "relay (relay even in -blocksonly mode, and unlimited transaction announcements)",
16 [ + - ]: 173 : "mempool (allow requesting BIP35 mempool contents)",
17 [ + - ]: 173 : "download (allow getheaders during IBD, no disconnect after maxuploadtarget limit)",
18 [ + - ]: 173 : "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 : 172 : bool TryParsePermissionFlags(const std::string& str, NetPermissionFlags& output, size_t& readen, bilingual_str& error)
25 : : {
26 : 172 : NetPermissionFlags flags = NetPermissionFlags::None;
27 : 172 : const auto atSeparator = str.find('@');
28 : :
29 : : // if '@' is not found (ie, "xxxxx"), the caller should apply implicit permissions
30 [ + + ]: 172 : if (atSeparator == std::string::npos) {
31 : 146 : NetPermissions::AddFlag(flags, NetPermissionFlags::Implicit);
32 : 146 : readen = 0;
33 : 146 : }
34 : : // else (ie, "perm1,perm2@xxxxx"), let's enumerate the permissions by splitting by ',' and calculate the flags
35 : : else {
36 : 26 : readen = 0;
37 : : // permissions == perm1,perm2
38 : 26 : const auto permissions = str.substr(0, atSeparator);
39 [ + + ]: 66 : while (readen < permissions.length()) {
40 : 44 : const auto commaSeparator = permissions.find(',', readen);
41 [ + + ]: 44 : const auto len = commaSeparator == std::string::npos ? permissions.length() - readen : commaSeparator - readen;
42 : : // permission == perm1
43 [ + - ]: 44 : const auto permission = permissions.substr(readen, len);
44 : 44 : readen += len; // We read "perm1"
45 [ + + ]: 44 : if (commaSeparator != std::string::npos) readen++; // We read ","
46 : :
47 [ + - + - : 44 : if (permission == "bloomfilter" || permission == "bloom") NetPermissions::AddFlag(flags, NetPermissionFlags::BloomFilter);
+ - + - #
# ]
48 [ + - + + : 44 : else if (permission == "noban") NetPermissions::AddFlag(flags, NetPermissionFlags::NoBan);
+ - ]
49 [ + - + + : 28 : else if (permission == "forcerelay") NetPermissions::AddFlag(flags, NetPermissionFlags::ForceRelay);
+ - ]
50 [ + - + + : 26 : else if (permission == "mempool") NetPermissions::AddFlag(flags, NetPermissionFlags::Mempool);
+ - ]
51 [ + - - + : 20 : else if (permission == "download") NetPermissions::AddFlag(flags, NetPermissionFlags::Download);
# # ]
52 [ + - + + : 20 : else if (permission == "all") NetPermissions::AddFlag(flags, NetPermissionFlags::All);
+ - ]
53 [ + - + + : 18 : else if (permission == "relay") NetPermissions::AddFlag(flags, NetPermissionFlags::Relay);
+ - ]
54 [ + - + + : 14 : else if (permission == "addr") NetPermissions::AddFlag(flags, NetPermissionFlags::Addr);
+ - ]
55 [ + - ]: 4 : else if (permission.length() == 0); // Allow empty entries
56 : : else {
57 [ + - + - ]: 4 : error = strprintf(_("Invalid P2P permission: '%s'"), permission);
58 : 4 : return false;
59 : : }
60 [ + + ]: 44 : }
61 : 22 : readen++;
62 [ - + + ]: 26 : }
63 : :
64 : 168 : output = flags;
65 [ + - + - ]: 168 : error = Untranslated("");
66 : 168 : return true;
67 : 172 : }
68 : :
69 : : }
70 : :
71 : 46 : std::vector<std::string> NetPermissions::ToStrings(NetPermissionFlags flags)
72 : : {
73 : 46 : std::vector<std::string> strings;
74 [ + - + + : 219 : if (NetPermissions::HasFlag(flags, NetPermissionFlags::BloomFilter)) strings.push_back("bloomfilter");
+ - + - ]
75 [ + - + + : 46 : if (NetPermissions::HasFlag(flags, NetPermissionFlags::NoBan)) strings.push_back("noban");
+ - + - ]
76 [ + - + + : 46 : if (NetPermissions::HasFlag(flags, NetPermissionFlags::ForceRelay)) strings.push_back("forcerelay");
+ - + - ]
77 [ + - + + : 46 : if (NetPermissions::HasFlag(flags, NetPermissionFlags::Relay)) strings.push_back("relay");
+ - + - ]
78 [ + - + + : 46 : if (NetPermissions::HasFlag(flags, NetPermissionFlags::Mempool)) strings.push_back("mempool");
+ - + - ]
79 [ + - + + : 46 : if (NetPermissions::HasFlag(flags, NetPermissionFlags::Download)) strings.push_back("download");
+ - + - ]
80 [ + - + + : 46 : if (NetPermissions::HasFlag(flags, NetPermissionFlags::Addr)) strings.push_back("addr");
+ - - + ]
81 : 46 : return strings;
82 [ + - ]: 46 : }
83 : :
84 : 86 : bool NetWhitebindPermissions::TryParse(const std::string& str, NetWhitebindPermissions& output, bilingual_str& error)
85 : : {
86 : : NetPermissionFlags flags;
87 : : size_t offset;
88 [ + + ]: 86 : if (!TryParsePermissionFlags(str, flags, offset, error)) return false;
89 : :
90 : 84 : const std::string strBind = str.substr(offset);
91 [ + - + - ]: 84 : const std::optional<CService> addrBind{Lookup(strBind, 0, false)};
92 [ + + ]: 84 : if (!addrBind.has_value()) {
93 [ + - + - ]: 68 : error = ResolveErrMsg("whitebind", strBind);
94 : 68 : return false;
95 : : }
96 [ + - + - : 16 : if (addrBind.value().GetPort() == 0) {
+ + ]
97 [ + - - + ]: 11 : error = strprintf(_("Need to specify a port with -whitebind: '%s'"), strBind);
98 : 11 : return false;
99 : : }
100 : :
101 : 5 : output.m_flags = flags;
102 [ + - + - ]: 5 : output.m_service = addrBind.value();
103 [ + - + - ]: 5 : error = Untranslated("");
104 : 5 : return true;
105 : 86 : }
106 : :
107 : 86 : bool NetWhitelistPermissions::TryParse(const std::string& str, NetWhitelistPermissions& output, bilingual_str& error)
108 : : {
109 : : NetPermissionFlags flags;
110 : : size_t offset;
111 [ + + ]: 86 : if (!TryParsePermissionFlags(str, flags, offset, error)) return false;
112 : :
113 : 84 : const std::string net = str.substr(offset);
114 [ + - ]: 84 : CSubNet subnet;
115 [ + - ]: 84 : LookupSubNet(net, subnet);
116 [ + - + + ]: 84 : if (!subnet.IsValid()) {
117 [ + - + - ]: 66 : error = strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net);
118 : 66 : return false;
119 : : }
120 : :
121 : 18 : output.m_flags = flags;
122 [ + - ]: 18 : output.m_subnet = subnet;
123 [ + - - + ]: 18 : error = Untranslated("");
124 : 18 : return true;
125 : 86 : }
|