pacemaker  2.1.7-0f7f88312f
Scalable High-Availability cluster resource manager
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 
27 typedef struct xml_acl_s {
28  enum xml_private_flags mode;
29  gchar *xpath;
30 } xml_acl_t;
31 
32 static void
33 free_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 
43 void
44 pcmk__free_acls(GList *acls)
45 {
46  g_list_free_full(acls, free_acl);
47 }
48 
49 static GList *
50 create_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 
125 static GList *
126 parse_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,
154  XML_ATTR_ID);
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 
206 static const char *
207 acl_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 
221 void
222 pcmk__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 
279 void
280 pcmk__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 
343 void
344 pcmk__enable_acl(xmlNode *acl_source, xmlNode *target, const char *user)
345 {
346  pcmk__unpack_acl(acl_source, target, user);
349 }
350 
351 static inline bool
352 test_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 
382 static bool
383 purge_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 
434 bool
435 xml_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);
499  free_xml(target);
500  target = NULL;
501  }
502 
503  if (target) {
504  *result = target;
505  }
506 
507  return true;
508 }
509 
522 static bool
523 implicitly_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 
533  path = pcmk__element_xpath(xml);
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 
562 void
563 pcmk__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 
604 bool
605 xml_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 
615 void
616 xml_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 
635 bool
636 xml_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 
646 bool
647 pcmk__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 
742 bool
743 pcmk_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 
757 char *
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 
789 const char *
790 pcmk__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 }
#define LOG_TRACE
Definition: logging.h:38
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:238
void xml_acl_disable(xmlNode *xml)
Definition: acl.c:616
A dumping ground.
#define XML_ACL_ATTR_REF
Definition: msg_xml.h:439
#define crm_notice(fmt, args...)
Definition: logging.h:383
char data[0]
Definition: cpg.c:55
#define pcmk__if_tracing(if_action, else_action)
void pcmk__free_acls(GList *acls)
Definition: acl.c:44
const char * name
Definition: cib.c:26
bool pcmk_acl_required(const char *user)
Check whether ACLs are required for a given user.
Definition: acl.c:743
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
#define XML_ACL_TAG_WRITE
Definition: msg_xml.h:437
void pcmk__apply_creation_acl(xmlNode *xml, bool check_top)
Definition: acl.c:563
G_GNUC_INTERNAL bool pcmk__is_user_in_group(const char *user, const char *group)
Definition: utils.c:54
void pcmk__set_xml_doc_flag(xmlNode *xml, enum xml_private_flags flag)
Definition: xml.c:78
#define LOG_NEVER
Definition: logging.h:48
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:789
#define XML_ACL_ATTR_REFv1
Definition: msg_xml.h:440
#define XML_ACL_TAG_ROLE
Definition: msg_xml.h:431
#define XML_ACL_ATTR_KIND
Definition: msg_xml.h:435
char * pcmk__uid2username(uid_t uid)
Definition: acl.c:758
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 pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
Definition: acl.c:647
#define crm_warn(fmt, args...)
Definition: logging.h:382
void pcmk_free_xml_subtree(xmlNode *xml)
Definition: xml.c:706
#define crm_debug(fmt, args...)
Definition: logging.h:386
#define XML_ATTR_ID
Definition: msg_xml.h:156
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:447
#define XML_ACL_ATTR_XPATH
Definition: msg_xml.h:443
#define XML_ACL_TAG_PERMISSION
Definition: msg_xml.h:432
#define crm_trace(fmt, args...)
Definition: logging.h:387
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:1217
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:99
#define XML_ATTR_NAME
Definition: msg_xml.h:157
void pcmk__enable_acl(xmlNode *acl_source, xmlNode *target, const char *user)
Definition: acl.c:344
#define XML_ACL_TAG_USERv1
Definition: msg_xml.h:429
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1193
Wrappers for and extensions to libxml2.
#define display_id(xml)
Definition: acl.c:545
const char * pcmk__update_acl_user(xmlNode *request, const char *field, const char *peer_user)
Definition: acl.c:790
#define XML_ACL_TAG_DENY
Definition: msg_xml.h:438
#define XML_ACL_ATTR_ATTRIBUTE
Definition: msg_xml.h:444
#define CRM_DAEMON_USER
Definition: config.h:30
void pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user)
Definition: acl.c:280
void free_xml(xmlNode *child)
Definition: xml.c:783
bool xml_acl_denied(const xmlNode *xml)
Check whether or not an XML node is ACL-denied.
Definition: acl.c:605
#define XML_CIB_TAG_ACLS
Definition: msg_xml.h:211
#define XML_ACL_ATTR_TAGv1
Definition: msg_xml.h:442
const xmlChar * pcmkXmlStr
Definition: xml.h:50
xml_private_flags
Definition: xml_internal.h:388
const char * target
Definition: pcmk_fence.c:29
#define XML_ACL_TAG_GROUP
Definition: msg_xml.h:430
xmlXPathObjectPtr xpath_search(const xmlNode *xml_top, const char *path)
Definition: xpath.c:139
pcmk__action_result_t result
Definition: pcmk_fence.c:35
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition: logging.h:323
const char * path
Definition: cib.c:28
#define crm_err(fmt, args...)
Definition: logging.h:381
#define CRM_ASSERT(expr)
Definition: results.h:42
#define pcmk__plural_alt(i, s1, s2)
#define XML_ACL_TAG_ROLE_REFv1
Definition: msg_xml.h:434
void pcmk__apply_acl(xmlNode *xml)
Definition: acl.c:222
xmlNode * getXpathResult(xmlXPathObjectPtr xpathObj, int index)
Definition: xpath.c:58
#define XML_ACL_TAG_READ
Definition: msg_xml.h:436
bool xml_acl_enabled(const xmlNode *xml)
Check whether or not an XML node is ACL-enabled.
Definition: acl.c:636
GString * pcmk__element_xpath(const xmlNode *xml)
Definition: xpath.c:278
#define XML_ACL_TAG_ROLE_REF
Definition: msg_xml.h:433
G_GNUC_INTERNAL bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy)
Definition: xml.c:49
#define ID(x)
Definition: msg_xml.h:474
const char * parent
Definition: cib.c:27
#define XML_ACL_TAG_USER
Definition: msg_xml.h:428
#define pcmk__set_xml_flags(xml_priv, flags_to_set)
#define pcmk__clear_xml_flags(xml_priv, flags_to_clear)
void freeXpathObject(xmlXPathObjectPtr xpathObj)
Definition: xpath.c:39
#define XML_ACL_ATTR_TAG
Definition: msg_xml.h:441
struct xml_acl_s xml_acl_t
uint64_t flags
Definition: remote.c:215