/*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
*/
/*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
/*
* Dispatch function for SMB2_CREATE
* [MS-SMB2] 2.2.13
*/
#include <smbsrv/smb2_kproto.h>
#include <smbsrv/smb_fsops.h>
/*
* Some flags used locally to keep track of which Create Context
*/
typedef struct smb2_create_ctx_elem {
typedef struct smb2_create_ctx {
/* Elements we may see in the request. */
/* Elements we my place in the response */
static uint32_t smb2_decode_create_ctx(
mbuf_chain_t *, smb2_create_ctx_t *);
static uint32_t smb2_encode_create_ctx(
mbuf_chain_t *, smb2_create_ctx_t *);
static int smb2_encode_create_ctx_elem(
static void smb2_free_create_ctx(smb2_create_ctx_t *);
{
int skip;
int rc = 0;
/*
* Paranoia. This will set sr->fid_ofile, so
* if we already have one, release it now.
*/
}
/*
* SMB2 Create request
*/
&StructSize, /* w */
&SecurityFlags, /* b */
&OplockLevel, /* b */
&ImpersonationLevel, /* l */
&SmbCreateFlags, /* q */
&Reserved4, /* q */
&NameOffset, /* w */
&NameLength, /* w */
&CreateCtxOffset, /* l */
&CreateCtxLength); /* l */
return (SDRC_ERROR);
/*
* We're normally positioned at the path name now,
* but there could be some padding before it.
*/
if (skip < 0) {
goto errout;
}
if (skip > 0)
/*
* Get the path name
*/
if (NameLength >= SMB_MAXPATHLEN) {
goto errout;
}
if (NameLength == 0) {
} else {
if (rc) {
goto errout;
}
}
switch (OplockLevel) {
case SMB2_OPLOCK_LEVEL_NONE:
break;
case SMB2_OPLOCK_LEVEL_II:
break;
break;
case SMB2_OPLOCK_LEVEL_BATCH:
break;
case SMB2_OPLOCK_LEVEL_LEASE:
goto errout;
}
/*
* ImpersonationLevel (spec. says ignore)
* SmbCreateFlags (spec. says ignore)
*/
goto errout;
}
goto errout;
}
/*
* If there is a "Create Context" payload, decode it.
* This may carry things like a security descriptor,
* extended attributes, etc. to be used in create.
*
* The create ctx buffer must start after the headers
* and file name, and must be 8-byte aligned.
*/
if (CreateCtxLength != 0) {
if ((CreateCtxOffset & 7) != 0 ||
goto errout;
}
if (rc) {
goto errout;
}
if (status)
goto errout;
goto errout;
}
if (status)
goto errout;
}
if (rc) {
goto errout;
}
}
/*
* Support for opening "Previous Versions".
* [MS-SMB2] 2.2.13.2.7 Data is an NT time.
*/
"q", &timewarp);
if (status)
goto errout;
}
}
/*
* The real open call. Note: this gets attributes into
* op->fqi.fq_fattr (SMB_AT_ALL). We need those below.
*/
if (status != NT_STATUS_SUCCESS)
goto errout;
/*
* Convert the negotiate Oplock level back into
* SMB2 encoding form.
*/
switch (op->op_oplock_level) {
default:
case SMB_OPLOCK_NONE:
break;
case SMB_OPLOCK_LEVEL_II:
break;
case SMB_OPLOCK_EXCLUSIVE:
break;
case SMB_OPLOCK_BATCH:
break;
}
/*
* NB: after the above smb_common_open() success,
* we have a handle allocated (sr->fid_ofile).
* If we don't return success, we must close it.
*
* Using sr->smb_fid as the file handle for now,
* though it could later be something larger,
* (16 bytes) similar to an NFSv4 open handle.
*/
smb2fid.persistent = 0;
case STYPE_DISKTREE:
case STYPE_PRINTQ:
break;
}
/*
* Build the Create Context to return; first the
* per-element parts, then the aggregated buffer.
*
* No response for these:
* CCTX_EA_BUFFER
* CCTX_SD_BUFFER
* CCTX_ALLOCATION_SIZE
* CCTX_TIMEWARP_TOKEN
*
* We don't handle these yet.
* CCTX_DH_REQUEST
* CCTX_DH_RECONNECT
* CCTX_REQUEST_LEASE
*/
}
"ll", 0, MaxAccess);
}
(void) smb_mbc_encodef(
/* reserved (16 bytes) .15. */
}
if (cctx.cc_out_flags) {
if (status)
goto errout;
}
/*
* SMB2 Create reply
*/
"wb.lTTTTqqllqqll",
89, /* StructSize */ /* w */
OplockLevel, /* b */
0, /* reserved2 */ /* l */
0, /* CreateCtxOffset l */
0); /* CreateCtxLength l */
if (rc != 0) {
goto errout;
}
if (CreateCtxLength != 0) {
/*
* Overwrite CreateCtxOffset, CreateCtxLength, pad
*/
"ll#C",
CreateCtxOffset, /* l */
CreateCtxLength, /* l */
CreateCtxLength, /* # */
if (rc != 0) {
goto errout;
}
} else {
}
return (SDRC_SUCCESS);
smb_ofile_close(of, 0);
if (cctx.cc_out_flags)
return (SDRC_SUCCESS);
}
/*
* Decode an SMB2 Create Context buffer into our internal form.
* No policy decisions about what's supported here, just decode.
*/
static uint32_t
{
union {
uint32_t i;
} cc_name;
int top_offset;
int rc;
for (;;) {
"lww..wl",
&next_off, /* l */
&name_off, /* w */
&name_len, /* w */
/* reserved .. */
&data_off, /* w */
&data_len); /* l */
if (rc)
break;
/*
* The Create Context "name", per [MS-SMB] 2.2.13.2
* They're defined as network-order integers for our
* switch below. We don't have routines to decode
* native order, so read as char[4] then ntohl.
* NB: in SMB3, some of these are 8 bytes.
*/
break;
if (rc)
break;
if (rc)
break;
switch (cc_name.i) {
case SMB2_CREATE_EA_BUFFER: /* ("ExtA") */
break;
case SMB2_CREATE_SD_BUFFER: /* ("SecD") */
break;
case SMB2_CREATE_DURABLE_HANDLE_REQUEST: /* ("DHnQ") */
break;
case SMB2_CREATE_DURABLE_HANDLE_RECONNECT: /* ("DHnC") */
break;
case SMB2_CREATE_ALLOCATION_SIZE: /* ("AISi") */
break;
case SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQ: /* ("MxAc") */
/* no input data for this */
break;
case SMB2_CREATE_TIMEWARP_TOKEN: /* ("TWrp") */
break;
case SMB2_CREATE_QUERY_ON_DISK_ID: /* ("QFid") */
/* no input data for this */
break;
case SMB2_CREATE_REQUEST_LEASE: /* ("RqLs") */
break;
default:
/*
* Unknown create context values are normal, and
* should be ignored. However, in debug mode,
* let's log them so we know which ones we're
* not handling (and may want to add).
*/
#ifdef DEBUG
cc_name.i);
#endif
break;
}
if ((data_off & 7) != 0)
break;
break;
if (rc)
break;
}
if (next_off == 0) {
/* Normal loop termination */
status = 0;
break;
}
if ((next_off & 7) != 0)
break;
break;
break;
}
return (status);
}
/*
* Encode an SMB2 Create Context buffer from our internal form.
*/
/* ARGSUSED */
static uint32_t
{
int rc;
if (rc)
return (NT_STATUS_INTERNAL_ERROR);
}
if (rc)
return (NT_STATUS_INTERNAL_ERROR);
}
if (last_top >= 0)
return (0);
}
static int
{
union {
uint32_t i;
} cc_name;
int rc;
/* as above */
/*
* This is the header, per [MS-SMB2] 2.2.13.2
* Sorry about the fixed offsets. We know we'll
* layout the data part as [name, payload] and
* name is a fixed length, so this easy.
* The final layout looks like this:
* a: this header (16 bytes)
* b: the name (4 bytes, 4 pad)
* c: the payload (variable)
*
* Note that "Next elem." is filled in later.
*/
out_mbc, "lwwwwl",
0, /* Next offset l */
16, /* NameOffset w */
4, /* NameLength w */
0, /* Reserved w */
24, /* DataOffset w */
if (rc)
return (rc);
/*
* Now the "name" and payload.
*/
out_mbc, "4c4.#C",
return (rc);
}
static void
{
}
}
}