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