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 2014 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * This command is used to create or open a file or directory.
  28  */
  29 
  30 
  31 #include <smbsrv/smb_kproto.h>
  32 #include <smbsrv/smb_fsops.h>
  33 #include <smbsrv/smb_vops.h>
  34 
  35 /*
  36  * smb_com_nt_create_andx
  37  *
  38  * This command is used to create or open a file or directory.
  39  *
  40  *  Client Request                     Description
  41  *  =================================  ==================================
  42  *
  43  *  UCHAR WordCount;                   Count of parameter words = 24
  44  *  UCHAR AndXCommand;                 Secondary command;  0xFF = None
  45  *  UCHAR AndXReserved;                Reserved (must be 0)
  46  *  USHORT AndXOffset;                 Offset to next command WordCount
  47  *  UCHAR Reserved;                    Reserved (must be 0)
  48  *  USHORT NameLength;                 Length of Name[] in bytes
  49  *  ULONG Flags;                       Create bit set:
  50  *                                     0x02 - Request an oplock
  51  *                                     0x04 - Request a batch oplock
  52  *                                     0x08 - Target of open must be
  53  *                                     directory
  54  *  ULONG RootDirectoryFid;            If non-zero, open is relative to
  55  *                                     this directory
  56  *  ACCESS_MASK DesiredAccess;         access desired
  57  *  LARGE_INTEGER AllocationSize;      Initial allocation size
  58  *  ULONG ExtFileAttributes;           File attributes
  59  *  ULONG ShareAccess;                 Type of share access
  60  *  ULONG CreateDisposition;           Action to take if file exists or
  61  *                                     not
  62  *  ULONG CreateOptions;               Options to use if creating a file
  63  *  ULONG ImpersonationLevel;          Security QOS information
  64  *  UCHAR SecurityFlags;               Security tracking mode flags:
  65  *                                     0x1 - SECURITY_CONTEXT_TRACKING
  66  *                                     0x2 - SECURITY_EFFECTIVE_ONLY
  67  *  USHORT ByteCount;                  Length of byte parameters
  68  *  STRING Name[];                     File to open or create
  69  *
  70  * The DesiredAccess parameter is specified in section 3.7 on  Access Mask
  71  * Encoding.
  72  *
  73  * If no value is specified, it still allows an application to query
  74  * attributes without actually accessing the file.
  75  *
  76  * The ExtFIleAttributes parameter specifies the file attributes and flags
  77  * for the file. The parameter's value is the sum of allowed attributes and
  78  * flags defined in section 3.11 on  Extended File Attribute Encoding
  79  *
  80  * The ShareAccess field Specifies how this file can be shared. This
  81  * parameter must be some combination of the following values:
  82  *
  83  * Name              Value      Meaning
  84  *                   0          Prevents the file from being shared.
  85  * FILE_SHARE_READ   0x00000001 Other open operations can be performed on
  86  *                               the file for read access.
  87  * FILE_SHARE_WRITE  0x00000002 Other open operations can be performed on
  88  *                               the file for write access.
  89  * FILE_SHARE_DELETE 0x00000004 Other open operations can be performed on
  90  *                               the file for delete access.
  91  *
  92  * The CreateDisposition parameter can contain one of the following values:
  93  *
  94  * CREATE_NEW        Creates a new file. The function fails if the
  95  *                   specified file already exists.
  96  * CREATE_ALWAYS     Creates a new file. The function overwrites the file
  97  *                   if it exists.
  98  * OPEN_EXISTING     Opens the file. The function fails if the file does
  99  *                   not exist.
 100  * OPEN_ALWAYS       Opens the file, if it exists. If the file does not
 101  *                   exist, act like CREATE_NEW.
 102  * TRUNCATE_EXISTING Opens the file. Once opened, the file is truncated so
 103  *                   that its size is zero bytes. The calling process must
 104  *                   open the file with at least GENERIC_WRITE access. The
 105  *                   function fails if the file does not exist.
 106  *
 107  * The ImpersonationLevel parameter can contain one or more of the
 108  * following values:
 109  *
 110  * SECURITY_ANONYMOUS        Specifies to impersonate the client at the
 111  *                           Anonymous impersonation level.
 112  * SECURITY_IDENTIFICATION   Specifies to impersonate the client at the
 113  *                           Identification impersonation level.
 114  * SECURITY_IMPERSONATION    Specifies to impersonate the client at the
 115  *                           Impersonation impersonation level.
 116  * SECURITY_DELEGATION       Specifies to impersonate the client at the
 117  *                           Delegation impersonation level.
 118  *
 119  * The SecurityFlags parameter can have either of the following two flags
 120  * set:
 121  *
 122  * SECURITY_CONTEXT_TRACKING  Specifies that the security tracking mode is
 123  *                            dynamic. If this flag is not specified,
 124  *                            Security Tracking Mode is static.
 125  * SECURITY_EFFECTIVE_ONLY    Specifies that only the enabled aspects of
 126  *                            the client's security context are available
 127  *                            to the server. If you do not specify this
 128  *                            flag, all aspects of the client's security
 129  *                            context are available. This flag allows the
 130  *                            client to limit the groups and privileges
 131  *                            that a server can use while impersonating the
 132  *                            client.
 133  *
 134  * The response is as follows:
 135  *
 136  *  Server Response                    Description
 137  *  =================================  ==================================
 138  *
 139  *  UCHAR WordCount;                   Count of parameter words = 26
 140  *  UCHAR AndXCommand;  Secondary      0xFF = None
 141  *  command;
 142  *  UCHAR AndXReserved;                MBZ
 143  *  USHORT AndXOffset;                 Offset to next command WordCount
 144  *  UCHAR OplockLevel;                 The oplock level granted
 145  *                                     0 - No oplock granted
 146  *                                     1 - Exclusive oplock granted
 147  *                                     2 - Batch oplock granted
 148  *                                     3 - Level II oplock granted
 149  *  USHORT Fid;                        The file ID
 150  *  ULONG CreateAction;                The action taken
 151  *  TIME CreationTime;                 The time the file was created
 152  *  TIME LastAccessTime;               The time the file was accessed
 153  *  TIME LastWriteTime;                The time the file was last written
 154  *  TIME ChangeTime;                   The time the file was last changed
 155  *  ULONG ExtFileAttributes;           The file attributes
 156  *  LARGE_INTEGER AllocationSize;      The number of bytes allocated
 157  *  LARGE_INTEGER EndOfFile;           The end of file offset
 158  *  USHORT FileType;
 159  *  USHORT DeviceState;                state of IPC device (e.g. pipe)
 160  *  BOOLEAN Directory;                 TRUE if this is a directory
 161  *  USHORT ByteCount;                  = 0
 162  *
 163  * The following SMBs may follow SMB_COM_NT_CREATE_ANDX:
 164  *
 165  *    SMB_COM_READ    SMB_COM_READ_ANDX
 166  *    SMB_COM_IOCTL
 167  */
 168 smb_sdrc_t
 169 smb_pre_nt_create_andx(smb_request_t *sr)
 170 {
 171         struct open_param *op = &sr->arg.open;
 172         uint8_t SecurityFlags;
 173         uint32_t ImpersonationLevel;
 174         uint16_t NameLength;
 175         int rc;
 176 
 177         bzero(op, sizeof (sr->arg.open));
 178 
 179         rc = smbsr_decode_vwv(sr, "5.wlllqlllllb",
 180             &NameLength,
 181             &op->nt_flags,
 182             &op->rootdirfid,
 183             &op->desired_access,
 184             &op->dsize,
 185             &op->dattr,
 186             &op->share_access,
 187             &op->create_disposition,
 188             &op->create_options,
 189             &ImpersonationLevel,
 190             &SecurityFlags);
 191 
 192         if (rc == 0) {
 193                 if (NameLength == 0) {
 194                         op->fqi.fq_path.pn_path = "\\";
 195                 } else if (NameLength >= SMB_MAXPATHLEN) {
 196                         smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
 197                             ERRDOS, ERROR_PATH_NOT_FOUND);
 198                         rc = -1;
 199                 } else {
 200                         rc = smbsr_decode_data(sr, "%#u", sr, NameLength,
 201                             &op->fqi.fq_path.pn_path);
 202                 }
 203         }
 204 
 205         op->op_oplock_level = SMB_OPLOCK_NONE;
 206         if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPLOCK) {
 207                 if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPBATCH)
 208                         op->op_oplock_level = SMB_OPLOCK_BATCH;
 209                 else
 210                         op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
 211         }
 212 
 213         DTRACE_SMB_2(op__NtCreateX__start, smb_request_t *, sr,
 214             struct open_param *, op);
 215 
 216         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 217 }
 218 
 219 void
 220 smb_post_nt_create_andx(smb_request_t *sr)
 221 {
 222         DTRACE_SMB_1(op__NtCreateX__done, smb_request_t *, sr);
 223 
 224         if (sr->arg.open.dir != NULL) {
 225                 smb_ofile_release(sr->arg.open.dir);
 226                 sr->arg.open.dir = NULL;
 227         }
 228 }
 229 
 230 smb_sdrc_t
 231 smb_com_nt_create_andx(struct smb_request *sr)
 232 {
 233         struct open_param       *op = &sr->arg.open;
 234         smb_attr_t              *ap = &op->fqi.fq_fattr;
 235         smb_ofile_t             *of;
 236         int                     rc;
 237         unsigned char           DirFlag;
 238         uint32_t                status;
 239 
 240         if ((op->create_options & FILE_DELETE_ON_CLOSE) &&
 241             !(op->desired_access & DELETE)) {
 242                 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
 243                     ERRDOS, ERRbadaccess);
 244                 return (SDRC_ERROR);
 245         }
 246 
 247         if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
 248                 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
 249                     ERRDOS, ERRbadaccess);
 250                 return (SDRC_ERROR);
 251         }
 252 
 253         if (op->dattr & FILE_FLAG_WRITE_THROUGH)
 254                 op->create_options |= FILE_WRITE_THROUGH;
 255 
 256         if (op->dattr & FILE_FLAG_DELETE_ON_CLOSE)
 257                 op->create_options |= FILE_DELETE_ON_CLOSE;
 258 
 259         if (op->dattr & FILE_FLAG_BACKUP_SEMANTICS)
 260                 op->create_options |= FILE_OPEN_FOR_BACKUP_INTENT;
 261 
 262         if (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT)
 263                 sr->user_cr = smb_user_getprivcred(sr->uid_user);
 264 
 265         if (op->rootdirfid == 0) {
 266                 op->fqi.fq_dnode = sr->tid_tree->t_snode;
 267         } else {
 268                 op->dir = smb_ofile_lookup_by_fid(sr, (uint16_t)op->rootdirfid);
 269                 if (op->dir == NULL) {
 270                         smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
 271                             ERRDOS, ERRbadfid);
 272                         return (SDRC_ERROR);
 273                 }
 274                 op->fqi.fq_dnode = op->dir->f_node;
 275         }
 276 
 277         op->op_oplock_levelII = B_TRUE;
 278 
 279         status = smb_common_open(sr);
 280         if (status != NT_STATUS_SUCCESS) {
 281                 smbsr_status(sr, status, 0, 0);
 282                 return (SDRC_ERROR);
 283         }
 284 
 285         /*
 286          * NB: after the above smb_common_open() success,
 287          * we have a handle allocated (sr->fid_ofile).
 288          * If we don't return success, we must close it.
 289          */
 290         of = sr->fid_ofile;
 291 
 292         switch (sr->tid_tree->t_res_type & STYPE_MASK) {
 293         case STYPE_DISKTREE:
 294         case STYPE_PRINTQ:
 295                 if (op->create_options & FILE_DELETE_ON_CLOSE)
 296                         smb_ofile_set_delete_on_close(of);
 297 
 298                 DirFlag = smb_node_is_dir(of->f_node) ? 1 : 0;
 299                 rc = smbsr_encode_result(sr, 34, 0, "bb.wbwlTTTTlqqwwbw",
 300                     34,
 301                     sr->andx_com,
 302                     0x67,
 303                     op->op_oplock_level,
 304                     sr->smb_fid,
 305                     op->action_taken,
 306                     &ap->sa_crtime,
 307                     &ap->sa_vattr.va_atime,
 308                     &ap->sa_vattr.va_mtime,
 309                     &ap->sa_vattr.va_ctime,
 310                     op->dattr & FILE_ATTRIBUTE_MASK,
 311                     ap->sa_allocsz,
 312                     ap->sa_vattr.va_size,
 313                     op->ftype,
 314                     op->devstate,
 315                     DirFlag,
 316                     0);
 317                 break;
 318 
 319         case STYPE_IPC:
 320                 rc = smbsr_encode_result(sr, 34, 0, "bb.wbwlqqqqlqqwwbw",
 321                     34,
 322                     sr->andx_com,
 323                     0x67,
 324                     0,
 325                     sr->smb_fid,
 326                     op->action_taken,
 327                     0LL,
 328                     0LL,
 329                     0LL,
 330                     0LL,
 331                     FILE_ATTRIBUTE_NORMAL,
 332                     0x1000LL,
 333                     0LL,
 334                     op->ftype,
 335                     op->devstate,
 336                     0,
 337                     0);
 338                 break;
 339 
 340         default:
 341                 smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
 342                     ERRDOS, ERROR_INVALID_FUNCTION);
 343                 goto errout;
 344         }
 345         if (rc == 0)
 346                 return (SDRC_SUCCESS);
 347 
 348 errout:
 349         smb_ofile_close(of, 0);
 350         return (SDRC_ERROR);
 351 }