pacemaker  2.1.5-b7adf64e51
Scalable High-Availability cluster resource manager
acl.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2022 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  char *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  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  crm_element_name(xml));
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 = strdup(xpath);
81  CRM_ASSERT(acl->xpath != NULL);
82  crm_trace("Unpacked ACL <%s> element using xpath: %s",
83  crm_element_name(xml), acl->xpath);
84 
85  } else {
86  GString *buf = g_string_sized_new(128);
87 
88  if ((ref != NULL) && (attr != NULL)) {
89  // NOTE: schema currently does not allow this
90  pcmk__g_strcat(buf, "//", pcmk__s(tag, "*"), "[@" XML_ATTR_ID "='",
91  ref, "' and @", attr, "]", NULL);
92 
93  } else if (ref != NULL) {
94  pcmk__g_strcat(buf, "//", pcmk__s(tag, "*"), "[@" XML_ATTR_ID "='",
95  ref, "']", NULL);
96 
97  } else if (attr != NULL) {
98  pcmk__g_strcat(buf, "//", pcmk__s(tag, "*"), "[@", attr, "]", NULL);
99 
100  } else {
101  pcmk__g_strcat(buf, "//", pcmk__s(tag, "*"), NULL);
102  }
103 
104  acl->xpath = strdup((const char *) buf->str);
105  CRM_ASSERT(acl->xpath != NULL);
106 
107  g_string_free(buf, TRUE);
108  crm_trace("Unpacked ACL <%s> element as xpath: %s",
109  crm_element_name(xml), acl->xpath);
110  }
111 
112  return g_list_append(acls, acl);
113 }
114 
127 static GList *
128 parse_acl_entry(const xmlNode *acl_top, const xmlNode *acl_entry, GList *acls)
129 {
130  xmlNode *child = NULL;
131 
132  for (child = pcmk__xe_first_child(acl_entry); child;
133  child = pcmk__xe_next(child)) {
134  const char *tag = crm_element_name(child);
135  const char *kind = crm_element_value(child, XML_ACL_ATTR_KIND);
136 
137  if (strcmp(XML_ACL_TAG_PERMISSION, tag) == 0){
138  CRM_ASSERT(kind != NULL);
139  crm_trace("Unpacking ACL <%s> element of kind '%s'", tag, kind);
140  tag = kind;
141  } else {
142  crm_trace("Unpacking ACL <%s> element", tag);
143  }
144 
145  if (strcmp(XML_ACL_TAG_ROLE_REF, tag) == 0
146  || strcmp(XML_ACL_TAG_ROLE_REFv1, tag) == 0) {
147  const char *ref_role = crm_element_value(child, XML_ATTR_ID);
148 
149  if (ref_role) {
150  xmlNode *role = NULL;
151 
152  for (role = pcmk__xe_first_child(acl_top); role;
153  role = pcmk__xe_next(role)) {
154  if (!strcmp(XML_ACL_TAG_ROLE, (const char *) role->name)) {
155  const char *role_id = crm_element_value(role,
156  XML_ATTR_ID);
157 
158  if (role_id && strcmp(ref_role, role_id) == 0) {
159  crm_trace("Unpacking referenced role '%s' in ACL <%s> element",
160  role_id, crm_element_name(acl_entry));
161  acls = parse_acl_entry(acl_top, role, acls);
162  break;
163  }
164  }
165  }
166  }
167 
168  } else if (strcmp(XML_ACL_TAG_READ, tag) == 0) {
169  acls = create_acl(child, acls, pcmk__xf_acl_read);
170 
171  } else if (strcmp(XML_ACL_TAG_WRITE, tag) == 0) {
172  acls = create_acl(child, acls, pcmk__xf_acl_write);
173 
174  } else if (strcmp(XML_ACL_TAG_DENY, tag) == 0) {
175  acls = create_acl(child, acls, pcmk__xf_acl_deny);
176 
177  } else {
178  crm_warn("Ignoring unknown ACL %s '%s'",
179  (kind? "kind" : "element"), tag);
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 static const char *
209 acl_to_text(enum xml_private_flags flags)
210 {
212  return "deny";
213 
214  } else if (pcmk_any_flags_set(flags, pcmk__xf_acl_write|pcmk__xf_acl_create)) {
215  return "read/write";
216 
217  } else if (pcmk_is_set(flags, pcmk__xf_acl_read)) {
218  return "read";
219  }
220  return "none";
221 }
222 
223 void
224 pcmk__apply_acl(xmlNode *xml)
225 {
226  GList *aIter = NULL;
227  xml_doc_private_t *docpriv = xml->doc->_private;
228  xml_node_private_t *nodepriv;
229  xmlXPathObjectPtr xpathObj = NULL;
230 
231  if (!xml_acl_enabled(xml)) {
232  crm_trace("Skipping ACLs for user '%s' because not enabled for this XML",
233  docpriv->user);
234  return;
235  }
236 
237  for (aIter = docpriv->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  static struct qb_log_callsite *trace_cs = NULL;
246  xmlNode *match = getXpathResult(xpathObj, lpc);
247 
248  nodepriv = match->_private;
249  pcmk__set_xml_flags(nodepriv, acl->mode);
250 
251  /* Build a GString only if tracing is enabled.
252  * Can't use pcmk__log_else() because the else_action would be
253  * continue.
254  */
255  if (trace_cs == NULL) {
256  trace_cs = qb_log_callsite_get(__func__, __FILE__, "apply_acl",
257  LOG_TRACE, __LINE__, 0);
258  }
259  if (crm_is_callsite_active(trace_cs, LOG_TRACE, 0)) {
260  GString *path = pcmk__element_xpath(match);
261  crm_trace("Applying %s ACL to %s matched by %s",
262  acl_to_text(acl->mode), (const char *) path->str,
263  acl->xpath);
264  g_string_free(path, TRUE);
265  }
266  }
267  crm_trace("Applied %s ACL %s (%d match%s)",
268  acl_to_text(acl->mode), acl->xpath, max,
269  ((max == 1)? "" : "es"));
270  freeXpathObject(xpathObj);
271  }
272 }
273 
287 void
288 pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user)
289 {
290  xml_doc_private_t *docpriv = NULL;
291 
292  if ((target == NULL) || (target->doc == NULL)
293  || (target->doc->_private == NULL)) {
294  return;
295  }
296 
297  docpriv = 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 (docpriv->acls == NULL) {
303  xmlNode *acls = get_xpath_object("//" XML_CIB_TAG_ACLS,
304  source, LOG_NEVER);
305 
306  pcmk__str_update(&docpriv->user, user);
307 
308  if (acls) {
309  xmlNode *child = NULL;
310 
311  for (child = pcmk__xe_first_child(acls); child;
312  child = pcmk__xe_next(child)) {
313  const char *tag = crm_element_name(child);
314 
315  if (!strcmp(tag, XML_ACL_TAG_USER)
316  || !strcmp(tag, XML_ACL_TAG_USERv1)) {
317  const char *id = crm_element_value(child, XML_ATTR_NAME);
318 
319  if (id == NULL) {
320  id = crm_element_value(child, XML_ATTR_ID);
321  }
322 
323  if (id && strcmp(id, user) == 0) {
324  crm_debug("Unpacking ACLs for user '%s'", id);
325  docpriv->acls = parse_acl_entry(acls, child, docpriv->acls);
326  }
327  } else if (!strcmp(tag, XML_ACL_TAG_GROUP)) {
328  const char *id = crm_element_value(child, XML_ATTR_NAME);
329 
330  if (id == NULL) {
331  id = crm_element_value(child, XML_ATTR_ID);
332  }
333 
334  if (id && pcmk__is_user_in_group(user,id)) {
335  crm_debug("Unpacking ACLs for group '%s'", id);
336  docpriv->acls = parse_acl_entry(acls, child, docpriv->acls);
337  }
338  }
339  }
340  }
341  }
342 }
343 
352 void
353 pcmk__enable_acl(xmlNode *acl_source, xmlNode *target, const char *user)
354 {
355  pcmk__unpack_acl(acl_source, target, user);
358 }
359 
360 static inline bool
361 test_acl_mode(enum xml_private_flags allowed, enum xml_private_flags requested)
362 {
363  if (pcmk_is_set(allowed, pcmk__xf_acl_deny)) {
364  return false;
365 
366  } else if (pcmk_all_flags_set(allowed, requested)) {
367  return true;
368 
369  } else if (pcmk_is_set(requested, pcmk__xf_acl_read)
370  && pcmk_is_set(allowed, pcmk__xf_acl_write)) {
371  return true;
372 
373  } else if (pcmk_is_set(requested, pcmk__xf_acl_create)
374  && pcmk_any_flags_set(allowed, pcmk__xf_acl_write|pcmk__xf_created)) {
375  return true;
376  }
377  return false;
378 }
379 
391 static bool
392 purge_xml_attributes(xmlNode *xml)
393 {
394  xmlNode *child = NULL;
395  xmlAttr *xIter = NULL;
396  bool readable_children = false;
397  xml_node_private_t *nodepriv = xml->_private;
398 
399  if (test_acl_mode(nodepriv->flags, pcmk__xf_acl_read)) {
400  crm_trace("%s[@id=%s] is readable", crm_element_name(xml), ID(xml));
401  return true;
402  }
403 
404  xIter = xml->properties;
405  while (xIter != NULL) {
406  xmlAttr *tmp = xIter;
407  const char *prop_name = (const char *)xIter->name;
408 
409  xIter = xIter->next;
410  if (strcmp(prop_name, XML_ATTR_ID) == 0) {
411  continue;
412  }
413 
414  xmlUnsetProp(xml, tmp->name);
415  }
416 
417  child = pcmk__xml_first_child(xml);
418  while ( child != NULL ) {
419  xmlNode *tmp = child;
420 
421  child = pcmk__xml_next(child);
422  readable_children |= purge_xml_attributes(tmp);
423  }
424 
425  if (!readable_children) {
426  free_xml(xml); /* Nothing readable under here, purge completely */
427  }
428  return readable_children;
429 }
430 
442 bool
443 xml_acl_filtered_copy(const char *user, xmlNode *acl_source, xmlNode *xml,
444  xmlNode **result)
445 {
446  GList *aIter = NULL;
447  xmlNode *target = NULL;
448  xml_doc_private_t *docpriv = NULL;
449 
450  *result = NULL;
451  if ((xml == NULL) || !pcmk_acl_required(user)) {
452  crm_trace("Not filtering XML because ACLs not required for user '%s'",
453  user);
454  return false;
455  }
456 
457  crm_trace("Filtering XML copy using user '%s' ACLs", user);
458  target = copy_xml(xml);
459  if (target == NULL) {
460  return true;
461  }
462 
463  pcmk__enable_acl(acl_source, target, user);
464 
465  docpriv = target->doc->_private;
466  for(aIter = docpriv->acls; aIter != NULL && target; aIter = aIter->next) {
467  int max = 0;
468  xml_acl_t *acl = aIter->data;
469 
470  if (acl->mode != pcmk__xf_acl_deny) {
471  /* Nothing to do */
472 
473  } else if (acl->xpath) {
474  int lpc = 0;
475  xmlXPathObjectPtr xpathObj = xpath_search(target, acl->xpath);
476 
477  max = numXpathResults(xpathObj);
478  for(lpc = 0; lpc < max; lpc++) {
479  xmlNode *match = getXpathResult(xpathObj, lpc);
480 
481  if (!purge_xml_attributes(match) && (match == target)) {
482  crm_trace("ACLs deny user '%s' access to entire XML document",
483  user);
484  freeXpathObject(xpathObj);
485  return true;
486  }
487  }
488  crm_trace("ACLs deny user '%s' access to %s (%d %s)",
489  user, acl->xpath, max,
490  pcmk__plural_alt(max, "match", "matches"));
491  freeXpathObject(xpathObj);
492  }
493  }
494 
495  if (!purge_xml_attributes(target)) {
496  crm_trace("ACLs deny user '%s' access to entire XML document", user);
497  return true;
498  }
499 
500  if (docpriv->acls) {
501  g_list_free_full(docpriv->acls, free_acl);
502  docpriv->acls = NULL;
503 
504  } else {
505  crm_trace("User '%s' without ACLs denied access to entire XML document",
506  user);
507  free_xml(target);
508  target = NULL;
509  }
510 
511  if (target) {
512  *result = target;
513  }
514 
515  return true;
516 }
517 
530 static bool
531 implicitly_allowed(const xmlNode *xml)
532 {
533  GString *path = NULL;
534 
535  for (xmlAttr *prop = xml->properties; prop != NULL; prop = prop->next) {
536  if (strcmp((const char *) prop->name, XML_ATTR_ID) != 0) {
537  return false;
538  }
539  }
540 
541  path = pcmk__element_xpath(xml);
542  CRM_ASSERT(path != NULL);
543 
544  if (strstr((const char *) path->str, "/" XML_CIB_TAG_ACLS "/") != NULL) {
545  g_string_free(path, TRUE);
546  return false;
547  }
548 
549  g_string_free(path, TRUE);
550  return true;
551 }
552 
553 #define display_id(xml) (ID(xml)? ID(xml) : "<unset>")
554 
570 void
571 pcmk__apply_creation_acl(xmlNode *xml, bool check_top)
572 {
573  xml_node_private_t *nodepriv = xml->_private;
574 
575  if (pcmk_is_set(nodepriv->flags, pcmk__xf_created)) {
576  if (implicitly_allowed(xml)) {
577  crm_trace("Creation of <%s> scaffolding with id=\"%s\""
578  " is implicitly allowed",
579  crm_element_name(xml), display_id(xml));
580 
581  } else if (pcmk__check_acl(xml, NULL, pcmk__xf_acl_write)) {
582  crm_trace("ACLs allow creation of <%s> with id=\"%s\"",
583  crm_element_name(xml), display_id(xml));
584 
585  } else if (check_top) {
586  crm_trace("ACLs disallow creation of <%s> with id=\"%s\"",
587  crm_element_name(xml), display_id(xml));
589  return;
590 
591  } else {
592  crm_notice("ACLs would disallow creation of %s<%s> with id=\"%s\" ",
593  ((xml == xmlDocGetRootElement(xml->doc))? "root element " : ""),
594  crm_element_name(xml), display_id(xml));
595  }
596  }
597 
598  for (xmlNode *cIter = pcmk__xml_first_child(xml); cIter != NULL; ) {
599  xmlNode *child = cIter;
600  cIter = pcmk__xml_next(cIter); /* In case it is free'd */
601  pcmk__apply_creation_acl(child, true);
602  }
603 }
604 
612 bool
613 xml_acl_denied(const xmlNode *xml)
614 {
615  if (xml && xml->doc && xml->doc->_private){
616  xml_doc_private_t *docpriv = xml->doc->_private;
617 
618  return pcmk_is_set(docpriv->flags, pcmk__xf_acl_denied);
619  }
620  return false;
621 }
622 
623 void
624 xml_acl_disable(xmlNode *xml)
625 {
626  if (xml_acl_enabled(xml)) {
627  xml_doc_private_t *docpriv = xml->doc->_private;
628 
629  /* Catch anything that was created but shouldn't have been */
630  pcmk__apply_acl(xml);
631  pcmk__apply_creation_acl(xml, false);
633  }
634 }
635 
643 bool
644 xml_acl_enabled(const xmlNode *xml)
645 {
646  if (xml && xml->doc && xml->doc->_private){
647  xml_doc_private_t *docpriv = xml->doc->_private;
648 
649  return pcmk_is_set(docpriv->flags, pcmk__xf_acl_enabled);
650  }
651  return false;
652 }
653 
654 bool
655 pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
656 {
657  CRM_ASSERT(xml);
658  CRM_ASSERT(xml->doc);
659  CRM_ASSERT(xml->doc->_private);
660 
661  if (pcmk__tracking_xml_changes(xml, false) && xml_acl_enabled(xml)) {
662  xmlNode *parent = xml;
663  xml_doc_private_t *docpriv = xml->doc->_private;
664  GString *xpath = NULL;
665 
666  if (docpriv->acls == NULL) {
668 
669  pcmk__log_else(LOG_TRACE, return false);
670  xpath = pcmk__element_xpath(xml);
671  if (name != NULL) {
672  pcmk__g_strcat(xpath, "[@", name, "]", NULL);
673  }
674 
675  qb_log_from_external_source(__func__, __FILE__,
676  "User '%s' without ACLs denied %s "
677  "access to %s", LOG_TRACE, __LINE__, 0,
678  docpriv->user, acl_to_text(mode),
679  (const char *) xpath->str);
680  g_string_free(xpath, TRUE);
681  return false;
682  }
683 
684  /* Walk the tree upwards looking for xml_acl_* flags
685  * - Creating an attribute requires write permissions for the node
686  * - Creating a child requires write permissions for the parent
687  */
688 
689  if (name) {
690  xmlAttr *attr = xmlHasProp(xml, (pcmkXmlStr) name);
691 
692  if (attr && mode == pcmk__xf_acl_create) {
693  mode = pcmk__xf_acl_write;
694  }
695  }
696 
697  while (parent && parent->_private) {
698  xml_node_private_t *nodepriv = parent->_private;
699  if (test_acl_mode(nodepriv->flags, mode)) {
700  return true;
701 
702  } else if (pcmk_is_set(nodepriv->flags, pcmk__xf_acl_deny)) {
704 
705  pcmk__log_else(LOG_TRACE, return false);
706  xpath = pcmk__element_xpath(xml);
707  if (name != NULL) {
708  pcmk__g_strcat(xpath, "[@", name, "]", NULL);
709  }
710 
711  qb_log_from_external_source(__func__, __FILE__,
712  "%sACL denies user '%s' %s access "
713  "to %s", LOG_TRACE, __LINE__, 0,
714  (parent != xml)? "Parent ": "",
715  docpriv->user, acl_to_text(mode),
716  (const char *) xpath->str);
717  g_string_free(xpath, TRUE);
718  return false;
719  }
720  parent = parent->parent;
721  }
722 
724 
725  pcmk__log_else(LOG_TRACE, return false);
726  xpath = pcmk__element_xpath(xml);
727  if (name != NULL) {
728  pcmk__g_strcat(xpath, "[@", name, "]", NULL);
729  }
730 
731  qb_log_from_external_source(__func__, __FILE__,
732  "Default ACL denies user '%s' %s access to "
733  "%s", LOG_TRACE, __LINE__, 0,
734  docpriv->user, acl_to_text(mode),
735  (const char *) xpath->str);
736  g_string_free(xpath, TRUE);
737  return false;
738  }
739 
740  return true;
741 }
742 
750 bool
751 pcmk_acl_required(const char *user)
752 {
753  if (pcmk__str_empty(user)) {
754  crm_trace("ACLs not required because no user set");
755  return false;
756 
757  } else if (!strcmp(user, CRM_DAEMON_USER) || !strcmp(user, "root")) {
758  crm_trace("ACLs not required for privileged user %s", user);
759  return false;
760  }
761  crm_trace("ACLs required for %s", user);
762  return true;
763 }
764 
765 char *
767 {
768  struct passwd *pwent = getpwuid(uid);
769 
770  if (pwent == NULL) {
771  crm_perror(LOG_INFO, "Cannot get user details for user ID %d", uid);
772  return NULL;
773  }
774  return strdup(pwent->pw_name);
775 }
776 
795 const char *
796 pcmk__update_acl_user(xmlNode *request, const char *field,
797  const char *peer_user)
798 {
799  static const char *effective_user = NULL;
800  const char *requested_user = NULL;
801  const char *user = NULL;
802 
803  if (effective_user == NULL) {
804  effective_user = pcmk__uid2username(geteuid());
805  if (effective_user == NULL) {
806  effective_user = strdup("#unprivileged");
807  CRM_CHECK(effective_user != NULL, return NULL);
808  crm_err("Unable to determine effective user, assuming unprivileged for ACLs");
809  }
810  }
811 
812  requested_user = crm_element_value(request, XML_ACL_TAG_USER);
813  if (requested_user == NULL) {
814  /* @COMPAT rolling upgrades <=1.1.11
815  *
816  * field is checked for backward compatibility with older versions that
817  * did not use XML_ACL_TAG_USER.
818  */
819  requested_user = crm_element_value(request, field);
820  }
821 
822  if (!pcmk__is_privileged(effective_user)) {
823  /* We're not running as a privileged user, set or overwrite any existing
824  * value for $XML_ACL_TAG_USER
825  */
826  user = effective_user;
827 
828  } else if (peer_user == NULL && requested_user == NULL) {
829  /* No user known or requested, use 'effective_user' and make sure one is
830  * set for the request
831  */
832  user = effective_user;
833 
834  } else if (peer_user == NULL) {
835  /* No user known, trusting 'requested_user' */
836  user = requested_user;
837 
838  } else if (!pcmk__is_privileged(peer_user)) {
839  /* The peer is not a privileged user, set or overwrite any existing
840  * value for $XML_ACL_TAG_USER
841  */
842  user = peer_user;
843 
844  } else if (requested_user == NULL) {
845  /* Even if we're privileged, make sure there is always a value set */
846  user = peer_user;
847 
848  } else {
849  /* Legal delegation to 'requested_user' */
850  user = requested_user;
851  }
852 
853  // This requires pointer comparison, not string comparison
854  if (user != crm_element_value(request, XML_ACL_TAG_USER)) {
855  crm_xml_add(request, XML_ACL_TAG_USER, user);
856  }
857 
858  if (field != NULL && user != crm_element_value(request, field)) {
859  crm_xml_add(request, field, user);
860  }
861 
862  return requested_user;
863 }
#define LOG_TRACE
Definition: logging.h:37
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:227
void xml_acl_disable(xmlNode *xml)
Definition: acl.c:624
A dumping ground.
#define XML_ACL_ATTR_REF
Definition: msg_xml.h:433
#define crm_notice(fmt, args...)
Definition: logging.h:361
char data[0]
Definition: cpg.c:55
void pcmk__free_acls(GList *acls)
Definition: acl.c:44
const char * name
Definition: cib.c:24
bool pcmk_acl_required(const char *user)
Check whether ACLs are required for a given user.
Definition: acl.c:751
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:323
#define XML_ACL_TAG_WRITE
Definition: msg_xml.h:431
#define pcmk__log_else(level, else_action)
void pcmk__apply_creation_acl(xmlNode *xml, bool check_top)
Definition: acl.c:571
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:108
#define LOG_NEVER
Definition: logging.h:47
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Definition: xpath.c:214
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:891
#define XML_ACL_ATTR_REFv1
Definition: msg_xml.h:434
#define XML_ACL_TAG_ROLE
Definition: msg_xml.h:425
#define XML_ACL_ATTR_KIND
Definition: msg_xml.h:429
char * pcmk__uid2username(uid_t uid)
Definition: acl.c:766
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:443
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
Definition: acl.c:655
#define crm_warn(fmt, args...)
Definition: logging.h:360
void pcmk_free_xml_subtree(xmlNode *xml)
Definition: xml.c:808
#define crm_debug(fmt, args...)
Definition: logging.h:364
#define XML_ATTR_ID
Definition: msg_xml.h:134
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:517
#define XML_ACL_ATTR_XPATH
Definition: msg_xml.h:437
#define XML_ACL_TAG_PERMISSION
Definition: msg_xml.h:426
#define crm_trace(fmt, args...)
Definition: logging.h:365
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:1214
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:121
#define XML_ATTR_NAME
Definition: msg_xml.h:135
void pcmk__enable_acl(xmlNode *acl_source, xmlNode *target, const char *user)
Definition: acl.c:353
#define XML_ACL_TAG_USERv1
Definition: msg_xml.h:423
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1190
Wrappers for and extensions to libxml2.
#define display_id(xml)
Definition: acl.c:553
const char * pcmk__update_acl_user(xmlNode *request, const char *field, const char *peer_user)
Definition: acl.c:796
#define XML_ACL_TAG_DENY
Definition: msg_xml.h:432
#define XML_ACL_ATTR_ATTRIBUTE
Definition: msg_xml.h:438
#define CRM_DAEMON_USER
Definition: config.h:30
void pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user)
Definition: acl.c:288
void free_xml(xmlNode *child)
Definition: xml.c:885
bool xml_acl_denied(const xmlNode *xml)
Check whether or not an XML node is ACL-denied.
Definition: acl.c:613
#define XML_CIB_TAG_ACLS
Definition: msg_xml.h:193
#define XML_ACL_ATTR_TAGv1
Definition: msg_xml.h:436
const xmlChar * pcmkXmlStr
Definition: xml.h:50
gboolean crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags)
Definition: logging.c:635
xml_private_flags
Definition: xml_internal.h:320
const char * target
Definition: pcmk_fence.c:29
#define XML_ACL_TAG_GROUP
Definition: msg_xml.h:424
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:310
const char * path
Definition: cib.c:26
#define crm_err(fmt, args...)
Definition: logging.h:359
#define CRM_ASSERT(expr)
Definition: results.h:42
xmlXPathObjectPtr xpath_search(xmlNode *xml_top, const char *path)
Definition: xpath.c:139
#define pcmk__plural_alt(i, s1, s2)
#define XML_ACL_TAG_ROLE_REFv1
Definition: msg_xml.h:428
void pcmk__apply_acl(xmlNode *xml)
Definition: acl.c:224
xmlNode * getXpathResult(xmlXPathObjectPtr xpathObj, int index)
Definition: xpath.c:58
#define XML_ACL_TAG_READ
Definition: msg_xml.h:430
bool xml_acl_enabled(const xmlNode *xml)
Check whether or not an XML node is ACL-enabled.
Definition: acl.c:644
GString * pcmk__element_xpath(const xmlNode *xml)
Definition: xpath.c:281
#define XML_ACL_TAG_ROLE_REF
Definition: msg_xml.h:427
G_GNUC_INTERNAL bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy)
Definition: xml.c:49
#define ID(x)
Definition: msg_xml.h:468
const char * parent
Definition: cib.c:25
#define XML_ACL_TAG_USER
Definition: msg_xml.h:422
#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:435
struct xml_acl_s xml_acl_t
uint64_t flags
Definition: remote.c:215