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