1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/sid.h>
27 #include <sys/acl.h>
28 #include <acl/acl_common.h>
29 #include <smbsrv/smb_sid.h>
30 #include <smbsrv/smb_fsops.h>
31 #include <smbsrv/smb_idmap.h>
32 #include <smbsrv/smb_kproto.h>
33
34 #define ACE_FD_INHERIT_ACE (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE)
35
36 #define ZACE_IS_OWNER(zace) ((zace->a_flags & ACE_TYPE_FLAGS) == ACE_OWNER)
37 #define ZACE_IS_OWNGRP(zace) \
38 ((zace->a_flags & ACE_TYPE_FLAGS) == (ACE_IDENTIFIER_GROUP|ACE_GROUP))
39
40 #define ZACE_IS_USER(zace) \
41 (((zace->a_flags & ACE_TYPE_FLAGS) == 0) || (ZACE_IS_OWNER(zace)))
42 #define ZACE_IS_GROUP(zace) (zace->a_flags & ACE_IDENTIFIER_GROUP)
43 #define ZACE_IS_EVERYONE(zace) (zace->a_flags & ACE_EVERYONE)
44
45 #define ZACE_IS_PROPAGATE(zace) \
46 ((zace->a_flags & ACE_NO_PROPAGATE_INHERIT_ACE) == 0)
47
48 #define ZACE_IS_CREATOR_OWNER(zace) \
49 (ZACE_IS_USER(zace) && (zace->a_who == IDMAP_WK_CREATOR_OWNER_UID))
50
51 #define ZACE_IS_CREATOR_GROUP(zace) \
52 (ZACE_IS_GROUP(zace) && (zace->a_who == IDMAP_WK_CREATOR_GROUP_GID))
53
54 #define ZACE_IS_CREATOR(zace) \
55 (ZACE_IS_CREATOR_OWNER(zace) || ZACE_IS_CREATOR_GROUP(zace))
56
57 /*
58 * ACE groups within a DACL
59 *
60 * This is from lower to higher ACE order priority
61 */
62 #define SMB_AG_START 0
63 #define SMB_AG_ALW_INHRT 0
64 #define SMB_AG_DNY_INHRT 1
65 #define SMB_AG_ALW_DRCT 2
66 #define SMB_AG_DNY_DRCT 3
67 #define SMB_AG_NUM 4
68
69 #define DEFAULT_DACL_ACENUM 2
70 /*
71 * Default ACL:
72 * owner: full access
73 * SYSTEM: full access
74 */
75 static ace_t default_dacl[DEFAULT_DACL_ACENUM] = {
76 { (uid_t)-1, ACE_ALL_PERMS, 0, ACE_ACCESS_ALLOWED_ACE_TYPE },
77 { IDMAP_WK_LOCAL_SYSTEM_GID, ACE_ALL_PERMS, ACE_IDENTIFIER_GROUP,
78 ACE_ACCESS_ALLOWED_ACE_TYPE }
79 };
80
81 /*
82 * Note:
83 *
84 * smb_acl_xxx functions work with smb_acl_t which represents the CIFS format
85 * smb_fsacl_xxx functions work with acl_t which represents the Solaris native
86 * format
87 */
88
89 static idmap_stat smb_fsacl_getsids(smb_idmap_batch_t *, acl_t *);
90 static acl_t *smb_fsacl_null_empty(boolean_t);
91 static int smb_fsacl_inheritable(acl_t *, int);
92
93 static void smb_ace_inherit(ace_t *, ace_t *, int, uid_t, gid_t);
94 static boolean_t smb_ace_isvalid(smb_ace_t *, int);
95 static uint16_t smb_ace_len(smb_ace_t *);
96 static uint32_t smb_ace_mask_g2s(uint32_t);
97 static uint16_t smb_ace_flags_tozfs(uint8_t);
98 static uint8_t smb_ace_flags_fromzfs(uint16_t);
99 static boolean_t smb_ace_wellknown_update(const char *, ace_t *);
100
101 smb_acl_t *
smb_acl_alloc(uint8_t revision,uint16_t bsize,uint16_t acecnt)102 smb_acl_alloc(uint8_t revision, uint16_t bsize, uint16_t acecnt)
103 {
104 smb_acl_t *acl;
105 int size;
106
107 size = sizeof (smb_acl_t) + (acecnt * sizeof (smb_ace_t));
108 acl = kmem_zalloc(size, KM_SLEEP);
109 acl->sl_revision = revision;
110 acl->sl_bsize = bsize;
111 acl->sl_acecnt = acecnt;
112 acl->sl_aces = (smb_ace_t *)(acl + 1);
113
114 list_create(&acl->sl_sorted, sizeof (smb_ace_t),
115 offsetof(smb_ace_t, se_sln));
116 return (acl);
117 }
118
119 void
smb_acl_free(smb_acl_t * acl)120 smb_acl_free(smb_acl_t *acl)
121 {
122 int i, size;
123 void *ace;
124
125 if (acl == NULL)
126 return;
127
128 for (i = 0; i < acl->sl_acecnt; i++)
129 smb_sid_free(acl->sl_aces[i].se_sid);
130
131 while ((ace = list_head(&acl->sl_sorted)) != NULL)
132 list_remove(&acl->sl_sorted, ace);
133 list_destroy(&acl->sl_sorted);
134
135 size = sizeof (smb_acl_t) + (acl->sl_acecnt * sizeof (smb_ace_t));
136 kmem_free(acl, size);
137 }
138
139 /*
140 * smb_acl_len
141 *
142 * Returns the size of given ACL in bytes. Note that this
143 * is not an in-memory size, it's the ACL's size as it would
144 * appear on the wire
145 */
146 uint16_t
smb_acl_len(smb_acl_t * acl)147 smb_acl_len(smb_acl_t *acl)
148 {
149 return ((acl) ? acl->sl_bsize : 0);
150 }
151
152 boolean_t
smb_acl_isvalid(smb_acl_t * acl,int which_acl)153 smb_acl_isvalid(smb_acl_t *acl, int which_acl)
154 {
155 int i;
156
157 if (acl->sl_bsize < SMB_ACL_HDRSIZE)
158 return (B_FALSE);
159
160 if (acl->sl_revision != ACL_REVISION) {
161 /*
162 * we are rejecting ACLs with object-specific ACEs for now
163 */
164 return (B_FALSE);
165 }
166
167 for (i = 0; i < acl->sl_acecnt; i++) {
168 if (!smb_ace_isvalid(&acl->sl_aces[i], which_acl))
169 return (B_FALSE);
170 }
171
172 return (B_TRUE);
173 }
174
175 /*
176 * smb_acl_sort
177 *
178 * Sorts the given ACL in place if it needs to be sorted.
179 *
180 * The following is an excerpt from MSDN website.
181 *
182 * Order of ACEs in a DACL
183 *
184 * For Windows NT versions 4.0 and earlier, the preferred order of ACEs
185 * is simple: In a DACL, all access-denied ACEs should precede any
186 * access-allowed ACEs.
187 *
188 * For Windows 2000 or later, the proper order of ACEs is more complicated
189 * because of the introduction of object-specific ACEs and automatic
190 * inheritance.
191 *
192 * The following describes the preferred order:
193 *
194 * To ensure that noninherited ACEs have precedence over inherited ACEs,
195 * place all noninherited ACEs in a group before any inherited ACEs. This
196 * ordering ensures, for example, that a noninherited access-denied ACE
197 * is enforced regardless of any inherited ACE that allows access.
198 * Within the groups of noninherited ACEs and inherited ACEs, order ACEs
199 * according to ACE type, as the following shows:
200 * . Access-denied ACEs that apply to the object itself
201 * . Access-denied ACEs that apply to a subobject of the
202 * object, such as a property set or property
203 * . Access-allowed ACEs that apply to the object itself
204 * . Access-allowed ACEs that apply to a subobject of the object
205 *
206 * So, here is the desired ACE order
207 *
208 * deny-direct, allow-direct, deny-inherited, allow-inherited
209 *
210 * Of course, not all ACE types are required in an ACL.
211 */
212 void
smb_acl_sort(smb_acl_t * acl)213 smb_acl_sort(smb_acl_t *acl)
214 {
215 list_t ace_grps[SMB_AG_NUM];
216 list_t *alist;
217 smb_ace_t *ace;
218 uint8_t ace_flags;
219 int ag, i;
220
221 ASSERT(acl);
222
223 if (acl->sl_acecnt == 0) {
224 /*
225 * ACL with no entry is a valid ACL and it means
226 * no access for anybody.
227 */
228 return;
229 }
230
231 for (i = SMB_AG_START; i < SMB_AG_NUM; i++) {
232 list_create(&ace_grps[i], sizeof (smb_ace_t),
233 offsetof(smb_ace_t, se_sln));
234 }
235
236 for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; ++i, ace++) {
237 ace_flags = ace->se_hdr.se_flags;
238
239 switch (ace->se_hdr.se_type) {
240 case ACCESS_DENIED_ACE_TYPE:
241 ag = (ace_flags & INHERITED_ACE) ?
242 SMB_AG_DNY_INHRT : SMB_AG_DNY_DRCT;
243 break;
244
245 case ACCESS_ALLOWED_ACE_TYPE:
246 ag = (ace_flags & INHERITED_ACE) ?
247 SMB_AG_ALW_INHRT : SMB_AG_ALW_DRCT;
248 break;
249
250 default:
251 /*
252 * This is the lowest priority group so we put
253 * evertything unknown here.
254 */
255 ag = SMB_AG_ALW_INHRT;
256 break;
257 }
258
259 /* Add the ACE to the selected group */
260 list_insert_tail(&ace_grps[ag], ace);
261 }
262
263 /*
264 * start with highest priority ACE group and append
265 * the ACEs to the ACL.
266 */
267 for (i = SMB_AG_NUM - 1; i >= SMB_AG_START; i--) {
268 alist = &ace_grps[i];
269 while ((ace = list_head(alist)) != NULL) {
270 list_remove(alist, ace);
271 list_insert_tail(&acl->sl_sorted, ace);
272 }
273 list_destroy(alist);
274 }
275 }
276
277 /*
278 * smb_acl_from_zfs
279 *
280 * Converts given ZFS ACL to a Windows ACL.
281 *
282 * A pointer to allocated memory for the Win ACL will be
283 * returned upon successful conversion.
284 */
285 smb_acl_t *
smb_acl_from_zfs(acl_t * zacl)286 smb_acl_from_zfs(acl_t *zacl)
287 {
288 ace_t *zace;
289 int numaces;
290 smb_acl_t *acl;
291 smb_ace_t *ace;
292 smb_idmap_batch_t sib;
293 smb_idmap_t *sim;
294 idmap_stat idm_stat;
295
296 idm_stat = smb_idmap_batch_create(&sib, zacl->acl_cnt,
297 SMB_IDMAP_ID2SID);
298 if (idm_stat != IDMAP_SUCCESS)
299 return (NULL);
300
301 if (smb_fsacl_getsids(&sib, zacl) != IDMAP_SUCCESS) {
302 smb_idmap_batch_destroy(&sib);
303 return (NULL);
304 }
305
306 acl = smb_acl_alloc(ACL_REVISION, SMB_ACL_HDRSIZE, zacl->acl_cnt);
307
308 sim = sib.sib_maps;
309 for (numaces = 0, zace = zacl->acl_aclp;
310 numaces < zacl->acl_cnt;
311 zace++, numaces++, sim++) {
312 ASSERT(sim->sim_sid);
313 if (sim->sim_sid == NULL) {
314 smb_acl_free(acl);
315 acl = NULL;
316 break;
317 }
318
319 ace = &acl->sl_aces[numaces];
320 ace->se_hdr.se_type = zace->a_type;
321 ace->se_hdr.se_flags = smb_ace_flags_fromzfs(zace->a_flags);
322 ace->se_mask = zace->a_access_mask;
323 ace->se_sid = smb_sid_dup(sim->sim_sid);
324 ace->se_hdr.se_bsize = smb_ace_len(ace);
325
326 acl->sl_bsize += ace->se_hdr.se_bsize;
327 }
328
329 smb_idmap_batch_destroy(&sib);
330 return (acl);
331 }
332
333 /*
334 * smb_acl_to_zfs
335 *
336 * Converts given Windows ACL to a ZFS ACL.
337 *
338 * fs_acl will contain a pointer to the created ZFS ACL.
339 * The allocated memory should be freed by calling
340 * smb_fsacl_free().
341 *
342 * Since the output parameter, fs_acl, is allocated in this
343 * function, the caller has to make sure *fs_acl is NULL which
344 * means it's not pointing to any memory.
345 */
346 uint32_t
smb_acl_to_zfs(smb_acl_t * acl,uint32_t flags,int which_acl,acl_t ** fs_acl)347 smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl)
348 {
349 smb_ace_t *ace;
350 acl_t *zacl;
351 ace_t *zace;
352 smb_idmap_batch_t sib;
353 smb_idmap_t *sim;
354 idmap_stat idm_stat;
355 char *sidstr;
356 int i;
357
358 ASSERT(fs_acl);
359 ASSERT(*fs_acl == NULL);
360
361 if (acl && !smb_acl_isvalid(acl, which_acl))
362 return (NT_STATUS_INVALID_ACL);
363
364 if ((acl == NULL) || (acl->sl_acecnt == 0)) {
365 if (which_acl == SMB_DACL_SECINFO) {
366 *fs_acl = smb_fsacl_null_empty(acl == NULL);
367 }
368
369 return (NT_STATUS_SUCCESS);
370 }
371
372 idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt,
373 SMB_IDMAP_SID2ID);
374 if (idm_stat != IDMAP_SUCCESS)
375 return (NT_STATUS_INTERNAL_ERROR);
376
377 sidstr = kmem_alloc(SMB_SID_STRSZ, KM_SLEEP);
378 zacl = smb_fsacl_alloc(acl->sl_acecnt, flags);
379
380 zace = zacl->acl_aclp;
381 ace = acl->sl_aces;
382 sim = sib.sib_maps;
383
384 for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) {
385 zace->a_type = ace->se_hdr.se_type & ACE_ALL_TYPES;
386 zace->a_access_mask = smb_ace_mask_g2s(ace->se_mask);
387 zace->a_flags = smb_ace_flags_tozfs(ace->se_hdr.se_flags);
388 zace->a_who = (uid_t)-1;
389
390 smb_sid_tostr(ace->se_sid, sidstr);
391
392 if (!smb_ace_wellknown_update(sidstr, zace)) {
393 sim->sim_id = &zace->a_who;
394 idm_stat = smb_idmap_batch_getid(sib.sib_idmaph, sim,
395 ace->se_sid, SMB_IDMAP_UNKNOWN);
396
397 if (idm_stat != IDMAP_SUCCESS) {
398 kmem_free(sidstr, SMB_SID_STRSZ);
399 smb_fsacl_free(zacl);
400 smb_idmap_batch_destroy(&sib);
401 return (NT_STATUS_INTERNAL_ERROR);
402 }
403 }
404 }
405
406 kmem_free(sidstr, SMB_SID_STRSZ);
407
408 idm_stat = smb_idmap_batch_getmappings(&sib);
409 if (idm_stat != IDMAP_SUCCESS) {
410 smb_fsacl_free(zacl);
411 smb_idmap_batch_destroy(&sib);
412 return (NT_STATUS_NONE_MAPPED);
413 }
414
415 /*
416 * Set the ACEs group flag based on the type of ID returned.
417 */
418 zace = zacl->acl_aclp;
419 ace = acl->sl_aces;
420 sim = sib.sib_maps;
421 for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) {
422 if (zace->a_who == (uid_t)-1)
423 continue;
424
425 if (sim->sim_idtype == SMB_IDMAP_GROUP)
426 zace->a_flags |= ACE_IDENTIFIER_GROUP;
427 }
428
429 smb_idmap_batch_destroy(&sib);
430
431 *fs_acl = zacl;
432 return (NT_STATUS_SUCCESS);
433 }
434
435 static boolean_t
smb_ace_wellknown_update(const char * sid,ace_t * zace)436 smb_ace_wellknown_update(const char *sid, ace_t *zace)
437 {
438 struct {
439 char *sid;
440 uint16_t flags;
441 } map[] = {
442 { NT_WORLD_SIDSTR, ACE_EVERYONE },
443 { NT_BUILTIN_CURRENT_OWNER_SIDSTR, ACE_OWNER },
444 { NT_BUILTIN_CURRENT_GROUP_SIDSTR,
445 (ACE_GROUP | ACE_IDENTIFIER_GROUP) },
446 };
447
448 int i;
449
450 for (i = 0; i < (sizeof (map) / sizeof (map[0])); ++i) {
451 if (strcmp(sid, map[i].sid) == 0) {
452 zace->a_flags |= map[i].flags;
453 return (B_TRUE);
454 }
455 }
456
457 return (B_FALSE);
458 }
459
460 /*
461 * smb_fsacl_getsids
462 *
463 * Batch all the uid/gid in given ZFS ACL to get their corresponding SIDs.
464 */
465 static idmap_stat
smb_fsacl_getsids(smb_idmap_batch_t * sib,acl_t * zacl)466 smb_fsacl_getsids(smb_idmap_batch_t *sib, acl_t *zacl)
467 {
468 ace_t *zace;
469 idmap_stat idm_stat;
470 smb_idmap_t *sim;
471 uid_t id;
472 int i, idtype;
473
474 sim = sib->sib_maps;
475
476 for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt;
477 zace++, i++, sim++) {
478 switch (zace->a_flags & ACE_TYPE_FLAGS) {
479 case ACE_OWNER:
480 idtype = SMB_IDMAP_OWNERAT;
481 break;
482
483 case (ACE_GROUP | ACE_IDENTIFIER_GROUP):
484 /* owning group */
485 idtype = SMB_IDMAP_GROUPAT;
486 break;
487
488 case ACE_IDENTIFIER_GROUP:
489 /* regular group */
490 id = zace->a_who;
491 idtype = SMB_IDMAP_GROUP;
492 break;
493
494 case ACE_EVERYONE:
495 idtype = SMB_IDMAP_EVERYONE;
496 break;
497
498 default:
499 /* user entry */
500 id = zace->a_who;
501 idtype = SMB_IDMAP_USER;
502 }
503
504 idm_stat = smb_idmap_batch_getsid(sib->sib_idmaph, sim,
505 id, idtype);
506
507 if (idm_stat != IDMAP_SUCCESS) {
508 return (idm_stat);
509 }
510 }
511
512 idm_stat = smb_idmap_batch_getmappings(sib);
513 return (idm_stat);
514 }
515
516 /*
517 * smb_fsacl_null_empty
518 *
519 * NULL DACL means everyone full-access
520 * Empty DACL means everyone full-deny
521 *
522 * ZFS ACL must have at least one entry so smb server has
523 * to simulate the aforementioned expected behavior by adding
524 * an entry in case the requested DACL is null or empty. Adding
525 * a everyone full-deny entry has proved to be problematic in
526 * tests since a deny entry takes precedence over allow entries.
527 * So, instead of adding a everyone full-deny, an owner ACE with
528 * owner implicit permissions will be set.
529 */
530 static acl_t *
smb_fsacl_null_empty(boolean_t null)531 smb_fsacl_null_empty(boolean_t null)
532 {
533 acl_t *zacl;
534 ace_t *zace;
535
536 zacl = smb_fsacl_alloc(1, ACL_AUTO_INHERIT);
537 zace = zacl->acl_aclp;
538
539 zace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
540 if (null) {
541 zace->a_access_mask = ACE_ALL_PERMS;
542 zace->a_flags = ACE_EVERYONE;
543 } else {
544 zace->a_access_mask = ACE_READ_ACL | ACE_WRITE_ACL |
545 ACE_READ_ATTRIBUTES;
546 zace->a_flags = ACE_OWNER;
547 }
548
549 return (zacl);
550 }
551
552 /*
553 * FS ACL (acl_t) Functions
554 */
555 acl_t *
smb_fsacl_alloc(int acenum,int flags)556 smb_fsacl_alloc(int acenum, int flags)
557 {
558 acl_t *acl;
559
560 acl = acl_alloc(ACE_T);
561 acl->acl_cnt = acenum;
562 acl->acl_aclp = kmem_zalloc(acl->acl_entry_size * acenum, KM_SLEEP);
563 acl->acl_flags = flags;
564 return (acl);
565 }
566
567 void
smb_fsacl_free(acl_t * acl)568 smb_fsacl_free(acl_t *acl)
569 {
570 if (acl)
571 acl_free(acl);
572 }
573
574 /*
575 * smb_fsop_aclmerge
576 *
577 * smb_fsop_aclread/write routines which interact with filesystem
578 * work with single ACL. This routine merges given DACL and SACL
579 * which might have been created during CIFS to FS conversion into
580 * one single ACL.
581 */
582 acl_t *
smb_fsacl_merge(acl_t * dacl,acl_t * sacl)583 smb_fsacl_merge(acl_t *dacl, acl_t *sacl)
584 {
585 acl_t *acl;
586 int dacl_size;
587
588 ASSERT(dacl);
589 ASSERT(sacl);
590
591 acl = smb_fsacl_alloc(dacl->acl_cnt + sacl->acl_cnt, dacl->acl_flags);
592 dacl_size = dacl->acl_cnt * dacl->acl_entry_size;
593 bcopy(dacl->acl_aclp, acl->acl_aclp, dacl_size);
594 bcopy(sacl->acl_aclp, (char *)acl->acl_aclp + dacl_size,
595 sacl->acl_cnt * sacl->acl_entry_size);
596
597 return (acl);
598 }
599
600 /*
601 * smb_fsacl_split
602 *
603 * splits the given ACE_T ACL (zacl) to one or two ACLs (DACL/SACL) based on
604 * the 'which_acl' parameter. Note that output dacl/sacl parameters could be
605 * NULL even if they're specified in 'which_acl', which means the target
606 * doesn't have any access and/or audit ACEs.
607 */
608 void
smb_fsacl_split(acl_t * zacl,acl_t ** dacl,acl_t ** sacl,int which_acl)609 smb_fsacl_split(acl_t *zacl, acl_t **dacl, acl_t **sacl, int which_acl)
610 {
611 ace_t *zace;
612 ace_t *access_ace;
613 ace_t *audit_ace;
614 int naccess, naudit;
615 int get_dacl, get_sacl;
616 int i;
617
618 *dacl = *sacl = NULL;
619 naccess = naudit = 0;
620 get_dacl = (which_acl & SMB_DACL_SECINFO);
621 get_sacl = (which_acl & SMB_SACL_SECINFO);
622
623 for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) {
624 if (get_dacl && smb_ace_is_access(zace->a_type))
625 naccess++;
626 else if (get_sacl && smb_ace_is_audit(zace->a_type))
627 naudit++;
628 }
629
630 if (naccess) {
631 *dacl = smb_fsacl_alloc(naccess, zacl->acl_flags);
632 access_ace = (*dacl)->acl_aclp;
633 }
634
635 if (naudit) {
636 *sacl = smb_fsacl_alloc(naudit, zacl->acl_flags);
637 audit_ace = (*sacl)->acl_aclp;
638 }
639
640 for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) {
641 if (get_dacl && smb_ace_is_access(zace->a_type)) {
642 *access_ace = *zace;
643 access_ace++;
644 } else if (get_sacl && smb_ace_is_audit(zace->a_type)) {
645 *audit_ace = *zace;
646 audit_ace++;
647 }
648 }
649 }
650
651 /*
652 * ACE Inheritance Rules
653 *
654 * The system propagates inheritable ACEs to child objects according to a
655 * set of inheritance rules. The system places inherited ACEs in the child's
656 * DACL according to the preferred order of ACEs in a DACL. For Windows
657 * 2000 or later, the system sets the INHERITED_ACE flag in all inherited ACEs.
658 *
659 * The following table shows the ACEs inherited by container and noncontainer
660 * child objects for different combinations of inheritance flags. These
661 * inheritance rules work the same for both DACLs and SACLs.
662 *
663 * Parent ACE type Effect on Child ACL
664 * ----------------------- -------------------
665 * OBJECT_INHERIT_ACE only Noncontainer child objects:
666 * Inherited as an effective ACE.
667 * Container child objects:
668 * Containers inherit an inherit-only ACE
669 * unless the NO_PROPAGATE_INHERIT_ACE bit
670 * flag is also set.
671 *
672 * CONTAINER_INHERIT_ACE only Noncontainer child objects:
673 * No effect on the child object.
674 * Container child objects:
675 * The child object inherits an effective ACE.
676 * The inherited ACE is inheritable unless the
677 * NO_PROPAGATE_INHERIT_ACE bit flag is also set.
678 *
679 * CONTAINER_INHERIT_ACE and
680 * OBJECT_INHERIT_ACE Noncontainer child objects:
681 * Inherited as an effective ACE.
682 * Container child objects:
683 * The child object inherits an effective ACE.
684 * The inherited ACE is inheritable unless the
685 * NO_PROPAGATE_INHERIT_ACE bit flag is also set
686 *
687 * No inheritance flags set No effect on child container or noncontainer
688 * objects.
689 *
690 * If an inherited ACE is an effective ACE for the child object, the system
691 * maps any generic rights to the specific rights for the child object.
692 * Similarly, the system maps generic SIDs, such as CREATOR_OWNER, to the
693 * appropriate SID. If an inherited ACE is an inherit-only ACE, any generic
694 * rights or generic SIDs are left unchanged so that they can be mapped
695 * appropriately when the ACE is inherited by the next generation of child
696 * objects.
697 *
698 * For a case in which a container object inherits an ACE that is both
699 * effective on the container and inheritable by its descendants, the
700 * container may inherit two ACEs. This occurs if the inheritable ACE
701 * contains generic information. The container inherits an inherit-only
702 * ACE containing the generic information and an effective-only ACE in
703 * which the generic information has been mapped.
704 */
705
706 /*
707 * smb_fsacl_inherit
708 *
709 * Manufacture the inherited ACL from the given ACL considering
710 * the new object type (file/dir) specified by 'is_dir'. The
711 * returned ACL is used in smb_fsop_create/smb_fsop_mkdir functions.
712 * This function implements Windows inheritance rules explained above.
713 *
714 * Note that the in/out ACLs are ZFS ACLs not Windows ACLs
715 */
716 acl_t *
smb_fsacl_inherit(acl_t * dir_zacl,int is_dir,int which_acl,cred_t * cr)717 smb_fsacl_inherit(acl_t *dir_zacl, int is_dir, int which_acl, cred_t *cr)
718 {
719 boolean_t use_default = B_FALSE;
720 int num_inheritable = 0;
721 int numaces;
722 ace_t *dir_zace;
723 acl_t *new_zacl;
724 ace_t *new_zace;
725 ksid_t *owner_sid;
726 ksid_t *group_sid;
727 uid_t uid;
728 gid_t gid;
729
730 owner_sid = crgetsid(cr, KSID_OWNER);
731 group_sid = crgetsid(cr, KSID_GROUP);
732 ASSERT(owner_sid);
733 ASSERT(group_sid);
734 uid = owner_sid->ks_id;
735 gid = group_sid->ks_id;
736
737 num_inheritable = smb_fsacl_inheritable(dir_zacl, is_dir);
738
739 if (num_inheritable == 0) {
740 if (which_acl == SMB_DACL_SECINFO) {
741 /* No inheritable access ACEs -> default DACL */
742 num_inheritable = DEFAULT_DACL_ACENUM;
743 use_default = B_TRUE;
744 } else {
745 return (NULL);
746 }
747 }
748
749 new_zacl = smb_fsacl_alloc(num_inheritable, ACL_AUTO_INHERIT);
750 new_zace = new_zacl->acl_aclp;
751
752 if (use_default) {
753 bcopy(default_dacl, new_zacl->acl_aclp, sizeof (default_dacl));
754 new_zace->a_who = uid;
755 return (new_zacl);
756 }
757
758 for (numaces = 0, dir_zace = dir_zacl->acl_aclp;
759 numaces < dir_zacl->acl_cnt;
760 dir_zace++, numaces++) {
761 switch (dir_zace->a_flags & ACE_FD_INHERIT_ACE) {
762 case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE):
763 /*
764 * Files inherit an effective ACE.
765 *
766 * Dirs inherit an effective ACE.
767 * The inherited ACE is inheritable unless the
768 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set
769 */
770 smb_ace_inherit(dir_zace, new_zace, is_dir, uid, gid);
771 new_zace++;
772
773 if (is_dir && ZACE_IS_CREATOR(dir_zace) &&
774 (ZACE_IS_PROPAGATE(dir_zace))) {
775 *new_zace = *dir_zace;
776 new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
777 ACE_INHERITED_ACE);
778 new_zace++;
779 }
780 break;
781
782 case ACE_FILE_INHERIT_ACE:
783 /*
784 * Files inherit as an effective ACE.
785 *
786 * Dirs inherit an inherit-only ACE
787 * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit
788 * flag is also set.
789 */
790 if (is_dir == 0) {
791 smb_ace_inherit(dir_zace, new_zace, is_dir,
792 uid, gid);
793 new_zace++;
794 } else if (ZACE_IS_PROPAGATE(dir_zace)) {
795 *new_zace = *dir_zace;
796 new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
797 ACE_INHERITED_ACE);
798 new_zace++;
799 }
800 break;
801
802 case ACE_DIRECTORY_INHERIT_ACE:
803 /*
804 * No effect on files
805 *
806 * Dirs inherit an effective ACE.
807 * The inherited ACE is inheritable unless the
808 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set.
809 */
810 if (is_dir == 0)
811 break;
812
813 smb_ace_inherit(dir_zace, new_zace, is_dir, uid, gid);
814 new_zace++;
815
816 if (ZACE_IS_CREATOR(dir_zace) &&
817 (ZACE_IS_PROPAGATE(dir_zace))) {
818 *new_zace = *dir_zace;
819 new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
820 ACE_INHERITED_ACE);
821 new_zace++;
822 }
823
824 break;
825
826 default:
827 break;
828 }
829 }
830
831 return (new_zacl);
832 }
833
834 /*
835 * smb_fsacl_from_vsa
836 *
837 * Converts given vsecattr_t structure to a acl_t structure.
838 *
839 * The allocated memory for retuned acl_t should be freed by
840 * calling acl_free().
841 */
842 acl_t *
smb_fsacl_from_vsa(vsecattr_t * vsecattr,acl_type_t acl_type)843 smb_fsacl_from_vsa(vsecattr_t *vsecattr, acl_type_t acl_type)
844 {
845 int aclbsize = 0; /* size of acl list in bytes */
846 int dfaclbsize = 0; /* size of default acl list in bytes */
847 int numacls;
848 acl_t *acl_info;
849
850 ASSERT(vsecattr);
851
852 acl_info = acl_alloc(acl_type);
853 if (acl_info == NULL)
854 return (NULL);
855
856 acl_info->acl_flags = 0;
857
858 switch (acl_type) {
859
860 case ACLENT_T:
861 numacls = vsecattr->vsa_aclcnt + vsecattr->vsa_dfaclcnt;
862 aclbsize = vsecattr->vsa_aclcnt * sizeof (aclent_t);
863 dfaclbsize = vsecattr->vsa_dfaclcnt * sizeof (aclent_t);
864
865 acl_info->acl_cnt = numacls;
866 acl_info->acl_aclp = kmem_alloc(aclbsize + dfaclbsize,
867 KM_SLEEP);
868 (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp,
869 aclbsize);
870 (void) memcpy((char *)acl_info->acl_aclp + aclbsize,
871 vsecattr->vsa_dfaclentp, dfaclbsize);
872
873 if (acl_info->acl_cnt <= MIN_ACL_ENTRIES)
874 acl_info->acl_flags |= ACL_IS_TRIVIAL;
875
876 break;
877
878 case ACE_T:
879 aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t);
880 acl_info->acl_cnt = vsecattr->vsa_aclcnt;
881 acl_info->acl_flags = vsecattr->vsa_aclflags;
882 acl_info->acl_aclp = kmem_alloc(aclbsize, KM_SLEEP);
883 (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp,
884 aclbsize);
885 if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0)
886 acl_info->acl_flags |= ACL_IS_TRIVIAL;
887
888 break;
889
890 default:
891 acl_free(acl_info);
892 return (NULL);
893 }
894
895 if (aclbsize && vsecattr->vsa_aclentp)
896 kmem_free(vsecattr->vsa_aclentp, aclbsize);
897 if (dfaclbsize && vsecattr->vsa_dfaclentp)
898 kmem_free(vsecattr->vsa_dfaclentp, dfaclbsize);
899
900 return (acl_info);
901 }
902
903 /*
904 * smb_fsacl_to_vsa
905 *
906 * Converts given acl_t structure to a vsecattr_t structure.
907 *
908 * IMPORTANT:
909 * Upon successful return the memory allocated for vsa_aclentp
910 * should be freed by calling kmem_free(). The size is returned
911 * in aclbsize.
912 */
913 int
smb_fsacl_to_vsa(acl_t * acl_info,vsecattr_t * vsecattr,int * aclbsize)914 smb_fsacl_to_vsa(acl_t *acl_info, vsecattr_t *vsecattr, int *aclbsize)
915 {
916 int error = 0;
917 int numacls;
918 aclent_t *aclp;
919
920 ASSERT(acl_info);
921 ASSERT(vsecattr);
922 ASSERT(aclbsize);
923
924 bzero(vsecattr, sizeof (vsecattr_t));
925 *aclbsize = 0;
926
927 switch (acl_info->acl_type) {
928 case ACLENT_T:
929 numacls = acl_info->acl_cnt;
930 /*
931 * Minimum ACL size is three entries so might as well
932 * bail out here. Also limit request size to prevent user
933 * from allocating too much kernel memory. Maximum size
934 * is MAX_ACL_ENTRIES for the ACL part and MAX_ACL_ENTRIES
935 * for the default ACL part.
936 */
937 if (numacls < 3 || numacls > (MAX_ACL_ENTRIES * 2)) {
938 error = EINVAL;
939 break;
940 }
941
942 vsecattr->vsa_mask = VSA_ACL;
943
944 vsecattr->vsa_aclcnt = numacls;
945 *aclbsize = numacls * sizeof (aclent_t);
946 vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP);
947 (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp,
948 *aclbsize);
949
950 /* Sort the acl list */
951 ksort((caddr_t)vsecattr->vsa_aclentp,
952 vsecattr->vsa_aclcnt, sizeof (aclent_t), cmp2acls);
953
954 /* Break into acl and default acl lists */
955 for (numacls = 0, aclp = vsecattr->vsa_aclentp;
956 numacls < vsecattr->vsa_aclcnt;
957 aclp++, numacls++) {
958 if (aclp->a_type & ACL_DEFAULT)
959 break;
960 }
961
962 /* Find where defaults start (if any) */
963 if (numacls < vsecattr->vsa_aclcnt) {
964 vsecattr->vsa_mask |= VSA_DFACL;
965 vsecattr->vsa_dfaclcnt = vsecattr->vsa_aclcnt - numacls;
966 vsecattr->vsa_dfaclentp = aclp;
967 vsecattr->vsa_aclcnt = numacls;
968 }
969
970 /* Adjust if they're all defaults */
971 if (vsecattr->vsa_aclcnt == 0) {
972 vsecattr->vsa_mask &= ~VSA_ACL;
973 vsecattr->vsa_aclentp = NULL;
974 }
975
976 /* Only directories can have defaults */
977 if (vsecattr->vsa_dfaclcnt &&
978 (acl_info->acl_flags & ACL_IS_DIR)) {
979 error = ENOTDIR;
980 }
981
982 break;
983
984 case ACE_T:
985 if (acl_info->acl_cnt < 1 ||
986 acl_info->acl_cnt > MAX_ACL_ENTRIES) {
987 error = EINVAL;
988 break;
989 }
990
991 vsecattr->vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS;
992 vsecattr->vsa_aclcnt = acl_info->acl_cnt;
993 vsecattr->vsa_aclflags = acl_info->acl_flags & ACL_FLAGS_ALL;
994 *aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t);
995 vsecattr->vsa_aclentsz = *aclbsize;
996 vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP);
997 (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp,
998 *aclbsize);
999
1000 break;
1001
1002 default:
1003 error = EINVAL;
1004 }
1005
1006 return (error);
1007 }
1008
1009 /*
1010 * smb_fsacl_inheritable
1011 *
1012 * Checks to see if there are any inheritable ACEs in the
1013 * given ZFS ACL. Returns the number of inheritable ACEs.
1014 *
1015 * The inherited ACL could be different based on the type of
1016 * new object (file/dir) specified by 'is_dir'.
1017 *
1018 * Note that the input ACL is a ZFS ACL not Windows ACL.
1019 */
1020 static int
smb_fsacl_inheritable(acl_t * zacl,int is_dir)1021 smb_fsacl_inheritable(acl_t *zacl, int is_dir)
1022 {
1023 int numaces;
1024 int num_inheritable = 0;
1025 ace_t *zace;
1026
1027 if (zacl == NULL)
1028 return (0);
1029
1030 for (numaces = 0, zace = zacl->acl_aclp;
1031 numaces < zacl->acl_cnt;
1032 zace++, numaces++) {
1033 switch (zace->a_flags & ACE_FD_INHERIT_ACE) {
1034 case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE):
1035 /*
1036 * Files inherit an effective ACE.
1037 *
1038 * Dirs inherit an effective ACE.
1039 * The inherited ACE is inheritable unless the
1040 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set
1041 */
1042 num_inheritable++;
1043
1044 if (is_dir && ZACE_IS_CREATOR(zace) &&
1045 (ZACE_IS_PROPAGATE(zace))) {
1046 num_inheritable++;
1047 }
1048 break;
1049
1050 case ACE_FILE_INHERIT_ACE:
1051 /*
1052 * Files inherit as an effective ACE.
1053 *
1054 * Dirs inherit an inherit-only ACE
1055 * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit
1056 * flag is also set.
1057 */
1058 if (is_dir == 0)
1059 num_inheritable++;
1060 else if (ZACE_IS_PROPAGATE(zace))
1061 num_inheritable++;
1062 break;
1063
1064 case ACE_DIRECTORY_INHERIT_ACE:
1065 /*
1066 * No effect on files
1067 *
1068 * Dirs inherit an effective ACE.
1069 * The inherited ACE is inheritable unless the
1070 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set.
1071 */
1072 if (is_dir == 0)
1073 break;
1074
1075 num_inheritable++;
1076
1077 if (ZACE_IS_CREATOR(zace) &&
1078 (ZACE_IS_PROPAGATE(zace)))
1079 num_inheritable++;
1080 break;
1081
1082 default:
1083 break;
1084 }
1085 }
1086
1087 return (num_inheritable);
1088 }
1089
1090
1091 /*
1092 * ACE Functions
1093 */
1094
1095 /*
1096 * This is generic (ACL version 2) vs. object-specific
1097 * (ACL version 4) ACE types.
1098 */
1099 boolean_t
smb_ace_is_generic(int type)1100 smb_ace_is_generic(int type)
1101 {
1102 switch (type) {
1103 case ACE_ACCESS_ALLOWED_ACE_TYPE:
1104 case ACE_ACCESS_DENIED_ACE_TYPE:
1105 case ACE_SYSTEM_AUDIT_ACE_TYPE:
1106 case ACE_SYSTEM_ALARM_ACE_TYPE:
1107 case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
1108 case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE:
1109 case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
1110 case ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE:
1111 return (B_TRUE);
1112
1113 default:
1114 break;
1115 }
1116
1117 return (B_FALSE);
1118 }
1119
1120 boolean_t
smb_ace_is_access(int type)1121 smb_ace_is_access(int type)
1122 {
1123 switch (type) {
1124 case ACE_ACCESS_ALLOWED_ACE_TYPE:
1125 case ACE_ACCESS_DENIED_ACE_TYPE:
1126 case ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
1127 case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:
1128 case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE:
1129 case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
1130 case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE:
1131 case ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
1132 case ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
1133 return (B_TRUE);
1134
1135 default:
1136 break;
1137 }
1138
1139 return (B_FALSE);
1140 }
1141
1142 boolean_t
smb_ace_is_audit(int type)1143 smb_ace_is_audit(int type)
1144 {
1145 switch (type) {
1146 case ACE_SYSTEM_AUDIT_ACE_TYPE:
1147 case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE:
1148 case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
1149 case ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
1150 return (B_TRUE);
1151
1152 default:
1153 break;
1154 }
1155
1156 return (B_FALSE);
1157 }
1158
1159 /*
1160 * smb_ace_len
1161 *
1162 * Returns the length of the given ACE as it appears in an
1163 * ACL on the wire (i.e. a flat buffer which contains the SID)
1164 */
1165 static uint16_t
smb_ace_len(smb_ace_t * ace)1166 smb_ace_len(smb_ace_t *ace)
1167 {
1168 ASSERT(ace);
1169 ASSERT(ace->se_sid);
1170
1171 if (ace == NULL)
1172 return (0);
1173
1174 return (SMB_ACE_HDRSIZE + sizeof (ace->se_mask) +
1175 smb_sid_len(ace->se_sid));
1176 }
1177
1178 static void
smb_ace_inherit(ace_t * dir_zace,ace_t * zace,int is_dir,uid_t uid,gid_t gid)1179 smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir, uid_t uid, gid_t gid)
1180 {
1181 *zace = *dir_zace;
1182
1183 /* This is an effective ACE so remove the inherit_only flag */
1184 zace->a_flags &= ~ACE_INHERIT_ONLY_ACE;
1185 /* Mark this ACE as inherited */
1186 zace->a_flags |= ACE_INHERITED_ACE;
1187
1188 /*
1189 * If this is a file or NO_PROPAGATE is set then this inherited
1190 * ACE is not inheritable so clear the inheritance flags
1191 */
1192 if (!(is_dir && ZACE_IS_PROPAGATE(dir_zace)))
1193 zace->a_flags &= ~ACE_INHERIT_FLAGS;
1194
1195 /*
1196 * Replace creator owner/group ACEs with actual owner/group ACEs.
1197 * This is a non-inheritable effective ACE.
1198 */
1199 if (ZACE_IS_CREATOR_OWNER(dir_zace)) {
1200 zace->a_who = uid;
1201 zace->a_flags &= ~ACE_INHERIT_FLAGS;
1202 } else if (ZACE_IS_CREATOR_GROUP(dir_zace)) {
1203 zace->a_who = gid;
1204 zace->a_flags |= ACE_IDENTIFIER_GROUP;
1205 zace->a_flags &= ~ACE_INHERIT_FLAGS;
1206 }
1207 }
1208
1209 /*
1210 * smb_ace_mask_g2s
1211 *
1212 * Converts generic access bits in the given mask (if any)
1213 * to file specific bits. Generic access masks shouldn't be
1214 * stored in filesystem ACEs.
1215 */
1216 static uint32_t
smb_ace_mask_g2s(uint32_t mask)1217 smb_ace_mask_g2s(uint32_t mask)
1218 {
1219 if (mask & GENERIC_ALL) {
1220 mask &= ~(GENERIC_ALL | GENERIC_READ | GENERIC_WRITE
1221 | GENERIC_EXECUTE);
1222
1223 mask |= FILE_ALL_ACCESS;
1224 return (mask);
1225 }
1226
1227 if (mask & GENERIC_READ) {
1228 mask &= ~GENERIC_READ;
1229 mask |= FILE_GENERIC_READ;
1230 }
1231
1232 if (mask & GENERIC_WRITE) {
1233 mask &= ~GENERIC_WRITE;
1234 mask |= FILE_GENERIC_WRITE;
1235 }
1236
1237 if (mask & GENERIC_EXECUTE) {
1238 mask &= ~GENERIC_EXECUTE;
1239 mask |= FILE_GENERIC_EXECUTE;
1240 }
1241
1242 return (mask);
1243 }
1244
1245 /*
1246 * smb_ace_flags_tozfs
1247 *
1248 * This function maps the flags which have different values
1249 * in Windows and Solaris. The ones with the same value are
1250 * transferred untouched.
1251 */
1252 static uint16_t
smb_ace_flags_tozfs(uint8_t c_flags)1253 smb_ace_flags_tozfs(uint8_t c_flags)
1254 {
1255 uint16_t z_flags = 0;
1256
1257 if (c_flags & SUCCESSFUL_ACCESS_ACE_FLAG)
1258 z_flags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG;
1259
1260 if (c_flags & FAILED_ACCESS_ACE_FLAG)
1261 z_flags |= ACE_FAILED_ACCESS_ACE_FLAG;
1262
1263 if (c_flags & INHERITED_ACE)
1264 z_flags |= ACE_INHERITED_ACE;
1265
1266 z_flags |= (c_flags & ACE_INHERIT_FLAGS);
1267
1268 return (z_flags);
1269 }
1270
1271 static uint8_t
smb_ace_flags_fromzfs(uint16_t z_flags)1272 smb_ace_flags_fromzfs(uint16_t z_flags)
1273 {
1274 uint8_t c_flags;
1275
1276 c_flags = z_flags & ACE_INHERIT_FLAGS;
1277
1278 if (z_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)
1279 c_flags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1280
1281 if (z_flags & ACE_FAILED_ACCESS_ACE_FLAG)
1282 c_flags |= FAILED_ACCESS_ACE_FLAG;
1283
1284 if (z_flags & ACE_INHERITED_ACE)
1285 c_flags |= INHERITED_ACE;
1286
1287 return (c_flags);
1288 }
1289
1290 static boolean_t
smb_ace_isvalid(smb_ace_t * ace,int which_acl)1291 smb_ace_isvalid(smb_ace_t *ace, int which_acl)
1292 {
1293 uint16_t min_len;
1294
1295 min_len = sizeof (smb_acehdr_t);
1296
1297 if (ace->se_hdr.se_bsize < min_len)
1298 return (B_FALSE);
1299
1300 if (smb_ace_is_access(ace->se_hdr.se_type) &&
1301 (which_acl != SMB_DACL_SECINFO))
1302 return (B_FALSE);
1303
1304 if (smb_ace_is_audit(ace->se_hdr.se_type) &&
1305 (which_acl != SMB_SACL_SECINFO))
1306 return (B_FALSE);
1307
1308 if (smb_ace_is_generic(ace->se_hdr.se_type)) {
1309 if (!smb_sid_isvalid(ace->se_sid))
1310 return (B_FALSE);
1311
1312 min_len += sizeof (ace->se_mask);
1313 min_len += smb_sid_len(ace->se_sid);
1314
1315 if (ace->se_hdr.se_bsize < min_len)
1316 return (B_FALSE);
1317 }
1318
1319 /*
1320 * object-specific ACE validation will be added later.
1321 */
1322 return (B_TRUE);
1323 }
1324