diff options
author | Gordon Ross <gwr@nexenta.com> | 2015-10-01 21:34:06 -0400 |
---|---|---|
committer | Gordon Ross <gwr@nexenta.com> | 2019-05-21 08:07:55 -0400 |
commit | c5f48fa536d16d8fe59d1bb62faa7eb8e891610c (patch) | |
tree | f4d5af986df2ce3a8d65c718d78057354b32329c | |
parent | 3bd40d9837ed643779c04bcc9d85d24be281ef29 (diff) | |
download | illumos-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.c | 13 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c | 136 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c | 131 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbsrv/smb_open_andx.c | 110 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbsrv/smb_opipe.c | 17 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbsrv/smb_pathname.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbsrv/smb_vops.c | 14 | ||||
-rw-r--r-- | usr/src/uts/common/smbsrv/ntifs.h | 4 | ||||
-rw-r--r-- | usr/src/uts/common/smbsrv/smb.h | 10 |
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 |