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 /// UNNEEDED by elogind
73 int calc_acl_mask_if_needed(acl_t *acl_p) {
79 for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i);
81 r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
84 if (acl_get_tag_type(i, &tag) < 0)
90 if (IN_SET(tag, ACL_USER, ACL_GROUP)) {
91 if (acl_calc_mask(acl_p) < 0)
103 int add_base_acls_if_needed(acl_t *acl_p, const char *path) {
106 bool have_user_obj = false, have_group_obj = false, have_other = false;
108 _cleanup_(acl_freep) acl_t basic = NULL;
112 for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i);
114 r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
117 if (acl_get_tag_type(i, &tag) < 0)
120 if (tag == ACL_USER_OBJ)
121 have_user_obj = true;
122 else if (tag == ACL_GROUP_OBJ)
123 have_group_obj = true;
124 else if (tag == ACL_OTHER)
126 if (have_user_obj && have_group_obj && have_other)
136 basic = acl_from_mode(st.st_mode);
140 for (r = acl_get_entry(basic, ACL_FIRST_ENTRY, &i);
142 r = acl_get_entry(basic, ACL_NEXT_ENTRY, &i)) {
146 if (acl_get_tag_type(i, &tag) < 0)
149 if ((tag == ACL_USER_OBJ && have_user_obj) ||
150 (tag == ACL_GROUP_OBJ && have_group_obj) ||
151 (tag == ACL_OTHER && have_other))
154 r = acl_create_entry(acl_p, &dst);
158 r = acl_copy_entry(dst, i);
167 int acl_search_groups(const char *path, char ***ret_groups) {
168 _cleanup_strv_free_ char **g = NULL;
169 _cleanup_(acl_free) acl_t acl = NULL;
176 acl = acl_get_file(path, ACL_TYPE_DEFAULT);
180 r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
182 _cleanup_(acl_free_gid_tpp) gid_t *gid = NULL;
190 if (acl_get_tag_type(entry, &tag) < 0)
193 if (tag != ACL_GROUP)
196 gid = acl_get_qualifier(entry);
200 if (in_gid(*gid) > 0) {
210 name = gid_to_name(*gid);
214 r = strv_consume(&g, name);
220 r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
231 int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) {
232 _cleanup_free_ char **a = NULL, **d = NULL; /* strings are not be freed */
233 _cleanup_strv_free_ char **split;
236 _cleanup_(acl_freep) acl_t a_acl = NULL, d_acl = NULL;
238 split = strv_split(text, ",");
242 STRV_FOREACH(entry, split) {
245 p = startswith(*entry, "default:");
247 p = startswith(*entry, "d:");
250 r = strv_push(&d, p);
252 r = strv_push(&a, *entry);
257 if (!strv_isempty(a)) {
258 _cleanup_free_ char *join;
260 join = strv_join(a, ",");
264 a_acl = acl_from_text(join);
269 r = calc_acl_mask_if_needed(&a_acl);
275 if (!strv_isempty(d)) {
276 _cleanup_free_ char *join;
278 join = strv_join(d, ",");
282 d_acl = acl_from_text(join);
287 r = calc_acl_mask_if_needed(&d_acl);
294 *acl_default = d_acl;
295 a_acl = d_acl = NULL;
300 static int acl_entry_equal(acl_entry_t a, acl_entry_t b) {
301 acl_tag_t tag_a, tag_b;
303 if (acl_get_tag_type(a, &tag_a) < 0)
306 if (acl_get_tag_type(b, &tag_b) < 0)
317 /* can have only one of those */
320 _cleanup_(acl_free_uid_tpp) uid_t *uid_a = NULL, *uid_b = NULL;
322 uid_a = acl_get_qualifier(a);
326 uid_b = acl_get_qualifier(b);
330 return *uid_a == *uid_b;
333 _cleanup_(acl_free_gid_tpp) gid_t *gid_a = NULL, *gid_b = NULL;
335 gid_a = acl_get_qualifier(a);
339 gid_b = acl_get_qualifier(b);
343 return *gid_a == *gid_b;
346 assert_not_reached("Unknown acl tag type");
350 static int find_acl_entry(acl_t acl, acl_entry_t entry, acl_entry_t *out) {
354 for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
356 r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
358 r = acl_entry_equal(i, entry);
371 int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) {
372 _cleanup_(acl_freep) acl_t old;
376 old = acl_get_file(path, type);
380 for (r = acl_get_entry(new, ACL_FIRST_ENTRY, &i);
382 r = acl_get_entry(new, ACL_NEXT_ENTRY, &i)) {
386 r = find_acl_entry(old, i, &j);
390 if (acl_create_entry(&old, &j) < 0)
393 if (acl_copy_entry(j, i) < 0)