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