diff --git a/src/controller/controller.c b/src/controller/controller.c index 222a7fe9ad..285d0e5079 100644 --- a/src/controller/controller.c +++ b/src/controller/controller.c @@ -397,6 +397,34 @@ bool controller_apply_config(Controller *controller) { } } + _cleanup_freev_ char **sections = cfg_list_sections(controller->config); + if (sections == NULL) { + bc_log_error("Failed to list config sections"); + return false; + } + for (size_t i = 0; sections[i] != NULL; i++) { + const char *section = sections[i]; + if (!str_has_prefix(section, "agent ")) { + continue; + } + const char *agent = section + strlen("agent "); + Node *node = controller_find_node(controller, agent); + if (node == NULL) { + /* Add it to the list if it allowed */ + bool allowed = cfg_s_get_bool_value(controller->config, section, CFG_ALLOWED); + if (allowed) { + node = controller_add_node(controller, agent); + } else { + continue; + } + } + + const char *selinux_context = cfg_s_get_value(controller->config, section, CFG_REQUIRED_SELINUX_CONTEXT); + if (selinux_context && !node_set_required_selinux_context(node, selinux_context)) { + return false; + } + } + const char *interval_msec = cfg_get_value(controller->config, CFG_HEARTBEAT_INTERVAL); if (interval_msec) { if (!controller_set_heartbeat_interval(controller, interval_msec)) { diff --git a/src/controller/node.c b/src/controller/node.c index 47eb298e92..8ae27b5b2f 100644 --- a/src/controller/node.c +++ b/src/controller/node.c @@ -230,6 +230,7 @@ void node_unref(Node *node) { free_and_null(node->name); free_and_null(node->object_path); free_and_null(node->peer_ip); + free_and_null(node->required_selinux_context); free(node); } @@ -242,6 +243,14 @@ void node_shutdown(Node *node) { } } +bool node_set_required_selinux_context(Node *node, const char *selinux_context) { + node->required_selinux_context = strdup(selinux_context); + if (node->required_selinux_context == NULL) { + return false; + } + return true; +} + bool node_export(Node *node) { Controller *controller = node->controller; @@ -955,6 +964,18 @@ static int node_method_register(sd_bus_message *m, void *userdata, UNUSED sd_bus return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_SERVICE_UNKNOWN, "Unexpected node name"); } + if (named_node->required_selinux_context && + (node->peer_selinux_context == NULL || + !streq(node->peer_selinux_context, named_node->required_selinux_context))) { + bc_log_errorf("Node tried to register as '%s' with wrong selinux context '%s', expected '%s'", + name, + node->peer_selinux_context ? node->peer_selinux_context : "(missing)", + named_node->required_selinux_context); + + /* This is same as for not allowed, don't allow probing for available names */ + return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_SERVICE_UNKNOWN, "Unexpected node name"); + } + if (node_has_agent(named_node)) { return sd_bus_reply_method_errorf( m, SD_BUS_ERROR_ADDRESS_IN_USE, "The node is already connected"); diff --git a/src/controller/node.h b/src/controller/node.h index 6643b2345b..f36af27c3d 100644 --- a/src/controller/node.h +++ b/src/controller/node.h @@ -52,6 +52,7 @@ struct Node { LIST_FIELDS(Node, nodes); char *name; /* NULL for not yet registered nodes */ + char *required_selinux_context; char *object_path; char *peer_ip; char *peer_selinux_context; @@ -80,6 +81,7 @@ bool node_has_agent(Node *node); bool node_is_online(Node *node); bool node_set_agent_bus(Node *node, sd_bus *bus); void node_unset_agent_bus(Node *node); +bool node_set_required_selinux_context(Node *node, const char *selinux_context); AgentRequest *node_request_list_units( Node *node, agent_request_response_t cb, void *userdata, free_func_t free_userdata); diff --git a/src/libbluechi/common/cfg.h b/src/libbluechi/common/cfg.h index 6708d9f5e8..b19069302a 100644 --- a/src/libbluechi/common/cfg.h +++ b/src/libbluechi/common/cfg.h @@ -19,6 +19,8 @@ #define CFG_CONTROLLER_HOST "ControllerHost" #define CFG_CONTROLLER_PORT "ControllerPort" #define CFG_CONTROLLER_ADDRESS "ControllerAddress" +#define CFG_ALLOWED "ALLOWED" +#define CFG_REQUIRED_SELINUX_CONTEXT "RequiredSelinuxContext" #define CFG_NODE_NAME "NodeName" #define CFG_ALLOWED_NODE_NAMES "AllowedNodeNames" #define CFG_HEARTBEAT_INTERVAL "HeartbeatInterval"