pacemaker 2.1.5-a3f44794f94
Scalable High-Availability cluster resource manager
acl.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2022 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/msg_xml.h>
23#include <crm/common/xml.h>
25#include "crmcommon_private.h"
26
27typedef struct xml_acl_s {
28 enum xml_private_flags mode;
29 char *xpath;
31
32static void
33free_acl(void *data)
34{
35 if (data) {
36 xml_acl_t *acl = data;
37
38 free(acl->xpath);
39 free(acl);
40 }
41}
42
43void
44pcmk__free_acls(GList *acls)
45{
46 g_list_free_full(acls, free_acl);
47}
48
49static GList *
50create_acl(const xmlNode *xml, GList *acls, enum xml_private_flags mode)
51{
52 xml_acl_t *acl = NULL;
53
54 const char *tag = crm_element_value(xml, XML_ACL_ATTR_TAG);
55 const char *ref = crm_element_value(xml, XML_ACL_ATTR_REF);
56 const char *xpath = crm_element_value(xml, XML_ACL_ATTR_XPATH);
57 const char *attr = crm_element_value(xml, XML_ACL_ATTR_ATTRIBUTE);
58
59 if (tag == NULL) {
60 // @COMPAT rolling upgrades <=1.1.11
62 }
63 if (ref == NULL) {
64 // @COMPAT rolling upgrades <=1.1.11
66 }
67
68 if ((tag == NULL) && (ref == NULL) && (xpath == NULL)) {
69 // Schema should prevent this, but to be safe ...
70 crm_trace("Ignoring ACL <%s> element without selection criteria",
71 crm_element_name(xml));
72 return NULL;
73 }
74
75 acl = calloc(1, sizeof (xml_acl_t));
76 CRM_ASSERT(acl != NULL);
77
78 acl->mode = mode;
79 if (xpath) {
80 acl->xpath = strdup(xpath);
81 CRM_ASSERT(acl->xpath != NULL);
82 crm_trace("Unpacked ACL <%s> element using xpath: %s",
83 crm_element_name(xml), acl->xpath);
84
85 } else {
86 GString *buf = g_string_sized_new(128);
87
88 if ((ref != NULL) && (attr != NULL)) {
89 // NOTE: schema currently does not allow this
90 pcmk__g_strcat(buf, "//", pcmk__s(tag, "*"), "[@" XML_ATTR_ID "='",
91 ref, "' and @", attr, "]", NULL);
92
93 } else if (ref != NULL) {
94 pcmk__g_strcat(buf, "//", pcmk__s(tag, "*"), "[@" XML_ATTR_ID "='",
95 ref, "']", NULL);
96
97 } else if (attr != NULL) {
98 pcmk__g_strcat(buf, "//", pcmk__s(tag, "*"), "[@", attr, "]", NULL);
99
100 } else {
101 pcmk__g_strcat(buf, "//", pcmk__s(tag, "*"), NULL);
102 }
103
104 acl->xpath = strdup((const char *) buf->str);
105 CRM_ASSERT(acl->xpath != NULL);
106
107 g_string_free(buf, TRUE);
108 crm_trace("Unpacked ACL <%s> element as xpath: %s",
109 crm_element_name(xml), acl->xpath);
110 }
111
112 return g_list_append(acls, acl);
113}
114
127static GList *
128parse_acl_entry(const xmlNode *acl_top, const xmlNode *acl_entry, GList *acls)
129{
130 xmlNode *child = NULL;
131
132 for (child = pcmk__xe_first_child(acl_entry); child;
133 child = pcmk__xe_next(child)) {
134 const char *tag = crm_element_name(child);
135 const char *kind = crm_element_value(child, XML_ACL_ATTR_KIND);
136
137 if (strcmp(XML_ACL_TAG_PERMISSION, tag) == 0){
138 CRM_ASSERT(kind != NULL);
139 crm_trace("Unpacking ACL <%s> element of kind '%s'", tag, kind);
140 tag = kind;
141 } else {
142 crm_trace("Unpacking ACL <%s> element", tag);
143 }
144
145 if (strcmp(XML_ACL_TAG_ROLE_REF, tag) == 0
146 || strcmp(XML_ACL_TAG_ROLE_REFv1, tag) == 0) {
147 const char *ref_role = crm_element_value(child, XML_ATTR_ID);
148
149 if (ref_role) {
150 xmlNode *role = NULL;
151
152 for (role = pcmk__xe_first_child(acl_top); role;
153 role = pcmk__xe_next(role)) {
154 if (!strcmp(XML_ACL_TAG_ROLE, (const char *) role->name)) {
155 const char *role_id = crm_element_value(role,
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, crm_element_name(acl_entry));
161 acls = parse_acl_entry(acl_top, role, acls);
162 break;
163 }
164 }
165 }
166 }
167
168 } else if (strcmp(XML_ACL_TAG_READ, tag) == 0) {
169 acls = create_acl(child, acls, pcmk__xf_acl_read);
170
171 } else if (strcmp(XML_ACL_TAG_WRITE, tag) == 0) {
172 acls = create_acl(child, acls, pcmk__xf_acl_write);
173
174 } else if (strcmp(XML_ACL_TAG_DENY, tag) == 0) {
175 acls = create_acl(child, acls, pcmk__xf_acl_deny);
176
177 } else {
178 crm_warn("Ignoring unknown ACL %s '%s'",
179 (kind? "kind" : "element"), tag);
180 }
181 }
182
183 return acls;
184}
185
186/*
187 <acls>
188 <acl_target id="l33t-haxor"><role id="auto-l33t-haxor"/></acl_target>
189 <acl_role id="auto-l33t-haxor">
190 <acl_permission id="crook-nothing" kind="deny" xpath="/cib"/>
191 </acl_role>
192 <acl_target id="niceguy">
193 <role id="observer"/>
194 </acl_target>
195 <acl_role id="observer">
196 <acl_permission id="observer-read-1" kind="read" xpath="/cib"/>
197 <acl_permission id="observer-write-1" kind="write" xpath="//nvpair[@name='stonith-enabled']"/>
198 <acl_permission id="observer-write-2" kind="write" xpath="//nvpair[@name='target-role']"/>
199 </acl_role>
200 <acl_target id="badidea"><role id="auto-badidea"/></acl_target>
201 <acl_role id="auto-badidea">
202 <acl_permission id="badidea-resources" kind="read" xpath="//meta_attributes"/>
203 <acl_permission id="badidea-resources-2" kind="deny" reference="dummy-meta_attributes"/>
204 </acl_role>
205 </acls>
206*/
207
208static const char *
209acl_to_text(enum xml_private_flags flags)
210{
212 return "deny";
213
214 } else if (pcmk_any_flags_set(flags, pcmk__xf_acl_write|pcmk__xf_acl_create)) {
215 return "read/write";
216
217 } else if (pcmk_is_set(flags, pcmk__xf_acl_read)) {
218 return "read";
219 }
220 return "none";
221}
222
223void
224pcmk__apply_acl(xmlNode *xml)
225{
226 GList *aIter = NULL;
227 xml_doc_private_t *docpriv = xml->doc->_private;
228 xml_node_private_t *nodepriv;
229 xmlXPathObjectPtr xpathObj = NULL;
230
231 if (!xml_acl_enabled(xml)) {
232 crm_trace("Skipping ACLs for user '%s' because not enabled for this XML",
233 docpriv->user);
234 return;
235 }
236
237 for (aIter = docpriv->acls; aIter != NULL; aIter = aIter->next) {
238 int max = 0, lpc = 0;
239 xml_acl_t *acl = aIter->data;
240
241 xpathObj = xpath_search(xml, acl->xpath);
242 max = numXpathResults(xpathObj);
243
244 for (lpc = 0; lpc < max; lpc++) {
245 static struct qb_log_callsite *trace_cs = NULL;
246 xmlNode *match = getXpathResult(xpathObj, lpc);
247
248 nodepriv = match->_private;
249 pcmk__set_xml_flags(nodepriv, acl->mode);
250
251 /* Build a GString only if tracing is enabled.
252 * Can't use pcmk__log_else() because the else_action would be
253 * continue.
254 */
255 if (trace_cs == NULL) {
256 trace_cs = qb_log_callsite_get(__func__, __FILE__, "apply_acl",
257 LOG_TRACE, __LINE__, 0);
258 }
259 if (crm_is_callsite_active(trace_cs, LOG_TRACE, 0)) {
260 GString *path = pcmk__element_xpath(match);
261 crm_trace("Applying %s ACL to %s matched by %s",
262 acl_to_text(acl->mode), (const char *) path->str,
263 acl->xpath);
264 g_string_free(path, TRUE);
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("//" XML_CIB_TAG_ACLS,
304 source, LOG_NEVER);
305
306 pcmk__str_update(&docpriv->user, user);
307
308 if (acls) {
309 xmlNode *child = NULL;
310
311 for (child = pcmk__xe_first_child(acls); child;
312 child = pcmk__xe_next(child)) {
313 const char *tag = crm_element_name(child);
314
315 if (!strcmp(tag, XML_ACL_TAG_USER)
316 || !strcmp(tag, XML_ACL_TAG_USERv1)) {
317 const char *id = crm_element_value(child, XML_ATTR_NAME);
318
319 if (id == NULL) {
320 id = crm_element_value(child, XML_ATTR_ID);
321 }
322
323 if (id && strcmp(id, user) == 0) {
324 crm_debug("Unpacking ACLs for user '%s'", id);
325 docpriv->acls = parse_acl_entry(acls, child, docpriv->acls);
326 }
327 } else if (!strcmp(tag, XML_ACL_TAG_GROUP)) {
328 const char *id = crm_element_value(child, XML_ATTR_NAME);
329
330 if (id == NULL) {
331 id = crm_element_value(child, XML_ATTR_ID);
332 }
333
334 if (id && pcmk__is_user_in_group(user,id)) {
335 crm_debug("Unpacking ACLs for group '%s'", id);
336 docpriv->acls = parse_acl_entry(acls, child, docpriv->acls);
337 }
338 }
339 }
340 }
341 }
342}
343
352void
353pcmk__enable_acl(xmlNode *acl_source, xmlNode *target, const char *user)
354{
355 pcmk__unpack_acl(acl_source, target, user);
358}
359
360static inline bool
361test_acl_mode(enum xml_private_flags allowed, enum xml_private_flags requested)
362{
363 if (pcmk_is_set(allowed, pcmk__xf_acl_deny)) {
364 return false;
365
366 } else if (pcmk_all_flags_set(allowed, requested)) {
367 return true;
368
369 } else if (pcmk_is_set(requested, pcmk__xf_acl_read)
370 && pcmk_is_set(allowed, pcmk__xf_acl_write)) {
371 return true;
372
373 } else if (pcmk_is_set(requested, pcmk__xf_acl_create)
374 && pcmk_any_flags_set(allowed, pcmk__xf_acl_write|pcmk__xf_created)) {
375 return true;
376 }
377 return false;
378}
379
391static bool
392purge_xml_attributes(xmlNode *xml)
393{
394 xmlNode *child = NULL;
395 xmlAttr *xIter = NULL;
396 bool readable_children = false;
397 xml_node_private_t *nodepriv = xml->_private;
398
399 if (test_acl_mode(nodepriv->flags, pcmk__xf_acl_read)) {
400 crm_trace("%s[@id=%s] is readable", crm_element_name(xml), ID(xml));
401 return true;
402 }
403
404 xIter = xml->properties;
405 while (xIter != NULL) {
406 xmlAttr *tmp = xIter;
407 const char *prop_name = (const char *)xIter->name;
408
409 xIter = xIter->next;
410 if (strcmp(prop_name, XML_ATTR_ID) == 0) {
411 continue;
412 }
413
414 xmlUnsetProp(xml, tmp->name);
415 }
416
417 child = pcmk__xml_first_child(xml);
418 while ( child != NULL ) {
419 xmlNode *tmp = child;
420
421 child = pcmk__xml_next(child);
422 readable_children |= purge_xml_attributes(tmp);
423 }
424
425 if (!readable_children) {
426 free_xml(xml); /* Nothing readable under here, purge completely */
427 }
428 return readable_children;
429}
430
442bool
443xml_acl_filtered_copy(const char *user, xmlNode *acl_source, xmlNode *xml,
444 xmlNode **result)
445{
446 GList *aIter = NULL;
447 xmlNode *target = NULL;
448 xml_doc_private_t *docpriv = NULL;
449
450 *result = NULL;
451 if ((xml == NULL) || !pcmk_acl_required(user)) {
452 crm_trace("Not filtering XML because ACLs not required for user '%s'",
453 user);
454 return false;
455 }
456
457 crm_trace("Filtering XML copy using user '%s' ACLs", user);
458 target = copy_xml(xml);
459 if (target == NULL) {
460 return true;
461 }
462
463 pcmk__enable_acl(acl_source, target, user);
464
465 docpriv = target->doc->_private;
466 for(aIter = docpriv->acls; aIter != NULL && target; aIter = aIter->next) {
467 int max = 0;
468 xml_acl_t *acl = aIter->data;
469
470 if (acl->mode != pcmk__xf_acl_deny) {
471 /* Nothing to do */
472
473 } else if (acl->xpath) {
474 int lpc = 0;
475 xmlXPathObjectPtr xpathObj = xpath_search(target, acl->xpath);
476
477 max = numXpathResults(xpathObj);
478 for(lpc = 0; lpc < max; lpc++) {
479 xmlNode *match = getXpathResult(xpathObj, lpc);
480
481 if (!purge_xml_attributes(match) && (match == target)) {
482 crm_trace("ACLs deny user '%s' access to entire XML document",
483 user);
484 freeXpathObject(xpathObj);
485 return true;
486 }
487 }
488 crm_trace("ACLs deny user '%s' access to %s (%d %s)",
489 user, acl->xpath, max,
490 pcmk__plural_alt(max, "match", "matches"));
491 freeXpathObject(xpathObj);
492 }
493 }
494
495 if (!purge_xml_attributes(target)) {
496 crm_trace("ACLs deny user '%s' access to entire XML document", user);
497 return true;
498 }
499
500 if (docpriv->acls) {
501 g_list_free_full(docpriv->acls, free_acl);
502 docpriv->acls = NULL;
503
504 } else {
505 crm_trace("User '%s' without ACLs denied access to entire XML document",
506 user);
508 target = NULL;
509 }
510
511 if (target) {
512 *result = target;
513 }
514
515 return true;
516}
517
530static bool
531implicitly_allowed(const xmlNode *xml)
532{
533 GString *path = NULL;
534
535 for (xmlAttr *prop = xml->properties; prop != NULL; prop = prop->next) {
536 if (strcmp((const char *) prop->name, XML_ATTR_ID) != 0) {
537 return false;
538 }
539 }
540
542 CRM_ASSERT(path != NULL);
543
544 if (strstr((const char *) path->str, "/" XML_CIB_TAG_ACLS "/") != NULL) {
545 g_string_free(path, TRUE);
546 return false;
547 }
548
549 g_string_free(path, TRUE);
550 return true;
551}
552
553#define display_id(xml) (ID(xml)? ID(xml) : "<unset>")
554
570void
571pcmk__apply_creation_acl(xmlNode *xml, bool check_top)
572{
573 xml_node_private_t *nodepriv = xml->_private;
574
575 if (pcmk_is_set(nodepriv->flags, pcmk__xf_created)) {
576 if (implicitly_allowed(xml)) {
577 crm_trace("Creation of <%s> scaffolding with id=\"%s\""
578 " is implicitly allowed",
579 crm_element_name(xml), display_id(xml));
580
581 } else if (pcmk__check_acl(xml, NULL, pcmk__xf_acl_write)) {
582 crm_trace("ACLs allow creation of <%s> with id=\"%s\"",
583 crm_element_name(xml), display_id(xml));
584
585 } else if (check_top) {
586 crm_trace("ACLs disallow creation of <%s> with id=\"%s\"",
587 crm_element_name(xml), display_id(xml));
589 return;
590
591 } else {
592 crm_notice("ACLs would disallow creation of %s<%s> with id=\"%s\" ",
593 ((xml == xmlDocGetRootElement(xml->doc))? "root element " : ""),
594 crm_element_name(xml), display_id(xml));
595 }
596 }
597
598 for (xmlNode *cIter = pcmk__xml_first_child(xml); cIter != NULL; ) {
599 xmlNode *child = cIter;
600 cIter = pcmk__xml_next(cIter); /* In case it is free'd */
601 pcmk__apply_creation_acl(child, true);
602 }
603}
604
612bool
613xml_acl_denied(const xmlNode *xml)
614{
615 if (xml && xml->doc && xml->doc->_private){
616 xml_doc_private_t *docpriv = xml->doc->_private;
617
618 return pcmk_is_set(docpriv->flags, pcmk__xf_acl_denied);
619 }
620 return false;
621}
622
623void
624xml_acl_disable(xmlNode *xml)
625{
626 if (xml_acl_enabled(xml)) {
627 xml_doc_private_t *docpriv = xml->doc->_private;
628
629 /* Catch anything that was created but shouldn't have been */
630 pcmk__apply_acl(xml);
631 pcmk__apply_creation_acl(xml, false);
633 }
634}
635
643bool
644xml_acl_enabled(const xmlNode *xml)
645{
646 if (xml && xml->doc && xml->doc->_private){
647 xml_doc_private_t *docpriv = xml->doc->_private;
648
649 return pcmk_is_set(docpriv->flags, pcmk__xf_acl_enabled);
650 }
651 return false;
652}
653
654bool
655pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
656{
657 CRM_ASSERT(xml);
658 CRM_ASSERT(xml->doc);
659 CRM_ASSERT(xml->doc->_private);
660
661 if (pcmk__tracking_xml_changes(xml, false) && xml_acl_enabled(xml)) {
662 xmlNode *parent = xml;
663 xml_doc_private_t *docpriv = xml->doc->_private;
664 GString *xpath = NULL;
665
666 if (docpriv->acls == NULL) {
668
669 pcmk__log_else(LOG_TRACE, return false);
670 xpath = pcmk__element_xpath(xml);
671 if (name != NULL) {
672 pcmk__g_strcat(xpath, "[@", name, "]", NULL);
673 }
674
675 qb_log_from_external_source(__func__, __FILE__,
676 "User '%s' without ACLs denied %s "
677 "access to %s", LOG_TRACE, __LINE__, 0,
678 docpriv->user, acl_to_text(mode),
679 (const char *) xpath->str);
680 g_string_free(xpath, TRUE);
681 return false;
682 }
683
684 /* Walk the tree upwards looking for xml_acl_* flags
685 * - Creating an attribute requires write permissions for the node
686 * - Creating a child requires write permissions for the parent
687 */
688
689 if (name) {
690 xmlAttr *attr = xmlHasProp(xml, (pcmkXmlStr) name);
691
692 if (attr && mode == pcmk__xf_acl_create) {
693 mode = pcmk__xf_acl_write;
694 }
695 }
696
697 while (parent && parent->_private) {
698 xml_node_private_t *nodepriv = parent->_private;
699 if (test_acl_mode(nodepriv->flags, mode)) {
700 return true;
701
702 } else if (pcmk_is_set(nodepriv->flags, pcmk__xf_acl_deny)) {
704
705 pcmk__log_else(LOG_TRACE, return false);
706 xpath = pcmk__element_xpath(xml);
707 if (name != NULL) {
708 pcmk__g_strcat(xpath, "[@", name, "]", NULL);
709 }
710
711 qb_log_from_external_source(__func__, __FILE__,
712 "%sACL denies user '%s' %s access "
713 "to %s", LOG_TRACE, __LINE__, 0,
714 (parent != xml)? "Parent ": "",
715 docpriv->user, acl_to_text(mode),
716 (const char *) xpath->str);
717 g_string_free(xpath, TRUE);
718 return false;
719 }
720 parent = parent->parent;
721 }
722
724
725 pcmk__log_else(LOG_TRACE, return false);
726 xpath = pcmk__element_xpath(xml);
727 if (name != NULL) {
728 pcmk__g_strcat(xpath, "[@", name, "]", NULL);
729 }
730
731 qb_log_from_external_source(__func__, __FILE__,
732 "Default ACL denies user '%s' %s access to "
733 "%s", LOG_TRACE, __LINE__, 0,
734 docpriv->user, acl_to_text(mode),
735 (const char *) xpath->str);
736 g_string_free(xpath, TRUE);
737 return false;
738 }
739
740 return true;
741}
742
750bool
751pcmk_acl_required(const char *user)
752{
753 if (pcmk__str_empty(user)) {
754 crm_trace("ACLs not required because no user set");
755 return false;
756
757 } else if (!strcmp(user, CRM_DAEMON_USER) || !strcmp(user, "root")) {
758 crm_trace("ACLs not required for privileged user %s", user);
759 return false;
760 }
761 crm_trace("ACLs required for %s", user);
762 return true;
763}
764
765char *
767{
768 struct passwd *pwent = getpwuid(uid);
769
770 if (pwent == NULL) {
771 crm_perror(LOG_INFO, "Cannot get user details for user ID %d", uid);
772 return NULL;
773 }
774 return strdup(pwent->pw_name);
775}
776
795const char *
796pcmk__update_acl_user(xmlNode *request, const char *field,
797 const char *peer_user)
798{
799 static const char *effective_user = NULL;
800 const char *requested_user = NULL;
801 const char *user = NULL;
802
803 if (effective_user == NULL) {
804 effective_user = pcmk__uid2username(geteuid());
805 if (effective_user == NULL) {
806 effective_user = strdup("#unprivileged");
807 CRM_CHECK(effective_user != NULL, return NULL);
808 crm_err("Unable to determine effective user, assuming unprivileged for ACLs");
809 }
810 }
811
812 requested_user = crm_element_value(request, XML_ACL_TAG_USER);
813 if (requested_user == NULL) {
814 /* @COMPAT rolling upgrades <=1.1.11
815 *
816 * field is checked for backward compatibility with older versions that
817 * did not use XML_ACL_TAG_USER.
818 */
819 requested_user = crm_element_value(request, field);
820 }
821
822 if (!pcmk__is_privileged(effective_user)) {
823 /* We're not running as a privileged user, set or overwrite any existing
824 * value for $XML_ACL_TAG_USER
825 */
826 user = effective_user;
827
828 } else if (peer_user == NULL && requested_user == NULL) {
829 /* No user known or requested, use 'effective_user' and make sure one is
830 * set for the request
831 */
832 user = effective_user;
833
834 } else if (peer_user == NULL) {
835 /* No user known, trusting 'requested_user' */
836 user = requested_user;
837
838 } else if (!pcmk__is_privileged(peer_user)) {
839 /* The peer is not a privileged user, set or overwrite any existing
840 * value for $XML_ACL_TAG_USER
841 */
842 user = peer_user;
843
844 } else if (requested_user == NULL) {
845 /* Even if we're privileged, make sure there is always a value set */
846 user = peer_user;
847
848 } else {
849 /* Legal delegation to 'requested_user' */
850 user = requested_user;
851 }
852
853 // This requires pointer comparison, not string comparison
854 if (user != crm_element_value(request, XML_ACL_TAG_USER)) {
855 crm_xml_add(request, XML_ACL_TAG_USER, user);
856 }
857
858 if (field != NULL && user != crm_element_value(request, field)) {
859 crm_xml_add(request, field, user);
860 }
861
862 return requested_user;
863}
bool xml_acl_denied(const xmlNode *xml)
Check whether or not an XML node is ACL-denied.
Definition: acl.c:613
#define display_id(xml)
Definition: acl.c:553
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
Definition: acl.c:655
void pcmk__free_acls(GList *acls)
Definition: acl.c:44
bool pcmk_acl_required(const char *user)
Check whether ACLs are required for a given user.
Definition: acl.c:751
char * pcmk__uid2username(uid_t uid)
Definition: acl.c:766
struct xml_acl_s xml_acl_t
void xml_acl_disable(xmlNode *xml)
Definition: acl.c:624
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:796
void pcmk__enable_acl(xmlNode *acl_source, xmlNode *target, const char *user)
Definition: acl.c:353
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:443
bool xml_acl_enabled(const xmlNode *xml)
Check whether or not an XML node is ACL-enabled.
Definition: acl.c:644
void pcmk__apply_creation_acl(xmlNode *xml, bool check_top)
Definition: acl.c:571
void pcmk__apply_acl(xmlNode *xml)
Definition: acl.c:224
const char * parent
Definition: cib.c:25
const char * path
Definition: cib.c:26
const char * name
Definition: cib.c:24
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:121
#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:49
#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:54
gboolean crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags)
Definition: logging.c:635
#define crm_warn(fmt, args...)
Definition: logging.h:360
#define crm_notice(fmt, args...)
Definition: logging.h:361
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition: logging.h:310
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:227
#define crm_debug(fmt, args...)
Definition: logging.h:364
#define crm_err(fmt, args...)
Definition: logging.h:359
#define LOG_NEVER
Definition: logging.h:47
#define crm_trace(fmt, args...)
Definition: logging.h:365
#define LOG_TRACE
Definition: logging.h:37
#define pcmk__log_else(level, else_action)
#define XML_ACL_TAG_ROLE
Definition: msg_xml.h:425
#define XML_ACL_TAG_PERMISSION
Definition: msg_xml.h:426
#define XML_ACL_TAG_USERv1
Definition: msg_xml.h:423
#define XML_ACL_ATTR_TAG
Definition: msg_xml.h:435
#define ID(x)
Definition: msg_xml.h:468
#define XML_ACL_ATTR_ATTRIBUTE
Definition: msg_xml.h:438
#define XML_ACL_TAG_USER
Definition: msg_xml.h:422
#define XML_ACL_TAG_WRITE
Definition: msg_xml.h:431
#define XML_ACL_TAG_ROLE_REF
Definition: msg_xml.h:427
#define XML_CIB_TAG_ACLS
Definition: msg_xml.h:193
#define XML_ACL_TAG_DENY
Definition: msg_xml.h:432
#define XML_ACL_TAG_READ
Definition: msg_xml.h:430
#define XML_ATTR_ID
Definition: msg_xml.h:134
#define XML_ACL_ATTR_XPATH
Definition: msg_xml.h:437
#define XML_ACL_TAG_GROUP
Definition: msg_xml.h:424
#define XML_ACL_ATTR_KIND
Definition: msg_xml.h:429
#define XML_ACL_ATTR_TAGv1
Definition: msg_xml.h:436
#define XML_ACL_TAG_ROLE_REFv1
Definition: msg_xml.h:428
#define XML_ACL_ATTR_REF
Definition: msg_xml.h:433
#define XML_ACL_ATTR_REFv1
Definition: msg_xml.h:434
#define XML_ATTR_NAME
Definition: msg_xml.h:135
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:517
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:323
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:1190
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:1214
Wrappers for and extensions to libxml2.
xmlXPathObjectPtr xpath_search(xmlNode *xml_top, const char *path)
Definition: xpath.c:139
const xmlChar * pcmkXmlStr
Definition: xml.h:50
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:214
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:885
void pcmk_free_xml_subtree(xmlNode *xml)
Definition: xml.c:808
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:891
void pcmk__set_xml_doc_flag(xmlNode *xml, enum xml_private_flags flag)
Definition: xml.c:108
xml_private_flags
Definition: xml_internal.h:320
@ pcmk__xf_acl_create
Definition: xml_internal.h:337
@ pcmk__xf_acl_enabled
Definition: xml_internal.h:332
@ pcmk__xf_created
Definition: xml_internal.h:324
@ pcmk__xf_acl_denied
Definition: xml_internal.h:338
@ pcmk__xf_acl_deny
Definition: xml_internal.h:335
@ pcmk__xf_acl_write
Definition: xml_internal.h:334
@ pcmk__xf_acl_read
Definition: xml_internal.h:333
GString * pcmk__element_xpath(const xmlNode *xml)
Definition: xpath.c:281