pacemaker 2.1.7-2.1.7
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
acl.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2023 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 gchar *xpath;
31
32static void
33free_acl(void *data)
34{
35 if (data) {
36 xml_acl_t *acl = data;
37
38 g_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 xml->name);
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 = g_strdup(xpath);
81 crm_trace("Unpacked ACL <%s> element using xpath: %s",
82 xml->name, acl->xpath);
83
84 } else {
85 GString *buf = g_string_sized_new(128);
86
87 if ((ref != NULL) && (attr != NULL)) {
88 // NOTE: schema currently does not allow this
89 pcmk__g_strcat(buf, "//", pcmk__s(tag, "*"), "[@" XML_ATTR_ID "='",
90 ref, "' and @", attr, "]", NULL);
91
92 } else if (ref != NULL) {
93 pcmk__g_strcat(buf, "//", pcmk__s(tag, "*"), "[@" XML_ATTR_ID "='",
94 ref, "']", NULL);
95
96 } else if (attr != NULL) {
97 pcmk__g_strcat(buf, "//", pcmk__s(tag, "*"), "[@", attr, "]", NULL);
98
99 } else {
100 pcmk__g_strcat(buf, "//", pcmk__s(tag, "*"), NULL);
101 }
102
103 acl->xpath = buf->str;
104
105 g_string_free(buf, FALSE);
106 crm_trace("Unpacked ACL <%s> element as xpath: %s",
107 xml->name, acl->xpath);
108 }
109
110 return g_list_append(acls, acl);
111}
112
125static GList *
126parse_acl_entry(const xmlNode *acl_top, const xmlNode *acl_entry, GList *acls)
127{
128 xmlNode *child = NULL;
129
130 for (child = pcmk__xe_first_child(acl_entry); child;
131 child = pcmk__xe_next(child)) {
132 const char *tag = (const char *) child->name;
133 const char *kind = crm_element_value(child, XML_ACL_ATTR_KIND);
134
135 if (pcmk__xe_is(child, XML_ACL_TAG_PERMISSION)) {
136 CRM_ASSERT(kind != NULL);
137 crm_trace("Unpacking ACL <%s> element of kind '%s'", tag, kind);
138 tag = kind;
139 } else {
140 crm_trace("Unpacking ACL <%s> element", tag);
141 }
142
143 if (strcmp(XML_ACL_TAG_ROLE_REF, tag) == 0
144 || strcmp(XML_ACL_TAG_ROLE_REFv1, tag) == 0) {
145 const char *ref_role = crm_element_value(child, XML_ATTR_ID);
146
147 if (ref_role) {
148 xmlNode *role = NULL;
149
150 for (role = pcmk__xe_first_child(acl_top); role;
151 role = pcmk__xe_next(role)) {
152 if (!strcmp(XML_ACL_TAG_ROLE, (const char *) role->name)) {
153 const char *role_id = crm_element_value(role,
155
156 if (role_id && strcmp(ref_role, role_id) == 0) {
157 crm_trace("Unpacking referenced role '%s' in ACL <%s> element",
158 role_id, acl_entry->name);
159 acls = parse_acl_entry(acl_top, role, acls);
160 break;
161 }
162 }
163 }
164 }
165
166 } else if (strcmp(XML_ACL_TAG_READ, tag) == 0) {
167 acls = create_acl(child, acls, pcmk__xf_acl_read);
168
169 } else if (strcmp(XML_ACL_TAG_WRITE, tag) == 0) {
170 acls = create_acl(child, acls, pcmk__xf_acl_write);
171
172 } else if (strcmp(XML_ACL_TAG_DENY, tag) == 0) {
173 acls = create_acl(child, acls, pcmk__xf_acl_deny);
174
175 } else {
176 crm_warn("Ignoring unknown ACL %s '%s'",
177 (kind? "kind" : "element"), tag);
178 }
179 }
180
181 return acls;
182}
183
184/*
185 <acls>
186 <acl_target id="l33t-haxor"><role id="auto-l33t-haxor"/></acl_target>
187 <acl_role id="auto-l33t-haxor">
188 <acl_permission id="crook-nothing" kind="deny" xpath="/cib"/>
189 </acl_role>
190 <acl_target id="niceguy">
191 <role id="observer"/>
192 </acl_target>
193 <acl_role id="observer">
194 <acl_permission id="observer-read-1" kind="read" xpath="/cib"/>
195 <acl_permission id="observer-write-1" kind="write" xpath="//nvpair[@name='stonith-enabled']"/>
196 <acl_permission id="observer-write-2" kind="write" xpath="//nvpair[@name='target-role']"/>
197 </acl_role>
198 <acl_target id="badidea"><role id="auto-badidea"/></acl_target>
199 <acl_role id="auto-badidea">
200 <acl_permission id="badidea-resources" kind="read" xpath="//meta_attributes"/>
201 <acl_permission id="badidea-resources-2" kind="deny" reference="dummy-meta_attributes"/>
202 </acl_role>
203 </acls>
204*/
205
206static const char *
207acl_to_text(enum xml_private_flags flags)
208{
210 return "deny";
211
212 } else if (pcmk_any_flags_set(flags, pcmk__xf_acl_write|pcmk__xf_acl_create)) {
213 return "read/write";
214
215 } else if (pcmk_is_set(flags, pcmk__xf_acl_read)) {
216 return "read";
217 }
218 return "none";
219}
220
221void
222pcmk__apply_acl(xmlNode *xml)
223{
224 GList *aIter = NULL;
225 xml_doc_private_t *docpriv = xml->doc->_private;
226 xml_node_private_t *nodepriv;
227 xmlXPathObjectPtr xpathObj = NULL;
228
229 if (!xml_acl_enabled(xml)) {
230 crm_trace("Skipping ACLs for user '%s' because not enabled for this XML",
231 docpriv->user);
232 return;
233 }
234
235 for (aIter = docpriv->acls; aIter != NULL; aIter = aIter->next) {
236 int max = 0, lpc = 0;
237 xml_acl_t *acl = aIter->data;
238
239 xpathObj = xpath_search(xml, acl->xpath);
240 max = numXpathResults(xpathObj);
241
242 for (lpc = 0; lpc < max; lpc++) {
243 xmlNode *match = getXpathResult(xpathObj, lpc);
244
245 nodepriv = match->_private;
246 pcmk__set_xml_flags(nodepriv, acl->mode);
247
248 // Build a GString only if tracing is enabled
250 {
251 GString *path = pcmk__element_xpath(match);
252 crm_trace("Applying %s ACL to %s matched by %s",
253 acl_to_text(acl->mode), path->str, acl->xpath);
254 g_string_free(path, TRUE);
255 },
256 {}
257 );
258 }
259 crm_trace("Applied %s ACL %s (%d match%s)",
260 acl_to_text(acl->mode), acl->xpath, max,
261 ((max == 1)? "" : "es"));
262 freeXpathObject(xpathObj);
263 }
264}
265
279void
280pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user)
281{
282 xml_doc_private_t *docpriv = NULL;
283
284 if ((target == NULL) || (target->doc == NULL)
285 || (target->doc->_private == NULL)) {
286 return;
287 }
288
289 docpriv = target->doc->_private;
290 if (!pcmk_acl_required(user)) {
291 crm_trace("Not unpacking ACLs because not required for user '%s'",
292 user);
293
294 } else if (docpriv->acls == NULL) {
295 xmlNode *acls = get_xpath_object("//" XML_CIB_TAG_ACLS,
296 source, LOG_NEVER);
297
298 pcmk__str_update(&docpriv->user, user);
299
300 if (acls) {
301 xmlNode *child = NULL;
302
303 for (child = pcmk__xe_first_child(acls); child;
304 child = pcmk__xe_next(child)) {
305
306 if (pcmk__xe_is(child, XML_ACL_TAG_USER)
307 || pcmk__xe_is(child, XML_ACL_TAG_USERv1)) {
308 const char *id = crm_element_value(child, XML_ATTR_NAME);
309
310 if (id == NULL) {
311 id = crm_element_value(child, XML_ATTR_ID);
312 }
313
314 if (id && strcmp(id, user) == 0) {
315 crm_debug("Unpacking ACLs for user '%s'", id);
316 docpriv->acls = parse_acl_entry(acls, child, docpriv->acls);
317 }
318 } else if (pcmk__xe_is(child, XML_ACL_TAG_GROUP)) {
319 const char *id = crm_element_value(child, XML_ATTR_NAME);
320
321 if (id == NULL) {
322 id = crm_element_value(child, XML_ATTR_ID);
323 }
324
325 if (id && pcmk__is_user_in_group(user,id)) {
326 crm_debug("Unpacking ACLs for group '%s'", id);
327 docpriv->acls = parse_acl_entry(acls, child, docpriv->acls);
328 }
329 }
330 }
331 }
332 }
333}
334
343void
344pcmk__enable_acl(xmlNode *acl_source, xmlNode *target, const char *user)
345{
346 pcmk__unpack_acl(acl_source, target, user);
349}
350
351static inline bool
352test_acl_mode(enum xml_private_flags allowed, enum xml_private_flags requested)
353{
354 if (pcmk_is_set(allowed, pcmk__xf_acl_deny)) {
355 return false;
356
357 } else if (pcmk_all_flags_set(allowed, requested)) {
358 return true;
359
360 } else if (pcmk_is_set(requested, pcmk__xf_acl_read)
361 && pcmk_is_set(allowed, pcmk__xf_acl_write)) {
362 return true;
363
364 } else if (pcmk_is_set(requested, pcmk__xf_acl_create)
365 && pcmk_any_flags_set(allowed, pcmk__xf_acl_write|pcmk__xf_created)) {
366 return true;
367 }
368 return false;
369}
370
382static bool
383purge_xml_attributes(xmlNode *xml)
384{
385 xmlNode *child = NULL;
386 xmlAttr *xIter = NULL;
387 bool readable_children = false;
388 xml_node_private_t *nodepriv = xml->_private;
389
390 if (test_acl_mode(nodepriv->flags, pcmk__xf_acl_read)) {
391 crm_trace("%s[@" XML_ATTR_ID "=%s] is readable",
392 xml->name, ID(xml));
393 return true;
394 }
395
396 xIter = xml->properties;
397 while (xIter != NULL) {
398 xmlAttr *tmp = xIter;
399 const char *prop_name = (const char *)xIter->name;
400
401 xIter = xIter->next;
402 if (strcmp(prop_name, XML_ATTR_ID) == 0) {
403 continue;
404 }
405
406 xmlUnsetProp(xml, tmp->name);
407 }
408
409 child = pcmk__xml_first_child(xml);
410 while ( child != NULL ) {
411 xmlNode *tmp = child;
412
413 child = pcmk__xml_next(child);
414 readable_children |= purge_xml_attributes(tmp);
415 }
416
417 if (!readable_children) {
418 free_xml(xml); /* Nothing readable under here, purge completely */
419 }
420 return readable_children;
421}
422
434bool
435xml_acl_filtered_copy(const char *user, xmlNode *acl_source, xmlNode *xml,
436 xmlNode **result)
437{
438 GList *aIter = NULL;
439 xmlNode *target = NULL;
440 xml_doc_private_t *docpriv = NULL;
441
442 *result = NULL;
443 if ((xml == NULL) || !pcmk_acl_required(user)) {
444 crm_trace("Not filtering XML because ACLs not required for user '%s'",
445 user);
446 return false;
447 }
448
449 crm_trace("Filtering XML copy using user '%s' ACLs", user);
450 target = copy_xml(xml);
451 if (target == NULL) {
452 return true;
453 }
454
455 pcmk__enable_acl(acl_source, target, user);
456
457 docpriv = target->doc->_private;
458 for(aIter = docpriv->acls; aIter != NULL && target; aIter = aIter->next) {
459 int max = 0;
460 xml_acl_t *acl = aIter->data;
461
462 if (acl->mode != pcmk__xf_acl_deny) {
463 /* Nothing to do */
464
465 } else if (acl->xpath) {
466 int lpc = 0;
467 xmlXPathObjectPtr xpathObj = xpath_search(target, acl->xpath);
468
469 max = numXpathResults(xpathObj);
470 for(lpc = 0; lpc < max; lpc++) {
471 xmlNode *match = getXpathResult(xpathObj, lpc);
472
473 if (!purge_xml_attributes(match) && (match == target)) {
474 crm_trace("ACLs deny user '%s' access to entire XML document",
475 user);
476 freeXpathObject(xpathObj);
477 return true;
478 }
479 }
480 crm_trace("ACLs deny user '%s' access to %s (%d %s)",
481 user, acl->xpath, max,
482 pcmk__plural_alt(max, "match", "matches"));
483 freeXpathObject(xpathObj);
484 }
485 }
486
487 if (!purge_xml_attributes(target)) {
488 crm_trace("ACLs deny user '%s' access to entire XML document", user);
489 return true;
490 }
491
492 if (docpriv->acls) {
493 g_list_free_full(docpriv->acls, free_acl);
494 docpriv->acls = NULL;
495
496 } else {
497 crm_trace("User '%s' without ACLs denied access to entire XML document",
498 user);
500 target = NULL;
501 }
502
503 if (target) {
504 *result = target;
505 }
506
507 return true;
508}
509
522static bool
523implicitly_allowed(const xmlNode *xml)
524{
525 GString *path = NULL;
526
527 for (xmlAttr *prop = xml->properties; prop != NULL; prop = prop->next) {
528 if (strcmp((const char *) prop->name, XML_ATTR_ID) != 0) {
529 return false;
530 }
531 }
532
534 CRM_ASSERT(path != NULL);
535
536 if (strstr((const char *) path->str, "/" XML_CIB_TAG_ACLS "/") != NULL) {
537 g_string_free(path, TRUE);
538 return false;
539 }
540
541 g_string_free(path, TRUE);
542 return true;
543}
544
545#define display_id(xml) (ID(xml)? ID(xml) : "<unset>")
546
562void
563pcmk__apply_creation_acl(xmlNode *xml, bool check_top)
564{
565 xml_node_private_t *nodepriv = xml->_private;
566
567 if (pcmk_is_set(nodepriv->flags, pcmk__xf_created)) {
568 if (implicitly_allowed(xml)) {
569 crm_trace("Creation of <%s> scaffolding with id=\"%s\""
570 " is implicitly allowed",
571 xml->name, display_id(xml));
572
573 } else if (pcmk__check_acl(xml, NULL, pcmk__xf_acl_write)) {
574 crm_trace("ACLs allow creation of <%s> with id=\"%s\"",
575 xml->name, display_id(xml));
576
577 } else if (check_top) {
578 crm_trace("ACLs disallow creation of <%s> with id=\"%s\"",
579 xml->name, display_id(xml));
581 return;
582
583 } else {
584 crm_notice("ACLs would disallow creation of %s<%s> with id=\"%s\"",
585 ((xml == xmlDocGetRootElement(xml->doc))? "root element " : ""),
586 xml->name, display_id(xml));
587 }
588 }
589
590 for (xmlNode *cIter = pcmk__xml_first_child(xml); cIter != NULL; ) {
591 xmlNode *child = cIter;
592 cIter = pcmk__xml_next(cIter); /* In case it is free'd */
593 pcmk__apply_creation_acl(child, true);
594 }
595}
596
604bool
605xml_acl_denied(const xmlNode *xml)
606{
607 if (xml && xml->doc && xml->doc->_private){
608 xml_doc_private_t *docpriv = xml->doc->_private;
609
610 return pcmk_is_set(docpriv->flags, pcmk__xf_acl_denied);
611 }
612 return false;
613}
614
615void
616xml_acl_disable(xmlNode *xml)
617{
618 if (xml_acl_enabled(xml)) {
619 xml_doc_private_t *docpriv = xml->doc->_private;
620
621 /* Catch anything that was created but shouldn't have been */
622 pcmk__apply_acl(xml);
623 pcmk__apply_creation_acl(xml, false);
625 }
626}
627
635bool
636xml_acl_enabled(const xmlNode *xml)
637{
638 if (xml && xml->doc && xml->doc->_private){
639 xml_doc_private_t *docpriv = xml->doc->_private;
640
641 return pcmk_is_set(docpriv->flags, pcmk__xf_acl_enabled);
642 }
643 return false;
644}
645
646bool
647pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
648{
649 CRM_ASSERT(xml);
650 CRM_ASSERT(xml->doc);
651 CRM_ASSERT(xml->doc->_private);
652
653 if (pcmk__tracking_xml_changes(xml, false) && xml_acl_enabled(xml)) {
654 xmlNode *parent = xml;
655 xml_doc_private_t *docpriv = xml->doc->_private;
656 GString *xpath = NULL;
657
658 if (docpriv->acls == NULL) {
660
661 pcmk__if_tracing({}, return false);
662 xpath = pcmk__element_xpath(xml);
663 if (name != NULL) {
664 pcmk__g_strcat(xpath, "[@", name, "]", NULL);
665 }
666
667 qb_log_from_external_source(__func__, __FILE__,
668 "User '%s' without ACLs denied %s "
669 "access to %s", LOG_TRACE, __LINE__, 0,
670 docpriv->user, acl_to_text(mode),
671 (const char *) xpath->str);
672 g_string_free(xpath, TRUE);
673 return false;
674 }
675
676 /* Walk the tree upwards looking for xml_acl_* flags
677 * - Creating an attribute requires write permissions for the node
678 * - Creating a child requires write permissions for the parent
679 */
680
681 if (name) {
682 xmlAttr *attr = xmlHasProp(xml, (pcmkXmlStr) name);
683
684 if (attr && mode == pcmk__xf_acl_create) {
685 mode = pcmk__xf_acl_write;
686 }
687 }
688
689 while (parent && parent->_private) {
690 xml_node_private_t *nodepriv = parent->_private;
691 if (test_acl_mode(nodepriv->flags, mode)) {
692 return true;
693
694 } else if (pcmk_is_set(nodepriv->flags, pcmk__xf_acl_deny)) {
696
697 pcmk__if_tracing({}, return false);
698 xpath = pcmk__element_xpath(xml);
699 if (name != NULL) {
700 pcmk__g_strcat(xpath, "[@", name, "]", NULL);
701 }
702
703 qb_log_from_external_source(__func__, __FILE__,
704 "%sACL denies user '%s' %s access "
705 "to %s", LOG_TRACE, __LINE__, 0,
706 (parent != xml)? "Parent ": "",
707 docpriv->user, acl_to_text(mode),
708 (const char *) xpath->str);
709 g_string_free(xpath, TRUE);
710 return false;
711 }
712 parent = parent->parent;
713 }
714
716
717 pcmk__if_tracing({}, return false);
718 xpath = pcmk__element_xpath(xml);
719 if (name != NULL) {
720 pcmk__g_strcat(xpath, "[@", name, "]", NULL);
721 }
722
723 qb_log_from_external_source(__func__, __FILE__,
724 "Default ACL denies user '%s' %s access to "
725 "%s", LOG_TRACE, __LINE__, 0,
726 docpriv->user, acl_to_text(mode),
727 (const char *) xpath->str);
728 g_string_free(xpath, TRUE);
729 return false;
730 }
731
732 return true;
733}
734
742bool
743pcmk_acl_required(const char *user)
744{
745 if (pcmk__str_empty(user)) {
746 crm_trace("ACLs not required because no user set");
747 return false;
748
749 } else if (!strcmp(user, CRM_DAEMON_USER) || !strcmp(user, "root")) {
750 crm_trace("ACLs not required for privileged user %s", user);
751 return false;
752 }
753 crm_trace("ACLs required for %s", user);
754 return true;
755}
756
757char *
759{
760 char *result = NULL;
761 struct passwd *pwent = getpwuid(uid);
762
763 if (pwent == NULL) {
764 crm_perror(LOG_INFO, "Cannot get user details for user ID %d", uid);
765 return NULL;
766 }
767 pcmk__str_update(&result, pwent->pw_name);
768 return result;
769}
770
789const char *
790pcmk__update_acl_user(xmlNode *request, const char *field,
791 const char *peer_user)
792{
793 static const char *effective_user = NULL;
794 const char *requested_user = NULL;
795 const char *user = NULL;
796
797 if (effective_user == NULL) {
798 effective_user = pcmk__uid2username(geteuid());
799 if (effective_user == NULL) {
800 effective_user = strdup("#unprivileged");
801 CRM_CHECK(effective_user != NULL, return NULL);
802 crm_err("Unable to determine effective user, assuming unprivileged for ACLs");
803 }
804 }
805
806 requested_user = crm_element_value(request, XML_ACL_TAG_USER);
807 if (requested_user == NULL) {
808 /* @COMPAT rolling upgrades <=1.1.11
809 *
810 * field is checked for backward compatibility with older versions that
811 * did not use XML_ACL_TAG_USER.
812 */
813 requested_user = crm_element_value(request, field);
814 }
815
816 if (!pcmk__is_privileged(effective_user)) {
817 /* We're not running as a privileged user, set or overwrite any existing
818 * value for $XML_ACL_TAG_USER
819 */
820 user = effective_user;
821
822 } else if (peer_user == NULL && requested_user == NULL) {
823 /* No user known or requested, use 'effective_user' and make sure one is
824 * set for the request
825 */
826 user = effective_user;
827
828 } else if (peer_user == NULL) {
829 /* No user known, trusting 'requested_user' */
830 user = requested_user;
831
832 } else if (!pcmk__is_privileged(peer_user)) {
833 /* The peer is not a privileged user, set or overwrite any existing
834 * value for $XML_ACL_TAG_USER
835 */
836 user = peer_user;
837
838 } else if (requested_user == NULL) {
839 /* Even if we're privileged, make sure there is always a value set */
840 user = peer_user;
841
842 } else {
843 /* Legal delegation to 'requested_user' */
844 user = requested_user;
845 }
846
847 // This requires pointer comparison, not string comparison
848 if (user != crm_element_value(request, XML_ACL_TAG_USER)) {
849 crm_xml_add(request, XML_ACL_TAG_USER, user);
850 }
851
852 if (field != NULL && user != crm_element_value(request, field)) {
853 crm_xml_add(request, field, user);
854 }
855
856 return requested_user;
857}
bool xml_acl_denied(const xmlNode *xml)
Check whether or not an XML node is ACL-denied.
Definition acl.c:605
#define display_id(xml)
Definition acl.c:545
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
Definition acl.c:647
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:743
char * pcmk__uid2username(uid_t uid)
Definition acl.c:758
struct xml_acl_s xml_acl_t
void xml_acl_disable(xmlNode *xml)
Definition acl.c:616
void pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user)
Definition acl.c:280
const char * pcmk__update_acl_user(xmlNode *request, const char *field, const char *peer_user)
Definition acl.c:790
void pcmk__enable_acl(xmlNode *acl_source, xmlNode *target, const char *user)
Definition acl.c:344
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:435
bool xml_acl_enabled(const xmlNode *xml)
Check whether or not an XML node is ACL-enabled.
Definition acl.c:636
void pcmk__apply_creation_acl(xmlNode *xml, bool check_top)
Definition acl.c:563
void pcmk__apply_acl(xmlNode *xml)
Definition acl.c:222
const char * parent
Definition cib.c:27
const char * path
Definition cib.c:28
const char * name
Definition cib.c:26
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:99
#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
#define crm_warn(fmt, args...)
Definition logging.h:380
#define crm_notice(fmt, args...)
Definition logging.h:381
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition logging.h:323
#define CRM_CHECK(expr, failure_action)
Definition logging.h:238
#define crm_debug(fmt, args...)
Definition logging.h:384
#define crm_err(fmt, args...)
Definition logging.h:379
#define LOG_NEVER
Definition logging.h:48
#define crm_trace(fmt, args...)
Definition logging.h:385
#define LOG_TRACE
Definition logging.h:38
#define pcmk__if_tracing(if_action, else_action)
#define XML_ACL_TAG_ROLE
Definition msg_xml.h:431
#define XML_ACL_TAG_PERMISSION
Definition msg_xml.h:432
#define XML_ACL_TAG_USERv1
Definition msg_xml.h:429
#define XML_ACL_ATTR_TAG
Definition msg_xml.h:441
#define ID(x)
Definition msg_xml.h:474
#define XML_ACL_ATTR_ATTRIBUTE
Definition msg_xml.h:444
#define XML_ACL_TAG_USER
Definition msg_xml.h:428
#define XML_ACL_TAG_WRITE
Definition msg_xml.h:437
#define XML_ACL_TAG_ROLE_REF
Definition msg_xml.h:433
#define XML_CIB_TAG_ACLS
Definition msg_xml.h:211
#define XML_ACL_TAG_DENY
Definition msg_xml.h:438
#define XML_ACL_TAG_READ
Definition msg_xml.h:436
#define XML_ATTR_ID
Definition msg_xml.h:156
#define XML_ACL_ATTR_XPATH
Definition msg_xml.h:443
#define XML_ACL_TAG_GROUP
Definition msg_xml.h:430
#define XML_ACL_ATTR_KIND
Definition msg_xml.h:435
#define XML_ACL_ATTR_TAGv1
Definition msg_xml.h:442
#define XML_ACL_TAG_ROLE_REFv1
Definition msg_xml.h:434
#define XML_ACL_ATTR_REF
Definition msg_xml.h:439
#define XML_ACL_ATTR_REFv1
Definition msg_xml.h:440
#define XML_ATTR_NAME
Definition msg_xml.h:157
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:447
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:302
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:1193
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
Definition strings.c:1217
Wrappers for and extensions to libxml2.
const xmlChar * pcmkXmlStr
Definition xml.h:50
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition xpath.c:211
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:783
void pcmk_free_xml_subtree(xmlNode *xml)
Definition xml.c:706
xmlXPathObjectPtr xpath_search(const xmlNode *xml_top, const char *path)
Definition xpath.c:139
xmlNode * copy_xml(xmlNode *src_node)
Definition xml.c:789
void pcmk__set_xml_doc_flag(xmlNode *xml, enum xml_private_flags flag)
Definition xml.c:78
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:278