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 2007 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/smbvar.h> 39 #include <smbsrv/smb_kproto.h> 40 #include <smbsrv/smb_fsops.h> 41 #include <smbsrv/ntstatus.h> 42 #include <smbsrv/ntaccess.h> 43 #include <smbsrv/nterror.h> 44 #include <smbsrv/ntifs.h> 45 #include <smbsrv/cifs.h> 46 #include <smbsrv/doserror.h> 47 48 /* 49 * smb_nt_transact_create 50 * 51 * This command is used to create or open a file or directory, when EAs 52 * or an SD must be applied to the file. The request parameter block 53 * encoding, data block encoding and output parameter block encoding are 54 * described in CIFS section 4.2.2. 55 * 56 * The format of the command is SmbNtTransact but it is basically the same 57 * as SmbNtCreateAndx with the option to supply extended attributes or a 58 * security descriptor. For information not defined in CIFS section 4.2.2 59 * see section 4.2.1 (NT_CREATE_ANDX). 60 */ 61 int 62 smb_nt_transact_create(struct smb_request *sr, struct smb_xa *xa) 63 { 64 struct open_param *op = &sr->arg.open; 65 uint8_t OplockLevel; 66 uint8_t DirFlag; 67 uint8_t SecurityFlags; 68 uint32_t ExtFileAttributes; 69 uint32_t sd_len; 70 uint32_t EaLength; 71 uint32_t Flags; 72 uint32_t ImpersonationLevel; 73 uint32_t RootDirFid; 74 uint32_t NameLength; 75 smb_attr_t new_attr; 76 smb_node_t *node; 77 smb_sd_t sd; 78 DWORD status; 79 int rc; 80 81 rc = smb_decode_mbc(&xa->req_param_mb, "%lllqllllllllb", 82 sr, 83 &Flags, 84 &RootDirFid, 85 &op->desired_access, 86 &op->dsize, 87 &ExtFileAttributes, 88 &op->share_access, 89 &op->create_disposition, 90 &op->create_options, 91 &sd_len, 92 &EaLength, 93 &NameLength, 94 &ImpersonationLevel, 95 &SecurityFlags); 96 97 if (rc != 0) { 98 smbsr_decode_error(sr); 99 /* NOTREACHED */ 100 } 101 102 /* 103 * If name length is zero, interpret as "\". 104 */ 105 if (NameLength == 0) { 106 op->fqi.path = "\\"; 107 } else { 108 rc = smb_decode_mbc(&xa->req_param_mb, "%#u", 109 sr, NameLength, &op->fqi.path); 110 if (rc != 0) { 111 smbsr_decode_error(sr); 112 /* NOTREACHED */ 113 } 114 } 115 116 if ((op->create_options & FILE_DELETE_ON_CLOSE) && 117 !(op->desired_access & DELETE)) { 118 smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); 119 /* NOTREACHED */ 120 } 121 122 if (sd_len) { 123 status = smb_decode_sd(xa, &sd); 124 if (status != NT_STATUS_SUCCESS) { 125 smbsr_raise_nt_error(sr, status); 126 /* NOTREACHED */ 127 } 128 op->sd = &sd; 129 } else { 130 op->sd = NULL; 131 } 132 133 op->fqi.srch_attr = 0; 134 op->omode = 0; 135 136 op->utime.tv_sec = op->utime.tv_nsec = 0; 137 op->my_flags = 0; 138 139 op->dattr = ExtFileAttributes; 140 141 if (Flags) { 142 if (Flags & NT_CREATE_FLAG_REQUEST_OPLOCK) { 143 if (Flags & NT_CREATE_FLAG_REQUEST_OPBATCH) { 144 op->my_flags = MYF_BATCH_OPLOCK; 145 } else { 146 op->my_flags = MYF_EXCLUSIVE_OPLOCK; 147 } 148 } 149 if (Flags & NT_CREATE_FLAG_OPEN_TARGET_DIR) 150 op->my_flags |= MYF_MUST_BE_DIRECTORY; 151 } 152 153 if (ExtFileAttributes & FILE_FLAG_WRITE_THROUGH) 154 op->create_options |= FILE_WRITE_THROUGH; 155 156 if (ExtFileAttributes & FILE_FLAG_DELETE_ON_CLOSE) 157 op->create_options |= FILE_DELETE_ON_CLOSE; 158 159 if (RootDirFid == 0) { 160 op->fqi.dir_snode = sr->tid_tree->t_snode; 161 } else { 162 sr->smb_fid = (ushort_t)RootDirFid; 163 sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, 164 sr->smb_fid); 165 /* 166 * XXX: ASSERT() for now but we should understand if the test 167 * of the return value is missing because it cannot happen. 168 */ 169 ASSERT(sr->fid_ofile != NULL); 170 op->fqi.dir_snode = sr->fid_ofile->f_node; 171 smbsr_disconnect_file(sr); 172 } 173 174 status = smb_open_subr(sr); 175 if (op->sd) 176 smb_sd_term(op->sd); 177 178 if (status != NT_STATUS_SUCCESS) { 179 if (status == NT_STATUS_SHARING_VIOLATION) 180 smbsr_raise_cifs_error(sr, 181 NT_STATUS_SHARING_VIOLATION, 182 ERRDOS, ERROR_SHARING_VIOLATION); 183 else 184 smbsr_raise_nt_error(sr, status); 185 186 /* NOTREACHED */ 187 } 188 189 if (STYPE_ISDSK(sr->tid_tree->t_res_type)) { 190 switch (MYF_OPLOCK_TYPE(op->my_flags)) { 191 case MYF_EXCLUSIVE_OPLOCK : 192 OplockLevel = 1; 193 break; 194 case MYF_BATCH_OPLOCK : 195 OplockLevel = 2; 196 break; 197 case MYF_LEVEL_II_OPLOCK : 198 OplockLevel = 3; 199 break; 200 case MYF_OPLOCK_NONE : 201 default: 202 OplockLevel = 0; 203 break; 204 } 205 206 if (op->create_options & FILE_DELETE_ON_CLOSE) 207 smb_preset_delete_on_close(sr->fid_ofile); 208 209 /* 210 * Set up the directory flag and ensure that 211 * we don't return a stale file size. 212 */ 213 node = sr->fid_ofile->f_node; 214 if (node->attr.sa_vattr.va_type == VDIR) { 215 DirFlag = 1; 216 new_attr.sa_vattr.va_size = 0; 217 } else { 218 DirFlag = 0; 219 new_attr.sa_mask = SMB_AT_SIZE; 220 (void) smb_fsop_getattr(sr, kcred, node, &new_attr); 221 node->attr.sa_vattr.va_size = new_attr.sa_vattr.va_size; 222 } 223 224 (void) smb_encode_mbc(&xa->rep_param_mb, "b.wllTTTTlqqwwb", 225 OplockLevel, 226 sr->smb_fid, 227 op->action_taken, 228 0, /* EaErrorOffset */ 229 &node->attr.sa_crtime, 230 &node->attr.sa_vattr.va_atime, 231 &node->attr.sa_vattr.va_mtime, 232 &node->attr.sa_vattr.va_ctime, 233 op->dattr & FILE_ATTRIBUTE_MASK, 234 new_attr.sa_vattr.va_size, 235 new_attr.sa_vattr.va_size, 236 op->ftype, 237 op->devstate, 238 DirFlag); 239 } else { 240 /* Named PIPE */ 241 (void) smb_encode_mbc(&xa->rep_param_mb, "b.wllTTTTlqqwwb", 242 0, 243 sr->smb_fid, 244 op->action_taken, 245 0, /* EaErrorOffset */ 246 0LL, 247 0LL, 248 0LL, 249 0LL, 250 op->dattr, 251 0x1000LL, 252 0LL, 253 op->ftype, 254 op->devstate, 255 0); 256 } 257 258 return (SDRC_NORMAL_REPLY); 259 } 260