1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21148c5f43SAlan Wright 
22da6c28aaSamw /*
23148c5f43SAlan Wright  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24*9dc30559SGordon Ross  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
25da6c28aaSamw  */
26da6c28aaSamw 
2755bf511dSas #include <smbsrv/smb_kproto.h>
28da6c28aaSamw 
29a90cf9f2SGordon Ross static void smb_encode_sacl(mbuf_chain_t *, smb_acl_t *);
30a90cf9f2SGordon Ross static void smb_encode_dacl(mbuf_chain_t *, smb_acl_t *);
31a90cf9f2SGordon Ross static smb_acl_t *smb_decode_acl(mbuf_chain_t *, uint32_t);
32da6c28aaSamw 
33da6c28aaSamw /*
34da6c28aaSamw  * smb_nt_transact_query_security_info
35da6c28aaSamw  *
36da6c28aaSamw  * This command allows the client to retrieve the security descriptor
37da6c28aaSamw  * on a file. The result of the call is returned to the client in the
38da6c28aaSamw  * Data part of the transaction response.
39da6c28aaSamw  *
40da6c28aaSamw  * Some clients specify a non-zero maximum data return size (mdrcnt)
41da6c28aaSamw  * for the SD and some specify zero. In either case, if the mdrcnt is
42da6c28aaSamw  * too small we need to return NT_STATUS_BUFFER_TOO_SMALL and a buffer
43da6c28aaSamw  * size hint. The client should then retry with the appropriate buffer
44da6c28aaSamw  * size.
45da6c28aaSamw  *
46da6c28aaSamw  *  Client Parameter Block             Description
47da6c28aaSamw  *  ================================== =================================
48da6c28aaSamw  *
49da6c28aaSamw  *  USHORT Fid;                        FID of target
50da6c28aaSamw  *  USHORT Reserved;                   MBZ
51da6c28aaSamw  *  ULONG secinfo;                     Fields of descriptor to set
52da6c28aaSamw  *
53da6c28aaSamw  *   Data Block Encoding                Description
54da6c28aaSamw  *   ================================== ==================================
55da6c28aaSamw  *
56da6c28aaSamw  *   Data[TotalDataCount]               Security Descriptor information
57da6c28aaSamw  */
58da6c28aaSamw 
597b59d02dSjb smb_sdrc_t
smb_nt_transact_query_security_info(struct smb_request * sr,struct smb_xa * xa)60da6c28aaSamw smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa)
61da6c28aaSamw {
6255bf511dSas 	smb_sd_t sd;
6355bf511dSas 	uint32_t secinfo;
6455bf511dSas 	uint32_t sdlen;
6555bf511dSas 	uint32_t status;
66dc20a302Sas 	smb_error_t err;
67da6c28aaSamw 
683db3f65cSamw 	if (smb_mbc_decodef(&xa->req_param_mb, "w2.l",
69da6c28aaSamw 	    &sr->smb_fid, &secinfo) != 0) {
70dc20a302Sas 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
71faa1795aSjb 		return (SDRC_ERROR);
72da6c28aaSamw 	}
73da6c28aaSamw 
742c2961f8Sjose borrego 	smbsr_lookup_file(sr);
75da6c28aaSamw 	if (sr->fid_ofile == NULL) {
76dc20a302Sas 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
77faa1795aSjb 		return (SDRC_ERROR);
78da6c28aaSamw 	}
79da6c28aaSamw 
80da6c28aaSamw 
81da6c28aaSamw 	if ((sr->fid_ofile->f_node == NULL) ||
82da6c28aaSamw 	    (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) {
83dc20a302Sas 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
8455bf511dSas 		    ERRDOS, ERROR_ACCESS_DENIED);
85faa1795aSjb 		return (SDRC_ERROR);
86da6c28aaSamw 	}
87da6c28aaSamw 
88b89a8333Snatalie li - Sun Microsystems - Irvine United States 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
89b89a8333Snatalie li - Sun Microsystems - Irvine United States 
90da6c28aaSamw 	if (sr->tid_tree->t_acltype != ACE_T) {
91da6c28aaSamw 		/*
92da6c28aaSamw 		 * If target filesystem doesn't support ACE_T acls then
93da6c28aaSamw 		 * don't process SACL
94da6c28aaSamw 		 */
95da6c28aaSamw 		secinfo &= ~SMB_SACL_SECINFO;
96da6c28aaSamw 	}
97da6c28aaSamw 
9855bf511dSas 	status = smb_sd_read(sr, &sd, secinfo);
99da6c28aaSamw 	if (status != NT_STATUS_SUCCESS) {
100dc20a302Sas 		smbsr_error(sr, status, 0, 0);
101faa1795aSjb 		return (SDRC_ERROR);
102da6c28aaSamw 	}
103da6c28aaSamw 
10455bf511dSas 	sdlen = smb_sd_len(&sd, secinfo);
10555bf511dSas 	if (sdlen == 0) {
10655bf511dSas 		smb_sd_term(&sd);
107dc20a302Sas 		smbsr_error(sr, NT_STATUS_INVALID_SECURITY_DESCR, 0, 0);
108faa1795aSjb 		return (SDRC_ERROR);
10955bf511dSas 	}
11055bf511dSas 
11155bf511dSas 	if (sdlen > xa->smb_mdrcnt) {
11255bf511dSas 		/*
11355bf511dSas 		 * The maximum data return count specified by the
11455bf511dSas 		 * client is not big enough to hold the security
11555bf511dSas 		 * descriptor. We have to return an error but we
11655bf511dSas 		 * should provide a buffer size hint for the client.
11755bf511dSas 		 */
1183db3f65cSamw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "l", sdlen);
119dc20a302Sas 		err.status   = NT_STATUS_BUFFER_TOO_SMALL;
120dc20a302Sas 		err.errcls   = ERRDOS;
121dc20a302Sas 		err.errcode  = ERROR_INSUFFICIENT_BUFFER;
122dc20a302Sas 		smbsr_set_error(sr, &err);
12355bf511dSas 		smb_sd_term(&sd);
124faa1795aSjb 		return (SDRC_SUCCESS);
12555bf511dSas 	}
126da6c28aaSamw 
127a90cf9f2SGordon Ross 	smb_encode_sd(&xa->rep_data_mb, &sd, secinfo);
1283db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_param_mb, "l", sdlen);
12955bf511dSas 	smb_sd_term(&sd);
130faa1795aSjb 	return (SDRC_SUCCESS);
131da6c28aaSamw }
132da6c28aaSamw 
133da6c28aaSamw /*
134da6c28aaSamw  * smb_nt_transact_set_security_info
135da6c28aaSamw  *
136da6c28aaSamw  * This command allows the client to change the security descriptor on a
137da6c28aaSamw  * file. All we do here is decode the parameters and the data. The data
138da6c28aaSamw  * is passed directly to smb_nt_set_security_object, with the security
139da6c28aaSamw  * information describing the information to set. There are no response
140da6c28aaSamw  * parameters or data.
141da6c28aaSamw  *
142da6c28aaSamw  *   Client Parameter Block Encoding    Description
143da6c28aaSamw  *   ================================== ==================================
144da6c28aaSamw  *   USHORT Fid;                        FID of target
145da6c28aaSamw  *   USHORT Reserved;                   MBZ
146da6c28aaSamw  *   ULONG SecurityInformation;         Fields of SD that to set
147da6c28aaSamw  *
148da6c28aaSamw  *   Data Block Encoding                Description
149da6c28aaSamw  *   ================================== ==================================
150da6c28aaSamw  *   Data[TotalDataCount]               Security Descriptor information
151da6c28aaSamw  */
1527b59d02dSjb smb_sdrc_t
smb_nt_transact_set_security_info(struct smb_request * sr,struct smb_xa * xa)153da6c28aaSamw smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa)
154da6c28aaSamw {
15555bf511dSas 	smb_sd_t sd;
15655bf511dSas 	uint32_t secinfo;
157da6c28aaSamw 	uint32_t status;
158da6c28aaSamw 
1593db3f65cSamw 	if (smb_mbc_decodef(&xa->req_param_mb, "w2.l",
16055bf511dSas 	    &sr->smb_fid, &secinfo) != 0) {
161dc20a302Sas 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
162faa1795aSjb 		return (SDRC_ERROR);
163da6c28aaSamw 	}
164da6c28aaSamw 
1652c2961f8Sjose borrego 	smbsr_lookup_file(sr);
166da6c28aaSamw 	if (sr->fid_ofile == NULL) {
167dc20a302Sas 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
168faa1795aSjb 		return (SDRC_ERROR);
169da6c28aaSamw 	}
170da6c28aaSamw 
171da6c28aaSamw 	if ((sr->fid_ofile->f_node == NULL) ||
172da6c28aaSamw 	    (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) {
173dc20a302Sas 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 0, 0);
174faa1795aSjb 		return (SDRC_ERROR);
175da6c28aaSamw 	}
176da6c28aaSamw 
177b89a8333Snatalie li - Sun Microsystems - Irvine United States 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
178b89a8333Snatalie li - Sun Microsystems - Irvine United States 
179c8ec8eeaSjose borrego 	if (SMB_TREE_IS_READONLY(sr)) {
180dc20a302Sas 		smbsr_error(sr, NT_STATUS_MEDIA_WRITE_PROTECTED, 0, 0);
181faa1795aSjb 		return (SDRC_ERROR);
182da6c28aaSamw 	}
183da6c28aaSamw 
184da6c28aaSamw 	if (sr->tid_tree->t_acltype != ACE_T) {
185da6c28aaSamw 		/*
186da6c28aaSamw 		 * If target filesystem doesn't support ACE_T acls then
187da6c28aaSamw 		 * don't process SACL
188da6c28aaSamw 		 */
18955bf511dSas 		secinfo &= ~SMB_SACL_SECINFO;
190da6c28aaSamw 	}
191da6c28aaSamw 
19255bf511dSas 	if ((secinfo & SMB_ALL_SECINFO) == 0) {
193da6c28aaSamw 		return (NT_STATUS_SUCCESS);
194da6c28aaSamw 	}
195da6c28aaSamw 
196a90cf9f2SGordon Ross 	status = smb_decode_sd(&xa->req_data_mb, &sd);
19755bf511dSas 	if (status != NT_STATUS_SUCCESS) {
198dc20a302Sas 		smbsr_error(sr, status, 0, 0);
199faa1795aSjb 		return (SDRC_ERROR);
200da6c28aaSamw 	}
201da6c28aaSamw 
20255bf511dSas 	if (((secinfo & SMB_OWNER_SECINFO) && (sd.sd_owner == NULL)) ||
20355bf511dSas 	    ((secinfo & SMB_GROUP_SECINFO) && (sd.sd_group == NULL))) {
204dc20a302Sas 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
205faa1795aSjb 		return (SDRC_ERROR);
20655bf511dSas 	}
207da6c28aaSamw 
2089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (!smb_node_is_system(sr->fid_ofile->f_node))
2099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		status = smb_sd_write(sr, &sd, secinfo);
2109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21155bf511dSas 	smb_sd_term(&sd);
212da6c28aaSamw 	if (status != NT_STATUS_SUCCESS) {
213dc20a302Sas 		smbsr_error(sr, status, 0, 0);
214faa1795aSjb 		return (SDRC_ERROR);
215da6c28aaSamw 	}
216da6c28aaSamw 
217faa1795aSjb 	return (SDRC_SUCCESS);
218da6c28aaSamw }
21955bf511dSas 
22055bf511dSas /*
22155bf511dSas  * smb_encode_sd
22255bf511dSas  *
22355bf511dSas  * Encodes given security descriptor in the reply buffer.
22455bf511dSas  */
225a90cf9f2SGordon Ross void
smb_encode_sd(mbuf_chain_t * mbc,smb_sd_t * sd,uint32_t secinfo)226a90cf9f2SGordon Ross smb_encode_sd(mbuf_chain_t *mbc, smb_sd_t *sd, uint32_t secinfo)
22755bf511dSas {
22855bf511dSas 	uint32_t offset = SMB_SD_HDRSIZE;
22955bf511dSas 
23055bf511dSas 	/* encode header */
231a90cf9f2SGordon Ross 	(void) smb_mbc_encodef(mbc, "b.w",
23255bf511dSas 	    sd->sd_revision, sd->sd_control | SE_SELF_RELATIVE);
23355bf511dSas 
23455bf511dSas 	/* owner offset */
23555bf511dSas 	if (secinfo & SMB_OWNER_SECINFO) {
23655bf511dSas 		ASSERT(sd->sd_owner);
237a90cf9f2SGordon Ross 		(void) smb_mbc_encodef(mbc, "l", offset);
2386537f381Sas 		offset += smb_sid_len(sd->sd_owner);
23955bf511dSas 	} else {
240a90cf9f2SGordon Ross 		(void) smb_mbc_encodef(mbc, "l", 0);
24155bf511dSas 	}
24255bf511dSas 
24355bf511dSas 	/* group offset */
24455bf511dSas 	if (secinfo & SMB_GROUP_SECINFO) {
24555bf511dSas 		ASSERT(sd->sd_group);
246a90cf9f2SGordon Ross 		(void) smb_mbc_encodef(mbc, "l", offset);
2476537f381Sas 		offset += smb_sid_len(sd->sd_group);
24855bf511dSas 	} else {
249a90cf9f2SGordon Ross 		(void) smb_mbc_encodef(mbc, "l", 0);
25055bf511dSas 	}
25155bf511dSas 
25255bf511dSas 	/* SACL offset */
25355bf511dSas 	if ((secinfo & SMB_SACL_SECINFO) && (sd->sd_sacl)) {
254a90cf9f2SGordon Ross 		(void) smb_mbc_encodef(mbc, "l", offset);
25555bf511dSas 		offset += smb_acl_len(sd->sd_sacl);
25655bf511dSas 	} else {
257a90cf9f2SGordon Ross 		(void) smb_mbc_encodef(mbc, "l", 0);
25855bf511dSas 	}
25955bf511dSas 
26055bf511dSas 	/* DACL offset */
26155bf511dSas 	if ((secinfo & SMB_DACL_SECINFO) && (sd->sd_dacl))
262a90cf9f2SGordon Ross 		(void) smb_mbc_encodef(mbc, "l", offset);
26355bf511dSas 	else
264a90cf9f2SGordon Ross 		(void) smb_mbc_encodef(mbc, "l", 0);
26555bf511dSas 
26655bf511dSas 	if (secinfo & SMB_OWNER_SECINFO)
267a90cf9f2SGordon Ross 		smb_encode_sid(mbc, sd->sd_owner);
26855bf511dSas 
26955bf511dSas 	if (secinfo & SMB_GROUP_SECINFO)
270a90cf9f2SGordon Ross 		smb_encode_sid(mbc, sd->sd_group);
27155bf511dSas 
27255bf511dSas 	if (secinfo & SMB_SACL_SECINFO)
273a90cf9f2SGordon Ross 		smb_encode_sacl(mbc, sd->sd_sacl);
27455bf511dSas 
27555bf511dSas 	if (secinfo & SMB_DACL_SECINFO)
276a90cf9f2SGordon Ross 		smb_encode_dacl(mbc, sd->sd_dacl);
27755bf511dSas }
27855bf511dSas 
27955bf511dSas /*
28055bf511dSas  * smb_encode_sid
28155bf511dSas  *
28255bf511dSas  * Encodes given SID in the reply buffer.
28355bf511dSas  */
284b1352070SAlan Wright void
smb_encode_sid(mbuf_chain_t * mbc,smb_sid_t * sid)285a90cf9f2SGordon Ross smb_encode_sid(mbuf_chain_t *mbc, smb_sid_t *sid)
28655bf511dSas {
28755bf511dSas 	int i;
28855bf511dSas 
289a90cf9f2SGordon Ross 	(void) smb_mbc_encodef(mbc, "bb",
2906537f381Sas 	    sid->sid_revision, sid->sid_subauthcnt);
29155bf511dSas 
29255bf511dSas 	for (i = 0; i < NT_SID_AUTH_MAX; i++) {
293a90cf9f2SGordon Ross 		(void) smb_mbc_encodef(mbc, "b",
2946537f381Sas 		    sid->sid_authority[i]);
29555bf511dSas 	}
29655bf511dSas 
2976537f381Sas 	for (i = 0; i < sid->sid_subauthcnt; i++) {
298a90cf9f2SGordon Ross 		(void) smb_mbc_encodef(mbc, "l",
2996537f381Sas 		    sid->sid_subauth[i]);
30055bf511dSas 	}
30155bf511dSas }
30255bf511dSas 
30355bf511dSas /*
30455bf511dSas  * smb_encode_sacl
30555bf511dSas  *
30655bf511dSas  * Encodes given SACL in the reply buffer.
30755bf511dSas  */
30855bf511dSas static void
smb_encode_sacl(mbuf_chain_t * mbc,smb_acl_t * acl)309a90cf9f2SGordon Ross smb_encode_sacl(mbuf_chain_t *mbc, smb_acl_t *acl)
31055bf511dSas {
31155bf511dSas 	smb_ace_t *ace;
31255bf511dSas 	int i;
31355bf511dSas 
31455bf511dSas 	if (acl == NULL)
31555bf511dSas 		return;
31655bf511dSas 
31755bf511dSas 	/* encode header */
318a90cf9f2SGordon Ross 	(void) smb_mbc_encodef(mbc, "b.ww2.", acl->sl_revision,
31955bf511dSas 	    acl->sl_bsize, acl->sl_acecnt);
32055bf511dSas 
32155bf511dSas 	for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) {
322a90cf9f2SGordon Ross 		(void) smb_mbc_encodef(mbc, "bbwl",
32355bf511dSas 		    ace->se_hdr.se_type, ace->se_hdr.se_flags,
32455bf511dSas 		    ace->se_hdr.se_bsize, ace->se_mask);
32555bf511dSas 
326a90cf9f2SGordon Ross 		smb_encode_sid(mbc, ace->se_sid);
32755bf511dSas 	}
32855bf511dSas }
32955bf511dSas 
33055bf511dSas /*
33155bf511dSas  * smb_encode_dacl
33255bf511dSas  *
33355bf511dSas  * Encodes given DACL in the reply buffer.
33455bf511dSas  */
33555bf511dSas static void
smb_encode_dacl(mbuf_chain_t * mbc,smb_acl_t * acl)336a90cf9f2SGordon Ross smb_encode_dacl(mbuf_chain_t *mbc, smb_acl_t *acl)
33755bf511dSas {
33855bf511dSas 	smb_ace_t *ace;
33955bf511dSas 
34055bf511dSas 	if (acl == NULL)
34155bf511dSas 		return;
34255bf511dSas 
34355bf511dSas 	/* encode header */
344a90cf9f2SGordon Ross 	(void) smb_mbc_encodef(mbc, "b.ww2.", acl->sl_revision,
34555bf511dSas 	    acl->sl_bsize, acl->sl_acecnt);
34655bf511dSas 
34755bf511dSas 	ace = list_head(&acl->sl_sorted);
34855bf511dSas 	while (ace) {
349a90cf9f2SGordon Ross 		(void) smb_mbc_encodef(mbc, "bbwl",
35055bf511dSas 		    ace->se_hdr.se_type, ace->se_hdr.se_flags,
35155bf511dSas 		    ace->se_hdr.se_bsize, ace->se_mask);
35255bf511dSas 
353a90cf9f2SGordon Ross 		smb_encode_sid(mbc, ace->se_sid);
35455bf511dSas 		ace = list_next(&acl->sl_sorted, ace);
35555bf511dSas 	}
35655bf511dSas }
35755bf511dSas 
35855bf511dSas /*
35955bf511dSas  * smb_decode_sd
36055bf511dSas  *
36155bf511dSas  * Decodes the security descriptor in the request buffer
36255bf511dSas  * and set the fields of 'sd' appropraitely. Upon successful
36355bf511dSas  * return, caller must free allocated memories by calling
36455bf511dSas  * smb_sd_term().
36555bf511dSas  */
36655bf511dSas uint32_t
smb_decode_sd(mbuf_chain_t * mbc,smb_sd_t * sd)367a90cf9f2SGordon Ross smb_decode_sd(mbuf_chain_t *mbc, smb_sd_t *sd)
36855bf511dSas {
36955bf511dSas 	struct mbuf_chain sdbuf;
37055bf511dSas 	uint32_t owner_offs;
37155bf511dSas 	uint32_t group_offs;
37255bf511dSas 	uint32_t sacl_offs;
37355bf511dSas 	uint32_t dacl_offs;
374*9dc30559SGordon Ross 	int rc;
37555bf511dSas 
37655bf511dSas 	smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION);
37755bf511dSas 
378a90cf9f2SGordon Ross 	(void) MBC_SHADOW_CHAIN(&sdbuf, mbc,
379a90cf9f2SGordon Ross 	    mbc->chain_offset,
380a90cf9f2SGordon Ross 	    mbc->max_bytes - mbc->chain_offset);
38155bf511dSas 
382*9dc30559SGordon Ross 	rc = smb_mbc_decodef(&sdbuf, "b.wllll",
38355bf511dSas 	    &sd->sd_revision, &sd->sd_control,
384*9dc30559SGordon Ross 	    &owner_offs, &group_offs, &sacl_offs, &dacl_offs);
38555bf511dSas 
386*9dc30559SGordon Ross 	/* Prevent disallowed flags in smb_sd_term. */
38755bf511dSas 	sd->sd_control &= ~SE_SELF_RELATIVE;
388*9dc30559SGordon Ross 	if (rc != 0)
389*9dc30559SGordon Ross 		goto decode_error;
39055bf511dSas 
39155bf511dSas 	if (owner_offs != 0) {
39255bf511dSas 		if (owner_offs < SMB_SD_HDRSIZE)
39355bf511dSas 			goto decode_error;
39455bf511dSas 
395a90cf9f2SGordon Ross 		sd->sd_owner = smb_decode_sid(mbc, owner_offs);
39655bf511dSas 		if (sd->sd_owner == NULL)
39755bf511dSas 			goto decode_error;
39855bf511dSas 	}
39955bf511dSas 
40055bf511dSas 	if (group_offs != 0) {
40155bf511dSas 		if (group_offs < SMB_SD_HDRSIZE)
40255bf511dSas 			goto decode_error;
40355bf511dSas 
404a90cf9f2SGordon Ross 		sd->sd_group = smb_decode_sid(mbc, group_offs);
40555bf511dSas 		if (sd->sd_group == NULL)
40655bf511dSas 			goto decode_error;
40755bf511dSas 	}
40855bf511dSas 
40955bf511dSas 	if (sacl_offs != 0) {
41055bf511dSas 		if ((sd->sd_control & SE_SACL_PRESENT) == 0)
41155bf511dSas 			goto decode_error;
41255bf511dSas 
41355bf511dSas 		if (sacl_offs < SMB_SD_HDRSIZE)
41455bf511dSas 			goto decode_error;
41555bf511dSas 
416a90cf9f2SGordon Ross 		sd->sd_sacl = smb_decode_acl(mbc, sacl_offs);
41755bf511dSas 		if (sd->sd_sacl == NULL)
41855bf511dSas 			goto decode_error;
41955bf511dSas 	}
42055bf511dSas 
42155bf511dSas 	if (dacl_offs != 0) {
42255bf511dSas 		if ((sd->sd_control & SE_DACL_PRESENT) == 0)
42355bf511dSas 			goto decode_error;
42455bf511dSas 
42555bf511dSas 		if (dacl_offs < SMB_SD_HDRSIZE)
42655bf511dSas 			goto decode_error;
42755bf511dSas 
428a90cf9f2SGordon Ross 		sd->sd_dacl = smb_decode_acl(mbc, dacl_offs);
42955bf511dSas 		if (sd->sd_dacl == NULL)
43055bf511dSas 			goto decode_error;
43155bf511dSas 	}
43255bf511dSas 
43355bf511dSas 	return (NT_STATUS_SUCCESS);
43455bf511dSas 
43555bf511dSas decode_error:
43655bf511dSas 	smb_sd_term(sd);
43755bf511dSas 	return (NT_STATUS_INVALID_SECURITY_DESCR);
43855bf511dSas }
43955bf511dSas 
44055bf511dSas /*
44155bf511dSas  * smb_decode_sid
44255bf511dSas  *
44355bf511dSas  * Allocates memory and decodes the SID in the request buffer
44455bf511dSas  * Upon successful return, caller must free the allocated memory
4456537f381Sas  * by calling smb_sid_free()
44655bf511dSas  */
4479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_sid_t *
smb_decode_sid(mbuf_chain_t * mbc,uint32_t offset)448a90cf9f2SGordon Ross smb_decode_sid(mbuf_chain_t *mbc, uint32_t offset)
44955bf511dSas {
45055bf511dSas 	uint8_t revision;
45155bf511dSas 	uint8_t subauth_cnt;
45255bf511dSas 	struct mbuf_chain sidbuf;
4536537f381Sas 	smb_sid_t *sid;
45455bf511dSas 	int sidlen;
45555bf511dSas 	int bytes_left;
45655bf511dSas 	int i;
45755bf511dSas 
458a90cf9f2SGordon Ross 	offset += mbc->chain_offset;
459a90cf9f2SGordon Ross 	bytes_left = mbc->max_bytes - offset;
460a90cf9f2SGordon Ross 	if (bytes_left < (int)sizeof (smb_sid_t))
46155bf511dSas 		return (NULL);
46255bf511dSas 
463a90cf9f2SGordon Ross 	if (MBC_SHADOW_CHAIN(&sidbuf, mbc, offset, bytes_left) != 0)
464a90cf9f2SGordon Ross 		return (NULL);
46555bf511dSas 
4663db3f65cSamw 	if (smb_mbc_decodef(&sidbuf, "bb", &revision, &subauth_cnt))
46755bf511dSas 		return (NULL);
46855bf511dSas 
4696537f381Sas 	sidlen = sizeof (smb_sid_t) - sizeof (uint32_t) +
47055bf511dSas 	    (subauth_cnt * sizeof (uint32_t));
4716537f381Sas 	sid = kmem_alloc(sidlen, KM_SLEEP);
47255bf511dSas 
4736537f381Sas 	sid->sid_revision = revision;
4746537f381Sas 	sid->sid_subauthcnt = subauth_cnt;
47555bf511dSas 
47655bf511dSas 	for (i = 0; i < NT_SID_AUTH_MAX; i++) {
4773db3f65cSamw 		if (smb_mbc_decodef(&sidbuf, "b", &sid->sid_authority[i]))
47855bf511dSas 			goto decode_err;
47955bf511dSas 	}
48055bf511dSas 
4816537f381Sas 	for (i = 0; i < sid->sid_subauthcnt; i++) {
4823db3f65cSamw 		if (smb_mbc_decodef(&sidbuf, "l", &sid->sid_subauth[i]))
48355bf511dSas 			goto decode_err;
48455bf511dSas 	}
48555bf511dSas 
48655bf511dSas 	return (sid);
48755bf511dSas 
48855bf511dSas decode_err:
4896537f381Sas 	kmem_free(sid, sidlen);
49055bf511dSas 	return (NULL);
49155bf511dSas }
49255bf511dSas 
49355bf511dSas /*
49455bf511dSas  * smb_decode_acl
49555bf511dSas  *
49655bf511dSas  * Allocates memory and decodes the ACL in the request buffer
49755bf511dSas  * Upon successful return, caller must free the allocated memory
49855bf511dSas  * by calling smb_acl_free().
49955bf511dSas  */
50055bf511dSas static smb_acl_t *
smb_decode_acl(mbuf_chain_t * mbc,uint32_t offset)501a90cf9f2SGordon Ross smb_decode_acl(mbuf_chain_t *mbc, uint32_t offset)
50255bf511dSas {
50355bf511dSas 	struct mbuf_chain aclbuf;
50455bf511dSas 	smb_acl_t *acl;
50555bf511dSas 	smb_ace_t *ace;
50655bf511dSas 	uint8_t revision;
50755bf511dSas 	uint16_t size;
50855bf511dSas 	uint16_t acecnt;
50955bf511dSas 	int bytes_left;
51055bf511dSas 	uint32_t sid_offs = offset;
51155bf511dSas 	int sidlen;
51255bf511dSas 	int i;
51355bf511dSas 
514a90cf9f2SGordon Ross 	offset += mbc->chain_offset;
515a90cf9f2SGordon Ross 	bytes_left = mbc->max_bytes - offset;
51655bf511dSas 	if (bytes_left < SMB_ACL_HDRSIZE)
51755bf511dSas 		return (NULL);
51855bf511dSas 
519a90cf9f2SGordon Ross 	if (MBC_SHADOW_CHAIN(&aclbuf, mbc, offset, bytes_left) != 0)
520a90cf9f2SGordon Ross 		return (NULL);
52155bf511dSas 
5223db3f65cSamw 	if (smb_mbc_decodef(&aclbuf, "b.ww2.", &revision, &size, &acecnt))
52355bf511dSas 		return (NULL);
52455bf511dSas 
52555bf511dSas 	if (size == 0)
52655bf511dSas 		return (NULL);
52755bf511dSas 
52855bf511dSas 	acl = smb_acl_alloc(revision, size, acecnt);
52955bf511dSas 
53055bf511dSas 	sid_offs += SMB_ACL_HDRSIZE;
53155bf511dSas 	for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) {
5323db3f65cSamw 		if (smb_mbc_decodef(&aclbuf, "bbwl",
53355bf511dSas 		    &ace->se_hdr.se_type, &ace->se_hdr.se_flags,
53455bf511dSas 		    &ace->se_hdr.se_bsize, &ace->se_mask))
53555bf511dSas 			goto decode_error;
53655bf511dSas 
53755bf511dSas 		sid_offs += SMB_ACE_HDRSIZE + sizeof (ace->se_mask);
538a90cf9f2SGordon Ross 		ace->se_sid = smb_decode_sid(mbc, sid_offs);
53955bf511dSas 		if (ace->se_sid == NULL)
54055bf511dSas 			goto decode_error;
541b89a8333Snatalie li - Sun Microsystems - Irvine United States 		/* This is SID length plus any paddings between ACEs */
542b89a8333Snatalie li - Sun Microsystems - Irvine United States 		sidlen = ace->se_hdr.se_bsize -
543b89a8333Snatalie li - Sun Microsystems - Irvine United States 		    (SMB_ACE_HDRSIZE + sizeof (ace->se_mask));
54455bf511dSas 		aclbuf.chain_offset += sidlen;
54555bf511dSas 		sid_offs += sidlen;
54655bf511dSas 	}
54755bf511dSas 
54855bf511dSas 	return (acl);
54955bf511dSas 
55055bf511dSas decode_error:
55155bf511dSas 	smb_acl_free(acl);
55255bf511dSas 	return (NULL);
55355bf511dSas }
554