From 3b47ad21dbdf721580e5efa44164ef37ad9153c3 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Dec 15 2020 18:02:10 +0000 Subject: High: executor: restrict certain IPC requests to Pacemaker daemons The executor IPC API allows clients to register resources, request agent execution, and so forth. If ACLs are enabled, this could allow an ACL-restricted user to bypass ACLs and execute any code as root. (If ACLs are not enabled, users in the haclient group have full access to the CIB, which already gives them that ability, so there is no additional exposure in that case.) When ACLs are supported, this commit effectively disables the executor IPC API for clients that aren't connecting as root or hacluster. Such clients can only register and poke now. --- diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c index 59ac02c..2900569 100644 --- a/daemons/execd/execd_commands.c +++ b/daemons/execd/execd_commands.c @@ -1519,8 +1519,12 @@ process_lrmd_signon(pcmk__client_t *client, xmlNode *request, int call_id, if (crm_is_true(is_ipc_provider)) { #ifdef SUPPORT_REMOTE - // This is a remote connection from a cluster node's controller - ipc_proxy_add_provider(client); + if ((client->remote != NULL) && client->remote->tls_handshake_complete) { + // This is a remote connection from a cluster node's controller + ipc_proxy_add_provider(client); + } else { + rc = -EACCES; + } #else rc = -EPROTONOSUPPORT; #endif @@ -1835,12 +1839,26 @@ process_lrmd_message(pcmk__client_t *client, uint32_t id, xmlNode *request) int do_notify = 0; xmlNode *reply = NULL; + bool allowed = true; + +#if ENABLE_ACL + /* Certain IPC commands may be done only by privileged users (i.e. root or + * hacluster) when ACLs are enabled, because they would otherwise provide a + * means of bypassing ACLs. + */ + allowed = is_set(client->flags, pcmk__client_privileged); +#endif + crm_trace("Processing %s operation from %s", op, client->id); crm_element_value_int(request, F_LRMD_CALLID, &call_id); if (crm_str_eq(op, CRM_OP_IPC_FWD, TRUE)) { #ifdef SUPPORT_REMOTE - ipc_proxy_forward_client(client, request); + if (allowed) { + ipc_proxy_forward_client(client, request); + } else { + rc = -EACCES; + } #else rc = -EPROTONOSUPPORT; #endif @@ -1849,38 +1867,70 @@ process_lrmd_message(pcmk__client_t *client, uint32_t id, xmlNode *request) rc = process_lrmd_signon(client, request, call_id, &reply); do_reply = 1; } else if (crm_str_eq(op, LRMD_OP_RSC_REG, TRUE)) { - rc = process_lrmd_rsc_register(client, id, request); - do_notify = 1; + if (allowed) { + rc = process_lrmd_rsc_register(client, id, request); + do_notify = 1; + } else { + rc = -EACCES; + } do_reply = 1; } else if (crm_str_eq(op, LRMD_OP_RSC_INFO, TRUE)) { - reply = process_lrmd_get_rsc_info(request, call_id); + if (allowed) { + reply = process_lrmd_get_rsc_info(request, call_id); + } else { + rc = -EACCES; + } do_reply = 1; } else if (crm_str_eq(op, LRMD_OP_RSC_UNREG, TRUE)) { - rc = process_lrmd_rsc_unregister(client, id, request); - /* don't notify anyone about failed un-registers */ - if (rc == pcmk_ok || rc == -EINPROGRESS) { - do_notify = 1; + if (allowed) { + rc = process_lrmd_rsc_unregister(client, id, request); + /* don't notify anyone about failed un-registers */ + if (rc == pcmk_ok || rc == -EINPROGRESS) { + do_notify = 1; + } + } else { + rc = -EACCES; } do_reply = 1; } else if (crm_str_eq(op, LRMD_OP_RSC_EXEC, TRUE)) { - rc = process_lrmd_rsc_exec(client, id, request); + if (allowed) { + rc = process_lrmd_rsc_exec(client, id, request); + } else { + rc = -EACCES; + } do_reply = 1; } else if (crm_str_eq(op, LRMD_OP_RSC_CANCEL, TRUE)) { - rc = process_lrmd_rsc_cancel(client, id, request); + if (allowed) { + rc = process_lrmd_rsc_cancel(client, id, request); + } else { + rc = -EACCES; + } do_reply = 1; } else if (crm_str_eq(op, LRMD_OP_POKE, TRUE)) { do_notify = 1; do_reply = 1; } else if (crm_str_eq(op, LRMD_OP_CHECK, TRUE)) { - xmlNode *data = get_message_xml(request, F_LRMD_CALLDATA); - const char *timeout = crm_element_value(data, F_LRMD_WATCHDOG); - CRM_LOG_ASSERT(data != NULL); - pcmk__valid_sbd_timeout(timeout); + if (allowed) { + xmlNode *data = get_message_xml(request, F_LRMD_CALLDATA); + + CRM_LOG_ASSERT(data != NULL); + pcmk__valid_sbd_timeout(crm_element_value(data, F_LRMD_WATCHDOG)); + } else { + rc = -EACCES; + } } else if (crm_str_eq(op, LRMD_OP_ALERT_EXEC, TRUE)) { - rc = process_lrmd_alert_exec(client, id, request); + if (allowed) { + rc = process_lrmd_alert_exec(client, id, request); + } else { + rc = -EACCES; + } do_reply = 1; } else if (crm_str_eq(op, LRMD_OP_GET_RECURRING, TRUE)) { - reply = process_lrmd_get_recurring(request, call_id); + if (allowed) { + reply = process_lrmd_get_recurring(request, call_id); + } else { + rc = -EACCES; + } do_reply = 1; } else { rc = -EOPNOTSUPP; @@ -1888,6 +1938,11 @@ process_lrmd_message(pcmk__client_t *client, uint32_t id, xmlNode *request) crm_err("Unknown IPC request '%s' from %s", op, client->name); } + if (rc == -EACCES) { + crm_warn("Rejecting IPC request '%s' from unprivileged client %s", + op, pcmk__client_name(client)); + } + crm_debug("Processed %s operation from %s: rc=%d, reply=%d, notify=%d", op, client->id, rc, do_reply, do_notify);