102d09e03SGordon Ross /*
202d09e03SGordon Ross * CDDL HEADER START
302d09e03SGordon Ross *
402d09e03SGordon Ross * The contents of this file are subject to the terms of the
502d09e03SGordon Ross * Common Development and Distribution License (the "License").
602d09e03SGordon Ross * You may not use this file except in compliance with the License.
702d09e03SGordon Ross *
802d09e03SGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
902d09e03SGordon Ross * or http://www.opensolaris.org/os/licensing.
1002d09e03SGordon Ross * See the License for the specific language governing permissions
1102d09e03SGordon Ross * and limitations under the License.
1202d09e03SGordon Ross *
1302d09e03SGordon Ross * When distributing Covered Code, include this CDDL HEADER in each
1402d09e03SGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1502d09e03SGordon Ross * If applicable, add the following below this CDDL HEADER, with the
1602d09e03SGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
1702d09e03SGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
1802d09e03SGordon Ross *
1902d09e03SGordon Ross * CDDL HEADER END
2002d09e03SGordon Ross */
2102d09e03SGordon Ross
2202d09e03SGordon Ross /*
23*1fdeec65Sjoyce mcintosh * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
2402d09e03SGordon Ross */
2502d09e03SGordon Ross
2602d09e03SGordon Ross /*
2702d09e03SGordon Ross * ACL conversion support for smbfs
2802d09e03SGordon Ross * (To/from NT/ZFS-style ACLs.)
2902d09e03SGordon Ross */
3002d09e03SGordon Ross
3102d09e03SGordon Ross #include <sys/types.h>
3202d09e03SGordon Ross #include <sys/errno.h>
3302d09e03SGordon Ross #include <sys/acl.h>
3402d09e03SGordon Ross #include <sys/byteorder.h>
3502d09e03SGordon Ross
3602d09e03SGordon Ross #ifdef _KERNEL
3702d09e03SGordon Ross
3802d09e03SGordon Ross #include <sys/cred.h>
3902d09e03SGordon Ross #include <sys/cmn_err.h>
4002d09e03SGordon Ross #include <sys/kmem.h>
4102d09e03SGordon Ross #include <sys/sunddi.h>
4202d09e03SGordon Ross #include <sys/vnode.h>
4302d09e03SGordon Ross #include <sys/vfs.h>
4402d09e03SGordon Ross
4502d09e03SGordon Ross #include <sys/kidmap.h>
4602d09e03SGordon Ross
4702d09e03SGordon Ross #else /* _KERNEL */
4802d09e03SGordon Ross
4902d09e03SGordon Ross #include <stdio.h>
5002d09e03SGordon Ross #include <stdlib.h>
5102d09e03SGordon Ross #include <strings.h>
5202d09e03SGordon Ross
5302d09e03SGordon Ross #include <idmap.h>
5402d09e03SGordon Ross
5502d09e03SGordon Ross #endif /* _KERNEL */
5602d09e03SGordon Ross
5702d09e03SGordon Ross #include <netsmb/mchain.h>
5802d09e03SGordon Ross #include <netsmb/smb.h>
5902d09e03SGordon Ross #include "smbfs_ntacl.h"
6002d09e03SGordon Ross
61bd7c6f51SGordon Ross #define NT_SD_REVISION 1
62bd7c6f51SGordon Ross #define NT_ACL_REVISION 2
63bd7c6f51SGordon Ross
6402d09e03SGordon Ross #ifdef _KERNEL
6502d09e03SGordon Ross #define MALLOC(size) kmem_alloc(size, KM_SLEEP)
6602d09e03SGordon Ross #define FREESZ(p, sz) kmem_free(p, sz)
6702d09e03SGordon Ross #else /* _KERNEL */
6802d09e03SGordon Ross #define MALLOC(size) malloc(size)
6902d09e03SGordon Ross #ifndef lint
7002d09e03SGordon Ross #define FREESZ(p, sz) free(p)
7102d09e03SGordon Ross #else /* lint */
7202d09e03SGordon Ross /* ARGSUSED */
7302d09e03SGordon Ross static void
FREESZ(void * p,size_t sz)7402d09e03SGordon Ross FREESZ(void *p, size_t sz)
7502d09e03SGordon Ross {
7602d09e03SGordon Ross free(p);
7702d09e03SGordon Ross }
7802d09e03SGordon Ross #endif /* lint */
7902d09e03SGordon Ross #endif /* _KERNEL */
8002d09e03SGordon Ross
8102d09e03SGordon Ross #define ERRCHK(expr) if ((error = expr) != 0) goto errout
8202d09e03SGordon Ross
8302d09e03SGordon Ross /*
8402d09e03SGordon Ross * Security IDentifier (SID)
8502d09e03SGordon Ross */
8602d09e03SGordon Ross static void
ifree_sid(i_ntsid_t * sid)8702d09e03SGordon Ross ifree_sid(i_ntsid_t *sid)
8802d09e03SGordon Ross {
8902d09e03SGordon Ross size_t sz;
9002d09e03SGordon Ross
9102d09e03SGordon Ross if (sid == NULL)
9202d09e03SGordon Ross return;
9302d09e03SGordon Ross
9402d09e03SGordon Ross sz = I_SID_SIZE(sid->sid_subauthcount);
9502d09e03SGordon Ross FREESZ(sid, sz);
9602d09e03SGordon Ross }
9702d09e03SGordon Ross
9802d09e03SGordon Ross static int
md_get_sid(mdchain_t * mdp,i_ntsid_t ** sidp)9902d09e03SGordon Ross md_get_sid(mdchain_t *mdp, i_ntsid_t **sidp)
10002d09e03SGordon Ross {
10102d09e03SGordon Ross i_ntsid_t *sid = NULL;
10202d09e03SGordon Ross uint8_t revision, subauthcount;
10302d09e03SGordon Ross uint32_t *subauthp;
10402d09e03SGordon Ross size_t sidsz;
10502d09e03SGordon Ross int error, i;
10602d09e03SGordon Ross
10702d09e03SGordon Ross if ((error = md_get_uint8(mdp, &revision)) != 0)
10802d09e03SGordon Ross return (error);
10902d09e03SGordon Ross if ((error = md_get_uint8(mdp, &subauthcount)) != 0)
11002d09e03SGordon Ross return (error);
11102d09e03SGordon Ross
11202d09e03SGordon Ross sidsz = I_SID_SIZE(subauthcount);
11302d09e03SGordon Ross
11402d09e03SGordon Ross if ((sid = MALLOC(sidsz)) == NULL)
11502d09e03SGordon Ross return (ENOMEM);
11602d09e03SGordon Ross
11702d09e03SGordon Ross bzero(sid, sidsz);
11802d09e03SGordon Ross sid->sid_revision = revision;
11902d09e03SGordon Ross sid->sid_subauthcount = subauthcount;
12002d09e03SGordon Ross ERRCHK(md_get_mem(mdp, sid->sid_authority, 6, MB_MSYSTEM));
12102d09e03SGordon Ross
12202d09e03SGordon Ross subauthp = &sid->sid_subauthvec[0];
12302d09e03SGordon Ross for (i = 0; i < subauthcount; i++) {
12402d09e03SGordon Ross ERRCHK(md_get_uint32le(mdp, subauthp));
12502d09e03SGordon Ross subauthp++;
12602d09e03SGordon Ross }
12702d09e03SGordon Ross
12802d09e03SGordon Ross /* Success! */
12902d09e03SGordon Ross *sidp = sid;
13002d09e03SGordon Ross return (0);
13102d09e03SGordon Ross
13202d09e03SGordon Ross errout:
13302d09e03SGordon Ross ifree_sid(sid);
13402d09e03SGordon Ross return (error);
13502d09e03SGordon Ross }
13602d09e03SGordon Ross
13702d09e03SGordon Ross static int
mb_put_sid(mbchain_t * mbp,i_ntsid_t * sid)13802d09e03SGordon Ross mb_put_sid(mbchain_t *mbp, i_ntsid_t *sid)
13902d09e03SGordon Ross {
14002d09e03SGordon Ross uint32_t *subauthp;
14102d09e03SGordon Ross int error, i;
14202d09e03SGordon Ross
14302d09e03SGordon Ross if (sid == NULL)
14402d09e03SGordon Ross return (EINVAL);
14502d09e03SGordon Ross
14602d09e03SGordon Ross ERRCHK(mb_put_uint8(mbp, sid->sid_revision));
14702d09e03SGordon Ross ERRCHK(mb_put_uint8(mbp, sid->sid_subauthcount));
14802d09e03SGordon Ross ERRCHK(mb_put_mem(mbp, sid->sid_authority, 6, MB_MSYSTEM));
14902d09e03SGordon Ross
15002d09e03SGordon Ross subauthp = &sid->sid_subauthvec[0];
15102d09e03SGordon Ross for (i = 0; i < sid->sid_subauthcount; i++) {
15202d09e03SGordon Ross ERRCHK(mb_put_uint32le(mbp, *subauthp));
15302d09e03SGordon Ross subauthp++;
15402d09e03SGordon Ross }
15502d09e03SGordon Ross
15602d09e03SGordon Ross /* Success! */
15702d09e03SGordon Ross return (0);
15802d09e03SGordon Ross
15902d09e03SGordon Ross errout:
16002d09e03SGordon Ross return (error);
16102d09e03SGordon Ross }
16202d09e03SGordon Ross
16302d09e03SGordon Ross
16402d09e03SGordon Ross /*
16502d09e03SGordon Ross * Access Control Entry (ACE)
16602d09e03SGordon Ross */
16702d09e03SGordon Ross static void
ifree_ace(i_ntace_t * ace)16802d09e03SGordon Ross ifree_ace(i_ntace_t *ace)
16902d09e03SGordon Ross {
17002d09e03SGordon Ross
17102d09e03SGordon Ross if (ace == NULL)
17202d09e03SGordon Ross return;
17302d09e03SGordon Ross
174bd7c6f51SGordon Ross switch (ace->ace_hdr.ace_type) {
175bd7c6f51SGordon Ross case ACCESS_ALLOWED_ACE_TYPE:
176bd7c6f51SGordon Ross case ACCESS_DENIED_ACE_TYPE:
177bd7c6f51SGordon Ross case SYSTEM_AUDIT_ACE_TYPE:
178bd7c6f51SGordon Ross case SYSTEM_ALARM_ACE_TYPE:
179bd7c6f51SGordon Ross ifree_sid(ace->ace_v2.ace_sid);
180bd7c6f51SGordon Ross FREESZ(ace, sizeof (i_ntace_v2_t));
181bd7c6f51SGordon Ross break;
182bd7c6f51SGordon Ross /* other types todo */
183bd7c6f51SGordon Ross default:
184bd7c6f51SGordon Ross break;
185bd7c6f51SGordon Ross }
18602d09e03SGordon Ross }
18702d09e03SGordon Ross
18802d09e03SGordon Ross static int
md_get_ace(mdchain_t * mdp,i_ntace_t ** acep)18902d09e03SGordon Ross md_get_ace(mdchain_t *mdp, i_ntace_t **acep)
19002d09e03SGordon Ross {
19102d09e03SGordon Ross mdchain_t tmp_md;
192bd7c6f51SGordon Ross i_ntace_hdr_t ace_hdr;
19302d09e03SGordon Ross i_ntace_t *ace = NULL;
194bd7c6f51SGordon Ross uint16_t alloc_size;
19502d09e03SGordon Ross int error;
19602d09e03SGordon Ross
19702d09e03SGordon Ross /*
19802d09e03SGordon Ross * The ACE is realy variable length,
19902d09e03SGordon Ross * with format determined by the type.
20002d09e03SGordon Ross *
20102d09e03SGordon Ross * There may also be padding after it, so
202bd7c6f51SGordon Ross * decode it using a copy of the mdchain,
20302d09e03SGordon Ross * and then consume the specified length.
20402d09e03SGordon Ross */
20502d09e03SGordon Ross tmp_md = *mdp;
20602d09e03SGordon Ross
207bd7c6f51SGordon Ross /* Fixed-size ACE header */
208bd7c6f51SGordon Ross ERRCHK(md_get_uint8(&tmp_md, &ace_hdr.ace_type));
209bd7c6f51SGordon Ross ERRCHK(md_get_uint8(&tmp_md, &ace_hdr.ace_flags));
210bd7c6f51SGordon Ross ERRCHK(md_get_uint16le(&tmp_md, &ace_hdr.ace_size));
21102d09e03SGordon Ross
212bd7c6f51SGordon Ross switch (ace_hdr.ace_type) {
213bd7c6f51SGordon Ross case ACCESS_ALLOWED_ACE_TYPE:
214bd7c6f51SGordon Ross case ACCESS_DENIED_ACE_TYPE:
215bd7c6f51SGordon Ross case SYSTEM_AUDIT_ACE_TYPE:
216bd7c6f51SGordon Ross case SYSTEM_ALARM_ACE_TYPE:
217bd7c6f51SGordon Ross alloc_size = sizeof (i_ntace_v2_t);
218bd7c6f51SGordon Ross if ((ace = MALLOC(alloc_size)) == NULL)
219bd7c6f51SGordon Ross return (ENOMEM);
220bd7c6f51SGordon Ross bzero(ace, alloc_size);
221bd7c6f51SGordon Ross /* ACE header */
222bd7c6f51SGordon Ross ace->ace_hdr.ace_type = ace_hdr.ace_type;
223bd7c6f51SGordon Ross ace->ace_hdr.ace_flags = ace_hdr.ace_flags;
224bd7c6f51SGordon Ross ace->ace_hdr.ace_size = alloc_size;
225bd7c6f51SGordon Ross /* Type-specific data. */
226bd7c6f51SGordon Ross ERRCHK(md_get_uint32le(&tmp_md, &ace->ace_v2.ace_rights));
227bd7c6f51SGordon Ross ERRCHK(md_get_sid(&tmp_md, &ace->ace_v2.ace_sid));
228bd7c6f51SGordon Ross break;
22902d09e03SGordon Ross
230bd7c6f51SGordon Ross /* other types todo */
231bd7c6f51SGordon Ross default:
232bd7c6f51SGordon Ross error = EIO;
233bd7c6f51SGordon Ross goto errout;
234bd7c6f51SGordon Ross }
235bd7c6f51SGordon Ross
236bd7c6f51SGordon Ross /* Now actually consume ace_hdr.ace_size */
237bd7c6f51SGordon Ross ERRCHK(md_get_mem(mdp, NULL, ace_hdr.ace_size, MB_MSYSTEM));
23802d09e03SGordon Ross
23902d09e03SGordon Ross /* Success! */
24002d09e03SGordon Ross *acep = ace;
24102d09e03SGordon Ross return (0);
24202d09e03SGordon Ross
24302d09e03SGordon Ross errout:
24402d09e03SGordon Ross ifree_ace(ace);
24502d09e03SGordon Ross return (error);
24602d09e03SGordon Ross }
24702d09e03SGordon Ross
24802d09e03SGordon Ross static int
mb_put_ace(mbchain_t * mbp,i_ntace_t * ace)24902d09e03SGordon Ross mb_put_ace(mbchain_t *mbp, i_ntace_t *ace)
25002d09e03SGordon Ross {
25102d09e03SGordon Ross int cnt0, error;
25202d09e03SGordon Ross uint16_t ace_len, *ace_len_p;
25302d09e03SGordon Ross
25402d09e03SGordon Ross if (ace == NULL)
25502d09e03SGordon Ross return (EINVAL);
25602d09e03SGordon Ross
25702d09e03SGordon Ross cnt0 = mbp->mb_count;
25802d09e03SGordon Ross
259bd7c6f51SGordon Ross /*
260bd7c6f51SGordon Ross * Put the (fixed-size) ACE header
261bd7c6f51SGordon Ross * Will fill in the length later.
262bd7c6f51SGordon Ross */
263bd7c6f51SGordon Ross ERRCHK(mb_put_uint8(mbp, ace->ace_hdr.ace_type));
264bd7c6f51SGordon Ross ERRCHK(mb_put_uint8(mbp, ace->ace_hdr.ace_flags));
26502d09e03SGordon Ross ace_len_p = mb_reserve(mbp, sizeof (*ace_len_p));
26602d09e03SGordon Ross if (ace_len_p == NULL) {
26702d09e03SGordon Ross error = ENOMEM;
26802d09e03SGordon Ross goto errout;
26902d09e03SGordon Ross }
27002d09e03SGordon Ross
271bd7c6f51SGordon Ross switch (ace->ace_hdr.ace_type) {
272bd7c6f51SGordon Ross case ACCESS_ALLOWED_ACE_TYPE:
273bd7c6f51SGordon Ross case ACCESS_DENIED_ACE_TYPE:
274bd7c6f51SGordon Ross case SYSTEM_AUDIT_ACE_TYPE:
275bd7c6f51SGordon Ross case SYSTEM_ALARM_ACE_TYPE:
276bd7c6f51SGordon Ross /* Put type-specific data. */
277bd7c6f51SGordon Ross ERRCHK(mb_put_uint32le(mbp, ace->ace_v2.ace_rights));
278bd7c6f51SGordon Ross ERRCHK(mb_put_sid(mbp, ace->ace_v2.ace_sid));
279bd7c6f51SGordon Ross break;
28002d09e03SGordon Ross
281bd7c6f51SGordon Ross /* other types todo */
282bd7c6f51SGordon Ross default:
283bd7c6f51SGordon Ross error = EIO;
284bd7c6f51SGordon Ross goto errout;
285bd7c6f51SGordon Ross }
286bd7c6f51SGordon Ross
287bd7c6f51SGordon Ross /* Fill in the (OtW) ACE length. */
28802d09e03SGordon Ross ace_len = mbp->mb_count - cnt0;
28902d09e03SGordon Ross *ace_len_p = htoles(ace_len);
29002d09e03SGordon Ross
29102d09e03SGordon Ross /* Success! */
29202d09e03SGordon Ross return (0);
29302d09e03SGordon Ross
29402d09e03SGordon Ross errout:
29502d09e03SGordon Ross return (error);
29602d09e03SGordon Ross }
29702d09e03SGordon Ross
29802d09e03SGordon Ross
29902d09e03SGordon Ross /*
30002d09e03SGordon Ross * Access Control List (ACL)
30102d09e03SGordon Ross */
30202d09e03SGordon Ross
30302d09e03SGordon Ross /* Not an OTW structure, so size can be at our convenience. */
30402d09e03SGordon Ross #define I_ACL_SIZE(cnt) (sizeof (i_ntacl_t) + (cnt) * sizeof (void *))
30502d09e03SGordon Ross
30602d09e03SGordon Ross static void
ifree_acl(i_ntacl_t * acl)30702d09e03SGordon Ross ifree_acl(i_ntacl_t *acl)
30802d09e03SGordon Ross {
30902d09e03SGordon Ross i_ntace_t **acep;
31002d09e03SGordon Ross size_t sz;
31102d09e03SGordon Ross int i;
31202d09e03SGordon Ross
31302d09e03SGordon Ross if (acl == NULL)
31402d09e03SGordon Ross return;
31502d09e03SGordon Ross
31602d09e03SGordon Ross acep = &acl->acl_acevec[0];
31702d09e03SGordon Ross for (i = 0; i < acl->acl_acecount; i++) {
31802d09e03SGordon Ross ifree_ace(*acep);
31902d09e03SGordon Ross acep++;
32002d09e03SGordon Ross }
32102d09e03SGordon Ross sz = I_ACL_SIZE(acl->acl_acecount);
32202d09e03SGordon Ross FREESZ(acl, sz);
32302d09e03SGordon Ross }
32402d09e03SGordon Ross
32502d09e03SGordon Ross static int
md_get_acl(mdchain_t * mdp,i_ntacl_t ** aclp)32602d09e03SGordon Ross md_get_acl(mdchain_t *mdp, i_ntacl_t **aclp)
32702d09e03SGordon Ross {
32802d09e03SGordon Ross i_ntacl_t *acl = NULL;
32902d09e03SGordon Ross i_ntace_t **acep;
33002d09e03SGordon Ross uint8_t revision;
33102d09e03SGordon Ross uint16_t acl_len, acecount;
33202d09e03SGordon Ross size_t aclsz;
33302d09e03SGordon Ross int i, error;
33402d09e03SGordon Ross
33502d09e03SGordon Ross if ((error = md_get_uint8(mdp, &revision)) != 0)
33602d09e03SGordon Ross return (error);
337bd7c6f51SGordon Ross if ((error = md_get_uint8(mdp, NULL)) != 0) /* pad1 */
33802d09e03SGordon Ross return (error);
33902d09e03SGordon Ross if ((error = md_get_uint16le(mdp, &acl_len)) != 0)
34002d09e03SGordon Ross return (error);
34102d09e03SGordon Ross if ((error = md_get_uint16le(mdp, &acecount)) != 0)
34202d09e03SGordon Ross return (error);
343bd7c6f51SGordon Ross if ((error = md_get_uint16le(mdp, NULL)) != 0) /* pad2 */
34402d09e03SGordon Ross return (error);
34502d09e03SGordon Ross
34602d09e03SGordon Ross aclsz = I_ACL_SIZE(acecount);
34702d09e03SGordon Ross if ((acl = MALLOC(aclsz)) == NULL)
34802d09e03SGordon Ross return (ENOMEM);
34902d09e03SGordon Ross bzero(acl, aclsz);
35002d09e03SGordon Ross acl->acl_revision = revision;
35102d09e03SGordon Ross acl->acl_acecount = acecount;
35202d09e03SGordon Ross
35302d09e03SGordon Ross acep = &acl->acl_acevec[0];
35402d09e03SGordon Ross for (i = 0; i < acl->acl_acecount; i++) {
35502d09e03SGordon Ross ERRCHK(md_get_ace(mdp, acep));
35602d09e03SGordon Ross acep++;
35702d09e03SGordon Ross }
35802d09e03SGordon Ross /*
35902d09e03SGordon Ross * There may be more data here, but
36002d09e03SGordon Ross * the caller takes care of that.
36102d09e03SGordon Ross */
36202d09e03SGordon Ross
36302d09e03SGordon Ross /* Success! */
36402d09e03SGordon Ross *aclp = acl;
36502d09e03SGordon Ross return (0);
36602d09e03SGordon Ross
36702d09e03SGordon Ross errout:
36802d09e03SGordon Ross ifree_acl(acl);
36902d09e03SGordon Ross return (error);
37002d09e03SGordon Ross }
37102d09e03SGordon Ross
37202d09e03SGordon Ross static int
mb_put_acl(mbchain_t * mbp,i_ntacl_t * acl)37302d09e03SGordon Ross mb_put_acl(mbchain_t *mbp, i_ntacl_t *acl)
37402d09e03SGordon Ross {
37502d09e03SGordon Ross i_ntace_t **acep;
37602d09e03SGordon Ross uint16_t acl_len, *acl_len_p;
37702d09e03SGordon Ross int i, cnt0, error;
37802d09e03SGordon Ross
37902d09e03SGordon Ross cnt0 = mbp->mb_count;
38002d09e03SGordon Ross
38102d09e03SGordon Ross ERRCHK(mb_put_uint8(mbp, acl->acl_revision));
38202d09e03SGordon Ross ERRCHK(mb_put_uint8(mbp, 0)); /* pad1 */
38302d09e03SGordon Ross acl_len_p = mb_reserve(mbp, sizeof (*acl_len_p));
38402d09e03SGordon Ross if (acl_len_p == NULL) {
38502d09e03SGordon Ross error = ENOMEM;
38602d09e03SGordon Ross goto errout;
38702d09e03SGordon Ross }
38802d09e03SGordon Ross ERRCHK(mb_put_uint16le(mbp, acl->acl_acecount));
38902d09e03SGordon Ross ERRCHK(mb_put_uint16le(mbp, 0)); /* pad2 */
39002d09e03SGordon Ross
39102d09e03SGordon Ross acep = &acl->acl_acevec[0];
39202d09e03SGordon Ross for (i = 0; i < acl->acl_acecount; i++) {
39302d09e03SGordon Ross ERRCHK(mb_put_ace(mbp, *acep));
39402d09e03SGordon Ross acep++;
39502d09e03SGordon Ross }
39602d09e03SGordon Ross
39702d09e03SGordon Ross /* Fill in acl_len_p */
39802d09e03SGordon Ross acl_len = mbp->mb_count - cnt0;
39902d09e03SGordon Ross *acl_len_p = htoles(acl_len);
40002d09e03SGordon Ross
40102d09e03SGordon Ross /* Success! */
40202d09e03SGordon Ross return (0);
40302d09e03SGordon Ross
40402d09e03SGordon Ross errout:
40502d09e03SGordon Ross return (error);
40602d09e03SGordon Ross }
40702d09e03SGordon Ross
40802d09e03SGordon Ross
40902d09e03SGordon Ross /*
41002d09e03SGordon Ross * Security Descriptor
41102d09e03SGordon Ross */
41202d09e03SGordon Ross void
smbfs_acl_free_sd(i_ntsd_t * sd)41302d09e03SGordon Ross smbfs_acl_free_sd(i_ntsd_t *sd)
41402d09e03SGordon Ross {
41502d09e03SGordon Ross
41602d09e03SGordon Ross if (sd == NULL)
41702d09e03SGordon Ross return;
41802d09e03SGordon Ross
41902d09e03SGordon Ross ifree_sid(sd->sd_owner);
42002d09e03SGordon Ross ifree_sid(sd->sd_group);
42102d09e03SGordon Ross ifree_acl(sd->sd_sacl);
42202d09e03SGordon Ross ifree_acl(sd->sd_dacl);
42302d09e03SGordon Ross
42402d09e03SGordon Ross FREESZ(sd, sizeof (*sd));
42502d09e03SGordon Ross }
42602d09e03SGordon Ross
42702d09e03SGordon Ross /*
42802d09e03SGordon Ross * Import a raw SD (mb chain) into "internal" form.
42902d09e03SGordon Ross * (like "absolute" form per. NT docs)
43002d09e03SGordon Ross * Returns allocated data in sdp
43102d09e03SGordon Ross *
43202d09e03SGordon Ross * Note: does NOT consume all the mdp data, so the
43302d09e03SGordon Ross * caller has to take care of that if necessary.
43402d09e03SGordon Ross */
43502d09e03SGordon Ross int
md_get_ntsd(mdchain_t * mdp,i_ntsd_t ** sdp)43602d09e03SGordon Ross md_get_ntsd(mdchain_t *mdp, i_ntsd_t **sdp)
43702d09e03SGordon Ross {
43802d09e03SGordon Ross i_ntsd_t *sd = NULL;
43902d09e03SGordon Ross mdchain_t top_md, tmp_md;
44002d09e03SGordon Ross uint32_t owneroff, groupoff, sacloff, dacloff;
44102d09e03SGordon Ross int error;
44202d09e03SGordon Ross
44302d09e03SGordon Ross if ((sd = MALLOC(sizeof (*sd))) == NULL)
44402d09e03SGordon Ross return (ENOMEM);
44502d09e03SGordon Ross bzero(sd, sizeof (*sd));
44602d09e03SGordon Ross
44702d09e03SGordon Ross /*
44802d09e03SGordon Ross * Offsets below are relative to this point,
44902d09e03SGordon Ross * so save the mdp state for use below.
45002d09e03SGordon Ross */
45102d09e03SGordon Ross top_md = *mdp;
45202d09e03SGordon Ross
45302d09e03SGordon Ross ERRCHK(md_get_uint8(mdp, &sd->sd_revision));
45402d09e03SGordon Ross ERRCHK(md_get_uint8(mdp, &sd->sd_rmctl));
45502d09e03SGordon Ross ERRCHK(md_get_uint16le(mdp, &sd->sd_flags));
45602d09e03SGordon Ross ERRCHK(md_get_uint32le(mdp, &owneroff));
45702d09e03SGordon Ross ERRCHK(md_get_uint32le(mdp, &groupoff));
45802d09e03SGordon Ross ERRCHK(md_get_uint32le(mdp, &sacloff));
45902d09e03SGordon Ross ERRCHK(md_get_uint32le(mdp, &dacloff));
46002d09e03SGordon Ross
46102d09e03SGordon Ross /*
462bd7c6f51SGordon Ross * The SD is "self-relative" on the wire,
463bd7c6f51SGordon Ross * but not after this decodes it.
464bd7c6f51SGordon Ross */
465bd7c6f51SGordon Ross sd->sd_flags &= ~SD_SELF_RELATIVE;
466bd7c6f51SGordon Ross
467bd7c6f51SGordon Ross /*
46802d09e03SGordon Ross * For each section make a temporary copy of the
46902d09e03SGordon Ross * top_md state, advance to the given offset, and
47002d09e03SGordon Ross * pass that to the lower md_get_xxx functions.
47102d09e03SGordon Ross * These could be marshalled in any order, but
47202d09e03SGordon Ross * are normally found in the order shown here.
47302d09e03SGordon Ross */
47402d09e03SGordon Ross if (sacloff) {
47502d09e03SGordon Ross tmp_md = top_md;
47602d09e03SGordon Ross md_get_mem(&tmp_md, NULL, sacloff, MB_MSYSTEM);
47702d09e03SGordon Ross ERRCHK(md_get_acl(&tmp_md, &sd->sd_sacl));
47802d09e03SGordon Ross }
47902d09e03SGordon Ross if (dacloff) {
48002d09e03SGordon Ross tmp_md = top_md;
48102d09e03SGordon Ross md_get_mem(&tmp_md, NULL, dacloff, MB_MSYSTEM);
48202d09e03SGordon Ross ERRCHK(md_get_acl(&tmp_md, &sd->sd_dacl));
48302d09e03SGordon Ross }
48402d09e03SGordon Ross if (owneroff) {
48502d09e03SGordon Ross tmp_md = top_md;
48602d09e03SGordon Ross md_get_mem(&tmp_md, NULL, owneroff, MB_MSYSTEM);
48702d09e03SGordon Ross ERRCHK(md_get_sid(&tmp_md, &sd->sd_owner));
48802d09e03SGordon Ross }
48902d09e03SGordon Ross if (groupoff) {
49002d09e03SGordon Ross tmp_md = top_md;
49102d09e03SGordon Ross md_get_mem(&tmp_md, NULL, groupoff, MB_MSYSTEM);
49202d09e03SGordon Ross ERRCHK(md_get_sid(&tmp_md, &sd->sd_group));
49302d09e03SGordon Ross }
49402d09e03SGordon Ross
49502d09e03SGordon Ross /* Success! */
49602d09e03SGordon Ross *sdp = sd;
49702d09e03SGordon Ross return (0);
49802d09e03SGordon Ross
49902d09e03SGordon Ross errout:
50002d09e03SGordon Ross smbfs_acl_free_sd(sd);
50102d09e03SGordon Ross return (error);
50202d09e03SGordon Ross }
50302d09e03SGordon Ross
50402d09e03SGordon Ross /*
50502d09e03SGordon Ross * Export an "internal" SD into an raw SD (mb chain).
50602d09e03SGordon Ross * (a.k.a "self-relative" form per. NT docs)
50702d09e03SGordon Ross * Returns allocated mbchain in mbp.
50802d09e03SGordon Ross */
50902d09e03SGordon Ross int
mb_put_ntsd(mbchain_t * mbp,i_ntsd_t * sd)51002d09e03SGordon Ross mb_put_ntsd(mbchain_t *mbp, i_ntsd_t *sd)
51102d09e03SGordon Ross {
51202d09e03SGordon Ross uint32_t *owneroffp, *groupoffp, *sacloffp, *dacloffp;
51302d09e03SGordon Ross uint32_t owneroff, groupoff, sacloff, dacloff;
514bd7c6f51SGordon Ross uint16_t flags;
51502d09e03SGordon Ross int cnt0, error;
51602d09e03SGordon Ross
51702d09e03SGordon Ross cnt0 = mbp->mb_count;
51802d09e03SGordon Ross owneroff = groupoff = sacloff = dacloff = 0;
51902d09e03SGordon Ross
520bd7c6f51SGordon Ross /* The SD is "self-relative" on the wire. */
521bd7c6f51SGordon Ross flags = sd->sd_flags | SD_SELF_RELATIVE;
522bd7c6f51SGordon Ross
52302d09e03SGordon Ross ERRCHK(mb_put_uint8(mbp, sd->sd_revision));
52402d09e03SGordon Ross ERRCHK(mb_put_uint8(mbp, sd->sd_rmctl));
525bd7c6f51SGordon Ross ERRCHK(mb_put_uint16le(mbp, flags));
52602d09e03SGordon Ross
52702d09e03SGordon Ross owneroffp = mb_reserve(mbp, sizeof (*owneroffp));
52802d09e03SGordon Ross groupoffp = mb_reserve(mbp, sizeof (*groupoffp));
52902d09e03SGordon Ross sacloffp = mb_reserve(mbp, sizeof (*sacloffp));
53002d09e03SGordon Ross dacloffp = mb_reserve(mbp, sizeof (*dacloffp));
53102d09e03SGordon Ross if (owneroffp == NULL || groupoffp == NULL ||
53202d09e03SGordon Ross sacloffp == NULL || dacloffp == NULL) {
53302d09e03SGordon Ross error = ENOMEM;
53402d09e03SGordon Ross goto errout;
53502d09e03SGordon Ross }
53602d09e03SGordon Ross
53702d09e03SGordon Ross /*
53802d09e03SGordon Ross * These could be marshalled in any order, but
53902d09e03SGordon Ross * are normally found in the order shown here.
54002d09e03SGordon Ross */
54102d09e03SGordon Ross if (sd->sd_sacl) {
54202d09e03SGordon Ross sacloff = mbp->mb_count - cnt0;
54302d09e03SGordon Ross ERRCHK(mb_put_acl(mbp, sd->sd_sacl));
54402d09e03SGordon Ross }
54502d09e03SGordon Ross if (sd->sd_dacl) {
54602d09e03SGordon Ross dacloff = mbp->mb_count - cnt0;
54702d09e03SGordon Ross ERRCHK(mb_put_acl(mbp, sd->sd_dacl));
54802d09e03SGordon Ross }
54902d09e03SGordon Ross if (sd->sd_owner) {
55002d09e03SGordon Ross owneroff = mbp->mb_count - cnt0;
55102d09e03SGordon Ross ERRCHK(mb_put_sid(mbp, sd->sd_owner));
55202d09e03SGordon Ross }
55302d09e03SGordon Ross if (sd->sd_group) {
55402d09e03SGordon Ross groupoff = mbp->mb_count - cnt0;
55502d09e03SGordon Ross ERRCHK(mb_put_sid(mbp, sd->sd_group));
55602d09e03SGordon Ross }
55702d09e03SGordon Ross
55802d09e03SGordon Ross /* Fill in the offsets */
55902d09e03SGordon Ross *owneroffp = htolel(owneroff);
56002d09e03SGordon Ross *groupoffp = htolel(groupoff);
56102d09e03SGordon Ross *sacloffp = htolel(sacloff);
56202d09e03SGordon Ross *dacloffp = htolel(dacloff);
56302d09e03SGordon Ross
56402d09e03SGordon Ross /* Success! */
56502d09e03SGordon Ross return (0);
56602d09e03SGordon Ross
56702d09e03SGordon Ross errout:
56802d09e03SGordon Ross return (error);
56902d09e03SGordon Ross }
57002d09e03SGordon Ross
57102d09e03SGordon Ross /*
572bd7c6f51SGordon Ross * ================================================================
573bd7c6f51SGordon Ross * Support for ACL fetch, including conversions
574bd7c6f51SGordon Ross * from Windows ACLs to NFSv4-style ACLs.
575bd7c6f51SGordon Ross * ================================================================
57602d09e03SGordon Ross */
57702d09e03SGordon Ross
578bd7c6f51SGordon Ross #define GENERIC_RIGHTS_MASK \
579bd7c6f51SGordon Ross (GENERIC_RIGHT_READ_ACCESS | GENERIC_RIGHT_WRITE_ACCESS |\
580bd7c6f51SGordon Ross GENERIC_RIGHT_EXECUTE_ACCESS | GENERIC_RIGHT_ALL_ACCESS)
581bd7c6f51SGordon Ross
582bd7c6f51SGordon Ross /*
583bd7c6f51SGordon Ross * Table for converting NT GENERIC_RIGHT_... to specific rights
584bd7c6f51SGordon Ross * appropriate for objects of type file.
585bd7c6f51SGordon Ross */
586bd7c6f51SGordon Ross struct gen2fsr {
587bd7c6f51SGordon Ross uint32_t gf_generic;
588bd7c6f51SGordon Ross uint32_t gf_specific;
589bd7c6f51SGordon Ross };
590bd7c6f51SGordon Ross static const struct gen2fsr
591bd7c6f51SGordon Ross smbfs_gen2fsr[] = {
592bd7c6f51SGordon Ross {
593bd7c6f51SGordon Ross GENERIC_RIGHT_READ_ACCESS,
594bd7c6f51SGordon Ross STD_RIGHT_SYNCHRONIZE_ACCESS |
595bd7c6f51SGordon Ross STD_RIGHT_READ_CONTROL_ACCESS |
596bd7c6f51SGordon Ross SA_RIGHT_FILE_READ_ATTRIBUTES |
597bd7c6f51SGordon Ross SA_RIGHT_FILE_READ_EA |
598bd7c6f51SGordon Ross SA_RIGHT_FILE_READ_DATA },
599bd7c6f51SGordon Ross {
600bd7c6f51SGordon Ross GENERIC_RIGHT_WRITE_ACCESS,
601bd7c6f51SGordon Ross STD_RIGHT_SYNCHRONIZE_ACCESS |
602bd7c6f51SGordon Ross STD_RIGHT_READ_CONTROL_ACCESS |
603bd7c6f51SGordon Ross SA_RIGHT_FILE_WRITE_ATTRIBUTES |
604bd7c6f51SGordon Ross SA_RIGHT_FILE_WRITE_EA |
605bd7c6f51SGordon Ross SA_RIGHT_FILE_APPEND_DATA |
606bd7c6f51SGordon Ross SA_RIGHT_FILE_WRITE_DATA },
607bd7c6f51SGordon Ross {
608bd7c6f51SGordon Ross GENERIC_RIGHT_EXECUTE_ACCESS,
609bd7c6f51SGordon Ross STD_RIGHT_SYNCHRONIZE_ACCESS |
610bd7c6f51SGordon Ross STD_RIGHT_READ_CONTROL_ACCESS |
611bd7c6f51SGordon Ross SA_RIGHT_FILE_READ_ATTRIBUTES |
612bd7c6f51SGordon Ross SA_RIGHT_FILE_EXECUTE },
613bd7c6f51SGordon Ross {
614bd7c6f51SGordon Ross GENERIC_RIGHT_ALL_ACCESS,
615bd7c6f51SGordon Ross STD_RIGHT_SYNCHRONIZE_ACCESS |
616bd7c6f51SGordon Ross STD_RIGHT_WRITE_OWNER_ACCESS |
617bd7c6f51SGordon Ross STD_RIGHT_WRITE_DAC_ACCESS |
618bd7c6f51SGordon Ross STD_RIGHT_READ_CONTROL_ACCESS |
619bd7c6f51SGordon Ross STD_RIGHT_DELETE_ACCESS |
620bd7c6f51SGordon Ross SA_RIGHT_FILE_ALL_ACCESS },
621bd7c6f51SGordon Ross { 0, 0 }
622bd7c6f51SGordon Ross };
623bd7c6f51SGordon Ross
624bd7c6f51SGordon Ross /*
625bd7c6f51SGordon Ross * Table for translating ZFS ACE flags to NT ACE flags.
626bd7c6f51SGordon Ross * The low four bits are the same, but not others.
627bd7c6f51SGordon Ross */
628bd7c6f51SGordon Ross struct zaf2naf {
629bd7c6f51SGordon Ross uint16_t za_flag;
630bd7c6f51SGordon Ross uint8_t na_flag;
631bd7c6f51SGordon Ross };
632bd7c6f51SGordon Ross static const struct zaf2naf
633bd7c6f51SGordon Ross smbfs_zaf2naf[] = {
634bd7c6f51SGordon Ross { ACE_FILE_INHERIT_ACE, OBJECT_INHERIT_ACE_FLAG },
635bd7c6f51SGordon Ross { ACE_DIRECTORY_INHERIT_ACE, CONTAINER_INHERIT_ACE_FLAG },
636bd7c6f51SGordon Ross { ACE_NO_PROPAGATE_INHERIT_ACE, NO_PROPAGATE_INHERIT_ACE_FLAG },
637bd7c6f51SGordon Ross { ACE_INHERIT_ONLY_ACE, INHERIT_ONLY_ACE_FLAG },
638bd7c6f51SGordon Ross { ACE_INHERITED_ACE, INHERITED_ACE_FLAG },
639bd7c6f51SGordon Ross { ACE_SUCCESSFUL_ACCESS_ACE_FLAG, SUCCESSFUL_ACCESS_ACE_FLAG },
640bd7c6f51SGordon Ross { ACE_FAILED_ACCESS_ACE_FLAG, FAILED_ACCESS_ACE_FLAG },
641bd7c6f51SGordon Ross { 0, 0 }
642bd7c6f51SGordon Ross };
64302d09e03SGordon Ross
64402d09e03SGordon Ross /*
64502d09e03SGordon Ross * Convert an NT SID to a string. Optionally return the
64602d09e03SGordon Ross * last sub-authority (or "relative ID" -- RID) in *ridp
64702d09e03SGordon Ross * and truncate the output string after the domain part.
64802d09e03SGordon Ross * If ridp==NULL, the output string is the whole SID,
64902d09e03SGordon Ross * including both the domain and RID.
65002d09e03SGordon Ross *
65102d09e03SGordon Ross * Return length written, or -1 on error.
65202d09e03SGordon Ross */
65302d09e03SGordon Ross int
smbfs_sid2str(i_ntsid_t * sid,char * obuf,size_t osz,uint32_t * ridp)65402d09e03SGordon Ross smbfs_sid2str(i_ntsid_t *sid,
65502d09e03SGordon Ross char *obuf, size_t osz, uint32_t *ridp)
65602d09e03SGordon Ross {
65702d09e03SGordon Ross char *s = obuf;
65802d09e03SGordon Ross uint64_t auth = 0;
65902d09e03SGordon Ross uint_t i, n;
66002d09e03SGordon Ross uint32_t subs, *ip;
66102d09e03SGordon Ross
66202d09e03SGordon Ross n = snprintf(s, osz, "S-%u", sid->sid_revision);
66302d09e03SGordon Ross if (n > osz)
66402d09e03SGordon Ross return (-1);
66502d09e03SGordon Ross s += n; osz -= n;
66602d09e03SGordon Ross
66702d09e03SGordon Ross for (i = 0; i < 6; i++)
66802d09e03SGordon Ross auth = (auth << 8) | sid->sid_authority[i];
66902d09e03SGordon Ross n = snprintf(s, osz, "-%llu", (u_longlong_t)auth);
67002d09e03SGordon Ross if (n > osz)
67102d09e03SGordon Ross return (-1);
67202d09e03SGordon Ross s += n; osz -= n;
67302d09e03SGordon Ross
67402d09e03SGordon Ross subs = sid->sid_subauthcount;
67502d09e03SGordon Ross if (subs < 1 || subs > 15)
67602d09e03SGordon Ross return (-1);
67702d09e03SGordon Ross if (ridp)
67802d09e03SGordon Ross subs--;
67902d09e03SGordon Ross
68002d09e03SGordon Ross ip = &sid->sid_subauthvec[0];
68102d09e03SGordon Ross for (; subs; subs--, ip++) {
68202d09e03SGordon Ross n = snprintf(s, osz, "-%u", *ip);
68302d09e03SGordon Ross if (n > osz)
68402d09e03SGordon Ross return (-1);
68502d09e03SGordon Ross s += n; osz -= n;
68602d09e03SGordon Ross }
68702d09e03SGordon Ross if (ridp)
68802d09e03SGordon Ross *ridp = *ip;
68902d09e03SGordon Ross
69002d09e03SGordon Ross /* LINTED E_PTRDIFF_OVERFLOW */
69102d09e03SGordon Ross return (s - obuf);
69202d09e03SGordon Ross }
69302d09e03SGordon Ross
69402d09e03SGordon Ross /*
69502d09e03SGordon Ross * Our interface to the idmap service.
69602d09e03SGordon Ross *
69702d09e03SGordon Ross * The idmap API is _almost_ the same between
69802d09e03SGordon Ross * kernel and user-level. But not quite...
69902d09e03SGordon Ross * Hope this improves readability below.
70002d09e03SGordon Ross */
70102d09e03SGordon Ross #ifdef _KERNEL
70202d09e03SGordon Ross
703bd7c6f51SGordon Ross #define I_getuidbysid(GH, SPP, RID, UIDP, SP) \
704bd7c6f51SGordon Ross kidmap_batch_getuidbysid(GH, SPP, RID, UIDP, SP)
705bd7c6f51SGordon Ross
706bd7c6f51SGordon Ross #define I_getgidbysid(GH, SPP, RID, GIDP, SP) \
707bd7c6f51SGordon Ross kidmap_batch_getgidbysid(GH, SPP, RID, GIDP, SP)
708bd7c6f51SGordon Ross
709bd7c6f51SGordon Ross #define I_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) \
71002d09e03SGordon Ross kidmap_batch_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP)
711bd7c6f51SGordon Ross
712bd7c6f51SGordon Ross #define I_getmappings kidmap_get_mappings
71302d09e03SGordon Ross
71402d09e03SGordon Ross #else /* _KERNEL */
71502d09e03SGordon Ross
716bd7c6f51SGordon Ross #define I_getuidbysid(GH, SPP, RID, UIDP, SP) \
717bd7c6f51SGordon Ross idmap_get_uidbysid(GH, SPP, RID, 0, UIDP, SP)
718bd7c6f51SGordon Ross
719bd7c6f51SGordon Ross #define I_getgidbysid(GH, SPP, RID, GIDP, SP) \
720bd7c6f51SGordon Ross idmap_get_gidbysid(GH, SPP, RID, 0, GIDP, SP)
721bd7c6f51SGordon Ross
722bd7c6f51SGordon Ross #define I_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) \
72302d09e03SGordon Ross idmap_get_pidbysid(GH, SPP, RID, 0, PIDP, ISUP, SP)
724bd7c6f51SGordon Ross
725bd7c6f51SGordon Ross #define I_getmappings idmap_get_mappings
72602d09e03SGordon Ross
72702d09e03SGordon Ross #endif /* _KERNEL */
72802d09e03SGordon Ross
72902d09e03SGordon Ross
73002d09e03SGordon Ross /*
731bd7c6f51SGordon Ross * The idmap request types, chosen so they also
732bd7c6f51SGordon Ross * match the values returned in mi_isuser.
733bd7c6f51SGordon Ross */
734bd7c6f51SGordon Ross #define IDM_TYPE_ANY -1
735bd7c6f51SGordon Ross #define IDM_TYPE_GROUP 0
736bd7c6f51SGordon Ross #define IDM_TYPE_USER 1
737bd7c6f51SGordon Ross
738bd7c6f51SGordon Ross /*
739bd7c6f51SGordon Ross * A sentinel value for mi_isuser (below) to indicate
74002d09e03SGordon Ross * that the SID is the well-known "Everyone" (S-1-1-0).
74102d09e03SGordon Ross * The idmap library only uses -1, 0, 1, so this value
74202d09e03SGordon Ross * is arbitrary but must not overlap w/ idmap values.
74302d09e03SGordon Ross * XXX: Could use a way for idmap to tell us when
74402d09e03SGordon Ross * it recognizes this well-known SID.
74502d09e03SGordon Ross */
746bd7c6f51SGordon Ross #define IDM_EVERYONE 11
747bd7c6f51SGordon Ross
748bd7c6f51SGordon Ross struct mapinfo2uid {
749bd7c6f51SGordon Ross uid_t mi_uid; /* or gid, or pid */
750bd7c6f51SGordon Ross int mi_isuser; /* IDM_TYPE */
751bd7c6f51SGordon Ross idmap_stat mi_status;
752bd7c6f51SGordon Ross };
75302d09e03SGordon Ross
75402d09e03SGordon Ross /*
75502d09e03SGordon Ross * Build an idmap request. Cleanup is
75602d09e03SGordon Ross * handled by the caller (error or not)
75702d09e03SGordon Ross */
75802d09e03SGordon Ross static int
mkrq_idmap_sid2ux(idmap_get_handle_t * idmap_gh,struct mapinfo2uid * mip,i_ntsid_t * sid,int req_type)75902d09e03SGordon Ross mkrq_idmap_sid2ux(
76002d09e03SGordon Ross idmap_get_handle_t *idmap_gh,
761bd7c6f51SGordon Ross struct mapinfo2uid *mip,
76202d09e03SGordon Ross i_ntsid_t *sid,
763bd7c6f51SGordon Ross int req_type)
76402d09e03SGordon Ross {
765bd7c6f51SGordon Ross char strbuf[256];
766bd7c6f51SGordon Ross char *sid_prefix;
76702d09e03SGordon Ross uint32_t rid;
76802d09e03SGordon Ross idmap_stat idms;
76902d09e03SGordon Ross
770bd7c6f51SGordon Ross if (smbfs_sid2str(sid, strbuf, sizeof (strbuf), &rid) < 0)
77102d09e03SGordon Ross return (EINVAL);
772bd7c6f51SGordon Ross sid_prefix = strbuf;
77302d09e03SGordon Ross
77402d09e03SGordon Ross /*
77502d09e03SGordon Ross * Give the "Everyone" group special treatment.
77602d09e03SGordon Ross */
77702d09e03SGordon Ross if (strcmp(sid_prefix, "S-1-1") == 0 && rid == 0) {
77802d09e03SGordon Ross /* This is "Everyone" */
77902d09e03SGordon Ross mip->mi_uid = (uid_t)-1;
780bd7c6f51SGordon Ross mip->mi_isuser = IDM_EVERYONE;
78102d09e03SGordon Ross mip->mi_status = 0;
78202d09e03SGordon Ross return (0);
78302d09e03SGordon Ross }
78402d09e03SGordon Ross
785bd7c6f51SGordon Ross switch (req_type) {
786bd7c6f51SGordon Ross
787bd7c6f51SGordon Ross case IDM_TYPE_USER:
788bd7c6f51SGordon Ross mip->mi_isuser = req_type;
789bd7c6f51SGordon Ross idms = I_getuidbysid(idmap_gh, sid_prefix, rid,
790bd7c6f51SGordon Ross &mip->mi_uid, &mip->mi_status);
791bd7c6f51SGordon Ross break;
792bd7c6f51SGordon Ross
793bd7c6f51SGordon Ross case IDM_TYPE_GROUP:
794bd7c6f51SGordon Ross mip->mi_isuser = req_type;
795bd7c6f51SGordon Ross idms = I_getgidbysid(idmap_gh, sid_prefix, rid,
796bd7c6f51SGordon Ross &mip->mi_uid, &mip->mi_status);
797bd7c6f51SGordon Ross break;
798bd7c6f51SGordon Ross
799bd7c6f51SGordon Ross case IDM_TYPE_ANY:
800bd7c6f51SGordon Ross idms = I_getpidbysid(idmap_gh, sid_prefix, rid,
80102d09e03SGordon Ross &mip->mi_uid, &mip->mi_isuser, &mip->mi_status);
802bd7c6f51SGordon Ross break;
803bd7c6f51SGordon Ross
804bd7c6f51SGordon Ross default:
805bd7c6f51SGordon Ross idms = IDMAP_ERR_OTHER;
806bd7c6f51SGordon Ross break;
807bd7c6f51SGordon Ross }
808bd7c6f51SGordon Ross
80902d09e03SGordon Ross if (idms != IDMAP_SUCCESS)
81002d09e03SGordon Ross return (EINVAL);
81102d09e03SGordon Ross
81202d09e03SGordon Ross return (0);
81302d09e03SGordon Ross }
81402d09e03SGordon Ross
815bd7c6f51SGordon Ross /*
816bd7c6f51SGordon Ross * Convert an NT ACE to a ZFS ACE.
817bd7c6f51SGordon Ross * ACE type was already validated.
818bd7c6f51SGordon Ross */
81902d09e03SGordon Ross static void
ntace2zace(ace_t * zacep,i_ntace_t * ntace,struct mapinfo2uid * mip)820bd7c6f51SGordon Ross ntace2zace(ace_t *zacep, i_ntace_t *ntace, struct mapinfo2uid *mip)
82102d09e03SGordon Ross {
822bd7c6f51SGordon Ross const struct zaf2naf *znaf;
823bd7c6f51SGordon Ross uid_t zwho;
82402d09e03SGordon Ross uint32_t zamask;
825bd7c6f51SGordon Ross uint16_t zflags;
82602d09e03SGordon Ross
82702d09e03SGordon Ross /*
828bd7c6f51SGordon Ross * Set the "ID type" flags in the ZFS ace flags.
82902d09e03SGordon Ross */
83002d09e03SGordon Ross zflags = 0;
83102d09e03SGordon Ross switch (mip->mi_isuser) {
832bd7c6f51SGordon Ross case IDM_EVERYONE:
833bd7c6f51SGordon Ross zflags = ACE_EVERYONE;
834bd7c6f51SGordon Ross zwho = (uid_t)-1;
83502d09e03SGordon Ross break;
836bd7c6f51SGordon Ross
837bd7c6f51SGordon Ross case IDM_TYPE_GROUP: /* it's a GID */
838bd7c6f51SGordon Ross zflags = ACE_IDENTIFIER_GROUP;
839bd7c6f51SGordon Ross zwho = mip->mi_uid;
84002d09e03SGordon Ross break;
841bd7c6f51SGordon Ross
84202d09e03SGordon Ross default:
843bd7c6f51SGordon Ross case IDM_TYPE_USER: /* it's a UID */
844bd7c6f51SGordon Ross zflags = 0;
845bd7c6f51SGordon Ross zwho = mip->mi_uid;
84602d09e03SGordon Ross break;
84702d09e03SGordon Ross }
84802d09e03SGordon Ross
84902d09e03SGordon Ross /*
850bd7c6f51SGordon Ross * Translate NT ACE flags to ZFS ACE flags.
85102d09e03SGordon Ross */
852bd7c6f51SGordon Ross for (znaf = smbfs_zaf2naf; znaf->za_flag; znaf++)
853bd7c6f51SGordon Ross if (ntace->ace_hdr.ace_flags & znaf->na_flag)
854bd7c6f51SGordon Ross zflags |= znaf->za_flag;
85502d09e03SGordon Ross
85602d09e03SGordon Ross /*
857bd7c6f51SGordon Ross * The "normal" access mask bits are the same, but
858bd7c6f51SGordon Ross * if the ACE has any GENERIC_RIGHT_... convert those
859bd7c6f51SGordon Ross * to specific rights. GENERIC bits are rarely seen,
860bd7c6f51SGordon Ross * but reportedly can happen with inherit-only ACEs.
86102d09e03SGordon Ross */
862bd7c6f51SGordon Ross zamask = ntace->ace_v2.ace_rights & ACE_ALL_PERMS;
863bd7c6f51SGordon Ross if (ntace->ace_v2.ace_rights & GENERIC_RIGHTS_MASK) {
864bd7c6f51SGordon Ross const struct gen2fsr *gf;
865bd7c6f51SGordon Ross for (gf = smbfs_gen2fsr; gf->gf_generic; gf++)
866bd7c6f51SGordon Ross if (ntace->ace_v2.ace_rights & gf->gf_generic)
867bd7c6f51SGordon Ross zamask |= gf->gf_specific;
86802d09e03SGordon Ross }
86902d09e03SGordon Ross
87002d09e03SGordon Ross /*
87102d09e03SGordon Ross * Fill in the ZFS-style ACE
87202d09e03SGordon Ross */
873bd7c6f51SGordon Ross zacep->a_who = zwho;
87402d09e03SGordon Ross zacep->a_access_mask = zamask;
87502d09e03SGordon Ross zacep->a_flags = zflags;
876bd7c6f51SGordon Ross zacep->a_type = ntace->ace_hdr.ace_type;
87702d09e03SGordon Ross }
87802d09e03SGordon Ross
87902d09e03SGordon Ross /*
88002d09e03SGordon Ross * Convert an internal SD to a ZFS-style ACL.
88102d09e03SGordon Ross * Note optional args: vsa/acl, uidp, gidp.
882bd7c6f51SGordon Ross *
883bd7c6f51SGordon Ross * This makes two passes over the SD, the first building a
884bd7c6f51SGordon Ross * "batch" request for idmap with results in mapinfo, the
885bd7c6f51SGordon Ross * second building a ZFS-style ACL using the idmap results.
88602d09e03SGordon Ross */
88702d09e03SGordon Ross int
smbfs_acl_sd2zfs(i_ntsd_t * sd,vsecattr_t * acl_info,uid_t * uidp,gid_t * gidp)88802d09e03SGordon Ross smbfs_acl_sd2zfs(
88902d09e03SGordon Ross i_ntsd_t *sd,
89002d09e03SGordon Ross #ifdef _KERNEL
89102d09e03SGordon Ross vsecattr_t *acl_info,
89202d09e03SGordon Ross #else /* _KERNEL */
89302d09e03SGordon Ross acl_t *acl_info,
89402d09e03SGordon Ross #endif /* _KERNEL */
89502d09e03SGordon Ross uid_t *uidp, gid_t *gidp)
89602d09e03SGordon Ross {
897bd7c6f51SGordon Ross struct mapinfo2uid *mip, *mapinfo = NULL;
89802d09e03SGordon Ross int error, i, mapcnt, zacecnt, zacl_size;
899bd7c6f51SGordon Ross ace_t *zacep0, *zacep;
900bd7c6f51SGordon Ross uid_t own_uid = (uid_t)-1;
901bd7c6f51SGordon Ross gid_t own_gid = (gid_t)-1;
90202d09e03SGordon Ross i_ntacl_t *ntacl;
90302d09e03SGordon Ross i_ntace_t **ntacep;
90402d09e03SGordon Ross idmap_get_handle_t *idmap_gh = NULL;
90502d09e03SGordon Ross idmap_stat idms;
90602d09e03SGordon Ross
90702d09e03SGordon Ross /*
90802d09e03SGordon Ross * sanity checks
90902d09e03SGordon Ross */
91002d09e03SGordon Ross if (acl_info) {
911bd7c6f51SGordon Ross #ifndef _KERNEL
91202d09e03SGordon Ross if (acl_info->acl_type != ACE_T ||
91302d09e03SGordon Ross acl_info->acl_aclp != NULL ||
91402d09e03SGordon Ross acl_info->acl_entry_size != sizeof (ace_t))
91502d09e03SGordon Ross return (EINVAL);
91602d09e03SGordon Ross #endif /* _KERNEL */
917bd7c6f51SGordon Ross if ((sd->sd_flags & SD_DACL_PRESENT) == 0)
918bd7c6f51SGordon Ross return (EINVAL);
919bd7c6f51SGordon Ross }
92002d09e03SGordon Ross
92102d09e03SGordon Ross /*
922bd7c6f51SGordon Ross * How many SID mappings will we need?
92302d09e03SGordon Ross */
92402d09e03SGordon Ross mapcnt = 0;
92502d09e03SGordon Ross if (sd->sd_owner)
92602d09e03SGordon Ross mapcnt++;
92702d09e03SGordon Ross if (sd->sd_group)
92802d09e03SGordon Ross mapcnt++;
929bd7c6f51SGordon Ross if ((sd->sd_flags & SD_SACL_PRESENT) &&
930bd7c6f51SGordon Ross (sd->sd_sacl != NULL))
93102d09e03SGordon Ross mapcnt += sd->sd_sacl->acl_acecount;
932bd7c6f51SGordon Ross if ((sd->sd_flags & SD_DACL_PRESENT) &&
933bd7c6f51SGordon Ross (sd->sd_dacl != NULL))
93402d09e03SGordon Ross mapcnt += sd->sd_dacl->acl_acecount;
935bd7c6f51SGordon Ross if (mapcnt == 0) {
936bd7c6f51SGordon Ross /*
937bd7c6f51SGordon Ross * We have a NULL DACL, SACL, and don't
938bd7c6f51SGordon Ross * have an owner or group, so there's no
939bd7c6f51SGordon Ross * idmap work to do. This is very rare,
940bd7c6f51SGordon Ross * so rather than complicate things below,
941bd7c6f51SGordon Ross * pretend we need one mapping slot.
942bd7c6f51SGordon Ross */
943bd7c6f51SGordon Ross mapcnt = 1;
944bd7c6f51SGordon Ross }
94502d09e03SGordon Ross
94602d09e03SGordon Ross mapinfo = MALLOC(mapcnt * sizeof (*mapinfo));
94702d09e03SGordon Ross if (mapinfo == NULL) {
94802d09e03SGordon Ross error = ENOMEM;
94902d09e03SGordon Ross goto errout;
95002d09e03SGordon Ross }
95102d09e03SGordon Ross bzero(mapinfo, mapcnt * sizeof (*mapinfo));
95202d09e03SGordon Ross
95302d09e03SGordon Ross
95402d09e03SGordon Ross /*
955bd7c6f51SGordon Ross * Get an imap "batch" request handle.
95602d09e03SGordon Ross */
95702d09e03SGordon Ross #ifdef _KERNEL
95802d09e03SGordon Ross idmap_gh = kidmap_get_create(curproc->p_zone);
95902d09e03SGordon Ross #else /* _KERNEL */
960*1fdeec65Sjoyce mcintosh idms = idmap_get_create(&idmap_gh);
96102d09e03SGordon Ross if (idms != IDMAP_SUCCESS) {
96202d09e03SGordon Ross error = ENOTACTIVE;
96302d09e03SGordon Ross goto errout;
96402d09e03SGordon Ross }
96502d09e03SGordon Ross #endif /* _KERNEL */
96602d09e03SGordon Ross
967bd7c6f51SGordon Ross /*
968bd7c6f51SGordon Ross * Build our request to the idmap deamon,
969bd7c6f51SGordon Ross * getting Unix IDs for every SID.
970bd7c6f51SGordon Ross */
97102d09e03SGordon Ross mip = mapinfo;
97202d09e03SGordon Ross if (sd->sd_owner) {
973bd7c6f51SGordon Ross error = mkrq_idmap_sid2ux(idmap_gh, mip,
974bd7c6f51SGordon Ross sd->sd_owner, IDM_TYPE_USER);
97502d09e03SGordon Ross if (error)
97602d09e03SGordon Ross goto errout;
97702d09e03SGordon Ross mip++;
97802d09e03SGordon Ross }
97902d09e03SGordon Ross if (sd->sd_group) {
980bd7c6f51SGordon Ross error = mkrq_idmap_sid2ux(idmap_gh, mip,
981bd7c6f51SGordon Ross sd->sd_group, IDM_TYPE_GROUP);
98202d09e03SGordon Ross if (error)
98302d09e03SGordon Ross goto errout;
98402d09e03SGordon Ross mip++;
98502d09e03SGordon Ross }
986bd7c6f51SGordon Ross if ((sd->sd_flags & SD_SACL_PRESENT) &&
987bd7c6f51SGordon Ross (sd->sd_sacl != NULL)) {
98802d09e03SGordon Ross ntacl = sd->sd_sacl;
98902d09e03SGordon Ross ntacep = &ntacl->acl_acevec[0];
99002d09e03SGordon Ross for (i = 0; i < ntacl->acl_acecount; i++) {
991bd7c6f51SGordon Ross error = mkrq_idmap_sid2ux(idmap_gh, mip,
992bd7c6f51SGordon Ross (*ntacep)->ace_v2.ace_sid, IDM_TYPE_ANY);
99302d09e03SGordon Ross if (error)
99402d09e03SGordon Ross goto errout;
99502d09e03SGordon Ross ntacep++;
99602d09e03SGordon Ross mip++;
99702d09e03SGordon Ross }
99802d09e03SGordon Ross }
999bd7c6f51SGordon Ross if ((sd->sd_flags & SD_DACL_PRESENT) &&
1000bd7c6f51SGordon Ross (sd->sd_dacl != NULL)) {
100102d09e03SGordon Ross ntacl = sd->sd_dacl;
100202d09e03SGordon Ross ntacep = &ntacl->acl_acevec[0];
100302d09e03SGordon Ross for (i = 0; i < ntacl->acl_acecount; i++) {
1004bd7c6f51SGordon Ross error = mkrq_idmap_sid2ux(idmap_gh, mip,
1005bd7c6f51SGordon Ross (*ntacep)->ace_v2.ace_sid, IDM_TYPE_ANY);
100602d09e03SGordon Ross if (error)
100702d09e03SGordon Ross goto errout;
100802d09e03SGordon Ross ntacep++;
100902d09e03SGordon Ross mip++;
101002d09e03SGordon Ross }
101102d09e03SGordon Ross }
101202d09e03SGordon Ross
1013bd7c6f51SGordon Ross if (mip != mapinfo) {
1014bd7c6f51SGordon Ross idms = I_getmappings(idmap_gh);
101502d09e03SGordon Ross if (idms != IDMAP_SUCCESS) {
101602d09e03SGordon Ross /* creative error choice */
101702d09e03SGordon Ross error = EIDRM;
101802d09e03SGordon Ross goto errout;
101902d09e03SGordon Ross }
1020bd7c6f51SGordon Ross }
102102d09e03SGordon Ross
102202d09e03SGordon Ross /*
102302d09e03SGordon Ross * With any luck, we now have Unix user/group IDs
102402d09e03SGordon Ross * for every Windows SID in the security descriptor.
102502d09e03SGordon Ross * The remaining work is just format conversion.
102602d09e03SGordon Ross */
102702d09e03SGordon Ross mip = mapinfo;
102802d09e03SGordon Ross if (sd->sd_owner) {
1029bd7c6f51SGordon Ross own_uid = mip->mi_uid;
103002d09e03SGordon Ross mip++;
103102d09e03SGordon Ross }
103202d09e03SGordon Ross if (sd->sd_group) {
1033bd7c6f51SGordon Ross own_gid = mip->mi_uid;
103402d09e03SGordon Ross mip++;
103502d09e03SGordon Ross }
103602d09e03SGordon Ross
1037bd7c6f51SGordon Ross if (uidp)
1038bd7c6f51SGordon Ross *uidp = own_uid;
1039bd7c6f51SGordon Ross if (gidp)
1040bd7c6f51SGordon Ross *gidp = own_gid;
1041bd7c6f51SGordon Ross
104202d09e03SGordon Ross if (acl_info == NULL) {
104302d09e03SGordon Ross /* Caller only wanted uid/gid */
1044bd7c6f51SGordon Ross goto done;
104502d09e03SGordon Ross }
104602d09e03SGordon Ross
104702d09e03SGordon Ross /*
104802d09e03SGordon Ross * Build the ZFS-style ACL
1049bd7c6f51SGordon Ross * First, allocate the most ZFS ACEs we'll need.
105002d09e03SGordon Ross */
105102d09e03SGordon Ross zacecnt = 0;
1052bd7c6f51SGordon Ross if ((sd->sd_flags & SD_SACL_PRESENT) &&
1053bd7c6f51SGordon Ross (sd->sd_sacl != NULL))
105402d09e03SGordon Ross zacecnt += sd->sd_sacl->acl_acecount;
1055bd7c6f51SGordon Ross
1056bd7c6f51SGordon Ross /* NB, have: (sd->sd_flags & SD_DACL_PRESENT) */
1057bd7c6f51SGordon Ross if ((sd->sd_dacl != NULL) &&
1058bd7c6f51SGordon Ross (sd->sd_dacl->acl_acecount > 0)) {
105902d09e03SGordon Ross zacecnt += sd->sd_dacl->acl_acecount;
1060bd7c6f51SGordon Ross } else {
1061bd7c6f51SGordon Ross /*
1062bd7c6f51SGordon Ross * DACL is NULL or empty. Either way,
1063bd7c6f51SGordon Ross * we'll need to add a ZFS ACE below.
1064bd7c6f51SGordon Ross */
1065bd7c6f51SGordon Ross zacecnt++;
1066bd7c6f51SGordon Ross }
106702d09e03SGordon Ross zacl_size = zacecnt * sizeof (ace_t);
1068bd7c6f51SGordon Ross zacep0 = MALLOC(zacl_size);
1069bd7c6f51SGordon Ross if (zacep0 == NULL) {
107002d09e03SGordon Ross error = ENOMEM;
107102d09e03SGordon Ross goto errout;
107202d09e03SGordon Ross }
1073bd7c6f51SGordon Ross zacep = zacep0;
107402d09e03SGordon Ross
1075bd7c6f51SGordon Ross if ((sd->sd_flags & SD_SACL_PRESENT) &&
1076bd7c6f51SGordon Ross (sd->sd_sacl != NULL)) {
107702d09e03SGordon Ross ntacl = sd->sd_sacl;
107802d09e03SGordon Ross ntacep = &ntacl->acl_acevec[0];
107902d09e03SGordon Ross for (i = 0; i < ntacl->acl_acecount; i++) {
108002d09e03SGordon Ross ntace2zace(zacep, *ntacep, mip);
108102d09e03SGordon Ross zacep++;
108202d09e03SGordon Ross ntacep++;
108302d09e03SGordon Ross mip++;
108402d09e03SGordon Ross }
108502d09e03SGordon Ross }
1086bd7c6f51SGordon Ross
1087bd7c6f51SGordon Ross /* NB, have: (sd->sd_flags & SD_DACL_PRESENT) */
1088bd7c6f51SGordon Ross if (sd->sd_dacl != NULL) {
108902d09e03SGordon Ross ntacl = sd->sd_dacl;
109002d09e03SGordon Ross ntacep = &ntacl->acl_acevec[0];
109102d09e03SGordon Ross for (i = 0; i < ntacl->acl_acecount; i++) {
109202d09e03SGordon Ross ntace2zace(zacep, *ntacep, mip);
109302d09e03SGordon Ross zacep++;
109402d09e03SGordon Ross ntacep++;
109502d09e03SGordon Ross mip++;
109602d09e03SGordon Ross }
109702d09e03SGordon Ross }
1098bd7c6f51SGordon Ross if (sd->sd_dacl == NULL) {
1099bd7c6f51SGordon Ross /*
1100bd7c6f51SGordon Ross * The SD has a NULL DACL. That means
1101bd7c6f51SGordon Ross * everyone@, full-control
1102bd7c6f51SGordon Ross */
1103bd7c6f51SGordon Ross zacep->a_who = (uid_t)-1;
1104bd7c6f51SGordon Ross zacep->a_access_mask = ACE_ALL_PERMS;
1105bd7c6f51SGordon Ross zacep->a_flags = ACE_EVERYONE;
1106bd7c6f51SGordon Ross zacep->a_type = ACCESS_ALLOWED_ACE_TYPE;
1107bd7c6f51SGordon Ross } else if (sd->sd_dacl->acl_acecount == 0) {
1108bd7c6f51SGordon Ross /*
1109bd7c6f51SGordon Ross * The SD has an Empty DACL. We need
1110bd7c6f51SGordon Ross * at least one ACE, so add one giving
1111bd7c6f51SGordon Ross * the owner the usual implied access.
1112bd7c6f51SGordon Ross */
1113bd7c6f51SGordon Ross zacep->a_who = (uid_t)-1;
1114bd7c6f51SGordon Ross zacep->a_access_mask = ACE_READ_ATTRIBUTES | \
1115bd7c6f51SGordon Ross ACE_READ_ACL | ACE_WRITE_ACL;
1116bd7c6f51SGordon Ross zacep->a_flags = ACE_OWNER;
1117bd7c6f51SGordon Ross zacep->a_type = ACCESS_ALLOWED_ACE_TYPE;
1118bd7c6f51SGordon Ross }
111902d09e03SGordon Ross
1120bd7c6f51SGordon Ross #ifdef _KERNEL
1121bd7c6f51SGordon Ross acl_info->vsa_aclcnt = zacecnt;
1122bd7c6f51SGordon Ross acl_info->vsa_aclentp = zacep0;
1123bd7c6f51SGordon Ross acl_info->vsa_aclentsz = zacl_size;
1124bd7c6f51SGordon Ross #else /* _KERNEL */
1125bd7c6f51SGordon Ross acl_info->acl_cnt = zacecnt;
1126bd7c6f51SGordon Ross acl_info->acl_aclp = zacep0;
1127bd7c6f51SGordon Ross #endif /* _KERNEL */
1128bd7c6f51SGordon Ross
1129bd7c6f51SGordon Ross done:
113002d09e03SGordon Ross error = 0;
113102d09e03SGordon Ross
113202d09e03SGordon Ross errout:
1133bd7c6f51SGordon Ross if (mapinfo != NULL)
113402d09e03SGordon Ross FREESZ(mapinfo, mapcnt * sizeof (*mapinfo));
1135bd7c6f51SGordon Ross #ifdef _KERNEL
1136bd7c6f51SGordon Ross if (idmap_gh != NULL)
1137bd7c6f51SGordon Ross kidmap_get_destroy(idmap_gh);
1138bd7c6f51SGordon Ross #else /* _KERNEL */
1139bd7c6f51SGordon Ross if (idmap_gh != NULL)
1140bd7c6f51SGordon Ross idmap_get_destroy(idmap_gh);
1141bd7c6f51SGordon Ross #endif /* _KERNEL */
114202d09e03SGordon Ross
114302d09e03SGordon Ross return (error);
114402d09e03SGordon Ross }
114502d09e03SGordon Ross
114602d09e03SGordon Ross
114702d09e03SGordon Ross /*
1148bd7c6f51SGordon Ross * ================================================================
1149bd7c6f51SGordon Ross * Support for ACL store, including conversions
1150bd7c6f51SGordon Ross * from NFSv4-style ACLs to Windows ACLs.
1151bd7c6f51SGordon Ross * ================================================================
115202d09e03SGordon Ross */
1153bd7c6f51SGordon Ross
1154bd7c6f51SGordon Ross /*
1155bd7c6f51SGordon Ross * Convert a "sid-prefix" string plus RID into an NT SID.
1156bd7c6f51SGordon Ross *
1157bd7c6f51SGordon Ross * If successful, sets *osid and returns zero,
1158bd7c6f51SGordon Ross * otherwise returns an errno value.
1159bd7c6f51SGordon Ross */
1160bd7c6f51SGordon Ross int
smbfs_str2sid(const char * sid_prefix,uint32_t * ridp,i_ntsid_t ** osidp)1161bd7c6f51SGordon Ross smbfs_str2sid(const char *sid_prefix, uint32_t *ridp, i_ntsid_t **osidp)
1162bd7c6f51SGordon Ross {
1163bd7c6f51SGordon Ross i_ntsid_t *sid = NULL;
1164bd7c6f51SGordon Ross u_longlong_t auth = 0;
1165bd7c6f51SGordon Ross ulong_t sa;
1166bd7c6f51SGordon Ross uint8_t sacnt;
1167bd7c6f51SGordon Ross const char *p;
1168bd7c6f51SGordon Ross char *np;
1169bd7c6f51SGordon Ross size_t size;
1170bd7c6f51SGordon Ross int i;
1171bd7c6f51SGordon Ross int err;
1172bd7c6f51SGordon Ross
1173bd7c6f51SGordon Ross if (sid_prefix == NULL)
1174bd7c6f51SGordon Ross return (EINVAL);
1175bd7c6f51SGordon Ross
1176bd7c6f51SGordon Ross p = sid_prefix;
1177bd7c6f51SGordon Ross if (strncmp(p, "S-1-", 4) != 0)
1178bd7c6f51SGordon Ross return (EINVAL);
1179bd7c6f51SGordon Ross p += 4;
1180bd7c6f51SGordon Ross
1181bd7c6f51SGordon Ross /* Parse the "authority" */
118202d09e03SGordon Ross #ifdef _KERNEL
1183bd7c6f51SGordon Ross err = ddi_strtoull(p, &np, 10, &auth);
1184bd7c6f51SGordon Ross if (err != 0)
1185bd7c6f51SGordon Ross return (err);
118602d09e03SGordon Ross #else /* _KERNEL */
1187bd7c6f51SGordon Ross auth = strtoull(p, &np, 10);
1188bd7c6f51SGordon Ross if (p == np)
1189bd7c6f51SGordon Ross return (EINVAL);
119002d09e03SGordon Ross #endif /* _KERNEL */
1191bd7c6f51SGordon Ross
1192bd7c6f51SGordon Ross /*
1193bd7c6f51SGordon Ross * Count the sub-authorities. Here, np points to
1194bd7c6f51SGordon Ross * the "-" before the first sub-authority.
1195bd7c6f51SGordon Ross */
1196bd7c6f51SGordon Ross sacnt = 0;
1197bd7c6f51SGordon Ross for (p = np; *p; p++) {
1198bd7c6f51SGordon Ross if (*p == '-')
1199bd7c6f51SGordon Ross sacnt++;
1200bd7c6f51SGordon Ross }
1201bd7c6f51SGordon Ross if (ridp != NULL)
1202bd7c6f51SGordon Ross sacnt++;
1203bd7c6f51SGordon Ross
1204bd7c6f51SGordon Ross /* Allocate the internal SID. */
1205bd7c6f51SGordon Ross size = I_SID_SIZE(sacnt);
1206bd7c6f51SGordon Ross sid = MALLOC(size);
1207bd7c6f51SGordon Ross if (sid == NULL)
1208bd7c6f51SGordon Ross return (ENOMEM);
1209bd7c6f51SGordon Ross bzero(sid, size);
1210bd7c6f51SGordon Ross
1211bd7c6f51SGordon Ross /* Fill it in. */
1212bd7c6f51SGordon Ross sid->sid_revision = 1;
1213bd7c6f51SGordon Ross sid->sid_subauthcount = sacnt;
1214bd7c6f51SGordon Ross for (i = 5; i >= 0; i--) {
1215bd7c6f51SGordon Ross sid->sid_authority[i] = auth & 0xFF;
1216bd7c6f51SGordon Ross auth = auth >> 8;
1217bd7c6f51SGordon Ross }
1218bd7c6f51SGordon Ross
1219bd7c6f51SGordon Ross err = EINVAL;
1220bd7c6f51SGordon Ross if (ridp != NULL)
1221bd7c6f51SGordon Ross sacnt--; /* Last SA not from string */
1222bd7c6f51SGordon Ross p = np;
1223bd7c6f51SGordon Ross for (i = 0; i < sacnt; i++) {
1224bd7c6f51SGordon Ross if (*p != '-') {
1225bd7c6f51SGordon Ross err = EINVAL;
1226bd7c6f51SGordon Ross goto out;
1227bd7c6f51SGordon Ross }
1228bd7c6f51SGordon Ross p++;
1229bd7c6f51SGordon Ross #ifdef _KERNEL
1230bd7c6f51SGordon Ross err = ddi_strtoul(p, &np, 10, &sa);
1231bd7c6f51SGordon Ross if (err != 0)
1232bd7c6f51SGordon Ross goto out;
1233bd7c6f51SGordon Ross #else /* _KERNEL */
1234bd7c6f51SGordon Ross sa = strtoul(p, &np, 10);
1235bd7c6f51SGordon Ross if (p == np) {
1236bd7c6f51SGordon Ross err = EINVAL;
1237bd7c6f51SGordon Ross goto out;
1238bd7c6f51SGordon Ross }
1239bd7c6f51SGordon Ross #endif /* _KERNEL */
1240bd7c6f51SGordon Ross sid->sid_subauthvec[i] = (uint32_t)sa;
1241bd7c6f51SGordon Ross p = np;
1242bd7c6f51SGordon Ross }
1243bd7c6f51SGordon Ross if (*p != '\0')
1244bd7c6f51SGordon Ross goto out;
1245bd7c6f51SGordon Ross if (ridp != NULL)
1246bd7c6f51SGordon Ross sid->sid_subauthvec[i] = *ridp;
1247bd7c6f51SGordon Ross err = 0;
1248bd7c6f51SGordon Ross
1249bd7c6f51SGordon Ross out:
1250bd7c6f51SGordon Ross if (err)
1251bd7c6f51SGordon Ross FREESZ(sid, size);
1252bd7c6f51SGordon Ross else
1253bd7c6f51SGordon Ross *osidp = sid;
1254bd7c6f51SGordon Ross
1255bd7c6f51SGordon Ross return (err);
1256bd7c6f51SGordon Ross }
1257bd7c6f51SGordon Ross
1258bd7c6f51SGordon Ross /*
1259bd7c6f51SGordon Ross * The idmap API is _almost_ the same between
1260bd7c6f51SGordon Ross * kernel and user-level. But not quite...
1261bd7c6f51SGordon Ross * Hope this improves readability below.
1262bd7c6f51SGordon Ross */
1263bd7c6f51SGordon Ross #ifdef _KERNEL
1264bd7c6f51SGordon Ross
1265bd7c6f51SGordon Ross #define I_getsidbyuid(GH, UID, SPP, RP, ST) \
1266bd7c6f51SGordon Ross kidmap_batch_getsidbyuid(GH, UID, SPP, RP, ST)
1267bd7c6f51SGordon Ross
1268bd7c6f51SGordon Ross #define I_getsidbygid(GH, GID, SPP, RP, ST) \
1269bd7c6f51SGordon Ross kidmap_batch_getsidbygid(GH, GID, SPP, RP, ST)
1270bd7c6f51SGordon Ross
1271bd7c6f51SGordon Ross #else /* _KERNEL */
1272bd7c6f51SGordon Ross
1273bd7c6f51SGordon Ross #define I_getsidbyuid(GH, UID, SPP, RP, ST) \
1274bd7c6f51SGordon Ross idmap_get_sidbyuid(GH, UID, 0, SPP, RP, ST)
1275bd7c6f51SGordon Ross
1276bd7c6f51SGordon Ross #define I_getsidbygid(GH, GID, SPP, RP, ST) \
1277bd7c6f51SGordon Ross idmap_get_sidbygid(GH, GID, 0, SPP, RP, ST)
1278bd7c6f51SGordon Ross
1279bd7c6f51SGordon Ross #endif /* _KERNEL */
1280bd7c6f51SGordon Ross
1281bd7c6f51SGordon Ross struct mapinfo2sid {
1282bd7c6f51SGordon Ross /* Yet another kernel vs. user difference. */
1283bd7c6f51SGordon Ross #ifdef _KERNEL
1284bd7c6f51SGordon Ross const char *mi_dsid; /* domain SID */
1285bd7c6f51SGordon Ross #else /* _KERNEL */
1286bd7c6f51SGordon Ross char *mi_dsid;
1287bd7c6f51SGordon Ross #endif /* _KERNEL */
1288bd7c6f51SGordon Ross uint32_t mi_rid; /* relative ID */
1289bd7c6f51SGordon Ross idmap_stat mi_status;
1290bd7c6f51SGordon Ross };
1291bd7c6f51SGordon Ross
1292bd7c6f51SGordon Ross /*
1293bd7c6f51SGordon Ross * Build an idmap request. Cleanup is
1294bd7c6f51SGordon Ross * handled by the caller (error or not)
1295bd7c6f51SGordon Ross */
1296bd7c6f51SGordon Ross static int
mkrq_idmap_ux2sid(idmap_get_handle_t * idmap_gh,struct mapinfo2sid * mip,uid_t uid,int req_type)1297bd7c6f51SGordon Ross mkrq_idmap_ux2sid(
1298bd7c6f51SGordon Ross idmap_get_handle_t *idmap_gh,
1299bd7c6f51SGordon Ross struct mapinfo2sid *mip,
1300bd7c6f51SGordon Ross uid_t uid, /* or gid */
1301bd7c6f51SGordon Ross int req_type)
1302bd7c6f51SGordon Ross {
1303bd7c6f51SGordon Ross idmap_stat idms;
1304bd7c6f51SGordon Ross
1305bd7c6f51SGordon Ross switch (req_type) {
1306bd7c6f51SGordon Ross
1307bd7c6f51SGordon Ross case IDM_TYPE_USER:
1308bd7c6f51SGordon Ross if (uid == (uid_t)-1)
1309bd7c6f51SGordon Ross return (EINVAL);
1310bd7c6f51SGordon Ross idms = I_getsidbyuid(idmap_gh, uid,
1311bd7c6f51SGordon Ross &mip->mi_dsid, &mip->mi_rid, &mip->mi_status);
1312bd7c6f51SGordon Ross break;
1313bd7c6f51SGordon Ross
1314bd7c6f51SGordon Ross case IDM_TYPE_GROUP:
1315bd7c6f51SGordon Ross if (uid == (uid_t)-1)
1316bd7c6f51SGordon Ross return (EINVAL);
1317bd7c6f51SGordon Ross idms = I_getsidbygid(idmap_gh, uid,
1318bd7c6f51SGordon Ross &mip->mi_dsid, &mip->mi_rid, &mip->mi_status);
1319bd7c6f51SGordon Ross break;
1320bd7c6f51SGordon Ross
1321bd7c6f51SGordon Ross case IDM_EVERYONE:
1322bd7c6f51SGordon Ross mip->mi_dsid = "S-1-1";
1323bd7c6f51SGordon Ross mip->mi_rid = 0;
1324bd7c6f51SGordon Ross mip->mi_status = 0;
1325bd7c6f51SGordon Ross idms = IDMAP_SUCCESS;
1326bd7c6f51SGordon Ross break;
1327bd7c6f51SGordon Ross
1328bd7c6f51SGordon Ross default:
1329bd7c6f51SGordon Ross idms = IDMAP_ERR_OTHER;
1330bd7c6f51SGordon Ross break;
1331bd7c6f51SGordon Ross }
1332bd7c6f51SGordon Ross
1333bd7c6f51SGordon Ross if (idms != IDMAP_SUCCESS)
1334bd7c6f51SGordon Ross return (EINVAL);
1335bd7c6f51SGordon Ross
1336bd7c6f51SGordon Ross return (0);
1337bd7c6f51SGordon Ross }
1338bd7c6f51SGordon Ross
1339bd7c6f51SGordon Ross /*
1340bd7c6f51SGordon Ross * Convert a ZFS ACE to an NT ACE.
1341bd7c6f51SGordon Ross * ACE type was already validated.
1342bd7c6f51SGordon Ross */
1343bd7c6f51SGordon Ross static int
zace2ntace(i_ntace_t ** ntacep,ace_t * zacep,struct mapinfo2sid * mip)1344bd7c6f51SGordon Ross zace2ntace(i_ntace_t **ntacep, ace_t *zacep, struct mapinfo2sid *mip)
1345bd7c6f51SGordon Ross {
1346bd7c6f51SGordon Ross const struct zaf2naf *znaf;
1347bd7c6f51SGordon Ross uint8_t aflags;
1348bd7c6f51SGordon Ross uint16_t alloc_size;
1349bd7c6f51SGordon Ross uint32_t rights;
1350bd7c6f51SGordon Ross i_ntace_t *ntace = NULL;
1351bd7c6f51SGordon Ross i_ntsid_t *sid = NULL;
1352bd7c6f51SGordon Ross int error;
1353bd7c6f51SGordon Ross
1354bd7c6f51SGordon Ross if (mip->mi_dsid == NULL || mip->mi_status != 0) {
1355bd7c6f51SGordon Ross return (EINVAL);
1356bd7c6f51SGordon Ross }
1357bd7c6f51SGordon Ross
1358bd7c6f51SGordon Ross /*
1359bd7c6f51SGordon Ross * Translate ZFS ACE flags to NT ACE flags.
1360bd7c6f51SGordon Ross */
1361bd7c6f51SGordon Ross aflags = 0;
1362bd7c6f51SGordon Ross for (znaf = smbfs_zaf2naf; znaf->za_flag; znaf++)
1363bd7c6f51SGordon Ross if (zacep->a_flags & znaf->za_flag)
1364bd7c6f51SGordon Ross aflags |= znaf->na_flag;
1365bd7c6f51SGordon Ross
1366bd7c6f51SGordon Ross /*
1367bd7c6f51SGordon Ross * The access rights bits are OK as-is.
1368bd7c6f51SGordon Ross */
1369bd7c6f51SGordon Ross rights = zacep->a_access_mask;
1370bd7c6f51SGordon Ross
1371bd7c6f51SGordon Ross /*
1372bd7c6f51SGordon Ross * Make sure we can get the SID.
1373bd7c6f51SGordon Ross * Note: allocates sid.
1374bd7c6f51SGordon Ross */
1375bd7c6f51SGordon Ross error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid, &sid);
1376bd7c6f51SGordon Ross if (error)
1377bd7c6f51SGordon Ross return (error);
1378bd7c6f51SGordon Ross
1379bd7c6f51SGordon Ross /*
1380bd7c6f51SGordon Ross * Allocate the NT ACE and fill it in.
1381bd7c6f51SGordon Ross */
1382bd7c6f51SGordon Ross alloc_size = sizeof (i_ntace_v2_t);
1383bd7c6f51SGordon Ross if ((ntace = MALLOC(alloc_size)) == NULL) {
1384bd7c6f51SGordon Ross ifree_sid(sid);
1385bd7c6f51SGordon Ross return (ENOMEM);
1386bd7c6f51SGordon Ross }
1387bd7c6f51SGordon Ross bzero(ntace, alloc_size);
1388bd7c6f51SGordon Ross
1389bd7c6f51SGordon Ross ntace->ace_hdr.ace_type = zacep->a_type;
1390bd7c6f51SGordon Ross ntace->ace_hdr.ace_flags = aflags;
1391bd7c6f51SGordon Ross ntace->ace_hdr.ace_size = alloc_size;
1392bd7c6f51SGordon Ross ntace->ace_v2.ace_rights = rights;
1393bd7c6f51SGordon Ross ntace->ace_v2.ace_sid = sid;
1394bd7c6f51SGordon Ross
1395bd7c6f51SGordon Ross *ntacep = ntace;
1396bd7c6f51SGordon Ross return (0);
1397bd7c6f51SGordon Ross }
1398bd7c6f51SGordon Ross
1399bd7c6f51SGordon Ross /*
1400bd7c6f51SGordon Ross * Convert a ZFS-style ACL to an internal SD.
1401bd7c6f51SGordon Ross * Set owner/group too if selector indicates.
1402bd7c6f51SGordon Ross * Always need to pass uid+gid, either the new
1403bd7c6f51SGordon Ross * (when setting them) or existing, so that any
1404bd7c6f51SGordon Ross * owner@ or group@ ACEs can be translated.
1405bd7c6f51SGordon Ross *
1406bd7c6f51SGordon Ross * This makes two passes over the ZFS ACL. The first builds a
1407bd7c6f51SGordon Ross * "batch" request for idmap with results in mapinfo, and the
1408bd7c6f51SGordon Ross * second builds the NT SD using the idmap SID results.
1409bd7c6f51SGordon Ross */
1410bd7c6f51SGordon Ross int
smbfs_acl_zfs2sd(vsecattr_t * acl_info,uid_t own_uid,gid_t own_gid,uint32_t selector,i_ntsd_t ** sdp)1411bd7c6f51SGordon Ross smbfs_acl_zfs2sd(
1412bd7c6f51SGordon Ross #ifdef _KERNEL
1413bd7c6f51SGordon Ross vsecattr_t *acl_info,
1414bd7c6f51SGordon Ross #else /* _KERNEL */
1415bd7c6f51SGordon Ross acl_t *acl_info,
1416bd7c6f51SGordon Ross #endif /* _KERNEL */
1417bd7c6f51SGordon Ross uid_t own_uid,
1418bd7c6f51SGordon Ross gid_t own_gid,
1419bd7c6f51SGordon Ross uint32_t selector,
142002d09e03SGordon Ross i_ntsd_t **sdp)
142102d09e03SGordon Ross {
1422bd7c6f51SGordon Ross struct mapinfo2sid *mip, *mip_acl, *mapinfo = NULL;
1423bd7c6f51SGordon Ross int aclsz, error, i, mapcnt;
1424bd7c6f51SGordon Ross int dacl_acecnt = 0;
1425bd7c6f51SGordon Ross int sacl_acecnt = 0;
1426bd7c6f51SGordon Ross int zacecnt = 0;
1427bd7c6f51SGordon Ross ace_t *zacevec = NULL;
1428bd7c6f51SGordon Ross ace_t *zacep;
1429bd7c6f51SGordon Ross i_ntsd_t *sd = NULL;
1430bd7c6f51SGordon Ross i_ntacl_t *acl = NULL;
1431bd7c6f51SGordon Ross i_ntace_t **acep = NULL;
1432bd7c6f51SGordon Ross idmap_get_handle_t *idmap_gh = NULL;
1433bd7c6f51SGordon Ross idmap_stat idms;
1434bd7c6f51SGordon Ross
1435bd7c6f51SGordon Ross /*
1436bd7c6f51SGordon Ross * First, get all the UID+GID to SID mappings.
1437bd7c6f51SGordon Ross * How many? Also sanity checks.
1438bd7c6f51SGordon Ross */
1439bd7c6f51SGordon Ross mapcnt = 0;
1440bd7c6f51SGordon Ross if (selector & OWNER_SECURITY_INFORMATION) {
1441bd7c6f51SGordon Ross if (own_uid == (uid_t)-1)
1442bd7c6f51SGordon Ross return (EINVAL);
1443bd7c6f51SGordon Ross mapcnt++;
1444bd7c6f51SGordon Ross }
1445bd7c6f51SGordon Ross if (selector & GROUP_SECURITY_INFORMATION) {
1446bd7c6f51SGordon Ross if (own_gid == (gid_t)-1)
1447bd7c6f51SGordon Ross return (EINVAL);
1448bd7c6f51SGordon Ross mapcnt++;
1449bd7c6f51SGordon Ross }
1450bd7c6f51SGordon Ross if (selector & (DACL_SECURITY_INFORMATION |
1451bd7c6f51SGordon Ross SACL_SECURITY_INFORMATION)) {
1452bd7c6f51SGordon Ross if (acl_info == NULL)
1453bd7c6f51SGordon Ross return (EINVAL);
1454bd7c6f51SGordon Ross if (own_uid == (uid_t)-1)
1455bd7c6f51SGordon Ross return (EINVAL);
1456bd7c6f51SGordon Ross if (own_gid == (gid_t)-1)
1457bd7c6f51SGordon Ross return (EINVAL);
1458bd7c6f51SGordon Ross #ifdef _KERNEL
1459bd7c6f51SGordon Ross if ((acl_info->vsa_mask & VSA_ACE) == 0)
1460bd7c6f51SGordon Ross return (EINVAL);
1461bd7c6f51SGordon Ross zacecnt = acl_info->vsa_aclcnt;
1462bd7c6f51SGordon Ross zacevec = acl_info->vsa_aclentp;
1463bd7c6f51SGordon Ross #else /* _KERNEL */
1464bd7c6f51SGordon Ross if (acl_info->acl_type != ACE_T ||
1465bd7c6f51SGordon Ross acl_info->acl_entry_size != sizeof (ace_t))
1466bd7c6f51SGordon Ross return (EINVAL);
1467bd7c6f51SGordon Ross zacecnt = acl_info->acl_cnt;
1468bd7c6f51SGordon Ross zacevec = acl_info->acl_aclp;
1469bd7c6f51SGordon Ross #endif /* _KERNEL */
1470bd7c6f51SGordon Ross if (zacecnt == 0 || zacevec == NULL)
1471bd7c6f51SGordon Ross return (EINVAL);
1472bd7c6f51SGordon Ross mapcnt += zacecnt;
1473bd7c6f51SGordon Ross }
1474bd7c6f51SGordon Ross if (mapcnt == 0)
1475bd7c6f51SGordon Ross return (EINVAL);
1476bd7c6f51SGordon Ross mapinfo = MALLOC(mapcnt * sizeof (*mapinfo));
1477bd7c6f51SGordon Ross if (mapinfo == NULL)
1478bd7c6f51SGordon Ross return (ENOMEM);
1479bd7c6f51SGordon Ross bzero(mapinfo, mapcnt * sizeof (*mapinfo));
1480bd7c6f51SGordon Ross /* no more returns until errout */
1481bd7c6f51SGordon Ross
1482bd7c6f51SGordon Ross /*
1483bd7c6f51SGordon Ross * Get an imap "batch" request handle.
1484bd7c6f51SGordon Ross */
1485bd7c6f51SGordon Ross #ifdef _KERNEL
1486bd7c6f51SGordon Ross idmap_gh = kidmap_get_create(curproc->p_zone);
1487bd7c6f51SGordon Ross #else /* _KERNEL */
1488*1fdeec65Sjoyce mcintosh idms = idmap_get_create(&idmap_gh);
1489bd7c6f51SGordon Ross if (idms != IDMAP_SUCCESS) {
1490bd7c6f51SGordon Ross error = ENOTACTIVE;
1491bd7c6f51SGordon Ross goto errout;
1492bd7c6f51SGordon Ross }
1493bd7c6f51SGordon Ross #endif /* _KERNEL */
1494bd7c6f51SGordon Ross
1495bd7c6f51SGordon Ross /*
1496bd7c6f51SGordon Ross * Build our request to the idmap deamon,
1497bd7c6f51SGordon Ross * getting SIDs for every Unix UID/GID.
1498bd7c6f51SGordon Ross * Also count DACL and SACL ACEs here.
1499bd7c6f51SGordon Ross */
1500bd7c6f51SGordon Ross mip = mapinfo;
1501bd7c6f51SGordon Ross if (selector & OWNER_SECURITY_INFORMATION) {
1502bd7c6f51SGordon Ross error = mkrq_idmap_ux2sid(idmap_gh, mip,
1503bd7c6f51SGordon Ross own_uid, IDM_TYPE_USER);
1504bd7c6f51SGordon Ross if (error)
1505bd7c6f51SGordon Ross goto errout;
1506bd7c6f51SGordon Ross mip++;
1507bd7c6f51SGordon Ross }
1508bd7c6f51SGordon Ross if (selector & GROUP_SECURITY_INFORMATION) {
1509bd7c6f51SGordon Ross error = mkrq_idmap_ux2sid(idmap_gh, mip,
1510bd7c6f51SGordon Ross own_gid, IDM_TYPE_GROUP);
1511bd7c6f51SGordon Ross if (error)
1512bd7c6f51SGordon Ross goto errout;
1513bd7c6f51SGordon Ross mip++;
1514bd7c6f51SGordon Ross }
1515bd7c6f51SGordon Ross if (selector & (DACL_SECURITY_INFORMATION |
1516bd7c6f51SGordon Ross SACL_SECURITY_INFORMATION)) {
1517bd7c6f51SGordon Ross int rqtype;
1518bd7c6f51SGordon Ross uid_t uid;
1519bd7c6f51SGordon Ross
1520bd7c6f51SGordon Ross zacep = zacevec;
1521bd7c6f51SGordon Ross for (i = 0; i < zacecnt; i++) {
1522bd7c6f51SGordon Ross
1523bd7c6f51SGordon Ross switch (zacep->a_type) {
1524bd7c6f51SGordon Ross case ACE_ACCESS_ALLOWED_ACE_TYPE:
1525bd7c6f51SGordon Ross case ACE_ACCESS_DENIED_ACE_TYPE:
1526bd7c6f51SGordon Ross dacl_acecnt++;
1527bd7c6f51SGordon Ross break;
1528bd7c6f51SGordon Ross case ACE_SYSTEM_AUDIT_ACE_TYPE:
1529bd7c6f51SGordon Ross case ACE_SYSTEM_ALARM_ACE_TYPE:
1530bd7c6f51SGordon Ross sacl_acecnt++;
1531bd7c6f51SGordon Ross break;
1532bd7c6f51SGordon Ross /* other types todo */
1533bd7c6f51SGordon Ross }
1534bd7c6f51SGordon Ross
1535bd7c6f51SGordon Ross if (zacep->a_flags & ACE_EVERYONE) {
1536bd7c6f51SGordon Ross rqtype = IDM_EVERYONE;
1537bd7c6f51SGordon Ross uid = (uid_t)-1;
1538bd7c6f51SGordon Ross } else if (zacep->a_flags & ACE_GROUP) {
1539bd7c6f51SGordon Ross /* owning group (a_who = -1) */
1540bd7c6f51SGordon Ross rqtype = IDM_TYPE_GROUP;
1541bd7c6f51SGordon Ross uid = (uid_t)own_gid;
1542bd7c6f51SGordon Ross } else if (zacep->a_flags & ACE_OWNER) {
1543bd7c6f51SGordon Ross /* owning user (a_who = -1) */
1544bd7c6f51SGordon Ross rqtype = IDM_TYPE_USER;
1545bd7c6f51SGordon Ross uid = (uid_t)own_uid;
1546bd7c6f51SGordon Ross } else if (zacep->a_flags & ACE_IDENTIFIER_GROUP) {
1547bd7c6f51SGordon Ross /* regular group */
1548bd7c6f51SGordon Ross rqtype = IDM_TYPE_GROUP;
1549bd7c6f51SGordon Ross uid = zacep->a_who;
1550bd7c6f51SGordon Ross } else {
1551bd7c6f51SGordon Ross rqtype = IDM_TYPE_USER;
1552bd7c6f51SGordon Ross uid = zacep->a_who;
1553bd7c6f51SGordon Ross }
1554bd7c6f51SGordon Ross
1555bd7c6f51SGordon Ross error = mkrq_idmap_ux2sid(idmap_gh, mip, uid, rqtype);
1556bd7c6f51SGordon Ross if (error)
1557bd7c6f51SGordon Ross goto errout;
1558bd7c6f51SGordon Ross zacep++;
1559bd7c6f51SGordon Ross mip++;
1560bd7c6f51SGordon Ross }
1561bd7c6f51SGordon Ross }
1562bd7c6f51SGordon Ross
1563bd7c6f51SGordon Ross idms = I_getmappings(idmap_gh);
1564bd7c6f51SGordon Ross if (idms != IDMAP_SUCCESS) {
1565bd7c6f51SGordon Ross /* creative error choice */
1566bd7c6f51SGordon Ross error = EIDRM;
1567bd7c6f51SGordon Ross goto errout;
1568bd7c6f51SGordon Ross }
1569bd7c6f51SGordon Ross
1570bd7c6f51SGordon Ross /*
1571bd7c6f51SGordon Ross * With any luck, we now have a Windows SID for
1572bd7c6f51SGordon Ross * every Unix UID or GID in the NFS/ZFS ACL.
1573bd7c6f51SGordon Ross * The remaining work is just format conversion,
1574bd7c6f51SGordon Ross * memory allocation, etc.
1575bd7c6f51SGordon Ross */
1576bd7c6f51SGordon Ross if ((sd = MALLOC(sizeof (*sd))) == NULL) {
1577bd7c6f51SGordon Ross error = ENOMEM;
1578bd7c6f51SGordon Ross goto errout;
1579bd7c6f51SGordon Ross }
1580bd7c6f51SGordon Ross bzero(sd, sizeof (*sd));
1581bd7c6f51SGordon Ross sd->sd_revision = NT_SD_REVISION;
1582bd7c6f51SGordon Ross
1583bd7c6f51SGordon Ross mip = mapinfo;
1584bd7c6f51SGordon Ross if (selector & OWNER_SECURITY_INFORMATION) {
1585bd7c6f51SGordon Ross error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid,
1586bd7c6f51SGordon Ross &sd->sd_owner);
1587bd7c6f51SGordon Ross mip++;
1588bd7c6f51SGordon Ross }
1589bd7c6f51SGordon Ross if (selector & GROUP_SECURITY_INFORMATION) {
1590bd7c6f51SGordon Ross error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid,
1591bd7c6f51SGordon Ross &sd->sd_group);
1592bd7c6f51SGordon Ross mip++;
1593bd7c6f51SGordon Ross }
1594bd7c6f51SGordon Ross
1595bd7c6f51SGordon Ross /*
1596bd7c6f51SGordon Ross * If setting both DACL and SACL, we will
1597bd7c6f51SGordon Ross * make two passes starting here in mapinfo.
1598bd7c6f51SGordon Ross */
1599bd7c6f51SGordon Ross mip_acl = mip;
1600bd7c6f51SGordon Ross
1601bd7c6f51SGordon Ross if (selector & DACL_SECURITY_INFORMATION) {
1602bd7c6f51SGordon Ross /*
1603bd7c6f51SGordon Ross * Caller wants to set the DACL.
1604bd7c6f51SGordon Ross */
1605bd7c6f51SGordon Ross aclsz = I_ACL_SIZE(dacl_acecnt);
1606bd7c6f51SGordon Ross if ((acl = MALLOC(aclsz)) == NULL) {
1607bd7c6f51SGordon Ross error = ENOMEM;
1608bd7c6f51SGordon Ross goto errout;
1609bd7c6f51SGordon Ross }
1610bd7c6f51SGordon Ross bzero(acl, aclsz);
1611bd7c6f51SGordon Ross
1612bd7c6f51SGordon Ross acl->acl_revision = NT_ACL_REVISION;
1613bd7c6f51SGordon Ross acl->acl_acecount = (uint16_t)dacl_acecnt;
1614bd7c6f51SGordon Ross acep = &acl->acl_acevec[0];
1615bd7c6f51SGordon Ross
1616bd7c6f51SGordon Ross /* 1st pass - scan for DACL ACE types. */
1617bd7c6f51SGordon Ross mip = mip_acl;
1618bd7c6f51SGordon Ross zacep = zacevec;
1619bd7c6f51SGordon Ross for (i = 0; i < zacecnt; i++) {
1620bd7c6f51SGordon Ross
1621bd7c6f51SGordon Ross switch (zacep->a_type) {
1622bd7c6f51SGordon Ross case ACE_ACCESS_ALLOWED_ACE_TYPE:
1623bd7c6f51SGordon Ross case ACE_ACCESS_DENIED_ACE_TYPE:
1624bd7c6f51SGordon Ross error = zace2ntace(acep, zacep, mip);
1625bd7c6f51SGordon Ross if (error != 0)
1626bd7c6f51SGordon Ross goto errout;
1627bd7c6f51SGordon Ross acep++;
1628bd7c6f51SGordon Ross break;
1629bd7c6f51SGordon Ross
1630bd7c6f51SGordon Ross case ACE_SYSTEM_AUDIT_ACE_TYPE:
1631bd7c6f51SGordon Ross case ACE_SYSTEM_ALARM_ACE_TYPE:
1632bd7c6f51SGordon Ross break;
1633bd7c6f51SGordon Ross /* other types todo */
1634bd7c6f51SGordon Ross }
1635bd7c6f51SGordon Ross zacep++;
1636bd7c6f51SGordon Ross mip++;
1637bd7c6f51SGordon Ross }
1638bd7c6f51SGordon Ross sd->sd_dacl = acl;
1639bd7c6f51SGordon Ross acl = NULL;
1640bd7c6f51SGordon Ross sd->sd_flags |= SD_DACL_PRESENT;
1641bd7c6f51SGordon Ross }
1642bd7c6f51SGordon Ross
1643bd7c6f51SGordon Ross if (selector & SACL_SECURITY_INFORMATION) {
1644bd7c6f51SGordon Ross /*
1645bd7c6f51SGordon Ross * Caller wants to set the SACL.
1646bd7c6f51SGordon Ross */
1647bd7c6f51SGordon Ross aclsz = I_ACL_SIZE(sacl_acecnt);
1648bd7c6f51SGordon Ross if ((acl = MALLOC(aclsz)) == NULL) {
1649bd7c6f51SGordon Ross error = ENOMEM;
1650bd7c6f51SGordon Ross goto errout;
1651bd7c6f51SGordon Ross }
1652bd7c6f51SGordon Ross bzero(acl, aclsz);
1653bd7c6f51SGordon Ross
1654bd7c6f51SGordon Ross acl->acl_revision = NT_ACL_REVISION;
1655bd7c6f51SGordon Ross acl->acl_acecount = (uint16_t)sacl_acecnt;
1656bd7c6f51SGordon Ross acep = &acl->acl_acevec[0];
1657bd7c6f51SGordon Ross
1658bd7c6f51SGordon Ross /* 2nd pass - scan for SACL ACE types. */
1659bd7c6f51SGordon Ross mip = mip_acl;
1660bd7c6f51SGordon Ross zacep = zacevec;
1661bd7c6f51SGordon Ross for (i = 0; i < zacecnt; i++) {
1662bd7c6f51SGordon Ross
1663bd7c6f51SGordon Ross switch (zacep->a_type) {
1664bd7c6f51SGordon Ross case ACE_ACCESS_ALLOWED_ACE_TYPE:
1665bd7c6f51SGordon Ross case ACE_ACCESS_DENIED_ACE_TYPE:
1666bd7c6f51SGordon Ross break;
1667bd7c6f51SGordon Ross
1668bd7c6f51SGordon Ross case ACE_SYSTEM_AUDIT_ACE_TYPE:
1669bd7c6f51SGordon Ross case ACE_SYSTEM_ALARM_ACE_TYPE:
1670bd7c6f51SGordon Ross error = zace2ntace(acep, zacep, mip);
1671bd7c6f51SGordon Ross if (error != 0)
1672bd7c6f51SGordon Ross goto errout;
1673bd7c6f51SGordon Ross acep++;
1674bd7c6f51SGordon Ross break;
1675bd7c6f51SGordon Ross /* other types todo */
1676bd7c6f51SGordon Ross }
1677bd7c6f51SGordon Ross zacep++;
1678bd7c6f51SGordon Ross mip++;
1679bd7c6f51SGordon Ross }
1680bd7c6f51SGordon Ross sd->sd_sacl = acl;
1681bd7c6f51SGordon Ross acl = NULL;
1682bd7c6f51SGordon Ross sd->sd_flags |= SD_SACL_PRESENT;
1683bd7c6f51SGordon Ross }
1684bd7c6f51SGordon Ross
1685bd7c6f51SGordon Ross *sdp = sd;
1686bd7c6f51SGordon Ross error = 0;
1687bd7c6f51SGordon Ross
1688bd7c6f51SGordon Ross errout:
1689bd7c6f51SGordon Ross if (error != 0) {
1690bd7c6f51SGordon Ross if (acl != NULL)
1691bd7c6f51SGordon Ross ifree_acl(acl);
1692bd7c6f51SGordon Ross if (sd != NULL)
1693bd7c6f51SGordon Ross smbfs_acl_free_sd(sd);
1694bd7c6f51SGordon Ross }
1695bd7c6f51SGordon Ross if (mapinfo != NULL)
1696bd7c6f51SGordon Ross FREESZ(mapinfo, mapcnt * sizeof (*mapinfo));
1697bd7c6f51SGordon Ross #ifdef _KERNEL
1698bd7c6f51SGordon Ross if (idmap_gh != NULL)
1699bd7c6f51SGordon Ross kidmap_get_destroy(idmap_gh);
1700bd7c6f51SGordon Ross #else /* _KERNEL */
1701bd7c6f51SGordon Ross if (idmap_gh != NULL)
1702bd7c6f51SGordon Ross idmap_get_destroy(idmap_gh);
1703bd7c6f51SGordon Ross #endif /* _KERNEL */
1704bd7c6f51SGordon Ross
1705bd7c6f51SGordon Ross return (error);
170602d09e03SGordon Ross }
1707