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