]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/acl-util.c
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/>.
25 #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 int calc_acl_mask_if_needed(acl_t
*acl_p
) {
77 for (r
= acl_get_entry(*acl_p
, ACL_FIRST_ENTRY
, &i
);
79 r
= acl_get_entry(*acl_p
, ACL_NEXT_ENTRY
, &i
)) {
82 if (acl_get_tag_type(i
, &tag
) < 0)
88 if (IN_SET(tag
, ACL_USER
, ACL_GROUP
)) {
89 if (acl_calc_mask(acl_p
) < 0)
101 int add_base_acls_if_needed(acl_t
*acl_p
, const char *path
) {
104 bool have_user_obj
= false, have_group_obj
= false, have_other
= false;
106 _cleanup_(acl_freep
) acl_t basic
= NULL
;
110 for (r
= acl_get_entry(*acl_p
, ACL_FIRST_ENTRY
, &i
);
112 r
= acl_get_entry(*acl_p
, ACL_NEXT_ENTRY
, &i
)) {
115 if (acl_get_tag_type(i
, &tag
) < 0)
118 if (tag
== ACL_USER_OBJ
)
119 have_user_obj
= true;
120 else if (tag
== ACL_GROUP_OBJ
)
121 have_group_obj
= true;
122 else if (tag
== ACL_OTHER
)
124 if (have_user_obj
&& have_group_obj
&& have_other
)
134 basic
= acl_from_mode(st
.st_mode
);
138 for (r
= acl_get_entry(basic
, ACL_FIRST_ENTRY
, &i
);
140 r
= acl_get_entry(basic
, ACL_NEXT_ENTRY
, &i
)) {
144 if (acl_get_tag_type(i
, &tag
) < 0)
147 if ((tag
== ACL_USER_OBJ
&& have_user_obj
) ||
148 (tag
== ACL_GROUP_OBJ
&& have_group_obj
) ||
149 (tag
== ACL_OTHER
&& have_other
))
152 r
= acl_create_entry(acl_p
, &dst
);
156 r
= acl_copy_entry(dst
, i
);
165 int acl_search_groups(const char *path
, char ***ret_groups
) {
166 _cleanup_strv_free_
char **g
= NULL
;
167 _cleanup_(acl_free
) acl_t acl
= NULL
;
174 acl
= acl_get_file(path
, ACL_TYPE_DEFAULT
);
178 r
= acl_get_entry(acl
, ACL_FIRST_ENTRY
, &entry
);
180 _cleanup_(acl_free_gid_tpp
) gid_t
*gid
= NULL
;
188 if (acl_get_tag_type(entry
, &tag
) < 0)
191 if (tag
!= ACL_GROUP
)
194 gid
= acl_get_qualifier(entry
);
198 if (in_gid(*gid
) > 0) {
208 name
= gid_to_name(*gid
);
212 r
= strv_consume(&g
, name
);
218 r
= acl_get_entry(acl
, ACL_NEXT_ENTRY
, &entry
);
229 int parse_acl(const char *text
, acl_t
*acl_access
, acl_t
*acl_default
, bool want_mask
) {
230 _cleanup_free_
char **a
= NULL
, **d
= NULL
; /* strings are not be freed */
231 _cleanup_strv_free_
char **split
;
234 _cleanup_(acl_freep
) acl_t a_acl
= NULL
, d_acl
= NULL
;
236 split
= strv_split(text
, ",");
240 STRV_FOREACH(entry
, split
) {
243 p
= startswith(*entry
, "default:");
245 p
= startswith(*entry
, "d:");
248 r
= strv_push(&d
, p
);
250 r
= strv_push(&a
, *entry
);
255 if (!strv_isempty(a
)) {
256 _cleanup_free_
char *join
;
258 join
= strv_join(a
, ",");
262 a_acl
= acl_from_text(join
);
267 r
= calc_acl_mask_if_needed(&a_acl
);
273 if (!strv_isempty(d
)) {
274 _cleanup_free_
char *join
;
276 join
= strv_join(d
, ",");
280 d_acl
= acl_from_text(join
);
285 r
= calc_acl_mask_if_needed(&d_acl
);
292 *acl_default
= d_acl
;
293 a_acl
= d_acl
= NULL
;
298 static int acl_entry_equal(acl_entry_t a
, acl_entry_t b
) {
299 acl_tag_t tag_a
, tag_b
;
301 if (acl_get_tag_type(a
, &tag_a
) < 0)
304 if (acl_get_tag_type(b
, &tag_b
) < 0)
315 /* can have only one of those */
318 _cleanup_(acl_free_uid_tpp
) uid_t
*uid_a
= NULL
, *uid_b
= NULL
;
320 uid_a
= acl_get_qualifier(a
);
324 uid_b
= acl_get_qualifier(b
);
328 return *uid_a
== *uid_b
;
331 _cleanup_(acl_free_gid_tpp
) gid_t
*gid_a
= NULL
, *gid_b
= NULL
;
333 gid_a
= acl_get_qualifier(a
);
337 gid_b
= acl_get_qualifier(b
);
341 return *gid_a
== *gid_b
;
344 assert_not_reached("Unknown acl tag type");
348 static int find_acl_entry(acl_t acl
, acl_entry_t entry
, acl_entry_t
*out
) {
352 for (r
= acl_get_entry(acl
, ACL_FIRST_ENTRY
, &i
);
354 r
= acl_get_entry(acl
, ACL_NEXT_ENTRY
, &i
)) {
356 r
= acl_entry_equal(i
, entry
);
369 int acls_for_file(const char *path
, acl_type_t type
, acl_t
new, acl_t
*acl
) {
370 _cleanup_(acl_freep
) acl_t old
;
374 old
= acl_get_file(path
, type
);
378 for (r
= acl_get_entry(new, ACL_FIRST_ENTRY
, &i
);
380 r
= acl_get_entry(new, ACL_NEXT_ENTRY
, &i
)) {
384 r
= find_acl_entry(old
, i
, &j
);
388 if (acl_create_entry(&old
, &j
) < 0)
391 if (acl_copy_entry(j
, i
) < 0)