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 */ 21da6c28aaSamw /* 22dc20a302Sas200622 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24da6c28aaSamw */ 25da6c28aaSamw 2655bf511dSas200622 #include <smbsrv/smb_kproto.h> 2755bf511dSas200622 #include <smbsrv/ntstatus.h> 2855bf511dSas200622 #include <smbsrv/nterror.h> 2955bf511dSas200622 #include <smbsrv/doserror.h> 3055bf511dSas200622 #include <smbsrv/cifs.h> 31da6c28aaSamw 3255bf511dSas200622 static void smb_encode_sd(struct smb_xa *, smb_sd_t *, uint32_t); 336537f381Sas200622 static void smb_encode_sid(struct smb_xa *, smb_sid_t *); 3455bf511dSas200622 static void smb_encode_sacl(struct smb_xa *, smb_acl_t *); 3555bf511dSas200622 static void smb_encode_dacl(struct smb_xa *, smb_acl_t *); 3655bf511dSas200622 3755bf511dSas200622 uint32_t smb_decode_sd(struct smb_xa *, smb_sd_t *); 386537f381Sas200622 static smb_sid_t *smb_decode_sid(struct smb_xa *, uint32_t); 3955bf511dSas200622 static smb_acl_t *smb_decode_acl(struct smb_xa *, uint32_t); 40da6c28aaSamw 41da6c28aaSamw /* 42da6c28aaSamw * smb_nt_transact_query_security_info 43da6c28aaSamw * 44da6c28aaSamw * This command allows the client to retrieve the security descriptor 45da6c28aaSamw * on a file. The result of the call is returned to the client in the 46da6c28aaSamw * Data part of the transaction response. 47da6c28aaSamw * 48da6c28aaSamw * Some clients specify a non-zero maximum data return size (mdrcnt) 49da6c28aaSamw * for the SD and some specify zero. In either case, if the mdrcnt is 50da6c28aaSamw * too small we need to return NT_STATUS_BUFFER_TOO_SMALL and a buffer 51da6c28aaSamw * size hint. The client should then retry with the appropriate buffer 52da6c28aaSamw * size. 53da6c28aaSamw * 54da6c28aaSamw * Client Parameter Block Description 55da6c28aaSamw * ================================== ================================= 56da6c28aaSamw * 57da6c28aaSamw * USHORT Fid; FID of target 58da6c28aaSamw * USHORT Reserved; MBZ 59da6c28aaSamw * ULONG secinfo; Fields of descriptor to set 60da6c28aaSamw * 61da6c28aaSamw * Data Block Encoding Description 62da6c28aaSamw * ================================== ================================== 63da6c28aaSamw * 64da6c28aaSamw * Data[TotalDataCount] Security Descriptor information 65da6c28aaSamw */ 66da6c28aaSamw 677b59d02dSjb150015 smb_sdrc_t 68da6c28aaSamw smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) 69da6c28aaSamw { 7055bf511dSas200622 smb_sd_t sd; 71da6c28aaSamw uint32_t secinfo; 7255bf511dSas200622 uint32_t sdlen; 73da6c28aaSamw uint32_t status; 74dc20a302Sas200622 smb_error_t err; 7555bf511dSas200622 763db3f65cSamw if (smb_mbc_decodef(&xa->req_param_mb, "w2.l", 77da6c28aaSamw &sr->smb_fid, &secinfo) != 0) { 78dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); 79faa1795aSjb150015 return (SDRC_ERROR); 80da6c28aaSamw } 81da6c28aaSamw 82da6c28aaSamw sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 83da6c28aaSamw if (sr->fid_ofile == NULL) { 84dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 85faa1795aSjb150015 return (SDRC_ERROR); 86da6c28aaSamw } 87da6c28aaSamw 88da6c28aaSamw 89da6c28aaSamw if ((sr->fid_ofile->f_node == NULL) || 90da6c28aaSamw (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) { 91dc20a302Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 9255bf511dSas200622 ERRDOS, ERROR_ACCESS_DENIED); 93faa1795aSjb150015 return (SDRC_ERROR); 94da6c28aaSamw } 95da6c28aaSamw 96*b89a8333Snatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 97*b89a8333Snatalie li - Sun Microsystems - Irvine United States 98da6c28aaSamw if (sr->tid_tree->t_acltype != ACE_T) { 99da6c28aaSamw /* 100da6c28aaSamw * If target filesystem doesn't support ACE_T acls then 101da6c28aaSamw * don't process SACL 102da6c28aaSamw */ 103da6c28aaSamw secinfo &= ~SMB_SACL_SECINFO; 104da6c28aaSamw } 105da6c28aaSamw 10655bf511dSas200622 status = smb_sd_read(sr, &sd, secinfo); 107da6c28aaSamw if (status != NT_STATUS_SUCCESS) { 108dc20a302Sas200622 smbsr_error(sr, status, 0, 0); 109faa1795aSjb150015 return (SDRC_ERROR); 110da6c28aaSamw } 111da6c28aaSamw 11255bf511dSas200622 sdlen = smb_sd_len(&sd, secinfo); 11355bf511dSas200622 if (sdlen == 0) { 11455bf511dSas200622 smb_sd_term(&sd); 115dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_SECURITY_DESCR, 0, 0); 116faa1795aSjb150015 return (SDRC_ERROR); 11755bf511dSas200622 } 118da6c28aaSamw 11955bf511dSas200622 if (sdlen > xa->smb_mdrcnt) { 12055bf511dSas200622 /* 12155bf511dSas200622 * The maximum data return count specified by the 12255bf511dSas200622 * client is not big enough to hold the security 12355bf511dSas200622 * descriptor. We have to return an error but we 12455bf511dSas200622 * should provide a buffer size hint for the client. 12555bf511dSas200622 */ 1263db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "l", sdlen); 127dc20a302Sas200622 err.severity = ERROR_SEVERITY_ERROR; 128dc20a302Sas200622 err.status = NT_STATUS_BUFFER_TOO_SMALL; 129dc20a302Sas200622 err.errcls = ERRDOS; 130dc20a302Sas200622 err.errcode = ERROR_INSUFFICIENT_BUFFER; 131dc20a302Sas200622 smbsr_set_error(sr, &err); 13255bf511dSas200622 smb_sd_term(&sd); 133faa1795aSjb150015 return (SDRC_SUCCESS); 13455bf511dSas200622 } 13555bf511dSas200622 13655bf511dSas200622 smb_encode_sd(xa, &sd, secinfo); 1373db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "l", sdlen); 13855bf511dSas200622 smb_sd_term(&sd); 139faa1795aSjb150015 return (SDRC_SUCCESS); 140da6c28aaSamw } 141da6c28aaSamw 142da6c28aaSamw /* 143da6c28aaSamw * smb_nt_transact_set_security_info 144da6c28aaSamw * 145da6c28aaSamw * This command allows the client to change the security descriptor on a 146da6c28aaSamw * file. All we do here is decode the parameters and the data. The data 147da6c28aaSamw * is passed directly to smb_nt_set_security_object, with the security 148da6c28aaSamw * information describing the information to set. There are no response 149da6c28aaSamw * parameters or data. 150da6c28aaSamw * 151da6c28aaSamw * Client Parameter Block Encoding Description 152da6c28aaSamw * ================================== ================================== 153da6c28aaSamw * USHORT Fid; FID of target 154da6c28aaSamw * USHORT Reserved; MBZ 155da6c28aaSamw * ULONG SecurityInformation; Fields of SD that to set 156da6c28aaSamw * 157da6c28aaSamw * Data Block Encoding Description 158da6c28aaSamw * ================================== ================================== 159da6c28aaSamw * Data[TotalDataCount] Security Descriptor information 160da6c28aaSamw */ 1617b59d02dSjb150015 smb_sdrc_t 162da6c28aaSamw smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa) 163da6c28aaSamw { 16455bf511dSas200622 smb_sd_t sd; 16555bf511dSas200622 uint32_t secinfo; 166da6c28aaSamw uint32_t status; 167da6c28aaSamw 1683db3f65cSamw if (smb_mbc_decodef(&xa->req_param_mb, "w2.l", 16955bf511dSas200622 &sr->smb_fid, &secinfo) != 0) { 170dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); 171faa1795aSjb150015 return (SDRC_ERROR); 172da6c28aaSamw } 173da6c28aaSamw 174da6c28aaSamw sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 175da6c28aaSamw if (sr->fid_ofile == NULL) { 176dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 177faa1795aSjb150015 return (SDRC_ERROR); 178da6c28aaSamw } 179da6c28aaSamw 180da6c28aaSamw if ((sr->fid_ofile->f_node == NULL) || 181da6c28aaSamw (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) { 182dc20a302Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 0, 0); 183faa1795aSjb150015 return (SDRC_ERROR); 184da6c28aaSamw } 185da6c28aaSamw 186*b89a8333Snatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 187*b89a8333Snatalie li - Sun Microsystems - Irvine United States 188c8ec8eeaSjose borrego if (SMB_TREE_IS_READONLY(sr)) { 189dc20a302Sas200622 smbsr_error(sr, NT_STATUS_MEDIA_WRITE_PROTECTED, 0, 0); 190faa1795aSjb150015 return (SDRC_ERROR); 191da6c28aaSamw } 192da6c28aaSamw 193da6c28aaSamw if (sr->tid_tree->t_acltype != ACE_T) { 194da6c28aaSamw /* 195da6c28aaSamw * If target filesystem doesn't support ACE_T acls then 196da6c28aaSamw * don't process SACL 197da6c28aaSamw */ 19855bf511dSas200622 secinfo &= ~SMB_SACL_SECINFO; 199da6c28aaSamw } 200da6c28aaSamw 20155bf511dSas200622 if ((secinfo & SMB_ALL_SECINFO) == 0) { 202da6c28aaSamw return (NT_STATUS_SUCCESS); 203da6c28aaSamw } 204da6c28aaSamw 20555bf511dSas200622 status = smb_decode_sd(xa, &sd); 20655bf511dSas200622 if (status != NT_STATUS_SUCCESS) { 207dc20a302Sas200622 smbsr_error(sr, status, 0, 0); 208faa1795aSjb150015 return (SDRC_ERROR); 209da6c28aaSamw } 210da6c28aaSamw 21155bf511dSas200622 if (((secinfo & SMB_OWNER_SECINFO) && (sd.sd_owner == NULL)) || 21255bf511dSas200622 ((secinfo & SMB_GROUP_SECINFO) && (sd.sd_group == NULL))) { 213dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); 214faa1795aSjb150015 return (SDRC_ERROR); 21555bf511dSas200622 } 216da6c28aaSamw 21755bf511dSas200622 status = smb_sd_write(sr, &sd, secinfo); 21855bf511dSas200622 smb_sd_term(&sd); 219da6c28aaSamw if (status != NT_STATUS_SUCCESS) { 220dc20a302Sas200622 smbsr_error(sr, status, 0, 0); 221faa1795aSjb150015 return (SDRC_ERROR); 222da6c28aaSamw } 223da6c28aaSamw 224faa1795aSjb150015 return (SDRC_SUCCESS); 225da6c28aaSamw } 22655bf511dSas200622 22755bf511dSas200622 /* 22855bf511dSas200622 * smb_encode_sd 22955bf511dSas200622 * 23055bf511dSas200622 * Encodes given security descriptor in the reply buffer. 23155bf511dSas200622 */ 23255bf511dSas200622 static void 23355bf511dSas200622 smb_encode_sd(struct smb_xa *xa, smb_sd_t *sd, uint32_t secinfo) 23455bf511dSas200622 { 23555bf511dSas200622 uint32_t offset = SMB_SD_HDRSIZE; 23655bf511dSas200622 23755bf511dSas200622 /* encode header */ 2383db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "b.w", 23955bf511dSas200622 sd->sd_revision, sd->sd_control | SE_SELF_RELATIVE); 24055bf511dSas200622 24155bf511dSas200622 /* owner offset */ 24255bf511dSas200622 if (secinfo & SMB_OWNER_SECINFO) { 24355bf511dSas200622 ASSERT(sd->sd_owner); 2443db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", offset); 2456537f381Sas200622 offset += smb_sid_len(sd->sd_owner); 24655bf511dSas200622 } else { 2473db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0); 24855bf511dSas200622 } 24955bf511dSas200622 25055bf511dSas200622 /* group offset */ 25155bf511dSas200622 if (secinfo & SMB_GROUP_SECINFO) { 25255bf511dSas200622 ASSERT(sd->sd_group); 2533db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", offset); 2546537f381Sas200622 offset += smb_sid_len(sd->sd_group); 25555bf511dSas200622 } else { 2563db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0); 25755bf511dSas200622 } 25855bf511dSas200622 25955bf511dSas200622 /* SACL offset */ 26055bf511dSas200622 if ((secinfo & SMB_SACL_SECINFO) && (sd->sd_sacl)) { 2613db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", offset); 26255bf511dSas200622 offset += smb_acl_len(sd->sd_sacl); 26355bf511dSas200622 } else { 2643db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0); 26555bf511dSas200622 } 26655bf511dSas200622 26755bf511dSas200622 /* DACL offset */ 26855bf511dSas200622 if ((secinfo & SMB_DACL_SECINFO) && (sd->sd_dacl)) 2693db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", offset); 27055bf511dSas200622 else 2713db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0); 27255bf511dSas200622 27355bf511dSas200622 if (secinfo & SMB_OWNER_SECINFO) 27455bf511dSas200622 smb_encode_sid(xa, sd->sd_owner); 27555bf511dSas200622 27655bf511dSas200622 if (secinfo & SMB_GROUP_SECINFO) 27755bf511dSas200622 smb_encode_sid(xa, sd->sd_group); 27855bf511dSas200622 27955bf511dSas200622 if (secinfo & SMB_SACL_SECINFO) 28055bf511dSas200622 smb_encode_sacl(xa, sd->sd_sacl); 28155bf511dSas200622 28255bf511dSas200622 if (secinfo & SMB_DACL_SECINFO) 28355bf511dSas200622 smb_encode_dacl(xa, sd->sd_dacl); 28455bf511dSas200622 } 28555bf511dSas200622 28655bf511dSas200622 /* 28755bf511dSas200622 * smb_encode_sid 28855bf511dSas200622 * 28955bf511dSas200622 * Encodes given SID in the reply buffer. 29055bf511dSas200622 */ 29155bf511dSas200622 static void 2926537f381Sas200622 smb_encode_sid(struct smb_xa *xa, smb_sid_t *sid) 29355bf511dSas200622 { 29455bf511dSas200622 int i; 29555bf511dSas200622 2963db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "bb", 2976537f381Sas200622 sid->sid_revision, sid->sid_subauthcnt); 29855bf511dSas200622 29955bf511dSas200622 for (i = 0; i < NT_SID_AUTH_MAX; i++) { 3003db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "b", 3016537f381Sas200622 sid->sid_authority[i]); 30255bf511dSas200622 } 30355bf511dSas200622 3046537f381Sas200622 for (i = 0; i < sid->sid_subauthcnt; i++) { 3053db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 3066537f381Sas200622 sid->sid_subauth[i]); 30755bf511dSas200622 } 30855bf511dSas200622 } 30955bf511dSas200622 31055bf511dSas200622 /* 31155bf511dSas200622 * smb_encode_sacl 31255bf511dSas200622 * 31355bf511dSas200622 * Encodes given SACL in the reply buffer. 31455bf511dSas200622 */ 31555bf511dSas200622 static void 31655bf511dSas200622 smb_encode_sacl(struct smb_xa *xa, smb_acl_t *acl) 31755bf511dSas200622 { 31855bf511dSas200622 smb_ace_t *ace; 31955bf511dSas200622 int i; 32055bf511dSas200622 32155bf511dSas200622 if (acl == NULL) 32255bf511dSas200622 return; 32355bf511dSas200622 32455bf511dSas200622 /* encode header */ 3253db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "b.ww2.", acl->sl_revision, 32655bf511dSas200622 acl->sl_bsize, acl->sl_acecnt); 32755bf511dSas200622 32855bf511dSas200622 for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) { 3293db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "bbwl", 33055bf511dSas200622 ace->se_hdr.se_type, ace->se_hdr.se_flags, 33155bf511dSas200622 ace->se_hdr.se_bsize, ace->se_mask); 33255bf511dSas200622 33355bf511dSas200622 smb_encode_sid(xa, ace->se_sid); 33455bf511dSas200622 } 33555bf511dSas200622 } 33655bf511dSas200622 33755bf511dSas200622 /* 33855bf511dSas200622 * smb_encode_dacl 33955bf511dSas200622 * 34055bf511dSas200622 * Encodes given DACL in the reply buffer. 34155bf511dSas200622 */ 34255bf511dSas200622 static void 34355bf511dSas200622 smb_encode_dacl(struct smb_xa *xa, smb_acl_t *acl) 34455bf511dSas200622 { 34555bf511dSas200622 smb_ace_t *ace; 34655bf511dSas200622 34755bf511dSas200622 if (acl == NULL) 34855bf511dSas200622 return; 34955bf511dSas200622 35055bf511dSas200622 /* encode header */ 3513db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "b.ww2.", acl->sl_revision, 35255bf511dSas200622 acl->sl_bsize, acl->sl_acecnt); 35355bf511dSas200622 35455bf511dSas200622 ace = list_head(&acl->sl_sorted); 35555bf511dSas200622 while (ace) { 3563db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "bbwl", 35755bf511dSas200622 ace->se_hdr.se_type, ace->se_hdr.se_flags, 35855bf511dSas200622 ace->se_hdr.se_bsize, ace->se_mask); 35955bf511dSas200622 36055bf511dSas200622 smb_encode_sid(xa, ace->se_sid); 36155bf511dSas200622 ace = list_next(&acl->sl_sorted, ace); 36255bf511dSas200622 } 36355bf511dSas200622 } 36455bf511dSas200622 36555bf511dSas200622 /* 36655bf511dSas200622 * smb_decode_sd 36755bf511dSas200622 * 36855bf511dSas200622 * Decodes the security descriptor in the request buffer 36955bf511dSas200622 * and set the fields of 'sd' appropraitely. Upon successful 37055bf511dSas200622 * return, caller must free allocated memories by calling 37155bf511dSas200622 * smb_sd_term(). 37255bf511dSas200622 */ 37355bf511dSas200622 uint32_t 37455bf511dSas200622 smb_decode_sd(struct smb_xa *xa, smb_sd_t *sd) 37555bf511dSas200622 { 37655bf511dSas200622 struct mbuf_chain sdbuf; 37755bf511dSas200622 uint32_t owner_offs; 37855bf511dSas200622 uint32_t group_offs; 37955bf511dSas200622 uint32_t sacl_offs; 38055bf511dSas200622 uint32_t dacl_offs; 38155bf511dSas200622 38255bf511dSas200622 smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION); 38355bf511dSas200622 38455bf511dSas200622 (void) MBC_SHADOW_CHAIN(&sdbuf, &xa->req_data_mb, 38555bf511dSas200622 xa->req_data_mb.chain_offset, 38655bf511dSas200622 xa->req_data_mb.max_bytes - xa->req_data_mb.chain_offset); 38755bf511dSas200622 3883db3f65cSamw if (smb_mbc_decodef(&sdbuf, "b.wllll", 38955bf511dSas200622 &sd->sd_revision, &sd->sd_control, 39055bf511dSas200622 &owner_offs, &group_offs, &sacl_offs, &dacl_offs)) 39155bf511dSas200622 goto decode_error; 39255bf511dSas200622 39355bf511dSas200622 sd->sd_control &= ~SE_SELF_RELATIVE; 39455bf511dSas200622 39555bf511dSas200622 if (owner_offs != 0) { 39655bf511dSas200622 if (owner_offs < SMB_SD_HDRSIZE) 39755bf511dSas200622 goto decode_error; 39855bf511dSas200622 39955bf511dSas200622 sd->sd_owner = smb_decode_sid(xa, owner_offs); 40055bf511dSas200622 if (sd->sd_owner == NULL) 40155bf511dSas200622 goto decode_error; 40255bf511dSas200622 } 40355bf511dSas200622 40455bf511dSas200622 if (group_offs != 0) { 40555bf511dSas200622 if (group_offs < SMB_SD_HDRSIZE) 40655bf511dSas200622 goto decode_error; 40755bf511dSas200622 40855bf511dSas200622 sd->sd_group = smb_decode_sid(xa, group_offs); 40955bf511dSas200622 if (sd->sd_group == NULL) 41055bf511dSas200622 goto decode_error; 41155bf511dSas200622 } 41255bf511dSas200622 41355bf511dSas200622 if (sacl_offs != 0) { 41455bf511dSas200622 if ((sd->sd_control & SE_SACL_PRESENT) == 0) 41555bf511dSas200622 goto decode_error; 41655bf511dSas200622 41755bf511dSas200622 if (sacl_offs < SMB_SD_HDRSIZE) 41855bf511dSas200622 goto decode_error; 41955bf511dSas200622 42055bf511dSas200622 sd->sd_sacl = smb_decode_acl(xa, sacl_offs); 42155bf511dSas200622 if (sd->sd_sacl == NULL) 42255bf511dSas200622 goto decode_error; 42355bf511dSas200622 } 42455bf511dSas200622 42555bf511dSas200622 if (dacl_offs != 0) { 42655bf511dSas200622 if ((sd->sd_control & SE_DACL_PRESENT) == 0) 42755bf511dSas200622 goto decode_error; 42855bf511dSas200622 42955bf511dSas200622 if (dacl_offs < SMB_SD_HDRSIZE) 43055bf511dSas200622 goto decode_error; 43155bf511dSas200622 43255bf511dSas200622 sd->sd_dacl = smb_decode_acl(xa, dacl_offs); 43355bf511dSas200622 if (sd->sd_dacl == NULL) 43455bf511dSas200622 goto decode_error; 43555bf511dSas200622 } 43655bf511dSas200622 43755bf511dSas200622 return (NT_STATUS_SUCCESS); 43855bf511dSas200622 43955bf511dSas200622 decode_error: 44055bf511dSas200622 smb_sd_term(sd); 44155bf511dSas200622 return (NT_STATUS_INVALID_SECURITY_DESCR); 44255bf511dSas200622 } 44355bf511dSas200622 44455bf511dSas200622 /* 44555bf511dSas200622 * smb_decode_sid 44655bf511dSas200622 * 44755bf511dSas200622 * Allocates memory and decodes the SID in the request buffer 44855bf511dSas200622 * Upon successful return, caller must free the allocated memory 4496537f381Sas200622 * by calling smb_sid_free() 45055bf511dSas200622 */ 4516537f381Sas200622 static smb_sid_t * 45255bf511dSas200622 smb_decode_sid(struct smb_xa *xa, uint32_t offset) 45355bf511dSas200622 { 45455bf511dSas200622 uint8_t revision; 45555bf511dSas200622 uint8_t subauth_cnt; 45655bf511dSas200622 struct mbuf_chain sidbuf; 4576537f381Sas200622 smb_sid_t *sid; 45855bf511dSas200622 int sidlen; 45955bf511dSas200622 int bytes_left; 46055bf511dSas200622 int i; 46155bf511dSas200622 46255bf511dSas200622 offset += xa->req_data_mb.chain_offset; 46355bf511dSas200622 bytes_left = xa->req_data_mb.max_bytes - offset; 4646537f381Sas200622 if (bytes_left < sizeof (smb_sid_t)) 46555bf511dSas200622 return (NULL); 46655bf511dSas200622 46755bf511dSas200622 (void) MBC_SHADOW_CHAIN(&sidbuf, &xa->req_data_mb, offset, bytes_left); 46855bf511dSas200622 4693db3f65cSamw if (smb_mbc_decodef(&sidbuf, "bb", &revision, &subauth_cnt)) 47055bf511dSas200622 return (NULL); 47155bf511dSas200622 4726537f381Sas200622 sidlen = sizeof (smb_sid_t) - sizeof (uint32_t) + 47355bf511dSas200622 (subauth_cnt * sizeof (uint32_t)); 4746537f381Sas200622 sid = kmem_alloc(sidlen, KM_SLEEP); 47555bf511dSas200622 4766537f381Sas200622 sid->sid_revision = revision; 4776537f381Sas200622 sid->sid_subauthcnt = subauth_cnt; 47855bf511dSas200622 47955bf511dSas200622 for (i = 0; i < NT_SID_AUTH_MAX; i++) { 4803db3f65cSamw if (smb_mbc_decodef(&sidbuf, "b", &sid->sid_authority[i])) 48155bf511dSas200622 goto decode_err; 48255bf511dSas200622 } 48355bf511dSas200622 4846537f381Sas200622 for (i = 0; i < sid->sid_subauthcnt; i++) { 4853db3f65cSamw if (smb_mbc_decodef(&sidbuf, "l", &sid->sid_subauth[i])) 48655bf511dSas200622 goto decode_err; 48755bf511dSas200622 } 48855bf511dSas200622 48955bf511dSas200622 return (sid); 49055bf511dSas200622 49155bf511dSas200622 decode_err: 4926537f381Sas200622 kmem_free(sid, sidlen); 49355bf511dSas200622 return (NULL); 49455bf511dSas200622 } 49555bf511dSas200622 49655bf511dSas200622 /* 49755bf511dSas200622 * smb_decode_acl 49855bf511dSas200622 * 49955bf511dSas200622 * Allocates memory and decodes the ACL in the request buffer 50055bf511dSas200622 * Upon successful return, caller must free the allocated memory 50155bf511dSas200622 * by calling smb_acl_free(). 50255bf511dSas200622 */ 50355bf511dSas200622 static smb_acl_t * 50455bf511dSas200622 smb_decode_acl(struct smb_xa *xa, uint32_t offset) 50555bf511dSas200622 { 50655bf511dSas200622 struct mbuf_chain aclbuf; 50755bf511dSas200622 smb_acl_t *acl; 50855bf511dSas200622 smb_ace_t *ace; 50955bf511dSas200622 uint8_t revision; 51055bf511dSas200622 uint16_t size; 51155bf511dSas200622 uint16_t acecnt; 51255bf511dSas200622 int bytes_left; 51355bf511dSas200622 uint32_t sid_offs = offset; 51455bf511dSas200622 int sidlen; 51555bf511dSas200622 int i; 51655bf511dSas200622 51755bf511dSas200622 offset += xa->req_data_mb.chain_offset; 51855bf511dSas200622 bytes_left = xa->req_data_mb.max_bytes - offset; 51955bf511dSas200622 if (bytes_left < SMB_ACL_HDRSIZE) 52055bf511dSas200622 return (NULL); 52155bf511dSas200622 52255bf511dSas200622 (void) MBC_SHADOW_CHAIN(&aclbuf, &xa->req_data_mb, offset, bytes_left); 52355bf511dSas200622 5243db3f65cSamw if (smb_mbc_decodef(&aclbuf, "b.ww2.", &revision, &size, &acecnt)) 52555bf511dSas200622 return (NULL); 52655bf511dSas200622 52755bf511dSas200622 if (size == 0) 52855bf511dSas200622 return (NULL); 52955bf511dSas200622 53055bf511dSas200622 acl = smb_acl_alloc(revision, size, acecnt); 53155bf511dSas200622 53255bf511dSas200622 sid_offs += SMB_ACL_HDRSIZE; 53355bf511dSas200622 for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) { 5343db3f65cSamw if (smb_mbc_decodef(&aclbuf, "bbwl", 53555bf511dSas200622 &ace->se_hdr.se_type, &ace->se_hdr.se_flags, 53655bf511dSas200622 &ace->se_hdr.se_bsize, &ace->se_mask)) 53755bf511dSas200622 goto decode_error; 53855bf511dSas200622 53955bf511dSas200622 sid_offs += SMB_ACE_HDRSIZE + sizeof (ace->se_mask); 54055bf511dSas200622 ace->se_sid = smb_decode_sid(xa, sid_offs); 54155bf511dSas200622 if (ace->se_sid == NULL) 54255bf511dSas200622 goto decode_error; 543*b89a8333Snatalie li - Sun Microsystems - Irvine United States /* This is SID length plus any paddings between ACEs */ 544*b89a8333Snatalie li - Sun Microsystems - Irvine United States sidlen = ace->se_hdr.se_bsize - 545*b89a8333Snatalie li - Sun Microsystems - Irvine United States (SMB_ACE_HDRSIZE + sizeof (ace->se_mask)); 54655bf511dSas200622 aclbuf.chain_offset += sidlen; 54755bf511dSas200622 sid_offs += sidlen; 54855bf511dSas200622 } 54955bf511dSas200622 55055bf511dSas200622 return (acl); 55155bf511dSas200622 55255bf511dSas200622 decode_error: 55355bf511dSas200622 smb_acl_free(acl); 55455bf511dSas200622 return (NULL); 55555bf511dSas200622 } 556