summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGordon Ross <gwr@nexenta.com>2015-10-01 21:34:06 -0400
committerGordon Ross <gwr@nexenta.com>2019-05-21 08:07:55 -0400
commitc5f48fa536d16d8fe59d1bb62faa7eb8e891610c (patch)
treef4d5af986df2ce3a8d65c718d78057354b32329c
parent3bd40d9837ed643779c04bcc9d85d24be281ef29 (diff)
downloadillumos-joyent-c5f48fa536d16d8fe59d1bb62faa7eb8e891610c.tar.gz
10974 SMB1 create file should support extended_response format
Reviewed by: Matt Barden <Matt.Barden@nexenta.com> Reviewed by: Bayard Bell <bayard.bell@nexenta.com> Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com> Reviewed by: Rick McNeal <rick.mcneal@nexenta.com> Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com> Reviewed by: Evan Layton <evan.layton@nexenta.com> Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_common_open.c13
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c136
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c131
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_open_andx.c110
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_opipe.c17
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_pathname.c4
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_vops.c14
-rw-r--r--usr/src/uts/common/smbsrv/ntifs.h4
-rw-r--r--usr/src/uts/common/smbsrv/smb.h10
9 files changed, 295 insertions, 144 deletions
diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_open.c b/usr/src/uts/common/fs/smbsrv/smb_common_open.c
index 695a2c062c..030d1fa360 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_common_open.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_common_open.c
@@ -109,7 +109,7 @@ smb_omode_to_amask(uint32_t desired_access)
return (FILE_GENERIC_READ | FILE_GENERIC_WRITE);
case SMB_DA_ACCESS_EXECUTE:
- return (FILE_GENERIC_EXECUTE);
+ return (FILE_GENERIC_READ | FILE_GENERIC_EXECUTE);
default:
return (FILE_GENERIC_ALL);
@@ -743,9 +743,16 @@ smb_open_subr(smb_request_t *sr)
/*
* We set alloc_size = op->dsize later,
- * after we have an ofile. See:
- * smb_set_open_attributes
+ * (in smb_set_open_attributes) after we
+ * have an ofile on which to save that.
+ *
+ * Legacy Open&X sets size to alloc_size
+ * when creating a new file.
*/
+ if (sr->smb_com == SMB_COM_OPEN_ANDX) {
+ new_attr.sa_vattr.va_size = op->dsize;
+ new_attr.sa_mask |= SMB_AT_SIZE;
+ }
rc = smb_fsop_create(sr, sr->user_cr, dnode,
op->fqi.fq_last_comp, &new_attr, &op->fqi.fq_fnode);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c b/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c
index 5b28b0778a..a787b9ed27 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -32,6 +32,8 @@
#include <smbsrv/smb_fsops.h>
#include <smbsrv/smb_vops.h>
+int smb_nt_create_enable_extended_response = 1;
+
/*
* smb_com_nt_create_andx
*
@@ -227,6 +229,9 @@ smb_post_nt_create_andx(smb_request_t *sr)
}
}
+/*
+ * A lot like smb_nt_transact_create
+ */
smb_sdrc_t
smb_com_nt_create_andx(struct smb_request *sr)
{
@@ -234,9 +239,21 @@ smb_com_nt_create_andx(struct smb_request *sr)
smb_attr_t *ap = &op->fqi.fq_fattr;
smb_ofile_t *of;
int rc;
- unsigned char DirFlag;
+ uint8_t DirFlag;
uint32_t status;
+ if (op->create_options & ~SMB_NTCREATE_VALID_OPTIONS) {
+ smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
+ ERRDOS, ERROR_INVALID_PARAMETER);
+ return (SDRC_ERROR);
+ }
+
+ if (op->create_options & FILE_OPEN_BY_FILE_ID) {
+ smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
+ ERRDOS, ERROR_NOT_SUPPORTED);
+ return (SDRC_ERROR);
+ }
+
if ((op->create_options & FILE_DELETE_ON_CLOSE) &&
!(op->desired_access & DELETE)) {
smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
@@ -294,47 +311,11 @@ smb_com_nt_create_andx(struct smb_request *sr)
case STYPE_PRINTQ:
if (op->create_options & FILE_DELETE_ON_CLOSE)
smb_ofile_set_delete_on_close(of);
-
DirFlag = smb_node_is_dir(of->f_node) ? 1 : 0;
- rc = smbsr_encode_result(sr, 34, 0, "bb.wbwlTTTTlqqwwbw",
- 34,
- sr->andx_com,
- 0x67,
- op->op_oplock_level,
- sr->smb_fid,
- op->action_taken,
- &ap->sa_crtime,
- &ap->sa_vattr.va_atime,
- &ap->sa_vattr.va_mtime,
- &ap->sa_vattr.va_ctime,
- op->dattr & FILE_ATTRIBUTE_MASK,
- ap->sa_allocsz,
- ap->sa_vattr.va_size,
- op->ftype,
- op->devstate,
- DirFlag,
- 0);
break;
case STYPE_IPC:
- rc = smbsr_encode_result(sr, 34, 0, "bb.wbwlqqqqlqqwwbw",
- 34,
- sr->andx_com,
- 0x67,
- 0,
- sr->smb_fid,
- op->action_taken,
- 0LL,
- 0LL,
- 0LL,
- 0LL,
- FILE_ATTRIBUTE_NORMAL,
- 0x1000LL,
- 0LL,
- op->ftype,
- op->devstate,
- 0,
- 0);
+ DirFlag = 0;
break;
default:
@@ -342,6 +323,83 @@ smb_com_nt_create_andx(struct smb_request *sr)
ERRDOS, ERROR_INVALID_FUNCTION);
goto errout;
}
+
+ if ((op->nt_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE) != 0 &&
+ smb_nt_create_enable_extended_response != 0) {
+ uint32_t MaxAccess = 0;
+ if (of->f_node != NULL) {
+ smb_fsop_eaccess(sr, of->f_cr, of->f_node, &MaxAccess);
+ }
+ MaxAccess |= of->f_granted_access;
+
+ /*
+ * Here is a really ugly protocol wart in SMB1:
+ *
+ * [MS-SMB] Sec. 2.2.4.9.2: Windows-based SMB servers
+ * send 50 (0x32) words in the extended response although
+ * they set the WordCount field to 0x2A.
+ *
+ * In other words, THEY LIE! We really do need to encode
+ * 50 words here, but lie and say we encoded 42 words.
+ * This means we can't use smbsr_encode_result() to
+ * build this response, because the rules it breaks
+ * would cause errors in smbsr_check_result().
+ *
+ * And that's not all (it gets worse...)
+ * Because of the bogus word count, some clients will
+ * read the byte count from within what should be the
+ * fileid field below. Leave that zero, like Win7.
+ *
+ * Apparently the only really useful thing in this
+ * extended response is MaxAccess.
+ */
+ sr->smb_wct = 50; /* real word count */
+ sr->smb_bcc = 0;
+ rc = smb_mbc_encodef(&sr->reply,
+ "bb.wbwlTTTTlqqwwb16.qllw",
+ 42, /* fake word count (b) */
+ sr->andx_com, /* (b.) */
+ 0x87, /* andx offset (w) */
+ op->op_oplock_level, /* (b) */
+ sr->smb_fid, /* (w) */
+ op->action_taken, /* (l) */
+ &ap->sa_crtime, /* (T) */
+ &ap->sa_vattr.va_atime, /* (T) */
+ &ap->sa_vattr.va_mtime, /* (T) */
+ &ap->sa_vattr.va_ctime, /* (T) */
+ op->dattr & FILE_ATTRIBUTE_MASK, /* (l) */
+ ap->sa_allocsz, /* (q) */
+ ap->sa_vattr.va_size, /* (q) */
+ op->ftype, /* (w) */
+ op->devstate, /* (w) */
+ DirFlag, /* (b) */
+ /* volume guid (16.) */
+ 0, /* file ID (see above) (q) */
+ MaxAccess, /* (l) */
+ 0, /* guest access (l) */
+ 0); /* byte count (w) */
+ } else {
+ rc = smbsr_encode_result(
+ sr, 34, 0, "bb.wbwlTTTTlqqwwbw",
+ 34, /* word count (b) */
+ sr->andx_com, /* (b.) */
+ 0x67, /* andx offset (w) */
+ op->op_oplock_level, /* (b) */
+ sr->smb_fid, /* (w) */
+ op->action_taken, /* (l) */
+ &ap->sa_crtime, /* (T) */
+ &ap->sa_vattr.va_atime, /* (T) */
+ &ap->sa_vattr.va_mtime, /* (T) */
+ &ap->sa_vattr.va_ctime, /* (T) */
+ op->dattr & FILE_ATTRIBUTE_MASK, /* (l) */
+ ap->sa_allocsz, /* (q) */
+ ap->sa_vattr.va_size, /* (q) */
+ op->ftype, /* (w) */
+ op->devstate, /* (w) */
+ DirFlag, /* (b) */
+ 0); /* byte count (w) */
+ }
+
if (rc == 0)
return (SDRC_SUCCESS);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c
index 7a04ba2b6a..34bf2d25c9 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -36,6 +36,8 @@
#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_fsops.h>
+extern int smb_nt_create_enable_extended_response;
+
/*
* smb_nt_transact_create
*
@@ -83,9 +85,9 @@ smb_pre_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
if (rc == 0) {
if (NameLength == 0) {
op->fqi.fq_path.pn_path = "\\";
- } else if (NameLength >= MAXPATHLEN) {
- smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND,
- ERRDOS, ERROR_PATH_NOT_FOUND);
+ } else if (NameLength >= SMB_MAXPATHLEN) {
+ smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
+ ERRDOS, ERROR_INVALID_NAME);
rc = -1;
} else {
rc = smb_mbc_decodef(&xa->req_param_mb, "%#u",
@@ -132,19 +134,36 @@ smb_post_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
kmem_free(sd, sizeof (smb_sd_t));
}
- if (sr->arg.open.dir != NULL)
+ if (sr->arg.open.dir != NULL) {
smb_ofile_release(sr->arg.open.dir);
+ sr->arg.open.dir = NULL;
+ }
}
+/*
+ * A lot like smb_com_nt_create_andx
+ */
smb_sdrc_t
smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
{
- struct open_param *op = &sr->arg.open;
- uint8_t DirFlag;
- smb_attr_t attr;
+ struct open_param *op = &sr->arg.open;
+ smb_attr_t *ap = &op->fqi.fq_fattr;
smb_ofile_t *of;
- uint32_t status;
int rc;
+ uint8_t DirFlag;
+ uint32_t status;
+
+ if (op->create_options & ~SMB_NTCREATE_VALID_OPTIONS) {
+ smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
+ ERRDOS, ERROR_INVALID_PARAMETER);
+ return (SDRC_ERROR);
+ }
+
+ if (op->create_options & FILE_OPEN_BY_FILE_ID) {
+ smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
+ ERRDOS, ERROR_NOT_SUPPORTED);
+ return (SDRC_ERROR);
+ }
if ((op->create_options & FILE_DELETE_ON_CLOSE) &&
!(op->desired_access & DELETE)) {
@@ -203,50 +222,11 @@ smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
case STYPE_PRINTQ:
if (op->create_options & FILE_DELETE_ON_CLOSE)
smb_ofile_set_delete_on_close(of);
-
DirFlag = smb_node_is_dir(of->f_node) ? 1 : 0;
- bzero(&attr, sizeof (attr));
- attr.sa_mask = SMB_AT_ALL;
- rc = smb_node_getattr(sr, of->f_node, of->f_cr, of, &attr);
- if (rc != 0) {
- smbsr_errno(sr, rc);
- goto errout;
- }
-
- rc = smb_mbc_encodef(&xa->rep_param_mb, "b.wllTTTTlqqwwb",
- op->op_oplock_level,
- sr->smb_fid,
- op->action_taken,
- 0, /* EaErrorOffset */
- &attr.sa_crtime,
- &attr.sa_vattr.va_atime,
- &attr.sa_vattr.va_mtime,
- &attr.sa_vattr.va_ctime,
- op->dattr & FILE_ATTRIBUTE_MASK,
- attr.sa_allocsz,
- attr.sa_vattr.va_size,
- op->ftype,
- op->devstate,
- DirFlag);
break;
case STYPE_IPC:
- bzero(&attr, sizeof (smb_attr_t));
- rc = smb_mbc_encodef(&xa->rep_param_mb, "b.wllTTTTlqqwwb",
- 0,
- sr->smb_fid,
- op->action_taken,
- 0, /* EaErrorOffset */
- &attr.sa_crtime,
- &attr.sa_vattr.va_atime,
- &attr.sa_vattr.va_mtime,
- &attr.sa_vattr.va_ctime,
- op->dattr,
- 0x1000LL,
- 0LL,
- op->ftype,
- op->devstate,
- 0);
+ DirFlag = 0;
break;
default:
@@ -254,7 +234,58 @@ smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
ERRDOS, ERROR_INVALID_FUNCTION);
goto errout;
}
- return (SDRC_SUCCESS);
+
+ if ((op->nt_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE) != 0 &&
+ smb_nt_create_enable_extended_response != 0) {
+ uint32_t MaxAccess = 0;
+ if (of->f_node != NULL) {
+ smb_fsop_eaccess(sr, of->f_cr, of->f_node, &MaxAccess);
+ }
+ MaxAccess |= of->f_granted_access;
+
+ rc = smb_mbc_encodef(
+ &xa->rep_param_mb, "bbwllTTTTlqqwwb16.qll",
+ op->op_oplock_level, /* (b) */
+ 1, /* ResponseType (b) */
+ sr->smb_fid, /* (w) */
+ op->action_taken, /* (l) */
+ 0, /* EaErrorOffset (l) */
+ &ap->sa_crtime, /* (T) */
+ &ap->sa_vattr.va_atime, /* (T) */
+ &ap->sa_vattr.va_mtime, /* (T) */
+ &ap->sa_vattr.va_ctime, /* (T) */
+ op->dattr & FILE_ATTRIBUTE_MASK, /* (l) */
+ ap->sa_allocsz, /* (q) */
+ ap->sa_vattr.va_size, /* (q) */
+ op->ftype, /* (w) */
+ op->devstate, /* (w) */
+ DirFlag, /* (b) */
+ /* volume guid (16.) */
+ op->fileid, /* (q) */
+ MaxAccess, /* (l) */
+ 0); /* guest access (l) */
+ } else {
+ rc = smb_mbc_encodef(
+ &xa->rep_param_mb, "bbwllTTTTlqqwwb",
+ op->op_oplock_level, /* (b) */
+ 0, /* ResponseType (b) */
+ sr->smb_fid, /* (w) */
+ op->action_taken, /* (l) */
+ 0, /* EaErrorOffset (l) */
+ &ap->sa_crtime, /* (T) */
+ &ap->sa_vattr.va_atime, /* (T) */
+ &ap->sa_vattr.va_mtime, /* (T) */
+ &ap->sa_vattr.va_ctime, /* (T) */
+ op->dattr & FILE_ATTRIBUTE_MASK, /* (l) */
+ ap->sa_allocsz, /* (q) */
+ ap->sa_vattr.va_size, /* (q) */
+ op->ftype, /* (w) */
+ op->devstate, /* (w) */
+ DirFlag); /* (b) */
+ }
+
+ if (rc == 0)
+ return (SDRC_SUCCESS);
errout:
smb_ofile_close(of, 0);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_open_andx.c b/usr/src/uts/common/fs/smbsrv/smb_open_andx.c
index c936366a9c..ff26c61119 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_open_andx.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_open_andx.c
@@ -20,10 +20,11 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
*/
#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smb_fsops.h>
#include <smbsrv/smb_vops.h>
int smb_open_dsize_check = 0;
@@ -316,6 +317,8 @@ errout:
return (SDRC_ERROR);
}
+int smb_openx_enable_extended_response = 1;
+
/*
* smb_pre_open_andx
* For compatibility with windows servers, the search attributes
@@ -325,7 +328,7 @@ smb_sdrc_t
smb_pre_open_andx(smb_request_t *sr)
{
struct open_param *op = &sr->arg.open;
- uint16_t flags;
+ uint16_t openx_flags;
uint32_t alloc_size;
uint32_t creation_time;
uint16_t file_attr, sattr;
@@ -334,7 +337,7 @@ smb_pre_open_andx(smb_request_t *sr)
bzero(op, sizeof (sr->arg.open));
rc = smbsr_decode_vwv(sr, "b.wwwwwlwll4.", &sr->andx_com,
- &sr->andx_off, &flags, &op->omode, &sattr,
+ &sr->andx_off, &openx_flags, &op->omode, &sattr,
&file_attr, &creation_time, &op->ofun, &alloc_size, &op->timeo);
if (rc == 0) {
@@ -343,12 +346,18 @@ smb_pre_open_andx(smb_request_t *sr)
op->dattr = file_attr;
op->dsize = alloc_size;
- if (flags & 2)
+ /*
+ * The openx_flags use some "extended" flags that
+ * happen to match some of the NtCreateX flags.
+ */
+ if (openx_flags & NT_CREATE_FLAG_REQUEST_OPLOCK)
op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
- else if (flags & 4)
+ else if (openx_flags & NT_CREATE_FLAG_REQUEST_OPBATCH)
op->op_oplock_level = SMB_OPLOCK_BATCH;
else
op->op_oplock_level = SMB_OPLOCK_NONE;
+ if (openx_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE)
+ op->nt_flags |= NT_CREATE_FLAG_EXTENDED_RESPONSE;
if ((creation_time != 0) && (creation_time != UINT_MAX))
op->crtime.tv_sec =
@@ -374,10 +383,11 @@ smb_sdrc_t
smb_com_open_andx(smb_request_t *sr)
{
struct open_param *op = &sr->arg.open;
+ smb_attr_t *ap = &op->fqi.fq_fattr;
smb_ofile_t *of;
uint32_t status;
+ uint32_t mtime_sec;
uint16_t file_attr;
- smb_attr_t attr;
int rc;
op->desired_access = smb_omode_to_amask(op->omode);
@@ -414,50 +424,20 @@ smb_com_open_andx(smb_request_t *sr)
of = sr->fid_ofile;
if (op->op_oplock_level != SMB_OPLOCK_NONE)
- op->action_taken |= SMB_OACT_LOCK;
+ op->action_taken |= SMB_OACT_OPLOCK;
else
- op->action_taken &= ~SMB_OACT_LOCK;
+ op->action_taken &= ~SMB_OACT_OPLOCK;
file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
- bzero(&attr, sizeof (attr));
+ mtime_sec = smb_time_gmt_to_local(sr, ap->sa_vattr.va_mtime.tv_sec);
switch (sr->tid_tree->t_res_type & STYPE_MASK) {
case STYPE_DISKTREE:
case STYPE_PRINTQ:
- attr.sa_mask = SMB_AT_MTIME;
- rc = smb_node_getattr(sr, of->f_node, of->f_cr, of, &attr);
- if (rc != 0) {
- smbsr_errno(sr, rc);
- goto errout;
- }
-
- rc = smbsr_encode_result(sr, 15, 0,
- "bb.wwwllwwwwl2.w",
- 15,
- sr->andx_com, VAR_BCC,
- sr->smb_fid,
- file_attr,
- smb_time_gmt_to_local(sr, attr.sa_vattr.va_mtime.tv_sec),
- (uint32_t)op->dsize,
- op->omode, op->ftype,
- op->devstate,
- op->action_taken, op->fileid,
- 0);
break;
case STYPE_IPC:
- rc = smbsr_encode_result(sr, 15, 0,
- "bb.wwwllwwwwl2.w",
- 15,
- sr->andx_com, VAR_BCC,
- sr->smb_fid,
- file_attr,
- 0L,
- 0L,
- op->omode, op->ftype,
- op->devstate,
- op->action_taken, op->fileid,
- 0);
+ mtime_sec = 0;
break;
default:
@@ -466,6 +446,52 @@ smb_com_open_andx(smb_request_t *sr)
goto errout;
}
+ if ((op->nt_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE) != 0 &&
+ smb_openx_enable_extended_response != 0) {
+ uint32_t MaxAccess = 0;
+ if (of->f_node != NULL) {
+ smb_fsop_eaccess(sr, of->f_cr, of->f_node, &MaxAccess);
+ }
+ MaxAccess |= of->f_granted_access;
+
+ rc = smbsr_encode_result(
+ sr, 19, 0, "bb.wwwllwwwwl2.llw",
+ 19, /* word count (b) */
+ sr->andx_com, /* (b.) */
+ VAR_BCC, /* andx offset (w) */
+ sr->smb_fid, /* (w) */
+ file_attr, /* (w) */
+ mtime_sec, /* (l) */
+ (uint32_t)op->dsize, /* (l) */
+ op->omode, /* (w) */
+ op->ftype, /* (w) */
+ op->devstate, /* (w) */
+ op->action_taken, /* (w) */
+ 0, /* legacy fileid (l) */
+ /* reserved (2.) */
+ MaxAccess, /* (l) */
+ 0, /* guest access (l) */
+ 0); /* byte count (w) */
+
+ } else {
+ rc = smbsr_encode_result(
+ sr, 15, 0, "bb.wwwllwwwwl2.w",
+ 15, /* word count (b) */
+ sr->andx_com, /* (b.) */
+ VAR_BCC, /* andx offset (w) */
+ sr->smb_fid, /* (w) */
+ file_attr, /* (w) */
+ mtime_sec, /* (l) */
+ (uint32_t)op->dsize, /* (l) */
+ op->omode, /* (w) */
+ op->ftype, /* (w) */
+ op->devstate, /* (w) */
+ op->action_taken, /* (w) */
+ 0, /* legacy fileid (l) */
+ /* reserved (2.) */
+ 0); /* byte count (w) */
+ }
+
if (rc == 0)
return (SDRC_SUCCESS);
@@ -548,9 +574,9 @@ smb_com_trans2_open2(smb_request_t *sr, smb_xa_t *xa)
}
if (op->op_oplock_level != SMB_OPLOCK_NONE)
- op->action_taken |= SMB_OACT_LOCK;
+ op->action_taken |= SMB_OACT_OPLOCK;
else
- op->action_taken &= ~SMB_OACT_LOCK;
+ op->action_taken &= ~SMB_OACT_OPLOCK;
file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_opipe.c b/usr/src/uts/common/fs/smbsrv/smb_opipe.c
index c08cba0ac6..f46ff659a8 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_opipe.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_opipe.c
@@ -212,6 +212,7 @@ int
smb_opipe_open(smb_request_t *sr, uint32_t uniqid)
{
smb_arg_open_t *op = &sr->sr_open;
+ smb_attr_t *ap = &op->fqi.fq_fattr;
smb_ofile_t *ofile;
smb_opipe_t *opipe;
smb_error_t err;
@@ -248,14 +249,19 @@ smb_opipe_open(smb_request_t *sr, uint32_t uniqid)
/* An "up" pointer, for debug. */
opipe->p_ofile = ofile;
- op->dsize = 0x01000;
- op->dattr = FILE_ATTRIBUTE_NORMAL;
+ /*
+ * Caller expects attributes in op->fqi
+ */
+ (void) smb_opipe_getattr(ofile, &op->fqi.fq_fattr);
+
+ op->dsize = 0;
+ op->dattr = ap->sa_dosattr;
+ op->fileid = ap->sa_vattr.va_nodeid;
op->ftype = SMB_FTYPE_MESG_PIPE;
- op->action_taken = SMB_OACT_LOCK | SMB_OACT_OPENED; /* 0x8001 */
+ op->action_taken = SMB_OACT_OPLOCK | SMB_OACT_OPENED;
op->devstate = SMB_PIPE_READMODE_MESSAGE
| SMB_PIPE_TYPE_MESSAGE
| SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */
- op->fileid = ofile->f_fid;
sr->smb_fid = ofile->f_fid;
sr->fid_ofile = ofile;
@@ -440,8 +446,9 @@ smb_opipe_getattr(smb_ofile_t *of, smb_attr_t *ap)
ap->sa_vattr.va_type = VFIFO;
ap->sa_vattr.va_nlink = 1;
+ ap->sa_vattr.va_nodeid = (uintptr_t)of->f_pipe;
ap->sa_dosattr = FILE_ATTRIBUTE_NORMAL;
- ap->sa_allocsz = 0x1000LL;
+ ap->sa_allocsz = SMB_PIPE_MAX_MSGSIZE;
return (0);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_pathname.c b/usr/src/uts/common/fs/smbsrv/smb_pathname.c
index 599698b78c..783dacdc9d 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_pathname.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_pathname.c
@@ -907,10 +907,10 @@ smb_pathname_validate(smb_request_t *sr, smb_pathname_t *pn)
return (B_FALSE);
}
- /* If fname is "." -> INVALID_OBJECT_NAME */
+ /* If fname is "." -> OBJECT_NAME_INVALID */
if (pn->pn_fname && (strcmp(pn->pn_fname, ".") == 0)) {
smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
- ERRDOS, ERROR_PATH_NOT_FOUND);
+ ERRDOS, ERROR_INVALID_NAME);
return (B_FALSE);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_vops.c b/usr/src/uts/common/fs/smbsrv/smb_vops.c
index 49b83a0cee..fb19baaff6 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_vops.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_vops.c
@@ -678,6 +678,20 @@ smb_vop_create(vnode_t *dvp, char *name, smb_attr_t *attr, vnode_t **vpp,
error = VOP_CREATE(dvp, np, vap, EXCL, attr->sa_vattr.va_mode,
vpp, cr, option_flags, &smb_ct, vsap);
+ /*
+ * One could argue that filesystems should obey the size
+ * if specified in the create attributes. Unfortunately,
+ * they only appear to let you truncate the size to zero.
+ * SMB needs to set a non-zero size, so work-around.
+ */
+ if (error == 0 && *vpp != NULL &&
+ (vap->va_mask & AT_SIZE) != 0 &&
+ vap->va_size > 0) {
+ vattr_t ta = *vap;
+ ta.va_mask = AT_SIZE;
+ (void) VOP_SETATTR(*vpp, &ta, 0, cr, &smb_ct);
+ }
+
return (error);
}
diff --git a/usr/src/uts/common/smbsrv/ntifs.h b/usr/src/uts/common/smbsrv/ntifs.h
index 79dcbf91da..bb3d7146c1 100644
--- a/usr/src/uts/common/smbsrv/ntifs.h
+++ b/usr/src/uts/common/smbsrv/ntifs.h
@@ -21,6 +21,8 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2016 by Delphix. All rights reserved.
*/
@@ -190,7 +192,7 @@ extern "C" {
#define FILE_RESERVED1 0x00400000
#define FILE_RESERVED2 0x00800000
-#define FILE_VALID_OPTION_FLAGS 0x007fffff
+#define FILE_VALID_OPTION_FLAGS 0x00ffffff
#define FILE_VALID_PIPE_OPTION_FLAGS 0x00000032
#define FILE_VALID_MAILSLOT_OPTION_FLAGS 0x00000032
#define FILE_VALID_SET_FLAGS 0x00000036
diff --git a/usr/src/uts/common/smbsrv/smb.h b/usr/src/uts/common/smbsrv/smb.h
index e7d0707d8b..c151a2a388 100644
--- a/usr/src/uts/common/smbsrv/smb.h
+++ b/usr/src/uts/common/smbsrv/smb.h
@@ -202,7 +202,15 @@ typedef uint32_t smb_utime_t;
#define NT_CREATE_FLAG_REQUEST_OPLOCK 0x02
#define NT_CREATE_FLAG_REQUEST_OPBATCH 0x04
#define NT_CREATE_FLAG_OPEN_TARGET_DIR 0x08
+#define NT_CREATE_FLAG_EXTENDED_RESPONSE 0x10
+/*
+ * The option flags valid in the SMB nt_create_andx call are a subset of
+ * those defined in ntifs.h (ditto SMB nt_transact_create)
+ */
+#define SMB_NTCREATE_VALID_OPTIONS (FILE_VALID_OPTION_FLAGS & ~( \
+ FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT |\
+ FILE_RESERVE_OPFILTER))
/*
* Define the filter flags for NtNotifyChangeDirectoryFile
@@ -654,11 +662,9 @@ typedef uint32_t smb_utime_t;
* 3 - The file existed and was truncated
*/
-#define SMB_OACT_LOCK 0x8000
#define SMB_OACT_OPENED 0x01
#define SMB_OACT_CREATED 0x02
#define SMB_OACT_TRUNCATED 0x03
-
#define SMB_OACT_OPLOCK 0x8000
#define SMB_FTYPE_DISK 0