xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c (revision 12890:16985853e3aa)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
22*12890SJoyce.McIntosh@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
235331Samw  */
245331Samw 
255331Samw /*
265331Samw  * This command is used to create or open a file or directory.
275331Samw  */
285331Samw 
295331Samw 
3010966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h>
315331Samw #include <smbsrv/smb_fsops.h>
325331Samw #include <smbsrv/smb_vops.h>
335331Samw 
345331Samw /*
355331Samw  * smb_com_nt_create_andx
365331Samw  *
375331Samw  * This command is used to create or open a file or directory.
385331Samw  *
395331Samw  *  Client Request                     Description
405331Samw  *  =================================  ==================================
415331Samw  *
425331Samw  *  UCHAR WordCount;                   Count of parameter words = 24
435331Samw  *  UCHAR AndXCommand;                 Secondary command;  0xFF = None
445331Samw  *  UCHAR AndXReserved;                Reserved (must be 0)
455331Samw  *  USHORT AndXOffset;                 Offset to next command WordCount
465331Samw  *  UCHAR Reserved;                    Reserved (must be 0)
475331Samw  *  USHORT NameLength;                 Length of Name[] in bytes
485331Samw  *  ULONG Flags;                       Create bit set:
495331Samw  *                                     0x02 - Request an oplock
505331Samw  *                                     0x04 - Request a batch oplock
515331Samw  *                                     0x08 - Target of open must be
525331Samw  *                                     directory
535331Samw  *  ULONG RootDirectoryFid;            If non-zero, open is relative to
545331Samw  *                                     this directory
555331Samw  *  ACCESS_MASK DesiredAccess;         access desired
565331Samw  *  LARGE_INTEGER AllocationSize;      Initial allocation size
575331Samw  *  ULONG ExtFileAttributes;           File attributes
585331Samw  *  ULONG ShareAccess;                 Type of share access
595331Samw  *  ULONG CreateDisposition;           Action to take if file exists or
605331Samw  *                                     not
615331Samw  *  ULONG CreateOptions;               Options to use if creating a file
625331Samw  *  ULONG ImpersonationLevel;          Security QOS information
635331Samw  *  UCHAR SecurityFlags;               Security tracking mode flags:
645331Samw  *                                     0x1 - SECURITY_CONTEXT_TRACKING
655331Samw  *                                     0x2 - SECURITY_EFFECTIVE_ONLY
665331Samw  *  USHORT ByteCount;                  Length of byte parameters
675331Samw  *  STRING Name[];                     File to open or create
685331Samw  *
695331Samw  * The DesiredAccess parameter is specified in section 3.7 on  Access Mask
705331Samw  * Encoding.
715331Samw  *
725331Samw  * If no value is specified, it still allows an application to query
735331Samw  * attributes without actually accessing the file.
745331Samw  *
755331Samw  * The ExtFIleAttributes parameter specifies the file attributes and flags
765331Samw  * for the file. The parameter's value is the sum of allowed attributes and
775331Samw  * flags defined in section 3.11 on  Extended File Attribute Encoding
785331Samw  *
795331Samw  * The ShareAccess field Specifies how this file can be shared. This
805331Samw  * parameter must be some combination of the following values:
815331Samw  *
825331Samw  * Name              Value      Meaning
835331Samw  *                   0          Prevents the file from being shared.
845331Samw  * FILE_SHARE_READ   0x00000001 Other open operations can be performed on
855331Samw  *                               the file for read access.
865331Samw  * FILE_SHARE_WRITE  0x00000002 Other open operations can be performed on
875331Samw  *                               the file for write access.
885331Samw  * FILE_SHARE_DELETE 0x00000004 Other open operations can be performed on
895331Samw  *                               the file for delete access.
905331Samw  *
915331Samw  * The CreateDisposition parameter can contain one of the following values:
925331Samw  *
935331Samw  * CREATE_NEW        Creates a new file. The function fails if the
945331Samw  *                   specified file already exists.
955331Samw  * CREATE_ALWAYS     Creates a new file. The function overwrites the file
965331Samw  *                   if it exists.
975331Samw  * OPEN_EXISTING     Opens the file. The function fails if the file does
985331Samw  *                   not exist.
995331Samw  * OPEN_ALWAYS       Opens the file, if it exists. If the file does not
1005331Samw  *                   exist, act like CREATE_NEW.
1015331Samw  * TRUNCATE_EXISTING Opens the file. Once opened, the file is truncated so
1025331Samw  *                   that its size is zero bytes. The calling process must
1035331Samw  *                   open the file with at least GENERIC_WRITE access. The
1045331Samw  *                   function fails if the file does not exist.
1055331Samw  *
1065331Samw  * The ImpersonationLevel parameter can contain one or more of the
1075331Samw  * following values:
1085331Samw  *
1095331Samw  * SECURITY_ANONYMOUS        Specifies to impersonate the client at the
1105331Samw  *                           Anonymous impersonation level.
1115331Samw  * SECURITY_IDENTIFICATION   Specifies to impersonate the client at the
1125331Samw  *                           Identification impersonation level.
1135331Samw  * SECURITY_IMPERSONATION    Specifies to impersonate the client at the
1145331Samw  *                           Impersonation impersonation level.
1155331Samw  * SECURITY_DELEGATION       Specifies to impersonate the client at the
1165331Samw  *                           Delegation impersonation level.
1175331Samw  *
1185331Samw  * The SecurityFlags parameter can have either of the following two flags
1195331Samw  * set:
1205331Samw  *
1215331Samw  * SECURITY_CONTEXT_TRACKING  Specifies that the security tracking mode is
1225331Samw  *                            dynamic. If this flag is not specified,
1235331Samw  *                            Security Tracking Mode is static.
1245331Samw  * SECURITY_EFFECTIVE_ONLY    Specifies that only the enabled aspects of
1255331Samw  *                            the client's security context are available
1265331Samw  *                            to the server. If you do not specify this
1275331Samw  *                            flag, all aspects of the client's security
1285331Samw  *                            context are available. This flag allows the
1295331Samw  *                            client to limit the groups and privileges
1305331Samw  *                            that a server can use while impersonating the
1315331Samw  *                            client.
1325331Samw  *
1335331Samw  * The response is as follows:
1345331Samw  *
1355331Samw  *  Server Response                    Description
1365331Samw  *  =================================  ==================================
1375331Samw  *
1385331Samw  *  UCHAR WordCount;                   Count of parameter words = 26
1395331Samw  *  UCHAR AndXCommand;  Secondary      0xFF = None
1405331Samw  *  command;
1415331Samw  *  UCHAR AndXReserved;                MBZ
1425331Samw  *  USHORT AndXOffset;                 Offset to next command WordCount
1435331Samw  *  UCHAR OplockLevel;                 The oplock level granted
1445331Samw  *                                     0 - No oplock granted
1455331Samw  *                                     1 - Exclusive oplock granted
1465331Samw  *                                     2 - Batch oplock granted
1475331Samw  *                                     3 - Level II oplock granted
1485331Samw  *  USHORT Fid;                        The file ID
1495331Samw  *  ULONG CreateAction;                The action taken
1505331Samw  *  TIME CreationTime;                 The time the file was created
1515331Samw  *  TIME LastAccessTime;               The time the file was accessed
1525331Samw  *  TIME LastWriteTime;                The time the file was last written
1535331Samw  *  TIME ChangeTime;                   The time the file was last changed
1545331Samw  *  ULONG ExtFileAttributes;           The file attributes
1555331Samw  *  LARGE_INTEGER AllocationSize;      The number of bytes allocated
1565331Samw  *  LARGE_INTEGER EndOfFile;           The end of file offset
1575331Samw  *  USHORT FileType;
1585331Samw  *  USHORT DeviceState;                state of IPC device (e.g. pipe)
1595331Samw  *  BOOLEAN Directory;                 TRUE if this is a directory
1605331Samw  *  USHORT ByteCount;                  = 0
1615331Samw  *
1625331Samw  * The following SMBs may follow SMB_COM_NT_CREATE_ANDX:
1635331Samw  *
1645331Samw  *    SMB_COM_READ    SMB_COM_READ_ANDX
1655331Samw  *    SMB_COM_IOCTL
1665331Samw  */
1676030Sjb150015 smb_sdrc_t
smb_pre_nt_create_andx(smb_request_t * sr)1686139Sjb150015 smb_pre_nt_create_andx(smb_request_t *sr)
1695331Samw {
1706139Sjb150015 	struct open_param *op = &sr->arg.open;
1716139Sjb150015 	uint8_t SecurityFlags;
1726139Sjb150015 	uint32_t ImpersonationLevel;
1736139Sjb150015 	uint16_t NameLength;
1745331Samw 	int rc;
1755331Samw 
1766139Sjb150015 	bzero(op, sizeof (sr->arg.open));
1775331Samw 
1785331Samw 	rc = smbsr_decode_vwv(sr, "5.wlllqlllllb",
1795331Samw 	    &NameLength,
1808934SJose.Borrego@Sun.COM 	    &op->nt_flags,
1816139Sjb150015 	    &op->rootdirfid,
1825331Samw 	    &op->desired_access,
1835331Samw 	    &op->dsize,
1846139Sjb150015 	    &op->dattr,
1855331Samw 	    &op->share_access,
1865331Samw 	    &op->create_disposition,
1875331Samw 	    &op->create_options,
1885331Samw 	    &ImpersonationLevel,
1895331Samw 	    &SecurityFlags);
1905331Samw 
1916139Sjb150015 	if (rc == 0) {
1926139Sjb150015 		if (NameLength == 0) {
1939343SAfshin.Ardakani@Sun.COM 			op->fqi.fq_path.pn_path = "\\";
1946139Sjb150015 		} else if (NameLength >= MAXPATHLEN) {
1956139Sjb150015 			smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND,
1966139Sjb150015 			    ERRDOS, ERROR_PATH_NOT_FOUND);
1976139Sjb150015 			rc = -1;
1986139Sjb150015 		} else {
1996139Sjb150015 			rc = smbsr_decode_data(sr, "%#u", sr, NameLength,
2009343SAfshin.Ardakani@Sun.COM 			    &op->fqi.fq_path.pn_path);
2016139Sjb150015 		}
2025331Samw 	}
2035331Samw 
2048934SJose.Borrego@Sun.COM 	op->op_oplock_level = SMB_OPLOCK_NONE;
2058934SJose.Borrego@Sun.COM 	if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPLOCK) {
2068934SJose.Borrego@Sun.COM 		if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPBATCH)
2078934SJose.Borrego@Sun.COM 			op->op_oplock_level = SMB_OPLOCK_BATCH;
2088934SJose.Borrego@Sun.COM 		else
2098934SJose.Borrego@Sun.COM 			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
2105331Samw 	}
2115331Samw 
2126139Sjb150015 	DTRACE_SMB_2(op__NtCreateX__start, smb_request_t *, sr,
2136139Sjb150015 	    struct open_param *, op);
2146139Sjb150015 
2156139Sjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
2166139Sjb150015 }
2176139Sjb150015 
2186139Sjb150015 void
smb_post_nt_create_andx(smb_request_t * sr)2196139Sjb150015 smb_post_nt_create_andx(smb_request_t *sr)
2206139Sjb150015 {
2216139Sjb150015 	DTRACE_SMB_1(op__NtCreateX__done, smb_request_t *, sr);
22210966SJordan.Brown@Sun.COM 
22310966SJordan.Brown@Sun.COM 	if (sr->arg.open.dir != NULL) {
22410966SJordan.Brown@Sun.COM 		smb_ofile_release(sr->arg.open.dir);
22510966SJordan.Brown@Sun.COM 		sr->arg.open.dir = NULL;
22610966SJordan.Brown@Sun.COM 	}
2276139Sjb150015 }
2286139Sjb150015 
2296139Sjb150015 smb_sdrc_t
smb_com_nt_create_andx(struct smb_request * sr)2306139Sjb150015 smb_com_nt_create_andx(struct smb_request *sr)
2316139Sjb150015 {
2326139Sjb150015 	struct open_param	*op = &sr->arg.open;
2336139Sjb150015 	unsigned char		DirFlag;
23410001SJoyce.McIntosh@Sun.COM 	smb_attr_t		attr;
2356139Sjb150015 	smb_node_t		*node;
2366139Sjb150015 	int rc;
2376139Sjb150015 
2386139Sjb150015 	if ((op->create_options & FILE_DELETE_ON_CLOSE) &&
2396139Sjb150015 	    !(op->desired_access & DELETE)) {
2408934SJose.Borrego@Sun.COM 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
2418934SJose.Borrego@Sun.COM 		    ERRDOS, ERRbadaccess);
2428934SJose.Borrego@Sun.COM 		return (SDRC_ERROR);
2438934SJose.Borrego@Sun.COM 	}
2448934SJose.Borrego@Sun.COM 
2458934SJose.Borrego@Sun.COM 	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
2468934SJose.Borrego@Sun.COM 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
2478934SJose.Borrego@Sun.COM 		    ERRDOS, ERRbadaccess);
2486139Sjb150015 		return (SDRC_ERROR);
2496139Sjb150015 	}
2506139Sjb150015 
2516139Sjb150015 	if (op->dattr & FILE_FLAG_WRITE_THROUGH)
2525331Samw 		op->create_options |= FILE_WRITE_THROUGH;
2535331Samw 
2546139Sjb150015 	if (op->dattr & FILE_FLAG_DELETE_ON_CLOSE)
2555331Samw 		op->create_options |= FILE_DELETE_ON_CLOSE;
2565331Samw 
2577961SNatalie.Li@Sun.COM 	if (op->dattr & FILE_FLAG_BACKUP_SEMANTICS)
2587961SNatalie.Li@Sun.COM 		op->create_options |= FILE_OPEN_FOR_BACKUP_INTENT;
2597961SNatalie.Li@Sun.COM 
2607961SNatalie.Li@Sun.COM 	if (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT)
2617961SNatalie.Li@Sun.COM 		sr->user_cr = smb_user_getprivcred(sr->uid_user);
2627961SNatalie.Li@Sun.COM 
2636139Sjb150015 	if (op->rootdirfid == 0) {
2649343SAfshin.Ardakani@Sun.COM 		op->fqi.fq_dnode = sr->tid_tree->t_snode;
2655331Samw 	} else {
26610966SJordan.Brown@Sun.COM 		op->dir = smb_ofile_lookup_by_fid(sr->tid_tree,
26710966SJordan.Brown@Sun.COM 		    (uint16_t)op->rootdirfid);
26810966SJordan.Brown@Sun.COM 		if (op->dir == NULL) {
2695772Sas200622 			smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
2705331Samw 			    ERRDOS, ERRbadfid);
2716139Sjb150015 			return (SDRC_ERROR);
2725331Samw 		}
27310966SJordan.Brown@Sun.COM 		op->fqi.fq_dnode = op->dir->f_node;
2745331Samw 	}
2755331Samw 
276*12890SJoyce.McIntosh@Sun.COM 	op->op_oplock_levelII = B_TRUE;
277*12890SJoyce.McIntosh@Sun.COM 
2786030Sjb150015 	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
2796139Sjb150015 		return (SDRC_ERROR);
2805331Samw 
28111447Samw@Sun.COM 	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
28211447Samw@Sun.COM 	case STYPE_DISKTREE:
28311447Samw@Sun.COM 	case STYPE_PRINTQ:
2845331Samw 		if (op->create_options & FILE_DELETE_ON_CLOSE)
2859231SAfshin.Ardakani@Sun.COM 			smb_ofile_set_delete_on_close(sr->fid_ofile);
2865331Samw 
2875331Samw 		node = sr->fid_ofile->f_node;
28810001SJoyce.McIntosh@Sun.COM 		DirFlag = smb_node_is_dir(node) ? 1 : 0;
28910001SJoyce.McIntosh@Sun.COM 		if (smb_node_getattr(sr, node, &attr) != 0) {
29010001SJoyce.McIntosh@Sun.COM 			smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
29110001SJoyce.McIntosh@Sun.COM 			    ERRDOS, ERROR_INTERNAL_ERROR);
29210001SJoyce.McIntosh@Sun.COM 			return (SDRC_ERROR);
2935331Samw 		}
2945331Samw 
2956030Sjb150015 		rc = smbsr_encode_result(sr, 34, 0, "bb.wbwlTTTTlqqwwbw",
2965331Samw 		    34,
2975331Samw 		    sr->andx_com,
2985331Samw 		    0x67,
299*12890SJoyce.McIntosh@Sun.COM 		    op->op_oplock_level,
3005331Samw 		    sr->smb_fid,
3015331Samw 		    op->action_taken,
30210001SJoyce.McIntosh@Sun.COM 		    &attr.sa_crtime,
30310001SJoyce.McIntosh@Sun.COM 		    &attr.sa_vattr.va_atime,
30410001SJoyce.McIntosh@Sun.COM 		    &attr.sa_vattr.va_mtime,
30510001SJoyce.McIntosh@Sun.COM 		    &attr.sa_vattr.va_ctime,
3065331Samw 		    op->dattr & FILE_ATTRIBUTE_MASK,
30710504SKeyur.Desai@Sun.COM 		    attr.sa_allocsz,
30810001SJoyce.McIntosh@Sun.COM 		    attr.sa_vattr.va_size,
3095331Samw 		    op->ftype,
3105331Samw 		    op->devstate,
3115331Samw 		    DirFlag,
3125331Samw 		    0);
31311447Samw@Sun.COM 		break;
31411447Samw@Sun.COM 
31511447Samw@Sun.COM 	case STYPE_IPC:
3166030Sjb150015 		rc = smbsr_encode_result(sr, 34, 0, "bb.wbwlqqqqlqqwwbw",
3175331Samw 		    34,
3185331Samw 		    sr->andx_com,
3195331Samw 		    0x67,
320*12890SJoyce.McIntosh@Sun.COM 		    0,
3215331Samw 		    sr->smb_fid,
3225331Samw 		    op->action_taken,
3235331Samw 		    0LL,
3245331Samw 		    0LL,
3255331Samw 		    0LL,
3265331Samw 		    0LL,
3277052Samw 		    FILE_ATTRIBUTE_NORMAL,
3285331Samw 		    0x1000LL,
3295331Samw 		    0LL,
3305331Samw 		    op->ftype,
3315331Samw 		    op->devstate,
3325331Samw 		    0,
3335331Samw 		    0);
33411447Samw@Sun.COM 		break;
33511447Samw@Sun.COM 
33611447Samw@Sun.COM 	default:
33711447Samw@Sun.COM 		smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
33811447Samw@Sun.COM 		    ERRDOS, ERROR_INVALID_FUNCTION);
33911447Samw@Sun.COM 		return (SDRC_ERROR);
3405331Samw 	}
3415331Samw 
3426139Sjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
3435331Samw }
344