pacemaker 2.1.8-2.1.8
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
acl.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2024 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU Lesser General Public License
7 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8 */
9
10#include <crm_internal.h>
11
12#include <stdio.h>
13#include <sys/types.h>
14#include <pwd.h>
15#include <string.h>
16#include <stdlib.h>
17#include <stdarg.h>
18
19#include <libxml/tree.h>
20
21#include <crm/crm.h>
22#include <crm/common/xml.h>
24#include "crmcommon_private.h"
25
26typedef struct xml_acl_s {
27 enum xml_private_flags mode;
28 gchar *xpath;
30
31static void
32free_acl(void *data)
33{
34 if (data) {
35 xml_acl_t *acl = data;
36
37 g_free(acl->xpath);
38 free(acl);
39 }
40}
41
42void
43pcmk__free_acls(GList *acls)
44{
45 g_list_free_full(acls, free_acl);
46}
47
48static GList *
49create_acl(const xmlNode *xml, GList *acls, enum xml_private_flags mode)
50{
51 xml_acl_t *acl = NULL;
52
53 const char *tag = crm_element_value(xml, PCMK_XA_OBJECT_TYPE);
54 const char *ref = crm_element_value(xml, PCMK_XA_REFERENCE);
55 const char *xpath = crm_element_value(xml, PCMK_XA_XPATH);
56 const char *attr = crm_element_value(xml, PCMK_XA_ATTRIBUTE);
57
58 if (tag == NULL) {
59 // @COMPAT Deprecated since 1.1.12 (needed for rolling upgrades)
61 }
62 if (ref == NULL) {
63 // @COMPAT Deprecated since 1.1.12 (needed for rolling upgrades)
65 }
66
67 if ((tag == NULL) && (ref == NULL) && (xpath == NULL)) {
68 // Schema should prevent this, but to be safe ...
69 crm_trace("Ignoring ACL <%s> element without selection criteria",
70 xml->name);
71 return NULL;
72 }
73
74 acl = pcmk__assert_alloc(1, sizeof (xml_acl_t));
75
76 acl->mode = mode;
77 if (xpath) {
78 acl->xpath = g_strdup(xpath);
79 crm_trace("Unpacked ACL <%s> element using xpath: %s",
80 xml->name, acl->xpath);
81
82 } else {
83 GString *buf = g_string_sized_new(128);
84
85 if ((ref != NULL) && (attr != NULL)) {
86 // NOTE: schema currently does not allow this
87 pcmk__g_strcat(buf, "//", pcmk__s(tag, "*"), "[@" PCMK_XA_ID "='",
88 ref, "' and @", attr, "]", NULL);
89
90 } else if (ref != NULL) {
91 pcmk__g_strcat(buf, "//", pcmk__s(tag, "*"), "[@" PCMK_XA_ID "='",
92 ref, "']", NULL);
93
94 } else if (attr != NULL) {
95 pcmk__g_strcat(buf, "//", pcmk__s(tag, "*"), "[@", attr, "]", NULL);
96
97 } else {
98 pcmk__g_strcat(buf, "//", pcmk__s(tag, "*"), NULL);
99 }
100
101 acl->xpath = buf->str;
102
103 g_string_free(buf, FALSE);
104 crm_trace("Unpacked ACL <%s> element as xpath: %s",
105 xml->name, acl->xpath);
106 }
107
108 return g_list_append(acls, acl);
109}
110
123static GList *
124parse_acl_entry(const xmlNode *acl_top, const xmlNode *acl_entry, GList *acls)
125{
126 xmlNode *child = NULL;
127
128 for (child = pcmk__xe_first_child(acl_entry, NULL, NULL, NULL);
129 child != NULL; child = pcmk__xe_next(child)) {
130
131 const char *tag = (const char *) child->name;
132 const char *kind = crm_element_value(child, PCMK_XA_KIND);
133
134 if (pcmk__xe_is(child, PCMK_XE_ACL_PERMISSION)) {
135 CRM_ASSERT(kind != NULL);
136 crm_trace("Unpacking ACL <%s> element of kind '%s'", tag, kind);
137 tag = kind;
138 } else {
139 crm_trace("Unpacking ACL <%s> element", tag);
140 }
141
142 /* @COMPAT PCMK__XE_ROLE_REF was deprecated in Pacemaker 1.1.12 (needed
143 * for rolling upgrades)
144 */
146 const char *ref_role = crm_element_value(child, PCMK_XA_ID);
147
148 if (ref_role) {
149 xmlNode *role = NULL;
150
151 for (role = pcmk__xe_first_child(acl_top, NULL, NULL, NULL);
152 role != NULL; role = pcmk__xe_next(role)) {
153
154 if (!strcmp(PCMK_XE_ACL_ROLE, (const char *) role->name)) {
155 const char *role_id = crm_element_value(role,
156 PCMK_XA_ID);
157
158 if (role_id && strcmp(ref_role, role_id) == 0) {
159 crm_trace("Unpacking referenced role '%s' in ACL <%s> element",
160 role_id, acl_entry->name);
161 acls = parse_acl_entry(acl_top, role, acls);
162 break;
163 }
164 }
165 }
166 }
167
168 /* @COMPAT Use of a tag instead of a PCMK_XA_KIND attribute was
169 * deprecated in 1.1.12. We still need to look for tags named
170 * PCMK_VALUE_READ, etc., to support rolling upgrades. However,
171 * eventually we can clean this up and make the variables more intuitive
172 * (for example, don't assign a PCMK_XA_KIND value to the tag variable).
173 */
174 } else if (strcmp(tag, PCMK_VALUE_READ) == 0) {
175 acls = create_acl(child, acls, pcmk__xf_acl_read);
176
177 } else if (strcmp(tag, PCMK_VALUE_WRITE) == 0) {
178 acls = create_acl(child, acls, pcmk__xf_acl_write);
179
180 } else if (strcmp(tag, PCMK_VALUE_DENY) == 0) {
181 acls = create_acl(child, acls, pcmk__xf_acl_deny);
182
183 } else {
184 crm_warn("Ignoring unknown ACL %s '%s'",
185 (kind? "kind" : "element"), tag);
186 }
187 }
188
189 return acls;
190}
191
192/*
193 <acls>
194 <acl_target id="l33t-haxor"><role id="auto-l33t-haxor"/></acl_target>
195 <acl_role id="auto-l33t-haxor">
196 <acl_permission id="crook-nothing" kind="deny" xpath="/cib"/>
197 </acl_role>
198 <acl_target id="niceguy">
199 <role id="observer"/>
200 </acl_target>
201 <acl_role id="observer">
202 <acl_permission id="observer-read-1" kind="read" xpath="/cib"/>
203 <acl_permission id="observer-write-1" kind="write" xpath="//nvpair[@name='stonith-enabled']"/>
204 <acl_permission id="observer-write-2" kind="write" xpath="//nvpair[@name='target-role']"/>
205 </acl_role>
206 <acl_target id="badidea"><role id="auto-badidea"/></acl_target>
207 <acl_role id="auto-badidea">
208 <acl_permission id="badidea-resources" kind="read" xpath="//meta_attributes"/>
209 <acl_permission id="badidea-resources-2" kind="deny" reference="dummy-meta_attributes"/>
210 </acl_role>
211 </acls>
212*/
213
214static const char *
215acl_to_text(enum xml_private_flags flags)
216{
218 return "deny";
219
220 } else if (pcmk_any_flags_set(flags, pcmk__xf_acl_write|pcmk__xf_acl_create)) {
221 return "read/write";
222
223 } else if (pcmk_is_set(flags, pcmk__xf_acl_read)) {
224 return "read";
225 }
226 return "none";
227}
228
229void
230pcmk__apply_acl(xmlNode *xml)
231{
232 GList *aIter = NULL;
233 xml_doc_private_t *docpriv = xml->doc->_private;
234 xml_node_private_t *nodepriv;
235 xmlXPathObjectPtr xpathObj = NULL;
236
237 if (!xml_acl_enabled(xml)) {
238 crm_trace("Skipping ACLs for user '%s' because not enabled for this XML",
239 docpriv->user);
240 return;
241 }
242
243 for (aIter = docpriv->acls; aIter != NULL; aIter = aIter->next) {
244 int max = 0, lpc = 0;
245 xml_acl_t *acl = aIter->data;
246
247 xpathObj = xpath_search(xml, acl->xpath);
248 max = numXpathResults(xpathObj);
249
250 for (lpc = 0; lpc < max; lpc++) {
251 xmlNode *match = getXpathResult(xpathObj, lpc);
252
253 nodepriv = match->_private;
254 pcmk__set_xml_flags(nodepriv, acl->mode);
255
256 // Build a GString only if tracing is enabled
258 {
259 GString *path = pcmk__element_xpath(match);
260 crm_trace("Applying %s ACL to %s matched by %s",
261 acl_to_text(acl->mode), path->str, acl->xpath);
262 g_string_free(path, TRUE);
263 },
264 {}
265 );
266 }
267 crm_trace("Applied %s ACL %s (%d match%s)",
268 acl_to_text(acl->mode), acl->xpath, max,
269 ((max == 1)? "" : "es"));
270 freeXpathObject(xpathObj);
271 }
272}
273
287void
288pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user)
289{
290 xml_doc_private_t *docpriv = NULL;
291
292 if ((target == NULL) || (target->doc == NULL)
293 || (target->doc->_private == NULL)) {
294 return;
295 }
296
297 docpriv = target->doc->_private;
298 if (!pcmk_acl_required(user)) {
299 crm_trace("Not unpacking ACLs because not required for user '%s'",
300 user);
301
302 } else if (docpriv->acls == NULL) {
303 xmlNode *acls = get_xpath_object("//" PCMK_XE_ACLS, source, LOG_NEVER);
304
305 pcmk__str_update(&docpriv->user, user);
306
307 if (acls) {
308 xmlNode *child = NULL;
309
310 for (child = pcmk__xe_first_child(acls, NULL, NULL, NULL);
311 child != NULL; child = pcmk__xe_next(child)) {
312
313 /* @COMPAT PCMK__XE_ACL_USER was deprecated in Pacemaker 1.1.12
314 * (needed for rolling upgrades)
315 */
316 if (pcmk__xe_is(child, PCMK_XE_ACL_TARGET)
317 || pcmk__xe_is(child, PCMK__XE_ACL_USER)) {
318 const char *id = crm_element_value(child, PCMK_XA_NAME);
319
320 if (id == NULL) {
321 id = crm_element_value(child, PCMK_XA_ID);
322 }
323
324 if (id && strcmp(id, user) == 0) {
325 crm_debug("Unpacking ACLs for user '%s'", id);
326 docpriv->acls = parse_acl_entry(acls, child, docpriv->acls);
327 }
328 } else if (pcmk__xe_is(child, PCMK_XE_ACL_GROUP)) {
329 const char *id = crm_element_value(child, PCMK_XA_NAME);
330
331 if (id == NULL) {
332 id = crm_element_value(child, PCMK_XA_ID);
333 }
334
335 if (id && pcmk__is_user_in_group(user,id)) {
336 crm_debug("Unpacking ACLs for group '%s'", id);
337 docpriv->acls = parse_acl_entry(acls, child, docpriv->acls);
338 }
339 }
340 }
341 }
342 }
343}
344
353void
354pcmk__enable_acl(xmlNode *acl_source, xmlNode *target, const char *user)
355{
356 pcmk__unpack_acl(acl_source, target, user);
359}
360
361static inline bool
362test_acl_mode(enum xml_private_flags allowed, enum xml_private_flags requested)
363{
364 if (pcmk_is_set(allowed, pcmk__xf_acl_deny)) {
365 return false;
366
367 } else if (pcmk_all_flags_set(allowed, requested)) {
368 return true;
369
370 } else if (pcmk_is_set(requested, pcmk__xf_acl_read)
371 && pcmk_is_set(allowed, pcmk__xf_acl_write)) {
372 return true;
373
374 } else if (pcmk_is_set(requested, pcmk__xf_acl_create)
375 && pcmk_any_flags_set(allowed, pcmk__xf_acl_write|pcmk__xf_created)) {
376 return true;
377 }
378 return false;
379}
380
392static bool
393purge_xml_attributes(xmlNode *xml)
394{
395 xmlNode *child = NULL;
396 xmlAttr *xIter = NULL;
397 bool readable_children = false;
398 xml_node_private_t *nodepriv = xml->_private;
399
400 if (test_acl_mode(nodepriv->flags, pcmk__xf_acl_read)) {
401 crm_trace("%s[@" PCMK_XA_ID "=%s] is readable",
402 xml->name, pcmk__xe_id(xml));
403 return true;
404 }
405
406 xIter = xml->properties;
407 while (xIter != NULL) {
408 xmlAttr *tmp = xIter;
409 const char *prop_name = (const char *)xIter->name;
410
411 xIter = xIter->next;
412 if (strcmp(prop_name, PCMK_XA_ID) == 0) {
413 continue;
414 }
415
416 xmlUnsetProp(xml, tmp->name);
417 }
418
419 child = pcmk__xml_first_child(xml);
420 while ( child != NULL ) {
421 xmlNode *tmp = child;
422
423 child = pcmk__xml_next(child);
424 readable_children |= purge_xml_attributes(tmp);
425 }
426
427 if (!readable_children) {
428 free_xml(xml); /* Nothing readable under here, purge completely */
429 }
430 return readable_children;
431}
432
444bool
445xml_acl_filtered_copy(const char *user, xmlNode *acl_source, xmlNode *xml,
446 xmlNode **result)
447{
448 GList *aIter = NULL;
449 xmlNode *target = NULL;
450 xml_doc_private_t *docpriv = NULL;
451
452 *result = NULL;
453 if ((xml == NULL) || !pcmk_acl_required(user)) {
454 crm_trace("Not filtering XML because ACLs not required for user '%s'",
455 user);
456 return false;
457 }
458
459 crm_trace("Filtering XML copy using user '%s' ACLs", user);
460 target = pcmk__xml_copy(NULL, xml);
461 if (target == NULL) {
462 return true;
463 }
464
465 pcmk__enable_acl(acl_source, target, user);
466
467 docpriv = target->doc->_private;
468 for(aIter = docpriv->acls; aIter != NULL && target; aIter = aIter->next) {
469 int max = 0;
470 xml_acl_t *acl = aIter->data;
471
472 if (acl->mode != pcmk__xf_acl_deny) {
473 /* Nothing to do */
474
475 } else if (acl->xpath) {
476 int lpc = 0;
477 xmlXPathObjectPtr xpathObj = xpath_search(target, acl->xpath);
478
479 max = numXpathResults(xpathObj);
480 for(lpc = 0; lpc < max; lpc++) {
481 xmlNode *match = getXpathResult(xpathObj, lpc);
482
483 if (!purge_xml_attributes(match) && (match == target)) {
484 crm_trace("ACLs deny user '%s' access to entire XML document",
485 user);
486 freeXpathObject(xpathObj);
487 return true;
488 }
489 }
490 crm_trace("ACLs deny user '%s' access to %s (%d %s)",
491 user, acl->xpath, max,
492 pcmk__plural_alt(max, "match", "matches"));
493 freeXpathObject(xpathObj);
494 }
495 }
496
497 if (!purge_xml_attributes(target)) {
498 crm_trace("ACLs deny user '%s' access to entire XML document", user);
499 return true;
500 }
501
502 if (docpriv->acls) {
503 g_list_free_full(docpriv->acls, free_acl);
504 docpriv->acls = NULL;
505
506 } else {
507 crm_trace("User '%s' without ACLs denied access to entire XML document",
508 user);
510 target = NULL;
511 }
512
513 if (target) {
514 *result = target;
515 }
516
517 return true;
518}
519
532static bool
533implicitly_allowed(const xmlNode *xml)
534{
535 GString *path = NULL;
536
537 for (xmlAttr *prop = xml->properties; prop != NULL; prop = prop->next) {
538 if (strcmp((const char *) prop->name, PCMK_XA_ID) != 0) {
539 return false;
540 }
541 }
542
544 CRM_ASSERT(path != NULL);
545
546 if (strstr((const char *) path->str, "/" PCMK_XE_ACLS "/") != NULL) {
547 g_string_free(path, TRUE);
548 return false;
549 }
550
551 g_string_free(path, TRUE);
552 return true;
553}
554
555#define display_id(xml) pcmk__s(pcmk__xe_id(xml), "<unset>")
556
572void
573pcmk__apply_creation_acl(xmlNode *xml, bool check_top)
574{
575 xml_node_private_t *nodepriv = xml->_private;
576
577 if (pcmk_is_set(nodepriv->flags, pcmk__xf_created)) {
578 if (implicitly_allowed(xml)) {
579 crm_trace("Creation of <%s> scaffolding with " PCMK_XA_ID "=\"%s\""
580 " is implicitly allowed",
581 xml->name, display_id(xml));
582
583 } else if (pcmk__check_acl(xml, NULL, pcmk__xf_acl_write)) {
584 crm_trace("ACLs allow creation of <%s> with " PCMK_XA_ID "=\"%s\"",
585 xml->name, display_id(xml));
586
587 } else if (check_top) {
588 crm_trace("ACLs disallow creation of <%s> with "
589 PCMK_XA_ID "=\"%s\"", xml->name, display_id(xml));
591 return;
592
593 } else {
594 crm_notice("ACLs would disallow creation of %s<%s> with "
595 PCMK_XA_ID "=\"%s\"",
596 ((xml == xmlDocGetRootElement(xml->doc))? "root element " : ""),
597 xml->name, display_id(xml));
598 }
599 }
600
601 for (xmlNode *cIter = pcmk__xml_first_child(xml); cIter != NULL; ) {
602 xmlNode *child = cIter;
603 cIter = pcmk__xml_next(cIter); /* In case it is free'd */
604 pcmk__apply_creation_acl(child, true);
605 }
606}
607
615bool
616xml_acl_denied(const xmlNode *xml)
617{
618 if (xml && xml->doc && xml->doc->_private){
619 xml_doc_private_t *docpriv = xml->doc->_private;
620
621 return pcmk_is_set(docpriv->flags, pcmk__xf_acl_denied);
622 }
623 return false;
624}
625
626void
627xml_acl_disable(xmlNode *xml)
628{
629 if (xml_acl_enabled(xml)) {
630 xml_doc_private_t *docpriv = xml->doc->_private;
631
632 /* Catch anything that was created but shouldn't have been */
633 pcmk__apply_acl(xml);
634 pcmk__apply_creation_acl(xml, false);
636 }
637}
638
646bool
647xml_acl_enabled(const xmlNode *xml)
648{
649 if (xml && xml->doc && xml->doc->_private){
650 xml_doc_private_t *docpriv = xml->doc->_private;
651
652 return pcmk_is_set(docpriv->flags, pcmk__xf_acl_enabled);
653 }
654 return false;
655}
656
657bool
658pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
659{
660 CRM_ASSERT(xml);
661 CRM_ASSERT(xml->doc);
662 CRM_ASSERT(xml->doc->_private);
663
664 if (pcmk__tracking_xml_changes(xml, false) && xml_acl_enabled(xml)) {
665 xmlNode *parent = xml;
666 xml_doc_private_t *docpriv = xml->doc->_private;
667 GString *xpath = NULL;
668
669 if (docpriv->acls == NULL) {
671
672 pcmk__if_tracing({}, return false);
673 xpath = pcmk__element_xpath(xml);
674 if (name != NULL) {
675 pcmk__g_strcat(xpath, "[@", name, "]", NULL);
676 }
677
678 qb_log_from_external_source(__func__, __FILE__,
679 "User '%s' without ACLs denied %s "
680 "access to %s", LOG_TRACE, __LINE__, 0,
681 docpriv->user, acl_to_text(mode),
682 (const char *) xpath->str);
683 g_string_free(xpath, TRUE);
684 return false;
685 }
686
687 /* Walk the tree upwards looking for xml_acl_* flags
688 * - Creating an attribute requires write permissions for the node
689 * - Creating a child requires write permissions for the parent
690 */
691
692 if (name) {
693 xmlAttr *attr = xmlHasProp(xml, (pcmkXmlStr) name);
694
695 if (attr && mode == pcmk__xf_acl_create) {
696 mode = pcmk__xf_acl_write;
697 }
698 }
699
700 while (parent && parent->_private) {
701 xml_node_private_t *nodepriv = parent->_private;
702 if (test_acl_mode(nodepriv->flags, mode)) {
703 return true;
704
705 } else if (pcmk_is_set(nodepriv->flags, pcmk__xf_acl_deny)) {
707
708 pcmk__if_tracing({}, return false);
709 xpath = pcmk__element_xpath(xml);
710 if (name != NULL) {
711 pcmk__g_strcat(xpath, "[@", name, "]", NULL);
712 }
713
714 qb_log_from_external_source(__func__, __FILE__,
715 "%sACL denies user '%s' %s access "
716 "to %s", LOG_TRACE, __LINE__, 0,
717 (parent != xml)? "Parent ": "",
718 docpriv->user, acl_to_text(mode),
719 (const char *) xpath->str);
720 g_string_free(xpath, TRUE);
721 return false;
722 }
723 parent = parent->parent;
724 }
725
727
728 pcmk__if_tracing({}, return false);
729 xpath = pcmk__element_xpath(xml);
730 if (name != NULL) {
731 pcmk__g_strcat(xpath, "[@", name, "]", NULL);
732 }
733
734 qb_log_from_external_source(__func__, __FILE__,
735 "Default ACL denies user '%s' %s access to "
736 "%s", LOG_TRACE, __LINE__, 0,
737 docpriv->user, acl_to_text(mode),
738 (const char *) xpath->str);
739 g_string_free(xpath, TRUE);
740 return false;
741 }
742
743 return true;
744}
745
753bool
754pcmk_acl_required(const char *user)
755{
756 if (pcmk__str_empty(user)) {
757 crm_trace("ACLs not required because no user set");
758 return false;
759
760 } else if (!strcmp(user, CRM_DAEMON_USER) || !strcmp(user, "root")) {
761 crm_trace("ACLs not required for privileged user %s", user);
762 return false;
763 }
764 crm_trace("ACLs required for %s", user);
765 return true;
766}
767
768char *
770{
771 struct passwd *pwent = getpwuid(uid);
772
773 if (pwent == NULL) {
774 crm_perror(LOG_INFO, "Cannot get user details for user ID %d", uid);
775 return NULL;
776 }
777 return pcmk__str_copy(pwent->pw_name);
778}
779
798const char *
799pcmk__update_acl_user(xmlNode *request, const char *field,
800 const char *peer_user)
801{
802 static const char *effective_user = NULL;
803 const char *requested_user = NULL;
804 const char *user = NULL;
805
806 if (effective_user == NULL) {
807 effective_user = pcmk__uid2username(geteuid());
808 if (effective_user == NULL) {
809 effective_user = pcmk__str_copy("#unprivileged");
810 crm_err("Unable to determine effective user, assuming unprivileged for ACLs");
811 }
812 }
813
814 requested_user = crm_element_value(request, PCMK_XE_ACL_TARGET);
815 if (requested_user == NULL) {
816 /* @COMPAT rolling upgrades <=1.1.11
817 *
818 * field is checked for backward compatibility with older versions that
819 * did not use PCMK_XE_ACL_TARGET.
820 */
821 requested_user = crm_element_value(request, field);
822 }
823
824 if (!pcmk__is_privileged(effective_user)) {
825 /* We're not running as a privileged user, set or overwrite any existing
826 * value for PCMK_XE_ACL_TARGET
827 */
828 user = effective_user;
829
830 } else if (peer_user == NULL && requested_user == NULL) {
831 /* No user known or requested, use 'effective_user' and make sure one is
832 * set for the request
833 */
834 user = effective_user;
835
836 } else if (peer_user == NULL) {
837 /* No user known, trusting 'requested_user' */
838 user = requested_user;
839
840 } else if (!pcmk__is_privileged(peer_user)) {
841 /* The peer is not a privileged user, set or overwrite any existing
842 * value for PCMK_XE_ACL_TARGET
843 */
844 user = peer_user;
845
846 } else if (requested_user == NULL) {
847 /* Even if we're privileged, make sure there is always a value set */
848 user = peer_user;
849
850 } else {
851 /* Legal delegation to 'requested_user' */
852 user = requested_user;
853 }
854
855 // This requires pointer comparison, not string comparison
856 if (user != crm_element_value(request, PCMK_XE_ACL_TARGET)) {
857 crm_xml_add(request, PCMK_XE_ACL_TARGET, user);
858 }
859
860 if (field != NULL && user != crm_element_value(request, field)) {
861 crm_xml_add(request, field, user);
862 }
863
864 return requested_user;
865}
bool xml_acl_denied(const xmlNode *xml)
Check whether or not an XML node is ACL-denied.
Definition acl.c:616
#define display_id(xml)
Definition acl.c:555
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
Definition acl.c:658
void pcmk__free_acls(GList *acls)
Definition acl.c:43
bool pcmk_acl_required(const char *user)
Check whether ACLs are required for a given user.
Definition acl.c:754
char * pcmk__uid2username(uid_t uid)
Definition acl.c:769
struct xml_acl_s xml_acl_t
void xml_acl_disable(xmlNode *xml)
Definition acl.c:627
void pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user)
Definition acl.c:288
const char * pcmk__update_acl_user(xmlNode *request, const char *field, const char *peer_user)
Definition acl.c:799
void pcmk__enable_acl(xmlNode *acl_source, xmlNode *target, const char *user)
Definition acl.c:354
bool xml_acl_filtered_copy(const char *user, xmlNode *acl_source, xmlNode *xml, xmlNode **result)
Copy ACL-allowed portions of specified XML.
Definition acl.c:445
bool xml_acl_enabled(const xmlNode *xml)
Check whether or not an XML node is ACL-enabled.
Definition acl.c:647
void pcmk__apply_creation_acl(xmlNode *xml, bool check_top)
Definition acl.c:573
void pcmk__apply_acl(xmlNode *xml)
Definition acl.c:230
const char * parent
Definition cib.c:27
const char * path
Definition cib.c:28
const char * name
Definition cib.c:26
#define pcmk__assert_alloc(nmemb, size)
Definition internal.h:297
uint64_t flags
Definition remote.c:3
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:98
#define CRM_DAEMON_USER
Definition config.h:30
char data[0]
Definition cpg.c:10
A dumping ground.
#define pcmk__set_xml_flags(xml_priv, flags_to_set)
G_GNUC_INTERNAL bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy)
Definition xml.c:60
#define pcmk__clear_xml_flags(xml_priv, flags_to_clear)
G_GNUC_INTERNAL bool pcmk__is_user_in_group(const char *user, const char *group)
Definition utils.c:53
#define crm_warn(fmt, args...)
Definition logging.h:392
#define crm_notice(fmt, args...)
Definition logging.h:395
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition logging.h:331
#define crm_debug(fmt, args...)
Definition logging.h:400
#define crm_err(fmt, args...)
Definition logging.h:389
#define LOG_NEVER
Definition logging.h:48
#define crm_trace(fmt, args...)
Definition logging.h:402
#define LOG_TRACE
Definition logging.h:38
#define pcmk__if_tracing(if_action, else_action)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:446
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition nvpair.c:301
#define PCMK_VALUE_WRITE
Definition options.h:220
#define PCMK_VALUE_READ
Definition options.h:196
#define PCMK_VALUE_DENY
Definition options.h:146
pcmk__action_result_t result
Definition pcmk_fence.c:35
const char * target
Definition pcmk_fence.c:29
#define CRM_ASSERT(expr)
Definition results.h:42
#define pcmk__plural_alt(i, s1, s2)
void pcmk__str_update(char **str, const char *value)
Definition strings.c:1277
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition strings.c:1050
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
Definition strings.c:1296
#define pcmk__str_copy(str)
Wrappers for and extensions to libxml2.
const xmlChar * pcmkXmlStr
Definition xml.h:41
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition xpath.c:189
xmlNode * getXpathResult(xmlXPathObjectPtr xpathObj, int index)
Definition xpath.c:58
void freeXpathObject(xmlXPathObjectPtr xpathObj)
Definition xpath.c:39
void free_xml(xmlNode *child)
Definition xml.c:867
void pcmk_free_xml_subtree(xmlNode *xml)
Definition xml.c:795
xmlXPathObjectPtr xpath_search(const xmlNode *xml_top, const char *path)
Definition xpath.c:139
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
Definition xml.c:883
void pcmk__set_xml_doc_flag(xmlNode *xml, enum xml_private_flags flag)
Definition xml.c:89
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition xml.c:440
xml_private_flags
@ pcmk__xf_acl_create
@ pcmk__xf_acl_enabled
@ pcmk__xf_created
@ pcmk__xf_acl_denied
@ pcmk__xf_acl_deny
@ pcmk__xf_acl_write
@ pcmk__xf_acl_read
GString * pcmk__element_xpath(const xmlNode *xml)
Definition xpath.c:256
#define PCMK_XE_ACL_GROUP
Definition xml_names.h:55
#define PCMK_XE_ACL_ROLE
Definition xml_names.h:57
#define PCMK_XE_ACL_TARGET
Definition xml_names.h:58
#define PCMK_XA_OBJECT_TYPE
Definition xml_names.h:339
#define PCMK_XA_XPATH
Definition xml_names.h:449
#define PCMK_XA_ID
Definition xml_names.h:296
#define PCMK_XE_ACLS
Definition xml_names.h:59
#define PCMK_XE_ACL_PERMISSION
Definition xml_names.h:56
#define PCMK_XA_KIND
Definition xml_names.h:307
#define PCMK_XA_ATTRIBUTE
Definition xml_names.h:231
#define PCMK_XA_TAG
Definition xml_names.h:412
#define PCMK_XA_NAME
Definition xml_names.h:325
#define PCMK_XE_ROLE
Definition xml_names.h:179
#define PCMK_XA_REFERENCE
Definition xml_names.h:367
#define PCMK__XE_ACL_USER
#define PCMK__XE_ROLE_REF
#define PCMK__XA_REF