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 /* 22cb174861Sjoyce mcintosh * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23*c5f48fa5SGordon Ross * Copyright 2016 Nexenta Systems, Inc. All rights reserved. 24da6c28aaSamw */ 25da6c28aaSamw 26da6c28aaSamw /* 27da6c28aaSamw * This command is used to create or open a file or directory, when EAs 28da6c28aaSamw * or an SD must be applied to the file. The functionality is similar 29da6c28aaSamw * to SmbNtCreateAndx with the option to supply extended attributes or 30da6c28aaSamw * a security descriptor. 31da6c28aaSamw * 32da6c28aaSamw * Note: we don't decode the extended attributes because we don't 33da6c28aaSamw * support them at this time. 34da6c28aaSamw */ 35da6c28aaSamw 3655bf511dSas200622 #include <smbsrv/smb_kproto.h> 37da6c28aaSamw #include <smbsrv/smb_fsops.h> 38da6c28aaSamw 39*c5f48fa5SGordon Ross extern int smb_nt_create_enable_extended_response; 40*c5f48fa5SGordon Ross 41da6c28aaSamw /* 42da6c28aaSamw * smb_nt_transact_create 43da6c28aaSamw * 44da6c28aaSamw * This command is used to create or open a file or directory, when EAs 45da6c28aaSamw * or an SD must be applied to the file. The request parameter block 46da6c28aaSamw * encoding, data block encoding and output parameter block encoding are 47da6c28aaSamw * described in CIFS section 4.2.2. 48da6c28aaSamw * 49da6c28aaSamw * The format of the command is SmbNtTransact but it is basically the same 50da6c28aaSamw * as SmbNtCreateAndx with the option to supply extended attributes or a 51da6c28aaSamw * security descriptor. For information not defined in CIFS section 4.2.2 52da6c28aaSamw * see section 4.2.1 (NT_CREATE_ANDX). 53da6c28aaSamw */ 547b59d02dSjb150015 smb_sdrc_t 55faa1795aSjb150015 smb_pre_nt_transact_create(smb_request_t *sr, smb_xa_t *xa) 56da6c28aaSamw { 57da6c28aaSamw struct open_param *op = &sr->arg.open; 58da6c28aaSamw uint8_t SecurityFlags; 59da6c28aaSamw uint32_t EaLength; 60da6c28aaSamw uint32_t ImpersonationLevel; 61da6c28aaSamw uint32_t NameLength; 62faa1795aSjb150015 uint32_t sd_len; 63faa1795aSjb150015 uint32_t status; 6455bf511dSas200622 smb_sd_t sd; 65da6c28aaSamw int rc; 66da6c28aaSamw 67faa1795aSjb150015 bzero(op, sizeof (sr->arg.open)); 68faa1795aSjb150015 693db3f65cSamw rc = smb_mbc_decodef(&xa->req_param_mb, "%lllqllllllllb", 70da6c28aaSamw sr, 712c2961f8Sjose borrego &op->nt_flags, 72faa1795aSjb150015 &op->rootdirfid, 73da6c28aaSamw &op->desired_access, 74da6c28aaSamw &op->dsize, 75faa1795aSjb150015 &op->dattr, 76da6c28aaSamw &op->share_access, 77da6c28aaSamw &op->create_disposition, 78da6c28aaSamw &op->create_options, 79da6c28aaSamw &sd_len, 80da6c28aaSamw &EaLength, 81da6c28aaSamw &NameLength, 82da6c28aaSamw &ImpersonationLevel, 83da6c28aaSamw &SecurityFlags); 84da6c28aaSamw 85faa1795aSjb150015 if (rc == 0) { 86da6c28aaSamw if (NameLength == 0) { 87eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States op->fqi.fq_path.pn_path = "\\"; 88*c5f48fa5SGordon Ross } else if (NameLength >= SMB_MAXPATHLEN) { 89*c5f48fa5SGordon Ross smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID, 90*c5f48fa5SGordon Ross ERRDOS, ERROR_INVALID_NAME); 91faa1795aSjb150015 rc = -1; 92da6c28aaSamw } else { 933db3f65cSamw rc = smb_mbc_decodef(&xa->req_param_mb, "%#u", 94eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States sr, NameLength, &op->fqi.fq_path.pn_path); 95faa1795aSjb150015 } 96da6c28aaSamw } 97da6c28aaSamw 982c2961f8Sjose borrego op->op_oplock_level = SMB_OPLOCK_NONE; 992c2961f8Sjose borrego if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPLOCK) { 1002c2961f8Sjose borrego if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPBATCH) 1012c2961f8Sjose borrego op->op_oplock_level = SMB_OPLOCK_BATCH; 102faa1795aSjb150015 else 1032c2961f8Sjose borrego op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE; 104da6c28aaSamw } 105da6c28aaSamw 10655bf511dSas200622 if (sd_len) { 107a90cf9f2SGordon Ross status = smb_decode_sd(&xa->req_data_mb, &sd); 10855bf511dSas200622 if (status != NT_STATUS_SUCCESS) { 109dc20a302Sas200622 smbsr_error(sr, status, 0, 0); 110faa1795aSjb150015 return (SDRC_ERROR); 111da6c28aaSamw } 112e5468186Sas200622 op->sd = kmem_alloc(sizeof (smb_sd_t), KM_SLEEP); 113e5468186Sas200622 *op->sd = sd; 114da6c28aaSamw } else { 11555bf511dSas200622 op->sd = NULL; 116da6c28aaSamw } 117da6c28aaSamw 118faa1795aSjb150015 DTRACE_SMB_2(op__NtTransactCreate__start, smb_request_t *, sr, 119faa1795aSjb150015 struct open_param *, op); 120da6c28aaSamw 121faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 122da6c28aaSamw } 123da6c28aaSamw 124faa1795aSjb150015 void 125faa1795aSjb150015 smb_post_nt_transact_create(smb_request_t *sr, smb_xa_t *xa) 126faa1795aSjb150015 { 127e5468186Sas200622 smb_sd_t *sd = sr->arg.open.sd; 128e5468186Sas200622 129faa1795aSjb150015 DTRACE_SMB_2(op__NtTransactCreate__done, smb_request_t *, sr, 130faa1795aSjb150015 smb_xa_t *, xa); 131e5468186Sas200622 132e5468186Sas200622 if (sd) { 133e5468186Sas200622 smb_sd_term(sd); 134e5468186Sas200622 kmem_free(sd, sizeof (smb_sd_t)); 135e5468186Sas200622 } 136bbf6f00cSJordan Brown 137*c5f48fa5SGordon Ross if (sr->arg.open.dir != NULL) { 138bbf6f00cSJordan Brown smb_ofile_release(sr->arg.open.dir); 139*c5f48fa5SGordon Ross sr->arg.open.dir = NULL; 140*c5f48fa5SGordon Ross } 141faa1795aSjb150015 } 142faa1795aSjb150015 143*c5f48fa5SGordon Ross /* 144*c5f48fa5SGordon Ross * A lot like smb_com_nt_create_andx 145*c5f48fa5SGordon Ross */ 146faa1795aSjb150015 smb_sdrc_t 147faa1795aSjb150015 smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa) 148faa1795aSjb150015 { 149faa1795aSjb150015 struct open_param *op = &sr->arg.open; 150*c5f48fa5SGordon Ross smb_attr_t *ap = &op->fqi.fq_fattr; 1515fd03bc0SGordon Ross smb_ofile_t *of; 1525fd03bc0SGordon Ross int rc; 153*c5f48fa5SGordon Ross uint8_t DirFlag; 154*c5f48fa5SGordon Ross uint32_t status; 155*c5f48fa5SGordon Ross 156*c5f48fa5SGordon Ross if (op->create_options & ~SMB_NTCREATE_VALID_OPTIONS) { 157*c5f48fa5SGordon Ross smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 158*c5f48fa5SGordon Ross ERRDOS, ERROR_INVALID_PARAMETER); 159*c5f48fa5SGordon Ross return (SDRC_ERROR); 160*c5f48fa5SGordon Ross } 161*c5f48fa5SGordon Ross 162*c5f48fa5SGordon Ross if (op->create_options & FILE_OPEN_BY_FILE_ID) { 163*c5f48fa5SGordon Ross smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, 164*c5f48fa5SGordon Ross ERRDOS, ERROR_NOT_SUPPORTED); 165*c5f48fa5SGordon Ross return (SDRC_ERROR); 166*c5f48fa5SGordon Ross } 167faa1795aSjb150015 168faa1795aSjb150015 if ((op->create_options & FILE_DELETE_ON_CLOSE) && 169faa1795aSjb150015 !(op->desired_access & DELETE)) { 1702c2961f8Sjose borrego smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 1712c2961f8Sjose borrego ERRDOS, ERRbadaccess); 1722c2961f8Sjose borrego return (SDRC_ERROR); 1732c2961f8Sjose borrego } 1742c2961f8Sjose borrego 1752c2961f8Sjose borrego if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) { 1762c2961f8Sjose borrego smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 1772c2961f8Sjose borrego ERRDOS, ERRbadaccess); 178faa1795aSjb150015 return (SDRC_ERROR); 179faa1795aSjb150015 } 180faa1795aSjb150015 181faa1795aSjb150015 if (op->dattr & FILE_FLAG_WRITE_THROUGH) 182da6c28aaSamw op->create_options |= FILE_WRITE_THROUGH; 183da6c28aaSamw 184faa1795aSjb150015 if (op->dattr & FILE_FLAG_DELETE_ON_CLOSE) 185da6c28aaSamw op->create_options |= FILE_DELETE_ON_CLOSE; 186da6c28aaSamw 187b89a8333Snatalie li - Sun Microsystems - Irvine United States if (op->dattr & FILE_FLAG_BACKUP_SEMANTICS) 188b89a8333Snatalie li - Sun Microsystems - Irvine United States op->create_options |= FILE_OPEN_FOR_BACKUP_INTENT; 189b89a8333Snatalie li - Sun Microsystems - Irvine United States 190b89a8333Snatalie li - Sun Microsystems - Irvine United States if (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT) 191b89a8333Snatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_user_getprivcred(sr->uid_user); 192b89a8333Snatalie li - Sun Microsystems - Irvine United States 193faa1795aSjb150015 if (op->rootdirfid == 0) { 194eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States op->fqi.fq_dnode = sr->tid_tree->t_snode; 195da6c28aaSamw } else { 1963b13a1efSThomas Keiser op->dir = smb_ofile_lookup_by_fid(sr, (uint16_t)op->rootdirfid); 197bbf6f00cSJordan Brown if (op->dir == NULL) { 198faa1795aSjb150015 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 199faa1795aSjb150015 ERRDOS, ERRbadfid); 200faa1795aSjb150015 return (SDRC_ERROR); 201faa1795aSjb150015 } 202bbf6f00cSJordan Brown op->fqi.fq_dnode = op->dir->f_node; 203da6c28aaSamw } 204da6c28aaSamw 205cb174861Sjoyce mcintosh op->op_oplock_levelII = B_TRUE; 206cb174861Sjoyce mcintosh 207a90cf9f2SGordon Ross status = smb_common_open(sr); 208a90cf9f2SGordon Ross if (status != NT_STATUS_SUCCESS) { 209a90cf9f2SGordon Ross smbsr_status(sr, status, 0, 0); 210faa1795aSjb150015 return (SDRC_ERROR); 211a90cf9f2SGordon Ross } 212da6c28aaSamw 2135fd03bc0SGordon Ross /* 2145fd03bc0SGordon Ross * NB: after the above smb_common_open() success, 2155fd03bc0SGordon Ross * we have a handle allocated (sr->fid_ofile). 2165fd03bc0SGordon Ross * If we don't return success, we must close it. 2175fd03bc0SGordon Ross */ 2185fd03bc0SGordon Ross of = sr->fid_ofile; 2195fd03bc0SGordon Ross 220f96bd5c8SAlan Wright switch (sr->tid_tree->t_res_type & STYPE_MASK) { 221f96bd5c8SAlan Wright case STYPE_DISKTREE: 222f96bd5c8SAlan Wright case STYPE_PRINTQ: 223da6c28aaSamw if (op->create_options & FILE_DELETE_ON_CLOSE) 2245fd03bc0SGordon Ross smb_ofile_set_delete_on_close(of); 2255fd03bc0SGordon Ross DirFlag = smb_node_is_dir(of->f_node) ? 1 : 0; 226f96bd5c8SAlan Wright break; 227f96bd5c8SAlan Wright 228f96bd5c8SAlan Wright case STYPE_IPC: 229*c5f48fa5SGordon Ross DirFlag = 0; 230f96bd5c8SAlan Wright break; 231f96bd5c8SAlan Wright 232f96bd5c8SAlan Wright default: 233f96bd5c8SAlan Wright smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST, 234f96bd5c8SAlan Wright ERRDOS, ERROR_INVALID_FUNCTION); 2355fd03bc0SGordon Ross goto errout; 236da6c28aaSamw } 237*c5f48fa5SGordon Ross 238*c5f48fa5SGordon Ross if ((op->nt_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE) != 0 && 239*c5f48fa5SGordon Ross smb_nt_create_enable_extended_response != 0) { 240*c5f48fa5SGordon Ross uint32_t MaxAccess = 0; 241*c5f48fa5SGordon Ross if (of->f_node != NULL) { 242*c5f48fa5SGordon Ross smb_fsop_eaccess(sr, of->f_cr, of->f_node, &MaxAccess); 243*c5f48fa5SGordon Ross } 244*c5f48fa5SGordon Ross MaxAccess |= of->f_granted_access; 245*c5f48fa5SGordon Ross 246*c5f48fa5SGordon Ross rc = smb_mbc_encodef( 247*c5f48fa5SGordon Ross &xa->rep_param_mb, "bbwllTTTTlqqwwb16.qll", 248*c5f48fa5SGordon Ross op->op_oplock_level, /* (b) */ 249*c5f48fa5SGordon Ross 1, /* ResponseType (b) */ 250*c5f48fa5SGordon Ross sr->smb_fid, /* (w) */ 251*c5f48fa5SGordon Ross op->action_taken, /* (l) */ 252*c5f48fa5SGordon Ross 0, /* EaErrorOffset (l) */ 253*c5f48fa5SGordon Ross &ap->sa_crtime, /* (T) */ 254*c5f48fa5SGordon Ross &ap->sa_vattr.va_atime, /* (T) */ 255*c5f48fa5SGordon Ross &ap->sa_vattr.va_mtime, /* (T) */ 256*c5f48fa5SGordon Ross &ap->sa_vattr.va_ctime, /* (T) */ 257*c5f48fa5SGordon Ross op->dattr & FILE_ATTRIBUTE_MASK, /* (l) */ 258*c5f48fa5SGordon Ross ap->sa_allocsz, /* (q) */ 259*c5f48fa5SGordon Ross ap->sa_vattr.va_size, /* (q) */ 260*c5f48fa5SGordon Ross op->ftype, /* (w) */ 261*c5f48fa5SGordon Ross op->devstate, /* (w) */ 262*c5f48fa5SGordon Ross DirFlag, /* (b) */ 263*c5f48fa5SGordon Ross /* volume guid (16.) */ 264*c5f48fa5SGordon Ross op->fileid, /* (q) */ 265*c5f48fa5SGordon Ross MaxAccess, /* (l) */ 266*c5f48fa5SGordon Ross 0); /* guest access (l) */ 267*c5f48fa5SGordon Ross } else { 268*c5f48fa5SGordon Ross rc = smb_mbc_encodef( 269*c5f48fa5SGordon Ross &xa->rep_param_mb, "bbwllTTTTlqqwwb", 270*c5f48fa5SGordon Ross op->op_oplock_level, /* (b) */ 271*c5f48fa5SGordon Ross 0, /* ResponseType (b) */ 272*c5f48fa5SGordon Ross sr->smb_fid, /* (w) */ 273*c5f48fa5SGordon Ross op->action_taken, /* (l) */ 274*c5f48fa5SGordon Ross 0, /* EaErrorOffset (l) */ 275*c5f48fa5SGordon Ross &ap->sa_crtime, /* (T) */ 276*c5f48fa5SGordon Ross &ap->sa_vattr.va_atime, /* (T) */ 277*c5f48fa5SGordon Ross &ap->sa_vattr.va_mtime, /* (T) */ 278*c5f48fa5SGordon Ross &ap->sa_vattr.va_ctime, /* (T) */ 279*c5f48fa5SGordon Ross op->dattr & FILE_ATTRIBUTE_MASK, /* (l) */ 280*c5f48fa5SGordon Ross ap->sa_allocsz, /* (q) */ 281*c5f48fa5SGordon Ross ap->sa_vattr.va_size, /* (q) */ 282*c5f48fa5SGordon Ross op->ftype, /* (w) */ 283*c5f48fa5SGordon Ross op->devstate, /* (w) */ 284*c5f48fa5SGordon Ross DirFlag); /* (b) */ 285*c5f48fa5SGordon Ross } 286*c5f48fa5SGordon Ross 287*c5f48fa5SGordon Ross if (rc == 0) 288faa1795aSjb150015 return (SDRC_SUCCESS); 2895fd03bc0SGordon Ross 2905fd03bc0SGordon Ross errout: 2915fd03bc0SGordon Ross smb_ofile_close(of, 0); 2925fd03bc0SGordon Ross return (SDRC_ERROR); 293da6c28aaSamw } 294