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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright (C) 2022 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Kea Hooks Basic
// Commercial End User License Agreement v2.0. See COPYING file in the premium/
// directory.

#include <config.h>

#include <rbac.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <rbac_log.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

using namespace isc;
using namespace isc::data;
using namespace isc::http;
using namespace isc::log;
using namespace isc::rbac;
using namespace std;

namespace isc {
namespace rbac {

RolePtr roleAssign;

RoleConfigTable roleConfigTable;

RoleConfigPtr defaultRoleConfig;

RoleConfigPtr unknownRoleConfig;

const SimpleKeywords RoleConfig::ROLE_PARAMETERS = {
    { "name",              Element::string },
    { "accept-commands",   Element::any },
    { "reject-commands",   Element::any },
    { "other-commands",    Element::string },
    { "list-match-first",  Element::string },
    { "response-filters",  Element::list },
    { "comment",           Element::string }
};

RoleConfigPtr
RoleConfig::getConfig(const string& role) {
    if (role.empty()) {
        return (defaultRoleConfig);
    }
    auto it = roleConfigTable.find(role);
    if (it == roleConfigTable.end()) {
        return (unknownRoleConfig);
    }
    return (it->second);
}

RoleConfigPtr
RoleConfig::parse(ConstElementPtr cfg, string name) {
    if (!cfg) {
        isc_throw(BadValue, "parse null role config");
    }
    if (cfg->getType() != Element::map) {
        isc_throw(BadValue, "role config is not a map");
    }

    // Keywords.
    SimpleParser::checkKeywords(RoleConfig::ROLE_PARAMETERS, cfg);

    // Name.
    ConstElementPtr name_elem = cfg->get("name");
    if (!name.empty() && name_elem) {
        isc_throw(BadValue, "spurious 'name' parameter for " << name
                  << " role");
    } else if (name.empty() && !name_elem) {
        isc_throw(BadValue, "'name' parameter is required in " << cfg->str());
    }
    if (name_elem) {
        name = name_elem->stringValue();
        if (name.empty()) {
            isc_throw(BadValue, "role config name is empty");
        }
    }

    // Accept ACL.
    ConstElementPtr accept_elem = cfg->get("accept-commands");
    AclPtr accept;
    if (accept_elem) {
        accept = Acl::parse(accept_elem);
    }

    // Reject ACL.
    ConstElementPtr reject_elem = cfg->get("reject-commands");
    AclPtr reject;
    if (reject_elem) {
        reject = Acl::parse(reject_elem);
    }

    // Others.
    bool others = false;
    ConstElementPtr others_elem = cfg->get("other-commands");
    if (others_elem) {
        const string& action = others_elem->stringValue();
        if ((action!= "accept") && (action != "reject")) {
            isc_throw(BadValue, "other-commands '" << action
                      << "' is not 'accept' or 'reject'");
        }
        others = (action == "accept");
    }

    // Preference.
    bool preference = true;
    ConstElementPtr pref_elem = cfg->get("list-match-first");
    if (pref_elem) {
        const string& pref = pref_elem->stringValue();
        if ((pref != "accept") && (pref != "reject")) {
            isc_throw(BadValue, "list-match-first '" << pref
                      << "' is not 'accept' or 'reject'");
        }
        preference = (pref == "accept");
    }

    // Response filters.
    ConstElementPtr resp_filters = cfg->get("response-filters");
    ResponseFilterList response_filters;
    if (resp_filters) {
        response_filters = ResponseFilter::parse(resp_filters);
    }

    return (RoleConfigPtr(new RoleConfig(name, accept, reject, others,
                                         preference, response_filters)));
}

HttpResponseJsonPtr
RoleConfig::createReject(const HttpRequestPtr& request,
                         const HttpStatusCode& status_code) {
    if (!request) {
        // Should not happen!
        isc_throw(Unexpected, "null request");
    }
    // From CtrlAgentResponseCreator::createStockHttpResponseInternal.
    HttpVersion http_version(request->context()->http_version_major_,
                             request->context()->http_version_minor_);
    if ((http_version < HttpVersion(1, 0)) ||
        (HttpVersion(1, 1) < http_version)) {
        http_version.major_ = 1;
        http_version.minor_ = 0;
    }
    HttpResponseJsonPtr response(new HttpResponseJson(http_version,
                                                      status_code));
    ElementPtr body = Element::createMap();
    uint16_t result = HttpResponse::statusCodeToNumber(status_code);
    body->set("result", Element::create(static_cast<long long>(result)));
    const string& text = HttpResponse::statusCodeToString(status_code);
    body->set("text", Element::create(text));
    response->setBodyAsJson(body);
    response->finalize();
    return (response);
}

} // end of namespace rbac
} // end of namespace isc