1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011,2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) {
36 for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
38 r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
44 if (acl_get_tag_type(i, &tag) < 0)
50 u = acl_get_qualifier(i);
68 int calc_acl_mask_if_needed(acl_t *acl_p) {
74 for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i);
76 r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
79 if (acl_get_tag_type(i, &tag) < 0)
85 if (IN_SET(tag, ACL_USER, ACL_GROUP)) {
86 if (acl_calc_mask(acl_p) < 0)
98 int add_base_acls_if_needed(acl_t *acl_p, const char *path) {
101 bool have_user_obj = false, have_group_obj = false, have_other = false;
103 _cleanup_(acl_freep) acl_t basic = NULL;
107 for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i);
109 r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
112 if (acl_get_tag_type(i, &tag) < 0)
115 if (tag == ACL_USER_OBJ)
116 have_user_obj = true;
117 else if (tag == ACL_GROUP_OBJ)
118 have_group_obj = true;
119 else if (tag == ACL_OTHER)
121 if (have_user_obj && have_group_obj && have_other)
131 basic = acl_from_mode(st.st_mode);
135 for (r = acl_get_entry(basic, ACL_FIRST_ENTRY, &i);
137 r = acl_get_entry(basic, ACL_NEXT_ENTRY, &i)) {
141 if (acl_get_tag_type(i, &tag) < 0)
144 if ((tag == ACL_USER_OBJ && have_user_obj) ||
145 (tag == ACL_GROUP_OBJ && have_group_obj) ||
146 (tag == ACL_OTHER && have_other))
149 r = acl_create_entry(acl_p, &dst);
153 r = acl_copy_entry(dst, i);
162 int acl_search_groups(const char *path, char ***ret_groups) {
163 _cleanup_strv_free_ char **g = NULL;
164 _cleanup_(acl_free) acl_t acl = NULL;
171 acl = acl_get_file(path, ACL_TYPE_DEFAULT);
175 r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
177 _cleanup_(acl_free_gid_tpp) gid_t *gid = NULL;
185 if (acl_get_tag_type(entry, &tag) < 0)
188 if (tag != ACL_GROUP)
191 gid = acl_get_qualifier(entry);
195 if (in_gid(*gid) > 0) {
205 name = gid_to_name(*gid);
209 r = strv_consume(&g, name);
215 r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
226 int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) {
227 _cleanup_free_ char **a = NULL, **d = NULL; /* strings are not be freed */
228 _cleanup_strv_free_ char **split;
231 _cleanup_(acl_freep) acl_t a_acl = NULL, d_acl = NULL;
233 split = strv_split(text, ",");
237 STRV_FOREACH(entry, split) {
240 p = startswith(*entry, "default:");
242 p = startswith(*entry, "d:");
245 r = strv_push(&d, p);
247 r = strv_push(&a, *entry);
252 if (!strv_isempty(a)) {
253 _cleanup_free_ char *join;
255 join = strv_join(a, ",");
259 a_acl = acl_from_text(join);
264 r = calc_acl_mask_if_needed(&a_acl);
270 if (!strv_isempty(d)) {
271 _cleanup_free_ char *join;
273 join = strv_join(d, ",");
277 d_acl = acl_from_text(join);
282 r = calc_acl_mask_if_needed(&d_acl);
289 *acl_default = d_acl;
290 a_acl = d_acl = NULL;
295 static int acl_entry_equal(acl_entry_t a, acl_entry_t b) {
296 acl_tag_t tag_a, tag_b;
298 if (acl_get_tag_type(a, &tag_a) < 0)
301 if (acl_get_tag_type(b, &tag_b) < 0)
312 /* can have only one of those */
315 _cleanup_(acl_free_uid_tpp) uid_t *uid_a = NULL, *uid_b = NULL;
317 uid_a = acl_get_qualifier(a);
321 uid_b = acl_get_qualifier(b);
325 return *uid_a == *uid_b;
328 _cleanup_(acl_free_gid_tpp) gid_t *gid_a = NULL, *gid_b = NULL;
330 gid_a = acl_get_qualifier(a);
334 gid_b = acl_get_qualifier(b);
338 return *gid_a == *gid_b;
341 assert_not_reached("Unknown acl tag type");
345 static int find_acl_entry(acl_t acl, acl_entry_t entry, acl_entry_t *out) {
349 for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
351 r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
353 r = acl_entry_equal(i, entry);
366 int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) {
367 _cleanup_(acl_freep) acl_t old;
371 old = acl_get_file(path, type);
375 for (r = acl_get_entry(new, ACL_FIRST_ENTRY, &i);
377 r = acl_get_entry(new, ACL_NEXT_ENTRY, &i)) {
381 r = find_acl_entry(old, i, &j);
385 if (acl_create_entry(&old, &j) < 0)
388 if (acl_copy_entry(j, i) < 0)