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, when EAs
275331Samw * or an SD must be applied to the file. The functionality is similar
285331Samw * to SmbNtCreateAndx with the option to supply extended attributes or
295331Samw * a security descriptor.
305331Samw *
315331Samw * Note: we don't decode the extended attributes because we don't
325331Samw * support them at this time.
335331Samw */
345331Samw
355521Sas200622 #include <smbsrv/smb_kproto.h>
365331Samw #include <smbsrv/smb_fsops.h>
375331Samw
385331Samw /*
395331Samw * smb_nt_transact_create
405331Samw *
415331Samw * This command is used to create or open a file or directory, when EAs
425331Samw * or an SD must be applied to the file. The request parameter block
435331Samw * encoding, data block encoding and output parameter block encoding are
445331Samw * described in CIFS section 4.2.2.
455331Samw *
465331Samw * The format of the command is SmbNtTransact but it is basically the same
475331Samw * as SmbNtCreateAndx with the option to supply extended attributes or a
485331Samw * security descriptor. For information not defined in CIFS section 4.2.2
495331Samw * see section 4.2.1 (NT_CREATE_ANDX).
505331Samw */
516030Sjb150015 smb_sdrc_t
smb_pre_nt_transact_create(smb_request_t * sr,smb_xa_t * xa)526139Sjb150015 smb_pre_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
535331Samw {
545331Samw struct open_param *op = &sr->arg.open;
556139Sjb150015 uint8_t SecurityFlags;
566139Sjb150015 uint32_t EaLength;
576139Sjb150015 uint32_t ImpersonationLevel;
586139Sjb150015 uint32_t NameLength;
596139Sjb150015 uint32_t sd_len;
606139Sjb150015 uint32_t status;
616139Sjb150015 smb_sd_t sd;
625331Samw int rc;
635331Samw
646139Sjb150015 bzero(op, sizeof (sr->arg.open));
656139Sjb150015
667052Samw rc = smb_mbc_decodef(&xa->req_param_mb, "%lllqllllllllb",
675331Samw sr,
688934SJose.Borrego@Sun.COM &op->nt_flags,
696139Sjb150015 &op->rootdirfid,
705331Samw &op->desired_access,
715331Samw &op->dsize,
726139Sjb150015 &op->dattr,
735331Samw &op->share_access,
745331Samw &op->create_disposition,
755331Samw &op->create_options,
765331Samw &sd_len,
775331Samw &EaLength,
785331Samw &NameLength,
795331Samw &ImpersonationLevel,
805331Samw &SecurityFlags);
815331Samw
826139Sjb150015 if (rc == 0) {
836139Sjb150015 if (NameLength == 0) {
849343SAfshin.Ardakani@Sun.COM op->fqi.fq_path.pn_path = "\\";
856139Sjb150015 } else if (NameLength >= MAXPATHLEN) {
866139Sjb150015 smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND,
876139Sjb150015 ERRDOS, ERROR_PATH_NOT_FOUND);
886139Sjb150015 rc = -1;
896139Sjb150015 } else {
907052Samw rc = smb_mbc_decodef(&xa->req_param_mb, "%#u",
919343SAfshin.Ardakani@Sun.COM sr, NameLength, &op->fqi.fq_path.pn_path);
926139Sjb150015 }
935331Samw }
945331Samw
958934SJose.Borrego@Sun.COM op->op_oplock_level = SMB_OPLOCK_NONE;
968934SJose.Borrego@Sun.COM if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPLOCK) {
978934SJose.Borrego@Sun.COM if (op->nt_flags & NT_CREATE_FLAG_REQUEST_OPBATCH)
988934SJose.Borrego@Sun.COM op->op_oplock_level = SMB_OPLOCK_BATCH;
998934SJose.Borrego@Sun.COM else
1008934SJose.Borrego@Sun.COM op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
1015331Samw }
1025331Samw
1035521Sas200622 if (sd_len) {
1045521Sas200622 status = smb_decode_sd(xa, &sd);
1055521Sas200622 if (status != NT_STATUS_SUCCESS) {
1065772Sas200622 smbsr_error(sr, status, 0, 0);
1076139Sjb150015 return (SDRC_ERROR);
1085331Samw }
1096165Sas200622 op->sd = kmem_alloc(sizeof (smb_sd_t), KM_SLEEP);
1106165Sas200622 *op->sd = sd;
1115331Samw } else {
1125521Sas200622 op->sd = NULL;
1135331Samw }
1145331Samw
1156139Sjb150015 DTRACE_SMB_2(op__NtTransactCreate__start, smb_request_t *, sr,
1166139Sjb150015 struct open_param *, op);
1176139Sjb150015
1186139Sjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1196139Sjb150015 }
1205331Samw
1216139Sjb150015 void
smb_post_nt_transact_create(smb_request_t * sr,smb_xa_t * xa)1226139Sjb150015 smb_post_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
1236139Sjb150015 {
1246165Sas200622 smb_sd_t *sd = sr->arg.open.sd;
1256165Sas200622
1266139Sjb150015 DTRACE_SMB_2(op__NtTransactCreate__done, smb_request_t *, sr,
1276139Sjb150015 smb_xa_t *, xa);
1286165Sas200622
1296165Sas200622 if (sd) {
1306165Sas200622 smb_sd_term(sd);
1316165Sas200622 kmem_free(sd, sizeof (smb_sd_t));
1326165Sas200622 }
13310966SJordan.Brown@Sun.COM
13410966SJordan.Brown@Sun.COM if (sr->arg.open.dir != NULL)
13510966SJordan.Brown@Sun.COM smb_ofile_release(sr->arg.open.dir);
1366139Sjb150015 }
1375331Samw
1386139Sjb150015 smb_sdrc_t
smb_nt_transact_create(smb_request_t * sr,smb_xa_t * xa)1396139Sjb150015 smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
1406139Sjb150015 {
1416139Sjb150015 struct open_param *op = &sr->arg.open;
1426139Sjb150015 uint8_t DirFlag;
14310001SJoyce.McIntosh@Sun.COM smb_attr_t attr;
1446139Sjb150015 smb_node_t *node;
1456139Sjb150015 uint32_t status;
1466139Sjb150015
1476139Sjb150015 if ((op->create_options & FILE_DELETE_ON_CLOSE) &&
1486139Sjb150015 !(op->desired_access & DELETE)) {
1498934SJose.Borrego@Sun.COM smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
1508934SJose.Borrego@Sun.COM ERRDOS, ERRbadaccess);
1518934SJose.Borrego@Sun.COM return (SDRC_ERROR);
1528934SJose.Borrego@Sun.COM }
1538934SJose.Borrego@Sun.COM
1548934SJose.Borrego@Sun.COM if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
1558934SJose.Borrego@Sun.COM smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
1568934SJose.Borrego@Sun.COM ERRDOS, ERRbadaccess);
1576139Sjb150015 return (SDRC_ERROR);
1585331Samw }
1595331Samw
1606139Sjb150015 if (op->dattr & FILE_FLAG_WRITE_THROUGH)
1615331Samw op->create_options |= FILE_WRITE_THROUGH;
1625331Samw
1636139Sjb150015 if (op->dattr & FILE_FLAG_DELETE_ON_CLOSE)
1645331Samw op->create_options |= FILE_DELETE_ON_CLOSE;
1655331Samw
1667961SNatalie.Li@Sun.COM if (op->dattr & FILE_FLAG_BACKUP_SEMANTICS)
1677961SNatalie.Li@Sun.COM op->create_options |= FILE_OPEN_FOR_BACKUP_INTENT;
1687961SNatalie.Li@Sun.COM
1697961SNatalie.Li@Sun.COM if (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT)
1707961SNatalie.Li@Sun.COM sr->user_cr = smb_user_getprivcred(sr->uid_user);
1717961SNatalie.Li@Sun.COM
1726139Sjb150015 if (op->rootdirfid == 0) {
1739343SAfshin.Ardakani@Sun.COM op->fqi.fq_dnode = sr->tid_tree->t_snode;
1745331Samw } else {
17510966SJordan.Brown@Sun.COM op->dir = smb_ofile_lookup_by_fid(sr->tid_tree,
17610966SJordan.Brown@Sun.COM (uint16_t)op->rootdirfid);
17710966SJordan.Brown@Sun.COM if (op->dir == NULL) {
1786139Sjb150015 smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
1796139Sjb150015 ERRDOS, ERRbadfid);
1806139Sjb150015 return (SDRC_ERROR);
1816139Sjb150015 }
18210966SJordan.Brown@Sun.COM op->fqi.fq_dnode = op->dir->f_node;
1835331Samw }
1845331Samw
185*12890SJoyce.McIntosh@Sun.COM op->op_oplock_levelII = B_TRUE;
186*12890SJoyce.McIntosh@Sun.COM
1876030Sjb150015 status = smb_common_open(sr);
1886030Sjb150015
1896030Sjb150015 if (status != NT_STATUS_SUCCESS)
1906139Sjb150015 return (SDRC_ERROR);
1915331Samw
19211447Samw@Sun.COM switch (sr->tid_tree->t_res_type & STYPE_MASK) {
19311447Samw@Sun.COM case STYPE_DISKTREE:
19411447Samw@Sun.COM case STYPE_PRINTQ:
1955331Samw if (op->create_options & FILE_DELETE_ON_CLOSE)
1969231SAfshin.Ardakani@Sun.COM smb_ofile_set_delete_on_close(sr->fid_ofile);
1975331Samw
1985331Samw node = sr->fid_ofile->f_node;
19910001SJoyce.McIntosh@Sun.COM DirFlag = smb_node_is_dir(node) ? 1 : 0;
20010001SJoyce.McIntosh@Sun.COM if (smb_node_getattr(sr, node, &attr) != 0) {
20110001SJoyce.McIntosh@Sun.COM smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
20210001SJoyce.McIntosh@Sun.COM ERRDOS, ERROR_INTERNAL_ERROR);
20310001SJoyce.McIntosh@Sun.COM return (SDRC_ERROR);
2045331Samw }
2055331Samw
2067052Samw (void) smb_mbc_encodef(&xa->rep_param_mb, "b.wllTTTTlqqwwb",
207*12890SJoyce.McIntosh@Sun.COM op->op_oplock_level,
2085331Samw sr->smb_fid,
2095331Samw op->action_taken,
2105331Samw 0, /* EaErrorOffset */
21110001SJoyce.McIntosh@Sun.COM &attr.sa_crtime,
21210001SJoyce.McIntosh@Sun.COM &attr.sa_vattr.va_atime,
21310001SJoyce.McIntosh@Sun.COM &attr.sa_vattr.va_mtime,
21410001SJoyce.McIntosh@Sun.COM &attr.sa_vattr.va_ctime,
2155331Samw op->dattr & FILE_ATTRIBUTE_MASK,
21610504SKeyur.Desai@Sun.COM attr.sa_allocsz,
21710001SJoyce.McIntosh@Sun.COM attr.sa_vattr.va_size,
2185331Samw op->ftype,
2195331Samw op->devstate,
2205331Samw DirFlag);
22111447Samw@Sun.COM break;
22211447Samw@Sun.COM
22311447Samw@Sun.COM case STYPE_IPC:
22410001SJoyce.McIntosh@Sun.COM bzero(&attr, sizeof (smb_attr_t));
2257052Samw (void) smb_mbc_encodef(&xa->rep_param_mb, "b.wllTTTTlqqwwb",
2265331Samw 0,
2275331Samw sr->smb_fid,
2285331Samw op->action_taken,
2295331Samw 0, /* EaErrorOffset */
23010001SJoyce.McIntosh@Sun.COM &attr.sa_crtime,
23110001SJoyce.McIntosh@Sun.COM &attr.sa_vattr.va_atime,
23210001SJoyce.McIntosh@Sun.COM &attr.sa_vattr.va_mtime,
23310001SJoyce.McIntosh@Sun.COM &attr.sa_vattr.va_ctime,
2345331Samw op->dattr,
2355331Samw 0x1000LL,
2365331Samw 0LL,
2375331Samw op->ftype,
2385331Samw op->devstate,
2395331Samw 0);
24011447Samw@Sun.COM break;
24111447Samw@Sun.COM
24211447Samw@Sun.COM default:
24311447Samw@Sun.COM smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
24411447Samw@Sun.COM ERRDOS, ERROR_INVALID_FUNCTION);
24511447Samw@Sun.COM return (SDRC_ERROR);
2465331Samw }
2475331Samw
2486139Sjb150015 return (SDRC_SUCCESS);
2495331Samw }
250