pacemaker  2.0.4-2deceaa
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
acl.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2020 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  const char *attr = crm_element_value(xml, XML_ACL_ATTR_ATTRIBUTE);
59 
60  if (tag == NULL) {
61  // @COMPAT rolling upgrades <=1.1.11
63  }
64  if (ref == NULL) {
65  // @COMPAT rolling upgrades <=1.1.11
67  }
68 
69  if ((tag == NULL) && (ref == NULL) && (xpath == NULL)) {
70  // Schema should prevent this, but to be safe ...
71  crm_trace("Ignoring ACL <%s> element without selection criteria",
72  crm_element_name(xml));
73  return NULL;
74  }
75 
76  acl = calloc(1, sizeof (xml_acl_t));
77  CRM_ASSERT(acl != NULL);
78 
79  acl->mode = mode;
80  if (xpath) {
81  acl->xpath = strdup(xpath);
82  CRM_ASSERT(acl->xpath != NULL);
83  crm_trace("Unpacked ACL <%s> element using xpath: %s",
84  crm_element_name(xml), acl->xpath);
85 
86  } else {
87  int offset = 0;
88  char buffer[MAX_XPATH_LEN];
89 
90  if (tag) {
91  offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
92  "//%s", tag);
93  } else {
94  offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
95  "//*");
96  }
97 
98  if (ref || attr) {
99  offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
100  "[");
101  }
102 
103  if (ref) {
104  offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
105  "@id='%s'", ref);
106  }
107 
108  // NOTE: schema currently does not allow this
109  if (ref && attr) {
110  offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
111  " and ");
112  }
113 
114  if (attr) {
115  offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
116  "@%s", attr);
117  }
118 
119  if (ref || attr) {
120  offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
121  "]");
122  }
123 
124  CRM_LOG_ASSERT(offset > 0);
125  acl->xpath = strdup(buffer);
126  CRM_ASSERT(acl->xpath != NULL);
127 
128  crm_trace("Unpacked ACL <%s> element as xpath: %s",
129  crm_element_name(xml), acl->xpath);
130  }
131 
132  return g_list_append(acls, acl);
133 }
134 
145 static GList *
146 __xml_acl_parse_entry(xmlNode *acl_top, xmlNode *acl_entry, GList *acls)
147 {
148  xmlNode *child = NULL;
149 
150  for (child = __xml_first_child_element(acl_entry); child;
151  child = __xml_next_element(child)) {
152  const char *tag = crm_element_name(child);
153  const char *kind = crm_element_value(child, XML_ACL_ATTR_KIND);
154 
155  if (strcmp(XML_ACL_TAG_PERMISSION, tag) == 0){
156  CRM_ASSERT(kind != NULL);
157  crm_trace("Unpacking ACL <%s> element of kind '%s'", tag, kind);
158  tag = kind;
159  } else {
160  crm_trace("Unpacking ACL <%s> element", tag);
161  }
162 
163  if (strcmp(XML_ACL_TAG_ROLE_REF, tag) == 0
164  || strcmp(XML_ACL_TAG_ROLE_REFv1, tag) == 0) {
165  const char *ref_role = crm_element_value(child, XML_ATTR_ID);
166 
167  if (ref_role) {
168  xmlNode *role = NULL;
169 
170  for (role = __xml_first_child_element(acl_top); role;
171  role = __xml_next_element(role)) {
172  if (!strcmp(XML_ACL_TAG_ROLE, (const char *) role->name)) {
173  const char *role_id = crm_element_value(role,
174  XML_ATTR_ID);
175 
176  if (role_id && strcmp(ref_role, role_id) == 0) {
177  crm_trace("Unpacking referenced role '%s' in ACL <%s> element",
178  role_id, crm_element_name(acl_entry));
179  acls = __xml_acl_parse_entry(acl_top, role, acls);
180  break;
181  }
182  }
183  }
184  }
185 
186  } else if (strcmp(XML_ACL_TAG_READ, tag) == 0) {
187  acls = __xml_acl_create(child, acls, xpf_acl_read);
188 
189  } else if (strcmp(XML_ACL_TAG_WRITE, tag) == 0) {
190  acls = __xml_acl_create(child, acls, xpf_acl_write);
191 
192  } else if (strcmp(XML_ACL_TAG_DENY, tag) == 0) {
193  acls = __xml_acl_create(child, acls, xpf_acl_deny);
194 
195  } else {
196  crm_warn("Ignoring unknown ACL %s '%s'",
197  (kind? "kind" : "element"), tag);
198  }
199  }
200 
201  return acls;
202 }
203 
204 /*
205  <acls>
206  <acl_target id="l33t-haxor"><role id="auto-l33t-haxor"/></acl_target>
207  <acl_role id="auto-l33t-haxor">
208  <acl_permission id="crook-nothing" kind="deny" xpath="/cib"/>
209  </acl_role>
210  <acl_target id="niceguy">
211  <role id="observer"/>
212  </acl_target>
213  <acl_role id="observer">
214  <acl_permission id="observer-read-1" kind="read" xpath="/cib"/>
215  <acl_permission id="observer-write-1" kind="write" xpath="//nvpair[@name='stonith-enabled']"/>
216  <acl_permission id="observer-write-2" kind="write" xpath="//nvpair[@name='target-role']"/>
217  </acl_role>
218  <acl_target id="badidea"><role id="auto-badidea"/></acl_target>
219  <acl_role id="auto-badidea">
220  <acl_permission id="badidea-resources" kind="read" xpath="//meta_attributes"/>
221  <acl_permission id="badidea-resources-2" kind="deny" reference="dummy-meta_attributes"/>
222  </acl_role>
223  </acls>
224 */
225 
226 static const char *
227 __xml_acl_to_text(enum xml_private_flags flags)
228 {
229  if (is_set(flags, xpf_acl_deny)) {
230  return "deny";
231 
232  } else if (is_set(flags, xpf_acl_write) || is_set(flags, xpf_acl_create)) {
233  return "read/write";
234 
235  } else if (is_set(flags, xpf_acl_read)) {
236  return "read";
237  }
238  return "none";
239 }
240 
241 void
242 pcmk__apply_acl(xmlNode *xml)
243 {
244  GListPtr aIter = NULL;
245  xml_private_t *p = xml->doc->_private;
246  xmlXPathObjectPtr xpathObj = NULL;
247 
248  if (xml_acl_enabled(xml) == FALSE) {
249  crm_trace("Skipping ACLs for user '%s' because not enabled for this XML",
250  p->user);
251  return;
252  }
253 
254  for (aIter = p->acls; aIter != NULL; aIter = aIter->next) {
255  int max = 0, lpc = 0;
256  xml_acl_t *acl = aIter->data;
257 
258  xpathObj = xpath_search(xml, acl->xpath);
259  max = numXpathResults(xpathObj);
260 
261  for (lpc = 0; lpc < max; lpc++) {
262  xmlNode *match = getXpathResult(xpathObj, lpc);
263  char *path = xml_get_path(match);
264 
265  p = match->_private;
266  crm_trace("Applying %s ACL to %s matched by %s",
267  __xml_acl_to_text(acl->mode), path, acl->xpath);
268 
269 #ifdef SUSE_ACL_COMPAT
270  if (is_not_set(p->flags, acl->mode)
271  && (is_set(p->flags, xpf_acl_read)
272  || is_set(p->flags, xpf_acl_write)
273  || is_set(p->flags, xpf_acl_deny))) {
274  pcmk__config_warn("Configuration element %s is matched by "
275  "multiple ACL rules, only the first applies "
276  "('%s' wins over '%s')",
277  path, __xml_acl_to_text(p->flags),
278  __xml_acl_to_text(acl->mode));
279  free(path);
280  continue;
281  }
282 #endif
283  p->flags |= acl->mode;
284  free(path);
285  }
286  crm_trace("Applied %s ACL %s (%d match%s)",
287  __xml_acl_to_text(acl->mode), acl->xpath, max,
288  ((max == 1)? "" : "es"));
289  freeXpathObject(xpathObj);
290  }
291 
292  p = xml->_private;
293  if (is_not_set(p->flags, xpf_acl_read)
294  && is_not_set(p->flags, xpf_acl_write)) {
295 
296  p->flags |= xpf_acl_deny;
297  p = xml->doc->_private;
298  crm_info("Applied default deny ACL for user '%s' to <%s>",
299  p->user, crm_element_name(xml));
300  }
301 
302 }
303 
312 void
313 pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user)
314 {
315 #if ENABLE_ACL
316  xml_private_t *p = NULL;
317 
318  if ((target == NULL) || (target->doc == NULL)
319  || (target->doc->_private == NULL)) {
320  return;
321  }
322 
323  p = target->doc->_private;
324  if (pcmk_acl_required(user) == FALSE) {
325  crm_trace("Not unpacking ACLs because not required for user '%s'",
326  user);
327 
328  } else if (p->acls == NULL) {
329  xmlNode *acls = get_xpath_object("//" XML_CIB_TAG_ACLS,
330  source, LOG_NEVER);
331 
332  free(p->user);
333  p->user = strdup(user);
334 
335  if (acls) {
336  xmlNode *child = NULL;
337 
338  for (child = __xml_first_child_element(acls); child;
339  child = __xml_next_element(child)) {
340  const char *tag = crm_element_name(child);
341 
342  if (!strcmp(tag, XML_ACL_TAG_USER)
343  || !strcmp(tag, XML_ACL_TAG_USERv1)) {
344  const char *id = crm_element_value(child, XML_ATTR_ID);
345 
346  if (id && strcmp(id, user) == 0) {
347  crm_debug("Unpacking ACLs for user '%s'", id);
348  p->acls = __xml_acl_parse_entry(acls, child, p->acls);
349  }
350  }
351  }
352  }
353  }
354 #endif
355 }
356 
357 static inline bool
358 __xml_acl_mode_test(enum xml_private_flags allowed,
359  enum xml_private_flags requested)
360 {
361  if (is_set(allowed, xpf_acl_deny)) {
362  return FALSE;
363 
364  } else if (is_set(allowed, requested)) {
365  return TRUE;
366 
367  } else if (is_set(requested, xpf_acl_read)
368  && is_set(allowed, xpf_acl_write)) {
369  return TRUE;
370 
371  } else if (is_set(requested, xpf_acl_create)
372  && is_set(allowed, xpf_acl_write)) {
373  return TRUE;
374 
375  } else if (is_set(requested, xpf_acl_create)
376  && is_set(allowed, xpf_created)) {
377  return TRUE;
378  }
379  return FALSE;
380 }
381 
382 /* rc = TRUE if orig_cib has been filtered
383  * That means '*result' rather than 'xml' should be exploited afterwards
384  */
385 static bool
386 __xml_purge_attributes(xmlNode *xml)
387 {
388  xmlNode *child = NULL;
389  xmlAttr *xIter = NULL;
390  bool readable_children = FALSE;
391  xml_private_t *p = xml->_private;
392 
393  if (__xml_acl_mode_test(p->flags, xpf_acl_read)) {
394  crm_trace("%s[@id=%s] is readable", crm_element_name(xml), ID(xml));
395  return TRUE;
396  }
397 
398  xIter = xml->properties;
399  while (xIter != NULL) {
400  xmlAttr *tmp = xIter;
401  const char *prop_name = (const char *)xIter->name;
402 
403  xIter = xIter->next;
404  if (strcmp(prop_name, XML_ATTR_ID) == 0) {
405  continue;
406  }
407 
408  xmlUnsetProp(xml, tmp->name);
409  }
410 
411  child = __xml_first_child(xml);
412  while ( child != NULL ) {
413  xmlNode *tmp = child;
414 
415  child = __xml_next(child);
416  readable_children |= __xml_purge_attributes(tmp);
417  }
418 
419  if (readable_children == FALSE) {
420  free_xml(xml); /* Nothing readable under here, purge completely */
421  }
422  return readable_children;
423 }
424 
436 bool
437 xml_acl_filtered_copy(const char *user, xmlNode *acl_source, xmlNode *xml,
438  xmlNode **result)
439 {
440  GListPtr aIter = NULL;
441  xmlNode *target = NULL;
442  xml_private_t *p = NULL;
443  xml_private_t *doc = NULL;
444 
445  *result = NULL;
446  if (xml == NULL || pcmk_acl_required(user) == FALSE) {
447  crm_trace("Not filtering XML because ACLs not required for user '%s'",
448  user);
449  return FALSE;
450  }
451 
452  crm_trace("Filtering XML copy using user '%s' ACLs", user);
453  target = copy_xml(xml);
454  if (target == NULL) {
455  return TRUE;
456  }
457 
458  pcmk__unpack_acl(acl_source, target, user);
460  pcmk__apply_acl(target);
461 
462  doc = target->doc->_private;
463  for(aIter = doc->acls; aIter != NULL && target; aIter = aIter->next) {
464  int max = 0;
465  xml_acl_t *acl = aIter->data;
466 
467  if (acl->mode != xpf_acl_deny) {
468  /* Nothing to do */
469 
470  } else if (acl->xpath) {
471  int lpc = 0;
472  xmlXPathObjectPtr xpathObj = xpath_search(target, acl->xpath);
473 
474  max = numXpathResults(xpathObj);
475  for(lpc = 0; lpc < max; lpc++) {
476  xmlNode *match = getXpathResult(xpathObj, lpc);
477 
478  if (__xml_purge_attributes(match) == FALSE && match == target) {
479  crm_trace("ACLs deny user '%s' access to entire XML document",
480  user);
481  freeXpathObject(xpathObj);
482  return TRUE;
483  }
484  }
485  crm_trace("ACLs deny user '%s' access to %s (%d match%s)",
486  user, acl->xpath, max, ((max == 1)? "" : "es"));
487  freeXpathObject(xpathObj);
488  }
489  }
490 
491  p = target->_private;
492  if (is_set(p->flags, xpf_acl_deny)
493  && (__xml_purge_attributes(target) == FALSE)) {
494  crm_trace("ACLs deny user '%s' access to entire XML document", user);
495  return TRUE;
496  }
497 
498  if (doc->acls) {
499  g_list_free_full(doc->acls, __xml_acl_free);
500  doc->acls = NULL;
501 
502  } else {
503  crm_trace("User '%s' without ACLs denied access to entire XML document",
504  user);
505  free_xml(target);
506  target = NULL;
507  }
508 
509  if (target) {
510  *result = target;
511  }
512 
513  return TRUE;
514 }
515 
528 static bool
529 implicitly_allowed(xmlNode *xml)
530 {
531  char *path = NULL;
532 
533  for (xmlAttr *prop = xml->properties; prop != NULL; prop = prop->next) {
534  if (strcmp((const char *) prop->name, XML_ATTR_ID) != 0) {
535  return FALSE;
536  }
537  }
538 
539  path = xml_get_path(xml);
540  if (strstr(path, "/" XML_CIB_TAG_ACLS "/") != NULL) {
541  free(path);
542  return FALSE;
543  }
544  free(path);
545 
546  return TRUE;
547 }
548 
549 #define display_id(xml) (ID(xml)? ID(xml) : "<unset>")
550 
564 void
565 pcmk__apply_creation_acl(xmlNode *xml, bool check_top)
566 {
567  xml_private_t *p = xml->_private;
568 
569  if (is_set(p->flags, xpf_created)) {
570  if (implicitly_allowed(xml)) {
571  crm_trace("Creation of <%s> scaffolding with id=\"%s\""
572  " is implicitly allowed",
573  crm_element_name(xml), display_id(xml));
574 
575  } else if (pcmk__check_acl(xml, NULL, xpf_acl_write)) {
576  crm_trace("ACLs allow creation of <%s> with id=\"%s\"",
577  crm_element_name(xml), display_id(xml));
578 
579  } else if (check_top) {
580  crm_trace("ACLs disallow creation of <%s> with id=\"%s\"",
581  crm_element_name(xml), display_id(xml));
583  return;
584 
585  } else {
586  crm_notice("ACLs would disallow creation of %s<%s> with id=\"%s\" ",
587  ((xml == xmlDocGetRootElement(xml->doc))? "root element " : ""),
588  crm_element_name(xml), display_id(xml));
589  }
590  }
591 
592  for (xmlNode *cIter = __xml_first_child(xml); cIter != NULL; ) {
593  xmlNode *child = cIter;
594  cIter = __xml_next(cIter); /* In case it is free'd */
595  pcmk__apply_creation_acl(child, TRUE);
596  }
597 }
598 
599 bool
600 xml_acl_denied(xmlNode *xml)
601 {
602  if (xml && xml->doc && xml->doc->_private){
603  xml_private_t *p = xml->doc->_private;
604 
605  return is_set(p->flags, xpf_acl_denied);
606  }
607  return FALSE;
608 }
609 
610 void
611 xml_acl_disable(xmlNode *xml)
612 {
613  if (xml_acl_enabled(xml)) {
614  xml_private_t *p = xml->doc->_private;
615 
616  /* Catch anything that was created but shouldn't have been */
617  pcmk__apply_acl(xml);
618  pcmk__apply_creation_acl(xml, FALSE);
620  }
621 }
622 
623 bool
624 xml_acl_enabled(xmlNode *xml)
625 {
626  if (xml && xml->doc && xml->doc->_private){
627  xml_private_t *p = xml->doc->_private;
628 
629  return is_set(p->flags, xpf_acl_enabled);
630  }
631  return FALSE;
632 }
633 
634 bool
635 pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
636 {
637  CRM_ASSERT(xml);
638  CRM_ASSERT(xml->doc);
639  CRM_ASSERT(xml->doc->_private);
640 
641 #if ENABLE_ACL
642  if (pcmk__tracking_xml_changes(xml, FALSE) && xml_acl_enabled(xml)) {
643  int offset = 0;
644  xmlNode *parent = xml;
645  char buffer[MAX_XPATH_LEN];
646  xml_private_t *docp = xml->doc->_private;
647 
648  offset = pcmk__element_xpath(NULL, xml, buffer, offset,
649  sizeof(buffer));
650  if (name) {
651  offset += snprintf(buffer + offset, MAX_XPATH_LEN - offset,
652  "[@%s]", name);
653  }
654  CRM_LOG_ASSERT(offset > 0);
655 
656  if (docp->acls == NULL) {
657  crm_trace("User '%s' without ACLs denied %s access to %s",
658  docp->user, __xml_acl_to_text(mode), buffer);
660  return FALSE;
661  }
662 
663  /* Walk the tree upwards looking for xml_acl_* flags
664  * - Creating an attribute requires write permissions for the node
665  * - Creating a child requires write permissions for the parent
666  */
667 
668  if (name) {
669  xmlAttr *attr = xmlHasProp(xml, (pcmkXmlStr) name);
670 
671  if (attr && mode == xpf_acl_create) {
672  mode = xpf_acl_write;
673  }
674  }
675 
676  while (parent && parent->_private) {
677  xml_private_t *p = parent->_private;
678  if (__xml_acl_mode_test(p->flags, mode)) {
679  return TRUE;
680 
681  } else if (is_set(p->flags, xpf_acl_deny)) {
682  crm_trace("Parent ACL denies user '%s' %s access to %s",
683  docp->user, __xml_acl_to_text(mode), buffer);
685  return FALSE;
686  }
687  parent = parent->parent;
688  }
689 
690  crm_trace("Default ACL denies user '%s' %s access to %s",
691  docp->user, __xml_acl_to_text(mode), buffer);
693  return FALSE;
694  }
695 #endif
696 
697  return TRUE;
698 }
699 
707 bool
708 pcmk_acl_required(const char *user)
709 {
710 #if ENABLE_ACL
711  if (pcmk__str_empty(user)) {
712  crm_trace("ACLs not required because no user set");
713  return FALSE;
714 
715  } else if (!strcmp(user, CRM_DAEMON_USER) || !strcmp(user, "root")) {
716  crm_trace("ACLs not required for privileged user %s", user);
717  return FALSE;
718  }
719  crm_trace("ACLs required for %s", user);
720  return TRUE;
721 #else
722  crm_trace("ACLs not required because not supported by this build");
723  return FALSE;
724 #endif
725 }
726 
727 #if ENABLE_ACL
728 char *
729 pcmk__uid2username(uid_t uid)
730 {
731  struct passwd *pwent = getpwuid(uid);
732 
733  if (pwent == NULL) {
734  crm_perror(LOG_INFO, "Cannot get user details for user ID %d", uid);
735  return NULL;
736  }
737  return strdup(pwent->pw_name);
738 }
739 
758 const char *
759 pcmk__update_acl_user(xmlNode *request, const char *field,
760  const char *peer_user)
761 {
762  static const char *effective_user = NULL;
763  const char *requested_user = NULL;
764  const char *user = NULL;
765 
766  if (effective_user == NULL) {
767  effective_user = pcmk__uid2username(geteuid());
768  if (effective_user == NULL) {
769  effective_user = strdup("#unprivileged");
770  CRM_CHECK(effective_user != NULL, return NULL);
771  crm_err("Unable to determine effective user, assuming unprivileged for ACLs");
772  }
773  }
774 
775  requested_user = crm_element_value(request, XML_ACL_TAG_USER);
776  if (requested_user == NULL) {
777  /* @COMPAT rolling upgrades <=1.1.11
778  *
779  * field is checked for backward compatibility with older versions that
780  * did not use XML_ACL_TAG_USER.
781  */
782  requested_user = crm_element_value(request, field);
783  }
784 
785  if (!pcmk__is_privileged(effective_user)) {
786  /* We're not running as a privileged user, set or overwrite any existing
787  * value for $XML_ACL_TAG_USER
788  */
789  user = effective_user;
790 
791  } else if (peer_user == NULL && requested_user == NULL) {
792  /* No user known or requested, use 'effective_user' and make sure one is
793  * set for the request
794  */
795  user = effective_user;
796 
797  } else if (peer_user == NULL) {
798  /* No user known, trusting 'requested_user' */
799  user = requested_user;
800 
801  } else if (!pcmk__is_privileged(peer_user)) {
802  /* The peer is not a privileged user, set or overwrite any existing
803  * value for $XML_ACL_TAG_USER
804  */
805  user = peer_user;
806 
807  } else if (requested_user == NULL) {
808  /* Even if we're privileged, make sure there is always a value set */
809  user = peer_user;
810 
811  } else {
812  /* Legal delegation to 'requested_user' */
813  user = requested_user;
814  }
815 
816  // This requires pointer comparison, not string comparison
817  if (user != crm_element_value(request, XML_ACL_TAG_USER)) {
818  crm_xml_add(request, XML_ACL_TAG_USER, user);
819  }
820 
821  if (field != NULL && user != crm_element_value(request, field)) {
822  crm_xml_add(request, field, user);
823  }
824 
825  return requested_user;
826 }
827 #endif
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:233
A dumping ground.
#define XML_ACL_ATTR_REF
Definition: msg_xml.h:381
#define crm_notice(fmt, args...)
Definition: logging.h:365
#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:2030
bool xml_acl_filtered_copy(const char *user, xmlNode *acl_source, xmlNode *xml, xmlNode **result)
Definition: acl.c:437
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:316
#define XML_ACL_TAG_WRITE
Definition: msg_xml.h:379
void pcmk__apply_creation_acl(xmlNode *xml, bool check_top)
Definition: acl.c:565
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:219
#define clear_bit(word, bit)
Definition: crm_internal.h:69
#define LOG_NEVER
Definition: logging.h:46
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:211
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:2142
#define XML_ACL_ATTR_REFv1
Definition: msg_xml.h:382
#define XML_ACL_TAG_ROLE
Definition: msg_xml.h:373
#define XML_ACL_ATTR_KIND
Definition: msg_xml.h:377
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
Definition: acl.c:635
#define crm_warn(fmt, args...)
Definition: logging.h:364
void pcmk_free_xml_subtree(xmlNode *xml)
Definition: xml.c:2069
#define crm_debug(fmt, args...)
Definition: logging.h:368
bool xml_acl_enabled(xmlNode *xml)
Definition: acl.c:624
#define XML_ATTR_ID
Definition: msg_xml.h:96
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:522
#define XML_ACL_ATTR_XPATH
Definition: msg_xml.h:385
#define XML_ACL_TAG_PERMISSION
Definition: msg_xml.h:374
#define crm_trace(fmt, args...)
Definition: logging.h:369
const char * pcmk__update_acl_user(xmlNode *request, const char *field, const char *peer_user)
#define XML_ACL_TAG_USERv1
Definition: msg_xml.h:371
Wrappers for and extensions to libxml2.
#define display_id(xml)
Definition: acl.c:549
#define XML_ACL_TAG_DENY
Definition: msg_xml.h:380
G_GNUC_INTERNAL void pcmk__set_xml_flag(xmlNode *xml, enum xml_private_flags flag)
Definition: xml.c:140
#define XML_ACL_ATTR_ATTRIBUTE
Definition: msg_xml.h:386
#define CRM_DAEMON_USER
Definition: config.h:32
void pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user)
Definition: acl.c:313
void free_xml(xmlNode *child)
Definition: xml.c:2136
xml_private_flags
#define XML_CIB_TAG_ACLS
Definition: msg_xml.h:147
#define XML_ACL_ATTR_TAGv1
Definition: msg_xml.h:384
const xmlChar * pcmkXmlStr
Definition: xml.h:51
const char * target
Definition: pcmk_fence.c:28
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition: logging.h:314
#define crm_err(fmt, args...)
Definition: logging.h:363
#define CRM_ASSERT(expr)
Definition: results.h:42
xmlXPathObjectPtr xpath_search(xmlNode *xml_top, const char *path)
Definition: xpath.c:136
#define XML_ACL_TAG_ROLE_REFv1
Definition: msg_xml.h:376
void pcmk__apply_acl(xmlNode *xml)
Definition: acl.c:242
xmlNode * getXpathResult(xmlXPathObjectPtr xpathObj, int index)
Definition: xpath.c:55
bool xml_acl_denied(xmlNode *xml)
Definition: acl.c:600
void xml_acl_disable(xmlNode *xml)
Definition: acl.c:611
char * xml_get_path(xmlNode *xml)
Definition: xml.c:2052
char data[0]
Definition: internal.h:90
#define XML_ACL_TAG_READ
Definition: msg_xml.h:378
#define XML_ACL_TAG_ROLE_REF
Definition: msg_xml.h:375
G_GNUC_INTERNAL bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy)
Definition: xml.c:74
#define ID(x)
Definition: msg_xml.h:418
#define XML_ACL_TAG_USER
Definition: msg_xml.h:370
char * pcmk__uid2username(uid_t uid)
char * name
Definition: pcmk_fence.c:30
void freeXpathObject(xmlXPathObjectPtr xpathObj)
Definition: xpath.c:36
#define XML_ACL_ATTR_TAG
Definition: msg_xml.h:383
GList * GListPtr
Definition: crm.h:214
#define crm_info(fmt, args...)
Definition: logging.h:366
struct xml_acl_s xml_acl_t
#define pcmk__config_warn(fmt...)
Definition: internal.h:100
bool pcmk_acl_required(const char *user)
Check whether ACLs are required for a given user.
Definition: acl.c:708
uint64_t flags
Definition: remote.c:149