aboutsummaryrefslogtreecommitdiff
path: root/src/net_permissions.cpp
blob: c3947173debd38f91829ef7e40ad8300eb53aaa3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <net_permissions.h>
#include <netbase.h>
#include <util/error.h>
#include <util/system.h>
#include <util/translation.h>

// The parse the following format "perm1,perm2@xxxxxx"
bool TryParsePermissionFlags(const std::string str, NetPermissionFlags& output, size_t& readen, std::string& error)
{
    NetPermissionFlags flags = PF_NONE;
    const auto atSeparator = str.find('@');

    // if '@' is not found (ie, "xxxxx"), the caller should apply implicit permissions
    if (atSeparator == std::string::npos) {
        NetPermissions::AddFlag(flags, PF_ISIMPLICIT);
        readen = 0;
    }
    // else (ie, "perm1,perm2@xxxxx"), let's enumerate the permissions by splitting by ',' and calculate the flags
    else {
        readen = 0;
        // permissions == perm1,perm2
        const auto permissions = str.substr(0, atSeparator);
        while (readen < permissions.length()) {
            const auto commaSeparator = permissions.find(',', readen);
            const auto len = commaSeparator == std::string::npos ? permissions.length() - readen : commaSeparator - readen;
            // permission == perm1
            const auto permission = permissions.substr(readen, len);
            readen += len; // We read "perm1"
            if (commaSeparator != std::string::npos) readen++; // We read ","

            if (permission == "bloomfilter" || permission == "bloom") NetPermissions::AddFlag(flags, PF_BLOOMFILTER);
            else if (permission == "noban") NetPermissions::AddFlag(flags, PF_NOBAN);
            else if (permission == "forcerelay") NetPermissions::AddFlag(flags, PF_FORCERELAY);
            else if (permission == "mempool") NetPermissions::AddFlag(flags, PF_MEMPOOL);
            else if (permission == "all") NetPermissions::AddFlag(flags, PF_ALL);
            else if (permission == "relay") NetPermissions::AddFlag(flags, PF_RELAY);
            else if (permission.length() == 0); // Allow empty entries
            else {
                error = strprintf(_("Invalid P2P permission: '%s'").translated, permission);
                return false;
            }
        }
        readen++;
    }

    output = flags;
    error = "";
    return true;
}

std::vector<std::string> NetPermissions::ToStrings(NetPermissionFlags flags)
{
    std::vector<std::string> strings;
    if (NetPermissions::HasFlag(flags, PF_BLOOMFILTER)) strings.push_back("bloomfilter");
    if (NetPermissions::HasFlag(flags, PF_NOBAN)) strings.push_back("noban");
    if (NetPermissions::HasFlag(flags, PF_FORCERELAY)) strings.push_back("forcerelay");
    if (NetPermissions::HasFlag(flags, PF_RELAY)) strings.push_back("relay");
    if (NetPermissions::HasFlag(flags, PF_MEMPOOL)) strings.push_back("mempool");
    return strings;
}

bool NetWhitebindPermissions::TryParse(const std::string str, NetWhitebindPermissions& output, std::string& error)
{
    NetPermissionFlags flags;
    size_t offset;
    if (!TryParsePermissionFlags(str, flags, offset, error)) return false;

    const std::string strBind = str.substr(offset);
    CService addrBind;
    if (!Lookup(strBind.c_str(), addrBind, 0, false)) {
        error = ResolveErrMsg("whitebind", strBind);
        return false;
    }
    if (addrBind.GetPort() == 0) {
        error = strprintf(_("Need to specify a port with -whitebind: '%s'").translated, strBind);
        return false;
    }

    output.m_flags = flags;
    output.m_service = addrBind;
    error = "";
    return true;
}

bool NetWhitelistPermissions::TryParse(const std::string str, NetWhitelistPermissions& output, std::string& error)
{
    NetPermissionFlags flags;
    size_t offset;
    if (!TryParsePermissionFlags(str, flags, offset, error)) return false;

    const std::string net = str.substr(offset);
    CSubNet subnet;
    LookupSubNet(net.c_str(), subnet);
    if (!subnet.IsValid()) {
        error = strprintf(_("Invalid netmask specified in -whitelist: '%s'").translated, net);
        return false;
    }

    output.m_flags = flags;
    output.m_subnet = subnet;
    error = "";
    return true;
}