Coverage Report

Created: 2026-05-16 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/kea/src/lib/process/redact_config.cc
Line
Count
Source
1
// Copyright (C) 2021-2026 Internet Systems Consortium, Inc. ("ISC")
2
//
3
// This Source Code Form is subject to the terms of the Mozilla Public
4
// License, v. 2.0. If a copy of the MPL was not distributed with this
5
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7
#include <config.h>
8
9
#include <process/redact_config.h>
10
11
#include <boost/algorithm/string.hpp>
12
13
using namespace isc;
14
using namespace isc::data;
15
using namespace std;
16
17
namespace {
18
19
template <typename ElementPtrType>
20
ElementPtrType
21
    redact(ElementPtrType const& element, list<string> json_path,
22
0
           string obscure, unsigned level) {
23
0
    if (!element) {
24
0
        isc_throw(BadValue, "redact() got a null pointer");
25
0
    }
26
0
    if (level == 0) {
27
0
        isc_throw(BadValue, "redact() elements nested too deeply");
28
0
    }
29
30
0
    string const next_key(json_path.empty() ? string() : json_path.front());
31
0
    ElementPtr result;
32
0
    if (element->getType() == Element::list) {
33
        // If we are looking for a list...
34
0
        if (next_key == "*" || next_key == "[]") {
35
            // But if we are looking specifically for a list...
36
0
            if (next_key == "[]") {
37
                // Then advance in the path.
38
0
                json_path.pop_front();
39
0
            }
40
            // Then redact all children.
41
0
            result = Element::createList();
42
0
            for (ElementPtr const& child : element->listValue()) {
43
0
                result->add(redact(child, json_path, obscure, level - 1));
44
0
            }
45
0
            return (result);
46
0
        }
47
0
    } else if (element->getType() == Element::map) {
48
        // If we are looking for anything or if we have reached the end of a
49
        /// path...
50
0
        if (next_key == "*" || json_path.empty()) {
51
            // Then iterate through all the children.
52
0
            result = Element::createMap();
53
0
            for (auto const& kv : element->mapValue()) {
54
0
                std::string const& key(kv.first);
55
0
                ConstElementPtr const& value(kv.second);
56
57
0
                if (boost::algorithm::ends_with(key, "password") ||
58
0
                    boost::algorithm::ends_with(key, "secret")) {
59
                    // Sensitive data
60
0
                    result->set(key, Element::create(obscure));
61
0
                } else if (key == "user-context") {
62
                    // Skip user contexts.
63
0
                    result->set(key, value);
64
0
                } else {
65
0
                    if (json_path.empty()) {
66
                        // End of path means no sensitive data expected in this
67
                        // subtree, so we stop here.
68
0
                        result->set(key, value);
69
0
                    } else {
70
                        // We are looking for anything '*' so redact further.
71
0
                        result->set(key, redact(value, json_path, obscure,
72
0
                                                level - 1));
73
0
                    }
74
0
                }
75
0
            }
76
0
            return (result);
77
0
        } else {
78
0
            ConstElementPtr child(element->get(next_key));
79
0
            if (child) {
80
0
                result = isc::data::copy(element, 1U);
81
0
                json_path.pop_front();
82
0
                result->set(next_key,
83
0
                            redact(child, json_path, obscure, level - 1));
84
0
                return (result);
85
0
            }
86
0
        }
87
0
    }
88
89
0
    return (element);
90
0
}
Unexecuted instantiation: redact_config.cc:boost::shared_ptr<isc::data::Element const> (anonymous namespace)::redact<boost::shared_ptr<isc::data::Element const> >(boost::shared_ptr<isc::data::Element const> const&, std::__1::list<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned int)
Unexecuted instantiation: redact_config.cc:boost::shared_ptr<isc::data::Element> (anonymous namespace)::redact<boost::shared_ptr<isc::data::Element> >(boost::shared_ptr<isc::data::Element> const&, std::__1::list<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned int)
91
92
}  // namespace
93
94
namespace isc {
95
namespace process {
96
97
ConstElementPtr
98
redactConfig(ConstElementPtr const& element, list<string> const& json_path,
99
0
             string obscure, unsigned max_nesting_depth) {
100
0
    return (redact(element, json_path, obscure, max_nesting_depth));
101
0
}
102
103
}  // namespace process
104
}  // namespace isc