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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * This command is used to create or open a file or directory, when EAs 30 * or an SD must be applied to the file. The functionality is similar 31 * to SmbNtCreateAndx with the option to supply extended attributes or 32 * a security descriptor. 33 * 34 * Note: we don't decode the extended attributes because we don't 35 * support them at this time. 36 */ 37 38 #include <smbsrv/smb_kproto.h> 39 #include <smbsrv/smb_fsops.h> 40 #include <smbsrv/ntstatus.h> 41 #include <smbsrv/ntaccess.h> 42 #include <smbsrv/nterror.h> 43 #include <smbsrv/cifs.h> 44 #include <smbsrv/doserror.h> 45 46 /* 47 * smb_nt_transact_create 48 * 49 * This command is used to create or open a file or directory, when EAs 50 * or an SD must be applied to the file. The request parameter block 51 * encoding, data block encoding and output parameter block encoding are 52 * described in CIFS section 4.2.2. 53 * 54 * The format of the command is SmbNtTransact but it is basically the same 55 * as SmbNtCreateAndx with the option to supply extended attributes or a 56 * security descriptor. For information not defined in CIFS section 4.2.2 57 * see section 4.2.1 (NT_CREATE_ANDX). 58 */ 59 smb_sdrc_t 60 smb_pre_nt_transact_create(smb_request_t *sr, smb_xa_t *xa) 61 { 62 struct open_param *op = &sr->arg.open; 63 uint8_t SecurityFlags; 64 uint32_t EaLength; 65 uint32_t Flags; 66 uint32_t ImpersonationLevel; 67 uint32_t NameLength; 68 uint32_t sd_len; 69 uint32_t status; 70 smb_sd_t sd; 71 int rc; 72 73 bzero(op, sizeof (sr->arg.open)); 74 75 rc = smb_mbc_decodef(&xa->req_param_mb, "%lllqllllllllb", 76 sr, 77 &Flags, 78 &op->rootdirfid, 79 &op->desired_access, 80 &op->dsize, 81 &op->dattr, 82 &op->share_access, 83 &op->create_disposition, 84 &op->create_options, 85 &sd_len, 86 &EaLength, 87 &NameLength, 88 &ImpersonationLevel, 89 &SecurityFlags); 90 91 if (rc == 0) { 92 if (NameLength == 0) { 93 op->fqi.path = "\\"; 94 } else if (NameLength >= MAXPATHLEN) { 95 smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND, 96 ERRDOS, ERROR_PATH_NOT_FOUND); 97 rc = -1; 98 } else { 99 rc = smb_mbc_decodef(&xa->req_param_mb, "%#u", 100 sr, NameLength, &op->fqi.path); 101 } 102 } 103 104 if (Flags) { 105 if (Flags & NT_CREATE_FLAG_REQUEST_OPLOCK) { 106 if (Flags & NT_CREATE_FLAG_REQUEST_OPBATCH) 107 op->my_flags = MYF_BATCH_OPLOCK; 108 else 109 op->my_flags = MYF_EXCLUSIVE_OPLOCK; 110 } 111 112 if (Flags & NT_CREATE_FLAG_OPEN_TARGET_DIR) 113 op->my_flags |= MYF_MUST_BE_DIRECTORY; 114 } 115 116 if (sd_len) { 117 status = smb_decode_sd(xa, &sd); 118 if (status != NT_STATUS_SUCCESS) { 119 smbsr_error(sr, status, 0, 0); 120 return (SDRC_ERROR); 121 } 122 op->sd = kmem_alloc(sizeof (smb_sd_t), KM_SLEEP); 123 *op->sd = sd; 124 } else { 125 op->sd = NULL; 126 } 127 128 DTRACE_SMB_2(op__NtTransactCreate__start, smb_request_t *, sr, 129 struct open_param *, op); 130 131 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 132 } 133 134 void 135 smb_post_nt_transact_create(smb_request_t *sr, smb_xa_t *xa) 136 { 137 smb_sd_t *sd = sr->arg.open.sd; 138 139 DTRACE_SMB_2(op__NtTransactCreate__done, smb_request_t *, sr, 140 smb_xa_t *, xa); 141 142 if (sd) { 143 smb_sd_term(sd); 144 kmem_free(sd, sizeof (smb_sd_t)); 145 } 146 } 147 148 smb_sdrc_t 149 smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa) 150 { 151 struct open_param *op = &sr->arg.open; 152 uint8_t OplockLevel; 153 uint8_t DirFlag; 154 smb_attr_t new_attr; 155 smb_node_t *node; 156 uint32_t status; 157 158 if ((op->create_options & FILE_DELETE_ON_CLOSE) && 159 !(op->desired_access & DELETE)) { 160 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); 161 return (SDRC_ERROR); 162 } 163 164 if (op->dattr & FILE_FLAG_WRITE_THROUGH) 165 op->create_options |= FILE_WRITE_THROUGH; 166 167 if (op->dattr & FILE_FLAG_DELETE_ON_CLOSE) 168 op->create_options |= FILE_DELETE_ON_CLOSE; 169 170 if (op->rootdirfid == 0) { 171 op->fqi.dir_snode = sr->tid_tree->t_snode; 172 } else { 173 sr->smb_fid = (ushort_t)op->rootdirfid; 174 sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, 175 sr->smb_fid); 176 if (sr->fid_ofile == NULL) { 177 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 178 ERRDOS, ERRbadfid); 179 return (SDRC_ERROR); 180 } 181 182 op->fqi.dir_snode = sr->fid_ofile->f_node; 183 smbsr_disconnect_file(sr); 184 } 185 186 status = smb_common_open(sr); 187 188 if (status != NT_STATUS_SUCCESS) 189 return (SDRC_ERROR); 190 191 if (STYPE_ISDSK(sr->tid_tree->t_res_type)) { 192 switch (MYF_OPLOCK_TYPE(op->my_flags)) { 193 case MYF_EXCLUSIVE_OPLOCK : 194 OplockLevel = 1; 195 break; 196 case MYF_BATCH_OPLOCK : 197 OplockLevel = 2; 198 break; 199 case MYF_LEVEL_II_OPLOCK : 200 OplockLevel = 3; 201 break; 202 case MYF_OPLOCK_NONE : 203 default: 204 OplockLevel = 0; 205 break; 206 } 207 208 if (op->create_options & FILE_DELETE_ON_CLOSE) 209 smb_preset_delete_on_close(sr->fid_ofile); 210 211 /* 212 * Set up the directory flag and ensure that 213 * we don't return a stale file size. 214 */ 215 node = sr->fid_ofile->f_node; 216 if (node->attr.sa_vattr.va_type == VDIR) { 217 DirFlag = 1; 218 new_attr.sa_vattr.va_size = 0; 219 } else { 220 DirFlag = 0; 221 new_attr.sa_mask = SMB_AT_SIZE; 222 (void) smb_fsop_getattr(sr, kcred, node, &new_attr); 223 node->attr.sa_vattr.va_size = new_attr.sa_vattr.va_size; 224 } 225 226 (void) smb_mbc_encodef(&xa->rep_param_mb, "b.wllTTTTlqqwwb", 227 OplockLevel, 228 sr->smb_fid, 229 op->action_taken, 230 0, /* EaErrorOffset */ 231 &node->attr.sa_crtime, 232 &node->attr.sa_vattr.va_atime, 233 &node->attr.sa_vattr.va_mtime, 234 &node->attr.sa_vattr.va_ctime, 235 op->dattr & FILE_ATTRIBUTE_MASK, 236 new_attr.sa_vattr.va_size, 237 new_attr.sa_vattr.va_size, 238 op->ftype, 239 op->devstate, 240 DirFlag); 241 } else { 242 /* Named PIPE */ 243 bzero(&new_attr, sizeof (smb_attr_t)); 244 (void) smb_mbc_encodef(&xa->rep_param_mb, "b.wllTTTTlqqwwb", 245 0, 246 sr->smb_fid, 247 op->action_taken, 248 0, /* EaErrorOffset */ 249 &new_attr.sa_crtime, 250 &new_attr.sa_vattr.va_atime, 251 &new_attr.sa_vattr.va_mtime, 252 &new_attr.sa_vattr.va_ctime, 253 op->dattr, 254 0x1000LL, 255 0LL, 256 op->ftype, 257 op->devstate, 258 0); 259 } 260 261 return (SDRC_SUCCESS); 262 } 263