Home | History | Annotate | Download | only in smbsrv
      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 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     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 >= MAXPATHLEN) {
    196 			smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND,
    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 	unsigned char		OplockLevel;
    235 	unsigned char		DirFlag;
    236 	smb_attr_t		attr;
    237 	smb_node_t		*node;
    238 	int rc;
    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->tid_tree,
    269 		    (uint16_t)op->rootdirfid);
    270 		if (op->dir == NULL) {
    271 			smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
    272 			    ERRDOS, ERRbadfid);
    273 			return (SDRC_ERROR);
    274 		}
    275 		op->fqi.fq_dnode = op->dir->f_node;
    276 	}
    277 
    278 	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
    279 		return (SDRC_ERROR);
    280 
    281 	if (STYPE_ISDSK(sr->tid_tree->t_res_type)) {
    282 		switch (op->op_oplock_level) {
    283 		case SMB_OPLOCK_EXCLUSIVE:
    284 			OplockLevel = 1;
    285 			break;
    286 		case SMB_OPLOCK_BATCH:
    287 			OplockLevel = 2;
    288 			break;
    289 		case SMB_OPLOCK_LEVEL_II:
    290 			OplockLevel = 3;
    291 			break;
    292 		case SMB_OPLOCK_NONE:
    293 		default:
    294 			OplockLevel = 0;
    295 			break;
    296 		}
    297 
    298 		if (op->create_options & FILE_DELETE_ON_CLOSE)
    299 			smb_ofile_set_delete_on_close(sr->fid_ofile);
    300 
    301 		node = sr->fid_ofile->f_node;
    302 		DirFlag = smb_node_is_dir(node) ? 1 : 0;
    303 		if (smb_node_getattr(sr, node, &attr) != 0) {
    304 			smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
    305 			    ERRDOS, ERROR_INTERNAL_ERROR);
    306 			return (SDRC_ERROR);
    307 		}
    308 
    309 		rc = smbsr_encode_result(sr, 34, 0, "bb.wbwlTTTTlqqwwbw",
    310 		    34,
    311 		    sr->andx_com,
    312 		    0x67,
    313 		    OplockLevel,
    314 		    sr->smb_fid,
    315 		    op->action_taken,
    316 		    &attr.sa_crtime,
    317 		    &attr.sa_vattr.va_atime,
    318 		    &attr.sa_vattr.va_mtime,
    319 		    &attr.sa_vattr.va_ctime,
    320 		    op->dattr & FILE_ATTRIBUTE_MASK,
    321 		    attr.sa_allocsz,
    322 		    attr.sa_vattr.va_size,
    323 		    op->ftype,
    324 		    op->devstate,
    325 		    DirFlag,
    326 		    0);
    327 	} else {
    328 		/* Named PIPE */
    329 		OplockLevel = 0;
    330 		rc = smbsr_encode_result(sr, 34, 0, "bb.wbwlqqqqlqqwwbw",
    331 		    34,
    332 		    sr->andx_com,
    333 		    0x67,
    334 		    OplockLevel,
    335 		    sr->smb_fid,
    336 		    op->action_taken,
    337 		    0LL,
    338 		    0LL,
    339 		    0LL,
    340 		    0LL,
    341 		    FILE_ATTRIBUTE_NORMAL,
    342 		    0x1000LL,
    343 		    0LL,
    344 		    op->ftype,
    345 		    op->devstate,
    346 		    0,
    347 		    0);
    348 	}
    349 
    350 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
    351 }
    352