xref: /titanic_52/usr/src/common/smbclnt/smbfs_ntacl.c (revision 02d09e03eb27f3a2dc299de704e45dae5173f43f)
1*02d09e03SGordon Ross /*
2*02d09e03SGordon Ross  * CDDL HEADER START
3*02d09e03SGordon Ross  *
4*02d09e03SGordon Ross  * The contents of this file are subject to the terms of the
5*02d09e03SGordon Ross  * Common Development and Distribution License (the "License").
6*02d09e03SGordon Ross  * You may not use this file except in compliance with the License.
7*02d09e03SGordon Ross  *
8*02d09e03SGordon Ross  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*02d09e03SGordon Ross  * or http://www.opensolaris.org/os/licensing.
10*02d09e03SGordon Ross  * See the License for the specific language governing permissions
11*02d09e03SGordon Ross  * and limitations under the License.
12*02d09e03SGordon Ross  *
13*02d09e03SGordon Ross  * When distributing Covered Code, include this CDDL HEADER in each
14*02d09e03SGordon Ross  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*02d09e03SGordon Ross  * If applicable, add the following below this CDDL HEADER, with the
16*02d09e03SGordon Ross  * fields enclosed by brackets "[]" replaced with your own identifying
17*02d09e03SGordon Ross  * information: Portions Copyright [yyyy] [name of copyright owner]
18*02d09e03SGordon Ross  *
19*02d09e03SGordon Ross  * CDDL HEADER END
20*02d09e03SGordon Ross  */
21*02d09e03SGordon Ross 
22*02d09e03SGordon Ross /*
23*02d09e03SGordon Ross  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*02d09e03SGordon Ross  * Use is subject to license terms.
25*02d09e03SGordon Ross  */
26*02d09e03SGordon Ross 
27*02d09e03SGordon Ross /*
28*02d09e03SGordon Ross  * ACL conversion support for smbfs
29*02d09e03SGordon Ross  * (To/from NT/ZFS-style ACLs.)
30*02d09e03SGordon Ross  */
31*02d09e03SGordon Ross 
32*02d09e03SGordon Ross #include <sys/types.h>
33*02d09e03SGordon Ross #include <sys/errno.h>
34*02d09e03SGordon Ross #include <sys/acl.h>
35*02d09e03SGordon Ross #include <sys/byteorder.h>
36*02d09e03SGordon Ross 
37*02d09e03SGordon Ross #ifdef _KERNEL
38*02d09e03SGordon Ross 
39*02d09e03SGordon Ross #include <sys/cred.h>
40*02d09e03SGordon Ross #include <sys/cmn_err.h>
41*02d09e03SGordon Ross #include <sys/kmem.h>
42*02d09e03SGordon Ross #include <sys/sunddi.h>
43*02d09e03SGordon Ross #include <sys/vnode.h>
44*02d09e03SGordon Ross #include <sys/vfs.h>
45*02d09e03SGordon Ross 
46*02d09e03SGordon Ross #include <sys/kidmap.h>
47*02d09e03SGordon Ross 
48*02d09e03SGordon Ross #else	/* _KERNEL */
49*02d09e03SGordon Ross 
50*02d09e03SGordon Ross #include <stdio.h>
51*02d09e03SGordon Ross #include <stdlib.h>
52*02d09e03SGordon Ross #include <strings.h>
53*02d09e03SGordon Ross 
54*02d09e03SGordon Ross #include <idmap.h>
55*02d09e03SGordon Ross 
56*02d09e03SGordon Ross #endif	/* _KERNEL */
57*02d09e03SGordon Ross 
58*02d09e03SGordon Ross #include <netsmb/mchain.h>
59*02d09e03SGordon Ross #include <netsmb/smb.h>
60*02d09e03SGordon Ross #include "smbfs_ntacl.h"
61*02d09e03SGordon Ross 
62*02d09e03SGordon Ross #ifdef _KERNEL
63*02d09e03SGordon Ross #define	MALLOC(size) kmem_alloc(size, KM_SLEEP)
64*02d09e03SGordon Ross #define	FREESZ(p, sz) kmem_free(p, sz)
65*02d09e03SGordon Ross #else	/* _KERNEL */
66*02d09e03SGordon Ross #define	MALLOC(size) malloc(size)
67*02d09e03SGordon Ross #ifndef lint
68*02d09e03SGordon Ross #define	FREESZ(p, sz) free(p)
69*02d09e03SGordon Ross #else	/* lint */
70*02d09e03SGordon Ross /* ARGSUSED */
71*02d09e03SGordon Ross static void
72*02d09e03SGordon Ross FREESZ(void *p, size_t sz)
73*02d09e03SGordon Ross {
74*02d09e03SGordon Ross 	free(p);
75*02d09e03SGordon Ross }
76*02d09e03SGordon Ross #endif	/* lint */
77*02d09e03SGordon Ross #endif	/* _KERNEL */
78*02d09e03SGordon Ross 
79*02d09e03SGordon Ross #define	ERRCHK(expr)	if ((error = expr) != 0) goto errout
80*02d09e03SGordon Ross 
81*02d09e03SGordon Ross /*
82*02d09e03SGordon Ross  * Security IDentifier (SID)
83*02d09e03SGordon Ross  */
84*02d09e03SGordon Ross static void
85*02d09e03SGordon Ross ifree_sid(i_ntsid_t *sid)
86*02d09e03SGordon Ross {
87*02d09e03SGordon Ross 	size_t sz;
88*02d09e03SGordon Ross 
89*02d09e03SGordon Ross 	if (sid == NULL)
90*02d09e03SGordon Ross 		return;
91*02d09e03SGordon Ross 
92*02d09e03SGordon Ross 	sz = I_SID_SIZE(sid->sid_subauthcount);
93*02d09e03SGordon Ross 	FREESZ(sid, sz);
94*02d09e03SGordon Ross }
95*02d09e03SGordon Ross 
96*02d09e03SGordon Ross static int
97*02d09e03SGordon Ross md_get_sid(mdchain_t *mdp, i_ntsid_t **sidp)
98*02d09e03SGordon Ross {
99*02d09e03SGordon Ross 	i_ntsid_t *sid = NULL;
100*02d09e03SGordon Ross 	uint8_t revision, subauthcount;
101*02d09e03SGordon Ross 	uint32_t *subauthp;
102*02d09e03SGordon Ross 	size_t sidsz;
103*02d09e03SGordon Ross 	int error, i;
104*02d09e03SGordon Ross 
105*02d09e03SGordon Ross 	if ((error = md_get_uint8(mdp, &revision)) != 0)
106*02d09e03SGordon Ross 		return (error);
107*02d09e03SGordon Ross 	if ((error = md_get_uint8(mdp, &subauthcount)) != 0)
108*02d09e03SGordon Ross 		return (error);
109*02d09e03SGordon Ross 
110*02d09e03SGordon Ross 	sidsz = I_SID_SIZE(subauthcount);
111*02d09e03SGordon Ross 
112*02d09e03SGordon Ross 	if ((sid = MALLOC(sidsz)) == NULL)
113*02d09e03SGordon Ross 		return (ENOMEM);
114*02d09e03SGordon Ross 
115*02d09e03SGordon Ross 	bzero(sid, sidsz);
116*02d09e03SGordon Ross 	sid->sid_revision = revision;
117*02d09e03SGordon Ross 	sid->sid_subauthcount = subauthcount;
118*02d09e03SGordon Ross 	ERRCHK(md_get_mem(mdp, sid->sid_authority, 6, MB_MSYSTEM));
119*02d09e03SGordon Ross 
120*02d09e03SGordon Ross 	subauthp = &sid->sid_subauthvec[0];
121*02d09e03SGordon Ross 	for (i = 0; i < subauthcount; i++) {
122*02d09e03SGordon Ross 		ERRCHK(md_get_uint32le(mdp, subauthp));
123*02d09e03SGordon Ross 		subauthp++;
124*02d09e03SGordon Ross 	}
125*02d09e03SGordon Ross 
126*02d09e03SGordon Ross 	/* Success! */
127*02d09e03SGordon Ross 	*sidp = sid;
128*02d09e03SGordon Ross 	return (0);
129*02d09e03SGordon Ross 
130*02d09e03SGordon Ross errout:
131*02d09e03SGordon Ross 	ifree_sid(sid);
132*02d09e03SGordon Ross 	return (error);
133*02d09e03SGordon Ross }
134*02d09e03SGordon Ross 
135*02d09e03SGordon Ross static int
136*02d09e03SGordon Ross mb_put_sid(mbchain_t *mbp, i_ntsid_t *sid)
137*02d09e03SGordon Ross {
138*02d09e03SGordon Ross 	uint32_t *subauthp;
139*02d09e03SGordon Ross 	int error, i;
140*02d09e03SGordon Ross 
141*02d09e03SGordon Ross 	if (sid == NULL)
142*02d09e03SGordon Ross 		return (EINVAL);
143*02d09e03SGordon Ross 
144*02d09e03SGordon Ross 	ERRCHK(mb_put_uint8(mbp, sid->sid_revision));
145*02d09e03SGordon Ross 	ERRCHK(mb_put_uint8(mbp, sid->sid_subauthcount));
146*02d09e03SGordon Ross 	ERRCHK(mb_put_mem(mbp, sid->sid_authority, 6, MB_MSYSTEM));
147*02d09e03SGordon Ross 
148*02d09e03SGordon Ross 	subauthp = &sid->sid_subauthvec[0];
149*02d09e03SGordon Ross 	for (i = 0; i < sid->sid_subauthcount; i++) {
150*02d09e03SGordon Ross 		ERRCHK(mb_put_uint32le(mbp, *subauthp));
151*02d09e03SGordon Ross 		subauthp++;
152*02d09e03SGordon Ross 	}
153*02d09e03SGordon Ross 
154*02d09e03SGordon Ross 	/* Success! */
155*02d09e03SGordon Ross 	return (0);
156*02d09e03SGordon Ross 
157*02d09e03SGordon Ross errout:
158*02d09e03SGordon Ross 	return (error);
159*02d09e03SGordon Ross }
160*02d09e03SGordon Ross 
161*02d09e03SGordon Ross 
162*02d09e03SGordon Ross /*
163*02d09e03SGordon Ross  * Access Control Entry (ACE)
164*02d09e03SGordon Ross  */
165*02d09e03SGordon Ross static void
166*02d09e03SGordon Ross ifree_ace(i_ntace_t *ace)
167*02d09e03SGordon Ross {
168*02d09e03SGordon Ross 
169*02d09e03SGordon Ross 	if (ace == NULL)
170*02d09e03SGordon Ross 		return;
171*02d09e03SGordon Ross 
172*02d09e03SGordon Ross 	ifree_sid(ace->ace_sid);
173*02d09e03SGordon Ross 	FREESZ(ace, sizeof (*ace));
174*02d09e03SGordon Ross }
175*02d09e03SGordon Ross 
176*02d09e03SGordon Ross static int
177*02d09e03SGordon Ross md_get_ace(mdchain_t *mdp, i_ntace_t **acep)
178*02d09e03SGordon Ross {
179*02d09e03SGordon Ross 	mdchain_t tmp_md;
180*02d09e03SGordon Ross 	i_ntace_t *ace = NULL;
181*02d09e03SGordon Ross 	uint16_t ace_len;
182*02d09e03SGordon Ross 	int error;
183*02d09e03SGordon Ross 
184*02d09e03SGordon Ross 	if ((ace = MALLOC(sizeof (*ace))) == NULL)
185*02d09e03SGordon Ross 		return (ENOMEM);
186*02d09e03SGordon Ross 	bzero(ace, sizeof (*ace));
187*02d09e03SGordon Ross 
188*02d09e03SGordon Ross 	/*
189*02d09e03SGordon Ross 	 * The ACE is realy variable length,
190*02d09e03SGordon Ross 	 * with format determined by the type.
191*02d09e03SGordon Ross 	 * XXX: This only decodes types 0-7
192*02d09e03SGordon Ross 	 *
193*02d09e03SGordon Ross 	 * There may also be padding after it, so
194*02d09e03SGordon Ross 	 * decode the using a copy of the mdchain,
195*02d09e03SGordon Ross 	 * and then consume the specified length.
196*02d09e03SGordon Ross 	 */
197*02d09e03SGordon Ross 	tmp_md = *mdp;
198*02d09e03SGordon Ross 
199*02d09e03SGordon Ross 	/* Fixed-size header */
200*02d09e03SGordon Ross 	ERRCHK(md_get_uint8(&tmp_md, &ace->ace_type));
201*02d09e03SGordon Ross 	ERRCHK(md_get_uint8(&tmp_md, &ace->ace_flags));
202*02d09e03SGordon Ross 	ERRCHK(md_get_uint16le(&tmp_md, &ace_len));
203*02d09e03SGordon Ross 
204*02d09e03SGordon Ross 	/* Variable-size body */
205*02d09e03SGordon Ross 	ERRCHK(md_get_uint32le(&tmp_md, &ace->ace_rights));
206*02d09e03SGordon Ross 	ERRCHK(md_get_sid(&tmp_md, &ace->ace_sid));
207*02d09e03SGordon Ross 
208*02d09e03SGordon Ross 	/* Now actually consume ace_len */
209*02d09e03SGordon Ross 	ERRCHK(md_get_mem(mdp, NULL, ace_len, MB_MSYSTEM));
210*02d09e03SGordon Ross 
211*02d09e03SGordon Ross 	/* Success! */
212*02d09e03SGordon Ross 	*acep = ace;
213*02d09e03SGordon Ross 	return (0);
214*02d09e03SGordon Ross 
215*02d09e03SGordon Ross errout:
216*02d09e03SGordon Ross 	ifree_ace(ace);
217*02d09e03SGordon Ross 	return (error);
218*02d09e03SGordon Ross }
219*02d09e03SGordon Ross 
220*02d09e03SGordon Ross static int
221*02d09e03SGordon Ross mb_put_ace(mbchain_t *mbp, i_ntace_t *ace)
222*02d09e03SGordon Ross {
223*02d09e03SGordon Ross 	int cnt0, error;
224*02d09e03SGordon Ross 	uint16_t ace_len, *ace_len_p;
225*02d09e03SGordon Ross 
226*02d09e03SGordon Ross 	if (ace == NULL)
227*02d09e03SGordon Ross 		return (EINVAL);
228*02d09e03SGordon Ross 
229*02d09e03SGordon Ross 	cnt0 = mbp->mb_count;
230*02d09e03SGordon Ross 
231*02d09e03SGordon Ross 	ERRCHK(mb_put_uint8(mbp, ace->ace_type));
232*02d09e03SGordon Ross 	ERRCHK(mb_put_uint8(mbp, ace->ace_flags));
233*02d09e03SGordon Ross 	ace_len_p = mb_reserve(mbp, sizeof (*ace_len_p));
234*02d09e03SGordon Ross 	if (ace_len_p == NULL) {
235*02d09e03SGordon Ross 		error = ENOMEM;
236*02d09e03SGordon Ross 		goto errout;
237*02d09e03SGordon Ross 	}
238*02d09e03SGordon Ross 	ERRCHK(mb_put_uint32le(mbp, ace->ace_rights));
239*02d09e03SGordon Ross 
240*02d09e03SGordon Ross 	ERRCHK(mb_put_sid(mbp, ace->ace_sid));
241*02d09e03SGordon Ross 
242*02d09e03SGordon Ross 	ace_len = mbp->mb_count - cnt0;
243*02d09e03SGordon Ross 	*ace_len_p = htoles(ace_len);
244*02d09e03SGordon Ross 
245*02d09e03SGordon Ross 	/* Success! */
246*02d09e03SGordon Ross 	return (0);
247*02d09e03SGordon Ross 
248*02d09e03SGordon Ross errout:
249*02d09e03SGordon Ross 	return (error);
250*02d09e03SGordon Ross }
251*02d09e03SGordon Ross 
252*02d09e03SGordon Ross 
253*02d09e03SGordon Ross /*
254*02d09e03SGordon Ross  * Access Control List (ACL)
255*02d09e03SGordon Ross  */
256*02d09e03SGordon Ross 
257*02d09e03SGordon Ross /* Not an OTW structure, so size can be at our convenience. */
258*02d09e03SGordon Ross #define	I_ACL_SIZE(cnt)	(sizeof (i_ntacl_t) + (cnt) * sizeof (void *))
259*02d09e03SGordon Ross 
260*02d09e03SGordon Ross static void
261*02d09e03SGordon Ross ifree_acl(i_ntacl_t *acl)
262*02d09e03SGordon Ross {
263*02d09e03SGordon Ross 	i_ntace_t **acep;
264*02d09e03SGordon Ross 	size_t sz;
265*02d09e03SGordon Ross 	int i;
266*02d09e03SGordon Ross 
267*02d09e03SGordon Ross 	if (acl == NULL)
268*02d09e03SGordon Ross 		return;
269*02d09e03SGordon Ross 
270*02d09e03SGordon Ross 	acep = &acl->acl_acevec[0];
271*02d09e03SGordon Ross 	for (i = 0; i < acl->acl_acecount; i++) {
272*02d09e03SGordon Ross 		ifree_ace(*acep);
273*02d09e03SGordon Ross 		acep++;
274*02d09e03SGordon Ross 	}
275*02d09e03SGordon Ross 	sz = I_ACL_SIZE(acl->acl_acecount);
276*02d09e03SGordon Ross 	FREESZ(acl, sz);
277*02d09e03SGordon Ross }
278*02d09e03SGordon Ross 
279*02d09e03SGordon Ross static int
280*02d09e03SGordon Ross md_get_acl(mdchain_t *mdp, i_ntacl_t **aclp)
281*02d09e03SGordon Ross {
282*02d09e03SGordon Ross 	i_ntacl_t *acl = NULL;
283*02d09e03SGordon Ross 	i_ntace_t **acep;
284*02d09e03SGordon Ross 	uint8_t revision;
285*02d09e03SGordon Ross 	uint16_t acl_len, acecount;
286*02d09e03SGordon Ross 	size_t aclsz;
287*02d09e03SGordon Ross 	int i, error;
288*02d09e03SGordon Ross 
289*02d09e03SGordon Ross 	if ((error = md_get_uint8(mdp, &revision)) != 0)
290*02d09e03SGordon Ross 		return (error);
291*02d09e03SGordon Ross 	if ((error = md_get_uint8(mdp, NULL)) != 0)
292*02d09e03SGordon Ross 		return (error);
293*02d09e03SGordon Ross 	if ((error = md_get_uint16le(mdp, &acl_len)) != 0)
294*02d09e03SGordon Ross 		return (error);
295*02d09e03SGordon Ross 	if ((error = md_get_uint16le(mdp, &acecount)) != 0)
296*02d09e03SGordon Ross 		return (error);
297*02d09e03SGordon Ross 	if ((error = md_get_uint16le(mdp, NULL)) != 0)
298*02d09e03SGordon Ross 		return (error);
299*02d09e03SGordon Ross 
300*02d09e03SGordon Ross 	aclsz = I_ACL_SIZE(acecount);
301*02d09e03SGordon Ross 	if ((acl = MALLOC(aclsz)) == NULL)
302*02d09e03SGordon Ross 		return (ENOMEM);
303*02d09e03SGordon Ross 	bzero(acl, aclsz);
304*02d09e03SGordon Ross 	acl->acl_revision = revision;
305*02d09e03SGordon Ross 	acl->acl_acecount = acecount;
306*02d09e03SGordon Ross 
307*02d09e03SGordon Ross 	acep = &acl->acl_acevec[0];
308*02d09e03SGordon Ross 	for (i = 0; i < acl->acl_acecount; i++) {
309*02d09e03SGordon Ross 		ERRCHK(md_get_ace(mdp, acep));
310*02d09e03SGordon Ross 		acep++;
311*02d09e03SGordon Ross 	}
312*02d09e03SGordon Ross 	/*
313*02d09e03SGordon Ross 	 * There may be more data here, but
314*02d09e03SGordon Ross 	 * the caller takes care of that.
315*02d09e03SGordon Ross 	 */
316*02d09e03SGordon Ross 
317*02d09e03SGordon Ross 	/* Success! */
318*02d09e03SGordon Ross 	*aclp = acl;
319*02d09e03SGordon Ross 	return (0);
320*02d09e03SGordon Ross 
321*02d09e03SGordon Ross errout:
322*02d09e03SGordon Ross 	ifree_acl(acl);
323*02d09e03SGordon Ross 	return (error);
324*02d09e03SGordon Ross }
325*02d09e03SGordon Ross 
326*02d09e03SGordon Ross static int
327*02d09e03SGordon Ross mb_put_acl(mbchain_t *mbp, i_ntacl_t *acl)
328*02d09e03SGordon Ross {
329*02d09e03SGordon Ross 	i_ntace_t **acep;
330*02d09e03SGordon Ross 	uint16_t acl_len, *acl_len_p;
331*02d09e03SGordon Ross 	int i, cnt0, error;
332*02d09e03SGordon Ross 
333*02d09e03SGordon Ross 	cnt0 = mbp->mb_count;
334*02d09e03SGordon Ross 
335*02d09e03SGordon Ross 	ERRCHK(mb_put_uint8(mbp, acl->acl_revision));
336*02d09e03SGordon Ross 	ERRCHK(mb_put_uint8(mbp, 0)); /* pad1 */
337*02d09e03SGordon Ross 	acl_len_p = mb_reserve(mbp, sizeof (*acl_len_p));
338*02d09e03SGordon Ross 	if (acl_len_p == NULL) {
339*02d09e03SGordon Ross 		error = ENOMEM;
340*02d09e03SGordon Ross 		goto errout;
341*02d09e03SGordon Ross 	}
342*02d09e03SGordon Ross 	ERRCHK(mb_put_uint16le(mbp, acl->acl_acecount));
343*02d09e03SGordon Ross 	ERRCHK(mb_put_uint16le(mbp, 0)); /* pad2 */
344*02d09e03SGordon Ross 
345*02d09e03SGordon Ross 	acep = &acl->acl_acevec[0];
346*02d09e03SGordon Ross 	for (i = 0; i < acl->acl_acecount; i++) {
347*02d09e03SGordon Ross 		ERRCHK(mb_put_ace(mbp, *acep));
348*02d09e03SGordon Ross 		acep++;
349*02d09e03SGordon Ross 	}
350*02d09e03SGordon Ross 
351*02d09e03SGordon Ross 	/* Fill in acl_len_p */
352*02d09e03SGordon Ross 	acl_len = mbp->mb_count - cnt0;
353*02d09e03SGordon Ross 	*acl_len_p = htoles(acl_len);
354*02d09e03SGordon Ross 
355*02d09e03SGordon Ross 	/* Success! */
356*02d09e03SGordon Ross 	return (0);
357*02d09e03SGordon Ross 
358*02d09e03SGordon Ross errout:
359*02d09e03SGordon Ross 	return (error);
360*02d09e03SGordon Ross }
361*02d09e03SGordon Ross 
362*02d09e03SGordon Ross 
363*02d09e03SGordon Ross /*
364*02d09e03SGordon Ross  * Security Descriptor
365*02d09e03SGordon Ross  */
366*02d09e03SGordon Ross void
367*02d09e03SGordon Ross smbfs_acl_free_sd(i_ntsd_t *sd)
368*02d09e03SGordon Ross {
369*02d09e03SGordon Ross 
370*02d09e03SGordon Ross 	if (sd == NULL)
371*02d09e03SGordon Ross 		return;
372*02d09e03SGordon Ross 
373*02d09e03SGordon Ross 	ifree_sid(sd->sd_owner);
374*02d09e03SGordon Ross 	ifree_sid(sd->sd_group);
375*02d09e03SGordon Ross 	ifree_acl(sd->sd_sacl);
376*02d09e03SGordon Ross 	ifree_acl(sd->sd_dacl);
377*02d09e03SGordon Ross 
378*02d09e03SGordon Ross 	FREESZ(sd, sizeof (*sd));
379*02d09e03SGordon Ross }
380*02d09e03SGordon Ross 
381*02d09e03SGordon Ross /*
382*02d09e03SGordon Ross  * Import a raw SD (mb chain) into "internal" form.
383*02d09e03SGordon Ross  * (like "absolute" form per. NT docs)
384*02d09e03SGordon Ross  * Returns allocated data in sdp
385*02d09e03SGordon Ross  *
386*02d09e03SGordon Ross  * Note: does NOT consume all the mdp data, so the
387*02d09e03SGordon Ross  * caller has to take care of that if necessary.
388*02d09e03SGordon Ross  */
389*02d09e03SGordon Ross int
390*02d09e03SGordon Ross md_get_ntsd(mdchain_t *mdp, i_ntsd_t **sdp)
391*02d09e03SGordon Ross {
392*02d09e03SGordon Ross 	i_ntsd_t *sd = NULL;
393*02d09e03SGordon Ross 	mdchain_t top_md, tmp_md;
394*02d09e03SGordon Ross 	uint32_t owneroff, groupoff, sacloff, dacloff;
395*02d09e03SGordon Ross 	int error;
396*02d09e03SGordon Ross 
397*02d09e03SGordon Ross 	if ((sd = MALLOC(sizeof (*sd))) == NULL)
398*02d09e03SGordon Ross 		return (ENOMEM);
399*02d09e03SGordon Ross 	bzero(sd, sizeof (*sd));
400*02d09e03SGordon Ross 
401*02d09e03SGordon Ross 	/*
402*02d09e03SGordon Ross 	 * Offsets below are relative to this point,
403*02d09e03SGordon Ross 	 * so save the mdp state for use below.
404*02d09e03SGordon Ross 	 */
405*02d09e03SGordon Ross 	top_md = *mdp;
406*02d09e03SGordon Ross 
407*02d09e03SGordon Ross 	ERRCHK(md_get_uint8(mdp, &sd->sd_revision));
408*02d09e03SGordon Ross 	ERRCHK(md_get_uint8(mdp, &sd->sd_rmctl));
409*02d09e03SGordon Ross 	ERRCHK(md_get_uint16le(mdp, &sd->sd_flags));
410*02d09e03SGordon Ross 	ERRCHK(md_get_uint32le(mdp, &owneroff));
411*02d09e03SGordon Ross 	ERRCHK(md_get_uint32le(mdp, &groupoff));
412*02d09e03SGordon Ross 	ERRCHK(md_get_uint32le(mdp, &sacloff));
413*02d09e03SGordon Ross 	ERRCHK(md_get_uint32le(mdp, &dacloff));
414*02d09e03SGordon Ross 
415*02d09e03SGordon Ross 	/*
416*02d09e03SGordon Ross 	 * For each section make a temporary copy of the
417*02d09e03SGordon Ross 	 * top_md state, advance to the given offset, and
418*02d09e03SGordon Ross 	 * pass that to the lower md_get_xxx functions.
419*02d09e03SGordon Ross 	 * These could be marshalled in any order, but
420*02d09e03SGordon Ross 	 * are normally found in the order shown here.
421*02d09e03SGordon Ross 	 */
422*02d09e03SGordon Ross 	if (sacloff) {
423*02d09e03SGordon Ross 		tmp_md = top_md;
424*02d09e03SGordon Ross 		md_get_mem(&tmp_md, NULL, sacloff, MB_MSYSTEM);
425*02d09e03SGordon Ross 		ERRCHK(md_get_acl(&tmp_md, &sd->sd_sacl));
426*02d09e03SGordon Ross 	}
427*02d09e03SGordon Ross 	if (dacloff) {
428*02d09e03SGordon Ross 		tmp_md = top_md;
429*02d09e03SGordon Ross 		md_get_mem(&tmp_md, NULL, dacloff, MB_MSYSTEM);
430*02d09e03SGordon Ross 		ERRCHK(md_get_acl(&tmp_md, &sd->sd_dacl));
431*02d09e03SGordon Ross 	}
432*02d09e03SGordon Ross 	if (owneroff) {
433*02d09e03SGordon Ross 		tmp_md = top_md;
434*02d09e03SGordon Ross 		md_get_mem(&tmp_md, NULL, owneroff, MB_MSYSTEM);
435*02d09e03SGordon Ross 		ERRCHK(md_get_sid(&tmp_md, &sd->sd_owner));
436*02d09e03SGordon Ross 	}
437*02d09e03SGordon Ross 	if (groupoff) {
438*02d09e03SGordon Ross 		tmp_md = top_md;
439*02d09e03SGordon Ross 		md_get_mem(&tmp_md, NULL, groupoff, MB_MSYSTEM);
440*02d09e03SGordon Ross 		ERRCHK(md_get_sid(&tmp_md, &sd->sd_group));
441*02d09e03SGordon Ross 	}
442*02d09e03SGordon Ross 
443*02d09e03SGordon Ross 	/* Success! */
444*02d09e03SGordon Ross 	*sdp = sd;
445*02d09e03SGordon Ross 	return (0);
446*02d09e03SGordon Ross 
447*02d09e03SGordon Ross errout:
448*02d09e03SGordon Ross 	smbfs_acl_free_sd(sd);
449*02d09e03SGordon Ross 	return (error);
450*02d09e03SGordon Ross }
451*02d09e03SGordon Ross 
452*02d09e03SGordon Ross /*
453*02d09e03SGordon Ross  * Export an "internal" SD into an raw SD (mb chain).
454*02d09e03SGordon Ross  * (a.k.a "self-relative" form per. NT docs)
455*02d09e03SGordon Ross  * Returns allocated mbchain in mbp.
456*02d09e03SGordon Ross  */
457*02d09e03SGordon Ross int
458*02d09e03SGordon Ross mb_put_ntsd(mbchain_t *mbp, i_ntsd_t *sd)
459*02d09e03SGordon Ross {
460*02d09e03SGordon Ross 	uint32_t *owneroffp, *groupoffp, *sacloffp, *dacloffp;
461*02d09e03SGordon Ross 	uint32_t owneroff, groupoff, sacloff, dacloff;
462*02d09e03SGordon Ross 	int cnt0, error;
463*02d09e03SGordon Ross 
464*02d09e03SGordon Ross 	cnt0 = mbp->mb_count;
465*02d09e03SGordon Ross 	owneroff = groupoff = sacloff = dacloff = 0;
466*02d09e03SGordon Ross 
467*02d09e03SGordon Ross 	ERRCHK(mb_put_uint8(mbp, sd->sd_revision));
468*02d09e03SGordon Ross 	ERRCHK(mb_put_uint8(mbp, sd->sd_rmctl));
469*02d09e03SGordon Ross 	ERRCHK(mb_put_uint16le(mbp, sd->sd_flags));
470*02d09e03SGordon Ross 
471*02d09e03SGordon Ross 	owneroffp = mb_reserve(mbp, sizeof (*owneroffp));
472*02d09e03SGordon Ross 	groupoffp = mb_reserve(mbp, sizeof (*groupoffp));
473*02d09e03SGordon Ross 	sacloffp  = mb_reserve(mbp, sizeof (*sacloffp));
474*02d09e03SGordon Ross 	dacloffp  = mb_reserve(mbp, sizeof (*dacloffp));
475*02d09e03SGordon Ross 	if (owneroffp == NULL || groupoffp == NULL ||
476*02d09e03SGordon Ross 	    sacloffp == NULL || dacloffp == NULL) {
477*02d09e03SGordon Ross 		error = ENOMEM;
478*02d09e03SGordon Ross 		goto errout;
479*02d09e03SGordon Ross 	}
480*02d09e03SGordon Ross 
481*02d09e03SGordon Ross 	/*
482*02d09e03SGordon Ross 	 * These could be marshalled in any order, but
483*02d09e03SGordon Ross 	 * are normally found in the order shown here.
484*02d09e03SGordon Ross 	 */
485*02d09e03SGordon Ross 	if (sd->sd_sacl) {
486*02d09e03SGordon Ross 		sacloff = mbp->mb_count - cnt0;
487*02d09e03SGordon Ross 		ERRCHK(mb_put_acl(mbp, sd->sd_sacl));
488*02d09e03SGordon Ross 	}
489*02d09e03SGordon Ross 	if (sd->sd_dacl) {
490*02d09e03SGordon Ross 		dacloff = mbp->mb_count - cnt0;
491*02d09e03SGordon Ross 		ERRCHK(mb_put_acl(mbp, sd->sd_dacl));
492*02d09e03SGordon Ross 	}
493*02d09e03SGordon Ross 	if (sd->sd_owner) {
494*02d09e03SGordon Ross 		owneroff = mbp->mb_count - cnt0;
495*02d09e03SGordon Ross 		ERRCHK(mb_put_sid(mbp, sd->sd_owner));
496*02d09e03SGordon Ross 	}
497*02d09e03SGordon Ross 	if (sd->sd_group) {
498*02d09e03SGordon Ross 		groupoff = mbp->mb_count - cnt0;
499*02d09e03SGordon Ross 		ERRCHK(mb_put_sid(mbp, sd->sd_group));
500*02d09e03SGordon Ross 	}
501*02d09e03SGordon Ross 
502*02d09e03SGordon Ross 	/* Fill in the offsets */
503*02d09e03SGordon Ross 	*owneroffp = htolel(owneroff);
504*02d09e03SGordon Ross 	*groupoffp = htolel(groupoff);
505*02d09e03SGordon Ross 	*sacloffp  = htolel(sacloff);
506*02d09e03SGordon Ross 	*dacloffp  = htolel(dacloff);
507*02d09e03SGordon Ross 
508*02d09e03SGordon Ross 	/* Success! */
509*02d09e03SGordon Ross 	return (0);
510*02d09e03SGordon Ross 
511*02d09e03SGordon Ross errout:
512*02d09e03SGordon Ross 	return (error);
513*02d09e03SGordon Ross }
514*02d09e03SGordon Ross 
515*02d09e03SGordon Ross 
516*02d09e03SGordon Ross /*
517*02d09e03SGordon Ross  * Helper functions for conversion between ZFS-style ACLs
518*02d09e03SGordon Ross  * and Windows Security Descriptors.
519*02d09e03SGordon Ross  */
520*02d09e03SGordon Ross 
521*02d09e03SGordon Ross 
522*02d09e03SGordon Ross /*
523*02d09e03SGordon Ross  * Convert an NT SID to a string. Optionally return the
524*02d09e03SGordon Ross  * last sub-authority (or "relative ID" -- RID) in *ridp
525*02d09e03SGordon Ross  * and truncate the output string after the domain part.
526*02d09e03SGordon Ross  * If ridp==NULL, the output string is the whole SID,
527*02d09e03SGordon Ross  * including both the domain and RID.
528*02d09e03SGordon Ross  *
529*02d09e03SGordon Ross  * Return length written, or -1 on error.
530*02d09e03SGordon Ross  */
531*02d09e03SGordon Ross int
532*02d09e03SGordon Ross smbfs_sid2str(i_ntsid_t *sid,
533*02d09e03SGordon Ross 	char *obuf, size_t osz, uint32_t *ridp)
534*02d09e03SGordon Ross {
535*02d09e03SGordon Ross 	char *s = obuf;
536*02d09e03SGordon Ross 	uint64_t auth = 0;
537*02d09e03SGordon Ross 	uint_t i, n;
538*02d09e03SGordon Ross 	uint32_t subs, *ip;
539*02d09e03SGordon Ross 
540*02d09e03SGordon Ross 	n = snprintf(s, osz, "S-%u", sid->sid_revision);
541*02d09e03SGordon Ross 	if (n > osz)
542*02d09e03SGordon Ross 		return (-1);
543*02d09e03SGordon Ross 	s += n; osz -= n;
544*02d09e03SGordon Ross 
545*02d09e03SGordon Ross 	for (i = 0; i < 6; i++)
546*02d09e03SGordon Ross 		auth = (auth << 8) | sid->sid_authority[i];
547*02d09e03SGordon Ross 	n = snprintf(s, osz, "-%llu", (u_longlong_t)auth);
548*02d09e03SGordon Ross 	if (n > osz)
549*02d09e03SGordon Ross 		return (-1);
550*02d09e03SGordon Ross 	s += n; osz -= n;
551*02d09e03SGordon Ross 
552*02d09e03SGordon Ross 	subs = sid->sid_subauthcount;
553*02d09e03SGordon Ross 	if (subs < 1 || subs > 15)
554*02d09e03SGordon Ross 		return (-1);
555*02d09e03SGordon Ross 	if (ridp)
556*02d09e03SGordon Ross 		subs--;
557*02d09e03SGordon Ross 
558*02d09e03SGordon Ross 	ip = &sid->sid_subauthvec[0];
559*02d09e03SGordon Ross 	for (; subs; subs--, ip++) {
560*02d09e03SGordon Ross 		n = snprintf(s, osz, "-%u", *ip);
561*02d09e03SGordon Ross 		if (n > osz)
562*02d09e03SGordon Ross 			return (-1);
563*02d09e03SGordon Ross 		s += n; osz -= n;
564*02d09e03SGordon Ross 	}
565*02d09e03SGordon Ross 	if (ridp)
566*02d09e03SGordon Ross 		*ridp = *ip;
567*02d09e03SGordon Ross 
568*02d09e03SGordon Ross 	/* LINTED E_PTRDIFF_OVERFLOW */
569*02d09e03SGordon Ross 	return (s - obuf);
570*02d09e03SGordon Ross }
571*02d09e03SGordon Ross 
572*02d09e03SGordon Ross /*
573*02d09e03SGordon Ross  * Our interface to the idmap service.
574*02d09e03SGordon Ross  *
575*02d09e03SGordon Ross  * The idmap API is _almost_ the same between
576*02d09e03SGordon Ross  * kernel and user-level.  But not quite...
577*02d09e03SGordon Ross  * Hope this improves readability below.
578*02d09e03SGordon Ross  */
579*02d09e03SGordon Ross #ifdef	_KERNEL
580*02d09e03SGordon Ross 
581*02d09e03SGordon Ross #define	I_GetPidBySid(GH, SPP, RID, PIDP, ISUP, SP) \
582*02d09e03SGordon Ross 	kidmap_batch_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP)
583*02d09e03SGordon Ross #define	I_GetMappings kidmap_get_mappings
584*02d09e03SGordon Ross 
585*02d09e03SGordon Ross #else /* _KERNEL */
586*02d09e03SGordon Ross 
587*02d09e03SGordon Ross #define	I_GetPidBySid(GH, SPP, RID, PIDP, ISUP, SP) \
588*02d09e03SGordon Ross 	idmap_get_pidbysid(GH, SPP, RID, 0, PIDP, ISUP, SP)
589*02d09e03SGordon Ross #define	I_GetMappings idmap_get_mappings
590*02d09e03SGordon Ross 
591*02d09e03SGordon Ross #endif /* _KERNEL */
592*02d09e03SGordon Ross 
593*02d09e03SGordon Ross struct mapinfo {
594*02d09e03SGordon Ross 	uid_t	mi_uid; /* or gid */
595*02d09e03SGordon Ross 	int	mi_isuser;
596*02d09e03SGordon Ross 	idmap_stat mi_status;
597*02d09e03SGordon Ross };
598*02d09e03SGordon Ross 
599*02d09e03SGordon Ross /*
600*02d09e03SGordon Ross  * A special value for mi_isuser (above) to indicate
601*02d09e03SGordon Ross  * that the SID is the well-known "Everyone" (S-1-1-0).
602*02d09e03SGordon Ross  * The idmap library only uses -1, 0, 1, so this value
603*02d09e03SGordon Ross  * is arbitrary but must not overlap w/ idmap values.
604*02d09e03SGordon Ross  * XXX: Could use a way for idmap to tell us when
605*02d09e03SGordon Ross  * it recognizes this well-known SID.
606*02d09e03SGordon Ross  */
607*02d09e03SGordon Ross #define	IS_WKSID_EVERYONE 11
608*02d09e03SGordon Ross 
609*02d09e03SGordon Ross /*
610*02d09e03SGordon Ross  * Build an idmap request.  Cleanup is
611*02d09e03SGordon Ross  * handled by the caller (error or not)
612*02d09e03SGordon Ross  */
613*02d09e03SGordon Ross static int
614*02d09e03SGordon Ross mkrq_idmap_sid2ux(
615*02d09e03SGordon Ross 	idmap_get_handle_t *idmap_gh,
616*02d09e03SGordon Ross 	i_ntsid_t *sid,
617*02d09e03SGordon Ross 	struct mapinfo *mip)
618*02d09e03SGordon Ross {
619*02d09e03SGordon Ross 	char sid_prefix[256];
620*02d09e03SGordon Ross 	uint32_t	rid;
621*02d09e03SGordon Ross 	idmap_stat	idms;
622*02d09e03SGordon Ross 
623*02d09e03SGordon Ross 	if (smbfs_sid2str(sid, sid_prefix, sizeof (sid_prefix), &rid) < 0)
624*02d09e03SGordon Ross 		return (EINVAL);
625*02d09e03SGordon Ross 
626*02d09e03SGordon Ross 	/*
627*02d09e03SGordon Ross 	 * Give the "Everyone" group special treatment.
628*02d09e03SGordon Ross 	 */
629*02d09e03SGordon Ross 	if (strcmp(sid_prefix, "S-1-1") == 0 && rid == 0) {
630*02d09e03SGordon Ross 		/* This is "Everyone" */
631*02d09e03SGordon Ross 		mip->mi_uid = (uid_t)-1;
632*02d09e03SGordon Ross 		mip->mi_isuser = IS_WKSID_EVERYONE;
633*02d09e03SGordon Ross 		mip->mi_status = 0;
634*02d09e03SGordon Ross 		return (0);
635*02d09e03SGordon Ross 	}
636*02d09e03SGordon Ross 
637*02d09e03SGordon Ross 	idms = I_GetPidBySid(idmap_gh, sid_prefix, rid,
638*02d09e03SGordon Ross 	    &mip->mi_uid, &mip->mi_isuser, &mip->mi_status);
639*02d09e03SGordon Ross 	if (idms != IDMAP_SUCCESS)
640*02d09e03SGordon Ross 		return (EINVAL);
641*02d09e03SGordon Ross 
642*02d09e03SGordon Ross 	return (0);
643*02d09e03SGordon Ross }
644*02d09e03SGordon Ross 
645*02d09e03SGordon Ross static void
646*02d09e03SGordon Ross ntace2zace(ace_t *zacep, i_ntace_t *ntace, struct mapinfo *mip)
647*02d09e03SGordon Ross {
648*02d09e03SGordon Ross 	uint32_t zamask;
649*02d09e03SGordon Ross 	uint16_t zflags, ntflags;
650*02d09e03SGordon Ross 	uint8_t zatype = ntace->ace_type;
651*02d09e03SGordon Ross 
652*02d09e03SGordon Ross 	/*
653*02d09e03SGordon Ross 	 * Translate NT ACE flags to ZFS ACE flags.
654*02d09e03SGordon Ross 	 * The low four bits are the same, but not
655*02d09e03SGordon Ross 	 * others: INHERITED_ACE_FLAG, etc.
656*02d09e03SGordon Ross 	 */
657*02d09e03SGordon Ross 	ntflags = ntace->ace_flags;
658*02d09e03SGordon Ross 	zflags = 0;
659*02d09e03SGordon Ross 
660*02d09e03SGordon Ross 	if (ntflags & OBJECT_INHERIT_ACE_FLAG)
661*02d09e03SGordon Ross 		zflags |= ACE_FILE_INHERIT_ACE;
662*02d09e03SGordon Ross 	if (ntflags & CONTAINER_INHERIT_ACE_FLAG)
663*02d09e03SGordon Ross 		zflags |= ACE_DIRECTORY_INHERIT_ACE;
664*02d09e03SGordon Ross 	if (ntflags & NO_PROPAGATE_INHERIT_ACE_FLAG)
665*02d09e03SGordon Ross 		zflags |= ACE_NO_PROPAGATE_INHERIT_ACE;
666*02d09e03SGordon Ross 	if (ntflags & INHERIT_ONLY_ACE_FLAG)
667*02d09e03SGordon Ross 		zflags |= ACE_INHERIT_ONLY_ACE;
668*02d09e03SGordon Ross 	if (ntflags & INHERITED_ACE_FLAG)
669*02d09e03SGordon Ross 		zflags |= ACE_INHERITED_ACE;
670*02d09e03SGordon Ross 
671*02d09e03SGordon Ross 	if (ntflags & SUCCESSFUL_ACCESS_ACE_FLAG)
672*02d09e03SGordon Ross 		zflags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG;
673*02d09e03SGordon Ross 	if (ntflags & FAILED_ACCESS_ACE_FLAG)
674*02d09e03SGordon Ross 		zflags |= ACE_FAILED_ACCESS_ACE_FLAG;
675*02d09e03SGordon Ross 
676*02d09e03SGordon Ross 	/*
677*02d09e03SGordon Ross 	 * Add the "ID type" flags to the ZFS ace flags.
678*02d09e03SGordon Ross 	 * Would be nice if the idmap header defined some
679*02d09e03SGordon Ross 	 * manifest constants for these "isuser" values.
680*02d09e03SGordon Ross 	 */
681*02d09e03SGordon Ross 	switch (mip->mi_isuser) {
682*02d09e03SGordon Ross 	case IS_WKSID_EVERYONE:
683*02d09e03SGordon Ross 		zflags |= ACE_EVERYONE;
684*02d09e03SGordon Ross 		break;
685*02d09e03SGordon Ross 	case 0: /* it's a GID */
686*02d09e03SGordon Ross 		zflags |= ACE_IDENTIFIER_GROUP;
687*02d09e03SGordon Ross 		break;
688*02d09e03SGordon Ross 	default:
689*02d09e03SGordon Ross 	case 1: /* it's a UID */
690*02d09e03SGordon Ross 		break;
691*02d09e03SGordon Ross 	}
692*02d09e03SGordon Ross 
693*02d09e03SGordon Ross 	/*
694*02d09e03SGordon Ross 	 * The access mask bits are the same, but
695*02d09e03SGordon Ross 	 * mask off any bits we don't expect.
696*02d09e03SGordon Ross 	 * Should not see any GENERIC_xxx flags,
697*02d09e03SGordon Ross 	 * as those are only valid in requested
698*02d09e03SGordon Ross 	 * access masks, not ACLs.  But if we do,
699*02d09e03SGordon Ross 	 * get those, silently clear them here.
700*02d09e03SGordon Ross 	 */
701*02d09e03SGordon Ross 	zamask = ntace->ace_rights & ACE_ALL_PERMS;
702*02d09e03SGordon Ross 
703*02d09e03SGordon Ross 	/*
704*02d09e03SGordon Ross 	 * Verify that it's a known ACE type.
705*02d09e03SGordon Ross 	 * Only handle the types that appear in
706*02d09e03SGordon Ross 	 * V2, V3, V4 ACLs for now.  Avoid failing
707*02d09e03SGordon Ross 	 * the whole conversion if we get unknown
708*02d09e03SGordon Ross 	 * ace types, but convert them to something
709*02d09e03SGordon Ross 	 * that will have no effect on access.
710*02d09e03SGordon Ross 	 */
711*02d09e03SGordon Ross 	if (zatype > SYSTEM_ALARM_OBJECT_ACE_TYPE) {
712*02d09e03SGordon Ross 		zatype = ACCESS_ALLOWED_ACE_TYPE;
713*02d09e03SGordon Ross 		zamask = 0; /* harmless */
714*02d09e03SGordon Ross 	}
715*02d09e03SGordon Ross 
716*02d09e03SGordon Ross 	/*
717*02d09e03SGordon Ross 	 * Fill in the ZFS-style ACE
718*02d09e03SGordon Ross 	 */
719*02d09e03SGordon Ross 	zacep->a_who = mip->mi_uid; /* from ace_sid */
720*02d09e03SGordon Ross 	zacep->a_access_mask = zamask;
721*02d09e03SGordon Ross 	zacep->a_flags = zflags;
722*02d09e03SGordon Ross 	zacep->a_type = zatype;
723*02d09e03SGordon Ross }
724*02d09e03SGordon Ross 
725*02d09e03SGordon Ross /*
726*02d09e03SGordon Ross  * Convert an internal SD to a ZFS-style ACL.
727*02d09e03SGordon Ross  * Note optional args: vsa/acl, uidp, gidp.
728*02d09e03SGordon Ross  */
729*02d09e03SGordon Ross int
730*02d09e03SGordon Ross smbfs_acl_sd2zfs(
731*02d09e03SGordon Ross 	i_ntsd_t *sd,
732*02d09e03SGordon Ross #ifdef	_KERNEL
733*02d09e03SGordon Ross 	vsecattr_t *acl_info,
734*02d09e03SGordon Ross #else /* _KERNEL */
735*02d09e03SGordon Ross 	acl_t *acl_info,
736*02d09e03SGordon Ross #endif /* _KERNEL */
737*02d09e03SGordon Ross 	uid_t *uidp, gid_t *gidp)
738*02d09e03SGordon Ross {
739*02d09e03SGordon Ross 	struct mapinfo *mip, *mapinfo = NULL;
740*02d09e03SGordon Ross 	int error, i, mapcnt, zacecnt, zacl_size;
741*02d09e03SGordon Ross 	ace_t *zacep;
742*02d09e03SGordon Ross 	i_ntacl_t *ntacl;
743*02d09e03SGordon Ross 	i_ntace_t **ntacep;
744*02d09e03SGordon Ross #ifndef	_KERNEL
745*02d09e03SGordon Ross 	idmap_handle_t *idmap_h = NULL;
746*02d09e03SGordon Ross #endif /* _KERNEL */
747*02d09e03SGordon Ross 	idmap_get_handle_t *idmap_gh = NULL;
748*02d09e03SGordon Ross 	idmap_stat	idms;
749*02d09e03SGordon Ross 
750*02d09e03SGordon Ross 	/*
751*02d09e03SGordon Ross 	 * sanity checks
752*02d09e03SGordon Ross 	 */
753*02d09e03SGordon Ross #ifndef	_KERNEL
754*02d09e03SGordon Ross 	if (acl_info) {
755*02d09e03SGordon Ross 		if (acl_info->acl_type != ACE_T ||
756*02d09e03SGordon Ross 		    acl_info->acl_aclp != NULL ||
757*02d09e03SGordon Ross 		    acl_info->acl_entry_size != sizeof (ace_t))
758*02d09e03SGordon Ross 			return (EINVAL);
759*02d09e03SGordon Ross 	}
760*02d09e03SGordon Ross #endif /* _KERNEL */
761*02d09e03SGordon Ross 
762*02d09e03SGordon Ross 	/*
763*02d09e03SGordon Ross 	 * First, get all the SID mappings.
764*02d09e03SGordon Ross 	 * How many?
765*02d09e03SGordon Ross 	 */
766*02d09e03SGordon Ross 	mapcnt = 0;
767*02d09e03SGordon Ross 	if (sd->sd_owner)
768*02d09e03SGordon Ross 		mapcnt++;
769*02d09e03SGordon Ross 	if (sd->sd_group)
770*02d09e03SGordon Ross 		mapcnt++;
771*02d09e03SGordon Ross 	if (sd->sd_sacl)
772*02d09e03SGordon Ross 		mapcnt += sd->sd_sacl->acl_acecount;
773*02d09e03SGordon Ross 	if (sd->sd_dacl)
774*02d09e03SGordon Ross 		mapcnt += sd->sd_dacl->acl_acecount;
775*02d09e03SGordon Ross 	if (mapcnt == 0)
776*02d09e03SGordon Ross 		return (EINVAL);
777*02d09e03SGordon Ross 
778*02d09e03SGordon Ross 	mapinfo = MALLOC(mapcnt * sizeof (*mapinfo));
779*02d09e03SGordon Ross 	if (mapinfo == NULL) {
780*02d09e03SGordon Ross 		error = ENOMEM;
781*02d09e03SGordon Ross 		goto errout;
782*02d09e03SGordon Ross 	}
783*02d09e03SGordon Ross 	bzero(mapinfo, mapcnt * sizeof (*mapinfo));
784*02d09e03SGordon Ross 
785*02d09e03SGordon Ross 
786*02d09e03SGordon Ross 	/*
787*02d09e03SGordon Ross 	 * Build our request to the idmap deamon.
788*02d09e03SGordon Ross 	 */
789*02d09e03SGordon Ross #ifdef	_KERNEL
790*02d09e03SGordon Ross 	idmap_gh = kidmap_get_create(curproc->p_zone);
791*02d09e03SGordon Ross #else /* _KERNEL */
792*02d09e03SGordon Ross 	idms = idmap_init(&idmap_h);
793*02d09e03SGordon Ross 	if (idms != IDMAP_SUCCESS) {
794*02d09e03SGordon Ross 		error = ENOTACTIVE;
795*02d09e03SGordon Ross 		goto errout;
796*02d09e03SGordon Ross 	}
797*02d09e03SGordon Ross 	idms = idmap_get_create(idmap_h, &idmap_gh);
798*02d09e03SGordon Ross 	if (idms != IDMAP_SUCCESS) {
799*02d09e03SGordon Ross 		error = ENOTACTIVE;
800*02d09e03SGordon Ross 		goto errout;
801*02d09e03SGordon Ross 	}
802*02d09e03SGordon Ross #endif /* _KERNEL */
803*02d09e03SGordon Ross 
804*02d09e03SGordon Ross 	mip = mapinfo;
805*02d09e03SGordon Ross 	if (sd->sd_owner) {
806*02d09e03SGordon Ross 		error = mkrq_idmap_sid2ux(
807*02d09e03SGordon Ross 		    idmap_gh, sd->sd_owner, mip);
808*02d09e03SGordon Ross 		if (error)
809*02d09e03SGordon Ross 			goto errout;
810*02d09e03SGordon Ross 		mip++;
811*02d09e03SGordon Ross 	}
812*02d09e03SGordon Ross 	if (sd->sd_group) {
813*02d09e03SGordon Ross 		error = mkrq_idmap_sid2ux(
814*02d09e03SGordon Ross 		    idmap_gh, sd->sd_group, mip);
815*02d09e03SGordon Ross 		if (error)
816*02d09e03SGordon Ross 			goto errout;
817*02d09e03SGordon Ross 		mip++;
818*02d09e03SGordon Ross 	}
819*02d09e03SGordon Ross 	if (sd->sd_sacl) {
820*02d09e03SGordon Ross 		ntacl = sd->sd_sacl;
821*02d09e03SGordon Ross 		ntacep = &ntacl->acl_acevec[0];
822*02d09e03SGordon Ross 		for (i = 0; i < ntacl->acl_acecount; i++) {
823*02d09e03SGordon Ross 			error = mkrq_idmap_sid2ux(
824*02d09e03SGordon Ross 			    idmap_gh, (*ntacep)->ace_sid, mip);
825*02d09e03SGordon Ross 			if (error)
826*02d09e03SGordon Ross 				goto errout;
827*02d09e03SGordon Ross 			ntacep++;
828*02d09e03SGordon Ross 			mip++;
829*02d09e03SGordon Ross 		}
830*02d09e03SGordon Ross 	}
831*02d09e03SGordon Ross 	if (sd->sd_dacl) {
832*02d09e03SGordon Ross 		ntacl = sd->sd_dacl;
833*02d09e03SGordon Ross 		ntacep = &ntacl->acl_acevec[0];
834*02d09e03SGordon Ross 		for (i = 0; i < ntacl->acl_acecount; i++) {
835*02d09e03SGordon Ross 			error = mkrq_idmap_sid2ux(
836*02d09e03SGordon Ross 			    idmap_gh, (*ntacep)->ace_sid, mip);
837*02d09e03SGordon Ross 			if (error)
838*02d09e03SGordon Ross 				goto errout;
839*02d09e03SGordon Ross 			ntacep++;
840*02d09e03SGordon Ross 			mip++;
841*02d09e03SGordon Ross 		}
842*02d09e03SGordon Ross 	}
843*02d09e03SGordon Ross 
844*02d09e03SGordon Ross 	idms = I_GetMappings(idmap_gh);
845*02d09e03SGordon Ross 	if (idms != IDMAP_SUCCESS) {
846*02d09e03SGordon Ross 		/* creative error choice */
847*02d09e03SGordon Ross 		error = EIDRM;
848*02d09e03SGordon Ross 		goto errout;
849*02d09e03SGordon Ross 	}
850*02d09e03SGordon Ross 
851*02d09e03SGordon Ross 	/*
852*02d09e03SGordon Ross 	 * With any luck, we now have Unix user/group IDs
853*02d09e03SGordon Ross 	 * for every Windows SID in the security descriptor.
854*02d09e03SGordon Ross 	 * The remaining work is just format conversion.
855*02d09e03SGordon Ross 	 */
856*02d09e03SGordon Ross 	mip = mapinfo;
857*02d09e03SGordon Ross 	if (sd->sd_owner) {
858*02d09e03SGordon Ross 		if (uidp) {
859*02d09e03SGordon Ross 			if (mip->mi_isuser == 1)
860*02d09e03SGordon Ross 				*uidp = mip->mi_uid;
861*02d09e03SGordon Ross 			else
862*02d09e03SGordon Ross 				*uidp = (uid_t)-1;
863*02d09e03SGordon Ross 		}
864*02d09e03SGordon Ross 		mip++;
865*02d09e03SGordon Ross 	} else {
866*02d09e03SGordon Ross 		if (uidp)
867*02d09e03SGordon Ross 			*uidp = (uid_t)-1;
868*02d09e03SGordon Ross 	}
869*02d09e03SGordon Ross 	if (sd->sd_group) {
870*02d09e03SGordon Ross 		if (gidp) {
871*02d09e03SGordon Ross 			if (mip->mi_isuser == 0)
872*02d09e03SGordon Ross 				*gidp = (gid_t)mip->mi_uid;
873*02d09e03SGordon Ross 			else
874*02d09e03SGordon Ross 				*gidp = (gid_t)-1;
875*02d09e03SGordon Ross 		}
876*02d09e03SGordon Ross 		mip++;
877*02d09e03SGordon Ross 	} else {
878*02d09e03SGordon Ross 		if (gidp)
879*02d09e03SGordon Ross 			*gidp = (gid_t)-1;
880*02d09e03SGordon Ross 	}
881*02d09e03SGordon Ross 
882*02d09e03SGordon Ross 	if (acl_info == NULL) {
883*02d09e03SGordon Ross 		/* Caller only wanted uid/gid */
884*02d09e03SGordon Ross 		goto ok_out;
885*02d09e03SGordon Ross 	}
886*02d09e03SGordon Ross 
887*02d09e03SGordon Ross 	/*
888*02d09e03SGordon Ross 	 * Build the ZFS-style ACL
889*02d09e03SGordon Ross 	 */
890*02d09e03SGordon Ross 	zacecnt = 0;
891*02d09e03SGordon Ross 	if (sd->sd_sacl)
892*02d09e03SGordon Ross 		zacecnt += sd->sd_sacl->acl_acecount;
893*02d09e03SGordon Ross 	if (sd->sd_dacl)
894*02d09e03SGordon Ross 		zacecnt += sd->sd_dacl->acl_acecount;
895*02d09e03SGordon Ross 	zacl_size = zacecnt * sizeof (ace_t);
896*02d09e03SGordon Ross 	zacep = MALLOC(zacl_size);
897*02d09e03SGordon Ross #ifdef _KERNEL
898*02d09e03SGordon Ross 	acl_info->vsa_aclentp = zacep;
899*02d09e03SGordon Ross 	acl_info->vsa_aclentsz = zacl_size;
900*02d09e03SGordon Ross #else	/* _KERNEL */
901*02d09e03SGordon Ross 	if (zacep == NULL) {
902*02d09e03SGordon Ross 		error = ENOMEM;
903*02d09e03SGordon Ross 		goto errout;
904*02d09e03SGordon Ross 	}
905*02d09e03SGordon Ross 	acl_info->acl_cnt = zacecnt;
906*02d09e03SGordon Ross 	acl_info->acl_aclp = zacep;
907*02d09e03SGordon Ross #endif	/* _KERNEL */
908*02d09e03SGordon Ross 
909*02d09e03SGordon Ross 	if (sd->sd_sacl) {
910*02d09e03SGordon Ross 		ntacl = sd->sd_sacl;
911*02d09e03SGordon Ross 		ntacep = &ntacl->acl_acevec[0];
912*02d09e03SGordon Ross 		for (i = 0; i < ntacl->acl_acecount; i++) {
913*02d09e03SGordon Ross 			ntace2zace(zacep, *ntacep, mip);
914*02d09e03SGordon Ross 			zacep++;
915*02d09e03SGordon Ross 			ntacep++;
916*02d09e03SGordon Ross 			mip++;
917*02d09e03SGordon Ross 		}
918*02d09e03SGordon Ross 	}
919*02d09e03SGordon Ross 	if (sd->sd_dacl) {
920*02d09e03SGordon Ross 		ntacl = sd->sd_dacl;
921*02d09e03SGordon Ross 		ntacep = &ntacl->acl_acevec[0];
922*02d09e03SGordon Ross 		for (i = 0; i < ntacl->acl_acecount; i++) {
923*02d09e03SGordon Ross 			ntace2zace(zacep, *ntacep, mip);
924*02d09e03SGordon Ross 			zacep++;
925*02d09e03SGordon Ross 			ntacep++;
926*02d09e03SGordon Ross 			mip++;
927*02d09e03SGordon Ross 		}
928*02d09e03SGordon Ross 	}
929*02d09e03SGordon Ross 
930*02d09e03SGordon Ross ok_out:
931*02d09e03SGordon Ross 	error = 0;
932*02d09e03SGordon Ross 
933*02d09e03SGordon Ross errout:
934*02d09e03SGordon Ross 	if (mapinfo)
935*02d09e03SGordon Ross 		FREESZ(mapinfo, mapcnt * sizeof (*mapinfo));
936*02d09e03SGordon Ross 
937*02d09e03SGordon Ross 	return (error);
938*02d09e03SGordon Ross }
939*02d09e03SGordon Ross 
940*02d09e03SGordon Ross 
941*02d09e03SGordon Ross /*
942*02d09e03SGordon Ross  * Convert an internal SD to a ZFS-style ACL.
943*02d09e03SGordon Ross  * Include owner/group too if uid/gid != -1.
944*02d09e03SGordon Ross  * Note optional arg: vsa/acl
945*02d09e03SGordon Ross  */
946*02d09e03SGordon Ross /*ARGSUSED*/
947*02d09e03SGordon Ross int smbfs_acl_zfs2sd(
948*02d09e03SGordon Ross #ifdef	_KERNEL
949*02d09e03SGordon Ross 	vsecattr_t *vsa,
950*02d09e03SGordon Ross #else /* _KERNEL */
951*02d09e03SGordon Ross 	acl_t *acl,
952*02d09e03SGordon Ross #endif /* _KERNEL */
953*02d09e03SGordon Ross 	uid_t uid, gid_t gid,
954*02d09e03SGordon Ross 	i_ntsd_t **sdp)
955*02d09e03SGordon Ross {
956*02d09e03SGordon Ross 	/* XXX - todo */
957*02d09e03SGordon Ross 	return (ENOSYS);
958*02d09e03SGordon Ross }
959