pacemaker  1.1.24-3850484742
Scalable High-Availability cluster resource manager
acl.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2019 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>
24 #include "crmcommon_private.h"
25 
26 #define MAX_XPATH_LEN 4096
27 
28 typedef struct xml_acl_s {
29  enum xml_private_flags mode;
30  char *xpath;
31 } xml_acl_t;
32 
33 static void
34 __xml_acl_free(void *data)
35 {
36  if (data) {
37  xml_acl_t *acl = data;
38 
39  free(acl->xpath);
40  free(acl);
41  }
42 }
43 
44 void
45 pcmk__free_acls(GList *acls)
46 {
47  g_list_free_full(acls, __xml_acl_free);
48 }
49 
50 static GList *
51 __xml_acl_create(xmlNode *xml, GList *acls, enum xml_private_flags mode)
52 {
53  xml_acl_t *acl = NULL;
54 
55  const char *tag = crm_element_value(xml, XML_ACL_ATTR_TAG);
56  const char *ref = crm_element_value(xml, XML_ACL_ATTR_REF);
57  const char *xpath = crm_element_value(xml, XML_ACL_ATTR_XPATH);
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  crm_trace("No criteria %p", xml);
70  return NULL;
71  }
72 
73  acl = calloc(1, sizeof (xml_acl_t));
74  if (acl) {
75  const char *attr = crm_element_value(xml, XML_ACL_ATTR_ATTRIBUTE);
76 
77  acl->mode = mode;
78  if (xpath) {
79  acl->xpath = strdup(xpath);
80  crm_trace("Using xpath: %s", acl->xpath);
81 
82  } else {
83  int offset = 0;
84  char buffer[MAX_XPATH_LEN];
85 
86  if (tag) {
87  offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
88  "//%s", tag);
89  } else {
90  offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
91  "//*");
92  }
93 
94  if (ref || attr) {
95  offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
96  "[");
97  }
98 
99  if (ref) {
100  offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
101  "@id='%s'", ref);
102  }
103 
104  if (ref && attr) {
105  offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
106  " and ");
107  }
108 
109  if (attr) {
110  offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
111  "@%s", attr);
112  }
113 
114  if (ref || attr) {
115  offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
116  "]");
117  }
118 
119  CRM_LOG_ASSERT(offset > 0);
120  acl->xpath = strdup(buffer);
121  crm_trace("Built xpath: %s", acl->xpath);
122  }
123 
124  acls = g_list_append(acls, acl);
125  }
126  return acls;
127 }
128 
129 static GList *
130 __xml_acl_parse_entry(xmlNode *acl_top, xmlNode *acl_entry, GList *acls)
131 {
132  xmlNode *child = NULL;
133 
134  for (child = __xml_first_child_element(acl_entry); child;
135  child = __xml_next_element(child)) {
136  const char *tag = crm_element_name(child);
137  const char *kind = crm_element_value(child, XML_ACL_ATTR_KIND);
138 
139  if (strcmp(XML_ACL_TAG_PERMISSION, tag) == 0){
140  tag = kind;
141  }
142 
143  crm_trace("Processing %s %p", tag, child);
144  if (tag == NULL) {
145  CRM_ASSERT(tag != NULL);
146 
147  } else if (strcmp(XML_ACL_TAG_ROLE_REF, tag) == 0
148  || strcmp(XML_ACL_TAG_ROLE_REFv1, tag) == 0) {
149  const char *ref_role = crm_element_value(child, XML_ATTR_ID);
150 
151  if (ref_role) {
152  xmlNode *role = NULL;
153 
154  for (role = __xml_first_child_element(acl_top); role;
155  role = __xml_next_element(role)) {
156  if (!strcmp(XML_ACL_TAG_ROLE, (const char *) role->name)) {
157  const char *role_id = crm_element_value(role,
158  XML_ATTR_ID);
159 
160  if (role_id && strcmp(ref_role, role_id) == 0) {
161  crm_debug("Unpacking referenced role: %s", role_id);
162  acls = __xml_acl_parse_entry(acl_top, role, acls);
163  break;
164  }
165  }
166  }
167  }
168 
169  } else if (strcmp(XML_ACL_TAG_READ, tag) == 0) {
170  acls = __xml_acl_create(child, acls, xpf_acl_read);
171 
172  } else if (strcmp(XML_ACL_TAG_WRITE, tag) == 0) {
173  acls = __xml_acl_create(child, acls, xpf_acl_write);
174 
175  } else if (strcmp(XML_ACL_TAG_DENY, tag) == 0) {
176  acls = __xml_acl_create(child, acls, xpf_acl_deny);
177 
178  } else {
179  crm_warn("Unknown ACL entry: %s/%s", tag, kind);
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 
208 #ifdef SUSE_ACL_COMPAT
209 static const char *
210 __xml_acl_to_text(enum xml_private_flags flags)
211 {
212  if (is_set(flags, xpf_acl_deny)) {
213  return "deny";
214 
215  } else if (is_set(flags, xpf_acl_write)) {
216  return "read/write";
217 
218  } else if (is_set(flags, xpf_acl_read)) {
219  return "read";
220  }
221  return "none";
222 }
223 #endif
224 
225 void
226 pcmk__apply_acl(xmlNode *xml)
227 {
228  GListPtr aIter = NULL;
229  xml_private_t *p = xml->doc->_private;
230  xmlXPathObjectPtr xpathObj = NULL;
231 
232  if (xml_acl_enabled(xml) == FALSE) {
233  crm_trace("Not applying ACLs for %s", p->user);
234  return;
235  }
236 
237  for (aIter = p->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  xmlNode *match = getXpathResult(xpathObj, lpc);
246  char *path = xml_get_path(match);
247 
248  p = match->_private;
249  crm_trace("Applying %x to %s for %s", acl->mode, path, acl->xpath);
250 
251 #ifdef SUSE_ACL_COMPAT
252  if (is_not_set(p->flags, acl->mode)
253  && (is_set(p->flags, xpf_acl_read)
254  || is_set(p->flags, xpf_acl_write)
255  || is_set(p->flags, xpf_acl_deny))) {
256  crm_config_warn("Configuration element %s is matched by "
257  "multiple ACL rules, only the first applies "
258  "('%s' wins over '%s')",
259  path, __xml_acl_to_text(p->flags),
260  __xml_acl_to_text(acl->mode));
261  free(path);
262  continue;
263  }
264 #endif
265  p->flags |= acl->mode;
266  free(path);
267  }
268  crm_trace("Now enforcing ACL: %s (%d matches)", acl->xpath, max);
269  freeXpathObject(xpathObj);
270  }
271 
272  p = xml->_private;
273  if (is_not_set(p->flags, xpf_acl_read)
274  && is_not_set(p->flags, xpf_acl_write)) {
275 
276  p->flags |= xpf_acl_deny;
277  p = xml->doc->_private;
278  crm_info("Enforcing default ACL for %s to %s",
279  p->user, crm_element_name(xml));
280  }
281 
282 }
283 
284 void
285 pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user)
286 {
287 #if ENABLE_ACL
288  xml_private_t *p = NULL;
289 
290  if ((target == NULL) || (target->doc == NULL)
291  || (target->doc->_private == NULL)) {
292  return;
293  }
294 
295  p = target->doc->_private;
296  if (pcmk_acl_required(user) == FALSE) {
297  crm_trace("no acls needed for '%s'", user);
298 
299  } else if (p->acls == NULL) {
300  xmlNode *acls = get_xpath_object("//" XML_CIB_TAG_ACLS,
301  source, LOG_TRACE);
302 
303  free(p->user);
304  p->user = strdup(user);
305 
306  if (acls) {
307  xmlNode *child = NULL;
308 
309  for (child = __xml_first_child_element(acls); child;
310  child = __xml_next_element(child)) {
311  const char *tag = crm_element_name(child);
312 
313  if (!strcmp(tag, XML_ACL_TAG_USER)
314  || !strcmp(tag, XML_ACL_TAG_USERv1)) {
315  const char *id = crm_element_value(child, XML_ATTR_ID);
316 
317  if (id && strcmp(id, user) == 0) {
318  crm_debug("Unpacking ACLs for %s", id);
319  p->acls = __xml_acl_parse_entry(acls, child, p->acls);
320  }
321  }
322  }
323  }
324  }
325 #endif
326 }
327 
328 static inline bool
329 __xml_acl_mode_test(enum xml_private_flags allowed,
330  enum xml_private_flags requested)
331 {
332  if (is_set(allowed, xpf_acl_deny)) {
333  return FALSE;
334 
335  } else if (is_set(allowed, requested)) {
336  return TRUE;
337 
338  } else if (is_set(requested, xpf_acl_read)
339  && is_set(allowed, xpf_acl_write)) {
340  return TRUE;
341 
342  } else if (is_set(requested, xpf_acl_create)
343  && is_set(allowed, xpf_acl_write)) {
344  return TRUE;
345 
346  } else if (is_set(requested, xpf_acl_create)
347  && is_set(allowed, xpf_created)) {
348  return TRUE;
349  }
350  return FALSE;
351 }
352 
353 /* rc = TRUE if orig_cib has been filtered
354  * That means '*result' rather than 'xml' should be exploited afterwards
355  */
356 static bool
357 __xml_purge_attributes(xmlNode *xml)
358 {
359  xmlNode *child = NULL;
360  xmlAttr *xIter = NULL;
361  bool readable_children = FALSE;
362  xml_private_t *p = xml->_private;
363 
364  if (__xml_acl_mode_test(p->flags, xpf_acl_read)) {
365  crm_trace("%s[@id=%s] is readable", crm_element_name(xml), ID(xml));
366  return TRUE;
367  }
368 
369  xIter = xml->properties;
370  while (xIter != NULL) {
371  xmlAttr *tmp = xIter;
372  const char *prop_name = (const char *)xIter->name;
373 
374  xIter = xIter->next;
375  if (strcmp(prop_name, XML_ATTR_ID) == 0) {
376  continue;
377  }
378 
379  xmlUnsetProp(xml, tmp->name);
380  }
381 
382  child = __xml_first_child(xml);
383  while ( child != NULL ) {
384  xmlNode *tmp = child;
385 
386  child = __xml_next(child);
387  readable_children |= __xml_purge_attributes(tmp);
388  }
389 
390  if (readable_children == FALSE) {
391  free_xml(xml); /* Nothing readable under here, purge completely */
392  }
393  return readable_children;
394 }
395 
396 bool
397 xml_acl_filtered_copy(const char *user, xmlNode *acl_source, xmlNode *xml,
398  xmlNode **result)
399 {
400  GListPtr aIter = NULL;
401  xmlNode *target = NULL;
402  xml_private_t *p = NULL;
403  xml_private_t *doc = NULL;
404 
405  *result = NULL;
406  if (xml == NULL || pcmk_acl_required(user) == FALSE) {
407  crm_trace("no acls needed for '%s'", user);
408  return FALSE;
409  }
410 
411  crm_trace("filtering copy of %p for '%s'", xml, user);
412  target = copy_xml(xml);
413  if (target == NULL) {
414  return TRUE;
415  }
416 
417  pcmk__unpack_acl(acl_source, target, user);
419  pcmk__apply_acl(target);
420 
421  doc = target->doc->_private;
422  for(aIter = doc->acls; aIter != NULL && target; aIter = aIter->next) {
423  int max = 0;
424  xml_acl_t *acl = aIter->data;
425 
426  if (acl->mode != xpf_acl_deny) {
427  /* Nothing to do */
428 
429  } else if (acl->xpath) {
430  int lpc = 0;
431  xmlXPathObjectPtr xpathObj = xpath_search(target, acl->xpath);
432 
433  max = numXpathResults(xpathObj);
434  for(lpc = 0; lpc < max; lpc++) {
435  xmlNode *match = getXpathResult(xpathObj, lpc);
436 
437  crm_trace("Purging attributes from %s", acl->xpath);
438  if (__xml_purge_attributes(match) == FALSE && match == target) {
439  crm_trace("No access to the entire document for %s", user);
440  freeXpathObject(xpathObj);
441  return TRUE;
442  }
443  }
444  crm_trace("Enforced ACL %s (%d matches)", acl->xpath, max);
445  freeXpathObject(xpathObj);
446  }
447  }
448 
449  p = target->_private;
450  if (is_set(p->flags, xpf_acl_deny)
451  && (__xml_purge_attributes(target) == FALSE)) {
452  crm_trace("No access to the entire document for %s", user);
453  return TRUE;
454  }
455 
456  if (doc->acls) {
457  g_list_free_full(doc->acls, __xml_acl_free);
458  doc->acls = NULL;
459 
460  } else {
461  crm_trace("Ordinary user '%s' cannot access the CIB without any defined ACLs",
462  doc->user);
463  free_xml(target);
464  target = NULL;
465  }
466 
467  if (target) {
468  *result = target;
469  }
470 
471  return TRUE;
472 }
473 
486 static bool
487 implicitly_allowed(xmlNode *xml)
488 {
489  char *path = NULL;
490 
491  for (xmlAttr *prop = xml->properties; prop != NULL; prop = prop->next) {
492  if (strcmp((const char *) prop->name, XML_ATTR_ID) != 0) {
493  return FALSE;
494  }
495  }
496 
497  path = xml_get_path(xml);
498  if (strstr(path, "/" XML_CIB_TAG_ACLS "/") != NULL) {
499  free(path);
500  return FALSE;
501  }
502  free(path);
503 
504  return TRUE;
505 }
506 
507 #define display_id(xml) (ID(xml)? ID(xml) : "<unset>")
508 
522 void
523 pcmk__post_process_acl(xmlNode *xml, bool check_top)
524 {
525  xml_private_t *p = xml->_private;
526 
527  if (is_set(p->flags, xpf_created)) {
528  if (implicitly_allowed(xml)) {
529  crm_trace("Creation of <%s> scaffolding with id=\"%s\""
530  " is implicitly allowed",
531  crm_element_name(xml), display_id(xml));
532 
533  } else if (pcmk__check_acl(xml, NULL, xpf_acl_write)) {
534  crm_trace("ACLs allow creation of <%s> with id=\"%s\"",
535  crm_element_name(xml), display_id(xml));
536 
537  } else if (check_top) {
538  crm_trace("ACLs disallow creation of <%s> with id=\"%s\"",
539  crm_element_name(xml), display_id(xml));
541  return;
542 
543  } else {
544  crm_trace("ACLs would disallow creation of <%s> with id=\"%s\"",
545  crm_element_name(xml), display_id(xml));
546  }
547  }
548 
549  for (xmlNode *cIter = __xml_first_child(xml); cIter != NULL; ) {
550  xmlNode *child = cIter;
551  cIter = __xml_next(cIter); /* In case it is free'd */
552  pcmk__post_process_acl(child, TRUE);
553  }
554 }
555 
556 bool
557 xml_acl_denied(xmlNode *xml)
558 {
559  if (xml && xml->doc && xml->doc->_private){
560  xml_private_t *p = xml->doc->_private;
561 
562  return is_set(p->flags, xpf_acl_denied);
563  }
564  return FALSE;
565 }
566 
567 void
568 xml_acl_disable(xmlNode *xml)
569 {
570  if (xml_acl_enabled(xml)) {
571  xml_private_t *p = xml->doc->_private;
572 
573  /* Catch anything that was created but shouldn't have been */
574  pcmk__apply_acl(xml);
575  pcmk__post_process_acl(xml, FALSE);
577  }
578 }
579 
580 bool
581 xml_acl_enabled(xmlNode *xml)
582 {
583  if (xml && xml->doc && xml->doc->_private){
584  xml_private_t *p = xml->doc->_private;
585 
586  return is_set(p->flags, xpf_acl_enabled);
587  }
588  return FALSE;
589 }
590 
591 bool
592 pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
593 {
594  CRM_ASSERT(xml);
595  CRM_ASSERT(xml->doc);
596  CRM_ASSERT(xml->doc->_private);
597 
598 #if ENABLE_ACL
599  if (pcmk__tracking_xml_changes(xml, FALSE) && xml_acl_enabled(xml)) {
600  int offset = 0;
601  xmlNode *parent = xml;
602  char buffer[MAX_XPATH_LEN];
603  xml_private_t *docp = xml->doc->_private;
604 
605  if (docp->acls == NULL) {
606  crm_trace("Ordinary user %s cannot access the CIB without any defined ACLs",
607  docp->user);
609  return FALSE;
610  }
611 
612  offset = pcmk__element_xpath(NULL, xml, buffer, offset,
613  sizeof(buffer));
614  if (name) {
615  offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
616  "[@%s]", name);
617  }
618  CRM_LOG_ASSERT(offset > 0);
619 
620  /* Walk the tree upwards looking for xml_acl_* flags
621  * - Creating an attribute requires write permissions for the node
622  * - Creating a child requires write permissions for the parent
623  */
624 
625  if (name) {
626  xmlAttr *attr = xmlHasProp(xml, (const xmlChar *)name);
627 
628  if (attr && mode == xpf_acl_create) {
629  mode = xpf_acl_write;
630  }
631  }
632 
633  while (parent && parent->_private) {
634  xml_private_t *p = parent->_private;
635  if (__xml_acl_mode_test(p->flags, mode)) {
636  return TRUE;
637 
638  } else if (is_set(p->flags, xpf_acl_deny)) {
639  crm_trace("%x access denied to %s: parent", mode, buffer);
641  return FALSE;
642  }
643  parent = parent->parent;
644  }
645 
646  crm_trace("%x access denied to %s: default", mode, buffer);
648  return FALSE;
649  }
650 #endif
651 
652  return TRUE;
653 }
654 
655 bool
656 pcmk_acl_required(const char *user)
657 {
658 #if ENABLE_ACL
659  if (user == NULL || strlen(user) == 0) {
660  crm_trace("no user set");
661  return FALSE;
662 
663  } else if (strcmp(user, CRM_DAEMON_USER) == 0) {
664  return FALSE;
665 
666  } else if (strcmp(user, "root") == 0) {
667  return FALSE;
668  }
669  crm_trace("ACLs required for %s", user);
670  return TRUE;
671 #else
672  crm_trace("ACLs not supported");
673  return FALSE;
674 #endif
675 }
676 
677 #if ENABLE_ACL
678 char *
679 uid2username(uid_t uid)
680 {
681  struct passwd *pwent = getpwuid(uid);
682 
683  if (pwent == NULL) {
684  crm_perror(LOG_INFO, "Cannot get user details for user ID %d", uid);
685  return NULL;
686  }
687  return strdup(pwent->pw_name);
688 }
689 
690 const char *
691 crm_acl_get_set_user(xmlNode *request, const char *field, const char *peer_user)
692 {
693  static const char *effective_user = NULL;
694  const char *requested_user = NULL;
695  const char *user = NULL;
696 
697  if (effective_user == NULL) {
698  effective_user = uid2username(geteuid());
699  if (effective_user == NULL) {
700  effective_user = strdup("#unprivileged");
701  CRM_CHECK(effective_user != NULL, return NULL);
702  crm_err("Unable to determine effective user, assuming unprivileged for ACLs");
703  }
704  }
705 
706  requested_user = crm_element_value(request, XML_ACL_TAG_USER);
707  if (requested_user == NULL) {
708  /* @COMPAT rolling upgrades <=1.1.11
709  *
710  * field is checked for backward compatibility with older versions that
711  * did not use XML_ACL_TAG_USER.
712  */
713  requested_user = crm_element_value(request, field);
714  }
715 
716  if (is_privileged(effective_user) == FALSE) {
717  /* We're not running as a privileged user, set or overwrite any existing
718  * value for $XML_ACL_TAG_USER
719  */
720  user = effective_user;
721 
722  } else if (peer_user == NULL && requested_user == NULL) {
723  /* No user known or requested, use 'effective_user' and make sure one is
724  * set for the request
725  */
726  user = effective_user;
727 
728  } else if (peer_user == NULL) {
729  /* No user known, trusting 'requested_user' */
730  user = requested_user;
731 
732  } else if (is_privileged(peer_user) == FALSE) {
733  /* The peer is not a privileged user, set or overwrite any existing
734  * value for $XML_ACL_TAG_USER
735  */
736  user = peer_user;
737 
738  } else if (requested_user == NULL) {
739  /* Even if we're privileged, make sure there is always a value set */
740  user = peer_user;
741 
742  } else {
743  /* Legal delegation to 'requested_user' */
744  user = requested_user;
745  }
746 
747  // This requires pointer comparison, not string comparison
748  if (user != crm_element_value(request, XML_ACL_TAG_USER)) {
749  crm_xml_add(request, XML_ACL_TAG_USER, user);
750  }
751 
752  if (field != NULL && user != crm_element_value(request, field)) {
753  crm_xml_add(request, field, user);
754  }
755 
756  return requested_user;
757 }
758 #endif
#define LOG_TRACE
Definition: logging.h:29
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:190
void xml_acl_disable(xmlNode *xml)
Definition: acl.c:568
A dumping ground.
#define XML_ACL_ATTR_REF
Definition: msg_xml.h:412
#define MAX_XPATH_LEN
Definition: acl.c:26
void pcmk__free_acls(GList *acls)
Definition: acl.c:45
G_GNUC_INTERNAL int pcmk__element_xpath(const char *prefix, xmlNode *xml, char *buffer, int offset, size_t buffer_size)
Definition: xml.c:2002
bool xml_acl_enabled(xmlNode *xml)
Definition: acl.c:581
bool pcmk_acl_required(const char *user)
Definition: acl.c:656
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:216
#define XML_ACL_TAG_WRITE
Definition: msg_xml.h:410
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:176
#define clear_bit(word, bit)
Definition: crm_internal.h:211
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:224
void pcmk__post_process_acl(xmlNode *xml, bool check_top)
Definition: acl.c:523
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:2114
#define XML_ACL_ATTR_REFv1
Definition: msg_xml.h:413
#define XML_ACL_TAG_ROLE
Definition: msg_xml.h:404
#define XML_ACL_ATTR_KIND
Definition: msg_xml.h:408
bool xml_acl_filtered_copy(const char *user, xmlNode *acl_source, xmlNode *xml, xmlNode **result)
Definition: acl.c:397
bool xml_acl_denied(xmlNode *xml)
Definition: acl.c:557
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
Definition: acl.c:592
#define crm_warn(fmt, args...)
Definition: logging.h:275
void pcmk_free_xml_subtree(xmlNode *xml)
Definition: xml.c:2041
#define crm_debug(fmt, args...)
Definition: logging.h:279
#define XML_ATTR_ID
Definition: msg_xml.h:102
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:393
#define XML_ACL_ATTR_XPATH
Definition: msg_xml.h:416
#define XML_ACL_TAG_PERMISSION
Definition: msg_xml.h:405
#define crm_trace(fmt, args...)
Definition: logging.h:280
#define XML_ACL_TAG_USERv1
Definition: msg_xml.h:402
Wrappers for and extensions to libxml2.
#define display_id(xml)
Definition: acl.c:507
#define XML_ACL_TAG_DENY
Definition: msg_xml.h:411
G_GNUC_INTERNAL void pcmk__set_xml_flag(xmlNode *xml, enum xml_private_flags flag)
Definition: xml.c:152
#define XML_ACL_ATTR_ATTRIBUTE
Definition: msg_xml.h:417
#define CRM_DAEMON_USER
Definition: config.h:47
void pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user)
Definition: acl.c:285
void free_xml(xmlNode *child)
Definition: xml.c:2108
xml_private_flags
#define XML_CIB_TAG_ACLS
Definition: msg_xml.h:167
#define XML_ACL_ATTR_TAGv1
Definition: msg_xml.h:415
#define crm_config_warn(fmt...)
Definition: crm_internal.h:226
#define crm_perror(level, fmt, args...)
Log a system error message.
Definition: logging.h:252
#define crm_err(fmt, args...)
Definition: logging.h:274
xmlXPathObjectPtr xpath_search(xmlNode *xml_top, const char *path)
Definition: xpath.c:145
#define XML_ACL_TAG_ROLE_REFv1
Definition: msg_xml.h:407
void pcmk__apply_acl(xmlNode *xml)
Definition: acl.c:226
xmlNode * getXpathResult(xmlXPathObjectPtr xpathObj, int index)
Definition: xpath.c:64
char * xml_get_path(xmlNode *xml)
Definition: xml.c:2024
#define CRM_ASSERT(expr)
Definition: error.h:20
char data[0]
Definition: internal.h:86
#define XML_ACL_TAG_READ
Definition: msg_xml.h:409
const char * crm_acl_get_set_user(xmlNode *request, const char *field, const char *peer_user)
#define XML_ACL_TAG_ROLE_REF
Definition: msg_xml.h:406
G_GNUC_INTERNAL bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy)
Definition: xml.c:86
#define ID(x)
Definition: msg_xml.h:452
#define XML_ACL_TAG_USER
Definition: msg_xml.h:401
void freeXpathObject(xmlXPathObjectPtr xpathObj)
Definition: xpath.c:45
#define XML_ACL_ATTR_TAG
Definition: msg_xml.h:414
GList * GListPtr
Definition: crm.h:210
#define crm_info(fmt, args...)
Definition: logging.h:277
char * uid2username(uid_t uid)
struct xml_acl_s xml_acl_t
uint64_t flags
Definition: remote.c:156