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