]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/acl-util.c
tmpfiles: add 'a' type to set ACLs
[thirdparty/systemd.git] / src / shared / acl-util.c
CommitLineData
f4b47811
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
478c8269 6 Copyright 2011,2013 Lennart Poettering
f4b47811
LP
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
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
f4b47811
LP
11 (at your option) any later version.
12
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
5430f7f2 16 Lesser General Public License for more details.
f4b47811 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
f4b47811
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <assert.h>
f4b47811
LP
23#include <errno.h>
24#include <stdbool.h>
25
79c07722 26#include "acl-util.h"
478c8269
ZJS
27#include "util.h"
28#include "strv.h"
f4b47811
LP
29
30int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) {
31 acl_entry_t i;
32 int found;
33
34 assert(acl);
35 assert(entry);
36
37 for (found = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
38 found > 0;
39 found = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
40
41 acl_tag_t tag;
42 uid_t *u;
43 bool b;
44
45 if (acl_get_tag_type(i, &tag) < 0)
46 return -errno;
47
48 if (tag != ACL_USER)
49 continue;
50
51 u = acl_get_qualifier(i);
52 if (!u)
53 return -errno;
54
55 b = *u == uid;
56 acl_free(u);
57
58 if (b) {
59 *entry = i;
60 return 1;
61 }
62 }
63
64 if (found < 0)
65 return -errno;
66
67 return 0;
68}
478c8269 69
23ad4dd8
JAS
70int calc_acl_mask_if_needed(acl_t *acl_p) {
71 acl_entry_t i;
72 int found;
73
74 assert(acl_p);
75
76 for (found = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i);
77 found > 0;
78 found = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
79
80 acl_tag_t tag;
81
82 if (acl_get_tag_type(i, &tag) < 0)
83 return -errno;
84
85 if (tag == ACL_MASK)
86 return 0;
87 }
88
89 if (found < 0)
90 return -errno;
91
92 if (acl_calc_mask(acl_p) < 0)
93 return -errno;
94
95 return 0;
96}
97
478c8269
ZJS
98int search_acl_groups(char*** dst, const char* path, bool* belong) {
99 acl_t acl;
100
101 assert(path);
102 assert(belong);
103
104 acl = acl_get_file(path, ACL_TYPE_DEFAULT);
105 if (acl) {
106 acl_entry_t entry;
107 int r;
108
109 r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
110 while (r > 0) {
111 acl_tag_t tag;
112 gid_t *gid;
113 char *name;
114
115 r = acl_get_tag_type(entry, &tag);
116 if (r < 0)
117 break;
118
119 if (tag != ACL_GROUP)
120 goto next;
121
122 gid = acl_get_qualifier(entry);
123 if (!gid)
124 break;
125
126 if (in_gid(*gid) > 0) {
127 *belong = true;
128 break;
129 }
130
131 name = gid_to_name(*gid);
132 if (!name) {
133 acl_free(acl);
134 return log_oom();
135 }
136
6e18964d 137 r = strv_consume(dst, name);
478c8269 138 if (r < 0) {
478c8269
ZJS
139 acl_free(acl);
140 return log_oom();
141 }
142
143 next:
144 r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
145 }
146
147 acl_free(acl);
148 }
149
150 return 0;
151}
f8eeeaf9
ZJS
152
153int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default) {
154 _cleanup_free_ char **a = NULL, **d = NULL; /* strings are not be freed */
155 _cleanup_strv_free_ char **split;
156 char **entry;
157 int r = -EINVAL;
158 _cleanup_(acl_freep) acl_t a_acl = NULL, d_acl = NULL;
159
160 split = strv_split(text, ",");
161 if (!split)
162 return log_oom();
163
164 STRV_FOREACH(entry, split) {
165 char *p;
166
167 p = startswith(*entry, "default:");
168 if (!p)
169 p = startswith(*entry, "d:");
170
171 if (p)
172 r = strv_push(&d, p);
173 else
174 r = strv_push(&a, *entry);
175 }
176 if (r < 0)
177 return r;
178
179 if (!strv_isempty(a)) {
180 _cleanup_free_ char *join;
181
182 join = strv_join(a, ",");
183 if (!join)
184 return -ENOMEM;
185
186 a_acl = acl_from_text(join);
187 if (!a_acl)
188 return -EINVAL;
189
190 r = calc_acl_mask_if_needed(&a_acl);
191 if (r < 0)
192 return r;
193 }
194
195 if (!strv_isempty(d)) {
196 _cleanup_free_ char *join;
197
198 join = strv_join(d, ",");
199 if (!join)
200 return -ENOMEM;
201
202 d_acl = acl_from_text(join);
203 if (!d_acl)
204 return -EINVAL;
205
206 r = calc_acl_mask_if_needed(&d_acl);
207 if (r < 0)
208 return r;
209 }
210
211 *acl_access = a_acl;
212 *acl_default = d_acl;
213 a_acl = d_acl = NULL;
214 return 0;
215}