Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • lts-team/packages/samba
  • thctlo/samba-lintianfix
  • arnaudr/samba
  • jrwren/samba
  • paride/samba
  • athos/samba
  • henrich/samba
  • cnotin/samba
  • mimi89999/samba
  • samba-team/samba
  • ahasenack/samba
  • jrtc27/samba
  • noel/samba
13 results
Show changes
Commits on Source (37)
Showing
with 499 additions and 58 deletions
......@@ -89,7 +89,7 @@ SAMBA_VERSION_PRE_RELEASE=
# e.g. SAMBA_VERSION_RC_RELEASE=1 #
# -> "3.0.0rc1" #
########################################################
SAMBA_VERSION_RC_RELEASE=2
SAMBA_VERSION_RC_RELEASE=
########################################################
# To mark SVN snapshots this should be set to 'yes' #
......
Release Announcements
=====================
==============================
Release Notes for Samba 4.21.0
September 02, 2024
==============================
This is the second release candidate of Samba 4.21. This is *not*
intended for production environments and is designed for testing
purposes only. Please report any defects via the Samba bug reporting
system at https://bugzilla.samba.org/.
Samba 4.21 will be the next version of the Samba suite.
UPGRADING
=========
This is the first stable release of the Samba 4.21 release series.
Please read the release notes carefully before upgrading.
Hardening of "valid users", "invalid users", "read list" and "write list"
-------------------------------------------------------------------------
......@@ -80,6 +74,27 @@ never took into account later changes, and so has not worked for a
number of years. Samba 4.21 and LDB 2.10 removes this unused and
broken feature.
Changes in LDB handling of Unicode
----------------------------------
Developers using LDB up to version 2.9 could call ldb_set_utf8_fns()
to determine how LDB handled casefolding. This is used internally by
string comparison functions. In LDB 2.10 this function is deprecated,
and ldb_set_utf8_functions() is preferred. The new function allows a
direct comparison function to be set as well as a casefold function.
This improves performance and allows for more robust handling of
degenerate cases. The function should be called just after ldb_init(),
with the following arguments:
ldb_set_utf8_functions(ldb, /* the struct ldb_ctx LDB object */
context_variable /* possibly NULL */
casefold_function,
case_insensitive_comparison_function);
The default behaviour of LDB remains to perform ASCII casefolding
only, as if in the "C" locale. Recent versions have become
increasingly consistent in this.
Some Samba public libraries made private by default
---------------------------------------------------
......@@ -238,6 +253,137 @@ nodes. Check in smb.conf(5) the scripts winbind_ctdb_updatekeytab.sh and
For detailed information check the smb.conf(5) and net(8) manpages.
New cephfs VFS module
---------------------
Introduce new vfs-to-cephfs bridge which uses libcephfs low-level APIs (instead
of path-based operations in the existing module). It allows users to pass
explicit user-credentials per call (including supplementary groups), as well as
faster operations using inode and file-handle caching on the Samba side.
Configuration is identical to existing module, but using 'ceph_new' instead of
'ceph' for the relevant smb.conf entries. This new module is expected to
deprecate and replace the old one in next major release.
Group Managed Service Accounts
------------------------------
Samba 4.21 adds support for gMSAs (Group Managed Service Accounts),
completing support for Functional Level 2012.
The purpose of a gMSA is to allow a single host, or a cluster of
hosts, to share access to an automatically rotating password, avoiding
the weak static service passwords that are often the entrypoint of
attackers to AD domains. Each server has a strong and regularly
rotated password, which is used to access the gMSA account of (e.g.)
the database server.
Samba provides management and client tools, allowing services on Unix
hosts to access the current and next gMSA passwords, as well as obtain
a credentials cache.
Samba 4.20 announced the client-side tools for this feature. To avoid
duplication and provide consistency, the existing commands for
password viewing have been extended, so these commands operate both on
a gMSA (with credentials, over LDAP, specify -H) and locally for
accounts that have a compatible password (e.g. plaintext via GPG,
compatible hash)
samba-tool user getpassword
samba-tool user get-kerberos-ticket
samba-tool domain exportkeytab
An example command, which gets the NT hash for use with NTLM, is
samba-tool user getpassword -H ldap://server --machine-pass \
TestUser1 --attributes=unicodePwd
Kerberos is a better choice (gMSA accounts should not use LDAP simple
binds, for reasons of both security and compatibility). Use
samba-tool user get-kerberos-ticket -H ldap://server --machine-pass \
TestUser1 --output-krb5-ccache=/srv/service/krb5_ccache
gMSAs disclose a current and previous password. To access the previous
NT hash, use:
samba-tool user getpassword -H ldap://server --machine-pass TestUser1 \
--attrs=unicodePwd;previous=1
To access the previous password as UTF8, use:
samba-tool user getpassword -H ldap://server --machine-pass TestUser1 \
--attributes=pwdLastSet,virtualClearTextUTF8;previous=1
However, Windows tools for dealing with gMSAs tend to use Active
Directory Web Services (ADWS) from Powershell for setting up the
accounts, and this separate protocol is not supported by Samba 4.21.
Samba-tool commands for handling gMSA (KDS) root keys
-----------------------------------------------------
Group managed service accounts rotate passwords based on root keys,
which can be managed using samba-tool, with commands such as
samba-tool domain kds root_key create
samba-tool domain kds root_key list
Samba will create a new root key for new domains at provision time,
but users of gMSA accounts on upgraded domains will need to first
create a root key.
RFC 8070 PKINIT "Freshness extension" supported in the Heimdal KDC
------------------------------------------------------------------
The Heimdal KDC will recognise when a client provides proof that they
hold the hardware token used for smart-card authentication 'now' and
has not used a saved future-dated reply. Samba 4.21 now matches
Windows and will assign an extra SID to the user in this case,
allowing sensitive resources to be additionally protected.
Only Windows clients are known to support the client side of this
feature at this time.
New samba-tool Authentication Policy management command structure
-----------------------------------------------------------------
As foreshadowed in the Samba 4.20 release notes, the "samba-tool
domain auth policy" commands have been reworked to be more intuitive
based on user feedback and reflection.
Support for key features of AD Domain/Forest Functional Level 2012R2
--------------------------------------------------------------------
Combined with other changes in recent versions (such as claims support
in 4.20), Samba can now claim Functional Level 2012R2 support.
Build system
------------
In previous versions of Samba, packagers of Samba would set their
package-specific version strings using a patch to the
SAMBA_VERSION_VENDOR_SUFFIX line in the ./VERSION file. Now that is
achieved by using --vendor-suffix (at configure time), allowing this
to be more easily scripted. Vendors are encouraged to include their
name and full package version to assist with upstream debugging.
More deterministic builds
-------------------------
Samba builds are now more reproducible, providing better assurance
that the Samba binaries you run are the same as what is expected from
the source code. If locale settings are not changed, the same objects
will be produced from each compilation run. If Samba is built in a
different path, the object code will remain the same, but DWARF
debugging sections will change (while remaining functionally
equivalent).
See https://reproducible-builds.org/ for more information on this
industry-wide effort and
https://tests.reproducible-builds.org/debian/rb-pkg/unstable/amd64/samba.html
for the status in Debian.
Improved command-line redaction
-------------------------------
There are several options that can be used with Samba tools for
specifying secrets. Although this is best avoided, when these options
are used, Samba will redact the secrets in /proc, so that they won't
be seen in ps or top. This is now carried out more thoroughly,
redacting more options. There is a race inherent in this, and the
passwords will be visible for a short time. The secrets are also not
removed from .bash_history and similar files.
REMOVED FEATURES
================
......@@ -270,6 +416,45 @@ smb.conf changes
sync machine password script script
CHANGES SINCE 4.21.0rc4
=======================
o David Disseldorp <ddiss@samba.org>
* BUG 15699: Incorrect FSCTL_QUERY_ALLOCATED_RANGES response when truncated.
o Noel Power <noel.power@suse.com>
* BUG 15702: Bad variable definition for ParseTuple causing test failure for
Smb3UnixTests.test_create_context_reparse.
o Shachar Sharon <ssharon@redhat.com>
* BUG 15686: Add new vfs_ceph module (based on low level API).
CHANGES SINCE 4.21.0rc3
=======================
o Pavel Filipenský <pfilipensky@samba.org>
* BUG 15698: samba-tool can not load the default configuration file.
o Shachar Sharon <ssharon@redhat.com>
* BUG 15700: Crash when readlinkat fails.
CHANGES SINCE 4.21.0rc2
=======================
o Pavel Filipenský <pfilipensky@samba.org>
* BUG 15689: Can't add/delete special keys to keytab for nfs, cifs, http etc.
o Stefan Metzmacher <metze@samba.org>
* BUG 15696: Compound SMB2 requests don't return
NT_STATUS_NETWORK_SESSION_EXPIRED for all requests, confuses
MacOSX clients.
o Anoop C S <anoopcs@samba.org>
* BUG 15689: Can't add/delete special keys to keytab for nfs, cifs, http etc.
CHANGES SINCE 4.21.0rc1
=======================
......@@ -284,7 +469,7 @@ o Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
* BUG 15673: --version-* options are still not ergonomic, and they reject
tilde characters.
o Jo Sutton <josutton@catalyst.net.nz>
o Jennifer Sutton <jennifersutton@catalyst.net.nz>
* BUG 15690: ldb_version.h is missing from ldb public library
o Pavel Filipenský <pfilipensky@samba.org>
......
......@@ -17,5 +17,6 @@ echo "
<!ENTITY pathconfig.NTP_SIGND_SOCKET_DIR '\${prefix}/var/lib/ntp_signd'>
<!ENTITY pathconfig.MITKDCPATH '\${prefix}/sbin/krb5kdc'>
<!ENTITY pathconfig.SAMBA_DATADIR '\${prefix}/var/samba'>
<!ENTITY pathconfig.CTDB_DATADIR '\${prefix}/share/ctdb'>
<!ENTITY pathconfig.CONFIGFILE '\${prefix}/etc/smb.conf'>
"
......@@ -11,7 +11,7 @@
<para>
If keytabs should be generated in clustered environments it is recommended to update them on all nodes.
You can set the config option to &pathconfig.SAMBA_DATADIR;/scripts/winbind_ctdb_updatekeytab.sh in clustering case.
You can set the config option to &pathconfig.CTDB_DATADIR;/scripts/winbind_ctdb_updatekeytab.sh in clustering case.
It is also needed to activate the <constant>46.update-keytabs.script</constant> in ctdb,
it re-creates the keytab during the ctdb recovered event:
<programlisting>
......@@ -22,5 +22,5 @@
</description>
<value type="default"/>
<value type="example">&pathconfig.SAMBA_DATADIR;/scripts/winbind_ctdb_updatekeytab.sh</value>
<value type="example">&pathconfig.CTDB_DATADIR;/scripts/winbind_ctdb_updatekeytab.sh</value>
</samba:parameter>
......@@ -105,6 +105,11 @@ dynconfig = {
'FHS-PATH': '${DATADIR}',
'OVERWRITE': True,
},
'CTDB_DATADIR' : {
'STD-PATH': '${DATADIR}/ctdb',
'FHS-PATH': '${DATADIR}/ctdb',
'OVERWRITE': True,
},
'SAMBA_DATADIR' : {
'STD-PATH': '${DATADIR}/samba',
'FHS-PATH': '${DATADIR}/samba',
......
......@@ -1132,7 +1132,7 @@ bool handle_include(struct loadparm_context *lp_ctx, struct loadparm_service *se
DEBUG(2, ("Can't find include file %s\n", fname));
return false;
return true;
}
/***************************************************************************
......
......@@ -30,7 +30,7 @@ static PyObject *py_reparse_put(PyObject *module, PyObject *args)
char *reparse = NULL;
Py_ssize_t reparse_len;
unsigned long long tag = 0;
unsigned reserved = 0;
unsigned long reserved = 0;
uint8_t *buf = NULL;
ssize_t buflen;
PyObject *result = NULL;
......
......@@ -838,8 +838,9 @@ static bool pw2kt_default_keytab_name(char *name_str, size_t name_size)
break;
default:
DBG_ERR("Invalid kerberos method set (%d)\n",
lp_kerberos_method());
DBG_NOTICE("'kerberos method' is 'secrets only' but "
"'sync machine password to keytab' is not set "
"==> no keytab will be generated.\n");
return false;
}
......
......@@ -730,7 +730,7 @@ static int vfs_ceph_ll_lookup(const struct vfs_handle_struct *handle,
struct UserPerm *uperm = NULL;
int ret = -1;
DBG_DEBUG("[ceph] ceph_ll_lookup: parent-ino=%" PRIu64 " name=%s",
DBG_DEBUG("[ceph] ceph_ll_lookup: parent-ino=%" PRIu64 " name=%s\n",
parent->ino, name);
uperm = vfs_ceph_userperm_new(handle);
......@@ -2455,7 +2455,6 @@ static int vfs_ceph_readlinkat(struct vfs_handle_struct *handle,
size_t bufsiz)
{
int result = -1;
struct vfs_ceph_iref iref = {0};
struct vfs_ceph_fh *dircfh = NULL;
DBG_DEBUG("[CEPH] readlinkat(%p, %s, %p, %llu)\n",
......@@ -2468,17 +2467,29 @@ static int vfs_ceph_readlinkat(struct vfs_handle_struct *handle,
if (result != 0) {
goto out;
}
result = vfs_ceph_ll_lookupat(handle,
dircfh,
smb_fname->base_name,
&iref);
if (result != 0) {
goto out;
}
result = vfs_ceph_ll_readlinkat(handle, dircfh, &iref, buf, bufsiz);
if (strcmp(smb_fname->base_name, "") != 0) {
struct vfs_ceph_iref iref = {0};
vfs_ceph_iput(handle, &iref);
result = vfs_ceph_ll_lookupat(handle,
dircfh,
smb_fname->base_name,
&iref);
if (result != 0) {
goto out;
}
result = vfs_ceph_ll_readlinkat(handle,
dircfh,
&iref,
buf,
bufsiz);
vfs_ceph_iput(handle, &iref);
} else {
result = vfs_ceph_ll_readlinkat(handle,
dircfh,
&dircfh->iref,
buf,
bufsiz);
}
out:
DBG_DEBUG("[CEPH] readlinkat(...) = %d\n", result);
return status_code(result);
......
......@@ -6,7 +6,9 @@ bld.INSTALL_FILES('${BINDIR}',
'smbtar',
chmod=MODE_755, flat=True)
bld.INSTALL_FILES('${BINDIR}', 'samba-log-parser', chmod=MODE_755, flat=True)
bld.INSTALL_FILES('${DATADIR}', 'winbind_ctdb_updatekeytab.sh', chmod=MODE_755, flat=True)
if conf.env.with_ctdb:
bld.INSTALL_FILES(bld.env.CTDB_DATADIR+"/scripts",
'winbind_ctdb_updatekeytab.sh', chmod=MODE_755, flat=True)
# Callout scripts for use in selftest environment
bld.SAMBA_SCRIPT('smbaddshare', pattern='smbaddshare', installdir='.')
......
......@@ -582,6 +582,10 @@ static NTSTATUS symlink_target_below_conn(
talloc_tos(), dirfsp, symlink_name, &target);
}
if (!NT_STATUS_IS_OK(status)) {
return status;
}
status = safe_symlink_target_path(talloc_tos(),
connection_path,
dirfsp->fsp_name->base_name,
......
......@@ -268,7 +268,8 @@ static bool smbd_smb2_ioctl_is_failure(uint32_t ctl_code, NTSTATUS status,
if (NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)
&& ((ctl_code == FSCTL_PIPE_TRANSCEIVE)
|| (ctl_code == FSCTL_PIPE_PEEK)
|| (ctl_code == FSCTL_DFS_GET_REFERRALS))) {
|| (ctl_code == FSCTL_DFS_GET_REFERRALS)
|| (ctl_code == FSCTL_QUERY_ALLOCATED_RANGES))) {
return false;
}
......@@ -344,6 +345,7 @@ static void smbd_smb2_request_ioctl_done(struct tevent_req *subreq)
* in:
* - fsctl_dfs_get_refers()
* - smbd_smb2_ioctl_pipe_read_done()
* - fsctl_qar()
*/
status = NT_STATUS_BUFFER_TOO_SMALL;
}
......
......@@ -3,7 +3,7 @@
Core SMB2 server
Copyright (C) Stefan Metzmacher 2009
Copyright (C) David Disseldorp 2013-2015
Copyright (C) David Disseldorp 2013-2024
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -538,6 +538,7 @@ static NTSTATUS fsctl_qar_seek_fill(TALLOC_CTX *mem_ctx,
struct files_struct *fsp,
off_t curr_off,
off_t max_off,
size_t in_max_output,
DATA_BLOB *qar_array_blob)
{
NTSTATUS status = NT_STATUS_NOT_SUPPORTED;
......@@ -578,6 +579,17 @@ static NTSTATUS fsctl_qar_seek_fill(TALLOC_CTX *mem_ctx,
return NT_STATUS_INTERNAL_ERROR;
}
if (qar_array_blob->length + sizeof(qar_buf) > in_max_output) {
/*
* Earlier check ensures space for one range or more.
* Subsequent overflow results in a truncated response.
*/
DBG_NOTICE("truncated QAR output: need > %zu, max %zu\n",
qar_array_blob->length + sizeof(qar_buf),
in_max_output);
return STATUS_BUFFER_OVERFLOW;
}
qar_buf.file_off = data_off;
/* + 1 to convert maximum offset to length */
qar_buf.len = MIN(hole_off, max_off + 1) - data_off;
......@@ -652,6 +664,13 @@ static NTSTATUS fsctl_qar(TALLOC_CTX *mem_ctx,
return NT_STATUS_INVALID_PARAMETER;
}
/* must have enough space for at least one range */
if (in_max_output < sizeof(struct file_alloced_range_buf)) {
DEBUG(2, ("QAR max %lu insufficient for one range\n",
(unsigned long)in_max_output));
return NT_STATUS_BUFFER_TOO_SMALL;
}
/*
* Maximum offset is either the last valid offset _before_ EOF, or the
* last byte offset within the requested range. -1 converts length to
......@@ -687,31 +706,24 @@ static NTSTATUS fsctl_qar(TALLOC_CTX *mem_ctx,
status = fsctl_qar_buf_push(mem_ctx, &qar_buf, &qar_array_blob);
} else {
status = fsctl_qar_seek_fill(mem_ctx, fsp, qar_req.buf.file_off,
max_off, &qar_array_blob);
}
if (!NT_STATUS_IS_OK(status)) {
return status;
max_off, in_max_output,
&qar_array_blob);
}
/* marshall response buffer. */
qar_rsp.far_buf_array = qar_array_blob;
if (NT_STATUS_IS_OK(status)
|| NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
/* marshall response. STATUS_BUFFER_OVERFLOW=truncated */
qar_rsp.far_buf_array = qar_array_blob;
ndr_ret = ndr_push_struct_blob(out_output, mem_ctx, &qar_rsp,
(ndr_push_flags_fn_t)ndr_push_fsctl_query_alloced_ranges_rsp);
if (ndr_ret != NDR_ERR_SUCCESS) {
DEBUG(0, ("failed to marshall QAR rsp\n"));
return NT_STATUS_INVALID_PARAMETER;
}
if (out_output->length > in_max_output) {
DEBUG(2, ("QAR output len %lu exceeds max %lu\n",
(unsigned long)out_output->length,
(unsigned long)in_max_output));
data_blob_free(out_output);
return NT_STATUS_BUFFER_TOO_SMALL;
ndr_ret = ndr_push_struct_blob(out_output, mem_ctx, &qar_rsp,
(ndr_push_flags_fn_t)ndr_push_fsctl_query_alloced_ranges_rsp);
if (ndr_ret != NDR_ERR_SUCCESS) {
DEBUG(0, ("failed to marshall QAR rsp\n"));
return NT_STATUS_INVALID_PARAMETER;
}
}
return NT_STATUS_OK;
return status;
}
static void smb2_ioctl_filesys_dup_extents_done(struct tevent_req *subreq);
......
......@@ -3050,6 +3050,7 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
bool signing_required = false;
bool encryption_desired = false;
bool encryption_required = false;
bool session_expired = false;
inhdr = SMBD_SMB2_IN_HDR_PTR(req);
......@@ -3098,6 +3099,9 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
signing_required = x->global->signing_flags & SMBXSRV_SIGNING_REQUIRED;
encryption_desired = x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
encryption_required = x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
session_expired =
NT_STATUS_EQUAL(session_status,
NT_STATUS_NETWORK_SESSION_EXPIRED);
}
req->async_internal = false;
......@@ -3171,7 +3175,7 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
* This check is mostly for giving the correct error code
* for compounded requests.
*/
if (!NT_STATUS_IS_OK(session_status)) {
if (!session_expired && !NT_STATUS_IS_OK(session_status)) {
return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
}
} else {
......@@ -3257,6 +3261,9 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
}
if (!NT_STATUS_IS_OK(session_status)) {
if (session_expired && opcode == SMB2_OP_CREATE) {
req->compound_create_err = session_status;
}
return smbd_smb2_request_error(req, session_status);
}
}
......@@ -3308,11 +3315,18 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
skipped_signing:
if (flags & SMB2_HDR_FLAG_CHAINED) {
if (!NT_STATUS_IS_OK(req->compound_create_err)) {
return smbd_smb2_request_error(req,
req->compound_create_err);
}
req->compound_related = true;
}
if (call->need_session) {
if (!NT_STATUS_IS_OK(session_status)) {
if (session_expired && opcode == SMB2_OP_CREATE) {
req->compound_create_err = session_status;
}
return smbd_smb2_request_error(req, session_status);
}
}
......
......@@ -86,7 +86,8 @@ static bool smb2_ioctl_is_failure(uint32_t ctl_code, NTSTATUS status,
if (NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)
&& ((ctl_code == FSCTL_PIPE_TRANSCEIVE)
|| (ctl_code == FSCTL_PIPE_PEEK)
|| (ctl_code == FSCTL_DFS_GET_REFERRALS))) {
|| (ctl_code == FSCTL_DFS_GET_REFERRALS)
|| (ctl_code == FSCTL_QUERY_ALLOCATED_RANGES))) {
return false;
}
......
......@@ -3,7 +3,7 @@
test suite for SMB2 ioctl operations
Copyright (C) David Disseldorp 2011-2016
Copyright (C) David Disseldorp 2011-2024
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -3838,6 +3838,151 @@ static bool test_ioctl_sparse_qar_malformed(struct torture_context *torture,
return true;
}
static bool test_ioctl_sparse_qar_truncated(struct torture_context *torture,
struct smb2_tree *tree)
{
struct smb2_handle fh;
union smb_ioctl ioctl;
struct file_alloced_range_buf far_buf;
NTSTATUS status;
enum ndr_err_code ndr_ret;
TALLOC_CTX *tmp_ctx = talloc_new(tree);
bool ok;
struct file_alloced_range_buf far_rsp;
ok = test_setup_create_fill(torture, tree, tmp_ctx,
FNAME, &fh, 0, SEC_RIGHTS_FILE_ALL,
FILE_ATTRIBUTE_NORMAL);
torture_assert(torture, ok, "setup file");
status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &fh,
FILE_SUPPORTS_SPARSE_FILES, &ok);
torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
if (!ok) {
smb2_util_close(tree, fh);
torture_skip(torture, "Sparse files not supported\n");
}
status = test_ioctl_sparse_req(torture, tmp_ctx, tree, fh, true);
torture_assert_ntstatus_ok(torture, status, "FSCTL_SET_SPARSE");
/*
* Write 0 and 1M offsets as (hopefully) two separate extents.
* XXX this test assumes that these ranges will be recorded as separate
* FSCTL_QUERY_ALLOCATED_RANGES extents, which isn't strictly required:
* the spec basically says the FS can do what it wants as long as
* non-zeroed data ranges aren't reported as sparse holes.
*/
ok = write_pattern(torture, tree, tmp_ctx, fh,
0, /* off */
1024, /* len */
0); /* pattern offset */
torture_assert(torture, ok, "write pattern");
ok = write_pattern(torture, tree, tmp_ctx, fh,
1024 * 1024, /* off */
1024, /* len */
0); /* pattern offset */
torture_assert(torture, ok, "write pattern");
/* qar max output enough to carry one range, should be truncated */
ZERO_STRUCT(ioctl);
ioctl.smb2.level = RAW_IOCTL_SMB2;
ioctl.smb2.in.file.handle = fh;
ioctl.smb2.in.function = FSCTL_QUERY_ALLOCATED_RANGES;
ioctl.smb2.in.max_output_response = sizeof(struct file_alloced_range_buf);
ioctl.smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
far_buf.file_off = 0;
far_buf.len = 2048 * 1024;
ndr_ret = ndr_push_struct_blob(&ioctl.smb2.in.out, tmp_ctx,
&far_buf,
(ndr_push_flags_fn_t)ndr_push_file_alloced_range_buf);
torture_assert_ndr_success(torture, ndr_ret, "push far ndr buf");
status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
torture_assert_ntstatus_equal(torture, status,
STATUS_BUFFER_OVERFLOW, "qar truncated");
torture_assert_size_equal(torture,
ioctl.smb2.out.out.length, sizeof(far_buf),
"qar outlen");
ndr_ret = ndr_pull_struct_blob(&ioctl.smb2.out.out, tmp_ctx,
&far_rsp,
(ndr_pull_flags_fn_t)ndr_pull_file_alloced_range_buf);
torture_assert_ndr_success(torture, ndr_ret, "pull far range");
torture_assert_u64_equal(torture, far_rsp.file_off, 0, "far offset");
/* length depends on allocation behaviour of FS, so allow range */
torture_assert(torture, far_rsp.len >= 1024, "far len");
/* qar max output for just under 2 ranges, should be truncated */
ZERO_STRUCT(ioctl);
ioctl.smb2.level = RAW_IOCTL_SMB2;
ioctl.smb2.in.file.handle = fh;
ioctl.smb2.in.function = FSCTL_QUERY_ALLOCATED_RANGES;
ioctl.smb2.in.max_output_response = 31;
ioctl.smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
far_buf.file_off = 0;
far_buf.len = 2048 * 1024;
ndr_ret = ndr_push_struct_blob(&ioctl.smb2.in.out, tmp_ctx,
&far_buf,
(ndr_push_flags_fn_t)ndr_push_file_alloced_range_buf);
torture_assert_ndr_success(torture, ndr_ret, "push far ndr buf");
status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
torture_assert_ntstatus_equal(torture, status,
STATUS_BUFFER_OVERFLOW, "qar truncated");
torture_assert_size_equal(torture,
ioctl.smb2.out.out.length, sizeof(far_buf),
"qar outlen");
ndr_ret = ndr_pull_struct_blob(&ioctl.smb2.out.out, tmp_ctx,
&far_rsp,
(ndr_pull_flags_fn_t)ndr_pull_file_alloced_range_buf);
torture_assert_ndr_success(torture, ndr_ret, "pull far range");
torture_assert_u64_equal(torture, far_rsp.file_off, 0, "far offset");
torture_assert(torture, far_rsp.len >= 1024, "far len");
/* qar max output for 2 ranges, should pass */
ZERO_STRUCT(ioctl);
ioctl.smb2.level = RAW_IOCTL_SMB2;
ioctl.smb2.in.file.handle = fh;
ioctl.smb2.in.function = FSCTL_QUERY_ALLOCATED_RANGES;
ioctl.smb2.in.max_output_response = 32;
ioctl.smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
far_buf.file_off = 0;
far_buf.len = 2048 * 1024;
ndr_ret = ndr_push_struct_blob(&ioctl.smb2.in.out, tmp_ctx,
&far_buf,
(ndr_push_flags_fn_t)ndr_push_file_alloced_range_buf);
torture_assert_ndr_success(torture, ndr_ret, "push far ndr buf");
status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
torture_assert_ntstatus_ok(torture, status, "qar non-truncated");
torture_assert_size_equal(torture,
ioctl.smb2.out.out.length,
2 * sizeof(far_buf), "qar outlen");
ndr_ret = ndr_pull_struct_blob(&ioctl.smb2.out.out, tmp_ctx,
&far_rsp,
(ndr_pull_flags_fn_t)ndr_pull_file_alloced_range_buf);
torture_assert_ndr_success(torture, ndr_ret, "pull far range");
torture_assert_u64_equal(torture, far_rsp.file_off, 0, "far offset");
torture_assert(torture, far_rsp.len >= 1024, "far len");
/* move to next buffer */
ioctl.smb2.out.out.data += sizeof(far_buf);
ioctl.smb2.out.out.length -= sizeof(far_buf);
ndr_ret = ndr_pull_struct_blob(&ioctl.smb2.out.out, tmp_ctx,
&far_rsp,
(ndr_pull_flags_fn_t)ndr_pull_file_alloced_range_buf);
torture_assert_ndr_success(torture, ndr_ret, "pull far range");
torture_assert_u64_equal(torture, far_rsp.file_off, 1024 * 1024,
"far offset");
torture_assert(torture, far_rsp.len >= 1024, "far len");
smb2_util_close(tree, fh);
talloc_free(tmp_ctx);
return true;
}
bool test_ioctl_alternate_data_stream(struct torture_context *tctx)
{
bool ret = false;
......@@ -7548,6 +7693,8 @@ struct torture_suite *torture_smb2_ioctl_init(TALLOC_CTX *ctx)
test_ioctl_sparse_qar);
torture_suite_add_1smb2_test(suite, "sparse_qar_malformed",
test_ioctl_sparse_qar_malformed);
torture_suite_add_1smb2_test(suite, "sparse_qar_truncated",
test_ioctl_sparse_qar_truncated);
torture_suite_add_1smb2_test(suite, "sparse_punch",
test_ioctl_sparse_punch);
torture_suite_add_1smb2_test(suite, "sparse_hole_dealloc",
......
......@@ -1317,6 +1317,7 @@ static bool test_session_expire2i(struct torture_context *tctx,
char fname[256];
struct smb2_handle dh;
struct smb2_handle dh2;
struct smb2_handle relhandle = { .data = { UINT64_MAX, UINT64_MAX } };
struct smb2_handle _h1;
struct smb2_handle *h1 = NULL;
struct smb2_create io1;
......@@ -1330,7 +1331,10 @@ static bool test_session_expire2i(struct torture_context *tctx,
struct smb2_ioctl ctl;
struct smb2_break oack;
struct smb2_lease_break_ack lack;
struct smb2_create cio;
struct smb2_find fnd;
struct smb2_close cl;
struct smb2_request *reqs[3] = { NULL, };
union smb_search_data *d = NULL;
unsigned int count;
struct smb2_request *req = NULL;
......@@ -1562,6 +1566,58 @@ static bool test_session_expire2i(struct torture_context *tctx,
ret, done, "smb2_find_level "
"returned unexpected status");
/* Now do a compound open + query directory + close handle. */
smb2_transport_compound_start(tree->session->transport, 3);
torture_comment(tctx, "Compound: Open+QueryDirectory+Close => EXPIRED\n");
ZERO_STRUCT(cio);
cio.in.oplock_level = 0;
cio.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_DIR_READ_ATTRIBUTE | SEC_DIR_LIST;
cio.in.file_attributes = 0;
cio.in.create_disposition = NTCREATEX_DISP_OPEN;
cio.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE;
cio.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT;
cio.in.fname = "";
reqs[0] = smb2_create_send(tree, &cio);
torture_assert_not_null_goto(tctx, reqs[0], ret, done,
"smb2_create_send failed\n");
smb2_transport_compound_set_related(tree->session->transport, true);
ZERO_STRUCT(fnd);
fnd.in.file.handle = relhandle;
fnd.in.pattern = "*";
fnd.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE;
fnd.in.max_response_size= 0x100;
fnd.in.level = SMB2_FIND_BOTH_DIRECTORY_INFO;
reqs[1] = smb2_find_send(tree, &fnd);
torture_assert_not_null_goto(tctx, reqs[1], ret, done,
"smb2_find_send failed\n");
ZERO_STRUCT(cl);
cl.in.file.handle = relhandle;
reqs[2] = smb2_close_send(tree, &cl);
torture_assert_not_null_goto(tctx, reqs[2], ret, done,
"smb2_close_send failed\n");
status = smb2_create_recv(reqs[0], tree, &cio);
torture_assert_ntstatus_equal_goto(tctx, status,
NT_STATUS_NETWORK_SESSION_EXPIRED,
ret, done, "smb2_create "
"returned unexpected status");
status = smb2_find_recv(reqs[1], tree, &fnd);
torture_assert_ntstatus_equal_goto(tctx, status,
NT_STATUS_NETWORK_SESSION_EXPIRED,
ret, done, "smb2_find "
"returned unexpected status");
status = smb2_close_recv(reqs[2], &cl);
torture_assert_ntstatus_equal_goto(tctx, status,
NT_STATUS_NETWORK_SESSION_EXPIRED,
ret, done, "smb2_close "
"returned unexpected status");
torture_comment(tctx, "1st notify => CANCEL\n");
smb2_cancel(req);
......