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 [ + - # # ]: 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 : }
|