Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/fs/nfs/nfs_commonacl.c
107228 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2009 Rick Macklem, University of Guelph
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
* SUCH DAMAGE.
27
*
28
*/
29
30
#include <sys/cdefs.h>
31
#include <fs/nfs/nfsport.h>
32
33
extern int nfsrv_useacl;
34
35
static int nfsrv_acemasktoperm(u_int32_t acetype, u_int32_t mask, int owner,
36
__enum_uint8(vtype) type, acl_perm_t *permp);
37
38
/*
39
* Handle xdr for an NFSv4 ace.
40
*/
41
int
42
nfsrv_dissectace(struct nfsrv_descript *nd, struct acl_entry *acep,
43
bool server, int *aceerrp, int *acesizep)
44
{
45
u_int32_t *tl;
46
int len, gotid = 0, owner = 0, error = 0, aceerr = 0;
47
u_char *name, namestr[NFSV4_SMALLSTR + 1];
48
u_int32_t flag, mask, acetype;
49
gid_t gid;
50
uid_t uid;
51
52
*aceerrp = 0;
53
acep->ae_flags = 0;
54
NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
55
acetype = fxdr_unsigned(u_int32_t, *tl++);
56
flag = fxdr_unsigned(u_int32_t, *tl++);
57
mask = fxdr_unsigned(u_int32_t, *tl++);
58
len = fxdr_unsigned(int, *tl);
59
/*
60
* The RFCs do not specify a limit to the length of the "who", but
61
* NFSV4_OPAQUELIMIT (1024) should be sufficient.
62
*/
63
if (len < 0 || len > NFSV4_OPAQUELIMIT) {
64
error = NFSERR_BADXDR;
65
goto nfsmout;
66
} else if (len == 0) {
67
/* Netapp filers return a 0 length who for nil users */
68
acep->ae_tag = ACL_EVERYONE; /* Avoid panics. */
69
acep->ae_id = ACL_UNDEFINED_ID;
70
acep->ae_perm = (acl_perm_t)0;
71
acep->ae_entry_type = ACL_ENTRY_TYPE_DENY;
72
if (acesizep)
73
*acesizep = 4 * NFSX_UNSIGNED;
74
error = 0;
75
goto nfsmout;
76
}
77
if (len > NFSV4_SMALLSTR)
78
name = malloc(len + 1, M_NFSSTRING, M_WAITOK);
79
else
80
name = namestr;
81
error = nfsrv_mtostr(nd, name, len);
82
if (error) {
83
if (len > NFSV4_SMALLSTR)
84
free(name, M_NFSSTRING);
85
goto nfsmout;
86
}
87
if (len == 6) {
88
if (!NFSBCMP(name, "OWNER@", 6)) {
89
acep->ae_tag = ACL_USER_OBJ;
90
acep->ae_id = ACL_UNDEFINED_ID;
91
owner = 1;
92
gotid = 1;
93
} else if (!NFSBCMP(name, "GROUP@", 6)) {
94
acep->ae_tag = ACL_GROUP_OBJ;
95
acep->ae_id = ACL_UNDEFINED_ID;
96
gotid = 1;
97
}
98
} else if (len == 9 && !NFSBCMP(name, "EVERYONE@", 9)) {
99
acep->ae_tag = ACL_EVERYONE;
100
acep->ae_id = ACL_UNDEFINED_ID;
101
gotid = 1;
102
}
103
if (gotid == 0) {
104
if (flag & NFSV4ACE_IDENTIFIERGROUP) {
105
acep->ae_tag = ACL_GROUP;
106
aceerr = nfsv4_strtogid(nd, name, len, &gid);
107
if (aceerr == 0)
108
acep->ae_id = (uid_t)gid;
109
} else {
110
acep->ae_tag = ACL_USER;
111
aceerr = nfsv4_strtouid(nd, name, len, &uid);
112
if (aceerr == 0)
113
acep->ae_id = uid;
114
}
115
}
116
if (len > NFSV4_SMALLSTR)
117
free(name, M_NFSSTRING);
118
119
if (aceerr == 0) {
120
/*
121
* Handle the flags.
122
*/
123
flag &= ~NFSV4ACE_IDENTIFIERGROUP;
124
if (flag & NFSV4ACE_FILEINHERIT) {
125
flag &= ~NFSV4ACE_FILEINHERIT;
126
acep->ae_flags |= ACL_ENTRY_FILE_INHERIT;
127
}
128
if (flag & NFSV4ACE_DIRECTORYINHERIT) {
129
flag &= ~NFSV4ACE_DIRECTORYINHERIT;
130
acep->ae_flags |= ACL_ENTRY_DIRECTORY_INHERIT;
131
}
132
if (flag & NFSV4ACE_NOPROPAGATEINHERIT) {
133
flag &= ~NFSV4ACE_NOPROPAGATEINHERIT;
134
acep->ae_flags |= ACL_ENTRY_NO_PROPAGATE_INHERIT;
135
}
136
if (flag & NFSV4ACE_INHERITONLY) {
137
flag &= ~NFSV4ACE_INHERITONLY;
138
acep->ae_flags |= ACL_ENTRY_INHERIT_ONLY;
139
}
140
if (flag & NFSV4ACE_SUCCESSFULACCESS) {
141
flag &= ~NFSV4ACE_SUCCESSFULACCESS;
142
acep->ae_flags |= ACL_ENTRY_SUCCESSFUL_ACCESS;
143
}
144
if (flag & NFSV4ACE_FAILEDACCESS) {
145
flag &= ~NFSV4ACE_FAILEDACCESS;
146
acep->ae_flags |= ACL_ENTRY_FAILED_ACCESS;
147
}
148
/*
149
* Set ae_entry_type.
150
*/
151
if (acetype == NFSV4ACE_ALLOWEDTYPE)
152
acep->ae_entry_type = ACL_ENTRY_TYPE_ALLOW;
153
else if (acetype == NFSV4ACE_DENIEDTYPE)
154
acep->ae_entry_type = ACL_ENTRY_TYPE_DENY;
155
else if (!server && acetype == NFSV4ACE_AUDITTYPE)
156
acep->ae_entry_type = ACL_ENTRY_TYPE_AUDIT;
157
else if (!server && acetype == NFSV4ACE_ALARMTYPE)
158
acep->ae_entry_type = ACL_ENTRY_TYPE_ALARM;
159
else
160
aceerr = NFSERR_ATTRNOTSUPP;
161
}
162
163
/*
164
* Now, check for unsupported flag bits.
165
*/
166
if (aceerr == 0 && flag != 0)
167
aceerr = NFSERR_ATTRNOTSUPP;
168
169
/*
170
* And turn the mask into perm bits.
171
*/
172
if (aceerr == 0)
173
aceerr = nfsrv_acemasktoperm(acetype, mask, owner, VREG,
174
&acep->ae_perm);
175
*aceerrp = aceerr;
176
if (acesizep)
177
*acesizep = NFSM_RNDUP(len) + (4 * NFSX_UNSIGNED);
178
error = 0;
179
nfsmout:
180
NFSEXITCODE(error);
181
return (error);
182
}
183
184
static acl_tag_t nfsv4_to_posixacltag[NFSV4_POSIXACL_TAG_OTHER + 1] =
185
{ ACL_UNDEFINED_TAG, ACL_USER_OBJ, ACL_USER, ACL_GROUP_OBJ,
186
ACL_GROUP, ACL_MASK, ACL_OTHER };
187
188
/*
189
* Handle xdr for a POSIX draft ace.
190
*/
191
int
192
nfsrv_dissectposixace(struct nfsrv_descript *nd, struct acl_entry *acep,
193
bool server, int *aceerrp, int *acesizep)
194
{
195
uint32_t *tl, tag;
196
int len, error = 0, aceerr = 0;
197
u_char *name, namestr[NFSV4_SMALLSTR + 1];
198
gid_t gid;
199
uid_t uid;
200
201
*aceerrp = 0;
202
NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_UNSIGNED);
203
tag = fxdr_unsigned(uint32_t, *tl++);
204
acep->ae_perm = fxdr_unsigned(acl_perm_t, *tl++);
205
len = fxdr_unsigned(int, *tl);
206
/*
207
* The RFCs do not specify a limit to the length of the "who", but
208
* NFSV4_OPAQUELIMIT (1024) should be sufficient.
209
*/
210
if (len < 0 || len > NFSV4_OPAQUELIMIT) {
211
error = NFSERR_BADXDR;
212
goto nfsmout;
213
}
214
if (tag < NFSV4_POSIXACL_TAG_USER_OBJ ||
215
tag > NFSV4_POSIXACL_TAG_OTHER) {
216
error = NFSERR_ATTRNOTSUPP;
217
goto nfsmout;
218
}
219
acep->ae_tag = nfsv4_to_posixacltag[tag];
220
if (len > NFSV4_SMALLSTR)
221
name = malloc(len + 1, M_NFSSTRING, M_WAITOK);
222
else
223
name = namestr;
224
if (len > 0)
225
error = nfsrv_mtostr(nd, name, len);
226
if (error != 0) {
227
if (len > NFSV4_SMALLSTR)
228
free(name, M_NFSSTRING);
229
goto nfsmout;
230
}
231
switch (acep->ae_tag) {
232
case ACL_USER:
233
aceerr = nfsv4_strtouid(nd, name, len, &uid);
234
if (aceerr == 0)
235
acep->ae_id = uid;
236
break;
237
case ACL_GROUP:
238
aceerr = nfsv4_strtogid(nd, name, len, &gid);
239
if (aceerr == 0)
240
acep->ae_id = (uid_t)gid;
241
break;
242
case ACL_USER_OBJ:
243
case ACL_GROUP_OBJ:
244
case ACL_MASK:
245
case ACL_OTHER:
246
break;
247
default:
248
aceerr = NFSERR_ATTRNOTSUPP;
249
}
250
if (len > NFSV4_SMALLSTR)
251
free(name, M_NFSSTRING);
252
253
*aceerrp = aceerr;
254
if (acesizep != NULL)
255
*acesizep = NFSM_RNDUP(len) + (3 * NFSX_UNSIGNED);
256
error = 0;
257
nfsmout:
258
NFSEXITCODE(error);
259
return (error);
260
}
261
262
/*
263
* Turn an NFSv4 ace mask into R/W/X flag bits.
264
*/
265
static int
266
nfsrv_acemasktoperm(u_int32_t acetype, u_int32_t mask, int owner,
267
__enum_uint8(vtype) type, acl_perm_t *permp)
268
{
269
acl_perm_t perm = 0x0;
270
int error = 0;
271
272
if (mask & NFSV4ACE_READDATA) {
273
mask &= ~NFSV4ACE_READDATA;
274
perm |= ACL_READ_DATA;
275
}
276
if (mask & NFSV4ACE_LISTDIRECTORY) {
277
mask &= ~NFSV4ACE_LISTDIRECTORY;
278
perm |= ACL_LIST_DIRECTORY;
279
}
280
if (mask & NFSV4ACE_WRITEDATA) {
281
mask &= ~NFSV4ACE_WRITEDATA;
282
perm |= ACL_WRITE_DATA;
283
}
284
if (mask & NFSV4ACE_ADDFILE) {
285
mask &= ~NFSV4ACE_ADDFILE;
286
perm |= ACL_ADD_FILE;
287
}
288
if (mask & NFSV4ACE_APPENDDATA) {
289
mask &= ~NFSV4ACE_APPENDDATA;
290
perm |= ACL_APPEND_DATA;
291
}
292
if (mask & NFSV4ACE_ADDSUBDIRECTORY) {
293
mask &= ~NFSV4ACE_ADDSUBDIRECTORY;
294
perm |= ACL_ADD_SUBDIRECTORY;
295
}
296
if (mask & NFSV4ACE_READNAMEDATTR) {
297
mask &= ~NFSV4ACE_READNAMEDATTR;
298
perm |= ACL_READ_NAMED_ATTRS;
299
}
300
if (mask & NFSV4ACE_WRITENAMEDATTR) {
301
mask &= ~NFSV4ACE_WRITENAMEDATTR;
302
perm |= ACL_WRITE_NAMED_ATTRS;
303
}
304
if (mask & NFSV4ACE_EXECUTE) {
305
mask &= ~NFSV4ACE_EXECUTE;
306
perm |= ACL_EXECUTE;
307
}
308
if (mask & NFSV4ACE_SEARCH) {
309
mask &= ~NFSV4ACE_SEARCH;
310
perm |= ACL_EXECUTE;
311
}
312
if (mask & NFSV4ACE_DELETECHILD) {
313
mask &= ~NFSV4ACE_DELETECHILD;
314
perm |= ACL_DELETE_CHILD;
315
}
316
if (mask & NFSV4ACE_READATTRIBUTES) {
317
mask &= ~NFSV4ACE_READATTRIBUTES;
318
perm |= ACL_READ_ATTRIBUTES;
319
}
320
if (mask & NFSV4ACE_WRITEATTRIBUTES) {
321
mask &= ~NFSV4ACE_WRITEATTRIBUTES;
322
perm |= ACL_WRITE_ATTRIBUTES;
323
}
324
if (mask & NFSV4ACE_DELETE) {
325
mask &= ~NFSV4ACE_DELETE;
326
perm |= ACL_DELETE;
327
}
328
if (mask & NFSV4ACE_READACL) {
329
mask &= ~NFSV4ACE_READACL;
330
perm |= ACL_READ_ACL;
331
}
332
if (mask & NFSV4ACE_WRITEACL) {
333
mask &= ~NFSV4ACE_WRITEACL;
334
perm |= ACL_WRITE_ACL;
335
}
336
if (mask & NFSV4ACE_WRITEOWNER) {
337
mask &= ~NFSV4ACE_WRITEOWNER;
338
perm |= ACL_WRITE_OWNER;
339
}
340
if (mask & NFSV4ACE_SYNCHRONIZE) {
341
mask &= ~NFSV4ACE_SYNCHRONIZE;
342
perm |= ACL_SYNCHRONIZE;
343
}
344
if (mask != 0) {
345
error = NFSERR_ATTRNOTSUPP;
346
goto out;
347
}
348
*permp = perm;
349
350
out:
351
NFSEXITCODE(error);
352
return (error);
353
}
354
355
/* local functions */
356
static int nfsrv_buildace(struct nfsrv_descript *, u_char *, int,
357
__enum_uint8(vtype), int, int, struct acl_entry *);
358
static int nfsrv_buildposixace(struct nfsrv_descript *, u_char *, int,
359
struct acl_entry *);
360
361
/*
362
* This function builds an NFSv4 ace.
363
*/
364
static int
365
nfsrv_buildace(struct nfsrv_descript *nd, u_char *name, int namelen,
366
__enum_uint8(vtype) type, int group, int owner, struct acl_entry *ace)
367
{
368
u_int32_t *tl, aceflag = 0x0, acemask = 0x0, acetype;
369
int full_len;
370
371
full_len = NFSM_RNDUP(namelen);
372
NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED + full_len);
373
374
/*
375
* Fill in the ace type.
376
*/
377
if (ace->ae_entry_type & ACL_ENTRY_TYPE_ALLOW)
378
acetype = NFSV4ACE_ALLOWEDTYPE;
379
else if (ace->ae_entry_type & ACL_ENTRY_TYPE_DENY)
380
acetype = NFSV4ACE_DENIEDTYPE;
381
else if (ace->ae_entry_type & ACL_ENTRY_TYPE_AUDIT)
382
acetype = NFSV4ACE_AUDITTYPE;
383
else
384
acetype = NFSV4ACE_ALARMTYPE;
385
*tl++ = txdr_unsigned(acetype);
386
387
/*
388
* Set the flag bits from the ACL.
389
*/
390
if (ace->ae_flags & ACL_ENTRY_FILE_INHERIT)
391
aceflag |= NFSV4ACE_FILEINHERIT;
392
if (ace->ae_flags & ACL_ENTRY_DIRECTORY_INHERIT)
393
aceflag |= NFSV4ACE_DIRECTORYINHERIT;
394
if (ace->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT)
395
aceflag |= NFSV4ACE_NOPROPAGATEINHERIT;
396
if (ace->ae_flags & ACL_ENTRY_INHERIT_ONLY)
397
aceflag |= NFSV4ACE_INHERITONLY;
398
if (ace->ae_flags & ACL_ENTRY_SUCCESSFUL_ACCESS)
399
aceflag |= NFSV4ACE_SUCCESSFULACCESS;
400
if (ace->ae_flags & ACL_ENTRY_FAILED_ACCESS)
401
aceflag |= NFSV4ACE_FAILEDACCESS;
402
if (group)
403
aceflag |= NFSV4ACE_IDENTIFIERGROUP;
404
*tl++ = txdr_unsigned(aceflag);
405
if (type == VDIR) {
406
if (ace->ae_perm & ACL_LIST_DIRECTORY)
407
acemask |= NFSV4ACE_LISTDIRECTORY;
408
if (ace->ae_perm & ACL_ADD_FILE)
409
acemask |= NFSV4ACE_ADDFILE;
410
if (ace->ae_perm & ACL_ADD_SUBDIRECTORY)
411
acemask |= NFSV4ACE_ADDSUBDIRECTORY;
412
if (ace->ae_perm & ACL_READ_NAMED_ATTRS)
413
acemask |= NFSV4ACE_READNAMEDATTR;
414
if (ace->ae_perm & ACL_WRITE_NAMED_ATTRS)
415
acemask |= NFSV4ACE_WRITENAMEDATTR;
416
if (ace->ae_perm & ACL_EXECUTE)
417
acemask |= NFSV4ACE_SEARCH;
418
if (ace->ae_perm & ACL_DELETE_CHILD)
419
acemask |= NFSV4ACE_DELETECHILD;
420
if (ace->ae_perm & ACL_READ_ATTRIBUTES)
421
acemask |= NFSV4ACE_READATTRIBUTES;
422
if (ace->ae_perm & ACL_WRITE_ATTRIBUTES)
423
acemask |= NFSV4ACE_WRITEATTRIBUTES;
424
if (ace->ae_perm & ACL_DELETE)
425
acemask |= NFSV4ACE_DELETE;
426
if (ace->ae_perm & ACL_READ_ACL)
427
acemask |= NFSV4ACE_READACL;
428
if (ace->ae_perm & ACL_WRITE_ACL)
429
acemask |= NFSV4ACE_WRITEACL;
430
if (ace->ae_perm & ACL_WRITE_OWNER)
431
acemask |= NFSV4ACE_WRITEOWNER;
432
if (ace->ae_perm & ACL_SYNCHRONIZE)
433
acemask |= NFSV4ACE_SYNCHRONIZE;
434
} else {
435
acemask = nfs_aceperm(ace->ae_perm);
436
}
437
*tl++ = txdr_unsigned(acemask);
438
*tl++ = txdr_unsigned(namelen);
439
if (full_len - namelen)
440
*(tl + (namelen / NFSX_UNSIGNED)) = 0x0;
441
NFSBCOPY(name, (caddr_t)tl, namelen);
442
return (full_len + 4 * NFSX_UNSIGNED);
443
}
444
445
/*
446
* Convert ae_perm to NFSv4 ACL acemask4 for regular files.
447
*/
448
uint32_t
449
nfs_aceperm(acl_perm_t ae_perm)
450
{
451
uint32_t acemask = 0x0;
452
453
if (ae_perm & ACL_READ_DATA)
454
acemask |= NFSV4ACE_READDATA;
455
if (ae_perm & ACL_WRITE_DATA)
456
acemask |= NFSV4ACE_WRITEDATA;
457
if (ae_perm & ACL_APPEND_DATA)
458
acemask |= NFSV4ACE_APPENDDATA;
459
if (ae_perm & ACL_READ_NAMED_ATTRS)
460
acemask |= NFSV4ACE_READNAMEDATTR;
461
if (ae_perm & ACL_WRITE_NAMED_ATTRS)
462
acemask |= NFSV4ACE_WRITENAMEDATTR;
463
if (ae_perm & ACL_EXECUTE)
464
acemask |= NFSV4ACE_EXECUTE;
465
if (ae_perm & ACL_READ_ATTRIBUTES)
466
acemask |= NFSV4ACE_READATTRIBUTES;
467
if (ae_perm & ACL_WRITE_ATTRIBUTES)
468
acemask |= NFSV4ACE_WRITEATTRIBUTES;
469
if (ae_perm & ACL_DELETE)
470
acemask |= NFSV4ACE_DELETE;
471
if (ae_perm & ACL_READ_ACL)
472
acemask |= NFSV4ACE_READACL;
473
if (ae_perm & ACL_WRITE_ACL)
474
acemask |= NFSV4ACE_WRITEACL;
475
if (ae_perm & ACL_WRITE_OWNER)
476
acemask |= NFSV4ACE_WRITEOWNER;
477
if (ae_perm & ACL_SYNCHRONIZE)
478
acemask |= NFSV4ACE_SYNCHRONIZE;
479
return (acemask);
480
}
481
482
/*
483
* This function builds a POSIX draft ace.
484
*/
485
static int
486
nfsrv_buildposixace(struct nfsrv_descript *nd, u_char *name, int namelen,
487
struct acl_entry *ace)
488
{
489
uint32_t *tl;
490
int full_len;
491
492
full_len = NFSM_RNDUP(namelen);
493
NFSM_BUILD(tl, uint32_t *, 3 * NFSX_UNSIGNED + full_len);
494
495
/*
496
* Fill in the ace tag.
497
*/
498
switch (ace->ae_tag) {
499
case ACL_USER_OBJ:
500
*tl++ = txdr_unsigned(NFSV4_POSIXACL_TAG_USER_OBJ);
501
break;
502
case ACL_USER:
503
*tl++ = txdr_unsigned(NFSV4_POSIXACL_TAG_USER);
504
break;
505
case ACL_GROUP_OBJ:
506
*tl++ = txdr_unsigned(NFSV4_POSIXACL_TAG_GROUP_OBJ);
507
break;
508
case ACL_GROUP:
509
*tl++ = txdr_unsigned(NFSV4_POSIXACL_TAG_GROUP);
510
break;
511
case ACL_MASK:
512
*tl++ = txdr_unsigned(NFSV4_POSIXACL_TAG_MASK);
513
break;
514
case ACL_OTHER:
515
*tl++ = txdr_unsigned(NFSV4_POSIXACL_TAG_OTHER);
516
break;
517
default:
518
printf("nfsrv_buildposixace: bad ae_tag 0x%x\n", ace->ae_tag);
519
*tl++ = txdr_unsigned(0);
520
}
521
522
/*
523
* Fill in the permission bits.
524
*/
525
*tl++ = txdr_unsigned(ace->ae_perm);
526
*tl++ = txdr_unsigned(namelen);
527
if (namelen > 0) {
528
if (full_len - namelen)
529
*(tl + (namelen / NFSX_UNSIGNED)) = 0x0;
530
memcpy(tl, name, namelen);
531
}
532
return (full_len + 3 * NFSX_UNSIGNED);
533
}
534
535
/*
536
* Build an NFSv4 ACL.
537
*/
538
int
539
nfsrv_buildacl(struct nfsrv_descript *nd, NFSACL_T *aclp, __enum_uint8(vtype) type,
540
NFSPROC_T *p)
541
{
542
int i, entrycnt = 0, retlen;
543
u_int32_t *entrycntp;
544
int isowner, isgroup, namelen, malloced;
545
u_char *name, namestr[NFSV4_SMALLSTR];
546
547
NFSM_BUILD(entrycntp, u_int32_t *, NFSX_UNSIGNED);
548
retlen = NFSX_UNSIGNED;
549
/*
550
* Loop through the acl entries, building each one.
551
*/
552
for (i = 0; i < aclp->acl_cnt; i++) {
553
isowner = isgroup = malloced = 0;
554
switch (aclp->acl_entry[i].ae_tag) {
555
case ACL_USER_OBJ:
556
isowner = 1;
557
name = "OWNER@";
558
namelen = 6;
559
break;
560
case ACL_GROUP_OBJ:
561
isgroup = 1;
562
name = "GROUP@";
563
namelen = 6;
564
break;
565
case ACL_EVERYONE:
566
name = "EVERYONE@";
567
namelen = 9;
568
break;
569
case ACL_USER:
570
name = namestr;
571
nfsv4_uidtostr(aclp->acl_entry[i].ae_id, &name,
572
&namelen);
573
if (name != namestr)
574
malloced = 1;
575
break;
576
case ACL_GROUP:
577
isgroup = 1;
578
name = namestr;
579
nfsv4_gidtostr((gid_t)aclp->acl_entry[i].ae_id, &name,
580
&namelen);
581
if (name != namestr)
582
malloced = 1;
583
break;
584
default:
585
continue;
586
}
587
retlen += nfsrv_buildace(nd, name, namelen, type, isgroup,
588
isowner, &aclp->acl_entry[i]);
589
entrycnt++;
590
if (malloced)
591
free(name, M_NFSSTRING);
592
}
593
*entrycntp = txdr_unsigned(entrycnt);
594
return (retlen);
595
}
596
597
/*
598
* Build a POSIX draft ACL.
599
*/
600
int
601
nfsrv_buildposixacl(struct nfsrv_descript *nd, NFSACL_T *aclp,
602
acl_type_t acltype)
603
{
604
int i, entrycnt = 0, retlen;
605
uint32_t *entrycntp;
606
unsigned int cnt;
607
int namelen;
608
u_char *name, namestr[NFSV4_SMALLSTR];
609
bool malloced;
610
611
NFSM_BUILD(entrycntp, uint32_t *, NFSX_UNSIGNED);
612
retlen = NFSX_UNSIGNED;
613
cnt = 0;
614
if (aclp != NULL)
615
cnt = aclp->acl_cnt;
616
/*
617
* Loop through the acl entries, building each one.
618
*/
619
for (i = 0; i < cnt; i++) {
620
malloced = false;
621
switch (aclp->acl_entry[i].ae_tag) {
622
case ACL_USER_OBJ:
623
case ACL_GROUP_OBJ:
624
case ACL_OTHER:
625
case ACL_MASK:
626
namelen = 0;
627
break;
628
case ACL_USER:
629
name = namestr;
630
nfsv4_uidtostr(aclp->acl_entry[i].ae_id, &name,
631
&namelen);
632
if (name != namestr)
633
malloced = true;
634
break;
635
case ACL_GROUP:
636
name = namestr;
637
nfsv4_gidtostr((gid_t)aclp->acl_entry[i].ae_id, &name,
638
&namelen);
639
if (name != namestr)
640
malloced = true;
641
break;
642
default:
643
continue;
644
}
645
retlen += nfsrv_buildposixace(nd, name, namelen,
646
&aclp->acl_entry[i]);
647
entrycnt++;
648
if (malloced)
649
free(name, M_NFSSTRING);
650
}
651
*entrycntp = txdr_unsigned(entrycnt);
652
return (retlen);
653
}
654
655
/*
656
* Compare two NFSv4 acls.
657
* Return 0 if they are the same, 1 if not the same.
658
*/
659
int
660
nfsrv_compareacl(NFSACL_T *aclp1, NFSACL_T *aclp2)
661
{
662
int i;
663
struct acl_entry *acep1, *acep2;
664
665
if (aclp1->acl_cnt != aclp2->acl_cnt)
666
return (1);
667
acep1 = aclp1->acl_entry;
668
acep2 = aclp2->acl_entry;
669
for (i = 0; i < aclp1->acl_cnt; i++) {
670
if (acep1->ae_tag != acep2->ae_tag)
671
return (1);
672
switch (acep1->ae_tag) {
673
case ACL_GROUP:
674
case ACL_USER:
675
if (acep1->ae_id != acep2->ae_id)
676
return (1);
677
/* fall through */
678
case ACL_USER_OBJ:
679
case ACL_GROUP_OBJ:
680
case ACL_OTHER:
681
if (acep1->ae_perm != acep2->ae_perm)
682
return (1);
683
}
684
acep1++;
685
acep2++;
686
}
687
return (0);
688
}
689
690