1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2017 Nexenta Systems, Inc. All rights reserved. 24 */ 25 26 /* 27 * This command is used to create or open a file or directory, when EAs 28 * or an SD must be applied to the file. The functionality is similar 29 * to SmbNtCreateAndx with the option to supply extended attributes or 30 * a security descriptor. 31 * 32 * Note: we don't decode the extended attributes because we don't 33 * support them at this time. 34 */ 35 36 #include <smbsrv/smb_kproto.h> 37 #include <smbsrv/smb_fsops.h> 38 39 extern int smb_nt_create_enable_extended_response; 40 41 /* 42 * smb_nt_transact_create 43 * 44 * This command is used to create or open a file or directory, when EAs 45 * or an SD must be applied to the file. The request parameter block 46 * encoding, data block encoding and output parameter block encoding are 47 * described in CIFS section 4.2.2. 48 * 49 * The format of the command is SmbNtTransact but it is basically the same 50 * as SmbNtCreateAndx with the option to supply extended attributes or a 51 * security descriptor. For information not defined in CIFS section 4.2.2 52 * see section 4.2.1 (NT_CREATE_ANDX). 53 */ 54 smb_sdrc_t 55 smb_pre_nt_transact_create(smb_request_t *sr, smb_xa_t *xa) 56 { 57 struct open_param *op = &sr->arg.open; 58 uint8_t SecurityFlags; 59 uint32_t EaLength; 60 uint32_t ImpersonationLevel; 61 uint32_t NameLength; 62 uint32_t sd_len; 63 uint32_t status; 64 smb_sd_t sd; 65 int rc; 66 67 bzero(op, sizeof (sr->arg.open)); 68 69 rc = smb_mbc_decodef(&xa->req_param_mb, "%lllqllllllllb", 70 sr, 71 &op->nt_flags, 72 &op->rootdirfid, 73 &op->desired_access, 74 &op->dsize, 75 &op->dattr, 76 &op->share_access, 77 &op->create_disposition, 78 &op->create_options, 79 &sd_len, 80 &EaLength, 81 &NameLength, 82 &ImpersonationLevel, 83 &SecurityFlags); 84 85 if (rc == 0) { 86 if (NameLength == 0) { 87 op->fqi.fq_path.pn_path = "\\"; 88 } else if (NameLength >= SMB_MAXPATHLEN) { 89 smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID, 90 ERRDOS, ERROR_INVALID_NAME); 91 rc = -1; 92 } else { 93 rc = smb_mbc_decodef(&xa->req_param_mb, "%#u", 94 sr, NameLength, &op->fqi.fq_path.pn_path); 95 } 96 } 97 98 op->op_oplock_level = SMB_OPLOCK_NONE; 99 if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPLOCK) { 100 if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPBATCH) 101 op->op_oplock_level = SMB_OPLOCK_BATCH; 102 else 103 op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE; 104 } 105 106 if (sd_len) { 107 status = smb_decode_sd(&xa->req_data_mb, &sd); 108 if (status != NT_STATUS_SUCCESS) { 109 smbsr_error(sr, status, 0, 0); 110 return (SDRC_ERROR); 111 } 112 op->sd = kmem_alloc(sizeof (smb_sd_t), KM_SLEEP); 113 *op->sd = sd; 114 } else { 115 op->sd = NULL; 116 } 117 118 DTRACE_SMB_START(op__NtTransactCreate, smb_request_t *, sr); 119 120 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 121 } 122 123 void 124 smb_post_nt_transact_create(smb_request_t *sr, smb_xa_t *xa) 125 { 126 smb_sd_t *sd = sr->arg.open.sd; 127 _NOTE(ARGUNUSED(xa)) 128 129 DTRACE_SMB_DONE(op__NtTransactCreate, smb_request_t *, sr); 130 131 if (sd) { 132 smb_sd_term(sd); 133 kmem_free(sd, sizeof (smb_sd_t)); 134 } 135 136 if (sr->arg.open.dir != NULL) { 137 smb_ofile_release(sr->arg.open.dir); 138 sr->arg.open.dir = NULL; 139 } 140 } 141 142 /* 143 * A lot like smb_com_nt_create_andx 144 */ 145 smb_sdrc_t 146 smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa) 147 { 148 struct open_param *op = &sr->arg.open; 149 smb_attr_t *ap = &op->fqi.fq_fattr; 150 smb_ofile_t *of; 151 int rc; 152 uint8_t DirFlag; 153 uint32_t status; 154 155 if (op->create_options & ~SMB_NTCREATE_VALID_OPTIONS) { 156 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 157 ERRDOS, ERROR_INVALID_PARAMETER); 158 return (SDRC_ERROR); 159 } 160 161 if (op->create_options & FILE_OPEN_BY_FILE_ID) { 162 smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, 163 ERRDOS, ERROR_NOT_SUPPORTED); 164 return (SDRC_ERROR); 165 } 166 167 if ((op->create_options & FILE_DELETE_ON_CLOSE) && 168 !(op->desired_access & DELETE)) { 169 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 170 ERRDOS, ERRbadaccess); 171 return (SDRC_ERROR); 172 } 173 174 if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) { 175 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 176 ERRDOS, ERRbadaccess); 177 return (SDRC_ERROR); 178 } 179 180 if (op->dattr & FILE_FLAG_WRITE_THROUGH) 181 op->create_options |= FILE_WRITE_THROUGH; 182 183 if (op->dattr & FILE_FLAG_DELETE_ON_CLOSE) 184 op->create_options |= FILE_DELETE_ON_CLOSE; 185 186 if (op->dattr & FILE_FLAG_BACKUP_SEMANTICS) 187 op->create_options |= FILE_OPEN_FOR_BACKUP_INTENT; 188 189 if (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT) 190 sr->user_cr = smb_user_getprivcred(sr->uid_user); 191 192 if (op->rootdirfid == 0) { 193 op->fqi.fq_dnode = sr->tid_tree->t_snode; 194 } else { 195 op->dir = smb_ofile_lookup_by_fid(sr, (uint16_t)op->rootdirfid); 196 if (op->dir == NULL) { 197 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 198 ERRDOS, ERRbadfid); 199 return (SDRC_ERROR); 200 } 201 op->fqi.fq_dnode = op->dir->f_node; 202 } 203 204 status = smb_common_open(sr); 205 if (status != NT_STATUS_SUCCESS) { 206 smbsr_status(sr, status, 0, 0); 207 return (SDRC_ERROR); 208 } 209 if (op->op_oplock_level != SMB_OPLOCK_NONE) { 210 /* Oplock req. in op->op_oplock_level etc. */ 211 smb1_oplock_acquire(sr, B_TRUE); 212 } 213 214 /* 215 * NB: after the above smb_common_open() success, 216 * we have a handle allocated (sr->fid_ofile). 217 * If we don't return success, we must close it. 218 */ 219 of = sr->fid_ofile; 220 221 switch (sr->tid_tree->t_res_type & STYPE_MASK) { 222 case STYPE_DISKTREE: 223 case STYPE_PRINTQ: 224 if (op->create_options & FILE_DELETE_ON_CLOSE) 225 smb_ofile_set_delete_on_close(sr, of); 226 DirFlag = smb_node_is_dir(of->f_node) ? 1 : 0; 227 break; 228 229 case STYPE_IPC: 230 DirFlag = 0; 231 break; 232 233 default: 234 smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST, 235 ERRDOS, ERROR_INVALID_FUNCTION); 236 goto errout; 237 } 238 239 if ((op->nt_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE) != 0 && 240 smb_nt_create_enable_extended_response != 0) { 241 uint32_t MaxAccess = 0; 242 if (of->f_node != NULL) { 243 smb_fsop_eaccess(sr, of->f_cr, of->f_node, &MaxAccess); 244 } 245 MaxAccess |= of->f_granted_access; 246 247 rc = smb_mbc_encodef( 248 &xa->rep_param_mb, "bbwllTTTTlqqwwb16.qll", 249 op->op_oplock_level, /* (b) */ 250 1, /* ResponseType (b) */ 251 sr->smb_fid, /* (w) */ 252 op->action_taken, /* (l) */ 253 0, /* EaErrorOffset (l) */ 254 &ap->sa_crtime, /* (T) */ 255 &ap->sa_vattr.va_atime, /* (T) */ 256 &ap->sa_vattr.va_mtime, /* (T) */ 257 &ap->sa_vattr.va_ctime, /* (T) */ 258 op->dattr & FILE_ATTRIBUTE_MASK, /* (l) */ 259 ap->sa_allocsz, /* (q) */ 260 ap->sa_vattr.va_size, /* (q) */ 261 op->ftype, /* (w) */ 262 op->devstate, /* (w) */ 263 DirFlag, /* (b) */ 264 /* volume guid (16.) */ 265 op->fileid, /* (q) */ 266 MaxAccess, /* (l) */ 267 0); /* guest access (l) */ 268 } else { 269 rc = smb_mbc_encodef( 270 &xa->rep_param_mb, "bbwllTTTTlqqwwb", 271 op->op_oplock_level, /* (b) */ 272 0, /* ResponseType (b) */ 273 sr->smb_fid, /* (w) */ 274 op->action_taken, /* (l) */ 275 0, /* EaErrorOffset (l) */ 276 &ap->sa_crtime, /* (T) */ 277 &ap->sa_vattr.va_atime, /* (T) */ 278 &ap->sa_vattr.va_mtime, /* (T) */ 279 &ap->sa_vattr.va_ctime, /* (T) */ 280 op->dattr & FILE_ATTRIBUTE_MASK, /* (l) */ 281 ap->sa_allocsz, /* (q) */ 282 ap->sa_vattr.va_size, /* (q) */ 283 op->ftype, /* (w) */ 284 op->devstate, /* (w) */ 285 DirFlag); /* (b) */ 286 } 287 288 if (rc == 0) 289 return (SDRC_SUCCESS); 290 291 errout: 292 smb_ofile_close(of, 0); 293 return (SDRC_ERROR); 294 } 295