Kea: unix_command_config.cc Source File

| Kea 3.2.0-git

unix_command_config.cc
Go to the documentation of this file.
1// Copyright (C) 2015-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 <asiolink/io_asio_socket.h>
10#include <cc/dhcp_config_error.h>
11#include <config/command_mgr.h>
12#include <config/config_log.h>
13#include <config/unix_command_config.h>
14#include <util/filesystem.h>
15#include <limits>
16#include <list>
17
18using namespace isc;
19using namespace isc::asiolink;
20using namespace isc::config;
21using namespace isc::data;
22using namespace isc::dhcp;
23using namespace isc::util::file;
24using namespace std;
25
26namespace isc {
27namespace config {
28
29namespace {
30 // Singleton PathChecker to set and hold valid unix socket path.
31 PathCheckerPtr socket_path_checker_;
32};
33
34const mode_t UnixCommandConfig::DEFAULT_SOCKET_PATH_PERMS = (S_IRWXU | S_IRGRP | S_IXGRP);
35
36mode_t UnixCommandConfig::socket_path_perms_ = UnixCommandConfig::DEFAULT_SOCKET_PATH_PERMS;
37
38UnixCommandConfig::UnixCommandConfig(ConstElementPtr config)
39 : socket_type_("unix"), socket_name_() {
40 if (config->getType() != Element::map) {
41 isc_throw(DhcpConfigError, "expected map type ("
42 << config->getPosition() << ")");
43 }
44 // Get socket type.
45 ConstElementPtr socket_type = config->get("socket-type");
46 if (socket_type) {
47 if (socket_type->getType() != Element::string) {
48 isc_throw(DhcpConfigError,
49 "invalid type specified for parameter 'socket-type' ("
50 << socket_type->getPosition() << ")");
51 }
52 socket_type_ = socket_type->stringValue();
53 if ((socket_type_ != "unix")) {
54 isc_throw(DhcpConfigError, "unsupported 'socket-type' '"
55 << socket_type_ << "' not 'unix'");
56 }
57 }
58
59 // Reject HTTP/HTTPS only keywords.
60 list<string> bad_keywords = {
61 "socket-address", "socket-port", "authentication",
62 "trust-anchor", "cert-file", "key-file", "cert-required",
63 "http-headers"
64 };
65 for (auto const& keyword : bad_keywords) {
66 if (config->contains(keyword)) {
67 isc_throw(DhcpConfigError,
68 "parameter '" << keyword << "' is not supported by UNIX "
69 "control sockets");
70 }
71 }
72
73 // Get socket name.
74 ConstElementPtr socket_name = config->get("socket-name");
75 if (!socket_name) {
76 isc_throw(DhcpConfigError, "Mandatory 'socket-name' parameter missing");
77 }
78
79 if (socket_name->getType() != Element::string) {
80 isc_throw(DhcpConfigError,
81 "invalid type specified for parameter 'socket-name' ("
82 << socket_name->getPosition() << ")");
83 }
84
85 try {
86 socket_name_ = validatePath(socket_name->stringValue());
87 } catch (const std::exception& ex) {
88 isc_throw(DhcpConfigError, "'socket-name' is invalid: " << ex.what());
89 }
90
91 // Get user context.
92 ConstElementPtr user_context = config->get("user-context");
93 if (user_context) {
94 setContext(user_context);
95 }
96}
97
98 ElementPtr
99UnixCommandConfig::toElement() const {
100 ElementPtr result = Element::createMap();
101 // Set user-context.
102 contextToElement(result);
103 // Set socket type.
104 result->set("socket-type", Element::create(socket_type_));
105 // Set socket name.
106 result->set("socket-name", Element::create(socket_name_));
107 return (result);
108}
109
110std::string
111UnixCommandConfig::getSocketPath(bool reset /* = false */,
112 const std::string explicit_path /* = "" */) {
113 if (!socket_path_checker_ || reset) {
114 socket_path_checker_.reset(new PathChecker(CONTROL_SOCKET_DIR,
115 "KEA_CONTROL_SOCKET_DIR"));
116 if (!explicit_path.empty()) {
117 socket_path_checker_->getPath(true, explicit_path);
118 }
119 }
120
121 return (socket_path_checker_->getPath());
122}
123
124std::string
125UnixCommandConfig::validatePath(const std::string socket_path) {
126 if (!socket_path_checker_) {
127 getSocketPath();
128 }
129
130 std::string valid_path;
131 try {
132 valid_path = socket_path_checker_->validatePath(socket_path);
133 } catch (const SecurityWarn& ex) {
134 LOG_WARN(command_logger, COMMAND_UNIX_SOCKET_PATH_SECURITY_WARNING)
135 .arg(ex.what());
136 // Skip checking permissions.
137 return(socket_path);
138 }
139
140 auto parent_path = socket_path_checker_->getPath();
141 auto parent_perms = getPermissions(parent_path);
142 if ((parent_perms & ~socket_path_perms_) != 0) {
143 std::ostringstream oss;
144 oss << "socket path:" << parent_path
145 << " does not exist or has more relaxed permissions than "
146 << std::oct << socket_path_perms_;
147
148 if (PathChecker::shouldEnforceSecurity()) {
149 isc_throw (DhcpConfigError, oss.str());
150 }
151
152 LOG_WARN(command_logger, COMMAND_UNIX_SOCKET_PERMISSIONS_SECURITY_WARNING)
153 .arg(oss.str());
154 }
155
156 return (valid_path);
157}
158
159mode_t
160UnixCommandConfig::getSocketPathPerms() {
161 return (socket_path_perms_);
162}
163
164void
165UnixCommandConfig::setSocketPathPerms(mode_t perms
166 /* = DEFAULT_SOCKET_PATH_PERMS */) {
167 socket_path_perms_ = perms;
168}
169
170} // end of isc::config
171} // end of isc
Element::create
static ElementPtr create(const Position &pos=ZERO_POSITION())
Create a NullElement.
Definition data.cc:299
Element::map
@ map
Definition data.h:160
Element::string
@ string
Definition data.h:157
Element::createMap
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:354
isc::Exception::what
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
Definition exceptions/exceptions.cc:32
isc::config::UnixCommandConfig::getSocketPath
static std::string getSocketPath(bool reset=false, const std::string explicit_path="")
Fetches the supported control socket path.
Definition unix_command_config.cc:111
isc::config::UnixCommandConfig::getSocketPathPerms
static mode_t getSocketPathPerms()
Fetches the required socket path permissions mask.
Definition unix_command_config.cc:160
isc::config::UnixCommandConfig::UnixCommandConfig
UnixCommandConfig(isc::data::ConstElementPtr config)
Constructor.
Definition unix_command_config.cc:38
isc::config::UnixCommandConfig::DEFAULT_SOCKET_PATH_PERMS
static const mode_t DEFAULT_SOCKET_PATH_PERMS
Defines the default permissions for unix socket parent directory.
Definition unix_command_config.h:26
isc::config::UnixCommandConfig::setSocketPathPerms
static void setSocketPathPerms(mode_t perms=DEFAULT_SOCKET_PATH_PERMS)
Sets the required socket path permissions mask.
Definition unix_command_config.cc:165
isc::config::UnixCommandConfig::toElement
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
Definition unix_command_config.cc:99
isc::config::UnixCommandConfig::validatePath
static std::string validatePath(const std::string socket_path)
Validates a path against the supported path for unix control sockets.
Definition unix_command_config.cc:125
isc::config::UnixCommandConfig::socket_path_perms_
static mode_t socket_path_perms_
Stores the default permissions for unix socket parent directory.
Definition unix_command_config.h:29
isc::dhcp::DhcpConfigError
To be removed. Please use ConfigError instead.
Definition dhcp_config_error.h:58
isc::util::file::PathChecker
Embodies a supported path against which file paths can be validated.
Definition filesystem.h:222
isc::util::file::PathChecker::shouldEnforceSecurity
static bool shouldEnforceSecurity()
Indicates security checks should be enforced.
Definition filesystem.cc:361
isc::util::file::SecurityWarn
A generic exception that is thrown if a parameter given violates security check but enforcement is la...
Definition filesystem.h:22
command_mgr.h
config_log.h
if
if(!(yy_init))
Definition d2_lexer.cc:1515
dhcp_config_error.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition exceptions/exceptions.h:210
filesystem.h
io_asio_socket.h
LOG_WARN
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition macros.h:26
isc::asiolink
Definition addr_utilities.cc:170
isc::config
Definition command_interpreter.cc:23
isc::config::COMMAND_UNIX_SOCKET_PATH_SECURITY_WARNING
const isc::log::MessageID COMMAND_UNIX_SOCKET_PATH_SECURITY_WARNING
Definition config_messages.h:36
isc::config::COMMAND_UNIX_SOCKET_PERMISSIONS_SECURITY_WARNING
const isc::log::MessageID COMMAND_UNIX_SOCKET_PERMISSIONS_SECURITY_WARNING
Definition config_messages.h:37
isc::config::command_logger
isc::log::Logger command_logger("commands")
Command processing Logger.
Definition config_log.h:21
isc::data
Definition base_stamped_element.cc:12
isc::data::ConstElementPtr
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:30
isc::data::ElementPtr
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
isc::dhcp
Definition dhcp4/client_handler.cc:20
isc::util::file
Definition filesystem.cc:29
isc::util::file::PathCheckerPtr
boost::shared_ptr< PathChecker > PathCheckerPtr
Defines a pointer to a PathChecker.
Definition filesystem.h:342
isc::util::file::getPermissions
mode_t getPermissions(const std::string path)
Fetches the file permissions mask.
Definition filesystem.cc:56
isc
Defines the logger used by the top-level component of kea-lfc.
Definition check_exists_add.cc:18
isc::data::UserContext::contextToElement
void contextToElement(data::ElementPtr map) const
Merge unparse a user_context object.
Definition user_context.cc:15
isc::data::UserContext::setContext
void setContext(const data::ConstElementPtr &ctx)
Sets user context.
Definition user_context.h:30
unix_command_config.h