15331Samw /*
25331Samw * CDDL HEADER START
35331Samw *
45331Samw * The contents of this file are subject to the terms of the
55331Samw * Common Development and Distribution License (the "License").
65331Samw * You may not use this file except in compliance with the License.
75331Samw *
85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw * or http://www.opensolaris.org/os/licensing.
105331Samw * See the License for the specific language governing permissions
115331Samw * and limitations under the License.
125331Samw *
135331Samw * When distributing Covered Code, include this CDDL HEADER in each
145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw * If applicable, add the following below this CDDL HEADER, with the
165331Samw * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw *
195331Samw * CDDL HEADER END
205331Samw */
21*12508Samw@Sun.COM
225331Samw /*
23*12508Samw@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
245331Samw */
255331Samw
265521Sas200622 #include <smbsrv/smb_kproto.h>
275331Samw
285521Sas200622 static void smb_encode_sd(struct smb_xa *, smb_sd_t *, uint32_t);
295521Sas200622 static void smb_encode_sacl(struct smb_xa *, smb_acl_t *);
305521Sas200622 static void smb_encode_dacl(struct smb_xa *, smb_acl_t *);
315521Sas200622 static smb_acl_t *smb_decode_acl(struct smb_xa *, uint32_t);
325331Samw
335331Samw /*
345331Samw * smb_nt_transact_query_security_info
355331Samw *
365331Samw * This command allows the client to retrieve the security descriptor
375331Samw * on a file. The result of the call is returned to the client in the
385331Samw * Data part of the transaction response.
395331Samw *
405331Samw * Some clients specify a non-zero maximum data return size (mdrcnt)
415331Samw * for the SD and some specify zero. In either case, if the mdrcnt is
425331Samw * too small we need to return NT_STATUS_BUFFER_TOO_SMALL and a buffer
435331Samw * size hint. The client should then retry with the appropriate buffer
445331Samw * size.
455331Samw *
465331Samw * Client Parameter Block Description
475331Samw * ================================== =================================
485331Samw *
495331Samw * USHORT Fid; FID of target
505331Samw * USHORT Reserved; MBZ
515331Samw * ULONG secinfo; Fields of descriptor to set
525331Samw *
535331Samw * Data Block Encoding Description
545331Samw * ================================== ==================================
555331Samw *
565331Samw * Data[TotalDataCount] Security Descriptor information
575331Samw */
585331Samw
596030Sjb150015 smb_sdrc_t
smb_nt_transact_query_security_info(struct smb_request * sr,struct smb_xa * xa)605331Samw smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa)
615331Samw {
625521Sas200622 smb_sd_t sd;
635521Sas200622 uint32_t secinfo;
645521Sas200622 uint32_t sdlen;
655521Sas200622 uint32_t status;
665772Sas200622 smb_error_t err;
675331Samw
687052Samw if (smb_mbc_decodef(&xa->req_param_mb, "w2.l",
695331Samw &sr->smb_fid, &secinfo) != 0) {
705772Sas200622 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
716139Sjb150015 return (SDRC_ERROR);
725331Samw }
735331Samw
748934SJose.Borrego@Sun.COM smbsr_lookup_file(sr);
755331Samw if (sr->fid_ofile == NULL) {
765772Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
776139Sjb150015 return (SDRC_ERROR);
785331Samw }
795331Samw
805331Samw
815331Samw if ((sr->fid_ofile->f_node == NULL) ||
825331Samw (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) {
835772Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
845521Sas200622 ERRDOS, ERROR_ACCESS_DENIED);
856139Sjb150015 return (SDRC_ERROR);
865331Samw }
875331Samw
887961SNatalie.Li@Sun.COM sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
897961SNatalie.Li@Sun.COM
905331Samw if (sr->tid_tree->t_acltype != ACE_T) {
915331Samw /*
925331Samw * If target filesystem doesn't support ACE_T acls then
935331Samw * don't process SACL
945331Samw */
955331Samw secinfo &= ~SMB_SACL_SECINFO;
965331Samw }
975331Samw
985521Sas200622 status = smb_sd_read(sr, &sd, secinfo);
995331Samw if (status != NT_STATUS_SUCCESS) {
1005772Sas200622 smbsr_error(sr, status, 0, 0);
1016139Sjb150015 return (SDRC_ERROR);
1025331Samw }
1035331Samw
1045521Sas200622 sdlen = smb_sd_len(&sd, secinfo);
1055521Sas200622 if (sdlen == 0) {
1065521Sas200622 smb_sd_term(&sd);
1075772Sas200622 smbsr_error(sr, NT_STATUS_INVALID_SECURITY_DESCR, 0, 0);
1086139Sjb150015 return (SDRC_ERROR);
1095521Sas200622 }
1105331Samw
1115521Sas200622 if (sdlen > xa->smb_mdrcnt) {
1125521Sas200622 /*
1135521Sas200622 * The maximum data return count specified by the
1145521Sas200622 * client is not big enough to hold the security
1155521Sas200622 * descriptor. We have to return an error but we
1165521Sas200622 * should provide a buffer size hint for the client.
1175521Sas200622 */
1187052Samw (void) smb_mbc_encodef(&xa->rep_param_mb, "l", sdlen);
1195772Sas200622 err.status = NT_STATUS_BUFFER_TOO_SMALL;
1205772Sas200622 err.errcls = ERRDOS;
1215772Sas200622 err.errcode = ERROR_INSUFFICIENT_BUFFER;
1225772Sas200622 smbsr_set_error(sr, &err);
1235521Sas200622 smb_sd_term(&sd);
1246139Sjb150015 return (SDRC_SUCCESS);
1255521Sas200622 }
1265521Sas200622
1275521Sas200622 smb_encode_sd(xa, &sd, secinfo);
1287052Samw (void) smb_mbc_encodef(&xa->rep_param_mb, "l", sdlen);
1295521Sas200622 smb_sd_term(&sd);
1306139Sjb150015 return (SDRC_SUCCESS);
1315331Samw }
1325331Samw
1335331Samw /*
1345331Samw * smb_nt_transact_set_security_info
1355331Samw *
1365331Samw * This command allows the client to change the security descriptor on a
1375331Samw * file. All we do here is decode the parameters and the data. The data
1385331Samw * is passed directly to smb_nt_set_security_object, with the security
1395331Samw * information describing the information to set. There are no response
1405331Samw * parameters or data.
1415331Samw *
1425331Samw * Client Parameter Block Encoding Description
1435331Samw * ================================== ==================================
1445331Samw * USHORT Fid; FID of target
1455331Samw * USHORT Reserved; MBZ
1465331Samw * ULONG SecurityInformation; Fields of SD that to set
1475331Samw *
1485331Samw * Data Block Encoding Description
1495331Samw * ================================== ==================================
1505331Samw * Data[TotalDataCount] Security Descriptor information
1515331Samw */
1526030Sjb150015 smb_sdrc_t
smb_nt_transact_set_security_info(struct smb_request * sr,struct smb_xa * xa)1535331Samw smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa)
1545331Samw {
1555521Sas200622 smb_sd_t sd;
1565521Sas200622 uint32_t secinfo;
1575331Samw uint32_t status;
1585331Samw
1597052Samw if (smb_mbc_decodef(&xa->req_param_mb, "w2.l",
1605521Sas200622 &sr->smb_fid, &secinfo) != 0) {
1615772Sas200622 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
1626139Sjb150015 return (SDRC_ERROR);
1635331Samw }
1645331Samw
1658934SJose.Borrego@Sun.COM smbsr_lookup_file(sr);
1665331Samw if (sr->fid_ofile == NULL) {
1675772Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
1686139Sjb150015 return (SDRC_ERROR);
1695331Samw }
1705331Samw
1715331Samw if ((sr->fid_ofile->f_node == NULL) ||
1725331Samw (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) {
1735772Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 0, 0);
1746139Sjb150015 return (SDRC_ERROR);
1755331Samw }
1765331Samw
1777961SNatalie.Li@Sun.COM sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
1787961SNatalie.Li@Sun.COM
1797348SJose.Borrego@Sun.COM if (SMB_TREE_IS_READONLY(sr)) {
1805772Sas200622 smbsr_error(sr, NT_STATUS_MEDIA_WRITE_PROTECTED, 0, 0);
1816139Sjb150015 return (SDRC_ERROR);
1825331Samw }
1835331Samw
1845331Samw if (sr->tid_tree->t_acltype != ACE_T) {
1855331Samw /*
1865331Samw * If target filesystem doesn't support ACE_T acls then
1875331Samw * don't process SACL
1885331Samw */
1895521Sas200622 secinfo &= ~SMB_SACL_SECINFO;
1905331Samw }
1915331Samw
1925521Sas200622 if ((secinfo & SMB_ALL_SECINFO) == 0) {
1935331Samw return (NT_STATUS_SUCCESS);
1945331Samw }
1955331Samw
1965521Sas200622 status = smb_decode_sd(xa, &sd);
1975521Sas200622 if (status != NT_STATUS_SUCCESS) {
1985772Sas200622 smbsr_error(sr, status, 0, 0);
1996139Sjb150015 return (SDRC_ERROR);
2005331Samw }
2015331Samw
2025521Sas200622 if (((secinfo & SMB_OWNER_SECINFO) && (sd.sd_owner == NULL)) ||
2035521Sas200622 ((secinfo & SMB_GROUP_SECINFO) && (sd.sd_group == NULL))) {
2045772Sas200622 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
2056139Sjb150015 return (SDRC_ERROR);
2065521Sas200622 }
2075331Samw
20811963SAfshin.Ardakani@Sun.COM if (!smb_node_is_system(sr->fid_ofile->f_node))
20911963SAfshin.Ardakani@Sun.COM status = smb_sd_write(sr, &sd, secinfo);
21011963SAfshin.Ardakani@Sun.COM
2115521Sas200622 smb_sd_term(&sd);
2125331Samw if (status != NT_STATUS_SUCCESS) {
2135772Sas200622 smbsr_error(sr, status, 0, 0);
2146139Sjb150015 return (SDRC_ERROR);
2155331Samw }
2165331Samw
2176139Sjb150015 return (SDRC_SUCCESS);
2185331Samw }
2195521Sas200622
2205521Sas200622 /*
2215521Sas200622 * smb_encode_sd
2225521Sas200622 *
2235521Sas200622 * Encodes given security descriptor in the reply buffer.
2245521Sas200622 */
2255521Sas200622 static void
smb_encode_sd(struct smb_xa * xa,smb_sd_t * sd,uint32_t secinfo)2265521Sas200622 smb_encode_sd(struct smb_xa *xa, smb_sd_t *sd, uint32_t secinfo)
2275521Sas200622 {
2285521Sas200622 uint32_t offset = SMB_SD_HDRSIZE;
2295521Sas200622
2305521Sas200622 /* encode header */
2317052Samw (void) smb_mbc_encodef(&xa->rep_data_mb, "b.w",
2325521Sas200622 sd->sd_revision, sd->sd_control | SE_SELF_RELATIVE);
2335521Sas200622
2345521Sas200622 /* owner offset */
2355521Sas200622 if (secinfo & SMB_OWNER_SECINFO) {
2365521Sas200622 ASSERT(sd->sd_owner);
2377052Samw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", offset);
2386432Sas200622 offset += smb_sid_len(sd->sd_owner);
2395521Sas200622 } else {
2407052Samw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0);
2415521Sas200622 }
2425521Sas200622
2435521Sas200622 /* group offset */
2445521Sas200622 if (secinfo & SMB_GROUP_SECINFO) {
2455521Sas200622 ASSERT(sd->sd_group);
2467052Samw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", offset);
2476432Sas200622 offset += smb_sid_len(sd->sd_group);
2485521Sas200622 } else {
2497052Samw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0);
2505521Sas200622 }
2515521Sas200622
2525521Sas200622 /* SACL offset */
2535521Sas200622 if ((secinfo & SMB_SACL_SECINFO) && (sd->sd_sacl)) {
2547052Samw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", offset);
2555521Sas200622 offset += smb_acl_len(sd->sd_sacl);
2565521Sas200622 } else {
2577052Samw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0);
2585521Sas200622 }
2595521Sas200622
2605521Sas200622 /* DACL offset */
2615521Sas200622 if ((secinfo & SMB_DACL_SECINFO) && (sd->sd_dacl))
2627052Samw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", offset);
2635521Sas200622 else
2647052Samw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0);
2655521Sas200622
2665521Sas200622 if (secinfo & SMB_OWNER_SECINFO)
2675521Sas200622 smb_encode_sid(xa, sd->sd_owner);
2685521Sas200622
2695521Sas200622 if (secinfo & SMB_GROUP_SECINFO)
2705521Sas200622 smb_encode_sid(xa, sd->sd_group);
2715521Sas200622
2725521Sas200622 if (secinfo & SMB_SACL_SECINFO)
2735521Sas200622 smb_encode_sacl(xa, sd->sd_sacl);
2745521Sas200622
2755521Sas200622 if (secinfo & SMB_DACL_SECINFO)
2765521Sas200622 smb_encode_dacl(xa, sd->sd_dacl);
2775521Sas200622 }
2785521Sas200622
2795521Sas200622 /*
2805521Sas200622 * smb_encode_sid
2815521Sas200622 *
2825521Sas200622 * Encodes given SID in the reply buffer.
2835521Sas200622 */
2849914Samw@Sun.COM void
smb_encode_sid(struct smb_xa * xa,smb_sid_t * sid)2856432Sas200622 smb_encode_sid(struct smb_xa *xa, smb_sid_t *sid)
2865521Sas200622 {
2875521Sas200622 int i;
2885521Sas200622
2897052Samw (void) smb_mbc_encodef(&xa->rep_data_mb, "bb",
2906432Sas200622 sid->sid_revision, sid->sid_subauthcnt);
2915521Sas200622
2925521Sas200622 for (i = 0; i < NT_SID_AUTH_MAX; i++) {
2937052Samw (void) smb_mbc_encodef(&xa->rep_data_mb, "b",
2946432Sas200622 sid->sid_authority[i]);
2955521Sas200622 }
2965521Sas200622
2976432Sas200622 for (i = 0; i < sid->sid_subauthcnt; i++) {
2987052Samw (void) smb_mbc_encodef(&xa->rep_data_mb, "l",
2996432Sas200622 sid->sid_subauth[i]);
3005521Sas200622 }
3015521Sas200622 }
3025521Sas200622
3035521Sas200622 /*
3045521Sas200622 * smb_encode_sacl
3055521Sas200622 *
3065521Sas200622 * Encodes given SACL in the reply buffer.
3075521Sas200622 */
3085521Sas200622 static void
smb_encode_sacl(struct smb_xa * xa,smb_acl_t * acl)3095521Sas200622 smb_encode_sacl(struct smb_xa *xa, smb_acl_t *acl)
3105521Sas200622 {
3115521Sas200622 smb_ace_t *ace;
3125521Sas200622 int i;
3135521Sas200622
3145521Sas200622 if (acl == NULL)
3155521Sas200622 return;
3165521Sas200622
3175521Sas200622 /* encode header */
3187052Samw (void) smb_mbc_encodef(&xa->rep_data_mb, "b.ww2.", acl->sl_revision,
3195521Sas200622 acl->sl_bsize, acl->sl_acecnt);
3205521Sas200622
3215521Sas200622 for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) {
3227052Samw (void) smb_mbc_encodef(&xa->rep_data_mb, "bbwl",
3235521Sas200622 ace->se_hdr.se_type, ace->se_hdr.se_flags,
3245521Sas200622 ace->se_hdr.se_bsize, ace->se_mask);
3255521Sas200622
3265521Sas200622 smb_encode_sid(xa, ace->se_sid);
3275521Sas200622 }
3285521Sas200622 }
3295521Sas200622
3305521Sas200622 /*
3315521Sas200622 * smb_encode_dacl
3325521Sas200622 *
3335521Sas200622 * Encodes given DACL in the reply buffer.
3345521Sas200622 */
3355521Sas200622 static void
smb_encode_dacl(struct smb_xa * xa,smb_acl_t * acl)3365521Sas200622 smb_encode_dacl(struct smb_xa *xa, smb_acl_t *acl)
3375521Sas200622 {
3385521Sas200622 smb_ace_t *ace;
3395521Sas200622
3405521Sas200622 if (acl == NULL)
3415521Sas200622 return;
3425521Sas200622
3435521Sas200622 /* encode header */
3447052Samw (void) smb_mbc_encodef(&xa->rep_data_mb, "b.ww2.", acl->sl_revision,
3455521Sas200622 acl->sl_bsize, acl->sl_acecnt);
3465521Sas200622
3475521Sas200622 ace = list_head(&acl->sl_sorted);
3485521Sas200622 while (ace) {
3497052Samw (void) smb_mbc_encodef(&xa->rep_data_mb, "bbwl",
3505521Sas200622 ace->se_hdr.se_type, ace->se_hdr.se_flags,
3515521Sas200622 ace->se_hdr.se_bsize, ace->se_mask);
3525521Sas200622
3535521Sas200622 smb_encode_sid(xa, ace->se_sid);
3545521Sas200622 ace = list_next(&acl->sl_sorted, ace);
3555521Sas200622 }
3565521Sas200622 }
3575521Sas200622
3585521Sas200622 /*
3595521Sas200622 * smb_decode_sd
3605521Sas200622 *
3615521Sas200622 * Decodes the security descriptor in the request buffer
3625521Sas200622 * and set the fields of 'sd' appropraitely. Upon successful
3635521Sas200622 * return, caller must free allocated memories by calling
3645521Sas200622 * smb_sd_term().
3655521Sas200622 */
3665521Sas200622 uint32_t
smb_decode_sd(struct smb_xa * xa,smb_sd_t * sd)3675521Sas200622 smb_decode_sd(struct smb_xa *xa, smb_sd_t *sd)
3685521Sas200622 {
3695521Sas200622 struct mbuf_chain sdbuf;
3705521Sas200622 uint32_t owner_offs;
3715521Sas200622 uint32_t group_offs;
3725521Sas200622 uint32_t sacl_offs;
3735521Sas200622 uint32_t dacl_offs;
3745521Sas200622
3755521Sas200622 smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION);
3765521Sas200622
3775521Sas200622 (void) MBC_SHADOW_CHAIN(&sdbuf, &xa->req_data_mb,
3785521Sas200622 xa->req_data_mb.chain_offset,
3795521Sas200622 xa->req_data_mb.max_bytes - xa->req_data_mb.chain_offset);
3805521Sas200622
3817052Samw if (smb_mbc_decodef(&sdbuf, "b.wllll",
3825521Sas200622 &sd->sd_revision, &sd->sd_control,
3835521Sas200622 &owner_offs, &group_offs, &sacl_offs, &dacl_offs))
3845521Sas200622 goto decode_error;
3855521Sas200622
3865521Sas200622 sd->sd_control &= ~SE_SELF_RELATIVE;
3875521Sas200622
3885521Sas200622 if (owner_offs != 0) {
3895521Sas200622 if (owner_offs < SMB_SD_HDRSIZE)
3905521Sas200622 goto decode_error;
3915521Sas200622
3925521Sas200622 sd->sd_owner = smb_decode_sid(xa, owner_offs);
3935521Sas200622 if (sd->sd_owner == NULL)
3945521Sas200622 goto decode_error;
3955521Sas200622 }
3965521Sas200622
3975521Sas200622 if (group_offs != 0) {
3985521Sas200622 if (group_offs < SMB_SD_HDRSIZE)
3995521Sas200622 goto decode_error;
4005521Sas200622
4015521Sas200622 sd->sd_group = smb_decode_sid(xa, group_offs);
4025521Sas200622 if (sd->sd_group == NULL)
4035521Sas200622 goto decode_error;
4045521Sas200622 }
4055521Sas200622
4065521Sas200622 if (sacl_offs != 0) {
4075521Sas200622 if ((sd->sd_control & SE_SACL_PRESENT) == 0)
4085521Sas200622 goto decode_error;
4095521Sas200622
4105521Sas200622 if (sacl_offs < SMB_SD_HDRSIZE)
4115521Sas200622 goto decode_error;
4125521Sas200622
4135521Sas200622 sd->sd_sacl = smb_decode_acl(xa, sacl_offs);
4145521Sas200622 if (sd->sd_sacl == NULL)
4155521Sas200622 goto decode_error;
4165521Sas200622 }
4175521Sas200622
4185521Sas200622 if (dacl_offs != 0) {
4195521Sas200622 if ((sd->sd_control & SE_DACL_PRESENT) == 0)
4205521Sas200622 goto decode_error;
4215521Sas200622
4225521Sas200622 if (dacl_offs < SMB_SD_HDRSIZE)
4235521Sas200622 goto decode_error;
4245521Sas200622
4255521Sas200622 sd->sd_dacl = smb_decode_acl(xa, dacl_offs);
4265521Sas200622 if (sd->sd_dacl == NULL)
4275521Sas200622 goto decode_error;
4285521Sas200622 }
4295521Sas200622
4305521Sas200622 return (NT_STATUS_SUCCESS);
4315521Sas200622
4325521Sas200622 decode_error:
4335521Sas200622 smb_sd_term(sd);
4345521Sas200622 return (NT_STATUS_INVALID_SECURITY_DESCR);
4355521Sas200622 }
4365521Sas200622
4375521Sas200622 /*
4385521Sas200622 * smb_decode_sid
4395521Sas200622 *
4405521Sas200622 * Allocates memory and decodes the SID in the request buffer
4415521Sas200622 * Upon successful return, caller must free the allocated memory
4426432Sas200622 * by calling smb_sid_free()
4435521Sas200622 */
44411963SAfshin.Ardakani@Sun.COM smb_sid_t *
smb_decode_sid(struct smb_xa * xa,uint32_t offset)4455521Sas200622 smb_decode_sid(struct smb_xa *xa, uint32_t offset)
4465521Sas200622 {
4475521Sas200622 uint8_t revision;
4485521Sas200622 uint8_t subauth_cnt;
4495521Sas200622 struct mbuf_chain sidbuf;
4506432Sas200622 smb_sid_t *sid;
4515521Sas200622 int sidlen;
4525521Sas200622 int bytes_left;
4535521Sas200622 int i;
4545521Sas200622
4555521Sas200622 offset += xa->req_data_mb.chain_offset;
4565521Sas200622 bytes_left = xa->req_data_mb.max_bytes - offset;
4576432Sas200622 if (bytes_left < sizeof (smb_sid_t))
4585521Sas200622 return (NULL);
4595521Sas200622
4605521Sas200622 (void) MBC_SHADOW_CHAIN(&sidbuf, &xa->req_data_mb, offset, bytes_left);
4615521Sas200622
4627052Samw if (smb_mbc_decodef(&sidbuf, "bb", &revision, &subauth_cnt))
4635521Sas200622 return (NULL);
4645521Sas200622
4656432Sas200622 sidlen = sizeof (smb_sid_t) - sizeof (uint32_t) +
4665521Sas200622 (subauth_cnt * sizeof (uint32_t));
4676432Sas200622 sid = kmem_alloc(sidlen, KM_SLEEP);
4685521Sas200622
4696432Sas200622 sid->sid_revision = revision;
4706432Sas200622 sid->sid_subauthcnt = subauth_cnt;
4715521Sas200622
4725521Sas200622 for (i = 0; i < NT_SID_AUTH_MAX; i++) {
4737052Samw if (smb_mbc_decodef(&sidbuf, "b", &sid->sid_authority[i]))
4745521Sas200622 goto decode_err;
4755521Sas200622 }
4765521Sas200622
4776432Sas200622 for (i = 0; i < sid->sid_subauthcnt; i++) {
4787052Samw if (smb_mbc_decodef(&sidbuf, "l", &sid->sid_subauth[i]))
4795521Sas200622 goto decode_err;
4805521Sas200622 }
4815521Sas200622
4825521Sas200622 return (sid);
4835521Sas200622
4845521Sas200622 decode_err:
4856432Sas200622 kmem_free(sid, sidlen);
4865521Sas200622 return (NULL);
4875521Sas200622 }
4885521Sas200622
4895521Sas200622 /*
4905521Sas200622 * smb_decode_acl
4915521Sas200622 *
4925521Sas200622 * Allocates memory and decodes the ACL in the request buffer
4935521Sas200622 * Upon successful return, caller must free the allocated memory
4945521Sas200622 * by calling smb_acl_free().
4955521Sas200622 */
4965521Sas200622 static smb_acl_t *
smb_decode_acl(struct smb_xa * xa,uint32_t offset)4975521Sas200622 smb_decode_acl(struct smb_xa *xa, uint32_t offset)
4985521Sas200622 {
4995521Sas200622 struct mbuf_chain aclbuf;
5005521Sas200622 smb_acl_t *acl;
5015521Sas200622 smb_ace_t *ace;
5025521Sas200622 uint8_t revision;
5035521Sas200622 uint16_t size;
5045521Sas200622 uint16_t acecnt;
5055521Sas200622 int bytes_left;
5065521Sas200622 uint32_t sid_offs = offset;
5075521Sas200622 int sidlen;
5085521Sas200622 int i;
5095521Sas200622
5105521Sas200622 offset += xa->req_data_mb.chain_offset;
5115521Sas200622 bytes_left = xa->req_data_mb.max_bytes - offset;
5125521Sas200622 if (bytes_left < SMB_ACL_HDRSIZE)
5135521Sas200622 return (NULL);
5145521Sas200622
5155521Sas200622 (void) MBC_SHADOW_CHAIN(&aclbuf, &xa->req_data_mb, offset, bytes_left);
5165521Sas200622
5177052Samw if (smb_mbc_decodef(&aclbuf, "b.ww2.", &revision, &size, &acecnt))
5185521Sas200622 return (NULL);
5195521Sas200622
5205521Sas200622 if (size == 0)
5215521Sas200622 return (NULL);
5225521Sas200622
5235521Sas200622 acl = smb_acl_alloc(revision, size, acecnt);
5245521Sas200622
5255521Sas200622 sid_offs += SMB_ACL_HDRSIZE;
5265521Sas200622 for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) {
5277052Samw if (smb_mbc_decodef(&aclbuf, "bbwl",
5285521Sas200622 &ace->se_hdr.se_type, &ace->se_hdr.se_flags,
5295521Sas200622 &ace->se_hdr.se_bsize, &ace->se_mask))
5305521Sas200622 goto decode_error;
5315521Sas200622
5325521Sas200622 sid_offs += SMB_ACE_HDRSIZE + sizeof (ace->se_mask);
5335521Sas200622 ace->se_sid = smb_decode_sid(xa, sid_offs);
5345521Sas200622 if (ace->se_sid == NULL)
5355521Sas200622 goto decode_error;
5367961SNatalie.Li@Sun.COM /* This is SID length plus any paddings between ACEs */
5377961SNatalie.Li@Sun.COM sidlen = ace->se_hdr.se_bsize -
5387961SNatalie.Li@Sun.COM (SMB_ACE_HDRSIZE + sizeof (ace->se_mask));
5395521Sas200622 aclbuf.chain_offset += sidlen;
5405521Sas200622 sid_offs += sidlen;
5415521Sas200622 }
5425521Sas200622
5435521Sas200622 return (acl);
5445521Sas200622
5455521Sas200622 decode_error:
5465521Sas200622 smb_acl_free(acl);
5475521Sas200622 return (NULL);
5485521Sas200622 }
549