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