13 #include <sys/types.h> 19 #include <libxml/tree.h> 26 typedef struct xml_acl_s {
45 g_list_free_full(acls, free_acl);
67 if ((tag == NULL) && (ref == NULL) && (xpath == NULL)) {
69 crm_trace(
"Ignoring ACL <%s> element without selection criteria",
78 acl->xpath = g_strdup(xpath);
79 crm_trace(
"Unpacked ACL <%s> element using xpath: %s",
80 xml->name, acl->xpath);
83 GString *buf = g_string_sized_new(128);
85 if ((ref != NULL) && (attr != NULL)) {
88 ref,
"' and @", attr,
"]", NULL);
90 }
else if (ref != NULL) {
94 }
else if (attr != NULL) {
95 pcmk__g_strcat(buf,
"//", pcmk__s(tag,
"*"),
"[@", attr,
"]", NULL);
101 acl->xpath = buf->str;
103 g_string_free(buf, FALSE);
104 crm_trace(
"Unpacked ACL <%s> element as xpath: %s",
105 xml->name, acl->xpath);
108 return g_list_append(acls, acl);
124 parse_acl_entry(
const xmlNode *acl_top,
const xmlNode *acl_entry, GList *acls)
126 xmlNode *child = NULL;
129 child != NULL; child = pcmk__xe_next(child)) {
131 const char *tag = (
const char *) child->name;
136 crm_trace(
"Unpacking ACL <%s> element of kind '%s'", tag, kind);
139 crm_trace(
"Unpacking ACL <%s> element", tag);
149 xmlNode *role = NULL;
152 role != NULL; role = pcmk__xe_next(role)) {
158 if (role_id && strcmp(ref_role, role_id) == 0) {
159 crm_trace(
"Unpacking referenced role '%s' in ACL <%s> element",
160 role_id, acl_entry->name);
161 acls = parse_acl_entry(acl_top, role, acls);
184 crm_warn(
"Ignoring unknown ACL %s '%s'",
185 (kind?
"kind" :
"element"), tag);
235 xmlXPathObjectPtr xpathObj = NULL;
238 crm_trace(
"Skipping ACLs for user '%s' because not enabled for this XML",
243 for (aIter = docpriv->
acls; aIter != NULL; aIter = aIter->next) {
244 int max = 0, lpc = 0;
248 max = numXpathResults(xpathObj);
250 for (lpc = 0; lpc < max; lpc++) {
253 nodepriv = match->_private;
260 crm_trace(
"Applying %s ACL to %s matched by %s",
261 acl_to_text(acl->mode),
path->str, acl->xpath);
262 g_string_free(
path, TRUE);
267 crm_trace(
"Applied %s ACL %s (%d match%s)",
268 acl_to_text(acl->mode), acl->xpath, max,
269 ((max == 1)?
"" :
"es"));
293 || (
target->doc->_private == NULL)) {
297 docpriv =
target->doc->_private;
299 crm_trace(
"Not unpacking ACLs because not required for user '%s'",
302 }
else if (docpriv->
acls == NULL) {
308 xmlNode *child = NULL;
311 child != NULL; child = pcmk__xe_next(child)) {
324 if (
id && strcmp(
id, user) == 0) {
325 crm_debug(
"Unpacking ACLs for user '%s'",
id);
326 docpriv->
acls = parse_acl_entry(acls, child, docpriv->
acls);
336 crm_debug(
"Unpacking ACLs for group '%s'",
id);
337 docpriv->
acls = parse_acl_entry(acls, child, docpriv->
acls);
367 }
else if (pcmk_all_flags_set(allowed, requested)) {
393 purge_xml_attributes(xmlNode *xml)
395 xmlNode *child = NULL;
396 xmlAttr *xIter = NULL;
397 bool readable_children =
false;
402 xml->name, pcmk__xe_id(xml));
406 xIter = xml->properties;
407 while (xIter != NULL) {
408 xmlAttr *tmp = xIter;
409 const char *prop_name = (
const char *)xIter->name;
419 child = pcmk__xml_first_child(xml);
420 while ( child != NULL ) {
421 xmlNode *tmp = child;
423 child = pcmk__xml_next(child);
424 readable_children |= purge_xml_attributes(tmp);
427 if (!readable_children) {
430 return readable_children;
454 crm_trace(
"Not filtering XML because ACLs not required for user '%s'",
459 crm_trace(
"Filtering XML copy using user '%s' ACLs", user);
467 docpriv =
target->doc->_private;
468 for(aIter = docpriv->
acls; aIter != NULL &&
target; aIter = aIter->next) {
475 }
else if (acl->xpath) {
479 max = numXpathResults(xpathObj);
480 for(lpc = 0; lpc < max; lpc++) {
483 if (!purge_xml_attributes(match) && (match ==
target)) {
484 crm_trace(
"ACLs deny user '%s' access to entire XML document",
490 crm_trace(
"ACLs deny user '%s' access to %s (%d %s)",
491 user, acl->xpath, max,
497 if (!purge_xml_attributes(
target)) {
498 crm_trace(
"ACLs deny user '%s' access to entire XML document", user);
503 g_list_free_full(docpriv->
acls, free_acl);
504 docpriv->
acls = NULL;
507 crm_trace(
"User '%s' without ACLs denied access to entire XML document",
533 implicitly_allowed(
const xmlNode *xml)
535 GString *
path = NULL;
537 for (xmlAttr *prop = xml->properties; prop != NULL; prop = prop->next) {
538 if (strcmp((
const char *) prop->name,
PCMK_XA_ID) != 0) {
547 g_string_free(
path, TRUE);
551 g_string_free(
path, TRUE);
555 #define display_id(xml) pcmk__s(pcmk__xe_id(xml), "<unset>") 578 if (implicitly_allowed(xml)) {
580 " is implicitly allowed",
587 }
else if (check_top) {
588 crm_trace(
"ACLs disallow creation of <%s> with " 594 crm_notice(
"ACLs would disallow creation of %s<%s> with " 596 ((xml == xmlDocGetRootElement(xml->doc))?
"root element " :
""),
601 for (xmlNode *cIter = pcmk__xml_first_child(xml); cIter != NULL; ) {
602 xmlNode *child = cIter;
603 cIter = pcmk__xml_next(cIter);
618 if (xml && xml->doc && xml->doc->_private){
649 if (xml && xml->doc && xml->doc->_private){
661 && (xml->doc->_private != NULL));
666 GString *xpath = NULL;
668 if (docpriv->
acls == NULL) {
677 qb_log_from_external_source(__func__, __FILE__,
678 "User '%s' without ACLs denied %s " 680 docpriv->
user, acl_to_text(mode),
681 (
const char *) xpath->str);
682 g_string_free(xpath, TRUE);
701 if (test_acl_mode(nodepriv->
flags, mode)) {
713 qb_log_from_external_source(__func__, __FILE__,
714 "%sACL denies user '%s' %s access " 716 (
parent != xml)?
"Parent ":
"",
717 docpriv->
user, acl_to_text(mode),
718 (
const char *) xpath->str);
719 g_string_free(xpath, TRUE);
733 qb_log_from_external_source(__func__, __FILE__,
734 "Default ACL denies user '%s' %s access to " 736 docpriv->
user, acl_to_text(mode),
737 (
const char *) xpath->str);
738 g_string_free(xpath, TRUE);
755 if (pcmk__str_empty(user)) {
756 crm_trace(
"ACLs not required because no user set");
760 crm_trace(
"ACLs not required for privileged user %s", user);
770 struct passwd *pwent = getpwuid(uid);
773 crm_perror(LOG_INFO,
"Cannot get user details for user ID %d", uid);
799 const char *peer_user)
801 static const char *effective_user = NULL;
802 const char *requested_user = NULL;
803 const char *user = NULL;
805 if (effective_user == NULL) {
807 if (effective_user == NULL) {
809 crm_err(
"Unable to determine effective user, assuming unprivileged for ACLs");
814 if (requested_user == NULL) {
823 if (!pcmk__is_privileged(effective_user)) {
827 user = effective_user;
829 }
else if (peer_user == NULL && requested_user == NULL) {
833 user = effective_user;
835 }
else if (peer_user == NULL) {
837 user = requested_user;
839 }
else if (!pcmk__is_privileged(peer_user)) {
845 }
else if (requested_user == NULL) {
851 user = requested_user;
863 return requested_user;
void xml_acl_disable(xmlNode *xml)
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
#define crm_notice(fmt, args...)
#define pcmk__if_tracing(if_action, else_action)
void pcmk__free_acls(GList *acls)
#define PCMK__XE_ACL_USER
#define PCMK_XA_REFERENCE
bool pcmk_acl_required(const char *user)
Check whether ACLs are required for a given user.
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
void pcmk__apply_creation_acl(xmlNode *xml, bool check_top)
G_GNUC_INTERNAL bool pcmk__is_user_in_group(const char *user, const char *group)
void pcmk__set_xml_doc_flag(xmlNode *xml, enum xml_private_flags flag)
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
#define PCMK_XE_ACL_PERMISSION
char * pcmk__uid2username(uid_t uid)
bool xml_acl_filtered_copy(const char *user, xmlNode *acl_source, xmlNode *xml, xmlNode **result)
Copy ACL-allowed portions of specified XML.
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
#define crm_warn(fmt, args...)
void pcmk_free_xml_subtree(xmlNode *xml)
#define crm_debug(fmt, args...)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
#define crm_trace(fmt, args...)
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
#define PCMK__XE_ROLE_REF
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
void pcmk__enable_acl(xmlNode *acl_source, xmlNode *target, const char *user)
void pcmk__str_update(char **str, const char *value)
Wrappers for and extensions to libxml2.
const char * pcmk__update_acl_user(xmlNode *request, const char *field, const char *peer_user)
void pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user)
void free_xml(xmlNode *child)
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
bool xml_acl_denied(const xmlNode *xml)
Check whether or not an XML node is ACL-denied.
#define pcmk__str_copy(str)
const xmlChar * pcmkXmlStr
#define pcmk__assert(expr)
xmlXPathObjectPtr xpath_search(const xmlNode *xml_top, const char *path)
#define PCMK_XE_ACL_TARGET
pcmk__action_result_t result
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
#define crm_err(fmt, args...)
#define pcmk__plural_alt(i, s1, s2)
#define PCMK_XE_ACL_GROUP
void pcmk__apply_acl(xmlNode *xml)
xmlNode * getXpathResult(xmlXPathObjectPtr xpathObj, int index)
#define PCMK_XA_ATTRIBUTE
bool xml_acl_enabled(const xmlNode *xml)
Check whether or not an XML node is ACL-enabled.
GString * pcmk__element_xpath(const xmlNode *xml)
G_GNUC_INTERNAL bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy)
#define pcmk__set_xml_flags(xml_priv, flags_to_set)
#define PCMK_XA_OBJECT_TYPE
#define pcmk__clear_xml_flags(xml_priv, flags_to_clear)
#define pcmk__assert_alloc(nmemb, size)
void freeXpathObject(xmlXPathObjectPtr xpathObj)
struct xml_acl_s xml_acl_t
G_GNUC_INTERNAL int pcmk__xa_remove(xmlAttr *attr, bool force)