pacemaker 2.1.1-77db578727
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
acl.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2021 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
27#define MAX_XPATH_LEN 4096
28
29typedef struct xml_acl_s {
30 enum xml_private_flags mode;
31 char *xpath;
33
34static void
35free_acl(void *data)
36{
37 if (data) {
38 xml_acl_t *acl = data;
39
40 free(acl->xpath);
41 free(acl);
42 }
43}
44
45void
46pcmk__free_acls(GList *acls)
47{
48 g_list_free_full(acls, free_acl);
49}
50
51static GList *
52create_acl(xmlNode *xml, GList *acls, enum xml_private_flags mode)
53{
54 xml_acl_t *acl = NULL;
55
56 const char *tag = crm_element_value(xml, XML_ACL_ATTR_TAG);
57 const char *ref = crm_element_value(xml, XML_ACL_ATTR_REF);
58 const char *xpath = crm_element_value(xml, XML_ACL_ATTR_XPATH);
59 const char *attr = crm_element_value(xml, XML_ACL_ATTR_ATTRIBUTE);
60
61 if (tag == NULL) {
62 // @COMPAT rolling upgrades <=1.1.11
64 }
65 if (ref == NULL) {
66 // @COMPAT rolling upgrades <=1.1.11
68 }
69
70 if ((tag == NULL) && (ref == NULL) && (xpath == NULL)) {
71 // Schema should prevent this, but to be safe ...
72 crm_trace("Ignoring ACL <%s> element without selection criteria",
73 crm_element_name(xml));
74 return NULL;
75 }
76
77 acl = calloc(1, sizeof (xml_acl_t));
78 CRM_ASSERT(acl != NULL);
79
80 acl->mode = mode;
81 if (xpath) {
82 acl->xpath = strdup(xpath);
83 CRM_ASSERT(acl->xpath != NULL);
84 crm_trace("Unpacked ACL <%s> element using xpath: %s",
85 crm_element_name(xml), acl->xpath);
86
87 } else {
88 int offset = 0;
89 char buffer[MAX_XPATH_LEN];
90
91 if (tag) {
92 offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
93 "//%s", tag);
94 } else {
95 offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
96 "//*");
97 }
98
99 if (ref || attr) {
100 offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
101 "[");
102 }
103
104 if (ref) {
105 offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
106 "@id='%s'", ref);
107 }
108
109 // NOTE: schema currently does not allow this
110 if (ref && attr) {
111 offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
112 " and ");
113 }
114
115 if (attr) {
116 offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
117 "@%s", attr);
118 }
119
120 if (ref || attr) {
121 offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
122 "]");
123 }
124
125 CRM_LOG_ASSERT(offset > 0);
126 acl->xpath = strdup(buffer);
127 CRM_ASSERT(acl->xpath != NULL);
128
129 crm_trace("Unpacked ACL <%s> element as xpath: %s",
130 crm_element_name(xml), acl->xpath);
131 }
132
133 return g_list_append(acls, acl);
134}
135
146static GList *
147parse_acl_entry(xmlNode *acl_top, xmlNode *acl_entry, GList *acls)
148{
149 xmlNode *child = NULL;
150
151 for (child = pcmk__xe_first_child(acl_entry); child;
152 child = pcmk__xe_next(child)) {
153 const char *tag = crm_element_name(child);
154 const char *kind = crm_element_value(child, XML_ACL_ATTR_KIND);
155
156 if (strcmp(XML_ACL_TAG_PERMISSION, tag) == 0){
157 CRM_ASSERT(kind != NULL);
158 crm_trace("Unpacking ACL <%s> element of kind '%s'", tag, kind);
159 tag = kind;
160 } else {
161 crm_trace("Unpacking ACL <%s> element", tag);
162 }
163
164 if (strcmp(XML_ACL_TAG_ROLE_REF, tag) == 0
165 || strcmp(XML_ACL_TAG_ROLE_REFv1, tag) == 0) {
166 const char *ref_role = crm_element_value(child, XML_ATTR_ID);
167
168 if (ref_role) {
169 xmlNode *role = NULL;
170
171 for (role = pcmk__xe_first_child(acl_top); role;
172 role = pcmk__xe_next(role)) {
173 if (!strcmp(XML_ACL_TAG_ROLE, (const char *) role->name)) {
174 const char *role_id = crm_element_value(role,
176
177 if (role_id && strcmp(ref_role, role_id) == 0) {
178 crm_trace("Unpacking referenced role '%s' in ACL <%s> element",
179 role_id, crm_element_name(acl_entry));
180 acls = parse_acl_entry(acl_top, role, acls);
181 break;
182 }
183 }
184 }
185 }
186
187 } else if (strcmp(XML_ACL_TAG_READ, tag) == 0) {
188 acls = create_acl(child, acls, xpf_acl_read);
189
190 } else if (strcmp(XML_ACL_TAG_WRITE, tag) == 0) {
191 acls = create_acl(child, acls, xpf_acl_write);
192
193 } else if (strcmp(XML_ACL_TAG_DENY, tag) == 0) {
194 acls = create_acl(child, acls, xpf_acl_deny);
195
196 } else {
197 crm_warn("Ignoring unknown ACL %s '%s'",
198 (kind? "kind" : "element"), tag);
199 }
200 }
201
202 return acls;
203}
204
205/*
206 <acls>
207 <acl_target id="l33t-haxor"><role id="auto-l33t-haxor"/></acl_target>
208 <acl_role id="auto-l33t-haxor">
209 <acl_permission id="crook-nothing" kind="deny" xpath="/cib"/>
210 </acl_role>
211 <acl_target id="niceguy">
212 <role id="observer"/>
213 </acl_target>
214 <acl_role id="observer">
215 <acl_permission id="observer-read-1" kind="read" xpath="/cib"/>
216 <acl_permission id="observer-write-1" kind="write" xpath="//nvpair[@name='stonith-enabled']"/>
217 <acl_permission id="observer-write-2" kind="write" xpath="//nvpair[@name='target-role']"/>
218 </acl_role>
219 <acl_target id="badidea"><role id="auto-badidea"/></acl_target>
220 <acl_role id="auto-badidea">
221 <acl_permission id="badidea-resources" kind="read" xpath="//meta_attributes"/>
222 <acl_permission id="badidea-resources-2" kind="deny" reference="dummy-meta_attributes"/>
223 </acl_role>
224 </acls>
225*/
226
227static const char *
228acl_to_text(enum xml_private_flags flags)
229{
231 return "deny";
232
233 } else if (pcmk_any_flags_set(flags, xpf_acl_write|xpf_acl_create)) {
234 return "read/write";
235
236 } else if (pcmk_is_set(flags, xpf_acl_read)) {
237 return "read";
238 }
239 return "none";
240}
241
242void
243pcmk__apply_acl(xmlNode *xml)
244{
245 GList *aIter = NULL;
246 xml_private_t *p = xml->doc->_private;
247 xmlXPathObjectPtr xpathObj = NULL;
248
249 if (!xml_acl_enabled(xml)) {
250 crm_trace("Skipping ACLs for user '%s' because not enabled for this XML",
251 p->user);
252 return;
253 }
254
255 for (aIter = p->acls; aIter != NULL; aIter = aIter->next) {
256 int max = 0, lpc = 0;
257 xml_acl_t *acl = aIter->data;
258
259 xpathObj = xpath_search(xml, acl->xpath);
260 max = numXpathResults(xpathObj);
261
262 for (lpc = 0; lpc < max; lpc++) {
263 xmlNode *match = getXpathResult(xpathObj, lpc);
264 char *path = xml_get_path(match);
265
266 p = match->_private;
267 crm_trace("Applying %s ACL to %s matched by %s",
268 acl_to_text(acl->mode), path, acl->xpath);
269 pcmk__set_xml_flags(p, acl->mode);
270 free(path);
271 }
272 crm_trace("Applied %s ACL %s (%d match%s)",
273 acl_to_text(acl->mode), acl->xpath, max,
274 ((max == 1)? "" : "es"));
275 freeXpathObject(xpathObj);
276 }
277}
278
287void
288pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user)
289{
290 xml_private_t *p = NULL;
291
292 if ((target == NULL) || (target->doc == NULL)
293 || (target->doc->_private == NULL)) {
294 return;
295 }
296
297 p = 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 (p->acls == NULL) {
303 xmlNode *acls = get_xpath_object("//" XML_CIB_TAG_ACLS,
304 source, LOG_NEVER);
305
306 free(p->user);
307 p->user = strdup(user);
308
309 if (acls) {
310 xmlNode *child = NULL;
311
312 for (child = pcmk__xe_first_child(acls); child;
313 child = pcmk__xe_next(child)) {
314 const char *tag = crm_element_name(child);
315
316 if (!strcmp(tag, XML_ACL_TAG_USER)
317 || !strcmp(tag, XML_ACL_TAG_USERv1)) {
318 const char *id = crm_element_value(child, XML_ATTR_ID);
319
320 if (id && strcmp(id, user) == 0) {
321 crm_debug("Unpacking ACLs for user '%s'", id);
322 p->acls = parse_acl_entry(acls, child, p->acls);
323 }
324 }
325 }
326 }
327 }
328}
329
330static inline bool
331test_acl_mode(enum xml_private_flags allowed, enum xml_private_flags requested)
332{
333 if (pcmk_is_set(allowed, xpf_acl_deny)) {
334 return false;
335
336 } else if (pcmk_all_flags_set(allowed, requested)) {
337 return true;
338
339 } else if (pcmk_is_set(requested, xpf_acl_read)
340 && pcmk_is_set(allowed, xpf_acl_write)) {
341 return true;
342
343 } else if (pcmk_is_set(requested, xpf_acl_create)
344 && pcmk_any_flags_set(allowed, xpf_acl_write|xpf_created)) {
345 return true;
346 }
347 return false;
348}
349
350static bool
351purge_xml_attributes(xmlNode *xml)
352{
353 xmlNode *child = NULL;
354 xmlAttr *xIter = NULL;
355 bool readable_children = false;
356 xml_private_t *p = xml->_private;
357
358 if (test_acl_mode(p->flags, xpf_acl_read)) {
359 crm_trace("%s[@id=%s] is readable", crm_element_name(xml), ID(xml));
360 return true;
361 }
362
363 xIter = xml->properties;
364 while (xIter != NULL) {
365 xmlAttr *tmp = xIter;
366 const char *prop_name = (const char *)xIter->name;
367
368 xIter = xIter->next;
369 if (strcmp(prop_name, XML_ATTR_ID) == 0) {
370 continue;
371 }
372
373 xmlUnsetProp(xml, tmp->name);
374 }
375
376 child = pcmk__xml_first_child(xml);
377 while ( child != NULL ) {
378 xmlNode *tmp = child;
379
380 child = pcmk__xml_next(child);
381 readable_children |= purge_xml_attributes(tmp);
382 }
383
384 if (!readable_children) {
385 free_xml(xml); /* Nothing readable under here, purge completely */
386 }
387 return readable_children;
388}
389
402bool
403xml_acl_filtered_copy(const char *user, xmlNode *acl_source, xmlNode *xml,
404 xmlNode **result)
405{
406 GList *aIter = NULL;
407 xmlNode *target = NULL;
408 xml_private_t *doc = NULL;
409
410 *result = NULL;
411 if ((xml == NULL) || !pcmk_acl_required(user)) {
412 crm_trace("Not filtering XML because ACLs not required for user '%s'",
413 user);
414 return false;
415 }
416
417 crm_trace("Filtering XML copy using user '%s' ACLs", user);
418 target = copy_xml(xml);
419 if (target == NULL) {
420 return true;
421 }
422
423 pcmk__unpack_acl(acl_source, target, user);
426
427 doc = target->doc->_private;
428 for(aIter = doc->acls; aIter != NULL && target; aIter = aIter->next) {
429 int max = 0;
430 xml_acl_t *acl = aIter->data;
431
432 if (acl->mode != xpf_acl_deny) {
433 /* Nothing to do */
434
435 } else if (acl->xpath) {
436 int lpc = 0;
437 xmlXPathObjectPtr xpathObj = xpath_search(target, acl->xpath);
438
439 max = numXpathResults(xpathObj);
440 for(lpc = 0; lpc < max; lpc++) {
441 xmlNode *match = getXpathResult(xpathObj, lpc);
442
443 if (!purge_xml_attributes(match) && (match == target)) {
444 crm_trace("ACLs deny user '%s' access to entire XML document",
445 user);
446 freeXpathObject(xpathObj);
447 return true;
448 }
449 }
450 crm_trace("ACLs deny user '%s' access to %s (%d %s)",
451 user, acl->xpath, max,
452 pcmk__plural_alt(max, "match", "matches"));
453 freeXpathObject(xpathObj);
454 }
455 }
456
457 if (!purge_xml_attributes(target)) {
458 crm_trace("ACLs deny user '%s' access to entire XML document", user);
459 return true;
460 }
461
462 if (doc->acls) {
463 g_list_free_full(doc->acls, free_acl);
464 doc->acls = NULL;
465
466 } else {
467 crm_trace("User '%s' without ACLs denied access to entire XML document",
468 user);
470 target = NULL;
471 }
472
473 if (target) {
474 *result = target;
475 }
476
477 return true;
478}
479
492static bool
493implicitly_allowed(xmlNode *xml)
494{
495 char *path = NULL;
496
497 for (xmlAttr *prop = xml->properties; prop != NULL; prop = prop->next) {
498 if (strcmp((const char *) prop->name, XML_ATTR_ID) != 0) {
499 return false;
500 }
501 }
502
503 path = xml_get_path(xml);
504 if (strstr(path, "/" XML_CIB_TAG_ACLS "/") != NULL) {
505 free(path);
506 return false;
507 }
508 free(path);
509
510 return true;
511}
512
513#define display_id(xml) (ID(xml)? ID(xml) : "<unset>")
514
528void
529pcmk__apply_creation_acl(xmlNode *xml, bool check_top)
530{
531 xml_private_t *p = xml->_private;
532
533 if (pcmk_is_set(p->flags, xpf_created)) {
534 if (implicitly_allowed(xml)) {
535 crm_trace("Creation of <%s> scaffolding with id=\"%s\""
536 " is implicitly allowed",
537 crm_element_name(xml), display_id(xml));
538
539 } else if (pcmk__check_acl(xml, NULL, xpf_acl_write)) {
540 crm_trace("ACLs allow creation of <%s> with id=\"%s\"",
541 crm_element_name(xml), display_id(xml));
542
543 } else if (check_top) {
544 crm_trace("ACLs disallow creation of <%s> with id=\"%s\"",
545 crm_element_name(xml), display_id(xml));
547 return;
548
549 } else {
550 crm_notice("ACLs would disallow creation of %s<%s> with id=\"%s\" ",
551 ((xml == xmlDocGetRootElement(xml->doc))? "root element " : ""),
552 crm_element_name(xml), display_id(xml));
553 }
554 }
555
556 for (xmlNode *cIter = pcmk__xml_first_child(xml); cIter != NULL; ) {
557 xmlNode *child = cIter;
558 cIter = pcmk__xml_next(cIter); /* In case it is free'd */
559 pcmk__apply_creation_acl(child, true);
560 }
561}
562
563bool
564xml_acl_denied(xmlNode *xml)
565{
566 if (xml && xml->doc && xml->doc->_private){
567 xml_private_t *p = xml->doc->_private;
568
569 return pcmk_is_set(p->flags, xpf_acl_denied);
570 }
571 return false;
572}
573
574void
575xml_acl_disable(xmlNode *xml)
576{
577 if (xml_acl_enabled(xml)) {
578 xml_private_t *p = xml->doc->_private;
579
580 /* Catch anything that was created but shouldn't have been */
581 pcmk__apply_acl(xml);
582 pcmk__apply_creation_acl(xml, false);
584 }
585}
586
587bool
588xml_acl_enabled(xmlNode *xml)
589{
590 if (xml && xml->doc && xml->doc->_private){
591 xml_private_t *p = xml->doc->_private;
592
594 }
595 return false;
596}
597
598bool
599pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
600{
601 CRM_ASSERT(xml);
602 CRM_ASSERT(xml->doc);
603 CRM_ASSERT(xml->doc->_private);
604
605 if (pcmk__tracking_xml_changes(xml, false) && xml_acl_enabled(xml)) {
606 int offset = 0;
607 xmlNode *parent = xml;
608 char buffer[MAX_XPATH_LEN];
609 xml_private_t *docp = xml->doc->_private;
610
611 offset = pcmk__element_xpath(NULL, xml, buffer, offset,
612 sizeof(buffer));
613 if (name) {
614 offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
615 "[@%s]", name);
616 }
617 CRM_LOG_ASSERT(offset > 0);
618
619 if (docp->acls == NULL) {
620 crm_trace("User '%s' without ACLs denied %s access to %s",
621 docp->user, acl_to_text(mode), buffer);
623 return false;
624 }
625
626 /* Walk the tree upwards looking for xml_acl_* flags
627 * - Creating an attribute requires write permissions for the node
628 * - Creating a child requires write permissions for the parent
629 */
630
631 if (name) {
632 xmlAttr *attr = xmlHasProp(xml, (pcmkXmlStr) name);
633
634 if (attr && mode == xpf_acl_create) {
635 mode = xpf_acl_write;
636 }
637 }
638
639 while (parent && parent->_private) {
640 xml_private_t *p = parent->_private;
641 if (test_acl_mode(p->flags, mode)) {
642 return true;
643
644 } else if (pcmk_is_set(p->flags, xpf_acl_deny)) {
645 crm_trace("%sACL denies user '%s' %s access to %s",
646 (parent != xml) ? "Parent " : "", docp->user,
647 acl_to_text(mode), buffer);
649 return false;
650 }
651 parent = parent->parent;
652 }
653
654 crm_trace("Default ACL denies user '%s' %s access to %s",
655 docp->user, acl_to_text(mode), buffer);
657 return false;
658 }
659
660 return true;
661}
662
670bool
671pcmk_acl_required(const char *user)
672{
673 if (pcmk__str_empty(user)) {
674 crm_trace("ACLs not required because no user set");
675 return false;
676
677 } else if (!strcmp(user, CRM_DAEMON_USER) || !strcmp(user, "root")) {
678 crm_trace("ACLs not required for privileged user %s", user);
679 return false;
680 }
681 crm_trace("ACLs required for %s", user);
682 return true;
683}
684
685char *
687{
688 struct passwd *pwent = getpwuid(uid);
689
690 if (pwent == NULL) {
691 crm_perror(LOG_INFO, "Cannot get user details for user ID %d", uid);
692 return NULL;
693 }
694 return strdup(pwent->pw_name);
695}
696
715const char *
716pcmk__update_acl_user(xmlNode *request, const char *field,
717 const char *peer_user)
718{
719 static const char *effective_user = NULL;
720 const char *requested_user = NULL;
721 const char *user = NULL;
722
723 if (effective_user == NULL) {
724 effective_user = pcmk__uid2username(geteuid());
725 if (effective_user == NULL) {
726 effective_user = strdup("#unprivileged");
727 CRM_CHECK(effective_user != NULL, return NULL);
728 crm_err("Unable to determine effective user, assuming unprivileged for ACLs");
729 }
730 }
731
732 requested_user = crm_element_value(request, XML_ACL_TAG_USER);
733 if (requested_user == NULL) {
734 /* @COMPAT rolling upgrades <=1.1.11
735 *
736 * field is checked for backward compatibility with older versions that
737 * did not use XML_ACL_TAG_USER.
738 */
739 requested_user = crm_element_value(request, field);
740 }
741
742 if (!pcmk__is_privileged(effective_user)) {
743 /* We're not running as a privileged user, set or overwrite any existing
744 * value for $XML_ACL_TAG_USER
745 */
746 user = effective_user;
747
748 } else if (peer_user == NULL && requested_user == NULL) {
749 /* No user known or requested, use 'effective_user' and make sure one is
750 * set for the request
751 */
752 user = effective_user;
753
754 } else if (peer_user == NULL) {
755 /* No user known, trusting 'requested_user' */
756 user = requested_user;
757
758 } else if (!pcmk__is_privileged(peer_user)) {
759 /* The peer is not a privileged user, set or overwrite any existing
760 * value for $XML_ACL_TAG_USER
761 */
762 user = peer_user;
763
764 } else if (requested_user == NULL) {
765 /* Even if we're privileged, make sure there is always a value set */
766 user = peer_user;
767
768 } else {
769 /* Legal delegation to 'requested_user' */
770 user = requested_user;
771 }
772
773 // This requires pointer comparison, not string comparison
774 if (user != crm_element_value(request, XML_ACL_TAG_USER)) {
775 crm_xml_add(request, XML_ACL_TAG_USER, user);
776 }
777
778 if (field != NULL && user != crm_element_value(request, field)) {
779 crm_xml_add(request, field, user);
780 }
781
782 return requested_user;
783}
#define display_id(xml)
Definition acl.c:513
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
Definition acl.c:599
void pcmk__free_acls(GList *acls)
Definition acl.c:46
bool pcmk_acl_required(const char *user)
Check whether ACLs are required for a given user.
Definition acl.c:671
#define MAX_XPATH_LEN
Definition acl.c:27
char * pcmk__uid2username(uid_t uid)
Definition acl.c:686
bool xml_acl_denied(xmlNode *xml)
Definition acl.c:564
struct xml_acl_s xml_acl_t
void xml_acl_disable(xmlNode *xml)
Definition acl.c:575
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:716
bool xml_acl_filtered_copy(const char *user, xmlNode *acl_source, xmlNode *xml, xmlNode **result)
Definition acl.c:403
void pcmk__apply_creation_acl(xmlNode *xml, bool check_top)
Definition acl.c:529
bool xml_acl_enabled(xmlNode *xml)
Definition acl.c:588
void pcmk__apply_acl(xmlNode *xml)
Definition acl.c:243
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:114
#define CRM_DAEMON_USER
Definition config.h:32
char data[0]
Definition cpg.c:10
A dumping ground.
G_GNUC_INTERNAL int pcmk__element_xpath(const char *prefix, xmlNode *xml, char *buffer, int offset, size_t buffer_size)
Definition xpath.c:269
#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:52
#define pcmk__clear_xml_flags(xml_priv, flags_to_clear)
xml_private_flags
@ xpf_acl_denied
@ xpf_created
@ xpf_acl_read
@ xpf_acl_enabled
@ xpf_acl_deny
@ xpf_acl_write
@ xpf_acl_create
G_GNUC_INTERNAL void pcmk__set_xml_doc_flag(xmlNode *xml, enum xml_private_flags flag)
Definition xml.c:118
#define crm_warn(fmt, args...)
Definition logging.h:351
#define CRM_LOG_ASSERT(expr)
Definition logging.h:202
#define crm_notice(fmt, args...)
Definition logging.h:352
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition logging.h:301
#define CRM_CHECK(expr, failure_action)
Definition logging.h:218
#define crm_debug(fmt, args...)
Definition logging.h:355
#define crm_err(fmt, args...)
Definition logging.h:350
#define LOG_NEVER
Definition logging.h:46
#define crm_trace(fmt, args...)
Definition logging.h:356
#define XML_ACL_TAG_ROLE
Definition msg_xml.h:411
#define XML_ACL_TAG_PERMISSION
Definition msg_xml.h:412
#define XML_ACL_TAG_USERv1
Definition msg_xml.h:409
#define XML_ACL_ATTR_TAG
Definition msg_xml.h:421
#define ID(x)
Definition msg_xml.h:456
#define XML_ACL_ATTR_ATTRIBUTE
Definition msg_xml.h:424
#define XML_ACL_TAG_USER
Definition msg_xml.h:408
#define XML_ACL_TAG_WRITE
Definition msg_xml.h:417
#define XML_ACL_TAG_ROLE_REF
Definition msg_xml.h:413
#define XML_CIB_TAG_ACLS
Definition msg_xml.h:187
#define XML_ACL_TAG_DENY
Definition msg_xml.h:418
#define XML_ACL_TAG_READ
Definition msg_xml.h:416
#define XML_ATTR_ID
Definition msg_xml.h:129
#define XML_ACL_ATTR_XPATH
Definition msg_xml.h:423
#define XML_ACL_ATTR_KIND
Definition msg_xml.h:415
#define XML_ACL_ATTR_TAGv1
Definition msg_xml.h:422
#define XML_ACL_TAG_ROLE_REFv1
Definition msg_xml.h:414
#define XML_ACL_ATTR_REF
Definition msg_xml.h:419
#define XML_ACL_ATTR_REFv1
Definition msg_xml.h:420
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:530
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:324
char * name
Definition pcmk_fence.c:31
const char * target
Definition pcmk_fence.c:29
#define CRM_ASSERT(expr)
Definition results.h:42
#define pcmk__plural_alt(i, s1, s2)
Wrappers for and extensions to libxml2.
xmlXPathObjectPtr xpath_search(xmlNode *xml_top, const char *path)
Definition xpath.c:139
char * xml_get_path(xmlNode *xml)
Definition xpath.c:291
const xmlChar * pcmkXmlStr
Definition xml.h:51
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:823
void pcmk_free_xml_subtree(xmlNode *xml)
Definition xml.c:755
xmlNode * copy_xml(xmlNode *src_node)
Definition xml.c:829