xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.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, 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