xref: /onnv-gate/usr/src/lib/libsmbfs/smb/acl_api.c (revision 6711:d684034ad960)
1*6711Sgwr /*
2*6711Sgwr  * CDDL HEADER START
3*6711Sgwr  *
4*6711Sgwr  * The contents of this file are subject to the terms of the
5*6711Sgwr  * Common Development and Distribution License (the "License").
6*6711Sgwr  * You may not use this file except in compliance with the License.
7*6711Sgwr  *
8*6711Sgwr  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*6711Sgwr  * or http://www.opensolaris.org/os/licensing.
10*6711Sgwr  * See the License for the specific language governing permissions
11*6711Sgwr  * and limitations under the License.
12*6711Sgwr  *
13*6711Sgwr  * When distributing Covered Code, include this CDDL HEADER in each
14*6711Sgwr  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*6711Sgwr  * If applicable, add the following below this CDDL HEADER, with the
16*6711Sgwr  * fields enclosed by brackets "[]" replaced with your own identifying
17*6711Sgwr  * information: Portions Copyright [yyyy] [name of copyright owner]
18*6711Sgwr  *
19*6711Sgwr  * CDDL HEADER END
20*6711Sgwr  */
21*6711Sgwr 
22*6711Sgwr /*
23*6711Sgwr  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*6711Sgwr  * Use is subject to license terms.
25*6711Sgwr  */
26*6711Sgwr 
27*6711Sgwr #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*6711Sgwr 
29*6711Sgwr /*
30*6711Sgwr  * ACL API for smbfs
31*6711Sgwr  */
32*6711Sgwr 
33*6711Sgwr #include <sys/types.h>
34*6711Sgwr #include <sys/errno.h>
35*6711Sgwr #include <sys/cred.h>
36*6711Sgwr #include <sys/cmn_err.h>
37*6711Sgwr #include <sys/kmem.h>
38*6711Sgwr #include <sys/sunddi.h>
39*6711Sgwr #include <sys/acl.h>
40*6711Sgwr #include <sys/vnode.h>
41*6711Sgwr #include <sys/vfs.h>
42*6711Sgwr #include <sys/byteorder.h>
43*6711Sgwr 
44*6711Sgwr #include <errno.h>
45*6711Sgwr #include <stdio.h>
46*6711Sgwr #include <strings.h>
47*6711Sgwr #include <unistd.h>
48*6711Sgwr 
49*6711Sgwr #include <umem.h>
50*6711Sgwr #include <idmap.h>
51*6711Sgwr 
52*6711Sgwr #include <sys/fs/smbfs_ioctl.h>
53*6711Sgwr 
54*6711Sgwr #include <netsmb/smb_lib.h>
55*6711Sgwr #include <netsmb/smbfs_acl.h>
56*6711Sgwr #include <netsmb/smbfs_isec.h>
57*6711Sgwr 
58*6711Sgwr /* Sanity check SD sizes */
59*6711Sgwr #define	MAX_RAW_SD_SIZE	32768
60*6711Sgwr 
61*6711Sgwr /* XXX: acl_common.h */
62*6711Sgwr acl_t *acl_alloc(enum acl_type);
63*6711Sgwr void acl_free(acl_t *);
64*6711Sgwr 
65*6711Sgwr 
66*6711Sgwr /*
67*6711Sgwr  * Get/set a Windows security descriptor (SD)
68*6711Sgwr  * using the (private) smbfs ioctl mechanism.
69*6711Sgwr  * Note: Get allocates mbp->mb_top
70*6711Sgwr  */
71*6711Sgwr 
72*6711Sgwr /* ARGSUSED */
73*6711Sgwr int
74*6711Sgwr smbfs_acl_iocget(int fd, uint32_t selector, mbdata_t *mbp)
75*6711Sgwr {
76*6711Sgwr 	ioc_sdbuf_t	iocb;
77*6711Sgwr 	struct mbuf	*m;
78*6711Sgwr 	int		error;
79*6711Sgwr 
80*6711Sgwr 	error = mb_init(mbp, MAX_RAW_SD_SIZE);
81*6711Sgwr 	if (error)
82*6711Sgwr 		return (error);
83*6711Sgwr 
84*6711Sgwr 	m = mbp->mb_top;
85*6711Sgwr 	iocb.addr = mtod(m, uintptr_t);
86*6711Sgwr 	iocb.alloc = m->m_maxlen;
87*6711Sgwr 	iocb.used = 0;
88*6711Sgwr 	iocb.selector = selector;
89*6711Sgwr 
90*6711Sgwr 	/*
91*6711Sgwr 	 * This does the OTW Get.
92*6711Sgwr 	 */
93*6711Sgwr 	if (ioctl(fd, SMBFSIO_GETSD, &iocb) < 0) {
94*6711Sgwr 		error = errno;
95*6711Sgwr 		goto errout;
96*6711Sgwr 	}
97*6711Sgwr 
98*6711Sgwr 	m->m_len = iocb.used;
99*6711Sgwr 	return (0);
100*6711Sgwr 
101*6711Sgwr errout:
102*6711Sgwr 	mb_done(mbp);
103*6711Sgwr 	return (error);
104*6711Sgwr }
105*6711Sgwr 
106*6711Sgwr /* ARGSUSED */
107*6711Sgwr int
108*6711Sgwr smbfs_acl_iocset(int fd, uint32_t selector, mbdata_t *mbp)
109*6711Sgwr {
110*6711Sgwr 	ioc_sdbuf_t	iocb;
111*6711Sgwr 	struct mbuf	*m;
112*6711Sgwr 	int		error;
113*6711Sgwr 
114*6711Sgwr 	/* Make the data contiguous. */
115*6711Sgwr 	error = m_lineup(mbp->mb_top, &m);
116*6711Sgwr 	if (error)
117*6711Sgwr 		return (error);
118*6711Sgwr 
119*6711Sgwr 	if (mbp->mb_top != m)
120*6711Sgwr 		mb_initm(mbp, m);
121*6711Sgwr 
122*6711Sgwr 	iocb.addr = mtod(m, uintptr_t);
123*6711Sgwr 	iocb.alloc = m->m_maxlen;
124*6711Sgwr 	iocb.used  = m->m_len;
125*6711Sgwr 	iocb.selector = selector;
126*6711Sgwr 
127*6711Sgwr 	/*
128*6711Sgwr 	 * This does the OTW Set.
129*6711Sgwr 	 */
130*6711Sgwr 	if (ioctl(fd, SMBFSIO_SETSD, &iocb) < 0)
131*6711Sgwr 		error = errno;
132*6711Sgwr 
133*6711Sgwr 	return (error);
134*6711Sgwr }
135*6711Sgwr 
136*6711Sgwr /*
137*6711Sgwr  * Get an NT SD from the open file via ioctl.
138*6711Sgwr  */
139*6711Sgwr int
140*6711Sgwr smbfs_acl_getsd(int fd, uint32_t selector, i_ntsd_t **sdp)
141*6711Sgwr {
142*6711Sgwr 	mbdata_t *mbp, mb_store;
143*6711Sgwr 	int error;
144*6711Sgwr 
145*6711Sgwr 	mbp = &mb_store;
146*6711Sgwr 	bzero(mbp, sizeof (*mbp));
147*6711Sgwr 
148*6711Sgwr 	/*
149*6711Sgwr 	 * Get the raw Windows SD via ioctl.
150*6711Sgwr 	 * Returns allocated mbchain in mbp.
151*6711Sgwr 	 */
152*6711Sgwr 	error = smbfs_acl_iocget(fd, selector, mbp);
153*6711Sgwr 	if (error == 0) {
154*6711Sgwr 		/*
155*6711Sgwr 		 * Import the raw SD into "internal" form.
156*6711Sgwr 		 * (like "absolute" form per. NT docs)
157*6711Sgwr 		 * Returns allocated data in sdp
158*6711Sgwr 		 */
159*6711Sgwr 		error = mb_get_ntsd(mbp, sdp);
160*6711Sgwr 	}
161*6711Sgwr 
162*6711Sgwr 	mb_done(mbp);
163*6711Sgwr 	return (error);
164*6711Sgwr }
165*6711Sgwr 
166*6711Sgwr /*
167*6711Sgwr  * Set an NT SD onto the open file via ioctl.
168*6711Sgwr  */
169*6711Sgwr int
170*6711Sgwr smbfs_acl_setsd(int fd, uint32_t selector, i_ntsd_t *sd)
171*6711Sgwr {
172*6711Sgwr 	mbdata_t *mbp, mb_store;
173*6711Sgwr 	int error;
174*6711Sgwr 
175*6711Sgwr 	mbp = &mb_store;
176*6711Sgwr 	mb_init(mbp, M_MINSIZE);
177*6711Sgwr 
178*6711Sgwr 	/*
179*6711Sgwr 	 * Export the "internal" SD into an mb chain.
180*6711Sgwr 	 * (a.k.a "self-relative" form per. NT docs)
181*6711Sgwr 	 * Returns allocated mbchain in mbp.
182*6711Sgwr 	 */
183*6711Sgwr 	error = mb_put_ntsd(mbp, sd);
184*6711Sgwr 	if (error == 0) {
185*6711Sgwr 		/*
186*6711Sgwr 		 * Set the raw Windows SD via ioctl.
187*6711Sgwr 		 */
188*6711Sgwr 		error = smbfs_acl_iocset(fd, selector, mbp);
189*6711Sgwr 	}
190*6711Sgwr 
191*6711Sgwr 	mb_done(mbp);
192*6711Sgwr 
193*6711Sgwr 	return (error);
194*6711Sgwr }
195*6711Sgwr 
196*6711Sgwr 
197*6711Sgwr 
198*6711Sgwr /*
199*6711Sgwr  * Convenience function to Get security using a
200*6711Sgwr  * ZFS-style ACL (libsec acl, type=ACE_T)
201*6711Sgwr  * Intentionally similar to: facl_get(3SEC)
202*6711Sgwr  */
203*6711Sgwr int
204*6711Sgwr smbfs_acl_get(int fd, acl_t **aclp, uid_t *uidp, gid_t *gidp)
205*6711Sgwr {
206*6711Sgwr 	i_ntsd_t *sd = NULL;
207*6711Sgwr 	acl_t *acl = NULL;
208*6711Sgwr 	uint32_t selector;
209*6711Sgwr 	int error;
210*6711Sgwr 
211*6711Sgwr 	/*
212*6711Sgwr 	 * Which parts of the SD are being requested?
213*6711Sgwr 	 * XXX: Should we request the SACL too?  If so,
214*6711Sgwr 	 * might that cause this access to be denied?
215*6711Sgwr 	 * Or maybe: if we get access denied, try the
216*6711Sgwr 	 * open/fetch again without the SACL bit.
217*6711Sgwr 	 */
218*6711Sgwr 	selector = 0;
219*6711Sgwr 	if (aclp)
220*6711Sgwr 		selector |= DACL_SECURITY_INFORMATION;
221*6711Sgwr 	if (uidp)
222*6711Sgwr 		selector |= OWNER_SECURITY_INFORMATION;
223*6711Sgwr 	if (gidp)
224*6711Sgwr 		selector |= GROUP_SECURITY_INFORMATION;
225*6711Sgwr 
226*6711Sgwr 	if (selector == 0)
227*6711Sgwr 		return (0);
228*6711Sgwr 
229*6711Sgwr 	/*
230*6711Sgwr 	 * Get the Windows SD via ioctl, in
231*6711Sgwr 	 * "internal" (absolute) form.
232*6711Sgwr 	 */
233*6711Sgwr 	error = smbfs_acl_getsd(fd, selector, &sd);
234*6711Sgwr 	if (error)
235*6711Sgwr 		return (error);
236*6711Sgwr 	/* Note: sd now holds allocated data. */
237*6711Sgwr 
238*6711Sgwr 	/*
239*6711Sgwr 	 * Convert the internal SD to a ZFS ACL.
240*6711Sgwr 	 * Get uid/gid too if pointers != NULL.
241*6711Sgwr 	 */
242*6711Sgwr 	if (aclp) {
243*6711Sgwr 		acl = acl_alloc(ACE_T);
244*6711Sgwr 		if (acl == NULL) {
245*6711Sgwr 			error = ENOMEM;
246*6711Sgwr 			goto out;
247*6711Sgwr 		}
248*6711Sgwr 	}
249*6711Sgwr 	error = smbfs_acl_sd2zfs(sd, acl, uidp, gidp);
250*6711Sgwr 	if (error)
251*6711Sgwr 		goto out;
252*6711Sgwr 
253*6711Sgwr 	/* Success! */
254*6711Sgwr 	if (aclp) {
255*6711Sgwr 		*aclp = acl;
256*6711Sgwr 		acl = NULL;
257*6711Sgwr 	}
258*6711Sgwr 
259*6711Sgwr out:
260*6711Sgwr 	if (acl)
261*6711Sgwr 		acl_free(acl);
262*6711Sgwr 	smbfs_acl_free_sd(sd);
263*6711Sgwr 	return (error);
264*6711Sgwr }
265*6711Sgwr 
266*6711Sgwr /*
267*6711Sgwr  * Convenience function to Set security using a
268*6711Sgwr  * ZFS-style ACL (libsec acl, type=ACE_T)
269*6711Sgwr  * Intentionally similar to: facl_set(3SEC)
270*6711Sgwr  */
271*6711Sgwr int
272*6711Sgwr smbfs_acl_set(int fd, acl_t *acl, uid_t uid, gid_t gid)
273*6711Sgwr {
274*6711Sgwr 	i_ntsd_t *sd = NULL;
275*6711Sgwr 	uint32_t selector;
276*6711Sgwr 	int error;
277*6711Sgwr 
278*6711Sgwr 	/*
279*6711Sgwr 	 * Which parts of the SD are being modified?
280*6711Sgwr 	 * XXX: Ditto comments above re. SACL.
281*6711Sgwr 	 */
282*6711Sgwr 	selector = 0;
283*6711Sgwr 	if (acl)
284*6711Sgwr 		selector |= DACL_SECURITY_INFORMATION;
285*6711Sgwr 	if (uid != (uid_t)-1)
286*6711Sgwr 		selector |= OWNER_SECURITY_INFORMATION;
287*6711Sgwr 	if (gid != (gid_t)-1)
288*6711Sgwr 		selector |= GROUP_SECURITY_INFORMATION;
289*6711Sgwr 	if (selector == 0)
290*6711Sgwr 		return (0);
291*6711Sgwr 
292*6711Sgwr 	if (acl && acl->acl_type != ACE_T)
293*6711Sgwr 		return (EINVAL);
294*6711Sgwr 
295*6711Sgwr 	/*
296*6711Sgwr 	 * Convert the ZFS ACL to an internal SD.
297*6711Sgwr 	 * Returns allocated data in sd
298*6711Sgwr 	 */
299*6711Sgwr 	error = smbfs_acl_zfs2sd(acl, uid, gid, &sd);
300*6711Sgwr 	if (error == 0)
301*6711Sgwr 		error = smbfs_acl_setsd(fd, selector, sd);
302*6711Sgwr 
303*6711Sgwr 	smbfs_acl_free_sd(sd);
304*6711Sgwr 
305*6711Sgwr 	return (error);
306*6711Sgwr }
307