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