]>
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 "string-util.h"
30 int acl_find_uid(acl_t acl
, uid_t uid
, acl_entry_t
*entry
) {
37 for (r
= acl_get_entry(acl
, ACL_FIRST_ENTRY
, &i
);
39 r
= acl_get_entry(acl
, ACL_NEXT_ENTRY
, &i
)) {
45 if (acl_get_tag_type(i
, &tag
) < 0)
51 u
= acl_get_qualifier(i
);
69 int calc_acl_mask_if_needed(acl_t
*acl_p
) {
75 for (r
= acl_get_entry(*acl_p
, ACL_FIRST_ENTRY
, &i
);
77 r
= acl_get_entry(*acl_p
, ACL_NEXT_ENTRY
, &i
)) {
80 if (acl_get_tag_type(i
, &tag
) < 0)
86 if (IN_SET(tag
, ACL_USER
, ACL_GROUP
)) {
87 if (acl_calc_mask(acl_p
) < 0)
99 int add_base_acls_if_needed(acl_t
*acl_p
, const char *path
) {
102 bool have_user_obj
= false, have_group_obj
= false, have_other
= false;
104 _cleanup_(acl_freep
) acl_t basic
= NULL
;
108 for (r
= acl_get_entry(*acl_p
, ACL_FIRST_ENTRY
, &i
);
110 r
= acl_get_entry(*acl_p
, ACL_NEXT_ENTRY
, &i
)) {
113 if (acl_get_tag_type(i
, &tag
) < 0)
116 if (tag
== ACL_USER_OBJ
)
117 have_user_obj
= true;
118 else if (tag
== ACL_GROUP_OBJ
)
119 have_group_obj
= true;
120 else if (tag
== ACL_OTHER
)
122 if (have_user_obj
&& have_group_obj
&& have_other
)
132 basic
= acl_from_mode(st
.st_mode
);
136 for (r
= acl_get_entry(basic
, ACL_FIRST_ENTRY
, &i
);
138 r
= acl_get_entry(basic
, ACL_NEXT_ENTRY
, &i
)) {
142 if (acl_get_tag_type(i
, &tag
) < 0)
145 if ((tag
== ACL_USER_OBJ
&& have_user_obj
) ||
146 (tag
== ACL_GROUP_OBJ
&& have_group_obj
) ||
147 (tag
== ACL_OTHER
&& have_other
))
150 r
= acl_create_entry(acl_p
, &dst
);
154 r
= acl_copy_entry(dst
, i
);
163 int acl_search_groups(const char *path
, char ***ret_groups
) {
164 _cleanup_strv_free_
char **g
= NULL
;
165 _cleanup_(acl_free
) acl_t acl
= NULL
;
172 acl
= acl_get_file(path
, ACL_TYPE_DEFAULT
);
176 r
= acl_get_entry(acl
, ACL_FIRST_ENTRY
, &entry
);
178 _cleanup_(acl_free_gid_tpp
) gid_t
*gid
= NULL
;
186 if (acl_get_tag_type(entry
, &tag
) < 0)
189 if (tag
!= ACL_GROUP
)
192 gid
= acl_get_qualifier(entry
);
196 if (in_gid(*gid
) > 0) {
206 name
= gid_to_name(*gid
);
210 r
= strv_consume(&g
, name
);
216 r
= acl_get_entry(acl
, ACL_NEXT_ENTRY
, &entry
);
227 int parse_acl(const char *text
, acl_t
*acl_access
, acl_t
*acl_default
, bool want_mask
) {
228 _cleanup_free_
char **a
= NULL
, **d
= NULL
; /* strings are not be freed */
229 _cleanup_strv_free_
char **split
;
232 _cleanup_(acl_freep
) acl_t a_acl
= NULL
, d_acl
= NULL
;
234 split
= strv_split(text
, ",");
238 STRV_FOREACH(entry
, split
) {
241 p
= startswith(*entry
, "default:");
243 p
= startswith(*entry
, "d:");
246 r
= strv_push(&d
, p
);
248 r
= strv_push(&a
, *entry
);
253 if (!strv_isempty(a
)) {
254 _cleanup_free_
char *join
;
256 join
= strv_join(a
, ",");
260 a_acl
= acl_from_text(join
);
265 r
= calc_acl_mask_if_needed(&a_acl
);
271 if (!strv_isempty(d
)) {
272 _cleanup_free_
char *join
;
274 join
= strv_join(d
, ",");
278 d_acl
= acl_from_text(join
);
283 r
= calc_acl_mask_if_needed(&d_acl
);
290 *acl_default
= d_acl
;
291 a_acl
= d_acl
= NULL
;
296 static int acl_entry_equal(acl_entry_t a
, acl_entry_t b
) {
297 acl_tag_t tag_a
, tag_b
;
299 if (acl_get_tag_type(a
, &tag_a
) < 0)
302 if (acl_get_tag_type(b
, &tag_b
) < 0)
313 /* can have only one of those */
316 _cleanup_(acl_free_uid_tpp
) uid_t
*uid_a
= NULL
, *uid_b
= NULL
;
318 uid_a
= acl_get_qualifier(a
);
322 uid_b
= acl_get_qualifier(b
);
326 return *uid_a
== *uid_b
;
329 _cleanup_(acl_free_gid_tpp
) gid_t
*gid_a
= NULL
, *gid_b
= NULL
;
331 gid_a
= acl_get_qualifier(a
);
335 gid_b
= acl_get_qualifier(b
);
339 return *gid_a
== *gid_b
;
342 assert_not_reached("Unknown acl tag type");
346 static int find_acl_entry(acl_t acl
, acl_entry_t entry
, acl_entry_t
*out
) {
350 for (r
= acl_get_entry(acl
, ACL_FIRST_ENTRY
, &i
);
352 r
= acl_get_entry(acl
, ACL_NEXT_ENTRY
, &i
)) {
354 r
= acl_entry_equal(i
, entry
);
367 int acls_for_file(const char *path
, acl_type_t type
, acl_t
new, acl_t
*acl
) {
368 _cleanup_(acl_freep
) acl_t old
;
372 old
= acl_get_file(path
, type
);
376 for (r
= acl_get_entry(new, ACL_FIRST_ENTRY
, &i
);
378 r
= acl_get_entry(new, ACL_NEXT_ENTRY
, &i
)) {
382 r
= find_acl_entry(old
, i
, &j
);
386 if (acl_create_entry(&old
, &j
) < 0)
389 if (acl_copy_entry(j
, i
) < 0)