xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_sd.c (revision 9832:3569b6c7f56c)
1*9832Samw@Sun.COM /*
2*9832Samw@Sun.COM  * CDDL HEADER START
3*9832Samw@Sun.COM  *
4*9832Samw@Sun.COM  * The contents of this file are subject to the terms of the
5*9832Samw@Sun.COM  * Common Development and Distribution License (the "License").
6*9832Samw@Sun.COM  * You may not use this file except in compliance with the License.
7*9832Samw@Sun.COM  *
8*9832Samw@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9832Samw@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*9832Samw@Sun.COM  * See the License for the specific language governing permissions
11*9832Samw@Sun.COM  * and limitations under the License.
12*9832Samw@Sun.COM  *
13*9832Samw@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*9832Samw@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9832Samw@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*9832Samw@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*9832Samw@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*9832Samw@Sun.COM  *
19*9832Samw@Sun.COM  * CDDL HEADER END
20*9832Samw@Sun.COM  */
21*9832Samw@Sun.COM /*
22*9832Samw@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*9832Samw@Sun.COM  * Use is subject to license terms.
24*9832Samw@Sun.COM  */
25*9832Samw@Sun.COM 
26*9832Samw@Sun.COM /*
27*9832Samw@Sun.COM  * This is a helper file to get/set Windows SD. This is used by
28*9832Samw@Sun.COM  * SRVSVC service.
29*9832Samw@Sun.COM  */
30*9832Samw@Sun.COM #include <strings.h>
31*9832Samw@Sun.COM #include <libzfs.h>
32*9832Samw@Sun.COM #include <smbsrv/nterror.h>
33*9832Samw@Sun.COM #include <smbsrv/ntstatus.h>
34*9832Samw@Sun.COM #include <smbsrv/libmlsvc.h>
35*9832Samw@Sun.COM #include <smbsrv/ndl/srvsvc.ndl>
36*9832Samw@Sun.COM 
37*9832Samw@Sun.COM /* Size of offset members in mslm_security_descriptor structure */
38*9832Samw@Sun.COM #define	SRVSVC_SD_OFFSET_SZ	16
39*9832Samw@Sun.COM 
40*9832Samw@Sun.COM #define	SRVSVC_ACE_OFFSET	8
41*9832Samw@Sun.COM #define	SRVSVC_SID_OFFSET	8
42*9832Samw@Sun.COM 
43*9832Samw@Sun.COM static uint32_t srvsvc_sd_status_to_error(uint32_t);
44*9832Samw@Sun.COM static uint32_t srvsvc_sd_set_relative(smb_sd_t *, uint8_t *);
45*9832Samw@Sun.COM static uint32_t srvsvc_sd_set_absolute(uint8_t *, smb_sd_t *);
46*9832Samw@Sun.COM 
47*9832Samw@Sun.COM /*
48*9832Samw@Sun.COM  * This method computes ACL on share path from a share name.
49*9832Samw@Sun.COM  * Return 0 upon success, -1 upon failure.
50*9832Samw@Sun.COM  */
51*9832Samw@Sun.COM static int
52*9832Samw@Sun.COM srvsvc_shareacl_getpath(smb_share_t *si, char *shr_acl_path)
53*9832Samw@Sun.COM {
54*9832Samw@Sun.COM 	char dataset[MAXPATHLEN];
55*9832Samw@Sun.COM 	char mp[ZFS_MAXPROPLEN];
56*9832Samw@Sun.COM 	libzfs_handle_t *libhd;
57*9832Samw@Sun.COM 	zfs_handle_t *zfshd;
58*9832Samw@Sun.COM 	int ret = 0;
59*9832Samw@Sun.COM 
60*9832Samw@Sun.COM 	ret = smb_getdataset(si->shr_path, dataset, MAXPATHLEN);
61*9832Samw@Sun.COM 	if (ret != 0)
62*9832Samw@Sun.COM 		return (ret);
63*9832Samw@Sun.COM 
64*9832Samw@Sun.COM 	if ((libhd = libzfs_init()) == NULL)
65*9832Samw@Sun.COM 		return (-1);
66*9832Samw@Sun.COM 
67*9832Samw@Sun.COM 	if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_DATASET)) == NULL) {
68*9832Samw@Sun.COM 		libzfs_fini(libhd);
69*9832Samw@Sun.COM 		return (-1);
70*9832Samw@Sun.COM 	}
71*9832Samw@Sun.COM 
72*9832Samw@Sun.COM 	if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL,
73*9832Samw@Sun.COM 	    NULL, 0, B_FALSE) != 0) {
74*9832Samw@Sun.COM 		zfs_close(zfshd);
75*9832Samw@Sun.COM 		libzfs_fini(libhd);
76*9832Samw@Sun.COM 		return (-1);
77*9832Samw@Sun.COM 	}
78*9832Samw@Sun.COM 
79*9832Samw@Sun.COM 	zfs_close(zfshd);
80*9832Samw@Sun.COM 	libzfs_fini(libhd);
81*9832Samw@Sun.COM 
82*9832Samw@Sun.COM 	(void) snprintf(shr_acl_path, MAXPATHLEN, "%s/.zfs/shares/%s",
83*9832Samw@Sun.COM 	    mp, si->shr_name);
84*9832Samw@Sun.COM 
85*9832Samw@Sun.COM 	return (ret);
86*9832Samw@Sun.COM }
87*9832Samw@Sun.COM 
88*9832Samw@Sun.COM /*
89*9832Samw@Sun.COM  * This method sets Security Descriptor on a share path.
90*9832Samw@Sun.COM  *
91*9832Samw@Sun.COM  * Returns:
92*9832Samw@Sun.COM  *	ERROR_SUCCESS
93*9832Samw@Sun.COM  *	ERROR_NOT_ENOUGH_MEMORY
94*9832Samw@Sun.COM  *	ERROR_INVALID_ACL
95*9832Samw@Sun.COM  *	ERROR_INVALID_SID
96*9832Samw@Sun.COM  *	ERROR_INVALID_SECURITY_DESCR
97*9832Samw@Sun.COM  *	ERROR_NONE_MAPPED
98*9832Samw@Sun.COM  *	ERROR_INTERNAL_ERROR
99*9832Samw@Sun.COM  *	ERROR_PATH_NOT_FOUND
100*9832Samw@Sun.COM  */
101*9832Samw@Sun.COM uint32_t
102*9832Samw@Sun.COM srvsvc_sd_set(smb_share_t *si, uint8_t *sdbuf)
103*9832Samw@Sun.COM {
104*9832Samw@Sun.COM 	smb_sd_t sd;
105*9832Samw@Sun.COM 	uint32_t status = ERROR_SUCCESS;
106*9832Samw@Sun.COM 	char path[MAXPATHLEN];
107*9832Samw@Sun.COM 	int ret = 0;
108*9832Samw@Sun.COM 
109*9832Samw@Sun.COM 	ret = srvsvc_shareacl_getpath(si, path);
110*9832Samw@Sun.COM 	if (ret != 0)
111*9832Samw@Sun.COM 		return (ERROR_PATH_NOT_FOUND);
112*9832Samw@Sun.COM 
113*9832Samw@Sun.COM 	smb_sd_init(&sd, 0);
114*9832Samw@Sun.COM 	status = srvsvc_sd_set_absolute(sdbuf, &sd);
115*9832Samw@Sun.COM 	if (status != ERROR_SUCCESS) {
116*9832Samw@Sun.COM 		smb_sd_term(&sd);
117*9832Samw@Sun.COM 		return (status);
118*9832Samw@Sun.COM 	}
119*9832Samw@Sun.COM 
120*9832Samw@Sun.COM 	status = smb_sd_write(path, &sd, SMB_DACL_SECINFO);
121*9832Samw@Sun.COM 	status = srvsvc_sd_status_to_error(status);
122*9832Samw@Sun.COM 	smb_sd_term(&sd);
123*9832Samw@Sun.COM 
124*9832Samw@Sun.COM 	return (status);
125*9832Samw@Sun.COM }
126*9832Samw@Sun.COM 
127*9832Samw@Sun.COM /*
128*9832Samw@Sun.COM  * This method returns a Security Descriptor of a share path in self relative
129*9832Samw@Sun.COM  * format. Call to this function with NULL buffer, returns the size of the
130*9832Samw@Sun.COM  * security descriptor, which can be used to allocate buffer.
131*9832Samw@Sun.COM  *
132*9832Samw@Sun.COM  * Returns:
133*9832Samw@Sun.COM  *	ERROR_SUCCESS
134*9832Samw@Sun.COM  *	ERROR_NOT_ENOUGH_MEMORY
135*9832Samw@Sun.COM  *	ERROR_INVALID_ACL
136*9832Samw@Sun.COM  *	ERROR_INVALID_SID
137*9832Samw@Sun.COM  *	ERROR_INVALID_SECURITY_DESCR
138*9832Samw@Sun.COM  *	ERROR_INVALID_PARAMETER
139*9832Samw@Sun.COM  *	ERROR_NONE_MAPPED
140*9832Samw@Sun.COM  *	ERROR_INTERNAL_ERROR
141*9832Samw@Sun.COM  *	ERROR_PATH_NOT_FOUND
142*9832Samw@Sun.COM  */
143*9832Samw@Sun.COM uint32_t
144*9832Samw@Sun.COM srvsvc_sd_get(smb_share_t *si, uint8_t *sdbuf, uint32_t *size)
145*9832Samw@Sun.COM {
146*9832Samw@Sun.COM 	smb_sd_t sd;
147*9832Samw@Sun.COM 	uint32_t status = ERROR_SUCCESS;
148*9832Samw@Sun.COM 	char path[MAXPATHLEN];
149*9832Samw@Sun.COM 	int ret = 0;
150*9832Samw@Sun.COM 
151*9832Samw@Sun.COM 	if (sdbuf == NULL && size == NULL)
152*9832Samw@Sun.COM 		return (ERROR_INVALID_PARAMETER);
153*9832Samw@Sun.COM 
154*9832Samw@Sun.COM 	ret = srvsvc_shareacl_getpath(si, path);
155*9832Samw@Sun.COM 	if (ret != 0)
156*9832Samw@Sun.COM 		return (ERROR_PATH_NOT_FOUND);
157*9832Samw@Sun.COM 
158*9832Samw@Sun.COM 	bzero(&sd, sizeof (smb_sd_t));
159*9832Samw@Sun.COM 	status = smb_sd_read(path, &sd, SMB_ALL_SECINFO);
160*9832Samw@Sun.COM 	status = srvsvc_sd_status_to_error(status);
161*9832Samw@Sun.COM 	if (status != ERROR_SUCCESS) {
162*9832Samw@Sun.COM 		smb_sd_term(&sd);
163*9832Samw@Sun.COM 		return (status);
164*9832Samw@Sun.COM 	}
165*9832Samw@Sun.COM 
166*9832Samw@Sun.COM 	if (sdbuf == NULL) {
167*9832Samw@Sun.COM 		*size = smb_sd_len(&sd, SMB_ALL_SECINFO);
168*9832Samw@Sun.COM 		smb_sd_term(&sd);
169*9832Samw@Sun.COM 		return (status);
170*9832Samw@Sun.COM 	}
171*9832Samw@Sun.COM 
172*9832Samw@Sun.COM 	status = srvsvc_sd_set_relative(&sd, sdbuf);
173*9832Samw@Sun.COM 
174*9832Samw@Sun.COM 	smb_sd_term(&sd);
175*9832Samw@Sun.COM 	return (status);
176*9832Samw@Sun.COM }
177*9832Samw@Sun.COM 
178*9832Samw@Sun.COM /*
179*9832Samw@Sun.COM  * This method converts an ACE from absolute (pointer) to
180*9832Samw@Sun.COM  * self relative (flat buffer) format.
181*9832Samw@Sun.COM  *
182*9832Samw@Sun.COM  * Returns Win32 error codes.
183*9832Samw@Sun.COM  */
184*9832Samw@Sun.COM static uint32_t
185*9832Samw@Sun.COM srvsvc_ace_set_relative(mslm_ace_t *m_ace, struct mslm_sid *m_sid,
186*9832Samw@Sun.COM     smb_ace_t *ace)
187*9832Samw@Sun.COM {
188*9832Samw@Sun.COM 	if ((m_ace == NULL) || (ace == NULL))
189*9832Samw@Sun.COM 		return (ERROR_INVALID_PARAMETER);
190*9832Samw@Sun.COM 
191*9832Samw@Sun.COM 	bcopy(&ace->se_hdr, &m_ace->header, sizeof (mslm_ace_hdr_t));
192*9832Samw@Sun.COM 	m_ace->mask = ace->se_mask;
193*9832Samw@Sun.COM 
194*9832Samw@Sun.COM 	if ((ace->se_sid == NULL) || (m_sid == NULL))
195*9832Samw@Sun.COM 		return (ERROR_INVALID_PARAMETER);
196*9832Samw@Sun.COM 	bcopy(ace->se_sid, m_sid, smb_sid_len(ace->se_sid));
197*9832Samw@Sun.COM 
198*9832Samw@Sun.COM 	return (ERROR_SUCCESS);
199*9832Samw@Sun.COM }
200*9832Samw@Sun.COM 
201*9832Samw@Sun.COM /*
202*9832Samw@Sun.COM  * This method converts an ACL from absolute (pointer) to
203*9832Samw@Sun.COM  * self relative (flat buffer) format.
204*9832Samw@Sun.COM  *
205*9832Samw@Sun.COM  * Returns an initialized mslm_acl structure on success.
206*9832Samw@Sun.COM  * Returns NULL on failure.
207*9832Samw@Sun.COM  */
208*9832Samw@Sun.COM static struct mslm_acl *
209*9832Samw@Sun.COM srvsvc_acl_set_relative(uint8_t *sdbuf, smb_acl_t *acl)
210*9832Samw@Sun.COM {
211*9832Samw@Sun.COM 	struct mslm_acl *m_acl;
212*9832Samw@Sun.COM 
213*9832Samw@Sun.COM 	if (sdbuf == NULL)
214*9832Samw@Sun.COM 		return (NULL);
215*9832Samw@Sun.COM 
216*9832Samw@Sun.COM 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
217*9832Samw@Sun.COM 	m_acl = (struct mslm_acl *)sdbuf;
218*9832Samw@Sun.COM 	m_acl->revision = acl->sl_revision;
219*9832Samw@Sun.COM 	m_acl->sbz1 = 0;
220*9832Samw@Sun.COM 	m_acl->size = acl->sl_bsize;
221*9832Samw@Sun.COM 	m_acl->sbz2 = 0;
222*9832Samw@Sun.COM 	m_acl->ace_count = acl->sl_acecnt;
223*9832Samw@Sun.COM 
224*9832Samw@Sun.COM 	return (m_acl);
225*9832Samw@Sun.COM }
226*9832Samw@Sun.COM 
227*9832Samw@Sun.COM /*
228*9832Samw@Sun.COM  * This method converts Security Descriptor from absolute (pointer) to
229*9832Samw@Sun.COM  * self relative (flat buffer) format.
230*9832Samw@Sun.COM  *
231*9832Samw@Sun.COM  * Returns Win32 error codes.
232*9832Samw@Sun.COM  */
233*9832Samw@Sun.COM static uint32_t
234*9832Samw@Sun.COM srvsvc_sd_set_relative(smb_sd_t *sd, uint8_t *sdbuf)
235*9832Samw@Sun.COM {
236*9832Samw@Sun.COM 	mslm_security_descriptor_t *msd;
237*9832Samw@Sun.COM 	int offset, len, i;
238*9832Samw@Sun.COM 	smb_ace_t *ace;
239*9832Samw@Sun.COM 	mslm_ace_t *m_ace;
240*9832Samw@Sun.COM 	struct mslm_sid *m_sid;
241*9832Samw@Sun.COM 	uint16_t ace_cnt;
242*9832Samw@Sun.COM 	uint32_t status = ERROR_SUCCESS;
243*9832Samw@Sun.COM 
244*9832Samw@Sun.COM 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
245*9832Samw@Sun.COM 	msd = (mslm_security_descriptor_t *)sdbuf;
246*9832Samw@Sun.COM 	if (msd == NULL)
247*9832Samw@Sun.COM 		return (ERROR_INVALID_SECURITY_DESCR);
248*9832Samw@Sun.COM 
249*9832Samw@Sun.COM 	msd->revision = sd->sd_revision;
250*9832Samw@Sun.COM 	msd->sbz1 = 0;
251*9832Samw@Sun.COM 	msd->control = sd->sd_control | SE_SELF_RELATIVE;
252*9832Samw@Sun.COM 
253*9832Samw@Sun.COM 	offset = sizeof (mslm_security_descriptor_t) - SRVSVC_SD_OFFSET_SZ;
254*9832Samw@Sun.COM 	msd->offset_owner = msd->offset_group = 0;
255*9832Samw@Sun.COM 	msd->offset_sacl = msd->offset_dacl = 0;
256*9832Samw@Sun.COM 
257*9832Samw@Sun.COM 	if (sd->sd_owner != NULL) {
258*9832Samw@Sun.COM 		msd->offset_owner = offset;
259*9832Samw@Sun.COM 
260*9832Samw@Sun.COM 		if (sd->sd_owner == NULL)
261*9832Samw@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
262*9832Samw@Sun.COM 
263*9832Samw@Sun.COM 		len = smb_sid_len(sd->sd_owner);
264*9832Samw@Sun.COM 		bcopy(sd->sd_owner, &sdbuf[offset], len);
265*9832Samw@Sun.COM 		offset += len;
266*9832Samw@Sun.COM 	}
267*9832Samw@Sun.COM 
268*9832Samw@Sun.COM 	if (sd->sd_group != NULL) {
269*9832Samw@Sun.COM 		msd->offset_group = offset;
270*9832Samw@Sun.COM 
271*9832Samw@Sun.COM 		if (sd->sd_group == NULL)
272*9832Samw@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
273*9832Samw@Sun.COM 
274*9832Samw@Sun.COM 		len = smb_sid_len(sd->sd_group);
275*9832Samw@Sun.COM 		bcopy(sd->sd_group, &sdbuf[offset], len);
276*9832Samw@Sun.COM 		offset += len;
277*9832Samw@Sun.COM 	}
278*9832Samw@Sun.COM 
279*9832Samw@Sun.COM 	if (sd->sd_sacl != NULL) {
280*9832Samw@Sun.COM 		msd->offset_sacl = offset;
281*9832Samw@Sun.COM 		msd->sacl = srvsvc_acl_set_relative(&sdbuf[offset],
282*9832Samw@Sun.COM 		    sd->sd_sacl);
283*9832Samw@Sun.COM 		if (msd->sacl == NULL)
284*9832Samw@Sun.COM 			return (ERROR_INVALID_PARAMETER);
285*9832Samw@Sun.COM 
286*9832Samw@Sun.COM 		ace = sd->sd_sacl->sl_aces;
287*9832Samw@Sun.COM 		ace_cnt = msd->sacl->ace_count;
288*9832Samw@Sun.COM 		offset += SRVSVC_ACE_OFFSET;
289*9832Samw@Sun.COM 
290*9832Samw@Sun.COM 		for (i = 0; i < ace_cnt; i++, ace++) {
291*9832Samw@Sun.COM 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
292*9832Samw@Sun.COM 			m_ace = (mslm_ace_t *)&sdbuf[offset];
293*9832Samw@Sun.COM 			offset += SRVSVC_SID_OFFSET;
294*9832Samw@Sun.COM 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
295*9832Samw@Sun.COM 			m_sid = (struct mslm_sid *)&sdbuf[offset];
296*9832Samw@Sun.COM 
297*9832Samw@Sun.COM 			status = srvsvc_ace_set_relative(m_ace, m_sid, ace);
298*9832Samw@Sun.COM 			if (status != ERROR_SUCCESS)
299*9832Samw@Sun.COM 				return (status);
300*9832Samw@Sun.COM 			offset += smb_sid_len(ace->se_sid);
301*9832Samw@Sun.COM 		}
302*9832Samw@Sun.COM 	}
303*9832Samw@Sun.COM 
304*9832Samw@Sun.COM 	if (sd->sd_dacl != NULL) {
305*9832Samw@Sun.COM 		msd->offset_dacl = offset;
306*9832Samw@Sun.COM 		msd->dacl = srvsvc_acl_set_relative(&sdbuf[offset],
307*9832Samw@Sun.COM 		    sd->sd_dacl);
308*9832Samw@Sun.COM 		if (msd->dacl == NULL)
309*9832Samw@Sun.COM 			return (ERROR_INVALID_PARAMETER);
310*9832Samw@Sun.COM 
311*9832Samw@Sun.COM 		ace = sd->sd_dacl->sl_aces;
312*9832Samw@Sun.COM 		ace_cnt = msd->dacl->ace_count;
313*9832Samw@Sun.COM 		offset += SRVSVC_ACE_OFFSET;
314*9832Samw@Sun.COM 
315*9832Samw@Sun.COM 		for (i = 0; i < ace_cnt; i++, ace++) {
316*9832Samw@Sun.COM 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
317*9832Samw@Sun.COM 			m_ace = (mslm_ace_t *)&sdbuf[offset];
318*9832Samw@Sun.COM 			offset += SRVSVC_SID_OFFSET;
319*9832Samw@Sun.COM 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
320*9832Samw@Sun.COM 			m_sid = (struct mslm_sid *)&sdbuf[offset];
321*9832Samw@Sun.COM 
322*9832Samw@Sun.COM 			status = srvsvc_ace_set_relative(m_ace, m_sid, ace);
323*9832Samw@Sun.COM 			if (status != ERROR_SUCCESS)
324*9832Samw@Sun.COM 				return (status);
325*9832Samw@Sun.COM 			offset += smb_sid_len(ace->se_sid);
326*9832Samw@Sun.COM 		}
327*9832Samw@Sun.COM 	}
328*9832Samw@Sun.COM 
329*9832Samw@Sun.COM 	return (status);
330*9832Samw@Sun.COM }
331*9832Samw@Sun.COM 
332*9832Samw@Sun.COM /*
333*9832Samw@Sun.COM  * This method converts an ACE from self relative (flat buffer) to
334*9832Samw@Sun.COM  * absolute (pointer) format.
335*9832Samw@Sun.COM  *
336*9832Samw@Sun.COM  * Returns Win32 error codes.
337*9832Samw@Sun.COM  */
338*9832Samw@Sun.COM static uint32_t
339*9832Samw@Sun.COM srvsvc_ace_set_absolute(mslm_ace_t *m_ace, struct mslm_sid *m_sid,
340*9832Samw@Sun.COM     smb_ace_t *ace)
341*9832Samw@Sun.COM {
342*9832Samw@Sun.COM 	int sid_size = 0;
343*9832Samw@Sun.COM 	if ((m_ace == NULL) || (ace == NULL) || (m_sid == NULL))
344*9832Samw@Sun.COM 		return (ERROR_INVALID_PARAMETER);
345*9832Samw@Sun.COM 
346*9832Samw@Sun.COM 	bzero(ace, sizeof (smb_ace_t));
347*9832Samw@Sun.COM 	bcopy(&m_ace->header, &ace->se_hdr, sizeof (mslm_ace_hdr_t));
348*9832Samw@Sun.COM 	ace->se_mask = m_ace->mask;
349*9832Samw@Sun.COM 
350*9832Samw@Sun.COM 	sid_size = smb_sid_len((smb_sid_t *)m_sid);
351*9832Samw@Sun.COM 	if ((ace->se_sid = malloc(sid_size)) == NULL)
352*9832Samw@Sun.COM 		return (ERROR_NOT_ENOUGH_MEMORY);
353*9832Samw@Sun.COM 	bcopy(m_sid, ace->se_sid, sid_size);
354*9832Samw@Sun.COM 
355*9832Samw@Sun.COM 	return (ERROR_SUCCESS);
356*9832Samw@Sun.COM }
357*9832Samw@Sun.COM 
358*9832Samw@Sun.COM /*
359*9832Samw@Sun.COM  * This method converts an ACL from self relative (flat buffer) to
360*9832Samw@Sun.COM  * absolute (pointer) format.
361*9832Samw@Sun.COM  *
362*9832Samw@Sun.COM  * Returns an initialized smb_acl_t structure on success.
363*9832Samw@Sun.COM  * Returns NULL on failure.
364*9832Samw@Sun.COM  */
365*9832Samw@Sun.COM static smb_acl_t *
366*9832Samw@Sun.COM srvsvc_acl_set_absolute(uint8_t *sdbuf, int *offset)
367*9832Samw@Sun.COM {
368*9832Samw@Sun.COM 	uint8_t rev;
369*9832Samw@Sun.COM 	uint16_t sz, ace_cnt;
370*9832Samw@Sun.COM 	smb_acl_t *acl;
371*9832Samw@Sun.COM 
372*9832Samw@Sun.COM 	bcopy(&sdbuf[*offset], &rev, sizeof (uint8_t));
373*9832Samw@Sun.COM 	*offset += 2; /* Pad for Sbz1 */
374*9832Samw@Sun.COM 	bcopy(&sdbuf[*offset], &sz, sizeof (uint16_t));
375*9832Samw@Sun.COM 	*offset += 2;
376*9832Samw@Sun.COM 	bcopy(&sdbuf[*offset], &ace_cnt, sizeof (uint16_t));
377*9832Samw@Sun.COM 	*offset += 4; /* Pad for Sbz2 */
378*9832Samw@Sun.COM 
379*9832Samw@Sun.COM 	acl = smb_acl_alloc(rev, sz, ace_cnt);
380*9832Samw@Sun.COM 
381*9832Samw@Sun.COM 	return (acl);
382*9832Samw@Sun.COM }
383*9832Samw@Sun.COM 
384*9832Samw@Sun.COM /*
385*9832Samw@Sun.COM  * This method converts Security Descriptor from self relative (flat buffer) to
386*9832Samw@Sun.COM  * absolute (pointer) format.
387*9832Samw@Sun.COM  *
388*9832Samw@Sun.COM  * Returns Win32 error codes.
389*9832Samw@Sun.COM  */
390*9832Samw@Sun.COM static uint32_t
391*9832Samw@Sun.COM srvsvc_sd_set_absolute(uint8_t *sdbuf, smb_sd_t *sd)
392*9832Samw@Sun.COM {
393*9832Samw@Sun.COM 	mslm_security_descriptor_t *msd;
394*9832Samw@Sun.COM 	mslm_ace_t *m_ace;
395*9832Samw@Sun.COM 	struct mslm_sid *m_sid;
396*9832Samw@Sun.COM 	smb_ace_t *ace;
397*9832Samw@Sun.COM 	uint16_t ace_cnt;
398*9832Samw@Sun.COM 	int offset, i, sid_size;
399*9832Samw@Sun.COM 	uint32_t status = ERROR_SUCCESS;
400*9832Samw@Sun.COM 
401*9832Samw@Sun.COM 	if (sdbuf == NULL)
402*9832Samw@Sun.COM 		return (ERROR_INVALID_SECURITY_DESCR);
403*9832Samw@Sun.COM 
404*9832Samw@Sun.COM 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
405*9832Samw@Sun.COM 	msd = (mslm_security_descriptor_t *)sdbuf;
406*9832Samw@Sun.COM 
407*9832Samw@Sun.COM 	sd->sd_revision = msd->revision;
408*9832Samw@Sun.COM 	sd->sd_control = msd->control & (~SE_SELF_RELATIVE);
409*9832Samw@Sun.COM 
410*9832Samw@Sun.COM 	if (msd->offset_owner != 0) {
411*9832Samw@Sun.COM 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
412*9832Samw@Sun.COM 		m_sid = (struct mslm_sid *)&sdbuf[msd->offset_owner];
413*9832Samw@Sun.COM 		sid_size = smb_sid_len((smb_sid_t *)m_sid);
414*9832Samw@Sun.COM 
415*9832Samw@Sun.COM 		if ((sd->sd_owner = malloc(sid_size)) == NULL)
416*9832Samw@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
417*9832Samw@Sun.COM 		bcopy(m_sid, sd->sd_owner, sid_size);
418*9832Samw@Sun.COM 	}
419*9832Samw@Sun.COM 
420*9832Samw@Sun.COM 	if (msd->offset_group != 0) {
421*9832Samw@Sun.COM 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
422*9832Samw@Sun.COM 		m_sid = (struct mslm_sid *)&sdbuf[msd->offset_group];
423*9832Samw@Sun.COM 		sid_size = smb_sid_len((smb_sid_t *)m_sid);
424*9832Samw@Sun.COM 
425*9832Samw@Sun.COM 		if ((sd->sd_group = malloc(sid_size)) == NULL)
426*9832Samw@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
427*9832Samw@Sun.COM 		bcopy(m_sid, sd->sd_group, sid_size);
428*9832Samw@Sun.COM 	}
429*9832Samw@Sun.COM 
430*9832Samw@Sun.COM 	if (msd->offset_sacl != 0) {
431*9832Samw@Sun.COM 		offset = msd->offset_sacl;
432*9832Samw@Sun.COM 		sd->sd_sacl = srvsvc_acl_set_absolute(sdbuf, &offset);
433*9832Samw@Sun.COM 		if (sd->sd_sacl == NULL)
434*9832Samw@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
435*9832Samw@Sun.COM 
436*9832Samw@Sun.COM 		ace = sd->sd_sacl->sl_aces;
437*9832Samw@Sun.COM 		ace_cnt = sd->sd_sacl->sl_acecnt;
438*9832Samw@Sun.COM 
439*9832Samw@Sun.COM 		for (i = 0; i < ace_cnt; i++, ace++) {
440*9832Samw@Sun.COM 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
441*9832Samw@Sun.COM 			m_ace = (mslm_ace_t *)&sdbuf[offset];
442*9832Samw@Sun.COM 			offset += SRVSVC_SID_OFFSET;
443*9832Samw@Sun.COM 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
444*9832Samw@Sun.COM 			m_sid = (struct mslm_sid *)&sdbuf[offset];
445*9832Samw@Sun.COM 
446*9832Samw@Sun.COM 			status = srvsvc_ace_set_absolute(m_ace, m_sid, ace);
447*9832Samw@Sun.COM 			if (status != ERROR_SUCCESS)
448*9832Samw@Sun.COM 				return (status);
449*9832Samw@Sun.COM 			offset += smb_sid_len(ace->se_sid);
450*9832Samw@Sun.COM 		}
451*9832Samw@Sun.COM 	}
452*9832Samw@Sun.COM 
453*9832Samw@Sun.COM 	if (msd->offset_dacl != 0) {
454*9832Samw@Sun.COM 		offset = msd->offset_dacl;
455*9832Samw@Sun.COM 		sd->sd_dacl = srvsvc_acl_set_absolute(sdbuf, &offset);
456*9832Samw@Sun.COM 		if (sd->sd_dacl == NULL)
457*9832Samw@Sun.COM 			return (ERROR_NOT_ENOUGH_MEMORY);
458*9832Samw@Sun.COM 
459*9832Samw@Sun.COM 		ace = sd->sd_dacl->sl_aces;
460*9832Samw@Sun.COM 		ace_cnt = sd->sd_dacl->sl_acecnt;
461*9832Samw@Sun.COM 
462*9832Samw@Sun.COM 		for (i = 0; i < ace_cnt; i++, ace++) {
463*9832Samw@Sun.COM 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
464*9832Samw@Sun.COM 			m_ace = (mslm_ace_t *)&sdbuf[offset];
465*9832Samw@Sun.COM 			offset += SRVSVC_SID_OFFSET;
466*9832Samw@Sun.COM 			/*LINTED E_BAD_PTR_CAST_ALIGN*/
467*9832Samw@Sun.COM 			m_sid = (struct mslm_sid *)&sdbuf[offset];
468*9832Samw@Sun.COM 
469*9832Samw@Sun.COM 			status = srvsvc_ace_set_absolute(m_ace, m_sid, ace);
470*9832Samw@Sun.COM 			if (status != ERROR_SUCCESS)
471*9832Samw@Sun.COM 				return (status);
472*9832Samw@Sun.COM 			offset += smb_sid_len(ace->se_sid);
473*9832Samw@Sun.COM 		}
474*9832Samw@Sun.COM 	}
475*9832Samw@Sun.COM 
476*9832Samw@Sun.COM 	return (status);
477*9832Samw@Sun.COM }
478*9832Samw@Sun.COM 
479*9832Samw@Sun.COM /*
480*9832Samw@Sun.COM  * This method maps NT status codes into Win 32 error codes.
481*9832Samw@Sun.COM  * This method operates on status codes that are related
482*9832Samw@Sun.COM  * to processing of Security Descriptor.
483*9832Samw@Sun.COM  */
484*9832Samw@Sun.COM static uint32_t
485*9832Samw@Sun.COM srvsvc_sd_status_to_error(uint32_t status)
486*9832Samw@Sun.COM {
487*9832Samw@Sun.COM 	int i;
488*9832Samw@Sun.COM 	static struct {
489*9832Samw@Sun.COM 		uint32_t	nt_status;
490*9832Samw@Sun.COM 		uint32_t	err_code;
491*9832Samw@Sun.COM 	} errmap[] = {
492*9832Samw@Sun.COM 		{ NT_STATUS_SUCCESS,		ERROR_SUCCESS },
493*9832Samw@Sun.COM 		{ NT_STATUS_INVALID_ACL,	ERROR_INVALID_ACL },
494*9832Samw@Sun.COM 		{ NT_STATUS_INVALID_SID,	ERROR_INVALID_SID },
495*9832Samw@Sun.COM 		{ NT_STATUS_NONE_MAPPED,	ERROR_NONE_MAPPED }
496*9832Samw@Sun.COM 	};
497*9832Samw@Sun.COM 
498*9832Samw@Sun.COM 	for (i = 0; i < (sizeof (errmap) / sizeof (errmap[0])); ++i) {
499*9832Samw@Sun.COM 		if (status == errmap[i].nt_status)
500*9832Samw@Sun.COM 			return (errmap[i].err_code);
501*9832Samw@Sun.COM 	}
502*9832Samw@Sun.COM 
503*9832Samw@Sun.COM 	return (ERROR_INTERNAL_ERROR);
504*9832Samw@Sun.COM }
505