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