Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/posix1e/acl_from_text_nfs4.c
39476 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2008, 2009 Edward Tomasz NapieraƂa <[email protected]>
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <unistd.h>
31
#include <errno.h>
32
#include <assert.h>
33
#include <string.h>
34
#include <pwd.h>
35
#include <grp.h>
36
#include <ctype.h>
37
#include <err.h>
38
#include <sys/syscall.h>
39
#include <sys/types.h>
40
#include <sys/acl.h>
41
42
#include "acl_support.h"
43
44
#define MAX_ENTRY_LENGTH 512
45
46
/*
47
* Parse the tag field of ACL entry passed as "str". If qualifier
48
* needs to follow, then the variable referenced by "need_qualifier"
49
* is set to 1, otherwise it's set to 0.
50
*/
51
static int
52
parse_tag(const char *str, acl_entry_t entry, int *need_qualifier)
53
{
54
55
assert(need_qualifier != NULL);
56
*need_qualifier = 0;
57
58
if (strcmp(str, "owner@") == 0)
59
return (acl_set_tag_type(entry, ACL_USER_OBJ));
60
if (strcmp(str, "group@") == 0)
61
return (acl_set_tag_type(entry, ACL_GROUP_OBJ));
62
if (strcmp(str, "everyone@") == 0)
63
return (acl_set_tag_type(entry, ACL_EVERYONE));
64
65
*need_qualifier = 1;
66
67
if (strcmp(str, "user") == 0 || strcmp(str, "u") == 0)
68
return (acl_set_tag_type(entry, ACL_USER));
69
if (strcmp(str, "group") == 0 || strcmp(str, "g") == 0)
70
return (acl_set_tag_type(entry, ACL_GROUP));
71
72
warnx("malformed ACL: invalid \"tag\" field");
73
74
return (-1);
75
}
76
77
/*
78
* Parse the qualifier field of ACL entry passed as "str".
79
* If user or group name cannot be resolved, then the variable
80
* referenced by "need_qualifier" is set to 1; it will be checked
81
* later to figure out whether the appended_id is required.
82
*/
83
static int
84
parse_qualifier(char *str, acl_entry_t entry, int *need_qualifier)
85
{
86
int qualifier_length, error;
87
uid_t id;
88
acl_tag_t tag;
89
90
assert(need_qualifier != NULL);
91
*need_qualifier = 0;
92
93
qualifier_length = strlen(str);
94
95
if (qualifier_length == 0) {
96
warnx("malformed ACL: empty \"qualifier\" field");
97
return (-1);
98
}
99
100
error = acl_get_tag_type(entry, &tag);
101
if (error)
102
return (error);
103
104
error = _acl_name_to_id(tag, str, &id);
105
if (error) {
106
*need_qualifier = 1;
107
return (0);
108
}
109
110
return (acl_set_qualifier(entry, &id));
111
}
112
113
static int
114
parse_access_mask(char *str, acl_entry_t entry)
115
{
116
int error;
117
acl_perm_t perm;
118
119
error = _nfs4_parse_access_mask(str, &perm);
120
if (error)
121
return (error);
122
123
error = acl_set_permset(entry, &perm);
124
125
return (error);
126
}
127
128
static int
129
parse_flags(char *str, acl_entry_t entry)
130
{
131
int error;
132
acl_flag_t flags;
133
134
error = _nfs4_parse_flags(str, &flags);
135
if (error)
136
return (error);
137
138
error = acl_set_flagset_np(entry, &flags);
139
140
return (error);
141
}
142
143
static int
144
parse_entry_type(const char *str, acl_entry_t entry)
145
{
146
147
if (strcmp(str, "allow") == 0)
148
return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_ALLOW));
149
if (strcmp(str, "deny") == 0)
150
return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_DENY));
151
if (strcmp(str, "audit") == 0)
152
return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_AUDIT));
153
if (strcmp(str, "alarm") == 0)
154
return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_ALARM));
155
156
warnx("malformed ACL: invalid \"type\" field");
157
158
return (-1);
159
}
160
161
static int
162
parse_appended_id(char *str, acl_entry_t entry)
163
{
164
int qualifier_length;
165
char *end;
166
id_t id;
167
168
qualifier_length = strlen(str);
169
if (qualifier_length == 0) {
170
warnx("malformed ACL: \"appended id\" field present, "
171
"but empty");
172
return (-1);
173
}
174
175
id = strtod(str, &end);
176
if (end - str != qualifier_length) {
177
warnx("malformed ACL: appended id is not a number");
178
return (-1);
179
}
180
181
return (acl_set_qualifier(entry, &id));
182
}
183
184
static int
185
number_of_colons(const char *str)
186
{
187
int count = 0;
188
189
while (*str != '\0') {
190
if (*str == ':')
191
count++;
192
193
str++;
194
}
195
196
return (count);
197
}
198
199
int
200
_nfs4_acl_entry_from_text(acl_t aclp, char *str)
201
{
202
int error, need_qualifier;
203
acl_entry_t entry;
204
char *field, *qualifier_field;
205
206
error = acl_create_entry(&aclp, &entry);
207
if (error)
208
return (error);
209
210
assert(_entry_brand(entry) == ACL_BRAND_NFS4);
211
212
if (str == NULL)
213
goto truncated_entry;
214
field = strsep(&str, ":");
215
216
field = string_skip_whitespace(field);
217
if ((*field == '\0') && (!str)) {
218
/*
219
* Is an entirely comment line, skip to next
220
* comma.
221
*/
222
return (0);
223
}
224
225
error = parse_tag(field, entry, &need_qualifier);
226
if (error)
227
goto malformed_field;
228
229
if (need_qualifier) {
230
if (str == NULL)
231
goto truncated_entry;
232
qualifier_field = field = strsep(&str, ":");
233
error = parse_qualifier(field, entry, &need_qualifier);
234
if (error)
235
goto malformed_field;
236
}
237
238
if (str == NULL)
239
goto truncated_entry;
240
field = strsep(&str, ":");
241
error = parse_access_mask(field, entry);
242
if (error)
243
goto malformed_field;
244
245
if (str == NULL)
246
goto truncated_entry;
247
/* Do we have "flags" field? */
248
if (number_of_colons(str) > 0) {
249
field = strsep(&str, ":");
250
error = parse_flags(field, entry);
251
if (error)
252
goto malformed_field;
253
}
254
255
if (str == NULL)
256
goto truncated_entry;
257
field = strsep(&str, ":");
258
error = parse_entry_type(field, entry);
259
if (error)
260
goto malformed_field;
261
262
if (need_qualifier) {
263
if (str == NULL) {
264
warnx("malformed ACL: unknown user or group name "
265
"\"%s\"", qualifier_field);
266
goto truncated_entry;
267
}
268
269
error = parse_appended_id(str, entry);
270
if (error)
271
goto malformed_field;
272
}
273
274
return (0);
275
276
truncated_entry:
277
malformed_field:
278
acl_delete_entry(aclp, entry);
279
errno = EINVAL;
280
return (-1);
281
}
282
283