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 /*
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 /*
28 * ACL conversion support for smbfs
29 * (To/from NT/ZFS-style ACLs.)
30 */
31
32 #include <sys/types.h>
33 #include <sys/errno.h>
34 #include <sys/acl.h>
35 #include <sys/byteorder.h>
36
37 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
38
39 #include <sys/cred.h>
40 #include <sys/cmn_err.h>
41 #include <sys/kmem.h>
42 #include <sys/sunddi.h>
43 #include <sys/vnode.h>
44 #include <sys/vfs.h>
45
46 #else /* _KERNEL || _FAKE_KERNEL */
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <strings.h>
51
52 #endif /* _KERNEL || _FAKE_KERNEL */
53
54 #ifdef _KERNEL
55 #include <sys/kidmap.h>
56 #else /* _KERNEL */
57 #include <idmap.h>
58 #endif /* _KERNEL */
59
60 #include <netsmb/mchain.h>
61 #include <netsmb/smb.h>
62 #include "smbfs_ntacl.h"
63
64 #define NT_SD_REVISION 1
65 #define NT_ACL_REVISION 2
66
67 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
68 #define MALLOC(size) kmem_alloc(size, KM_SLEEP)
69 #define FREESZ(p, sz) kmem_free(p, sz)
70 #else /* _KERNEL */
71 #define MALLOC(size) malloc(size)
72 /*
73 * Define FREESZ() as inline function so the compiler will not
74 * trigger variable set but not used warning for sz in calling function.
75 */
76 /* ARGSUSED */
77 static inline void
FREESZ(void * p,size_t sz __unused)78 FREESZ(void *p, size_t sz __unused)
79 {
80 free(p);
81 }
82 #endif /* _KERNEL */
83
84 #define ERRCHK(expr) if ((error = expr) != 0) goto errout
85
86 /*
87 * Security IDentifier (SID)
88 */
89 static void
ifree_sid(i_ntsid_t * sid)90 ifree_sid(i_ntsid_t *sid)
91 {
92 size_t sz;
93
94 if (sid == NULL)
95 return;
96
97 sz = I_SID_SIZE(sid->sid_subauthcount);
98 FREESZ(sid, sz);
99 }
100
101 static int
md_get_sid(mdchain_t * mdp,i_ntsid_t ** sidp)102 md_get_sid(mdchain_t *mdp, i_ntsid_t **sidp)
103 {
104 i_ntsid_t *sid = NULL;
105 uint8_t revision, subauthcount;
106 uint32_t *subauthp;
107 size_t sidsz;
108 int error, i;
109
110 if ((error = md_get_uint8(mdp, &revision)) != 0)
111 return (error);
112 if ((error = md_get_uint8(mdp, &subauthcount)) != 0)
113 return (error);
114
115 sidsz = I_SID_SIZE(subauthcount);
116
117 if ((sid = MALLOC(sidsz)) == NULL)
118 return (ENOMEM);
119
120 bzero(sid, sidsz);
121 sid->sid_revision = revision;
122 sid->sid_subauthcount = subauthcount;
123 ERRCHK(md_get_mem(mdp, sid->sid_authority, 6, MB_MSYSTEM));
124
125 subauthp = &sid->sid_subauthvec[0];
126 for (i = 0; i < subauthcount; i++) {
127 ERRCHK(md_get_uint32le(mdp, subauthp));
128 subauthp++;
129 }
130
131 /* Success! */
132 *sidp = sid;
133 return (0);
134
135 errout:
136 ifree_sid(sid);
137 return (error);
138 }
139
140 static int
mb_put_sid(mbchain_t * mbp,i_ntsid_t * sid)141 mb_put_sid(mbchain_t *mbp, i_ntsid_t *sid)
142 {
143 uint32_t *subauthp;
144 int error, i;
145
146 if (sid == NULL)
147 return (EINVAL);
148
149 ERRCHK(mb_put_uint8(mbp, sid->sid_revision));
150 ERRCHK(mb_put_uint8(mbp, sid->sid_subauthcount));
151 ERRCHK(mb_put_mem(mbp, sid->sid_authority, 6, MB_MSYSTEM));
152
153 subauthp = &sid->sid_subauthvec[0];
154 for (i = 0; i < sid->sid_subauthcount; i++) {
155 ERRCHK(mb_put_uint32le(mbp, *subauthp));
156 subauthp++;
157 }
158
159 /* Success! */
160 return (0);
161
162 errout:
163 return (error);
164 }
165
166
167 /*
168 * Access Control Entry (ACE)
169 */
170 static void
ifree_ace(i_ntace_t * ace)171 ifree_ace(i_ntace_t *ace)
172 {
173
174 if (ace == NULL)
175 return;
176
177 switch (ace->ace_hdr.ace_type) {
178 case ACCESS_ALLOWED_ACE_TYPE:
179 case ACCESS_DENIED_ACE_TYPE:
180 case SYSTEM_AUDIT_ACE_TYPE:
181 case SYSTEM_ALARM_ACE_TYPE:
182 ifree_sid(ace->ace_v2.ace_sid);
183 FREESZ(ace, sizeof (i_ntace_v2_t));
184 break;
185 /* other types todo */
186 default:
187 break;
188 }
189 }
190
191 static int
md_get_ace(mdchain_t * mdp,i_ntace_t ** acep)192 md_get_ace(mdchain_t *mdp, i_ntace_t **acep)
193 {
194 mdchain_t tmp_md;
195 i_ntace_hdr_t ace_hdr;
196 i_ntace_t *ace = NULL;
197 uint16_t alloc_size;
198 int error;
199
200 /*
201 * The ACE is realy variable length,
202 * with format determined by the type.
203 *
204 * There may also be padding after it, so
205 * decode it using a copy of the mdchain,
206 * and then consume the specified length.
207 */
208 tmp_md = *mdp;
209
210 /* Fixed-size ACE header */
211 ERRCHK(md_get_uint8(&tmp_md, &ace_hdr.ace_type));
212 ERRCHK(md_get_uint8(&tmp_md, &ace_hdr.ace_flags));
213 ERRCHK(md_get_uint16le(&tmp_md, &ace_hdr.ace_size));
214
215 switch (ace_hdr.ace_type) {
216 case ACCESS_ALLOWED_ACE_TYPE:
217 case ACCESS_DENIED_ACE_TYPE:
218 case SYSTEM_AUDIT_ACE_TYPE:
219 case SYSTEM_ALARM_ACE_TYPE:
220 alloc_size = sizeof (i_ntace_v2_t);
221 if ((ace = MALLOC(alloc_size)) == NULL)
222 return (ENOMEM);
223 bzero(ace, alloc_size);
224 /* ACE header */
225 ace->ace_hdr.ace_type = ace_hdr.ace_type;
226 ace->ace_hdr.ace_flags = ace_hdr.ace_flags;
227 ace->ace_hdr.ace_size = alloc_size;
228 /* Type-specific data. */
229 ERRCHK(md_get_uint32le(&tmp_md, &ace->ace_v2.ace_rights));
230 ERRCHK(md_get_sid(&tmp_md, &ace->ace_v2.ace_sid));
231 break;
232
233 /* other types todo */
234 default:
235 error = EIO;
236 goto errout;
237 }
238
239 /* Now actually consume ace_hdr.ace_size */
240 ERRCHK(md_get_mem(mdp, NULL, ace_hdr.ace_size, MB_MSYSTEM));
241
242 /* Success! */
243 *acep = ace;
244 return (0);
245
246 errout:
247 ifree_ace(ace);
248 return (error);
249 }
250
251 static int
mb_put_ace(mbchain_t * mbp,i_ntace_t * ace)252 mb_put_ace(mbchain_t *mbp, i_ntace_t *ace)
253 {
254 int cnt0, error;
255 uint16_t ace_len, *ace_len_p;
256
257 if (ace == NULL)
258 return (EINVAL);
259
260 cnt0 = mbp->mb_count;
261
262 /*
263 * Put the (fixed-size) ACE header
264 * Will fill in the length later.
265 */
266 ERRCHK(mb_put_uint8(mbp, ace->ace_hdr.ace_type));
267 ERRCHK(mb_put_uint8(mbp, ace->ace_hdr.ace_flags));
268 ace_len_p = mb_reserve(mbp, sizeof (*ace_len_p));
269 if (ace_len_p == NULL) {
270 error = ENOMEM;
271 goto errout;
272 }
273
274 switch (ace->ace_hdr.ace_type) {
275 case ACCESS_ALLOWED_ACE_TYPE:
276 case ACCESS_DENIED_ACE_TYPE:
277 case SYSTEM_AUDIT_ACE_TYPE:
278 case SYSTEM_ALARM_ACE_TYPE:
279 /* Put type-specific data. */
280 ERRCHK(mb_put_uint32le(mbp, ace->ace_v2.ace_rights));
281 ERRCHK(mb_put_sid(mbp, ace->ace_v2.ace_sid));
282 break;
283
284 /* other types todo */
285 default:
286 error = EIO;
287 goto errout;
288 }
289
290 /* Fill in the (OtW) ACE length. */
291 ace_len = mbp->mb_count - cnt0;
292 *ace_len_p = htoles(ace_len);
293
294 /* Success! */
295 return (0);
296
297 errout:
298 return (error);
299 }
300
301
302 /*
303 * Access Control List (ACL)
304 */
305
306 /* Not an OTW structure, so size can be at our convenience. */
307 #define I_ACL_SIZE(cnt) (sizeof (i_ntacl_t) + (cnt) * sizeof (void *))
308
309 static void
ifree_acl(i_ntacl_t * acl)310 ifree_acl(i_ntacl_t *acl)
311 {
312 i_ntace_t **acep;
313 size_t sz;
314 int i;
315
316 if (acl == NULL)
317 return;
318
319 acep = &acl->acl_acevec[0];
320 for (i = 0; i < acl->acl_acecount; i++) {
321 ifree_ace(*acep);
322 acep++;
323 }
324 sz = I_ACL_SIZE(acl->acl_acecount);
325 FREESZ(acl, sz);
326 }
327
328 static int
md_get_acl(mdchain_t * mdp,i_ntacl_t ** aclp)329 md_get_acl(mdchain_t *mdp, i_ntacl_t **aclp)
330 {
331 i_ntacl_t *acl = NULL;
332 i_ntace_t **acep;
333 uint8_t revision;
334 uint16_t acl_len, acecount;
335 size_t aclsz;
336 int i, error;
337
338 if ((error = md_get_uint8(mdp, &revision)) != 0)
339 return (error);
340 if ((error = md_get_uint8(mdp, NULL)) != 0) /* pad1 */
341 return (error);
342 if ((error = md_get_uint16le(mdp, &acl_len)) != 0)
343 return (error);
344 if ((error = md_get_uint16le(mdp, &acecount)) != 0)
345 return (error);
346 if ((error = md_get_uint16le(mdp, NULL)) != 0) /* pad2 */
347 return (error);
348
349 aclsz = I_ACL_SIZE(acecount);
350 if ((acl = MALLOC(aclsz)) == NULL)
351 return (ENOMEM);
352 bzero(acl, aclsz);
353 acl->acl_revision = revision;
354 acl->acl_acecount = acecount;
355
356 acep = &acl->acl_acevec[0];
357 for (i = 0; i < acl->acl_acecount; i++) {
358 ERRCHK(md_get_ace(mdp, acep));
359 acep++;
360 }
361 /*
362 * There may be more data here, but
363 * the caller takes care of that.
364 */
365
366 /* Success! */
367 *aclp = acl;
368 return (0);
369
370 errout:
371 ifree_acl(acl);
372 return (error);
373 }
374
375 static int
mb_put_acl(mbchain_t * mbp,i_ntacl_t * acl)376 mb_put_acl(mbchain_t *mbp, i_ntacl_t *acl)
377 {
378 i_ntace_t **acep;
379 uint16_t acl_len, *acl_len_p;
380 int i, cnt0, error;
381
382 cnt0 = mbp->mb_count;
383
384 ERRCHK(mb_put_uint8(mbp, acl->acl_revision));
385 ERRCHK(mb_put_uint8(mbp, 0)); /* pad1 */
386 acl_len_p = mb_reserve(mbp, sizeof (*acl_len_p));
387 if (acl_len_p == NULL) {
388 error = ENOMEM;
389 goto errout;
390 }
391 ERRCHK(mb_put_uint16le(mbp, acl->acl_acecount));
392 ERRCHK(mb_put_uint16le(mbp, 0)); /* pad2 */
393
394 acep = &acl->acl_acevec[0];
395 for (i = 0; i < acl->acl_acecount; i++) {
396 ERRCHK(mb_put_ace(mbp, *acep));
397 acep++;
398 }
399
400 /* Fill in acl_len_p */
401 acl_len = mbp->mb_count - cnt0;
402 *acl_len_p = htoles(acl_len);
403
404 /* Success! */
405 return (0);
406
407 errout:
408 return (error);
409 }
410
411
412 /*
413 * Security Descriptor
414 */
415 void
smbfs_acl_free_sd(i_ntsd_t * sd)416 smbfs_acl_free_sd(i_ntsd_t *sd)
417 {
418
419 if (sd == NULL)
420 return;
421
422 ifree_sid(sd->sd_owner);
423 ifree_sid(sd->sd_group);
424 ifree_acl(sd->sd_sacl);
425 ifree_acl(sd->sd_dacl);
426
427 FREESZ(sd, sizeof (*sd));
428 }
429
430 /*
431 * Import a raw SD (mb chain) into "internal" form.
432 * (like "absolute" form per. NT docs)
433 * Returns allocated data in sdp
434 *
435 * Note: does NOT consume all the mdp data, so the
436 * caller has to take care of that if necessary.
437 */
438 int
md_get_ntsd(mdchain_t * mdp,i_ntsd_t ** sdp)439 md_get_ntsd(mdchain_t *mdp, i_ntsd_t **sdp)
440 {
441 i_ntsd_t *sd = NULL;
442 mdchain_t top_md, tmp_md;
443 uint32_t owneroff, groupoff, sacloff, dacloff;
444 int error;
445
446 if ((sd = MALLOC(sizeof (*sd))) == NULL)
447 return (ENOMEM);
448 bzero(sd, sizeof (*sd));
449
450 /*
451 * Offsets below are relative to this point,
452 * so save the mdp state for use below.
453 */
454 top_md = *mdp;
455
456 ERRCHK(md_get_uint8(mdp, &sd->sd_revision));
457 ERRCHK(md_get_uint8(mdp, &sd->sd_rmctl));
458 ERRCHK(md_get_uint16le(mdp, &sd->sd_flags));
459 ERRCHK(md_get_uint32le(mdp, &owneroff));
460 ERRCHK(md_get_uint32le(mdp, &groupoff));
461 ERRCHK(md_get_uint32le(mdp, &sacloff));
462 ERRCHK(md_get_uint32le(mdp, &dacloff));
463
464 /*
465 * The SD is "self-relative" on the wire,
466 * but not after this decodes it.
467 */
468 sd->sd_flags &= ~SD_SELF_RELATIVE;
469
470 /*
471 * For each section make a temporary copy of the
472 * top_md state, advance to the given offset, and
473 * pass that to the lower md_get_xxx functions.
474 * These could be marshalled in any order, but
475 * are normally found in the order shown here.
476 */
477 if (sacloff) {
478 tmp_md = top_md;
479 md_get_mem(&tmp_md, NULL, sacloff, MB_MSYSTEM);
480 ERRCHK(md_get_acl(&tmp_md, &sd->sd_sacl));
481 }
482 if (dacloff) {
483 tmp_md = top_md;
484 md_get_mem(&tmp_md, NULL, dacloff, MB_MSYSTEM);
485 ERRCHK(md_get_acl(&tmp_md, &sd->sd_dacl));
486 }
487 if (owneroff) {
488 tmp_md = top_md;
489 md_get_mem(&tmp_md, NULL, owneroff, MB_MSYSTEM);
490 ERRCHK(md_get_sid(&tmp_md, &sd->sd_owner));
491 }
492 if (groupoff) {
493 tmp_md = top_md;
494 md_get_mem(&tmp_md, NULL, groupoff, MB_MSYSTEM);
495 ERRCHK(md_get_sid(&tmp_md, &sd->sd_group));
496 }
497
498 /* Success! */
499 *sdp = sd;
500 return (0);
501
502 errout:
503 smbfs_acl_free_sd(sd);
504 return (error);
505 }
506
507 /*
508 * Export an "internal" SD into an raw SD (mb chain).
509 * (a.k.a "self-relative" form per. NT docs)
510 * Returns allocated mbchain in mbp.
511 */
512 int
mb_put_ntsd(mbchain_t * mbp,i_ntsd_t * sd)513 mb_put_ntsd(mbchain_t *mbp, i_ntsd_t *sd)
514 {
515 uint32_t *owneroffp, *groupoffp, *sacloffp, *dacloffp;
516 uint32_t owneroff, groupoff, sacloff, dacloff;
517 uint16_t flags;
518 int cnt0, error;
519
520 cnt0 = mbp->mb_count;
521 owneroff = groupoff = sacloff = dacloff = 0;
522
523 /* The SD is "self-relative" on the wire. */
524 flags = sd->sd_flags | SD_SELF_RELATIVE;
525
526 ERRCHK(mb_put_uint8(mbp, sd->sd_revision));
527 ERRCHK(mb_put_uint8(mbp, sd->sd_rmctl));
528 ERRCHK(mb_put_uint16le(mbp, flags));
529
530 owneroffp = mb_reserve(mbp, sizeof (*owneroffp));
531 groupoffp = mb_reserve(mbp, sizeof (*groupoffp));
532 sacloffp = mb_reserve(mbp, sizeof (*sacloffp));
533 dacloffp = mb_reserve(mbp, sizeof (*dacloffp));
534 if (owneroffp == NULL || groupoffp == NULL ||
535 sacloffp == NULL || dacloffp == NULL) {
536 error = ENOMEM;
537 goto errout;
538 }
539
540 /*
541 * These could be marshalled in any order, but
542 * are normally found in the order shown here.
543 */
544 if (sd->sd_sacl) {
545 sacloff = mbp->mb_count - cnt0;
546 ERRCHK(mb_put_acl(mbp, sd->sd_sacl));
547 }
548 if (sd->sd_dacl) {
549 dacloff = mbp->mb_count - cnt0;
550 ERRCHK(mb_put_acl(mbp, sd->sd_dacl));
551 }
552 if (sd->sd_owner) {
553 owneroff = mbp->mb_count - cnt0;
554 ERRCHK(mb_put_sid(mbp, sd->sd_owner));
555 }
556 if (sd->sd_group) {
557 groupoff = mbp->mb_count - cnt0;
558 ERRCHK(mb_put_sid(mbp, sd->sd_group));
559 }
560
561 /* Fill in the offsets */
562 *owneroffp = htolel(owneroff);
563 *groupoffp = htolel(groupoff);
564 *sacloffp = htolel(sacloff);
565 *dacloffp = htolel(dacloff);
566
567 /* Success! */
568 return (0);
569
570 errout:
571 return (error);
572 }
573
574 /*
575 * ================================================================
576 * Support for ACL fetch, including conversions
577 * from Windows ACLs to NFSv4-style ACLs.
578 * ================================================================
579 */
580
581 #define GENERIC_RIGHTS_MASK \
582 (GENERIC_RIGHT_READ_ACCESS | GENERIC_RIGHT_WRITE_ACCESS |\
583 GENERIC_RIGHT_EXECUTE_ACCESS | GENERIC_RIGHT_ALL_ACCESS)
584
585 /*
586 * Table for converting NT GENERIC_RIGHT_... to specific rights
587 * appropriate for objects of type file.
588 */
589 struct gen2fsr {
590 uint32_t gf_generic;
591 uint32_t gf_specific;
592 };
593 static const struct gen2fsr
594 smbfs_gen2fsr[] = {
595 {
596 GENERIC_RIGHT_READ_ACCESS,
597 STD_RIGHT_SYNCHRONIZE_ACCESS |
598 STD_RIGHT_READ_CONTROL_ACCESS |
599 SA_RIGHT_FILE_READ_ATTRIBUTES |
600 SA_RIGHT_FILE_READ_EA |
601 SA_RIGHT_FILE_READ_DATA },
602 {
603 GENERIC_RIGHT_WRITE_ACCESS,
604 STD_RIGHT_SYNCHRONIZE_ACCESS |
605 STD_RIGHT_READ_CONTROL_ACCESS |
606 SA_RIGHT_FILE_WRITE_ATTRIBUTES |
607 SA_RIGHT_FILE_WRITE_EA |
608 SA_RIGHT_FILE_APPEND_DATA |
609 SA_RIGHT_FILE_WRITE_DATA },
610 {
611 GENERIC_RIGHT_EXECUTE_ACCESS,
612 STD_RIGHT_SYNCHRONIZE_ACCESS |
613 STD_RIGHT_READ_CONTROL_ACCESS |
614 SA_RIGHT_FILE_READ_ATTRIBUTES |
615 SA_RIGHT_FILE_EXECUTE },
616 {
617 GENERIC_RIGHT_ALL_ACCESS,
618 STD_RIGHT_SYNCHRONIZE_ACCESS |
619 STD_RIGHT_WRITE_OWNER_ACCESS |
620 STD_RIGHT_WRITE_DAC_ACCESS |
621 STD_RIGHT_READ_CONTROL_ACCESS |
622 STD_RIGHT_DELETE_ACCESS |
623 SA_RIGHT_FILE_ALL_ACCESS },
624 { 0, 0 }
625 };
626
627 /*
628 * Table for translating ZFS ACE flags to NT ACE flags.
629 * The low four bits are the same, but not others.
630 */
631 struct zaf2naf {
632 uint16_t za_flag;
633 uint8_t na_flag;
634 };
635 static const struct zaf2naf
636 smbfs_zaf2naf[] = {
637 { ACE_FILE_INHERIT_ACE, OBJECT_INHERIT_ACE_FLAG },
638 { ACE_DIRECTORY_INHERIT_ACE, CONTAINER_INHERIT_ACE_FLAG },
639 { ACE_NO_PROPAGATE_INHERIT_ACE, NO_PROPAGATE_INHERIT_ACE_FLAG },
640 { ACE_INHERIT_ONLY_ACE, INHERIT_ONLY_ACE_FLAG },
641 { ACE_INHERITED_ACE, INHERITED_ACE_FLAG },
642 { ACE_SUCCESSFUL_ACCESS_ACE_FLAG, SUCCESSFUL_ACCESS_ACE_FLAG },
643 { ACE_FAILED_ACCESS_ACE_FLAG, FAILED_ACCESS_ACE_FLAG },
644 { 0, 0 }
645 };
646
647 /*
648 * Convert an NT SID to a string. Optionally return the
649 * last sub-authority (or "relative ID" -- RID) in *ridp
650 * and truncate the output string after the domain part.
651 * If ridp==NULL, the output string is the whole SID,
652 * including both the domain and RID.
653 *
654 * Return length written, or -1 on error.
655 */
656 int
smbfs_sid2str(i_ntsid_t * sid,char * obuf,size_t osz,uint32_t * ridp)657 smbfs_sid2str(i_ntsid_t *sid,
658 char *obuf, size_t osz, uint32_t *ridp)
659 {
660 char *s = obuf;
661 uint64_t auth = 0;
662 uint_t i, n;
663 uint32_t subs, *ip;
664
665 n = snprintf(s, osz, "S-%u", sid->sid_revision);
666 if (n > osz)
667 return (-1);
668 s += n; osz -= n;
669
670 for (i = 0; i < 6; i++)
671 auth = (auth << 8) | sid->sid_authority[i];
672 n = snprintf(s, osz, "-%llu", (u_longlong_t)auth);
673 if (n > osz)
674 return (-1);
675 s += n; osz -= n;
676
677 subs = sid->sid_subauthcount;
678 if (subs < 1 || subs > 15)
679 return (-1);
680 if (ridp)
681 subs--;
682
683 ip = &sid->sid_subauthvec[0];
684 for (; subs; subs--, ip++) {
685 n = snprintf(s, osz, "-%u", *ip);
686 if (n > osz)
687 return (-1);
688 s += n; osz -= n;
689 }
690 if (ridp)
691 *ridp = *ip;
692
693 /* LINTED E_PTRDIFF_OVERFLOW */
694 return (s - obuf);
695 }
696
697 /*
698 * Our interface to the idmap service.
699 *
700 * The idmap API is _almost_ the same between
701 * kernel and user-level. But not quite...
702 * Hope this improves readability below.
703 */
704 #ifdef _KERNEL
705
706 #define I_getuidbysid(GH, SPP, RID, UIDP, SP) \
707 kidmap_batch_getuidbysid(GH, SPP, RID, UIDP, SP)
708
709 #define I_getgidbysid(GH, SPP, RID, GIDP, SP) \
710 kidmap_batch_getgidbysid(GH, SPP, RID, GIDP, SP)
711
712 #define I_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) \
713 kidmap_batch_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP)
714
715 #define I_getmappings kidmap_get_mappings
716
717 #else /* _KERNEL */
718
719 #define I_getuidbysid(GH, SPP, RID, UIDP, SP) \
720 idmap_get_uidbysid(GH, SPP, RID, 0, UIDP, SP)
721
722 #define I_getgidbysid(GH, SPP, RID, GIDP, SP) \
723 idmap_get_gidbysid(GH, SPP, RID, 0, GIDP, SP)
724
725 #define I_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) \
726 idmap_get_pidbysid(GH, SPP, RID, 0, PIDP, ISUP, SP)
727
728 #define I_getmappings idmap_get_mappings
729
730 #endif /* _KERNEL */
731
732
733 /*
734 * The idmap request types, chosen so they also
735 * match the values returned in mi_isuser.
736 */
737 #define IDM_TYPE_ANY -1
738 #define IDM_TYPE_GROUP 0
739 #define IDM_TYPE_USER 1
740
741 /*
742 * A sentinel value for mi_isuser (below) to indicate
743 * that the SID is the well-known "Everyone" (S-1-1-0).
744 * The idmap library only uses -1, 0, 1, so this value
745 * is arbitrary but must not overlap w/ idmap values.
746 * XXX: Could use a way for idmap to tell us when
747 * it recognizes this well-known SID.
748 */
749 #define IDM_EVERYONE 11
750
751 struct mapinfo2uid {
752 uid_t mi_uid; /* or gid, or pid */
753 int mi_isuser; /* IDM_TYPE */
754 idmap_stat mi_status;
755 };
756
757 /*
758 * Build an idmap request. Cleanup is
759 * handled by the caller (error or not)
760 */
761 static int
mkrq_idmap_sid2ux(idmap_get_handle_t * idmap_gh,struct mapinfo2uid * mip,i_ntsid_t * sid,int req_type)762 mkrq_idmap_sid2ux(
763 idmap_get_handle_t *idmap_gh,
764 struct mapinfo2uid *mip,
765 i_ntsid_t *sid,
766 int req_type)
767 {
768 char strbuf[256];
769 char *sid_prefix;
770 uint32_t rid;
771 idmap_stat idms;
772
773 if (smbfs_sid2str(sid, strbuf, sizeof (strbuf), &rid) < 0)
774 return (EINVAL);
775 sid_prefix = strbuf;
776
777 /*
778 * Give the "Everyone" group special treatment.
779 */
780 if (strcmp(sid_prefix, "S-1-1") == 0 && rid == 0) {
781 /* This is "Everyone" */
782 mip->mi_uid = (uid_t)-1;
783 mip->mi_isuser = IDM_EVERYONE;
784 mip->mi_status = 0;
785 return (0);
786 }
787
788 switch (req_type) {
789
790 case IDM_TYPE_USER:
791 mip->mi_isuser = req_type;
792 idms = I_getuidbysid(idmap_gh, sid_prefix, rid,
793 &mip->mi_uid, &mip->mi_status);
794 break;
795
796 case IDM_TYPE_GROUP:
797 mip->mi_isuser = req_type;
798 idms = I_getgidbysid(idmap_gh, sid_prefix, rid,
799 &mip->mi_uid, &mip->mi_status);
800 break;
801
802 case IDM_TYPE_ANY:
803 idms = I_getpidbysid(idmap_gh, sid_prefix, rid,
804 &mip->mi_uid, &mip->mi_isuser, &mip->mi_status);
805 break;
806
807 default:
808 idms = IDMAP_ERR_OTHER;
809 break;
810 }
811
812 if (idms != IDMAP_SUCCESS)
813 return (EINVAL);
814
815 return (0);
816 }
817
818 /*
819 * Convert an NT ACE to a ZFS ACE.
820 * ACE type was already validated.
821 */
822 static void
ntace2zace(ace_t * zacep,i_ntace_t * ntace,struct mapinfo2uid * mip)823 ntace2zace(ace_t *zacep, i_ntace_t *ntace, struct mapinfo2uid *mip)
824 {
825 const struct zaf2naf *znaf;
826 uid_t zwho;
827 uint32_t zamask;
828 uint16_t zflags;
829
830 /*
831 * Set the "ID type" flags in the ZFS ace flags.
832 */
833 zflags = 0;
834 switch (mip->mi_isuser) {
835 case IDM_EVERYONE:
836 zflags = ACE_EVERYONE;
837 zwho = (uid_t)-1;
838 break;
839
840 case IDM_TYPE_GROUP: /* it's a GID */
841 zflags = ACE_IDENTIFIER_GROUP;
842 zwho = mip->mi_uid;
843 break;
844
845 default:
846 case IDM_TYPE_USER: /* it's a UID */
847 zflags = 0;
848 zwho = mip->mi_uid;
849 break;
850 }
851
852 /*
853 * Translate NT ACE flags to ZFS ACE flags.
854 */
855 for (znaf = smbfs_zaf2naf; znaf->za_flag; znaf++)
856 if (ntace->ace_hdr.ace_flags & znaf->na_flag)
857 zflags |= znaf->za_flag;
858
859 /*
860 * The "normal" access mask bits are the same, but
861 * if the ACE has any GENERIC_RIGHT_... convert those
862 * to specific rights. GENERIC bits are rarely seen,
863 * but reportedly can happen with inherit-only ACEs.
864 */
865 zamask = ntace->ace_v2.ace_rights & ACE_ALL_PERMS;
866 if (ntace->ace_v2.ace_rights & GENERIC_RIGHTS_MASK) {
867 const struct gen2fsr *gf;
868 for (gf = smbfs_gen2fsr; gf->gf_generic; gf++)
869 if (ntace->ace_v2.ace_rights & gf->gf_generic)
870 zamask |= gf->gf_specific;
871 }
872
873 /*
874 * Fill in the ZFS-style ACE
875 */
876 zacep->a_who = zwho;
877 zacep->a_access_mask = zamask;
878 zacep->a_flags = zflags;
879 zacep->a_type = ntace->ace_hdr.ace_type;
880 }
881
882 /*
883 * Convert an internal SD to a ZFS-style ACL.
884 * Note optional args: vsa/acl, uidp, gidp.
885 *
886 * This makes two passes over the SD, the first building a
887 * "batch" request for idmap with results in mapinfo, the
888 * second building a ZFS-style ACL using the idmap results.
889 */
890 int
smbfs_acl_sd2zfs(i_ntsd_t * sd,vsecattr_t * acl_info,uid_t * uidp,gid_t * gidp)891 smbfs_acl_sd2zfs(
892 i_ntsd_t *sd,
893 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
894 vsecattr_t *acl_info,
895 #else /* _KERNEL */
896 acl_t *acl_info,
897 #endif /* _KERNEL */
898 uid_t *uidp, gid_t *gidp)
899 {
900 struct mapinfo2uid *mip, *mapinfo = NULL;
901 int error, i, mapcnt, zacecnt, zacl_size;
902 ace_t *zacep0, *zacep;
903 uid_t own_uid = (uid_t)-1;
904 gid_t own_gid = (gid_t)-1;
905 i_ntacl_t *ntacl;
906 i_ntace_t **ntacep;
907 idmap_get_handle_t *idmap_gh = NULL;
908 idmap_stat idms;
909
910 /*
911 * sanity checks
912 */
913 if (acl_info) {
914 #if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
915 if (acl_info->acl_type != ACE_T ||
916 acl_info->acl_aclp != NULL ||
917 acl_info->acl_entry_size != sizeof (ace_t))
918 return (EINVAL);
919 #endif /* !_KERNEL */
920 if ((sd->sd_flags & SD_DACL_PRESENT) == 0)
921 return (EINVAL);
922 }
923
924 /*
925 * How many SID mappings will we need?
926 */
927 mapcnt = 0;
928 if (sd->sd_owner)
929 mapcnt++;
930 if (sd->sd_group)
931 mapcnt++;
932 if ((sd->sd_flags & SD_SACL_PRESENT) &&
933 (sd->sd_sacl != NULL))
934 mapcnt += sd->sd_sacl->acl_acecount;
935 if ((sd->sd_flags & SD_DACL_PRESENT) &&
936 (sd->sd_dacl != NULL))
937 mapcnt += sd->sd_dacl->acl_acecount;
938 if (mapcnt == 0) {
939 /*
940 * We have a NULL DACL, SACL, and don't
941 * have an owner or group, so there's no
942 * idmap work to do. This is very rare,
943 * so rather than complicate things below,
944 * pretend we need one mapping slot.
945 */
946 mapcnt = 1;
947 }
948
949 mapinfo = MALLOC(mapcnt * sizeof (*mapinfo));
950 if (mapinfo == NULL) {
951 error = ENOMEM;
952 goto errout;
953 }
954 bzero(mapinfo, mapcnt * sizeof (*mapinfo));
955
956
957 /*
958 * Get an imap "batch" request handle.
959 */
960 #ifdef _KERNEL
961 idmap_gh = kidmap_get_create(curproc->p_zone);
962 #else /* _KERNEL */
963 idms = idmap_get_create(&idmap_gh);
964 if (idms != IDMAP_SUCCESS) {
965 error = ENOTACTIVE;
966 goto errout;
967 }
968 #endif /* _KERNEL */
969
970 /*
971 * Build our request to the idmap deamon,
972 * getting Unix IDs for every SID.
973 */
974 mip = mapinfo;
975 if (sd->sd_owner) {
976 error = mkrq_idmap_sid2ux(idmap_gh, mip,
977 sd->sd_owner, IDM_TYPE_USER);
978 if (error)
979 goto errout;
980 mip++;
981 }
982 if (sd->sd_group) {
983 error = mkrq_idmap_sid2ux(idmap_gh, mip,
984 sd->sd_group, IDM_TYPE_GROUP);
985 if (error)
986 goto errout;
987 mip++;
988 }
989 if ((sd->sd_flags & SD_SACL_PRESENT) &&
990 (sd->sd_sacl != NULL)) {
991 ntacl = sd->sd_sacl;
992 ntacep = &ntacl->acl_acevec[0];
993 for (i = 0; i < ntacl->acl_acecount; i++) {
994 error = mkrq_idmap_sid2ux(idmap_gh, mip,
995 (*ntacep)->ace_v2.ace_sid, IDM_TYPE_ANY);
996 if (error)
997 goto errout;
998 ntacep++;
999 mip++;
1000 }
1001 }
1002 if ((sd->sd_flags & SD_DACL_PRESENT) &&
1003 (sd->sd_dacl != NULL)) {
1004 ntacl = sd->sd_dacl;
1005 ntacep = &ntacl->acl_acevec[0];
1006 for (i = 0; i < ntacl->acl_acecount; i++) {
1007 error = mkrq_idmap_sid2ux(idmap_gh, mip,
1008 (*ntacep)->ace_v2.ace_sid, IDM_TYPE_ANY);
1009 if (error)
1010 goto errout;
1011 ntacep++;
1012 mip++;
1013 }
1014 }
1015
1016 if (mip != mapinfo) {
1017 idms = I_getmappings(idmap_gh);
1018 if (idms != IDMAP_SUCCESS) {
1019 /* creative error choice */
1020 error = EIDRM;
1021 goto errout;
1022 }
1023 }
1024
1025 /*
1026 * With any luck, we now have Unix user/group IDs
1027 * for every Windows SID in the security descriptor.
1028 * The remaining work is just format conversion.
1029 */
1030 mip = mapinfo;
1031 if (sd->sd_owner) {
1032 own_uid = mip->mi_uid;
1033 mip++;
1034 }
1035 if (sd->sd_group) {
1036 own_gid = mip->mi_uid;
1037 mip++;
1038 }
1039
1040 if (uidp)
1041 *uidp = own_uid;
1042 if (gidp)
1043 *gidp = own_gid;
1044
1045 if (acl_info == NULL) {
1046 /* Caller only wanted uid/gid */
1047 goto done;
1048 }
1049
1050 /*
1051 * Build the ZFS-style ACL
1052 * First, allocate the most ZFS ACEs we'll need.
1053 */
1054 zacecnt = 0;
1055 if ((sd->sd_flags & SD_SACL_PRESENT) &&
1056 (sd->sd_sacl != NULL))
1057 zacecnt += sd->sd_sacl->acl_acecount;
1058
1059 /* NB, have: (sd->sd_flags & SD_DACL_PRESENT) */
1060 if ((sd->sd_dacl != NULL) &&
1061 (sd->sd_dacl->acl_acecount > 0)) {
1062 zacecnt += sd->sd_dacl->acl_acecount;
1063 } else {
1064 /*
1065 * DACL is NULL or empty. Either way,
1066 * we'll need to add a ZFS ACE below.
1067 */
1068 zacecnt++;
1069 }
1070 zacl_size = zacecnt * sizeof (ace_t);
1071 zacep0 = MALLOC(zacl_size);
1072 if (zacep0 == NULL) {
1073 error = ENOMEM;
1074 goto errout;
1075 }
1076 zacep = zacep0;
1077
1078 if ((sd->sd_flags & SD_SACL_PRESENT) &&
1079 (sd->sd_sacl != NULL)) {
1080 ntacl = sd->sd_sacl;
1081 ntacep = &ntacl->acl_acevec[0];
1082 for (i = 0; i < ntacl->acl_acecount; i++) {
1083 ntace2zace(zacep, *ntacep, mip);
1084 zacep++;
1085 ntacep++;
1086 mip++;
1087 }
1088 }
1089
1090 /* NB, have: (sd->sd_flags & SD_DACL_PRESENT) */
1091 if (sd->sd_dacl != NULL) {
1092 ntacl = sd->sd_dacl;
1093 ntacep = &ntacl->acl_acevec[0];
1094 for (i = 0; i < ntacl->acl_acecount; i++) {
1095 ntace2zace(zacep, *ntacep, mip);
1096 zacep++;
1097 ntacep++;
1098 mip++;
1099 }
1100 }
1101 if (sd->sd_dacl == NULL) {
1102 /*
1103 * The SD has a NULL DACL. That means
1104 * everyone@, full-control
1105 */
1106 zacep->a_who = (uid_t)-1;
1107 zacep->a_access_mask = ACE_ALL_PERMS;
1108 zacep->a_flags = ACE_EVERYONE;
1109 zacep->a_type = ACCESS_ALLOWED_ACE_TYPE;
1110 } else if (sd->sd_dacl->acl_acecount == 0) {
1111 /*
1112 * The SD has an Empty DACL. We need
1113 * at least one ACE, so add one giving
1114 * the owner the usual implied access.
1115 */
1116 zacep->a_who = (uid_t)-1;
1117 zacep->a_access_mask = ACE_READ_ATTRIBUTES | \
1118 ACE_READ_ACL | ACE_WRITE_ACL;
1119 zacep->a_flags = ACE_OWNER;
1120 zacep->a_type = ACCESS_ALLOWED_ACE_TYPE;
1121 }
1122
1123 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
1124 acl_info->vsa_aclcnt = zacecnt;
1125 acl_info->vsa_aclentp = zacep0;
1126 acl_info->vsa_aclentsz = zacl_size;
1127 #else /* _KERNEL */
1128 acl_info->acl_cnt = zacecnt;
1129 acl_info->acl_aclp = zacep0;
1130 #endif /* _KERNEL */
1131
1132 done:
1133 error = 0;
1134
1135 errout:
1136 if (mapinfo != NULL)
1137 FREESZ(mapinfo, mapcnt * sizeof (*mapinfo));
1138 #ifdef _KERNEL
1139 if (idmap_gh != NULL)
1140 kidmap_get_destroy(idmap_gh);
1141 #else /* _KERNEL */
1142 if (idmap_gh != NULL)
1143 idmap_get_destroy(idmap_gh);
1144 #endif /* _KERNEL */
1145
1146 return (error);
1147 }
1148
1149
1150 /*
1151 * ================================================================
1152 * Support for ACL store, including conversions
1153 * from NFSv4-style ACLs to Windows ACLs.
1154 * ================================================================
1155 */
1156
1157 /*
1158 * Convert a "sid-prefix" string plus RID into an NT SID.
1159 *
1160 * If successful, sets *osid and returns zero,
1161 * otherwise returns an errno value.
1162 */
1163 int
smbfs_str2sid(const char * sid_prefix,uint32_t * ridp,i_ntsid_t ** osidp)1164 smbfs_str2sid(const char *sid_prefix, uint32_t *ridp, i_ntsid_t **osidp)
1165 {
1166 i_ntsid_t *sid = NULL;
1167 u_longlong_t auth = 0;
1168 ulong_t sa;
1169 uint8_t sacnt;
1170 const char *p;
1171 char *np;
1172 size_t size;
1173 int i;
1174 int err;
1175
1176 if (sid_prefix == NULL)
1177 return (EINVAL);
1178
1179 p = sid_prefix;
1180 if (strncmp(p, "S-1-", 4) != 0)
1181 return (EINVAL);
1182 p += 4;
1183
1184 /* Parse the "authority" */
1185 #ifdef _KERNEL
1186 err = ddi_strtoull(p, &np, 10, &auth);
1187 if (err != 0)
1188 return (err);
1189 #else /* _KERNEL */
1190 auth = strtoull(p, &np, 10);
1191 if (p == np)
1192 return (EINVAL);
1193 #endif /* _KERNEL */
1194
1195 /*
1196 * Count the sub-authorities. Here, np points to
1197 * the "-" before the first sub-authority.
1198 */
1199 sacnt = 0;
1200 for (p = np; *p; p++) {
1201 if (*p == '-')
1202 sacnt++;
1203 }
1204 if (ridp != NULL)
1205 sacnt++;
1206
1207 /* Allocate the internal SID. */
1208 size = I_SID_SIZE(sacnt);
1209 sid = MALLOC(size);
1210 if (sid == NULL)
1211 return (ENOMEM);
1212 bzero(sid, size);
1213
1214 /* Fill it in. */
1215 sid->sid_revision = 1;
1216 sid->sid_subauthcount = sacnt;
1217 for (i = 5; i >= 0; i--) {
1218 sid->sid_authority[i] = auth & 0xFF;
1219 auth = auth >> 8;
1220 }
1221
1222 err = EINVAL;
1223 if (ridp != NULL)
1224 sacnt--; /* Last SA not from string */
1225 p = np;
1226 for (i = 0; i < sacnt; i++) {
1227 if (*p != '-') {
1228 err = EINVAL;
1229 goto out;
1230 }
1231 p++;
1232 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
1233 err = ddi_strtoul(p, &np, 10, &sa);
1234 if (err != 0)
1235 goto out;
1236 #else /* _KERNEL */
1237 sa = strtoul(p, &np, 10);
1238 if (p == np) {
1239 err = EINVAL;
1240 goto out;
1241 }
1242 #endif /* _KERNEL */
1243 sid->sid_subauthvec[i] = (uint32_t)sa;
1244 p = np;
1245 }
1246 if (*p != '\0')
1247 goto out;
1248 if (ridp != NULL)
1249 sid->sid_subauthvec[i] = *ridp;
1250 err = 0;
1251
1252 out:
1253 if (err)
1254 FREESZ(sid, size);
1255 else
1256 *osidp = sid;
1257
1258 return (err);
1259 }
1260
1261 /*
1262 * The idmap API is _almost_ the same between
1263 * kernel and user-level. But not quite...
1264 * Hope this improves readability below.
1265 */
1266 #ifdef _KERNEL
1267
1268 #define I_getsidbyuid(GH, UID, SPP, RP, ST) \
1269 kidmap_batch_getsidbyuid(GH, UID, SPP, RP, ST)
1270
1271 #define I_getsidbygid(GH, GID, SPP, RP, ST) \
1272 kidmap_batch_getsidbygid(GH, GID, SPP, RP, ST)
1273
1274 #else /* _KERNEL */
1275
1276 #define I_getsidbyuid(GH, UID, SPP, RP, ST) \
1277 idmap_get_sidbyuid(GH, UID, 0, SPP, RP, ST)
1278
1279 #define I_getsidbygid(GH, GID, SPP, RP, ST) \
1280 idmap_get_sidbygid(GH, GID, 0, SPP, RP, ST)
1281
1282 #endif /* _KERNEL */
1283
1284 struct mapinfo2sid {
1285 /* Yet another kernel vs. user difference. */
1286 #ifdef _KERNEL
1287 const char *mi_dsid; /* domain SID */
1288 #else /* _KERNEL */
1289 char *mi_dsid;
1290 #endif /* _KERNEL */
1291 uint32_t mi_rid; /* relative ID */
1292 idmap_stat mi_status;
1293 };
1294
1295 /*
1296 * Build an idmap request. Cleanup is
1297 * handled by the caller (error or not)
1298 */
1299 static int
mkrq_idmap_ux2sid(idmap_get_handle_t * idmap_gh,struct mapinfo2sid * mip,uid_t uid,int req_type)1300 mkrq_idmap_ux2sid(
1301 idmap_get_handle_t *idmap_gh,
1302 struct mapinfo2sid *mip,
1303 uid_t uid, /* or gid */
1304 int req_type)
1305 {
1306 idmap_stat idms;
1307
1308 switch (req_type) {
1309
1310 case IDM_TYPE_USER:
1311 if (uid == (uid_t)-1)
1312 return (EINVAL);
1313 idms = I_getsidbyuid(idmap_gh, uid,
1314 &mip->mi_dsid, &mip->mi_rid, &mip->mi_status);
1315 break;
1316
1317 case IDM_TYPE_GROUP:
1318 if (uid == (uid_t)-1)
1319 return (EINVAL);
1320 idms = I_getsidbygid(idmap_gh, uid,
1321 &mip->mi_dsid, &mip->mi_rid, &mip->mi_status);
1322 break;
1323
1324 case IDM_EVERYONE:
1325 mip->mi_dsid = "S-1-1";
1326 mip->mi_rid = 0;
1327 mip->mi_status = 0;
1328 idms = IDMAP_SUCCESS;
1329 break;
1330
1331 default:
1332 idms = IDMAP_ERR_OTHER;
1333 break;
1334 }
1335
1336 if (idms != IDMAP_SUCCESS)
1337 return (EINVAL);
1338
1339 return (0);
1340 }
1341
1342 /*
1343 * Convert a ZFS ACE to an NT ACE.
1344 * ACE type was already validated.
1345 */
1346 static int
zace2ntace(i_ntace_t ** ntacep,ace_t * zacep,struct mapinfo2sid * mip)1347 zace2ntace(i_ntace_t **ntacep, ace_t *zacep, struct mapinfo2sid *mip)
1348 {
1349 const struct zaf2naf *znaf;
1350 uint8_t aflags;
1351 uint16_t alloc_size;
1352 uint32_t rights;
1353 i_ntace_t *ntace = NULL;
1354 i_ntsid_t *sid = NULL;
1355 int error;
1356
1357 if (mip->mi_dsid == NULL || mip->mi_status != 0) {
1358 return (EINVAL);
1359 }
1360
1361 /*
1362 * Translate ZFS ACE flags to NT ACE flags.
1363 */
1364 aflags = 0;
1365 for (znaf = smbfs_zaf2naf; znaf->za_flag; znaf++)
1366 if (zacep->a_flags & znaf->za_flag)
1367 aflags |= znaf->na_flag;
1368
1369 /*
1370 * The access rights bits are OK as-is.
1371 */
1372 rights = zacep->a_access_mask;
1373
1374 /*
1375 * Make sure we can get the SID.
1376 * Note: allocates sid.
1377 */
1378 error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid, &sid);
1379 if (error)
1380 return (error);
1381
1382 /*
1383 * Allocate the NT ACE and fill it in.
1384 */
1385 alloc_size = sizeof (i_ntace_v2_t);
1386 if ((ntace = MALLOC(alloc_size)) == NULL) {
1387 ifree_sid(sid);
1388 return (ENOMEM);
1389 }
1390 bzero(ntace, alloc_size);
1391
1392 ntace->ace_hdr.ace_type = zacep->a_type;
1393 ntace->ace_hdr.ace_flags = aflags;
1394 ntace->ace_hdr.ace_size = alloc_size;
1395 ntace->ace_v2.ace_rights = rights;
1396 ntace->ace_v2.ace_sid = sid;
1397
1398 *ntacep = ntace;
1399 return (0);
1400 }
1401
1402 /*
1403 * Convert a ZFS-style ACL to an internal SD.
1404 * Set owner/group too if selector indicates.
1405 * Always need to pass uid+gid, either the new
1406 * (when setting them) or existing, so that any
1407 * owner@ or group@ ACEs can be translated.
1408 *
1409 * This makes two passes over the ZFS ACL. The first builds a
1410 * "batch" request for idmap with results in mapinfo, and the
1411 * second builds the NT SD using the idmap SID results.
1412 */
1413 int
smbfs_acl_zfs2sd(vsecattr_t * acl_info,uid_t own_uid,gid_t own_gid,uint32_t selector,i_ntsd_t ** sdp)1414 smbfs_acl_zfs2sd(
1415 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
1416 vsecattr_t *acl_info,
1417 #else /* _KERNEL */
1418 acl_t *acl_info,
1419 #endif /* _KERNEL */
1420 uid_t own_uid,
1421 gid_t own_gid,
1422 uint32_t selector,
1423 i_ntsd_t **sdp)
1424 {
1425 struct mapinfo2sid *mip, *mip_acl, *mapinfo = NULL;
1426 int aclsz, error, i, mapcnt;
1427 int dacl_acecnt = 0;
1428 int sacl_acecnt = 0;
1429 int zacecnt = 0;
1430 ace_t *zacevec = NULL;
1431 ace_t *zacep;
1432 i_ntsd_t *sd = NULL;
1433 i_ntacl_t *acl = NULL;
1434 i_ntace_t **acep = NULL;
1435 idmap_get_handle_t *idmap_gh = NULL;
1436 idmap_stat idms;
1437
1438 /*
1439 * First, get all the UID+GID to SID mappings.
1440 * How many? Also sanity checks.
1441 */
1442 mapcnt = 0;
1443 if (selector & OWNER_SECURITY_INFORMATION) {
1444 if (own_uid == (uid_t)-1)
1445 return (EINVAL);
1446 mapcnt++;
1447 }
1448 if (selector & GROUP_SECURITY_INFORMATION) {
1449 if (own_gid == (gid_t)-1)
1450 return (EINVAL);
1451 mapcnt++;
1452 }
1453 if (selector & (DACL_SECURITY_INFORMATION |
1454 SACL_SECURITY_INFORMATION)) {
1455 if (acl_info == NULL)
1456 return (EINVAL);
1457 if (own_uid == (uid_t)-1)
1458 return (EINVAL);
1459 if (own_gid == (gid_t)-1)
1460 return (EINVAL);
1461 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
1462 if ((acl_info->vsa_mask & VSA_ACE) == 0)
1463 return (EINVAL);
1464 zacecnt = acl_info->vsa_aclcnt;
1465 zacevec = acl_info->vsa_aclentp;
1466 #else /* _KERNEL */
1467 if (acl_info->acl_type != ACE_T ||
1468 acl_info->acl_entry_size != sizeof (ace_t))
1469 return (EINVAL);
1470 zacecnt = acl_info->acl_cnt;
1471 zacevec = acl_info->acl_aclp;
1472 #endif /* _KERNEL */
1473 if (zacecnt == 0 || zacevec == NULL)
1474 return (EINVAL);
1475 mapcnt += zacecnt;
1476 }
1477 if (mapcnt == 0)
1478 return (EINVAL);
1479 mapinfo = MALLOC(mapcnt * sizeof (*mapinfo));
1480 if (mapinfo == NULL)
1481 return (ENOMEM);
1482 bzero(mapinfo, mapcnt * sizeof (*mapinfo));
1483 /* no more returns until errout */
1484
1485 /*
1486 * Get an imap "batch" request handle.
1487 */
1488 #ifdef _KERNEL
1489 idmap_gh = kidmap_get_create(curproc->p_zone);
1490 #else /* _KERNEL */
1491 idms = idmap_get_create(&idmap_gh);
1492 if (idms != IDMAP_SUCCESS) {
1493 error = ENOTACTIVE;
1494 goto errout;
1495 }
1496 #endif /* _KERNEL */
1497
1498 /*
1499 * Build our request to the idmap deamon,
1500 * getting SIDs for every Unix UID/GID.
1501 * Also count DACL and SACL ACEs here.
1502 */
1503 mip = mapinfo;
1504 if (selector & OWNER_SECURITY_INFORMATION) {
1505 error = mkrq_idmap_ux2sid(idmap_gh, mip,
1506 own_uid, IDM_TYPE_USER);
1507 if (error)
1508 goto errout;
1509 mip++;
1510 }
1511 if (selector & GROUP_SECURITY_INFORMATION) {
1512 error = mkrq_idmap_ux2sid(idmap_gh, mip,
1513 own_gid, IDM_TYPE_GROUP);
1514 if (error)
1515 goto errout;
1516 mip++;
1517 }
1518 if (selector & (DACL_SECURITY_INFORMATION |
1519 SACL_SECURITY_INFORMATION)) {
1520 int rqtype;
1521 uid_t uid;
1522
1523 zacep = zacevec;
1524 for (i = 0; i < zacecnt; i++) {
1525
1526 switch (zacep->a_type) {
1527 case ACE_ACCESS_ALLOWED_ACE_TYPE:
1528 case ACE_ACCESS_DENIED_ACE_TYPE:
1529 dacl_acecnt++;
1530 break;
1531 case ACE_SYSTEM_AUDIT_ACE_TYPE:
1532 case ACE_SYSTEM_ALARM_ACE_TYPE:
1533 sacl_acecnt++;
1534 break;
1535 /* other types todo */
1536 }
1537
1538 if (zacep->a_flags & ACE_EVERYONE) {
1539 rqtype = IDM_EVERYONE;
1540 uid = (uid_t)-1;
1541 } else if (zacep->a_flags & ACE_GROUP) {
1542 /* owning group (a_who = -1) */
1543 rqtype = IDM_TYPE_GROUP;
1544 uid = (uid_t)own_gid;
1545 } else if (zacep->a_flags & ACE_OWNER) {
1546 /* owning user (a_who = -1) */
1547 rqtype = IDM_TYPE_USER;
1548 uid = (uid_t)own_uid;
1549 } else if (zacep->a_flags & ACE_IDENTIFIER_GROUP) {
1550 /* regular group */
1551 rqtype = IDM_TYPE_GROUP;
1552 uid = zacep->a_who;
1553 } else {
1554 rqtype = IDM_TYPE_USER;
1555 uid = zacep->a_who;
1556 }
1557
1558 error = mkrq_idmap_ux2sid(idmap_gh, mip, uid, rqtype);
1559 if (error)
1560 goto errout;
1561 zacep++;
1562 mip++;
1563 }
1564 }
1565
1566 idms = I_getmappings(idmap_gh);
1567 if (idms != IDMAP_SUCCESS) {
1568 /* creative error choice */
1569 error = EIDRM;
1570 goto errout;
1571 }
1572
1573 /*
1574 * With any luck, we now have a Windows SID for
1575 * every Unix UID or GID in the NFS/ZFS ACL.
1576 * The remaining work is just format conversion,
1577 * memory allocation, etc.
1578 */
1579 if ((sd = MALLOC(sizeof (*sd))) == NULL) {
1580 error = ENOMEM;
1581 goto errout;
1582 }
1583 bzero(sd, sizeof (*sd));
1584 sd->sd_revision = NT_SD_REVISION;
1585
1586 mip = mapinfo;
1587 if (selector & OWNER_SECURITY_INFORMATION) {
1588 error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid,
1589 &sd->sd_owner);
1590 mip++;
1591 }
1592 if (selector & GROUP_SECURITY_INFORMATION) {
1593 error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid,
1594 &sd->sd_group);
1595 mip++;
1596 }
1597
1598 /*
1599 * If setting both DACL and SACL, we will
1600 * make two passes starting here in mapinfo.
1601 */
1602 mip_acl = mip;
1603
1604 if (selector & DACL_SECURITY_INFORMATION) {
1605 /*
1606 * Caller wants to set the DACL.
1607 */
1608 aclsz = I_ACL_SIZE(dacl_acecnt);
1609 if ((acl = MALLOC(aclsz)) == NULL) {
1610 error = ENOMEM;
1611 goto errout;
1612 }
1613 bzero(acl, aclsz);
1614
1615 acl->acl_revision = NT_ACL_REVISION;
1616 acl->acl_acecount = (uint16_t)dacl_acecnt;
1617 acep = &acl->acl_acevec[0];
1618
1619 /* 1st pass - scan for DACL ACE types. */
1620 mip = mip_acl;
1621 zacep = zacevec;
1622 for (i = 0; i < zacecnt; i++) {
1623
1624 switch (zacep->a_type) {
1625 case ACE_ACCESS_ALLOWED_ACE_TYPE:
1626 case ACE_ACCESS_DENIED_ACE_TYPE:
1627 error = zace2ntace(acep, zacep, mip);
1628 if (error != 0)
1629 goto errout;
1630 acep++;
1631 break;
1632
1633 case ACE_SYSTEM_AUDIT_ACE_TYPE:
1634 case ACE_SYSTEM_ALARM_ACE_TYPE:
1635 break;
1636 /* other types todo */
1637 }
1638 zacep++;
1639 mip++;
1640 }
1641 sd->sd_dacl = acl;
1642 acl = NULL;
1643 sd->sd_flags |= SD_DACL_PRESENT;
1644 }
1645
1646 if (selector & SACL_SECURITY_INFORMATION) {
1647 /*
1648 * Caller wants to set the SACL.
1649 */
1650 aclsz = I_ACL_SIZE(sacl_acecnt);
1651 if ((acl = MALLOC(aclsz)) == NULL) {
1652 error = ENOMEM;
1653 goto errout;
1654 }
1655 bzero(acl, aclsz);
1656
1657 acl->acl_revision = NT_ACL_REVISION;
1658 acl->acl_acecount = (uint16_t)sacl_acecnt;
1659 acep = &acl->acl_acevec[0];
1660
1661 /* 2nd pass - scan for SACL ACE types. */
1662 mip = mip_acl;
1663 zacep = zacevec;
1664 for (i = 0; i < zacecnt; i++) {
1665
1666 switch (zacep->a_type) {
1667 case ACE_ACCESS_ALLOWED_ACE_TYPE:
1668 case ACE_ACCESS_DENIED_ACE_TYPE:
1669 break;
1670
1671 case ACE_SYSTEM_AUDIT_ACE_TYPE:
1672 case ACE_SYSTEM_ALARM_ACE_TYPE:
1673 error = zace2ntace(acep, zacep, mip);
1674 if (error != 0)
1675 goto errout;
1676 acep++;
1677 break;
1678 /* other types todo */
1679 }
1680 zacep++;
1681 mip++;
1682 }
1683 sd->sd_sacl = acl;
1684 acl = NULL;
1685 sd->sd_flags |= SD_SACL_PRESENT;
1686 }
1687
1688 *sdp = sd;
1689 error = 0;
1690
1691 errout:
1692 if (error != 0) {
1693 if (acl != NULL)
1694 ifree_acl(acl);
1695 if (sd != NULL)
1696 smbfs_acl_free_sd(sd);
1697 }
1698 if (mapinfo != NULL)
1699 FREESZ(mapinfo, mapcnt * sizeof (*mapinfo));
1700 #ifdef _KERNEL
1701 if (idmap_gh != NULL)
1702 kidmap_get_destroy(idmap_gh);
1703 #else /* _KERNEL */
1704 if (idmap_gh != NULL)
1705 idmap_get_destroy(idmap_gh);
1706 #endif /* _KERNEL */
1707
1708 return (error);
1709 }
1710