13 #include <sys/types.h> 19 #include <libxml/tree.h> 26 typedef struct xml_acl_s {
45 g_list_free_full(acls, free_acl);
58 if ((tag == NULL) && (ref == NULL) && (xpath == NULL)) {
60 crm_trace(
"Ignoring ACL <%s> element without selection criteria",
69 acl->xpath = g_strdup(xpath);
70 crm_trace(
"Unpacked ACL <%s> element using xpath: %s",
71 xml->name, acl->xpath);
74 GString *buf = g_string_sized_new(128);
76 if ((ref != NULL) && (attr != NULL)) {
79 ref,
"' and @", attr,
"]", NULL);
81 }
else if (ref != NULL) {
85 }
else if (attr != NULL) {
86 pcmk__g_strcat(buf,
"//", pcmk__s(tag,
"*"),
"[@", attr,
"]", NULL);
92 acl->xpath = buf->str;
94 g_string_free(buf, FALSE);
95 crm_trace(
"Unpacked ACL <%s> element as xpath: %s",
96 xml->name, acl->xpath);
99 return g_list_append(acls, acl);
115 parse_acl_entry(
const xmlNode *acl_top,
const xmlNode *acl_entry, GList *acls)
139 crm_warn(
"Ignoring unknown ACL kind '%s'", kind);
147 if (ref_role == NULL) {
155 const char *role_id = NULL;
164 crm_trace(
"Unpacking referenced role '%s' in <%s> element",
165 role_id, acl_entry->name);
166 acls = parse_acl_entry(acl_top, role, acls);
219 xmlXPathObjectPtr xpathObj = NULL;
222 crm_trace(
"Skipping ACLs for user '%s' because not enabled for this XML",
227 for (aIter = docpriv->
acls; aIter != NULL; aIter = aIter->next) {
228 int max = 0, lpc = 0;
232 max = numXpathResults(xpathObj);
234 for (lpc = 0; lpc < max; lpc++) {
237 nodepriv = match->_private;
244 crm_trace(
"Applying %s ACL to %s matched by %s",
245 acl_to_text(acl->mode),
path->str, acl->xpath);
246 g_string_free(
path, TRUE);
251 crm_trace(
"Applied %s ACL %s (%d match%s)",
252 acl_to_text(acl->mode), acl->xpath, max,
253 ((max == 1)?
"" :
"es"));
277 || (
target->doc->_private == NULL)) {
281 docpriv =
target->doc->_private;
283 crm_trace(
"Not unpacking ACLs because not required for user '%s'",
286 }
else if (docpriv->
acls == NULL) {
292 xmlNode *child = NULL;
304 if (
id && strcmp(
id, user) == 0) {
305 crm_debug(
"Unpacking ACLs for user '%s'",
id);
306 docpriv->
acls = parse_acl_entry(acls, child, docpriv->
acls);
316 crm_debug(
"Unpacking ACLs for group '%s'",
id);
317 docpriv->
acls = parse_acl_entry(acls, child, docpriv->
acls);
347 }
else if (pcmk_all_flags_set(allowed, requested)) {
373 purge_xml_attributes(xmlNode *xml)
375 xmlNode *child = NULL;
376 xmlAttr *xIter = NULL;
377 bool readable_children =
false;
382 xml->name, pcmk__xe_id(xml));
386 xIter = xml->properties;
387 while (xIter != NULL) {
388 xmlAttr *tmp = xIter;
389 const char *prop_name = (
const char *)xIter->name;
399 child = pcmk__xml_first_child(xml);
400 while ( child != NULL ) {
401 xmlNode *tmp = child;
403 child = pcmk__xml_next(child);
404 readable_children |= purge_xml_attributes(tmp);
407 if (!readable_children) {
411 return readable_children;
435 crm_trace(
"Not filtering XML because ACLs not required for user '%s'",
440 crm_trace(
"Filtering XML copy using user '%s' ACLs", user);
448 docpriv =
target->doc->_private;
449 for(aIter = docpriv->
acls; aIter != NULL &&
target; aIter = aIter->next) {
456 }
else if (acl->xpath) {
460 max = numXpathResults(xpathObj);
461 for(lpc = 0; lpc < max; lpc++) {
464 if (!purge_xml_attributes(match) && (match ==
target)) {
465 crm_trace(
"ACLs deny user '%s' access to entire XML document",
471 crm_trace(
"ACLs deny user '%s' access to %s (%d %s)",
472 user, acl->xpath, max,
478 if (!purge_xml_attributes(
target)) {
479 crm_trace(
"ACLs deny user '%s' access to entire XML document", user);
484 g_list_free_full(docpriv->
acls, free_acl);
485 docpriv->
acls = NULL;
488 crm_trace(
"User '%s' without ACLs denied access to entire XML document",
514 implicitly_allowed(
const xmlNode *xml)
516 GString *
path = NULL;
518 for (xmlAttr *prop = xml->properties; prop != NULL; prop = prop->next) {
519 if (strcmp((
const char *) prop->name,
PCMK_XA_ID) != 0) {
528 g_string_free(
path, TRUE);
532 g_string_free(
path, TRUE);
536 #define display_id(xml) pcmk__s(pcmk__xe_id(xml), "<unset>") 559 if (implicitly_allowed(xml)) {
561 " is implicitly allowed",
568 }
else if (check_top) {
572 bool is_root = (xmlDocGetRootElement(xml->doc) == xml);
575 crm_trace(
"ACLs disallow creation of %s<%s> with " 577 (is_root?
"root element " :
""), xml->name,
591 crm_notice(
"ACLs would disallow creation of %s<%s> with " 593 ((xml == xmlDocGetRootElement(xml->doc))?
"root element " :
""),
598 for (xmlNode *cIter = pcmk__xml_first_child(xml); cIter != NULL; ) {
599 xmlNode *child = cIter;
600 cIter = pcmk__xml_next(cIter);
615 if (xml && xml->doc && xml->doc->_private){
646 if (xml && xml->doc && xml->doc->_private){
658 && (xml->doc->_private != NULL));
663 GString *xpath = NULL;
665 if (docpriv->
acls == NULL) {
674 qb_log_from_external_source(__func__, __FILE__,
675 "User '%s' without ACLs denied %s " 677 docpriv->
user, acl_to_text(mode),
678 (
const char *) xpath->str);
679 g_string_free(xpath, TRUE);
698 if (test_acl_mode(nodepriv->
flags, mode)) {
710 qb_log_from_external_source(__func__, __FILE__,
711 "%sACL denies user '%s' %s access " 713 (
parent != xml)?
"Parent ":
"",
714 docpriv->
user, acl_to_text(mode),
715 (
const char *) xpath->str);
716 g_string_free(xpath, TRUE);
730 qb_log_from_external_source(__func__, __FILE__,
731 "Default ACL denies user '%s' %s access to " 733 docpriv->
user, acl_to_text(mode),
734 (
const char *) xpath->str);
735 g_string_free(xpath, TRUE);
752 if (pcmk__str_empty(user)) {
753 crm_trace(
"ACLs not required because no user set");
757 crm_trace(
"ACLs not required for privileged user %s", user);
767 struct passwd *pwent = getpwuid(uid);
770 crm_perror(LOG_INFO,
"Cannot get user details for user ID %d", uid);
796 const char *peer_user)
798 static const char *effective_user = NULL;
799 const char *requested_user = NULL;
800 const char *user = NULL;
802 if (effective_user == NULL) {
804 if (effective_user == NULL) {
806 crm_err(
"Unable to determine effective user, assuming unprivileged for ACLs");
811 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)
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
#define crm_notice(fmt, args...)
#define pcmk__if_tracing(if_action, else_action)
void pcmk__free_acls(GList *acls)
#define PCMK_XA_REFERENCE
bool pcmk_acl_required(const char *user)
Check whether ACLs are required for a given user.
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
void pcmk__xml_free(xmlNode *xml)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
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...)
#define crm_debug(fmt, args...)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
#define crm_trace(fmt, args...)
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
#define PCMK__XA_ACL_TARGET
#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)
bool xml_acl_denied(const xmlNode *xml)
Check whether or not an XML node is ACL-denied.
#define pcmk__str_copy(str)
xmlNode * pcmk__xe_next(const xmlNode *node, const char *element_name)
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)