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(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;
294 static int acl_entry_equal(acl_entry_t a, acl_entry_t b) {
295 acl_tag_t tag_a, tag_b;
297 if (acl_get_tag_type(a, &tag_a) < 0)
300 if (acl_get_tag_type(b, &tag_b) < 0)
311 /* can have only one of those */
314 _cleanup_(acl_free_uid_tpp) uid_t *uid_a = NULL, *uid_b = NULL;
316 uid_a = acl_get_qualifier(a);
320 uid_b = acl_get_qualifier(b);
324 return *uid_a == *uid_b;
327 _cleanup_(acl_free_gid_tpp) gid_t *gid_a = NULL, *gid_b = NULL;
329 gid_a = acl_get_qualifier(a);
333 gid_b = acl_get_qualifier(b);
337 return *gid_a == *gid_b;
340 assert_not_reached("Unknown acl tag type");
344 static int find_acl_entry(acl_t acl, acl_entry_t entry, acl_entry_t *out) {
348 for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
350 r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
352 r = acl_entry_equal(i, entry);
365 int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) {
366 _cleanup_(acl_freep) acl_t old;
370 old = acl_get_file(path, type);
374 for (r = acl_get_entry(new, ACL_FIRST_ENTRY, &i);
376 r = acl_get_entry(new, ACL_NEXT_ENTRY, &i)) {
380 r = find_acl_entry(old, i, &j);
384 if (acl_create_entry(&old, &j) < 0)
387 if (acl_copy_entry(j, i) < 0)