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/>.
26 #include "alloc-util.h"
27 #include "string-util.h"
29 #include "user-util.h"
32 int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) {
39 for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
41 r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
47 if (acl_get_tag_type(i, &tag) < 0)
53 u = acl_get_qualifier(i);
71 #if 0 /// UNNEEDED by elogind
72 int calc_acl_mask_if_needed(acl_t *acl_p) {
78 for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i);
80 r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
83 if (acl_get_tag_type(i, &tag) < 0)
89 if (IN_SET(tag, ACL_USER, ACL_GROUP)) {
90 if (acl_calc_mask(acl_p) < 0)
102 int add_base_acls_if_needed(acl_t *acl_p, const char *path) {
105 bool have_user_obj = false, have_group_obj = false, have_other = false;
107 _cleanup_(acl_freep) acl_t basic = NULL;
111 for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i);
113 r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
116 if (acl_get_tag_type(i, &tag) < 0)
119 if (tag == ACL_USER_OBJ)
120 have_user_obj = true;
121 else if (tag == ACL_GROUP_OBJ)
122 have_group_obj = true;
123 else if (tag == ACL_OTHER)
125 if (have_user_obj && have_group_obj && have_other)
135 basic = acl_from_mode(st.st_mode);
139 for (r = acl_get_entry(basic, ACL_FIRST_ENTRY, &i);
141 r = acl_get_entry(basic, ACL_NEXT_ENTRY, &i)) {
145 if (acl_get_tag_type(i, &tag) < 0)
148 if ((tag == ACL_USER_OBJ && have_user_obj) ||
149 (tag == ACL_GROUP_OBJ && have_group_obj) ||
150 (tag == ACL_OTHER && have_other))
153 r = acl_create_entry(acl_p, &dst);
157 r = acl_copy_entry(dst, i);
166 int acl_search_groups(const char *path, char ***ret_groups) {
167 _cleanup_strv_free_ char **g = NULL;
168 _cleanup_(acl_free) acl_t acl = NULL;
175 acl = acl_get_file(path, ACL_TYPE_DEFAULT);
179 r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
181 _cleanup_(acl_free_gid_tpp) gid_t *gid = NULL;
189 if (acl_get_tag_type(entry, &tag) < 0)
192 if (tag != ACL_GROUP)
195 gid = acl_get_qualifier(entry);
199 if (in_gid(*gid) > 0) {
209 name = gid_to_name(*gid);
213 r = strv_consume(&g, name);
219 r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
230 int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) {
231 _cleanup_free_ char **a = NULL, **d = NULL; /* strings are not be freed */
232 _cleanup_strv_free_ char **split;
235 _cleanup_(acl_freep) acl_t a_acl = NULL, d_acl = NULL;
237 split = strv_split(text, ",");
241 STRV_FOREACH(entry, split) {
244 p = startswith(*entry, "default:");
246 p = startswith(*entry, "d:");
249 r = strv_push(&d, p);
251 r = strv_push(&a, *entry);
256 if (!strv_isempty(a)) {
257 _cleanup_free_ char *join;
259 join = strv_join(a, ",");
263 a_acl = acl_from_text(join);
268 r = calc_acl_mask_if_needed(&a_acl);
274 if (!strv_isempty(d)) {
275 _cleanup_free_ char *join;
277 join = strv_join(d, ",");
281 d_acl = acl_from_text(join);
286 r = calc_acl_mask_if_needed(&d_acl);
293 *acl_default = d_acl;
294 a_acl = d_acl = NULL;
299 static int acl_entry_equal(acl_entry_t a, acl_entry_t b) {
300 acl_tag_t tag_a, tag_b;
302 if (acl_get_tag_type(a, &tag_a) < 0)
305 if (acl_get_tag_type(b, &tag_b) < 0)
316 /* can have only one of those */
319 _cleanup_(acl_free_uid_tpp) uid_t *uid_a = NULL, *uid_b = NULL;
321 uid_a = acl_get_qualifier(a);
325 uid_b = acl_get_qualifier(b);
329 return *uid_a == *uid_b;
332 _cleanup_(acl_free_gid_tpp) gid_t *gid_a = NULL, *gid_b = NULL;
334 gid_a = acl_get_qualifier(a);
338 gid_b = acl_get_qualifier(b);
342 return *gid_a == *gid_b;
345 assert_not_reached("Unknown acl tag type");
349 static int find_acl_entry(acl_t acl, acl_entry_t entry, acl_entry_t *out) {
353 for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
355 r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
357 r = acl_entry_equal(i, entry);
370 int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) {
371 _cleanup_(acl_freep) acl_t old;
375 old = acl_get_file(path, type);
379 for (r = acl_get_entry(new, ACL_FIRST_ENTRY, &i);
381 r = acl_get_entry(new, ACL_NEXT_ENTRY, &i)) {
385 r = find_acl_entry(old, i, &j);
389 if (acl_create_entry(&old, &j) < 0)
392 if (acl_copy_entry(j, i) < 0)