@@ -47,6 +47,32 @@ pcmk__free_acls(GList *acls)
4747 g_list_free_full (acls , free_acl );
4848}
4949
50+ /*!
51+ * \internal
52+ * \brief Parse an ACL mode from a string
53+ *
54+ * \param[in] text String to parse
55+ *
56+ * \return ACL mode corresponding to \p text
57+ */
58+ static enum pcmk__xml_flags
59+ parse_acl_mode (const char * text )
60+ {
61+ if (pcmk__str_eq (text , PCMK_VALUE_READ , pcmk__str_none )) {
62+ return pcmk__xf_acl_read ;
63+ }
64+
65+ if (pcmk__str_eq (text , PCMK_VALUE_WRITE , pcmk__str_none )) {
66+ return pcmk__xf_acl_write ;
67+ }
68+
69+ if (pcmk__str_eq (text , PCMK_VALUE_DENY , pcmk__str_none )) {
70+ return pcmk__xf_acl_deny ;
71+ }
72+
73+ return pcmk__xf_none ;
74+ }
75+
5076static GList *
5177create_acl (const xmlNode * xml , GList * acls , enum pcmk__xml_flags mode )
5278{
@@ -101,6 +127,51 @@ create_acl(const xmlNode *xml, GList *acls, enum pcmk__xml_flags mode)
101127 return g_list_append (acls , acl );
102128}
103129
130+ /*!
131+ * \internal
132+ * \brief Unpack a \c PCMK_XE_ACL_PERMISSION element to an \c xml_acl_t
133+ *
134+ * Append the new \c xml_acl_t object to a list.
135+ *
136+ * \param[in] xml Permission element to unpack
137+ * \param[in,out] acls List of ACLs to append to (\c NULL to start a new list)
138+ *
139+ * \return On success, \p acls with the new item appended, or a new list
140+ * containing only the new item if \p acls is \c NULL. On failure,
141+ * \p acls (unmodified).
142+ *
143+ * \note The caller is responsible for freeing the return value using
144+ * \c pcmk__free_acls().
145+ */
146+ static GList *
147+ unpack_acl_permission (const xmlNode * xml , GList * acls )
148+ {
149+ // ID unset is not possible with schema validation enabled
150+ const char * id = pcmk__s (pcmk__xe_id (xml ), "(no ID)" );
151+ const char * type = (const char * ) xml -> name ;
152+ const char * kind_s = pcmk__xe_get (xml , PCMK_XA_KIND );
153+ enum pcmk__xml_flags kind = pcmk__xf_none ;
154+
155+ if (kind_s == NULL ) {
156+ // Not possible with schema validation enabled
157+ pcmk__warn ("Ignoring <%s> element %s with no " PCMK_XA_KIND " "
158+ "attribute" , type , id );
159+ return acls ;
160+ }
161+
162+ kind = parse_acl_mode (kind_s );
163+ if (kind == pcmk__xf_none ) {
164+ pcmk__warn ("Ignoring <%s> element %s with unknown ACL kind '%s'" , type ,
165+ id , kind_s );
166+ return acls ;
167+ }
168+
169+ pcmk__trace ("Unpacking <%s> element %s with " PCMK_XA_KIND "='%s'" , type ,
170+ id , kind_s );
171+
172+ return create_acl (xml , acls , kind );
173+ }
174+
104175/*!
105176 * \internal
106177 * \brief Unpack a user, group, or role subtree of the ACLs section
@@ -121,25 +192,7 @@ parse_acl_entry(const xmlNode *acl_top, const xmlNode *acl_entry, GList *acls)
121192 child != NULL ; child = pcmk__xe_next (child , NULL )) {
122193
123194 if (pcmk__xe_is (child , PCMK_XE_ACL_PERMISSION )) {
124- const char * kind = pcmk__xe_get (child , PCMK_XA_KIND );
125-
126- pcmk__assert (kind != NULL );
127- pcmk__trace ("Unpacking <" PCMK_XE_ACL_PERMISSION "> element of "
128- "kind '%s'" ,
129- kind );
130-
131- if (pcmk__str_eq (kind , PCMK_VALUE_READ , pcmk__str_none )) {
132- acls = create_acl (child , acls , pcmk__xf_acl_read );
133-
134- } else if (pcmk__str_eq (kind , PCMK_VALUE_WRITE , pcmk__str_none )) {
135- acls = create_acl (child , acls , pcmk__xf_acl_write );
136-
137- } else if (pcmk__str_eq (kind , PCMK_VALUE_DENY , pcmk__str_none )) {
138- acls = create_acl (child , acls , pcmk__xf_acl_deny );
139-
140- } else {
141- pcmk__warn ("Ignoring unknown ACL kind '%s'" , kind );
142- }
195+ acls = unpack_acl_permission (child , acls );
143196
144197 } else if (pcmk__xe_is (child , PCMK_XE_ROLE )) {
145198 const char * ref_role = pcmk__xe_get (child , PCMK_XA_ID );
0 commit comments