[Pkg-samba-maint] [samba] 01/01: Imported Upstream version 4.3.6+dfsg
Jelmer Vernooij
jelmer at moszumanska.debian.org
Wed Mar 9 03:28:21 UTC 2016
This is an automated email from the git hooks/post-receive script.
jelmer pushed a commit to annotated tag upstream/4.3.6+dfsg
in repository samba.
commit 2ce684deb1c267a84fe6fc762a11911c77f80ede
Author: Jelmer Vernooij <jelmer at jelmer.uk>
Date: Sat Feb 27 23:27:47 2016 +0000
Imported Upstream version 4.3.6+dfsg
---
VERSION | 2 +-
WHATSNEW.txt | 247 +++-
auth/credentials/pycredentials.c | 8 +
ctdb/common/system_aix.c | 4 +-
ctdb/common/system_common.c | 2 +-
ctdb/common/system_freebsd.c | 4 +-
ctdb/common/system_gnu.c | 4 +-
ctdb/common/system_kfreebsd.c | 4 +-
ctdb/common/system_linux.c | 12 +-
ctdb/config/events.d/11.natgw | 4 -
ctdb/config/events.d/49.winbind | 7 -
ctdb/tools/ctdb.c | 4 +-
ctdb/utils/smnotify/smnotify.c | 6 +-
docs-xml/manpages/smbspool_krb5_wrapper.8.xml | 64 +
docs-xml/manpages/vfs_gpfs.8.xml | 6 +-
docs-xml/smbdotconf/winbind/idmapconfig.xml | 15 +-
docs-xml/wscript_build | 1 +
docs/manpages/dbwrap_tool.1 | 4 +-
docs/manpages/eventlogadm.8 | 4 +-
docs/manpages/findsmb.1 | 4 +-
docs/manpages/idmap_ad.8 | 4 +-
docs/manpages/idmap_autorid.8 | 4 +-
docs/manpages/idmap_hash.8 | 4 +-
docs/manpages/idmap_ldap.8 | 4 +-
docs/manpages/idmap_nss.8 | 4 +-
docs/manpages/idmap_rfc2307.8 | 4 +-
docs/manpages/idmap_rid.8 | 4 +-
docs/manpages/idmap_script.8 | 4 +-
docs/manpages/idmap_tdb.8 | 4 +-
docs/manpages/idmap_tdb2.8 | 4 +-
docs/manpages/libsmbclient.7 | 4 +-
docs/manpages/lmhosts.5 | 4 +-
docs/manpages/log2pcap.1 | 4 +-
docs/manpages/net.8 | 4 +-
docs/manpages/nmbd.8 | 4 +-
docs/manpages/nmblookup.1 | 4 +-
docs/manpages/ntlm_auth.1 | 4 +-
docs/manpages/pam_winbind.8 | 4 +-
docs/manpages/pam_winbind.conf.5 | 4 +-
docs/manpages/pdbedit.8 | 4 +-
docs/manpages/profiles.1 | 4 +-
docs/manpages/rpcclient.1 | 4 +-
docs/manpages/samba-regedit.8 | 4 +-
docs/manpages/samba-tool.8 | 4 +-
docs/manpages/samba.7 | 4 +-
docs/manpages/samba.8 | 4 +-
docs/manpages/sharesec.1 | 4 +-
docs/manpages/smb.conf.5 | 8 +-
docs/manpages/smbcacls.1 | 4 +-
docs/manpages/smbclient.1 | 4 +-
docs/manpages/smbcontrol.1 | 4 +-
docs/manpages/smbcquotas.1 | 4 +-
docs/manpages/smbd.8 | 4 +-
docs/manpages/smbget.1 | 4 +-
docs/manpages/smbgetrc.5 | 4 +-
docs/manpages/smbpasswd.5 | 4 +-
docs/manpages/smbpasswd.8 | 4 +-
docs/manpages/smbspool.8 | 4 +-
.../{vfs_xattr_tdb.8 => smbspool_krb5_wrapper.8} | 31 +-
docs/manpages/smbstatus.1 | 4 +-
docs/manpages/smbta-util.8 | 4 +-
docs/manpages/smbtar.1 | 4 +-
docs/manpages/smbtree.1 | 4 +-
docs/manpages/testparm.1 | 4 +-
docs/manpages/vfs_acl_tdb.8 | 4 +-
docs/manpages/vfs_acl_xattr.8 | 4 +-
docs/manpages/vfs_aio_fork.8 | 4 +-
docs/manpages/vfs_aio_linux.8 | 4 +-
docs/manpages/vfs_aio_pthread.8 | 4 +-
docs/manpages/vfs_audit.8 | 4 +-
docs/manpages/vfs_btrfs.8 | 4 +-
docs/manpages/vfs_cacheprime.8 | 4 +-
docs/manpages/vfs_cap.8 | 4 +-
docs/manpages/vfs_catia.8 | 4 +-
docs/manpages/vfs_ceph.8 | 4 +-
docs/manpages/vfs_commit.8 | 4 +-
docs/manpages/vfs_crossrename.8 | 4 +-
docs/manpages/vfs_default_quota.8 | 4 +-
docs/manpages/vfs_dirsort.8 | 4 +-
docs/manpages/vfs_extd_audit.8 | 4 +-
docs/manpages/vfs_fake_perms.8 | 4 +-
docs/manpages/vfs_fileid.8 | 4 +-
docs/manpages/vfs_fruit.8 | 4 +-
docs/manpages/vfs_full_audit.8 | 4 +-
docs/manpages/vfs_glusterfs.8 | 4 +-
docs/manpages/vfs_gpfs.8 | 12 +-
docs/manpages/vfs_linux_xfs_sgid.8 | 4 +-
docs/manpages/vfs_media_harmony.8 | 4 +-
docs/manpages/vfs_netatalk.8 | 4 +-
docs/manpages/vfs_prealloc.8 | 4 +-
docs/manpages/vfs_preopen.8 | 4 +-
docs/manpages/vfs_readahead.8 | 4 +-
docs/manpages/vfs_readonly.8 | 4 +-
docs/manpages/vfs_recycle.8 | 4 +-
docs/manpages/vfs_scannedonly.8 | 4 +-
docs/manpages/vfs_shadow_copy.8 | 4 +-
docs/manpages/vfs_shadow_copy2.8 | 4 +-
docs/manpages/vfs_shell_snap.8 | 4 +-
docs/manpages/vfs_smb_traffic_analyzer.8 | 4 +-
docs/manpages/vfs_snapper.8 | 4 +-
docs/manpages/vfs_streams_depot.8 | 4 +-
docs/manpages/vfs_streams_xattr.8 | 4 +-
docs/manpages/vfs_syncops.8 | 4 +-
docs/manpages/vfs_time_audit.8 | 4 +-
docs/manpages/vfs_tsmsm.8 | 4 +-
docs/manpages/vfs_unityed_media.8 | 4 +-
docs/manpages/vfs_worm.8 | 4 +-
docs/manpages/vfs_xattr_tdb.8 | 4 +-
docs/manpages/vfs_zfsacl.8 | 4 +-
docs/manpages/vfstest.1 | 4 +-
docs/manpages/wbinfo.1 | 4 +-
docs/manpages/winbind_krb5_locator.7 | 4 +-
docs/manpages/winbindd.8 | 4 +-
lib/async_req/wscript_build | 3 +-
lib/dbwrap/dbwrap_rbt.c | 159 ++-
lib/param/loadparm.c | 56 +-
lib/tsocket/tsocket_bsd.c | 62 +-
lib/util/util_strlist.c | 18 +-
librpc/idl/dns.idl | 18 +-
librpc/idl/dnsp.idl | 4 +-
librpc/idl/dnsserver.idl | 2 +-
librpc/ndr/ndr_dns.c | 27 +
librpc/ndr/ndr_dnsp.c | 24 +
librpc/ndr/ndr_dnsp.h | 4 +
librpc/wscript_build | 20 +-
python/samba/__init__.py | 24 +
python/samba/join.py | 19 +-
python/samba/netcmd/domain.py | 23 +-
python/samba/netcmd/fsmo.py | 3 +-
python/samba/tests/core.py | 16 +
python/samba/tests/dns.py | 640 ++++++---
python/samba/tests/{getopt.py => get_opt.py} | 0
selftest/knownfail | 2 +
selftest/target/Samba3.pm | 71 +
selftest/tests.py | 2 +-
source3/client/README.smbspool | 17 +
source3/client/client.c | 4 +-
source3/client/smbspool_krb5_wrapper.c | 210 +++
source3/include/proto.h | 1 -
source3/include/vfs.h | 12 +-
source3/lib/errmap_unix.c | 3 +
source3/libsmb/cli_smb2_fnum.c | 5 +-
source3/libsmb/cli_smb2_fnum.h | 1 +
source3/libsmb/clifile.c | 135 +-
source3/libsmb/libsmb_server.c | 4 +-
source3/libsmb/proto.h | 20 +-
source3/locking/locking.c | 3 +-
source3/modules/vfs_acl_common.c | 4 +-
source3/modules/vfs_fruit.c | 185 ++-
source3/modules/vfs_shadow_copy2.c | 107 +-
source3/modules/vfs_streams_xattr.c | 39 +-
source3/param/loadparm.c | 265 ++--
source3/script/tests/test_dfree_command.sh | 17 +-
source3/script/tests/test_shadow_copy.sh | 290 +++++
source3/selftest/tests.py | 7 +-
source3/smbd/close.c | 6 +-
source3/smbd/dfree.c | 9 +-
source3/smbd/dosmode.c | 32 +-
source3/smbd/fileio.c | 8 +-
source3/smbd/nttrans.c | 13 +
source3/smbd/open.c | 24 +-
source3/smbd/oplock.c | 3 +-
source3/smbd/posix_acls.c | 39 +-
source3/smbd/reply.c | 2 +-
source3/smbd/smb2_close.c | 2 +-
source3/smbd/smb2_create.c | 8 +
source3/smbd/trans2.c | 68 +-
source3/smbd/vfs.c | 82 +-
source3/torture/nbio.c | 2 +-
source3/torture/torture.c | 415 ++++++
source3/utils/smbcacls.c | 2 +-
source3/utils/smbget.c | 15 +-
source3/winbindd/winbindd_ads.c | 26 +-
source3/winbindd/winbindd_cache.c | 4 +-
source3/winbindd/winbindd_cm.c | 104 ++
source3/winbindd/winbindd_dual_srv.c | 8 -
source3/winbindd/winbindd_ndr.c | 3 +
source3/winbindd/winbindd_proto.h | 4 +
source3/winbindd/winbindd_reconnect.c | 38 +-
...nbindd_reconnect.c => winbindd_reconnect_ads.c} | 249 ++--
source3/wscript_build | 9 +
source4/auth/ntlm/auth_sam.c | 9 +-
source4/auth/sam.c | 158 ++-
source4/dns_server/dns_query.c | 15 +-
source4/dns_server/dns_update.c | 31 +-
source4/dsdb/tests/python/password_lockout.py | 359 +++++-
source4/kdc/hdb-samba4.c | 7 +-
source4/librpc/wscript_build | 4 +-
source4/scripting/devel/createtrust | 18 +-
source4/selftest/tests.py | 3 +-
source4/torture/smb2/create.c | 64 +
source4/torture/vfs/fruit.c | 1359 +++++++++++++++++---
testprogs/blackbox/dfree.sh | 8 +-
193 files changed, 5125 insertions(+), 1428 deletions(-)
diff --git a/VERSION b/VERSION
index 083561f..2dec4b2 100644
--- a/VERSION
+++ b/VERSION
@@ -25,7 +25,7 @@
########################################################
SAMBA_VERSION_MAJOR=4
SAMBA_VERSION_MINOR=3
-SAMBA_VERSION_RELEASE=3
+SAMBA_VERSION_RELEASE=6
########################################################
# If a official release has a serious bug #
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index ba2e101..a47ede4 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -1,4 +1,247 @@
=============================
+ Release Notes for Samba 4.3.6
+ March 8, 2016
+ =============================
+
+
+This is a security release in order to address the following CVEs:
+
+o CVE-2015-7560 (Incorrect ACL get/set allowed on symlink path)
+o CVE-2016-0771 (Out-of-bounds read in internal DNS server)
+
+=======
+Details
+=======
+
+o CVE-2015-7560:
+ All versions of Samba from 3.2.0 to 4.4.0rc3 inclusive are vulnerable to
+ a malicious client overwriting the ownership of ACLs using symlinks.
+
+ An authenticated malicious client can use SMB1 UNIX extensions to
+ create a symlink to a file or directory, and then use non-UNIX SMB1
+ calls to overwrite the contents of the ACL on the file or directory
+ linked to.
+
+o CVE-2016-0771:
+ All versions of Samba from 4.0.0 to 4.4.0rc3 inclusive, when deployed as
+ an AD DC and choose to run the internal DNS server, are vulnerable to an
+ out-of-bounds read issue during DNS TXT record handling caused by users
+ with permission to modify DNS records.
+
+ A malicious client can upload a specially constructed DNS TXT record,
+ resulting in a remote denial-of-service attack. As long as the affected
+ TXT record remains undisturbed in the Samba database, a targeted DNS
+ query may continue to trigger this exploit.
+
+ While unlikely, the out-of-bounds read may bypass safety checks and
+ allow leakage of memory from the server in the form of a DNS TXT reply.
+
+ By default only authenticated accounts can upload DNS records,
+ as "allow dns updates = secure only" is the default.
+ Any other value would allow anonymous clients to trigger this
+ bug, which is a much higher risk.
+
+
+Changes since 4.3.5:
+--------------------
+
+o Jeremy Allison <jra at samba.org>
+ * BUG 11648: CVE-2015-7560: Getting and setting Windows ACLs on symlinks can
+ change permissions on link target.
+
+o Garming Sam <garming at catalyst.net.nz>
+ * BUGs 11128, 11686: CVE-2016-0771: Read of uninitialized memory DNS TXT
+ handling.
+
+o Stefan Metzmacher <metze at samba.org>
+ * BUGs 11128, 11686: CVE-2016-0771: Read of uninitialized memory DNS TXT
+ handling.
+
+
+#######################################
+Reporting bugs & Development Discussion
+#######################################
+
+Please discuss this release on the samba-technical mailing list or by
+joining the #samba-technical IRC channel on irc.freenode.net.
+
+If you do report problems then please try to send high quality
+feedback. If you don't provide vital information to help us track down
+the problem then you will probably be ignored. All bug reports should
+be filed under the "Samba 4.1 and newer" product in the project's Bugzilla
+database (https://bugzilla.samba.org/).
+
+
+======================================================================
+== Our Code, Our Bugs, Our Responsibility.
+== The Samba Team
+======================================================================
+
+
+Older release notes to follow:
+------------------------------
+
+ =============================
+ Release Notes for Samba 4.3.5
+ February 23, 2016
+ =============================
+
+
+This is the latest stable release of Samba 4.3.
+
+
+Changes since 4.3.4:
+--------------------
+
+o Jeremy Allison <jra at samba.org>
+ * BUG 10489: s3: smbd: posix_acls: Fix check for setting u:g:o entry on a
+ filesystem with no ACL support.
+ * BUG 11703: s3: smbd: Fix timestamp rounding inside SMB2 create.
+
+o Christian Ambach <ambi at samba.org>
+ * BUG 6482: s3:utils/smbget: Fix recursive download.
+ * BUG 11400: s3:smbd/oplock: Obey kernel oplock setting when releasing
+ oplocks.
+
+o Alexander Bokovoy <ab at samba.org>
+ * BUG 11693: s3-parm: Clean up defaults when removing global parameters.
+
+o Ralph Boehme <slow at samba.org>
+ * BUG 11684: s3:smbd: Ignore initial allocation size for directory creation.
+ * BUG 11714: lib/tsocket: Work around sockets not supporting FIONREAD.
+
+o Amitay Isaacs <amitay at gmail.com>
+ * BUG 11705: ctdb: Remove error messages after kernel security update
+ (CVE-2015-8543).
+
+o Volker Lendecke <vl at samba.org>
+ * BUG 11732: param: Fix str_list_v3 to accept ";" again.
+
+o Stefan Metzmacher <metze at samba.org>
+ * BUG 11699: Use M2Crypto.RC4.RC4 on platforms without Crypto.Cipher.ARC4.
+
+o Jose A. Rivera <jarrpa at samba.org>
+ * BUG 11727: s3:smbd:open: Skip redundant call to file_set_dosmode when
+ creating a new file.
+
+o Christof Schmitt <cs at samba.org>
+ * BUG 11670: winbindd: Handle expired sessions correctly.
+
+o Andreas Schneider <asn at samba.org>
+ * BUG 11690: s3-client: Add a KRB5 wrapper for smbspool.
+
+o Uri Simchoni <uri at samba.org>
+ * BUG 11580: vfs_shadow_copy2: Fix case where snapshots are outside the
+ share.
+ * BUG 11662: smbclient: Query disk usage relative to current directory.
+ * BUG 11681: smbd: Show correct disk size for different quota and dfree block
+ sizes.
+ * BUG 11682: smbcacls: Fix uninitialized variable.
+
+o Martin Schwenke <martin at meltin.net>
+ * BUG 11719: ctdb-scripts: Drop use of "smbcontrol winbindd ip-dropped ...".
+
+o Hemanth Thummala <hemanth.thummala at nutanix.com>
+ * BUG 11708: loadparm: Fix memory leak issue.
+
+
+#######################################
+Reporting bugs & Development Discussion
+#######################################
+
+Please discuss this release on the samba-technical mailing list or by
+joining the #samba-technical IRC channel on irc.freenode.net.
+
+If you do report problems then please try to send high quality
+feedback. If you don't provide vital information to help us track down
+the problem then you will probably be ignored. All bug reports should
+be filed under the "Samba 4.1 and newer" product in the project's Bugzilla
+database (https://bugzilla.samba.org/).
+
+
+======================================================================
+== Our Code, Our Bugs, Our Responsibility.
+== The Samba Team
+======================================================================
+
+
+----------------------------------------------------------------------
+
+
+ =============================
+ Release Notes for Samba 4.3.4
+ January 12, 2016
+ =============================
+
+
+This is the latest stable release of Samba 4.3.
+
+
+Changes since 4.3.3:
+--------------------
+
+o Michael Adam <obnox at samba.org>
+ * BUG 11619: doc: Fix a typo in the smb.conf manpage, explanation of idmap
+ config.
+ * BUG 11647: s3:smbd: Fix a corner case of the symlink verification.
+
+o Jeremy Allison <jra at samba.org>
+ * BUG 11624: s3: libsmb: Correctly initialize the list head when keeping a
+ list of primary followed by DFS connections.
+ * BUG 11625: Reduce the memory footprint of empty string options.
+
+o Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
+ * BUG 11659: Update lastLogon and lastLogonTimestamp.
+
+o Ralph Boehme <slow at samba.org>
+ * BUG 11065: vfs_fruit: Enable POSIX directory rename semantics.
+ * BUG 11466: Copying files with vfs_fruit fails when using vfs_streams_xattr
+ without stream prefix and type suffix.
+ * BUG 11645: smbd: Make "hide dot files" option work with "store dos
+ attributes = yes".
+
+o Günther Deschner <gd at samba.org>
+ * BUG 11639: lib/async_req: Do not install async_connect_send_test.
+
+o Stefan Metzmacher <metze at samba.org>
+ * BUG 11394: Crash: Bad talloc magic value - access after free.
+
+o Rowland Penny <repenny241155 at gmail.com>
+ * BUG 11613: samba-tool: Fix uncaught exception if no fSMORoleOwner
+ attribute is given.
+
+o Karolin Seeger <kseeger at samba.org>
+ * BUG 11619: docs: Fix some typos in the idmap backend section.
+ * BUG 11641: docs: Fix typos in man vfs_gpfs.
+
+o Uri Simchoni <uri at samba.org>
+ * BUG 11649: smbd: Do not disable "store dos attributes" on-the-fly.
+
+
+#######################################
+Reporting bugs & Development Discussion
+#######################################
+
+Please discuss this release on the samba-technical mailing list or by
+joining the #samba-technical IRC channel on irc.freenode.net.
+
+If you do report problems then please try to send high quality
+feedback. If you don't provide vital information to help us track down
+the problem then you will probably be ignored. All bug reports should
+be filed under the "Samba 4.1 and newer" product in the project's Bugzilla
+database (https://bugzilla.samba.org/).
+
+
+======================================================================
+== Our Code, Our Bugs, Our Responsibility.
+== The Samba Team
+======================================================================
+
+
+----------------------------------------------------------------------
+
+
+ =============================
Release Notes for Samba 4.3.3
December 16, 2015
=============================
@@ -142,8 +385,8 @@ database (https://bugzilla.samba.org/).
======================================================================
-Older release notes to follow:
-------------------------------
+----------------------------------------------------------------------
+
=============================
Release Notes for Samba 4.3.2
diff --git a/auth/credentials/pycredentials.c b/auth/credentials/pycredentials.c
index e32d9a9..5fc2a70 100644
--- a/auth/credentials/pycredentials.c
+++ b/auth/credentials/pycredentials.c
@@ -209,6 +209,12 @@ static PyObject *py_creds_get_nt_hash(pytalloc_Object *self)
return PyString_FromStringAndSize(discard_const_p(char, ntpw->hash), 16);
}
+static PyObject *py_creds_get_kerberos_state(pytalloc_Object *self)
+{
+ int state = cli_credentials_get_kerberos_state(PyCredentials_AsCliCredentials(self));
+ return PyInt_FromLong(state);
+}
+
static PyObject *py_creds_set_kerberos_state(pytalloc_Object *self, PyObject *args)
{
int state;
@@ -452,6 +458,8 @@ static PyMethodDef py_creds_methods[] = {
"Parse credentials string." },
{ "get_nt_hash", (PyCFunction)py_creds_get_nt_hash, METH_NOARGS,
NULL },
+ { "get_kerberos_state", (PyCFunction)py_creds_get_kerberos_state, METH_NOARGS,
+ NULL },
{ "set_kerberos_state", (PyCFunction)py_creds_set_kerberos_state, METH_VARARGS,
NULL },
{ "set_krb_forwardable", (PyCFunction)py_creds_set_krb_forwardable, METH_VARARGS,
diff --git a/ctdb/common/system_aix.c b/ctdb/common/system_aix.c
index 41f61ae..2637442 100644
--- a/ctdb/common/system_aix.c
+++ b/ctdb/common/system_aix.c
@@ -44,7 +44,7 @@ int ctdb_sys_open_sending_socket(void)
int s, ret;
uint32_t one = 1;
- s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+ s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (s == -1) {
DEBUG(DEBUG_CRIT,(" failed to open raw socket (%s)\n",
strerror(errno)));
@@ -121,7 +121,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
- s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+ s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (s == -1) {
DEBUG(DEBUG_CRIT,(" failed to open raw socket (%s)\n",
strerror(errno)));
diff --git a/ctdb/common/system_common.c b/ctdb/common/system_common.c
index 899f3b5..3e30a6c 100644
--- a/ctdb/common/system_common.c
+++ b/ctdb/common/system_common.c
@@ -85,7 +85,7 @@ char *ctdb_sys_find_ifname(ctdb_sock_addr *addr)
struct ifconf ifc;
char *ptr;
- s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+ s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (s == -1) {
DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket (%s)\n",
strerror(errno)));
diff --git a/ctdb/common/system_freebsd.c b/ctdb/common/system_freebsd.c
index 9597a7a..02f7cce 100644
--- a/ctdb/common/system_freebsd.c
+++ b/ctdb/common/system_freebsd.c
@@ -158,7 +158,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
ip4pkt.tcp.th_sum = tcp_checksum((uint16_t *)&ip4pkt.tcp, sizeof(ip4pkt.tcp), &ip4pkt.ip);
/* open a raw socket to send this segment from */
- s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+ s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (s == -1) {
DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket (%s)\n",
strerror(errno)));
@@ -208,7 +208,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
ip6pkt.tcp.th_win = htons(1234);
ip6pkt.tcp.th_sum = tcp_checksum6((uint16_t *)&ip6pkt.tcp, sizeof(ip6pkt.tcp), &ip6pkt.ip6);
- s = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW);
+ s = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
if (s == -1) {
DEBUG(DEBUG_CRIT, (__location__ " Failed to open sending socket\n"));
return -1;
diff --git a/ctdb/common/system_gnu.c b/ctdb/common/system_gnu.c
index 2ab1399..1e0ae4c 100644
--- a/ctdb/common/system_gnu.c
+++ b/ctdb/common/system_gnu.c
@@ -156,7 +156,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
ip4pkt.tcp.check = tcp_checksum((uint16_t *)&ip4pkt.tcp, sizeof(ip4pkt.tcp), &ip4pkt.ip);
/* open a raw socket to send this segment from */
- s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+ s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (s == -1) {
DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket (%s)\n",
strerror(errno)));
@@ -203,7 +203,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
ip6pkt.tcp.window = htons(1234);
ip6pkt.tcp.check = tcp_checksum6((uint16_t *)&ip6pkt.tcp, sizeof(ip6pkt.tcp), &ip6pkt.ip6);
- s = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW);
+ s = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
if (s == -1) {
DEBUG(DEBUG_CRIT, (__location__ " Failed to open sending socket\n"));
return -1;
diff --git a/ctdb/common/system_kfreebsd.c b/ctdb/common/system_kfreebsd.c
index 41aa4d6..7cb6d92 100644
--- a/ctdb/common/system_kfreebsd.c
+++ b/ctdb/common/system_kfreebsd.c
@@ -156,7 +156,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
ip4pkt.tcp.check = tcp_checksum((uint16_t *)&ip4pkt.tcp, sizeof(ip4pkt.tcp), &ip4pkt.ip);
/* open a raw socket to send this segment from */
- s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+ s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (s == -1) {
DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket (%s)\n",
strerror(errno)));
@@ -203,7 +203,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
ip6pkt.tcp.window = htons(1234);
ip6pkt.tcp.check = tcp_checksum6((uint16_t *)&ip6pkt.tcp, sizeof(ip6pkt.tcp), &ip6pkt.ip6);
- s = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW);
+ s = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
if (s == -1) {
DEBUG(DEBUG_CRIT, (__location__ " Failed to open sending socket\n"));
return -1;
diff --git a/ctdb/common/system_linux.c b/ctdb/common/system_linux.c
index fdb8d12..2e58853 100644
--- a/ctdb/common/system_linux.c
+++ b/ctdb/common/system_linux.c
@@ -93,7 +93,7 @@ int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface)
switch (addr->ip.sin_family) {
case AF_INET:
- s = socket(PF_PACKET, SOCK_RAW, htons(ETHERTYPE_ARP));
+ s = socket(AF_PACKET, SOCK_RAW, ETHERTYPE_ARP);
if (s == -1){
DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n"));
return -1;
@@ -187,7 +187,7 @@ int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface)
close(s);
break;
case AF_INET6:
- s = socket(PF_PACKET, SOCK_RAW, htons(ETHERTYPE_ARP));
+ s = socket(AF_PACKET, SOCK_RAW, ETHERTYPE_ARP);
if (s == -1){
DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n"));
return -1;
@@ -357,7 +357,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
ip4pkt.tcp.check = tcp_checksum((uint16_t *)&ip4pkt.tcp, sizeof(ip4pkt.tcp), &ip4pkt.ip);
/* open a raw socket to send this segment from */
- s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+ s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (s == -1) {
DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket (%s)\n",
strerror(errno)));
@@ -406,7 +406,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
ip6pkt.tcp.window = htons(1234);
ip6pkt.tcp.check = tcp_checksum6((uint16_t *)&ip6pkt.tcp, sizeof(ip6pkt.tcp), &ip6pkt.ip6);
- s = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW);
+ s = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
if (s == -1) {
DEBUG(DEBUG_CRIT, (__location__ " Failed to open sending socket\n"));
return -1;
@@ -447,7 +447,7 @@ int ctdb_sys_open_capture_socket(const char *iface, void **private_data)
int s;
/* Open a socket to capture all traffic */
- s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+ s = socket(AF_PACKET, SOCK_RAW, ETH_P_ALL);
if (s == -1) {
DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n"));
return -1;
@@ -568,7 +568,7 @@ bool ctdb_sys_check_iface_exists(const char *iface)
int s;
struct ifreq ifr;
- s = socket(PF_PACKET, SOCK_RAW, 0);
+ s = socket(AF_PACKET, SOCK_RAW, 0);
if (s == -1){
/* We dont know if the interface exists, so assume yes */
DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n"));
diff --git a/ctdb/config/events.d/11.natgw b/ctdb/config/events.d/11.natgw
index 54e6cd9..29339f4 100755
--- a/ctdb/config/events.d/11.natgw
+++ b/ctdb/config/events.d/11.natgw
@@ -149,10 +149,6 @@ natgw_set_slave ()
_net="${_net_gw%@*}"
ip route add "$_net" via "$_natgwip" metric 10
done
-
- # Make sure winbindd does not stay bound to this address if we are
- # no longer NATGW master
- smbcontrol winbindd ip-dropped $CTDB_NATGW_PUBLIC_IP >/dev/null 2>&1
}
natgw_ensure_master ()
diff --git a/ctdb/config/events.d/49.winbind b/ctdb/config/events.d/49.winbind
index dee3c90..a1ea787 100755
--- a/ctdb/config/events.d/49.winbind
+++ b/ctdb/config/events.d/49.winbind
@@ -55,13 +55,6 @@ case "$1" in
ctdb_check_command wbinfo -p
;;
- takeip|releaseip)
- iface=$2
- ip=$3
- maskbits=$4
-
- smbcontrol winbindd ip-dropped $ip >/dev/null 2>/dev/null
- ;;
*)
ctdb_standard_event_handler "$@"
;;
diff --git a/ctdb/tools/ctdb.c b/ctdb/tools/ctdb.c
index c6da621..c5689c2 100644
--- a/ctdb/tools/ctdb.c
+++ b/ctdb/tools/ctdb.c
@@ -4496,7 +4496,7 @@ static int control_chktcpport(struct ctdb_context *ctdb, int argc, const char **
port = atoi(argv[0]);
- s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == -1) {
printf("Failed to open local socket\n");
return errno;
@@ -4508,7 +4508,7 @@ static int control_chktcpport(struct ctdb_context *ctdb, int argc, const char **
}
bzero(&sin, sizeof(sin));
- sin.sin_family = PF_INET;
+ sin.sin_family = AF_INET;
sin.sin_port = htons(port);
ret = bind(s, (struct sockaddr *)&sin, sizeof(sin));
close(s);
diff --git a/ctdb/utils/smnotify/smnotify.c b/ctdb/utils/smnotify/smnotify.c
index d7fd546..d5c5a4c 100644
--- a/ctdb/utils/smnotify/smnotify.c
+++ b/ctdb/utils/smnotify/smnotify.c
@@ -43,14 +43,14 @@ static int create_socket(const char *addr, int port)
int s;
struct sockaddr_in sock_in;
- s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s == -1) {
printf("Failed to open local socket\n");
exit(10);
}
bzero(&sock_in, sizeof(sock_in));
- sock_in.sin_family = PF_INET;
+ sock_in.sin_family = AF_INET;
sock_in.sin_port = htons(port);
inet_aton(addr, &sock_in.sin_addr);
if (bind(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) == -1) {
@@ -124,7 +124,7 @@ int main(int argc, const char *argv[])
/* Setup a sockaddr_in for the client we want to notify */
bzero(&sock_cl, sizeof(sock_cl));
- sock_cl.sin_family = PF_INET;
+ sock_cl.sin_family = AF_INET;
sock_cl.sin_port = htons(clientport);
inet_aton(client, &sock_cl.sin_addr);
diff --git a/docs-xml/manpages/smbspool_krb5_wrapper.8.xml b/docs-xml/manpages/smbspool_krb5_wrapper.8.xml
new file mode 100644
index 0000000..f9966e7
--- /dev/null
+++ b/docs-xml/manpages/smbspool_krb5_wrapper.8.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
+<refentry id="smbspool.8">
+
+<refmeta>
+ <refentrytitle>smbspool_krb5_wrapper</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class="source">Samba</refmiscinfo>
+ <refmiscinfo class="manual">System Administration tools</refmiscinfo>
+ <refmiscinfo class="version">4.4</refmiscinfo>
+</refmeta>
+
+
+<refnamediv>
+ <refname>smbspool_krb5_wrapper</refname>
+ <refpurpose>This is a CUPS printing backend which calls smbspool</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+ <cmdsynopsis>
+ <command>smbspool_krb5_wrapper</command>
+ <arg choice="req">job</arg>
+ <arg choice="req">user</arg>
+ <arg choice="req">title</arg>
+ <arg choice="req">copies</arg>
+ <arg choice="req">options</arg>
+ <arg choice="opt">filename</arg>
+ </cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1>
+ <title>DESCRIPTION</title>
+
+ <para>This tool is part of the <citerefentry><refentrytitle>samba</refentrytitle>
+ <manvolnum>7</manvolnum></citerefentry> suite.</para>
+
+ <para>smbspool_krb5_wrapper is a tool that can be used to print using
+ Kerberos credentials. To get this working smbspool_krb5_wrapper
+ needs to be the smb backend of CUPS. It needs to be owned by
+ root and the permissions for the binary need to be 0700. Once
+ smbspool_krb5_wrapper switched to the user trying to print it
+ executes smbspool. It should not be called by a user.</para>
+
+</refsect1>
+
+<refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry><refentrytitle>smbspool</refentrytitle>
+ <manvolnum>8</manvolnum></citerefentry>.</para>
+</refsect1>
+
+<refsect1>
+ <title>AUTHOR</title>
+
+ <para>The original Samba software and related utilities
+ were created by Andrew Tridgell. Samba is now developed
+ by the Samba Team as an Open Source project similar
+ to the way the Linux kernel is developed.</para>
+
+ <para>The smbspool_krb5_wrapper manpage was written by Andreas
+ Schneider.</para>
+</refsect1>
+
+</refentry>
diff --git a/docs-xml/manpages/vfs_gpfs.8.xml b/docs-xml/manpages/vfs_gpfs.8.xml
index 7bb4e90..e0c5951 100644
--- a/docs-xml/manpages/vfs_gpfs.8.xml
+++ b/docs-xml/manpages/vfs_gpfs.8.xml
@@ -42,14 +42,14 @@
</itemizedlist>
</para>
- <para><command>NOTE:</command>This module follows the posix-acl behaviour
+ <para><command>NOTE:</command> This module follows the posix-acl behaviour
and hence allows permission stealing via chown. Samba might allow at a later
point in time, to restrict the chown via this module as such restrictions
are the responsibility of the underlying filesystem than of Samba.
</para>
<para>This module makes use of the smb.conf parameter
- <smbconfoption name="acl map full control">acl map full control</smbconfoption>
+ <smbconfoption name="acl map full control"></smbconfoption>.
When set to yes (the default), this parameter will add in the FILE_DELETE_CHILD
bit on a returned ACE entry for a file (not a directory) that already
contains all file permissions except for FILE_DELETE and FILE_DELETE_CHILD.
@@ -471,7 +471,7 @@
</para>
<para>
At build time, only the header file <command>gpfs_gpl.h</command>
- is required , which is a symlink to <command>gpfs.h</command> in
+ is required, which is a symlink to <command>gpfs.h</command> in
gpfs versions newer than 3.2.1 PTF8.
</para>
</refsect1>
diff --git a/docs-xml/smbdotconf/winbind/idmapconfig.xml b/docs-xml/smbdotconf/winbind/idmapconfig.xml
index 434d379..db24784 100644
--- a/docs-xml/smbdotconf/winbind/idmapconfig.xml
+++ b/docs-xml/smbdotconf/winbind/idmapconfig.xml
@@ -38,21 +38,16 @@
(<citerefentry><refentrytitle>idmap_tdb2</refentrytitle> <manvolnum>8</manvolnum></citerefentry>),
ldap
(<citerefentry><refentrytitle>idmap_ldap</refentrytitle> <manvolnum>8</manvolnum></citerefentry>),
- ,
rid
(<citerefentry><refentrytitle>idmap_rid</refentrytitle> <manvolnum>8</manvolnum></citerefentry>),
- ,
hash
(<citerefentry><refentrytitle>idmap_hash</refentrytitle> <manvolnum>8</manvolnum></citerefentry>),
- ,
autorid
(<citerefentry><refentrytitle>idmap_autorid</refentrytitle> <manvolnum>8</manvolnum></citerefentry>),
- ,
ad
- (<citerefentry><refentrytitle>idmap_ad</refentrytitle> <manvolnum>8</manvolnum></citerefentry>),
- ,
- and nss.
- (<citerefentry><refentrytitle>idmap_nss</refentrytitle> <manvolnum>8</manvolnum></citerefentry>),
+ (<citerefentry><refentrytitle>idmap_ad</refentrytitle> <manvolnum>8</manvolnum></citerefentry>)
+ and nss
+ (<citerefentry><refentrytitle>idmap_nss</refentrytitle> <manvolnum>8</manvolnum></citerefentry>).
The corresponding manual pages contain the details, but
here is a summary.
</para>
@@ -65,9 +60,9 @@
mixture of the tdb and rid backend. It creates ranges for
each domain encountered and then uses the rid algorithm for each
of these automatically configured domains individually.
- The ad backend usees unix IDs stored in Active Directory via
+ The ad backend uses unix ids stored in Active Directory via
the standard schema extensions. The nss backend reverses
- the standard winbindd setup and gets the unixids via names
+ the standard winbindd setup and gets the unix ids via names
from nsswitch which can be useful in an ldap setup.
</para></listitem>
</varlistentry>
diff --git a/docs-xml/wscript_build b/docs-xml/wscript_build
index 5c42a31..8cdd2dd 100644
--- a/docs-xml/wscript_build
+++ b/docs-xml/wscript_build
@@ -38,6 +38,7 @@ manpages='''
manpages/smbpasswd.5
manpages/smbpasswd.8
manpages/smbspool.8
+ manpages/smbspool_krb5_wrapper.8
manpages/smbstatus.1
manpages/smbta-util.8
manpages/smbtar.1
diff --git a/docs/manpages/dbwrap_tool.1 b/docs/manpages/dbwrap_tool.1
index 7362765..38a088c 100644
--- a/docs/manpages/dbwrap_tool.1
+++ b/docs/manpages/dbwrap_tool.1
@@ -2,12 +2,12 @@
.\" Title: dbwrap_tool
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "DBWRAP_TOOL" "1" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "DBWRAP_TOOL" "1" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/eventlogadm.8 b/docs/manpages/eventlogadm.8
index 2375350..1fdf559 100644
--- a/docs/manpages/eventlogadm.8
+++ b/docs/manpages/eventlogadm.8
@@ -2,12 +2,12 @@
.\" Title: eventlogadm
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "EVENTLOGADM" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "EVENTLOGADM" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/findsmb.1 b/docs/manpages/findsmb.1
index f1f9c6d..c0c1ea3 100644
--- a/docs/manpages/findsmb.1
+++ b/docs/manpages/findsmb.1
@@ -2,12 +2,12 @@
.\" Title: findsmb
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "FINDSMB" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "FINDSMB" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_ad.8 b/docs/manpages/idmap_ad.8
index 313771d..c33d927 100644
--- a/docs/manpages/idmap_ad.8
+++ b/docs/manpages/idmap_ad.8
@@ -2,12 +2,12 @@
.\" Title: idmap_ad
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "IDMAP_AD" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_AD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_autorid.8 b/docs/manpages/idmap_autorid.8
index ec7d0b2..e06e626 100644
--- a/docs/manpages/idmap_autorid.8
+++ b/docs/manpages/idmap_autorid.8
@@ -2,12 +2,12 @@
.\" Title: idmap_autorid
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "IDMAP_AUTORID" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_AUTORID" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_hash.8 b/docs/manpages/idmap_hash.8
index 746d035..6b2c3b2 100644
--- a/docs/manpages/idmap_hash.8
+++ b/docs/manpages/idmap_hash.8
@@ -2,12 +2,12 @@
.\" Title: idmap_hash
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "IDMAP_HASH" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_HASH" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_ldap.8 b/docs/manpages/idmap_ldap.8
index 4afcadc..8383973 100644
--- a/docs/manpages/idmap_ldap.8
+++ b/docs/manpages/idmap_ldap.8
@@ -2,12 +2,12 @@
.\" Title: idmap_ldap
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "IDMAP_LDAP" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_LDAP" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_nss.8 b/docs/manpages/idmap_nss.8
index 2c40f24..5ebfafe 100644
--- a/docs/manpages/idmap_nss.8
+++ b/docs/manpages/idmap_nss.8
@@ -2,12 +2,12 @@
.\" Title: idmap_nss
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "IDMAP_NSS" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_NSS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_rfc2307.8 b/docs/manpages/idmap_rfc2307.8
index e4478ba..0f7532c 100644
--- a/docs/manpages/idmap_rfc2307.8
+++ b/docs/manpages/idmap_rfc2307.8
@@ -2,12 +2,12 @@
.\" Title: idmap_rfc2307
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "IDMAP_RFC2307" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_RFC2307" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_rid.8 b/docs/manpages/idmap_rid.8
index d237661..8a87aff 100644
--- a/docs/manpages/idmap_rid.8
+++ b/docs/manpages/idmap_rid.8
@@ -2,12 +2,12 @@
.\" Title: idmap_rid
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "IDMAP_RID" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_RID" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_script.8 b/docs/manpages/idmap_script.8
index c12d3a5..85deee2 100644
--- a/docs/manpages/idmap_script.8
+++ b/docs/manpages/idmap_script.8
@@ -2,12 +2,12 @@
.\" Title: idmap_script
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "IDMAP_SCRIPT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_SCRIPT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_tdb.8 b/docs/manpages/idmap_tdb.8
index fcc907c..dd060f7 100644
--- a/docs/manpages/idmap_tdb.8
+++ b/docs/manpages/idmap_tdb.8
@@ -2,12 +2,12 @@
.\" Title: idmap_tdb
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "IDMAP_TDB" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_TDB" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_tdb2.8 b/docs/manpages/idmap_tdb2.8
index 5a987e9..e38f223 100644
--- a/docs/manpages/idmap_tdb2.8
+++ b/docs/manpages/idmap_tdb2.8
@@ -2,12 +2,12 @@
.\" Title: idmap_tdb2
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "IDMAP_TDB2" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_TDB2" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/libsmbclient.7 b/docs/manpages/libsmbclient.7
index de44485..e4b20e3 100644
--- a/docs/manpages/libsmbclient.7
+++ b/docs/manpages/libsmbclient.7
@@ -2,12 +2,12 @@
.\" Title: libsmbclient
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: 7
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "LIBSMBCLIENT" "7" "12/10/2015" "Samba 4\&.3" "7"
+.TH "LIBSMBCLIENT" "7" "02/24/2016" "Samba 4\&.3" "7"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/lmhosts.5 b/docs/manpages/lmhosts.5
index 4152621..a8ff381 100644
--- a/docs/manpages/lmhosts.5
+++ b/docs/manpages/lmhosts.5
@@ -2,12 +2,12 @@
.\" Title: lmhosts
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: File Formats and Conventions
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "LMHOSTS" "5" "12/10/2015" "Samba 4\&.3" "File Formats and Conventions"
+.TH "LMHOSTS" "5" "02/24/2016" "Samba 4\&.3" "File Formats and Conventions"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/log2pcap.1 b/docs/manpages/log2pcap.1
index 0033027..b489e7d 100644
--- a/docs/manpages/log2pcap.1
+++ b/docs/manpages/log2pcap.1
@@ -2,12 +2,12 @@
.\" Title: log2pcap
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "LOG2PCAP" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "LOG2PCAP" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/net.8 b/docs/manpages/net.8
index c483d78..b0978a9 100644
--- a/docs/manpages/net.8
+++ b/docs/manpages/net.8
@@ -2,12 +2,12 @@
.\" Title: net
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "NET" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "NET" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/nmbd.8 b/docs/manpages/nmbd.8
index 155c6a5..bcf774a 100644
--- a/docs/manpages/nmbd.8
+++ b/docs/manpages/nmbd.8
@@ -2,12 +2,12 @@
.\" Title: nmbd
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "NMBD" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "NMBD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/nmblookup.1 b/docs/manpages/nmblookup.1
index d752790..6b2677d 100644
--- a/docs/manpages/nmblookup.1
+++ b/docs/manpages/nmblookup.1
@@ -2,12 +2,12 @@
.\" Title: nmblookup
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "NMBLOOKUP" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "NMBLOOKUP" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/ntlm_auth.1 b/docs/manpages/ntlm_auth.1
index b2ddd10..1d0fed8 100644
--- a/docs/manpages/ntlm_auth.1
+++ b/docs/manpages/ntlm_auth.1
@@ -2,12 +2,12 @@
.\" Title: ntlm_auth
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "NTLM_AUTH" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "NTLM_AUTH" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/pam_winbind.8 b/docs/manpages/pam_winbind.8
index 7ae4fd9..dbfca2b 100644
--- a/docs/manpages/pam_winbind.8
+++ b/docs/manpages/pam_winbind.8
@@ -2,12 +2,12 @@
.\" Title: pam_winbind
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: 8
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "PAM_WINBIND" "8" "12/10/2015" "Samba 4\&.3" "8"
+.TH "PAM_WINBIND" "8" "02/24/2016" "Samba 4\&.3" "8"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/pam_winbind.conf.5 b/docs/manpages/pam_winbind.conf.5
index f7a3554..9e3d7c8 100644
--- a/docs/manpages/pam_winbind.conf.5
+++ b/docs/manpages/pam_winbind.conf.5
@@ -2,12 +2,12 @@
.\" Title: pam_winbind.conf
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: 5
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "PAM_WINBIND\&.CONF" "5" "12/10/2015" "Samba 4\&.3" "5"
+.TH "PAM_WINBIND\&.CONF" "5" "02/24/2016" "Samba 4\&.3" "5"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/pdbedit.8 b/docs/manpages/pdbedit.8
index 6709a43..12245f1 100644
--- a/docs/manpages/pdbedit.8
+++ b/docs/manpages/pdbedit.8
@@ -2,12 +2,12 @@
.\" Title: pdbedit
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "PDBEDIT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "PDBEDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/profiles.1 b/docs/manpages/profiles.1
index 9570215..33296d1 100644
--- a/docs/manpages/profiles.1
+++ b/docs/manpages/profiles.1
@@ -2,12 +2,12 @@
.\" Title: profiles
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "PROFILES" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "PROFILES" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/rpcclient.1 b/docs/manpages/rpcclient.1
index a9e68f6..9e721db 100644
--- a/docs/manpages/rpcclient.1
+++ b/docs/manpages/rpcclient.1
@@ -2,12 +2,12 @@
.\" Title: rpcclient
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "RPCCLIENT" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "RPCCLIENT" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/samba-regedit.8 b/docs/manpages/samba-regedit.8
index 76db229..3b282b1 100644
--- a/docs/manpages/samba-regedit.8
+++ b/docs/manpages/samba-regedit.8
@@ -2,12 +2,12 @@
.\" Title: samba-regedit
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SAMBA\-REGEDIT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SAMBA\-REGEDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/samba-tool.8 b/docs/manpages/samba-tool.8
index 2e3aafa..c55158d 100644
--- a/docs/manpages/samba-tool.8
+++ b/docs/manpages/samba-tool.8
@@ -2,12 +2,12 @@
.\" Title: samba-tool
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SAMBA\-TOOL" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SAMBA\-TOOL" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/samba.7 b/docs/manpages/samba.7
index ad18244..3628bfd 100644
--- a/docs/manpages/samba.7
+++ b/docs/manpages/samba.7
@@ -2,12 +2,12 @@
.\" Title: samba
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: Miscellanea
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SAMBA" "7" "12/10/2015" "Samba 4\&.3" "Miscellanea"
+.TH "SAMBA" "7" "02/24/2016" "Samba 4\&.3" "Miscellanea"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/samba.8 b/docs/manpages/samba.8
index 31120f4..0bd4e30 100644
--- a/docs/manpages/samba.8
+++ b/docs/manpages/samba.8
@@ -2,12 +2,12 @@
.\" Title: samba
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SAMBA" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SAMBA" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/sharesec.1 b/docs/manpages/sharesec.1
index 9761e1c..e654488 100644
--- a/docs/manpages/sharesec.1
+++ b/docs/manpages/sharesec.1
@@ -2,12 +2,12 @@
.\" Title: sharesec
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SHARESEC" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SHARESEC" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5
index 02ea1b6..796aa3a 100644
--- a/docs/manpages/smb.conf.5
+++ b/docs/manpages/smb.conf.5
@@ -2,12 +2,12 @@
.\" Title: smb.conf
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: File Formats and Conventions
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SMB\&.CONF" "5" "12/10/2015" "Samba 4\&.3" "File Formats and Conventions"
+.TH "SMB\&.CONF" "5" "02/24/2016" "Samba 4\&.3" "File Formats and Conventions"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -4181,9 +4181,9 @@ There are three general options available:
.PP
backend = backend_name
.RS 4
-This specifies the name of the idmap plugin to use as the SID/uid/gid backend for this domain\&. The standard backends are tdb (\fBidmap_tdb\fR(8)), tdb2 (\fBidmap_tdb2\fR(8)), ldap (\fBidmap_ldap\fR(8)), , rid (\fBidmap_rid\fR(8)), , hash (\fBidmap_hash\fR(8)), , autorid (\fBidmap_autorid\fR(8)), , ad (\fBidmap_ad\fR(8)), , and nss\&. (\fBidmap_nss\fR(8)), The corresponding manual pages contain the details, but here is a summary\&.
+This specifies the name of the idmap plugin to use as the SID/uid/gid backend for this domain\&. The standard backends are tdb (\fBidmap_tdb\fR(8)), tdb2 (\fBidmap_tdb2\fR(8)), ldap (\fBidmap_ldap\fR(8)), rid (\fBidmap_rid\fR(8)), hash (\fBidmap_hash\fR(8)), autorid (\fBidmap_autorid\fR(8)), ad (\fBidmap_ad\fR(8)) and nss (\fBidmap_nss\fR(8))\&. The corresponding manual pages contain the details, but here is a summary\&.
.sp
-The first three of these create mappings of their own using internal unixid counters and store the mappings in a database\&. These are suitable for use in the default idmap configuration\&. The rid and hash backends use a pure algorithmic calculation to determine the unixid for a SID\&. The autorid module is a mixture of the tdb and rid backend\&. It creates ranges for each domain encountered and then uses the rid algorithm for each of these automatically configured domains individually\ [...]
+The first three of these create mappings of their own using internal unixid counters and store the mappings in a database\&. These are suitable for use in the default idmap configuration\&. The rid and hash backends use a pure algorithmic calculation to determine the unixid for a SID\&. The autorid module is a mixture of the tdb and rid backend\&. It creates ranges for each domain encountered and then uses the rid algorithm for each of these automatically configured domains individually\ [...]
.RE
.PP
range = low \- high
diff --git a/docs/manpages/smbcacls.1 b/docs/manpages/smbcacls.1
index 5d93e71..291ac5e 100644
--- a/docs/manpages/smbcacls.1
+++ b/docs/manpages/smbcacls.1
@@ -2,12 +2,12 @@
.\" Title: smbcacls
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SMBCACLS" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SMBCACLS" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbclient.1 b/docs/manpages/smbclient.1
index 907a2cc..395fbcf 100644
--- a/docs/manpages/smbclient.1
+++ b/docs/manpages/smbclient.1
@@ -2,12 +2,12 @@
.\" Title: smbclient
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SMBCLIENT" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SMBCLIENT" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbcontrol.1 b/docs/manpages/smbcontrol.1
index 5b0b37e..c8cf7ff 100644
--- a/docs/manpages/smbcontrol.1
+++ b/docs/manpages/smbcontrol.1
@@ -2,12 +2,12 @@
.\" Title: smbcontrol
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SMBCONTROL" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SMBCONTROL" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbcquotas.1 b/docs/manpages/smbcquotas.1
index 11e88df..22365d0 100644
--- a/docs/manpages/smbcquotas.1
+++ b/docs/manpages/smbcquotas.1
@@ -2,12 +2,12 @@
.\" Title: smbcquotas
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SMBCQUOTAS" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SMBCQUOTAS" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbd.8 b/docs/manpages/smbd.8
index e1e4ea5..0171d72 100644
--- a/docs/manpages/smbd.8
+++ b/docs/manpages/smbd.8
@@ -2,12 +2,12 @@
.\" Title: smbd
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SMBD" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SMBD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbget.1 b/docs/manpages/smbget.1
index 83846e4..566a67a 100644
--- a/docs/manpages/smbget.1
+++ b/docs/manpages/smbget.1
@@ -2,12 +2,12 @@
.\" Title: smbget
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SMBGET" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SMBGET" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbgetrc.5 b/docs/manpages/smbgetrc.5
index 573e6cc..c959419 100644
--- a/docs/manpages/smbgetrc.5
+++ b/docs/manpages/smbgetrc.5
@@ -2,12 +2,12 @@
.\" Title: smbgetrc
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: File Formats and Conventions
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SMBGETRC" "5" "12/10/2015" "Samba 4\&.3" "File Formats and Conventions"
+.TH "SMBGETRC" "5" "02/24/2016" "Samba 4\&.3" "File Formats and Conventions"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbpasswd.5 b/docs/manpages/smbpasswd.5
index 3431a0a..31b52a9 100644
--- a/docs/manpages/smbpasswd.5
+++ b/docs/manpages/smbpasswd.5
@@ -2,12 +2,12 @@
.\" Title: smbpasswd
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: File Formats and Conventions
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SMBPASSWD" "5" "12/10/2015" "Samba 4\&.3" "File Formats and Conventions"
+.TH "SMBPASSWD" "5" "02/24/2016" "Samba 4\&.3" "File Formats and Conventions"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbpasswd.8 b/docs/manpages/smbpasswd.8
index ba7f39e..3d00776 100644
--- a/docs/manpages/smbpasswd.8
+++ b/docs/manpages/smbpasswd.8
@@ -2,12 +2,12 @@
.\" Title: smbpasswd
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SMBPASSWD" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SMBPASSWD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbspool.8 b/docs/manpages/smbspool.8
index 2c06f81..c4bc508 100644
--- a/docs/manpages/smbspool.8
+++ b/docs/manpages/smbspool.8
@@ -2,12 +2,12 @@
.\" Title: smbspool
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SMBSPOOL" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SMBSPOOL" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_xattr_tdb.8 b/docs/manpages/smbspool_krb5_wrapper.8
similarity index 62%
copy from docs/manpages/vfs_xattr_tdb.8
copy to docs/manpages/smbspool_krb5_wrapper.8
index 6fc4e13..bd6f2b5 100644
--- a/docs/manpages/vfs_xattr_tdb.8
+++ b/docs/manpages/smbspool_krb5_wrapper.8
@@ -1,13 +1,13 @@
'\" t
-.\" Title: vfs_xattr_tdb
+.\" Title: smbspool_krb5_wrapper
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
-.\" Source: Samba 4.3
+.\" Source: Samba 4.4
.\" Language: English
.\"
-.TH "VFS_XATTR_TDB" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SMBSPOOL_KRB5_WRAPPE" "8" "02/24/2016" "Samba 4\&.4" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -28,29 +28,22 @@
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
-vfs_xattr_tdb \- Save Extended Attributes (EAs) in a tdb file
+smbspool_krb5_wrapper \- This is a CUPS printing backend which calls smbspool
.SH "SYNOPSIS"
.HP \w'\ 'u
-vfs objects = xattr_tdb
+smbspool_krb5_wrapper {job} {user} {title} {copies} {options} [filename]
.SH "DESCRIPTION"
.PP
-This VFS module is part of the
+This tool is part of the
\fBsamba\fR(7)
suite\&.
.PP
-The
-vfs_xattr_tdb
-VFS module stores Extended Attributes (EAs) in a tdb file\&. This enables the usage of Extended Attributes on OS and filesystems which do not support Extended Attributes by themselves\&.
+smbspool_krb5_wrapper is a tool that can be used to print using Kerberos credentials\&. To get this working smbspool_krb5_wrapper needs to be the smb backend of CUPS\&. It needs to be owned by root and the permissions for the binary need to be 0700\&. Once smbspool_krb5_wrapper switched to the user trying to print it executes smbspool\&. It should not be called by a user\&.
+.SH "SEE ALSO"
.PP
-This module is stackable\&.
-.SH "OPTIONS"
-.PP
-xattr_tdb:file = PATH
-.RS 4
-Name of the tdb file the EAs are stored in\&. If this option is not set, the default filename
-xattr\&.tdb
-is used\&.
-.RE
+\fBsmbspool\fR(8)\&.
.SH "AUTHOR"
.PP
The original Samba software and related utilities were created by Andrew Tridgell\&. Samba is now developed by the Samba Team as an Open Source project similar to the way the Linux kernel is developed\&.
+.PP
+The smbspool_krb5_wrapper manpage was written by Andreas Schneider\&.
diff --git a/docs/manpages/smbstatus.1 b/docs/manpages/smbstatus.1
index b99ac16..c2766d5 100644
--- a/docs/manpages/smbstatus.1
+++ b/docs/manpages/smbstatus.1
@@ -2,12 +2,12 @@
.\" Title: smbstatus
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SMBSTATUS" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SMBSTATUS" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbta-util.8 b/docs/manpages/smbta-util.8
index 3b2c570..f7349c7 100644
--- a/docs/manpages/smbta-util.8
+++ b/docs/manpages/smbta-util.8
@@ -2,12 +2,12 @@
.\" Title: smbta-util
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SMBTA\-UTIL" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SMBTA\-UTIL" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbtar.1 b/docs/manpages/smbtar.1
index cfefbcb..130b1a3 100644
--- a/docs/manpages/smbtar.1
+++ b/docs/manpages/smbtar.1
@@ -2,12 +2,12 @@
.\" Title: smbtar
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SMBTAR" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SMBTAR" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbtree.1 b/docs/manpages/smbtree.1
index f55444a..e757082 100644
--- a/docs/manpages/smbtree.1
+++ b/docs/manpages/smbtree.1
@@ -2,12 +2,12 @@
.\" Title: smbtree
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SMBTREE" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SMBTREE" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/testparm.1 b/docs/manpages/testparm.1
index 8b10943..5b42305 100644
--- a/docs/manpages/testparm.1
+++ b/docs/manpages/testparm.1
@@ -2,12 +2,12 @@
.\" Title: testparm
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "TESTPARM" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "TESTPARM" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_acl_tdb.8 b/docs/manpages/vfs_acl_tdb.8
index de7a868..9c69b5f 100644
--- a/docs/manpages/vfs_acl_tdb.8
+++ b/docs/manpages/vfs_acl_tdb.8
@@ -2,12 +2,12 @@
.\" Title: vfs_acl_tdb
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_ACL_TDB" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_ACL_TDB" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_acl_xattr.8 b/docs/manpages/vfs_acl_xattr.8
index 2924319..9ed7731 100644
--- a/docs/manpages/vfs_acl_xattr.8
+++ b/docs/manpages/vfs_acl_xattr.8
@@ -2,12 +2,12 @@
.\" Title: vfs_acl_xattr
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_ACL_XATTR" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_ACL_XATTR" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_aio_fork.8 b/docs/manpages/vfs_aio_fork.8
index 325c4bc..a5a8838 100644
--- a/docs/manpages/vfs_aio_fork.8
+++ b/docs/manpages/vfs_aio_fork.8
@@ -2,12 +2,12 @@
.\" Title: vfs_aio_fork
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_AIO_FORK" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_AIO_FORK" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_aio_linux.8 b/docs/manpages/vfs_aio_linux.8
index f1e618a..9029985 100644
--- a/docs/manpages/vfs_aio_linux.8
+++ b/docs/manpages/vfs_aio_linux.8
@@ -2,12 +2,12 @@
.\" Title: vfs_aio_linux
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_AIO_LINUX" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_AIO_LINUX" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_aio_pthread.8 b/docs/manpages/vfs_aio_pthread.8
index f18774f..0606288 100644
--- a/docs/manpages/vfs_aio_pthread.8
+++ b/docs/manpages/vfs_aio_pthread.8
@@ -2,12 +2,12 @@
.\" Title: vfs_aio_pthread
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_AIO_PTHREAD" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_AIO_PTHREAD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_audit.8 b/docs/manpages/vfs_audit.8
index 3ee45ff..0154f99 100644
--- a/docs/manpages/vfs_audit.8
+++ b/docs/manpages/vfs_audit.8
@@ -2,12 +2,12 @@
.\" Title: vfs_audit
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_AUDIT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_AUDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_btrfs.8 b/docs/manpages/vfs_btrfs.8
index 35c6f42..aea6e5a 100644
--- a/docs/manpages/vfs_btrfs.8
+++ b/docs/manpages/vfs_btrfs.8
@@ -2,12 +2,12 @@
.\" Title: vfs_btrfs
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_BTRFS" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_BTRFS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_cacheprime.8 b/docs/manpages/vfs_cacheprime.8
index 6bb4ad6..ce1cad4 100644
--- a/docs/manpages/vfs_cacheprime.8
+++ b/docs/manpages/vfs_cacheprime.8
@@ -2,12 +2,12 @@
.\" Title: vfs_cacheprime
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_CACHEPRIME" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_CACHEPRIME" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_cap.8 b/docs/manpages/vfs_cap.8
index 7d7d042..326c412 100644
--- a/docs/manpages/vfs_cap.8
+++ b/docs/manpages/vfs_cap.8
@@ -2,12 +2,12 @@
.\" Title: vfs_cap
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_CAP" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_CAP" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_catia.8 b/docs/manpages/vfs_catia.8
index c79a3c1..bc68933 100644
--- a/docs/manpages/vfs_catia.8
+++ b/docs/manpages/vfs_catia.8
@@ -2,12 +2,12 @@
.\" Title: vfs_catia
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_CATIA" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_CATIA" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_ceph.8 b/docs/manpages/vfs_ceph.8
index ab16c76..73b3d61 100644
--- a/docs/manpages/vfs_ceph.8
+++ b/docs/manpages/vfs_ceph.8
@@ -2,12 +2,12 @@
.\" Title: vfs_ceph
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_CEPH" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_CEPH" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_commit.8 b/docs/manpages/vfs_commit.8
index 74cb5f3..afbb350 100644
--- a/docs/manpages/vfs_commit.8
+++ b/docs/manpages/vfs_commit.8
@@ -2,12 +2,12 @@
.\" Title: vfs_commit
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_COMMIT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_COMMIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_crossrename.8 b/docs/manpages/vfs_crossrename.8
index 2bdca92..4b037a1 100644
--- a/docs/manpages/vfs_crossrename.8
+++ b/docs/manpages/vfs_crossrename.8
@@ -2,12 +2,12 @@
.\" Title: vfs_crossrename
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_CROSSRENAME" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_CROSSRENAME" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_default_quota.8 b/docs/manpages/vfs_default_quota.8
index c9aea70..9347894 100644
--- a/docs/manpages/vfs_default_quota.8
+++ b/docs/manpages/vfs_default_quota.8
@@ -2,12 +2,12 @@
.\" Title: vfs_default_quota
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_DEFAULT_QUOTA" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_DEFAULT_QUOTA" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_dirsort.8 b/docs/manpages/vfs_dirsort.8
index 5196ce9..6455c07 100644
--- a/docs/manpages/vfs_dirsort.8
+++ b/docs/manpages/vfs_dirsort.8
@@ -2,12 +2,12 @@
.\" Title: vfs_dirsort
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_DIRSORT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_DIRSORT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_extd_audit.8 b/docs/manpages/vfs_extd_audit.8
index d965c3c..48f605b 100644
--- a/docs/manpages/vfs_extd_audit.8
+++ b/docs/manpages/vfs_extd_audit.8
@@ -2,12 +2,12 @@
.\" Title: vfs_extd_audit
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_EXTD_AUDIT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_EXTD_AUDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_fake_perms.8 b/docs/manpages/vfs_fake_perms.8
index 53f9c94..68aac1f 100644
--- a/docs/manpages/vfs_fake_perms.8
+++ b/docs/manpages/vfs_fake_perms.8
@@ -2,12 +2,12 @@
.\" Title: vfs_fake_perms
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_FAKE_PERMS" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_FAKE_PERMS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_fileid.8 b/docs/manpages/vfs_fileid.8
index 883e260..2121630 100644
--- a/docs/manpages/vfs_fileid.8
+++ b/docs/manpages/vfs_fileid.8
@@ -2,12 +2,12 @@
.\" Title: vfs_fileid
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_FILEID" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_FILEID" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_fruit.8 b/docs/manpages/vfs_fruit.8
index 888afa5..7b8f212 100644
--- a/docs/manpages/vfs_fruit.8
+++ b/docs/manpages/vfs_fruit.8
@@ -2,12 +2,12 @@
.\" Title: vfs_fruit
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_FRUIT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_FRUIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_full_audit.8 b/docs/manpages/vfs_full_audit.8
index 2ba226b..4ea3f03 100644
--- a/docs/manpages/vfs_full_audit.8
+++ b/docs/manpages/vfs_full_audit.8
@@ -2,12 +2,12 @@
.\" Title: vfs_full_audit
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_FULL_AUDIT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_FULL_AUDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_glusterfs.8 b/docs/manpages/vfs_glusterfs.8
index 8843d96..e70933f 100644
--- a/docs/manpages/vfs_glusterfs.8
+++ b/docs/manpages/vfs_glusterfs.8
@@ -2,12 +2,12 @@
.\" Title: vfs_glusterfs
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_GLUSTERFS" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_GLUSTERFS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_gpfs.8 b/docs/manpages/vfs_gpfs.8
index bb33eb9..a5b158e 100644
--- a/docs/manpages/vfs_gpfs.8
+++ b/docs/manpages/vfs_gpfs.8
@@ -2,12 +2,12 @@
.\" Title: vfs_gpfs
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_GPFS" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_GPFS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -79,11 +79,11 @@ Lease support on GPFS
.sp
.RE
.PP
-NOTE:This module follows the posix\-acl behaviour and hence allows permission stealing via chown\&. Samba might allow at a later point in time, to restrict the chown via this module as such restrictions are the responsibility of the underlying filesystem than of Samba\&.
+NOTE:
+This module follows the posix\-acl behaviour and hence allows permission stealing via chown\&. Samba might allow at a later point in time, to restrict the chown via this module as such restrictions are the responsibility of the underlying filesystem than of Samba\&.
.PP
This module makes use of the smb\&.conf parameter
-\m[blue]\fBacl map full control = acl map full control\fR\m[]
-When set to yes (the default), this parameter will add in the FILE_DELETE_CHILD bit on a returned ACE entry for a file (not a directory) that already contains all file permissions except for FILE_DELETE and FILE_DELETE_CHILD\&. This can prevent Windows applications that request GENERIC_ALL access from getting ACCESS_DENIED errors when running against a filesystem with NFSv4 compatible ACLs\&.
+\m[blue]\fBacl map full control\fR\m[]\&. When set to yes (the default), this parameter will add in the FILE_DELETE_CHILD bit on a returned ACE entry for a file (not a directory) that already contains all file permissions except for FILE_DELETE and FILE_DELETE_CHILD\&. This can prevent Windows applications that request GENERIC_ALL access from getting ACCESS_DENIED errors when running against a filesystem with NFSv4 compatible ACLs\&.
.PP
This module is stackable\&.
.PP
@@ -670,7 +670,7 @@ library was open source and could be used at run time\&.
.PP
At build time, only the header file
gpfs_gpl\&.h
-is required , which is a symlink to
+is required, which is a symlink to
gpfs\&.h
in gpfs versions newer than 3\&.2\&.1 PTF8\&.
.SH "VERSION"
diff --git a/docs/manpages/vfs_linux_xfs_sgid.8 b/docs/manpages/vfs_linux_xfs_sgid.8
index 16abafd..0acaee5 100644
--- a/docs/manpages/vfs_linux_xfs_sgid.8
+++ b/docs/manpages/vfs_linux_xfs_sgid.8
@@ -2,12 +2,12 @@
.\" Title: vfs_syncops
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_SYNCOPS" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SYNCOPS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_media_harmony.8 b/docs/manpages/vfs_media_harmony.8
index a589cdb..eefadb3 100644
--- a/docs/manpages/vfs_media_harmony.8
+++ b/docs/manpages/vfs_media_harmony.8
@@ -2,12 +2,12 @@
.\" Title: vfs_media_harmony
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_MEDIA_HARMONY" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_MEDIA_HARMONY" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_netatalk.8 b/docs/manpages/vfs_netatalk.8
index 32f13fd..6cbe456 100644
--- a/docs/manpages/vfs_netatalk.8
+++ b/docs/manpages/vfs_netatalk.8
@@ -2,12 +2,12 @@
.\" Title: vfs_netatalk
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_NETATALK" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_NETATALK" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_prealloc.8 b/docs/manpages/vfs_prealloc.8
index 5d809ed..242a7e4 100644
--- a/docs/manpages/vfs_prealloc.8
+++ b/docs/manpages/vfs_prealloc.8
@@ -2,12 +2,12 @@
.\" Title: vfs_prealloc
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_PREALLOC" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_PREALLOC" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_preopen.8 b/docs/manpages/vfs_preopen.8
index 3298111..db8e404 100644
--- a/docs/manpages/vfs_preopen.8
+++ b/docs/manpages/vfs_preopen.8
@@ -2,12 +2,12 @@
.\" Title: vfs_preopen
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_PREOPEN" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_PREOPEN" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_readahead.8 b/docs/manpages/vfs_readahead.8
index 49da5b7..6c9fec5 100644
--- a/docs/manpages/vfs_readahead.8
+++ b/docs/manpages/vfs_readahead.8
@@ -2,12 +2,12 @@
.\" Title: vfs_readahead
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_READAHEAD" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_READAHEAD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_readonly.8 b/docs/manpages/vfs_readonly.8
index b74fbac..c335680 100644
--- a/docs/manpages/vfs_readonly.8
+++ b/docs/manpages/vfs_readonly.8
@@ -2,12 +2,12 @@
.\" Title: vfs_readonly
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_READONLY" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_READONLY" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_recycle.8 b/docs/manpages/vfs_recycle.8
index 2300bfb..d8e1ae8 100644
--- a/docs/manpages/vfs_recycle.8
+++ b/docs/manpages/vfs_recycle.8
@@ -2,12 +2,12 @@
.\" Title: vfs_recycle
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_RECYCLE" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_RECYCLE" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_scannedonly.8 b/docs/manpages/vfs_scannedonly.8
index 175937d..a5d9d5d 100644
--- a/docs/manpages/vfs_scannedonly.8
+++ b/docs/manpages/vfs_scannedonly.8
@@ -2,12 +2,12 @@
.\" Title: vfs_scannedonly
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_SCANNEDONLY" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SCANNEDONLY" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_shadow_copy.8 b/docs/manpages/vfs_shadow_copy.8
index bf13ea3..deff1c2 100644
--- a/docs/manpages/vfs_shadow_copy.8
+++ b/docs/manpages/vfs_shadow_copy.8
@@ -2,12 +2,12 @@
.\" Title: vfs_shadow_copy
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_SHADOW_COPY" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SHADOW_COPY" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_shadow_copy2.8 b/docs/manpages/vfs_shadow_copy2.8
index 7c94588..f4da715 100644
--- a/docs/manpages/vfs_shadow_copy2.8
+++ b/docs/manpages/vfs_shadow_copy2.8
@@ -2,12 +2,12 @@
.\" Title: vfs_shadow_copy2
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_SHADOW_COPY2" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SHADOW_COPY2" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_shell_snap.8 b/docs/manpages/vfs_shell_snap.8
index 951772e..dba4e3f 100644
--- a/docs/manpages/vfs_shell_snap.8
+++ b/docs/manpages/vfs_shell_snap.8
@@ -2,12 +2,12 @@
.\" Title: vfs_shell_snap
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_SHELL_SNAP" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SHELL_SNAP" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_smb_traffic_analyzer.8 b/docs/manpages/vfs_smb_traffic_analyzer.8
index f023b6d..b506a22 100644
--- a/docs/manpages/vfs_smb_traffic_analyzer.8
+++ b/docs/manpages/vfs_smb_traffic_analyzer.8
@@ -2,12 +2,12 @@
.\" Title: smb_traffic_analyzer
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "SMB_TRAFFIC_ANALYZER" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SMB_TRAFFIC_ANALYZER" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_snapper.8 b/docs/manpages/vfs_snapper.8
index 5f3c64a..401a35b 100644
--- a/docs/manpages/vfs_snapper.8
+++ b/docs/manpages/vfs_snapper.8
@@ -2,12 +2,12 @@
.\" Title: vfs_snapper
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_SNAPPER" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SNAPPER" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_streams_depot.8 b/docs/manpages/vfs_streams_depot.8
index 2b1456e..30238e2 100644
--- a/docs/manpages/vfs_streams_depot.8
+++ b/docs/manpages/vfs_streams_depot.8
@@ -2,12 +2,12 @@
.\" Title: vfs_streams_depot
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_STREAMS_DEPOT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_STREAMS_DEPOT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_streams_xattr.8 b/docs/manpages/vfs_streams_xattr.8
index 0eb4c5b..609d39e 100644
--- a/docs/manpages/vfs_streams_xattr.8
+++ b/docs/manpages/vfs_streams_xattr.8
@@ -2,12 +2,12 @@
.\" Title: vfs_streams_xattr
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_STREAMS_XATTR" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_STREAMS_XATTR" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_syncops.8 b/docs/manpages/vfs_syncops.8
index 97fb0d5..a36ff94 100644
--- a/docs/manpages/vfs_syncops.8
+++ b/docs/manpages/vfs_syncops.8
@@ -2,12 +2,12 @@
.\" Title: vfs_syncops
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_SYNCOPS" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SYNCOPS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_time_audit.8 b/docs/manpages/vfs_time_audit.8
index 948c08c..6e422fd 100644
--- a/docs/manpages/vfs_time_audit.8
+++ b/docs/manpages/vfs_time_audit.8
@@ -2,12 +2,12 @@
.\" Title: vfs_time_audit
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_TIME_AUDIT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_TIME_AUDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_tsmsm.8 b/docs/manpages/vfs_tsmsm.8
index c15264a..973455e 100644
--- a/docs/manpages/vfs_tsmsm.8
+++ b/docs/manpages/vfs_tsmsm.8
@@ -2,12 +2,12 @@
.\" Title: vfs_tsmsm
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_TSMSM" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_TSMSM" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_unityed_media.8 b/docs/manpages/vfs_unityed_media.8
index f8fce9c..a4263ee 100644
--- a/docs/manpages/vfs_unityed_media.8
+++ b/docs/manpages/vfs_unityed_media.8
@@ -2,12 +2,12 @@
.\" Title: vfs_unityed_media
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_UNITYED_MEDIA" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_UNITYED_MEDIA" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_worm.8 b/docs/manpages/vfs_worm.8
index f6635fe..9272ca4 100644
--- a/docs/manpages/vfs_worm.8
+++ b/docs/manpages/vfs_worm.8
@@ -2,12 +2,12 @@
.\" Title: vfs_worm
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_WORM" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_WORM" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_xattr_tdb.8 b/docs/manpages/vfs_xattr_tdb.8
index 6fc4e13..ab5624a 100644
--- a/docs/manpages/vfs_xattr_tdb.8
+++ b/docs/manpages/vfs_xattr_tdb.8
@@ -2,12 +2,12 @@
.\" Title: vfs_xattr_tdb
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_XATTR_TDB" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_XATTR_TDB" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_zfsacl.8 b/docs/manpages/vfs_zfsacl.8
index 6a7ceb6..49761b9 100644
--- a/docs/manpages/vfs_zfsacl.8
+++ b/docs/manpages/vfs_zfsacl.8
@@ -2,12 +2,12 @@
.\" Title: vfs_zfsacl
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFS_ZFSACL" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_ZFSACL" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfstest.1 b/docs/manpages/vfstest.1
index b0841c1..aa5f3d5 100644
--- a/docs/manpages/vfstest.1
+++ b/docs/manpages/vfstest.1
@@ -2,12 +2,12 @@
.\" Title: vfstest
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "VFSTEST" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "VFSTEST" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/wbinfo.1 b/docs/manpages/wbinfo.1
index 8231c0e..b50f729 100644
--- a/docs/manpages/wbinfo.1
+++ b/docs/manpages/wbinfo.1
@@ -2,12 +2,12 @@
.\" Title: wbinfo
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: User Commands
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "WBINFO" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "WBINFO" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/winbind_krb5_locator.7 b/docs/manpages/winbind_krb5_locator.7
index c2cd229..b9a7ed6 100644
--- a/docs/manpages/winbind_krb5_locator.7
+++ b/docs/manpages/winbind_krb5_locator.7
@@ -2,12 +2,12 @@
.\" Title: winbind_krb5_locator
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: 7
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "WINBIND_KRB5_LOCATOR" "7" "12/10/2015" "Samba 4\&.3" "7"
+.TH "WINBIND_KRB5_LOCATOR" "7" "02/24/2016" "Samba 4\&.3" "7"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/docs/manpages/winbindd.8 b/docs/manpages/winbindd.8
index 88a9457..8f30460 100644
--- a/docs/manpages/winbindd.8
+++ b/docs/manpages/winbindd.8
@@ -2,12 +2,12 @@
.\" Title: winbindd
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/10/2015
+.\" Date: 02/24/2016
.\" Manual: System Administration tools
.\" Source: Samba 4.3
.\" Language: English
.\"
-.TH "WINBINDD" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "WINBINDD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/lib/async_req/wscript_build b/lib/async_req/wscript_build
index 9c25223..bf79fdd 100644
--- a/lib/async_req/wscript_build
+++ b/lib/async_req/wscript_build
@@ -9,5 +9,6 @@ bld.SAMBA_SUBSYSTEM('LIBASYNC_REQ',
bld.SAMBA_BINARY('async_connect_send_test',
source='async_connect_send_test.c',
- deps='LIBASYNC_REQ'
+ deps='LIBASYNC_REQ',
+ install=False
)
diff --git a/lib/dbwrap/dbwrap_rbt.c b/lib/dbwrap/dbwrap_rbt.c
index 03f2f57..a9cc641 100644
--- a/lib/dbwrap/dbwrap_rbt.c
+++ b/lib/dbwrap/dbwrap_rbt.c
@@ -22,11 +22,15 @@
#include "dbwrap/dbwrap_private.h"
#include "dbwrap/dbwrap_rbt.h"
#include "../lib/util/rbtree.h"
+#include "../lib/util/dlinklist.h"
#define DBWRAP_RBT_ALIGN(_size_) (((_size_)+15)&~15)
struct db_rbt_ctx {
struct rb_root tree;
+ struct db_rbt_node *nodes;
+ size_t traverse_read;
+ struct db_rbt_node **traverse_nextp;
};
struct db_rbt_rec {
@@ -38,6 +42,7 @@ struct db_rbt_rec {
struct db_rbt_node {
struct rb_node rb_node;
size_t keysize, valuesize;
+ struct db_rbt_node *prev, *next;
};
/*
@@ -121,11 +126,16 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
struct db_rbt_node *node;
struct rb_node ** p;
- struct rb_node * parent;
+ struct rb_node *parent = NULL;
+ struct db_rbt_node *parent_node = NULL;
ssize_t reclen;
TDB_DATA this_key, this_val;
+ if (db_ctx->traverse_read > 0) {
+ return NT_STATUS_MEDIA_WRITE_PROTECTED;
+ }
+
if (rec_priv->node != NULL) {
/*
@@ -153,18 +163,25 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
return NT_STATUS_INSUFFICIENT_RESOURCES;
}
- node = talloc_size(db_ctx, reclen);
+ node = talloc_zero_size(db_ctx, reclen);
if (node == NULL) {
return NT_STATUS_NO_MEMORY;
}
if (rec_priv->node != NULL) {
+ if (db_ctx->traverse_nextp != NULL) {
+ if (*db_ctx->traverse_nextp == rec_priv->node) {
+ *db_ctx->traverse_nextp = node;
+ }
+ }
+
/*
* We need to delete the key from the tree and start fresh,
* there's not enough space in the existing record
*/
rb_erase(&rec_priv->node->rb_node, &db_ctx->tree);
+ DLIST_REMOVE(db_ctx->nodes, rec_priv->node);
/*
* Keep the existing node around for a while: If the record
@@ -172,8 +189,6 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
*/
}
- ZERO_STRUCT(node->rb_node);
-
node->keysize = rec->key.dsize;
node->valuesize = data.dsize;
@@ -193,10 +208,11 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
TDB_DATA search_key, search_val;
int res;
- parent = (*p);
-
r = db_rbt2node(*p);
+ parent = (*p);
+ parent_node = r;
+
db_rbt_parse_node(r, &search_key, &search_val);
res = db_rbt_compare(this_key, search_key);
@@ -213,6 +229,7 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
}
rb_link_node(&node->rb_node, parent, p);
+ DLIST_ADD_AFTER(db_ctx->nodes, node, parent_node);
rb_insert_color(&node->rb_node, &db_ctx->tree);
return NT_STATUS_OK;
@@ -224,26 +241,27 @@ static NTSTATUS db_rbt_delete(struct db_record *rec)
rec->db->private_data, struct db_rbt_ctx);
struct db_rbt_rec *rec_priv = (struct db_rbt_rec *)rec->private_data;
+ if (db_ctx->traverse_read > 0) {
+ return NT_STATUS_MEDIA_WRITE_PROTECTED;
+ }
+
if (rec_priv->node == NULL) {
return NT_STATUS_OK;
}
+ if (db_ctx->traverse_nextp != NULL) {
+ if (*db_ctx->traverse_nextp == rec_priv->node) {
+ *db_ctx->traverse_nextp = rec_priv->node->next;
+ }
+ }
+
rb_erase(&rec_priv->node->rb_node, &db_ctx->tree);
+ DLIST_REMOVE(db_ctx->nodes, rec_priv->node);
TALLOC_FREE(rec_priv->node);
return NT_STATUS_OK;
}
-static NTSTATUS db_rbt_store_deny(struct db_record *rec, TDB_DATA data, int flag)
-{
- return NT_STATUS_MEDIA_WRITE_PROTECTED;
-}
-
-static NTSTATUS db_rbt_delete_deny(struct db_record *rec)
-{
- return NT_STATUS_MEDIA_WRITE_PROTECTED;
-}
-
struct db_rbt_search_result {
TDB_DATA key;
TDB_DATA val;
@@ -385,75 +403,65 @@ static NTSTATUS db_rbt_parse_record(struct db_context *db, TDB_DATA key,
}
static int db_rbt_traverse_internal(struct db_context *db,
- struct rb_node *n,
int (*f)(struct db_record *db,
void *private_data),
void *private_data, uint32_t* count,
bool rw)
{
- struct rb_node *rb_right;
- struct rb_node *rb_left;
- struct db_record rec;
- struct db_rbt_rec rec_priv;
+ struct db_rbt_ctx *ctx = talloc_get_type_abort(
+ db->private_data, struct db_rbt_ctx);
+ struct db_rbt_node *cur = NULL;
+ struct db_rbt_node *next = NULL;
int ret;
- if (n == NULL) {
- return 0;
- }
+ for (cur = ctx->nodes; cur != NULL; cur = next) {
+ struct db_record rec;
+ struct db_rbt_rec rec_priv;
- rb_left = n->rb_left;
- rb_right = n->rb_right;
+ rec_priv.node = cur;
+ next = rec_priv.node->next;
- ret = db_rbt_traverse_internal(db, rb_left, f, private_data, count, rw);
- if (ret != 0) {
- return ret;
- }
-
- rec_priv.node = db_rbt2node(n);
- /* n might be altered by the callback function */
- n = NULL;
-
- ZERO_STRUCT(rec);
- rec.db = db;
- rec.private_data = &rec_priv;
- if (rw) {
+ ZERO_STRUCT(rec);
+ rec.db = db;
+ rec.private_data = &rec_priv;
rec.store = db_rbt_store;
rec.delete_rec = db_rbt_delete;
- } else {
- rec.store = db_rbt_store_deny;
- rec.delete_rec = db_rbt_delete_deny;
- }
- db_rbt_parse_node(rec_priv.node, &rec.key, &rec.value);
-
- ret = f(&rec, private_data);
- (*count) ++;
- if (ret != 0) {
- return ret;
- }
+ db_rbt_parse_node(rec_priv.node, &rec.key, &rec.value);
- if (rec_priv.node != NULL) {
- /*
- * If the current record is still there
- * we should take the current rb_right.
- */
- rb_right = rec_priv.node->rb_node.rb_right;
+ if (rw) {
+ ctx->traverse_nextp = &next;
+ }
+ ret = f(&rec, private_data);
+ (*count) ++;
+ if (rw) {
+ ctx->traverse_nextp = NULL;
+ }
+ if (ret != 0) {
+ return ret;
+ }
+ if (rec_priv.node != NULL) {
+ next = rec_priv.node->next;
+ }
}
- return db_rbt_traverse_internal(db, rb_right, f, private_data, count, rw);
+ return 0;
}
-static int db_rbt_traverse(struct db_context *db,
- int (*f)(struct db_record *db,
- void *private_data),
- void *private_data)
+static int db_rbt_traverse_read(struct db_context *db,
+ int (*f)(struct db_record *db,
+ void *private_data),
+ void *private_data)
{
struct db_rbt_ctx *ctx = talloc_get_type_abort(
db->private_data, struct db_rbt_ctx);
uint32_t count = 0;
+ int ret;
- int ret = db_rbt_traverse_internal(db, ctx->tree.rb_node,
- f, private_data, &count,
- true /* rw */);
+ ctx->traverse_read++;
+ ret = db_rbt_traverse_internal(db,
+ f, private_data, &count,
+ false /* rw */);
+ ctx->traverse_read--;
if (ret != 0) {
return -1;
}
@@ -463,18 +471,27 @@ static int db_rbt_traverse(struct db_context *db,
return count;
}
-static int db_rbt_traverse_read(struct db_context *db,
- int (*f)(struct db_record *db,
- void *private_data),
- void *private_data)
+static int db_rbt_traverse(struct db_context *db,
+ int (*f)(struct db_record *db,
+ void *private_data),
+ void *private_data)
{
struct db_rbt_ctx *ctx = talloc_get_type_abort(
db->private_data, struct db_rbt_ctx);
uint32_t count = 0;
+ int ret;
+
+ if (ctx->traverse_nextp != NULL) {
+ return -1;
+ };
+
+ if (ctx->traverse_read > 0) {
+ return db_rbt_traverse_read(db, f, private_data);
+ }
- int ret = db_rbt_traverse_internal(db, ctx->tree.rb_node,
- f, private_data, &count,
- false /* rw */);
+ ret = db_rbt_traverse_internal(db,
+ f, private_data, &count,
+ true /* rw */);
if (ret != 0) {
return -1;
}
diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c
index c26442a..7b75f13 100644
--- a/lib/param/loadparm.c
+++ b/lib/param/loadparm.c
@@ -508,16 +508,36 @@ bool lpcfg_parm_bool(struct loadparm_context *lp_ctx,
}
+/* this is used to prevent lots of mallocs of size 1 */
+static const char lpcfg_string_emtpy[] = "";
+
+/**
+ Free a string value.
+**/
+void lpcfg_string_free(char **s)
+{
+ if (s == NULL) {
+ return;
+ }
+ if (*s == lpcfg_string_emtpy) {
+ *s = NULL;
+ return;
+ }
+ TALLOC_FREE(*s);
+}
+
/**
* Set a string value, deallocating any existing space, and allocing the space
* for the string
*/
bool lpcfg_string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
{
- talloc_free(*dest);
+ lpcfg_string_free(dest);
- if (src == NULL)
- src = "";
+ if ((src == NULL) || (*src == '\0')) {
+ *dest = discard_const_p(char, lpcfg_string_emtpy);
+ return true;
+ }
*dest = talloc_strdup(mem_ctx, src);
if ((*dest) == NULL) {
@@ -534,10 +554,12 @@ bool lpcfg_string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
*/
bool lpcfg_string_set_upper(TALLOC_CTX *mem_ctx, char **dest, const char *src)
{
- talloc_free(*dest);
+ lpcfg_string_free(dest);
- if (src == NULL)
- src = "";
+ if ((src == NULL) || (*src == '\0')) {
+ *dest = discard_const_p(char, lpcfg_string_emtpy);
+ return true;
+ }
*dest = strupper_talloc(mem_ctx, src);
if ((*dest) == NULL) {
@@ -811,9 +833,8 @@ void set_param_opt(TALLOC_CTX *mem_ctx,
overridden */
return;
}
- TALLOC_FREE(opt->value);
TALLOC_FREE(opt->list);
- opt->value = talloc_strdup(opt, opt_value);
+ lpcfg_string_set(opt, &opt->value, opt_value);
opt->priority = priority;
not_added = false;
break;
@@ -825,16 +846,10 @@ void set_param_opt(TALLOC_CTX *mem_ctx,
if (new_opt == NULL) {
smb_panic("OOM");
}
-
- new_opt->key = talloc_strdup(new_opt, opt_name);
- if (new_opt->key == NULL) {
- smb_panic("talloc_strdup failed");
- }
-
- new_opt->value = talloc_strdup(new_opt, opt_value);
- if (new_opt->value == NULL) {
- smb_panic("talloc_strdup failed");
- }
+ new_opt->key = NULL;
+ lpcfg_string_set(new_opt, &new_opt->key, opt_name);
+ new_opt->value = NULL;
+ lpcfg_string_set(new_opt, &new_opt->value, opt_value);
new_opt->list = NULL;
new_opt->priority = priority;
@@ -2404,13 +2419,16 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
if ((parm_table[i].type == P_STRING ||
parm_table[i].type == P_USTRING) &&
!(lp_ctx->flags[i] & FLAG_CMDLINE)) {
+ TALLOC_CTX *parent_mem;
char **r;
if (parm_table[i].p_class == P_LOCAL) {
+ parent_mem = lp_ctx->sDefault;
r = (char **)(((char *)lp_ctx->sDefault) + parm_table[i].offset);
} else {
+ parent_mem = lp_ctx->globals;
r = (char **)(((char *)lp_ctx->globals) + parm_table[i].offset);
}
- *r = talloc_strdup(lp_ctx, "");
+ lpcfg_string_set(parent_mem, r, "");
}
}
diff --git a/lib/tsocket/tsocket_bsd.c b/lib/tsocket/tsocket_bsd.c
index 8203755..0756fb3 100644
--- a/lib/tsocket/tsocket_bsd.c
+++ b/lib/tsocket/tsocket_bsd.c
@@ -132,6 +132,43 @@ static int tsocket_bsd_common_prepare_fd(int fd, bool high_fd)
return -1;
}
+#ifdef HAVE_LINUX_RTNETLINK_H
+/**
+ * Get the amount of pending bytes from a netlink socket
+ *
+ * For some reason netlink sockets don't support querying the amount of pending
+ * data via ioctl with FIONREAD, which is what we use in tsocket_bsd_pending()
+ * below.
+ *
+ * We know we are on Linux as we're using netlink, which means we have a working
+ * MSG_TRUNC flag to recvmsg() as well, so we use that together with MSG_PEEK.
+ **/
+static ssize_t tsocket_bsd_netlink_pending(int fd)
+{
+ struct iovec iov;
+ struct msghdr msg;
+ char buf[1];
+
+ iov = (struct iovec) {
+ .iov_base = buf,
+ .iov_len = sizeof(buf)
+ };
+
+ msg = (struct msghdr) {
+ .msg_iov = &iov,
+ .msg_iovlen = 1
+ };
+
+ return recvmsg(fd, &msg, MSG_PEEK | MSG_TRUNC);
+}
+#else
+static ssize_t tsocket_bsd_netlink_pending(int fd)
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
static ssize_t tsocket_bsd_pending(int fd)
{
int ret, error;
@@ -640,6 +677,7 @@ struct tdgram_bsd {
void *event_ptr;
struct tevent_fd *fde;
bool optimize_recvfrom;
+ bool netlink;
void *readable_private;
void (*readable_handler)(void *private_data);
@@ -892,7 +930,12 @@ static void tdgram_bsd_recvfrom_handler(void *private_data)
int err;
bool retry;
- ret = tsocket_bsd_pending(bsds->fd);
+ if (bsds->netlink) {
+ ret = tsocket_bsd_netlink_pending(bsds->fd);
+ } else {
+ ret = tsocket_bsd_pending(bsds->fd);
+ }
+
if (state->first_try && ret == 0) {
state->first_try = false;
/* retry later */
@@ -1395,6 +1438,11 @@ int _tdgram_bsd_existing_socket(TALLOC_CTX *mem_ctx,
{
struct tdgram_context *dgram;
struct tdgram_bsd *bsds;
+#ifdef HAVE_LINUX_RTNETLINK_H
+ int result;
+ struct sockaddr sa;
+ socklen_t sa_len = sizeof(struct sockaddr);
+#endif
dgram = tdgram_context_create(mem_ctx,
&tdgram_bsd_ops,
@@ -1409,6 +1457,18 @@ int _tdgram_bsd_existing_socket(TALLOC_CTX *mem_ctx,
talloc_set_destructor(bsds, tdgram_bsd_destructor);
*_dgram = dgram;
+
+#ifdef HAVE_LINUX_RTNETLINK_H
+ /*
+ * Try to determine the protocol family and remember if it's
+ * AF_NETLINK. We don't care if this fails.
+ */
+ result = getsockname(fd, &sa, &sa_len);
+ if (result == 0 && sa.sa_family == AF_NETLINK) {
+ bsds->netlink = true;
+ }
+#endif
+
return 0;
}
diff --git a/lib/util/util_strlist.c b/lib/util/util_strlist.c
index 987fdfb..2c1c2d5 100644
--- a/lib/util/util_strlist.c
+++ b/lib/util/util_strlist.c
@@ -552,7 +552,23 @@ char **str_list_make_v3(TALLOC_CTX *mem_ctx, const char *string,
TALLOC_FREE(list);
return NULL;
}
- if (!sep) sep = LIST_SEP;
+
+ /*
+ * DON'T REPLACE THIS BY "LIST_SEP". The common version of
+ * LIST_SEP does not contain the ;, which used to be accepted
+ * by Samba 4.0 before param merges. It would be the far
+ * better solution to split the _v3 version again to source3/
+ * where it belongs, see the _v3 in its name.
+ *
+ * Unfortunately it is referenced in /lib/param/loadparm.c,
+ * which depends on the version that the AD-DC mandates,
+ * namely without the ; as part of the list separator. I am
+ * missing the waf fu to properly work around the wrong
+ * include paths here for this defect.
+ */
+ if (sep == NULL) {
+ sep = " \t,;\n\r";
+ }
num = 0;
str = s;
diff --git a/librpc/idl/dns.idl b/librpc/idl/dns.idl
index d247e0e..5435fcf 100644
--- a/librpc/idl/dns.idl
+++ b/librpc/idl/dns.idl
@@ -8,7 +8,7 @@
encoding if it doesn't work out
*/
-import "misc.idl";
+import "misc.idl", "dnsp.idl";
[
helper("librpc/ndr/ndr_dns.h"),
helpstring("DNS records"),
@@ -152,20 +152,12 @@ interface dns
} dns_soa_record;
typedef [public] struct {
- [value(strlen(cpu))] uint8 cpu_length;
- [charset(DOS)] uint8 cpu[cpu_length];
- [value(strlen(os))] uint8 os_length;
- [charset(DOS)] uint8 os[os_length];
- } dns_hinfo_record;
-
- typedef [public] struct {
uint16 preference;
dns_string exchange;
} dns_mx_record;
- typedef [public] struct {
- [value(strlen(txt))] uint8 length;
- [charset(DOS)] uint8 txt[length];
+ typedef [public,nopull] struct {
+ dnsp_string_list txt;
} dns_txt_record;
typedef [public] struct {
@@ -232,7 +224,7 @@ interface dns
[case(DNS_QTYPE_CNAME)] dns_string cname_record;
[case(DNS_QTYPE_SOA)] dns_soa_record soa_record;
[case(DNS_QTYPE_PTR)] dns_string ptr_record;
- [case(DNS_QTYPE_HINFO)] dns_hinfo_record hinfo_record;
+ [case(DNS_QTYPE_HINFO)] dnsp_hinfo hinfo_record;
[case(DNS_QTYPE_MX)] dns_mx_record mx_record;
[case(DNS_QTYPE_TXT)] dns_txt_record txt_record;
[case(DNS_QTYPE_RP)] dns_rp_record rp_record;
@@ -270,7 +262,7 @@ interface dns
/*
this is a convenience hook for ndrdump
*/
- void decode_dns_name_packet(
+ [nopython] void decode_dns_name_packet(
[in] dns_name_packet packet
);
}
diff --git a/librpc/idl/dnsp.idl b/librpc/idl/dnsp.idl
index 4c49001..d705cfc 100644
--- a/librpc/idl/dnsp.idl
+++ b/librpc/idl/dnsp.idl
@@ -263,11 +263,11 @@ interface dnsp
/*
these are convenience hooks for ndrdump
*/
- void decode_DnssrvRpcRecord(
+ [nopython] void decode_DnssrvRpcRecord(
[in] dnsp_DnssrvRpcRecord blob
);
- void decode_DnsProperty(
+ [nopython] void decode_DnsProperty(
[in] dnsp_DnsProperty blob
);
}
diff --git a/librpc/idl/dnsserver.idl b/librpc/idl/dnsserver.idl
index ca9c371..c7742e7 100644
--- a/librpc/idl/dnsserver.idl
+++ b/librpc/idl/dnsserver.idl
@@ -73,7 +73,7 @@ import "misc.idl", "dnsp.idl";
typedef [public,gensize] struct {
[value(strlen(str))] uint8 len;
- [charset(UTF8)] uint8 str[len];
+ [charset(UNIX)] uint8 str[len];
}
DNS_RPC_NAME;
diff --git a/librpc/ndr/ndr_dns.c b/librpc/ndr/ndr_dns.c
index 0b9e3b0..065d992 100644
--- a/librpc/ndr/ndr_dns.c
+++ b/librpc/ndr/ndr_dns.c
@@ -30,6 +30,7 @@
#include "includes.h"
#include "librpc/gen_ndr/ndr_dns.h"
#include "librpc/gen_ndr/ndr_misc.h"
+#include "librpc/gen_ndr/ndr_dnsp.h"
#include "system/locale.h"
#include "lib/util/util_net.h"
@@ -230,6 +231,29 @@ _PUBLIC_ enum ndr_err_code ndr_push_dns_string(struct ndr_push *ndr,
return ndr_push_bytes(ndr, (const uint8_t *)"", 1);
}
+_PUBLIC_ enum ndr_err_code ndr_pull_dns_txt_record(struct ndr_pull *ndr, int ndr_flags, struct dns_txt_record *r)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ enum ndr_err_code ndr_err;
+ uint32_t data_size = ndr->data_size;
+ uint32_t record_size = 0;
+ ndr_err = ndr_token_retrieve(&ndr->array_size_list, r,
+ &record_size);
+ if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NDR_PULL_NEED_BYTES(ndr, record_size);
+ ndr->data_size = ndr->offset + record_size;
+ }
+ NDR_CHECK(ndr_pull_align(ndr, 1));
+ NDR_CHECK(ndr_pull_dnsp_string_list(ndr, NDR_SCALARS, &r->txt));
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 1));
+ ndr->data_size = data_size;
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
_PUBLIC_ enum ndr_err_code ndr_push_dns_res_rec(struct ndr_push *ndr,
int ndr_flags,
const struct dns_res_rec *r)
@@ -302,6 +326,9 @@ _PUBLIC_ enum ndr_err_code ndr_pull_dns_res_rec(struct ndr_pull *ndr,
NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->length));
_saved_offset1 = ndr->offset;
if (r->length > 0) {
+ NDR_CHECK(ndr_token_store(ndr, &ndr->array_size_list,
+ &r->rdata,
+ r->length));
NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->rdata,
r->rr_type));
NDR_CHECK(ndr_pull_dns_rdata(ndr, NDR_SCALARS,
diff --git a/librpc/ndr/ndr_dnsp.c b/librpc/ndr/ndr_dnsp.c
index 46141c1..3cb96f9 100644
--- a/librpc/ndr/ndr_dnsp.c
+++ b/librpc/ndr/ndr_dnsp.c
@@ -222,3 +222,27 @@ enum ndr_err_code ndr_push_dnsp_string_list(struct ndr_push *ndr, int ndr_flags,
}
return NDR_ERR_SUCCESS;
}
+
+enum ndr_err_code ndr_dnsp_string_list_copy(TALLOC_CTX *mem_ctx,
+ const struct dnsp_string_list *src,
+ struct dnsp_string_list *dst)
+{
+ size_t i;
+
+ dst->count = 0;
+ dst->str = talloc_zero_array(mem_ctx, const char *, src->count);
+ if (dst->str == NULL) {
+ return NDR_ERR_ALLOC;
+ }
+
+ for (i = 0; i < src->count; i++) {
+ dst->str[i] = talloc_strdup(dst->str, src->str[i]);
+ if (dst->str[i] == NULL) {
+ TALLOC_FREE(dst->str);
+ return NDR_ERR_ALLOC;
+ }
+ }
+
+ dst->count = src->count;
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_dnsp.h b/librpc/ndr/ndr_dnsp.h
index 67f952c..0d56633 100644
--- a/librpc/ndr/ndr_dnsp.h
+++ b/librpc/ndr/ndr_dnsp.h
@@ -27,3 +27,7 @@ void ndr_print_dnsp_string(struct ndr_print *ndr, const char *name,
const char *dns_string);
enum ndr_err_code ndr_pull_dnsp_string(struct ndr_pull *ndr, int ndr_flags, const char **string);
enum ndr_err_code ndr_push_dnsp_string(struct ndr_push *ndr, int ndr_flags, const char *string);
+
+enum ndr_err_code ndr_dnsp_string_list_copy(TALLOC_CTX *mem_ctx,
+ const struct dnsp_string_list *src,
+ struct dnsp_string_list *dst);
diff --git a/librpc/wscript_build b/librpc/wscript_build
index 1594e72..d376bec 100644
--- a/librpc/wscript_build
+++ b/librpc/wscript_build
@@ -27,12 +27,12 @@ bld.SAMBA_SUBSYSTEM('NDR_NAMED_PIPE_AUTH',
bld.SAMBA_SUBSYSTEM('NDR_DNSSERVER',
source='gen_ndr/ndr_dnsserver.c ndr/ndr_dnsserver.c',
- public_deps='ndr'
+ public_deps='ndr NDR_DNSP'
)
bld.SAMBA_SUBSYSTEM('NDR_DNS',
source='gen_ndr/ndr_dns.c ndr/ndr_dns.c',
- public_deps='ndr'
+ public_deps='ndr NDR_DNSP'
)
bld.SAMBA_SUBSYSTEM('NDR_DSBACKUP',
@@ -371,7 +371,7 @@ bld.SAMBA_LIBRARY('ndr-standard',
pc_files='ndr_standard.pc',
deps='''NDR_SECURITY NDR_LSA NDR_SAMR NDR_NETLOGON NDR_EVENTLOG NDR_DFS
NDR_NTSVCS NDR_SVCCTL NDR_INITSHUTDOWN NDR_WKSSVC NDR_SRVSVC NDR_WINREG
- NDR_ECHO security NDR_DNS NDR_ATSVC NDR_SPOOLSS NDR_DSSETUP
+ NDR_ECHO security NDR_DNS NDR_DNSP NDR_ATSVC NDR_SPOOLSS NDR_DSSETUP
NDR_SERVER_ID NDR_NOTIFY''',
public_deps='ndr',
public_headers='gen_ndr/samr.h gen_ndr/ndr_samr.h gen_ndr/lsa.h gen_ndr/netlogon.h gen_ndr/atsvc.h gen_ndr/ndr_atsvc.h gen_ndr/ndr_svcctl.h gen_ndr/svcctl.h',
@@ -453,11 +453,6 @@ bld.SAMBA_SUBSYSTEM('RPC_NDR_AUDIOSRV',
public_deps='NDR_AUDIOSRV dcerpc-binding'
)
-bld.SAMBA_SUBSYSTEM('RPC_NDR_DNS',
- source='gen_ndr/ndr_dns_c.c',
- public_deps='dcerpc-binding NDR_DNS'
- )
-
bld.SAMBA_SUBSYSTEM('RPC_NDR_ECHO',
source='gen_ndr/ndr_echo_c.c',
public_deps='dcerpc-binding NDR_ECHO'
@@ -640,11 +635,6 @@ bld.SAMBA_SUBSYSTEM('RPC_NDR_BACKUPKEY',
public_deps='dcerpc-binding NDR_BACKUPKEY'
)
-bld.SAMBA_SUBSYSTEM('RPC_NDR_DNSP',
- source='gen_ndr/ndr_dnsp_c.c',
- public_deps='dcerpc-binding NDR_DNSP'
- )
-
bld.SAMBA_SUBSYSTEM('RPC_NDR_DNSSERVER',
source='gen_ndr/ndr_dnsserver_c.c',
public_deps='dcerpc-binding ndr-standard'
@@ -679,7 +669,7 @@ bld.SAMBA_SUBSYSTEM('RPC_NDR_MDSSVC',
bld.SAMBA_LIBRARY('ndr-samba',
source=[],
deps='''NDR_DRSBLOBS NDR_DRSUAPI NDR_IDMAP NDR_NTLMSSP NDR_SCHANNEL NDR_MGMT
- NDR_DNSP NDR_EPMAPPER NDR_XATTR NDR_UNIXINFO NDR_NAMED_PIPE_AUTH NDR_DCOM
+ NDR_DNSSERVER NDR_EPMAPPER NDR_XATTR NDR_UNIXINFO NDR_NAMED_PIPE_AUTH NDR_DCOM
NDR_NTPRINTING NDR_FSRVP NDR_WITNESS NDR_MDSSVC NDR_OPEN_FILES NDR_SMBXSRV''',
private_library=True,
grouping_library=True
@@ -691,7 +681,7 @@ bld.SAMBA_LIBRARY('dcerpc-samba',
deps='''RPC_NDR_LSA RPC_NDR_SAMR RPC_NDR_NETLOGON RPC_NDR_EVENTLOG
RPC_NDR_DFS RPC_NDR_NTSVCS RPC_NDR_SVCCTL RPC_NDR_INITSHUTDOWN
RPC_NDR_WKSSVC RPC_NDR_SRVSVC RPC_NDR_WINREG RPC_NDR_ECHO RPC_NDR_EPMAPPER
- RPC_NDR_ATSVC RPC_NDR_SPOOLSS RPC_NDR_DNS''',
+ RPC_NDR_ATSVC RPC_NDR_SPOOLSS RPC_NDR_DNSSERVER''',
public_deps='ndr-standard',
private_library=True,
grouping_library=True
diff --git a/python/samba/__init__.py b/python/samba/__init__.py
index 84b0b1f..aaf335c 100644
--- a/python/samba/__init__.py
+++ b/python/samba/__init__.py
@@ -362,6 +362,30 @@ def dn_from_dns_name(dnsdomain):
def current_unix_time():
return int(time.time())
+def string_to_byte_array(string):
+ blob = [0] * len(string)
+
+ for i in range(len(string)):
+ blob[i] = ord(string[i])
+
+ return blob
+
+def arcfour_encrypt(key, data):
+ try:
+ from Crypto.Cipher import ARC4
+ c = ARC4.new(key)
+ return c.encrypt(data)
+ except ImportError as e:
+ pass
+ try:
+ from M2Crypto.RC4 import RC4
+ c = RC4(key)
+ return c.update(data)
+ except ImportError as e:
+ pass
+ raise Exception("arcfour_encrypt() requires " +
+ "python*-crypto or python*-m2crypto or m2crypto")
+
import _glue
version = _glue.version
interface_ips = _glue.interface_ips
diff --git a/python/samba/join.py b/python/samba/join.py
index c356145..f71f3de 100644
--- a/python/samba/join.py
+++ b/python/samba/join.py
@@ -20,7 +20,7 @@
from samba.auth import system_session
from samba.samdb import SamDB
-from samba import gensec, Ldb, drs_utils
+from samba import gensec, Ldb, drs_utils, arcfour_encrypt, string_to_byte_array
import ldb, samba, sys, uuid
from samba.ndr import ndr_pack
from samba.dcerpc import security, drsuapi, misc, nbt, lsa, drsblobs
@@ -944,19 +944,6 @@ class dc_join(object):
def join_setup_trusts(ctx):
"""provision the local SAM."""
- def arcfour_encrypt(key, data):
- from Crypto.Cipher import ARC4
- c = ARC4.new(key)
- return c.encrypt(data)
-
- def string_to_array(string):
- blob = [0] * len(string)
-
- for i in range(len(string)):
- blob[i] = ord(string[i])
-
- return blob
-
print "Setup domain trusts with server %s" % ctx.server
binding_options = "" # why doesn't signing work here? w2k8r2 claims no session key
lsaconn = lsa.lsarpc("ncacn_np:%s[%s]" % (ctx.server, binding_options),
@@ -986,7 +973,7 @@ class dc_join(object):
except RuntimeError:
pass
- password_blob = string_to_array(ctx.trustdom_pass.encode('utf-16-le'))
+ password_blob = string_to_byte_array(ctx.trustdom_pass.encode('utf-16-le'))
clear_value = drsblobs.AuthInfoClear()
clear_value.size = len(password_blob)
@@ -1022,7 +1009,7 @@ class dc_join(object):
auth_blob = lsa.DATA_BUF2()
auth_blob.size = len(encrypted_trustpass)
- auth_blob.data = string_to_array(encrypted_trustpass)
+ auth_blob.data = string_to_byte_array(encrypted_trustpass)
auth_info = lsa.TrustDomainInfoAuthInfoInternal()
auth_info.auth_blob = auth_blob
diff --git a/python/samba/netcmd/domain.py b/python/samba/netcmd/domain.py
index f0710f2..119e8b2 100644
--- a/python/samba/netcmd/domain.py
+++ b/python/samba/netcmd/domain.py
@@ -58,7 +58,7 @@ from samba.upgrade import upgrade_from_samba3
from samba.drs_utils import (
sendDsReplicaSync, drsuapi_connect, drsException,
sendRemoveDsServer)
-
+from samba import arcfour_encrypt, string_to_byte_array
from samba.dsdb import (
DS_DOMAIN_FUNCTION_2000,
@@ -2125,24 +2125,16 @@ class cmd_domain_trust_create(DomainTrustCommand):
password = None
self.outf.write("Sorry, passwords do not match.\n")
- def string_to_array(string):
- blob = [0] * len(string)
-
- for i in range(len(string)):
- blob[i] = ord(string[i])
-
- return blob
-
incoming_secret = None
outgoing_secret = None
remote_policy_access = lsa.LSA_POLICY_VIEW_LOCAL_INFORMATION
if create_location == "local":
if local_trust_info.trust_direction & lsa.LSA_TRUST_DIRECTION_INBOUND:
incoming_password = get_password("Incoming Trust")
- incoming_secret = string_to_array(incoming_password.encode('utf-16-le'))
+ incoming_secret = string_to_byte_array(incoming_password.encode('utf-16-le'))
if local_trust_info.trust_direction & lsa.LSA_TRUST_DIRECTION_OUTBOUND:
outgoing_password = get_password("Outgoing Trust")
- outgoing_secret = string_to_array(outgoing_password.encode('utf-16-le'))
+ outgoing_secret = string_to_byte_array(outgoing_password.encode('utf-16-le'))
remote_trust_info = None
else:
@@ -2167,7 +2159,7 @@ class cmd_domain_trust_create(DomainTrustCommand):
#
# We can remove this once our client libraries
# support using the correct NTHASH.
- return string_to_array(pw1.encode('utf-16-le'))
+ return string_to_byte_array(pw1.encode('utf-16-le'))
# We mix characters from generate_random_password
# with random numbers from random.randint()
@@ -2320,11 +2312,6 @@ class cmd_domain_trust_create(DomainTrustCommand):
except RuntimeError as error:
raise self.RemoteRuntimeError(self, error, "failed to get netlogon dc info")
- def arcfour_encrypt(key, data):
- from Crypto.Cipher import ARC4
- c = ARC4.new(key)
- return c.encrypt(data)
-
def generate_AuthInOutBlob(secret, update_time):
if secret is None:
blob = drsblobs.trustAuthInOutBlob()
@@ -2368,7 +2355,7 @@ class cmd_domain_trust_create(DomainTrustCommand):
auth_blob = lsa.DATA_BUF2()
auth_blob.size = len(encrypted_trustpass)
- auth_blob.data = string_to_array(encrypted_trustpass)
+ auth_blob.data = string_to_byte_array(encrypted_trustpass)
auth_info = lsa.TrustDomainInfoAuthInfoInternal()
auth_info.auth_blob = auth_blob
diff --git a/python/samba/netcmd/fsmo.py b/python/samba/netcmd/fsmo.py
index 0b4488f..3904bcb 100644
--- a/python/samba/netcmd/fsmo.py
+++ b/python/samba/netcmd/fsmo.py
@@ -38,7 +38,8 @@ def get_fsmo_roleowner(samdb, roledn):
"""
res = samdb.search(roledn,
scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
- assert len(res) == 1
+ if len(res) == 0:
+ raise CommandError('"%s" does not have a FSMO roleowner' % roledn)
master_owner = res[0]["fSMORoleOwner"][0]
return master_owner
diff --git a/python/samba/tests/core.py b/python/samba/tests/core.py
index 8206e68..9dbaff1 100644
--- a/python/samba/tests/core.py
+++ b/python/samba/tests/core.py
@@ -20,6 +20,7 @@
import ldb
import os
import samba
+from samba import arcfour_encrypt, string_to_byte_array
from samba.tests import TestCase, TestCaseInTempDir
class SubstituteVarTestCase(TestCase):
@@ -48,6 +49,21 @@ class SubstituteVarTestCase(TestCase):
self.assertRaises(Exception, samba.check_all_substituted,
"Not subsituted: ${FOOBAR}")
+class ArcfourTestCase(TestCase):
+
+ def test_arcfour_direct(self):
+ key = '12345678'
+ plain = 'abcdefghi'
+ crypt_expected = '\xda\x91Z\xb0l\xd7\xb9\xcf\x99'
+ crypt_calculated = arcfour_encrypt(key, plain)
+ self.assertEquals(crypt_expected, crypt_calculated)
+
+class StringToByteArrayTestCase(TestCase):
+
+ def test_byte_array(self):
+ expected = [218, 145, 90, 176, 108, 215, 185, 207, 153]
+ calculated = string_to_byte_array('\xda\x91Z\xb0l\xd7\xb9\xcf\x99')
+ self.assertEquals(expected, calculated)
class LdbExtensionTests(TestCaseInTempDir):
diff --git a/python/samba/tests/dns.py b/python/samba/tests/dns.py
index 04ac356..e0739d0 100644
--- a/python/samba/tests/dns.py
+++ b/python/samba/tests/dns.py
@@ -16,18 +16,67 @@
#
import os
+import sys
import struct
import random
import socket
import samba.ndr as ndr
-import samba.dcerpc.dns as dns
from samba import credentials, param
from samba.tests import TestCase
-from samba.dcerpc import dnsp, dnsserver
-
+from samba.dcerpc import dns, dnsp, dnsserver
+from samba.netcmd.dns import TXTRecord, dns_record_match, data_to_dns_record
+from samba.tests.subunitrun import SubunitOptions, TestProgram
+import samba.getopt as options
+import optparse
+
+parser = optparse.OptionParser("dns.py <server name> <server ip> [options]")
+sambaopts = options.SambaOptions(parser)
+parser.add_option_group(sambaopts)
+
+# This timeout only has relevance when testing against Windows
+# Format errors tend to return patchy responses, so a timeout is needed.
+parser.add_option("--timeout", type="int", dest="timeout",
+ help="Specify timeout for DNS requests")
+
+# use command line creds if available
+credopts = options.CredentialsOptions(parser)
+parser.add_option_group(credopts)
+subunitopts = SubunitOptions(parser)
+parser.add_option_group(subunitopts)
+
+opts, args = parser.parse_args()
+
+lp = sambaopts.get_loadparm()
+creds = credopts.get_credentials(lp)
+
+timeout = opts.timeout
+
+if len(args) < 2:
+ parser.print_usage()
+ sys.exit(1)
+
+server_name = args[0]
+server_ip = args[1]
+creds.set_krb_forwardable(credentials.NO_KRB_FORWARDABLE)
+
+def make_txt_record(records):
+ rdata_txt = dns.txt_record()
+ s_list = dnsp.string_list()
+ s_list.count = len(records)
+ s_list.str = records
+ rdata_txt.txt = s_list
+ return rdata_txt
class DNSTest(TestCase):
+ def setUp(self):
+ global server, server_ip, lp, creds
+ super(DNSTest, self).setUp()
+ self.server = server_name
+ self.server_ip = server_ip
+ self.lp = lp
+ self.creds = creds
+
def errstr(self, errcode):
"Return a readable error code"
string_codes = [
@@ -83,9 +132,10 @@ class DNSTest(TestCase):
def get_dns_domain(self):
"Helper to get dns domain"
- return os.getenv('REALM', 'example.com').lower()
+ return self.creds.get_realm().lower()
- def dns_transaction_udp(self, packet, host=os.getenv('SERVER_IP'), dump=False):
+ def dns_transaction_udp(self, packet, host=server_ip,
+ dump=False, timeout=timeout):
"send a DNS query and read the reply"
s = None
try:
@@ -93,6 +143,7 @@ class DNSTest(TestCase):
if dump:
print self.hexdump(send_packet)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
+ s.settimeout(timeout)
s.connect((host, 53))
s.send(send_packet, 0)
recv_packet = s.recv(2048, 0)
@@ -103,7 +154,8 @@ class DNSTest(TestCase):
if s is not None:
s.close()
- def dns_transaction_tcp(self, packet, host=os.getenv('SERVER_IP'), dump=False):
+ def dns_transaction_tcp(self, packet, host=server_ip,
+ dump=False, timeout=timeout):
"send a DNS query and read the reply"
s = None
try:
@@ -111,6 +163,7 @@ class DNSTest(TestCase):
if dump:
print self.hexdump(send_packet)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
+ s.settimeout(timeout)
s.connect((host, 53))
tcp_packet = struct.pack('!H', len(send_packet))
tcp_packet += send_packet
@@ -123,6 +176,44 @@ class DNSTest(TestCase):
if s is not None:
s.close()
+ def make_txt_update(self, prefix, txt_array):
+ p = self.make_name_packet(dns.DNS_OPCODE_UPDATE)
+ updates = []
+
+ name = self.get_dns_domain()
+ u = self.make_name_question(name, dns.DNS_QTYPE_SOA, dns.DNS_QCLASS_IN)
+ updates.append(u)
+ self.finish_name_packet(p, updates)
+
+ updates = []
+ r = dns.res_rec()
+ r.name = "%s.%s" % (prefix, self.get_dns_domain())
+ r.rr_type = dns.DNS_QTYPE_TXT
+ r.rr_class = dns.DNS_QCLASS_IN
+ r.ttl = 900
+ r.length = 0xffff
+ rdata = make_txt_record(txt_array)
+ r.rdata = rdata
+ updates.append(r)
+ p.nscount = len(updates)
+ p.nsrecs = updates
+
+ return p
+
+ def check_query_txt(self, prefix, txt_array):
+ name = "%s.%s" % (prefix, self.get_dns_domain())
+ p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
+ questions = []
+
+ q = self.make_name_question(name, dns.DNS_QTYPE_TXT, dns.DNS_QCLASS_IN)
+ questions.append(q)
+
+ self.finish_name_packet(p, questions)
+ response = self.dns_transaction_udp(p)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.assertEquals(response.ancount, 1)
+ self.assertEquals(response.answers[0].rdata.txt.str, txt_array)
+
class TestSimpleQueries(DNSTest):
def test_one_a_query(self):
@@ -130,7 +221,7 @@ class TestSimpleQueries(DNSTest):
p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
questions = []
- name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+ name = "%s.%s" % (self.server, self.get_dns_domain())
q = self.make_name_question(name, dns.DNS_QTYPE_A, dns.DNS_QCLASS_IN)
print "asking for ", q.name
questions.append(q)
@@ -141,14 +232,14 @@ class TestSimpleQueries(DNSTest):
self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY)
self.assertEquals(response.ancount, 1)
self.assertEquals(response.answers[0].rdata,
- os.getenv('SERVER_IP'))
+ self.server_ip)
def test_one_a_query_tcp(self):
"create a query packet containing one query record via TCP"
p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
questions = []
- name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+ name = "%s.%s" % (self.server, self.get_dns_domain())
q = self.make_name_question(name, dns.DNS_QTYPE_A, dns.DNS_QCLASS_IN)
print "asking for ", q.name
questions.append(q)
@@ -159,14 +250,14 @@ class TestSimpleQueries(DNSTest):
self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY)
self.assertEquals(response.ancount, 1)
self.assertEquals(response.answers[0].rdata,
- os.getenv('SERVER_IP'))
+ self.server_ip)
def test_one_mx_query(self):
"create a query packet causing an empty RCODE_OK answer"
p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
questions = []
- name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+ name = "%s.%s" % (self.server, self.get_dns_domain())
q = self.make_name_question(name, dns.DNS_QTYPE_MX, dns.DNS_QCLASS_IN)
print "asking for ", q.name
questions.append(q)
@@ -180,7 +271,7 @@ class TestSimpleQueries(DNSTest):
p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
questions = []
- name = "invalid-%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+ name = "invalid-%s.%s" % (self.server, self.get_dns_domain())
q = self.make_name_question(name, dns.DNS_QTYPE_MX, dns.DNS_QCLASS_IN)
print "asking for ", q.name
questions.append(q)
@@ -196,7 +287,7 @@ class TestSimpleQueries(DNSTest):
p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
questions = []
- name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+ name = "%s.%s" % (self.server, self.get_dns_domain())
q = self.make_name_question(name, dns.DNS_QTYPE_A, dns.DNS_QCLASS_IN)
questions.append(q)
@@ -205,15 +296,22 @@ class TestSimpleQueries(DNSTest):
questions.append(q)
self.finish_name_packet(p, questions)
- response = self.dns_transaction_udp(p)
- self.assert_dns_rcode_equals(response, dns.DNS_RCODE_FORMERR)
+ try:
+ response = self.dns_transaction_udp(p)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_FORMERR)
+ except socket.timeout:
+ # Windows chooses not to respond to incorrectly formatted queries.
+ # Although this appears to be non-deterministic even for the same
+ # request twice, it also appears to be based on a how poorly the
+ # request is formatted.
+ pass
def test_qtype_all_query(self):
"create a QTYPE_ALL query"
p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
questions = []
- name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+ name = "%s.%s" % (self.server, self.get_dns_domain())
q = self.make_name_question(name, dns.DNS_QTYPE_ALL, dns.DNS_QCLASS_IN)
print "asking for ", q.name
questions.append(q)
@@ -230,7 +328,7 @@ class TestSimpleQueries(DNSTest):
self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY)
self.assertEquals(response.ancount, num_answers)
self.assertEquals(response.answers[0].rdata,
- os.getenv('SERVER_IP'))
+ self.server_ip)
if dc_ipv6 is not None:
self.assertEquals(response.answers[1].rdata, dc_ipv6)
@@ -239,13 +337,20 @@ class TestSimpleQueries(DNSTest):
p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
questions = []
- name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+ name = "%s.%s" % (self.server, self.get_dns_domain())
q = self.make_name_question(name, dns.DNS_QTYPE_ALL, dns.DNS_QCLASS_NONE)
questions.append(q)
self.finish_name_packet(p, questions)
- response = self.dns_transaction_udp(p)
- self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NOTIMP)
+ try:
+ response = self.dns_transaction_udp(p)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NOTIMP)
+ except socket.timeout:
+ # Windows chooses not to respond to incorrectly formatted queries.
+ # Although this appears to be non-deterministic even for the same
+ # request twice, it also appears to be based on a how poorly the
+ # request is formatted.
+ pass
# Only returns an authority section entry in BIND and Win DNS
# FIXME: Enable one Samba implements this feature
@@ -289,7 +394,7 @@ class TestDNSUpdates(DNSTest):
p = self.make_name_packet(dns.DNS_OPCODE_UPDATE)
updates = []
- name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+ name = "%s.%s" % (self.server, self.get_dns_domain())
u = self.make_name_question(name, dns.DNS_QTYPE_A, dns.DNS_QCLASS_IN)
updates.append(u)
@@ -298,8 +403,15 @@ class TestDNSUpdates(DNSTest):
updates.append(u)
self.finish_name_packet(p, updates)
- response = self.dns_transaction_udp(p)
- self.assert_dns_rcode_equals(response, dns.DNS_RCODE_FORMERR)
+ try:
+ response = self.dns_transaction_udp(p)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_FORMERR)
+ except socket.timeout:
+ # Windows chooses not to respond to incorrectly formatted queries.
+ # Although this appears to be non-deterministic even for the same
+ # request twice, it also appears to be based on a how poorly the
+ # request is formatted.
+ pass
def test_update_wrong_qclass(self):
"create update with DNS_QCLASS_NONE"
@@ -327,7 +439,7 @@ class TestDNSUpdates(DNSTest):
prereqs = []
r = dns.res_rec()
- r.name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+ r.name = "%s.%s" % (self.server, self.get_dns_domain())
r.rr_type = dns.DNS_QTYPE_TXT
r.rr_class = dns.DNS_QCLASS_NONE
r.ttl = 1
@@ -337,38 +449,18 @@ class TestDNSUpdates(DNSTest):
p.ancount = len(prereqs)
p.answers = prereqs
- response = self.dns_transaction_udp(p)
- self.assert_dns_rcode_equals(response, dns.DNS_RCODE_FORMERR)
-
-# I'd love to test this one, but it segfaults. :)
-# def test_update_prereq_with_non_null_length(self):
-# "test update with a non-null length"
-# p = self.make_name_packet(dns.DNS_OPCODE_UPDATE)
-# updates = []
-#
-# name = self.get_dns_domain()
-#
-# u = self.make_name_question(name, dns.DNS_QTYPE_SOA, dns.DNS_QCLASS_IN)
-# updates.append(u)
-# self.finish_name_packet(p, updates)
-#
-# prereqs = []
-# r = dns.res_rec()
-# r.name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
-# r.rr_type = dns.DNS_QTYPE_TXT
-# r.rr_class = dns.DNS_QCLASS_ANY
-# r.ttl = 0
-# r.length = 1
-# prereqs.append(r)
-#
-# p.ancount = len(prereqs)
-# p.answers = prereqs
-#
-# response = self.dns_transaction_udp(p)
-# self.assert_dns_rcode_equals(response, dns.DNS_RCODE_FORMERR)
-
- def test_update_prereq_nonexisting_name(self):
- "test update with a nonexisting name"
+ try:
+ response = self.dns_transaction_udp(p)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_FORMERR)
+ except socket.timeout:
+ # Windows chooses not to respond to incorrectly formatted queries.
+ # Although this appears to be non-deterministic even for the same
+ # request twice, it also appears to be based on a how poorly the
+ # request is formatted.
+ pass
+
+ def test_update_prereq_with_non_null_length(self):
+ "test update with a non-null length"
p = self.make_name_packet(dns.DNS_OPCODE_UPDATE)
updates = []
@@ -380,11 +472,11 @@ class TestDNSUpdates(DNSTest):
prereqs = []
r = dns.res_rec()
- r.name = "idontexist.%s" % self.get_dns_domain()
+ r.name = "%s.%s" % (self.server, self.get_dns_domain())
r.rr_type = dns.DNS_QTYPE_TXT
r.rr_class = dns.DNS_QCLASS_ANY
r.ttl = 0
- r.length = 0
+ r.length = 1
prereqs.append(r)
p.ancount = len(prereqs)
@@ -393,8 +485,8 @@ class TestDNSUpdates(DNSTest):
response = self.dns_transaction_udp(p)
self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NXRRSET)
- def test_update_add_txt_record(self):
- "test adding records works"
+ def test_update_prereq_nonexisting_name(self):
+ "test update with a nonexisting name"
p = self.make_name_packet(dns.DNS_OPCODE_UPDATE)
updates = []
@@ -404,76 +496,28 @@ class TestDNSUpdates(DNSTest):
updates.append(u)
self.finish_name_packet(p, updates)
- updates = []
+ prereqs = []
r = dns.res_rec()
- r.name = "textrec.%s" % self.get_dns_domain()
+ r.name = "idontexist.%s" % self.get_dns_domain()
r.rr_type = dns.DNS_QTYPE_TXT
- r.rr_class = dns.DNS_QCLASS_IN
- r.ttl = 900
- r.length = 0xffff
- rdata = dns.txt_record()
- rdata.txt = '"This is a test"'
- r.rdata = rdata
- updates.append(r)
- p.nscount = len(updates)
- p.nsrecs = updates
-
- response = self.dns_transaction_udp(p)
- self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
-
- p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
- questions = []
-
- name = "textrec.%s" % self.get_dns_domain()
- q = self.make_name_question(name, dns.DNS_QTYPE_TXT, dns.DNS_QCLASS_IN)
- questions.append(q)
-
- self.finish_name_packet(p, questions)
- response = self.dns_transaction_udp(p)
- self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
- self.assertEquals(response.ancount, 1)
- self.assertEquals(response.answers[0].rdata.txt, '"This is a test"')
-
- def test_update_add_two_txt_records(self):
- "test adding two txt records works"
- p = self.make_name_packet(dns.DNS_OPCODE_UPDATE)
- updates = []
-
- name = self.get_dns_domain()
-
- u = self.make_name_question(name, dns.DNS_QTYPE_SOA, dns.DNS_QCLASS_IN)
- updates.append(u)
- self.finish_name_packet(p, updates)
+ r.rr_class = dns.DNS_QCLASS_ANY
+ r.ttl = 0
+ r.length = 0
+ prereqs.append(r)
- updates = []
- r = dns.res_rec()
- r.name = "textrec2.%s" % self.get_dns_domain()
- r.rr_type = dns.DNS_QTYPE_TXT
- r.rr_class = dns.DNS_QCLASS_IN
- r.ttl = 900
- r.length = 0xffff
- rdata = dns.txt_record()
- rdata.txt = '"This is a test" "and this is a test, too"'
- r.rdata = rdata
- updates.append(r)
- p.nscount = len(updates)
- p.nsrecs = updates
+ p.ancount = len(prereqs)
+ p.answers = prereqs
response = self.dns_transaction_udp(p)
- self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
-
- p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
- questions = []
-
- name = "textrec2.%s" % self.get_dns_domain()
- q = self.make_name_question(name, dns.DNS_QTYPE_TXT, dns.DNS_QCLASS_IN)
- questions.append(q)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NXRRSET)
- self.finish_name_packet(p, questions)
+ def test_update_add_txt_record(self):
+ "test adding records works"
+ prefix, txt = 'textrec', ['"This is a test"']
+ p = self.make_txt_update(prefix, txt)
response = self.dns_transaction_udp(p)
self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
- self.assertEquals(response.ancount, 1)
- self.assertEquals(response.answers[0].rdata.txt, '"This is a test" "and this is a test, too"')
+ self.check_query_txt(prefix, txt)
def test_delete_record(self):
"Test if deleting records works"
@@ -497,8 +541,7 @@ class TestDNSUpdates(DNSTest):
r.rr_class = dns.DNS_QCLASS_IN
r.ttl = 900
r.length = 0xffff
- rdata = dns.txt_record()
- rdata.txt = '"This is a test"'
+ rdata = make_txt_record(['"This is a test"'])
r.rdata = rdata
updates.append(r)
p.nscount = len(updates)
@@ -534,8 +577,7 @@ class TestDNSUpdates(DNSTest):
r.rr_class = dns.DNS_QCLASS_NONE
r.ttl = 0
r.length = 0xffff
- rdata = dns.txt_record()
- rdata.txt = '"This is a test"'
+ rdata = make_txt_record(['"This is a test"'])
r.rdata = rdata
updates.append(r)
p.nscount = len(updates)
@@ -577,8 +619,7 @@ class TestDNSUpdates(DNSTest):
r.rr_class = dns.DNS_QCLASS_IN
r.ttl = 900
r.length = 0xffff
- rdata = dns.txt_record()
- rdata.txt = '"This is a test"'
+ rdata = make_txt_record(['"This is a test"'])
r.rdata = rdata
updates.append(r)
p.nscount = len(updates)
@@ -614,8 +655,7 @@ class TestDNSUpdates(DNSTest):
r.rr_class = dns.DNS_QCLASS_NONE
r.ttl = 0
r.length = 0xffff
- rdata = dns.txt_record()
- rdata.txt = '"This is a test"'
+ rdata = make_txt_record(['"This is a test"'])
r.rdata = rdata
updates.append(r)
p.nscount = len(updates)
@@ -652,8 +692,7 @@ class TestDNSUpdates(DNSTest):
r.rr_class = dns.DNS_QCLASS_IN
r.ttl = 900
r.length = 0xffff
- rdata = dns.txt_record()
- rdata.txt = '"This is a test"'
+ rdata = make_txt_record(['"This is a test"'])
r.rdata = rdata
updates.append(r)
p.nscount = len(updates)
@@ -738,7 +777,7 @@ class TestComplexQueries(DNSTest):
r.rr_class = dns.DNS_QCLASS_IN
r.ttl = 900
r.length = 0xffff
- r.rdata = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+ r.rdata = "%s.%s" % (self.server, self.get_dns_domain())
updates.append(r)
p.nscount = len(updates)
p.nsrecs = updates
@@ -764,7 +803,7 @@ class TestComplexQueries(DNSTest):
r.rr_class = dns.DNS_QCLASS_NONE
r.ttl = 0
r.length = 0xffff
- r.rdata = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+ r.rdata = "%s.%s" % (self.server, self.get_dns_domain())
updates.append(r)
p.nscount = len(updates)
p.nsrecs = updates
@@ -789,10 +828,10 @@ class TestComplexQueries(DNSTest):
self.assertEquals(response.ancount, 2)
self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_CNAME)
self.assertEquals(response.answers[0].rdata, "%s.%s" %
- (os.getenv('SERVER'), self.get_dns_domain()))
+ (self.server, self.get_dns_domain()))
self.assertEquals(response.answers[1].rr_type, dns.DNS_QTYPE_A)
self.assertEquals(response.answers[1].rdata,
- os.getenv('SERVER_IP'))
+ self.server_ip)
class TestInvalidQueries(DNSTest):
@@ -802,7 +841,7 @@ class TestInvalidQueries(DNSTest):
s = None
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
- s.connect((os.getenv('SERVER_IP'), 53))
+ s.connect((self.server_ip, 53))
s.send("", 0)
finally:
if s is not None:
@@ -811,7 +850,7 @@ class TestInvalidQueries(DNSTest):
p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
questions = []
- name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+ name = "%s.%s" % (self.server, self.get_dns_domain())
q = self.make_name_question(name, dns.DNS_QTYPE_A, dns.DNS_QCLASS_IN)
print "asking for ", q.name
questions.append(q)
@@ -822,10 +861,11 @@ class TestInvalidQueries(DNSTest):
self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY)
self.assertEquals(response.ancount, 1)
self.assertEquals(response.answers[0].rdata,
- os.getenv('SERVER_IP'))
+ self.server_ip)
def test_one_a_reply(self):
"send a reply instead of a query"
+ global timeout
p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
questions = []
@@ -841,37 +881,29 @@ class TestInvalidQueries(DNSTest):
try:
send_packet = ndr.ndr_pack(p)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
- host=os.getenv('SERVER_IP')
+ s.settimeout(timeout)
+ host=self.server_ip
s.connect((host, 53))
tcp_packet = struct.pack('!H', len(send_packet))
tcp_packet += send_packet
s.send(tcp_packet, 0)
recv_packet = s.recv(0xffff + 2, 0)
self.assertEquals(0, len(recv_packet))
+ except socket.timeout:
+ # Windows chooses not to respond to incorrectly formatted queries.
+ # Although this appears to be non-deterministic even for the same
+ # request twice, it also appears to be based on a how poorly the
+ # request is formatted.
+ pass
finally:
if s is not None:
s.close()
class TestZones(DNSTest):
- def get_loadparm(self):
- lp = param.LoadParm()
- lp.load(os.getenv("SMB_CONF_PATH"))
- return lp
-
- def get_credentials(self, lp):
- creds = credentials.Credentials()
- creds.guess(lp)
- creds.set_machine_account(lp)
- creds.set_krb_forwardable(credentials.NO_KRB_FORWARDABLE)
- return creds
-
def setUp(self):
super(TestZones, self).setUp()
- self.lp = self.get_loadparm()
- self.creds = self.get_credentials(self.lp)
- self.server = os.getenv("SERVER_IP")
self.zone = "test.lan"
- self.rpc_conn = dnsserver.dnsserver("ncacn_ip_tcp:%s" % (self.server),
+ self.rpc_conn = dnsserver.dnsserver("ncacn_ip_tcp:%s[sign]" % (self.server_ip),
self.lp, self.creds)
def tearDown(self):
@@ -891,7 +923,7 @@ class TestZones(DNSTest):
zone_create.dwDpFlags = dnsserver.DNS_DP_DOMAIN_DEFAULT
self.rpc_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
0,
- self.server,
+ self.server_ip,
None,
0,
'ZoneCreate',
@@ -901,7 +933,7 @@ class TestZones(DNSTest):
def delete_zone(self, zone):
self.rpc_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
0,
- self.server,
+ self.server_ip,
zone,
0,
'DeleteZoneFromDs',
@@ -918,6 +950,7 @@ class TestZones(DNSTest):
self.finish_name_packet(p, questions)
response = self.dns_transaction_udp(p)
+ # Windows returns OK while BIND logically seems to return NXDOMAIN
self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NXDOMAIN)
self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY)
self.assertEquals(response.ancount, 0)
@@ -935,8 +968,293 @@ class TestZones(DNSTest):
self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY)
self.assertEquals(response.ancount, 0)
+class TestRPCRoundtrip(DNSTest):
+ def setUp(self):
+ super(TestRPCRoundtrip, self).setUp()
+ self.rpc_conn = dnsserver.dnsserver("ncacn_ip_tcp:%s[sign]" % (self.server_ip),
+ self.lp, self.creds)
+
+ def tearDown(self):
+ super(TestRPCRoundtrip, self).tearDown()
+
+ def test_update_add_txt_rpc_to_dns(self):
+ prefix, txt = 'rpctextrec', ['"This is a test"']
+
+ name = "%s.%s" % (prefix, self.get_dns_domain())
+
+ rec = data_to_dns_record(dnsp.DNS_TYPE_TXT, '"\\"This is a test\\""')
+ add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+ add_rec_buf.rec = rec
+ try:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, add_rec_buf, None)
+
+ self.check_query_txt(prefix, txt)
+ finally:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, None, add_rec_buf)
+
+ def test_update_add_null_padded_txt_record(self):
+ "test adding records works"
+ prefix, txt = 'pad1textrec', ['"This is a test"', '', '']
+ p = self.make_txt_update(prefix, txt)
+ response = self.dns_transaction_udp(p)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.check_query_txt(prefix, txt)
+ self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+ self.get_dns_domain(),
+ "%s.%s" % (prefix, self.get_dns_domain()),
+ dnsp.DNS_TYPE_TXT, '"\\"This is a test\\"" "" ""'))
+
+ prefix, txt = 'pad2textrec', ['"This is a test"', '', '', 'more text']
+ p = self.make_txt_update(prefix, txt)
+ response = self.dns_transaction_udp(p)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.check_query_txt(prefix, txt)
+ self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+ self.get_dns_domain(),
+ "%s.%s" % (prefix, self.get_dns_domain()),
+ dnsp.DNS_TYPE_TXT, '"\\"This is a test\\"" "" "" "more text"'))
+
+ prefix, txt = 'pad3textrec', ['', '', '"This is a test"']
+ p = self.make_txt_update(prefix, txt)
+ response = self.dns_transaction_udp(p)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.check_query_txt(prefix, txt)
+ self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+ self.get_dns_domain(),
+ "%s.%s" % (prefix, self.get_dns_domain()),
+ dnsp.DNS_TYPE_TXT, '"" "" "\\"This is a test\\""'))
+
+ def test_update_add_padding_rpc_to_dns(self):
+ prefix, txt = 'pad1textrec', ['"This is a test"', '', '']
+ prefix = 'rpc' + prefix
+ name = "%s.%s" % (prefix, self.get_dns_domain())
+
+ rec = data_to_dns_record(dnsp.DNS_TYPE_TXT, '"\\"This is a test\\"" "" ""')
+ add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+ add_rec_buf.rec = rec
+ try:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, add_rec_buf, None)
+
+ self.check_query_txt(prefix, txt)
+ finally:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, None, add_rec_buf)
+
+ prefix, txt = 'pad2textrec', ['"This is a test"', '', '', 'more text']
+ prefix = 'rpc' + prefix
+ name = "%s.%s" % (prefix, self.get_dns_domain())
+ rec = data_to_dns_record(dnsp.DNS_TYPE_TXT, '"\\"This is a test\\"" "" "" "more text"')
+ add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+ add_rec_buf.rec = rec
+ try:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, add_rec_buf, None)
+
+ self.check_query_txt(prefix, txt)
+ finally:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, None, add_rec_buf)
+
+ prefix, txt = 'pad3textrec', ['', '', '"This is a test"']
+ prefix = 'rpc' + prefix
+ name = "%s.%s" % (prefix, self.get_dns_domain())
+
+ rec = data_to_dns_record(dnsp.DNS_TYPE_TXT, '"" "" "\\"This is a test\\""')
+ add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+ add_rec_buf.rec = rec
+ try:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, add_rec_buf, None)
+
+ self.check_query_txt(prefix, txt)
+ finally:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, None, add_rec_buf)
+
+ # Test is incomplete due to strlen against txt records
+ def test_update_add_null_char_txt_record(self):
+ "test adding records works"
+ prefix, txt = 'nulltextrec', ['NULL\x00BYTE']
+ p = self.make_txt_update(prefix, txt)
+ response = self.dns_transaction_udp(p)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.check_query_txt(prefix, ['NULL'])
+ self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+ self.get_dns_domain(),
+ "%s.%s" % (prefix, self.get_dns_domain()),
+ dnsp.DNS_TYPE_TXT, '"NULL"'))
+
+ prefix, txt = 'nulltextrec2', ['NULL\x00BYTE', 'NULL\x00BYTE']
+ p = self.make_txt_update(prefix, txt)
+ response = self.dns_transaction_udp(p)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.check_query_txt(prefix, ['NULL', 'NULL'])
+ self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+ self.get_dns_domain(),
+ "%s.%s" % (prefix, self.get_dns_domain()),
+ dnsp.DNS_TYPE_TXT, '"NULL" "NULL"'))
+
+ def test_update_add_null_char_rpc_to_dns(self):
+ prefix, txt = 'nulltextrec', ['NULL\x00BYTE']
+ prefix = 'rpc' + prefix
+ name = "%s.%s" % (prefix, self.get_dns_domain())
+
+ rec = data_to_dns_record(dnsp.DNS_TYPE_TXT, '"NULL"')
+ add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+ add_rec_buf.rec = rec
+ try:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, add_rec_buf, None)
+
+ self.check_query_txt(prefix, ['NULL'])
+ finally:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, None, add_rec_buf)
+
+ def test_update_add_hex_char_txt_record(self):
+ "test adding records works"
+ prefix, txt = 'hextextrec', ['HIGH\xFFBYTE']
+ p = self.make_txt_update(prefix, txt)
+ response = self.dns_transaction_udp(p)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.check_query_txt(prefix, txt)
+ self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+ self.get_dns_domain(),
+ "%s.%s" % (prefix, self.get_dns_domain()),
+ dnsp.DNS_TYPE_TXT, '"HIGH\xFFBYTE"'))
+
+ def test_update_add_hex_rpc_to_dns(self):
+ prefix, txt = 'hextextrec', ['HIGH\xFFBYTE']
+ prefix = 'rpc' + prefix
+ name = "%s.%s" % (prefix, self.get_dns_domain())
+
+ rec = data_to_dns_record(dnsp.DNS_TYPE_TXT, '"HIGH\xFFBYTE"')
+ add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+ add_rec_buf.rec = rec
+ try:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, add_rec_buf, None)
+
+ self.check_query_txt(prefix, txt)
+ finally:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, None, add_rec_buf)
+
+ def test_update_add_slash_txt_record(self):
+ "test adding records works"
+ prefix, txt = 'slashtextrec', ['Th\\=is=is a test']
+ p = self.make_txt_update(prefix, txt)
+ response = self.dns_transaction_udp(p)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.check_query_txt(prefix, txt)
+ self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+ self.get_dns_domain(),
+ "%s.%s" % (prefix, self.get_dns_domain()),
+ dnsp.DNS_TYPE_TXT, '"Th\\\\=is=is a test"'))
+
+ # This test fails against Windows as it eliminates slashes in RPC
+ # One typical use for a slash is in records like 'var=value' to
+ # escape '=' characters.
+ def test_update_add_slash_rpc_to_dns(self):
+ prefix, txt = 'slashtextrec', ['Th\\=is=is a test']
+ prefix = 'rpc' + prefix
+ name = "%s.%s" % (prefix, self.get_dns_domain())
+
+ rec = data_to_dns_record(dnsp.DNS_TYPE_TXT, '"Th\\\\=is=is a test"')
+ add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+ add_rec_buf.rec = rec
+ try:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, add_rec_buf, None)
+
+ self.check_query_txt(prefix, txt)
+ finally:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, None, add_rec_buf)
+
+ def test_update_add_two_txt_records(self):
+ "test adding two txt records works"
+ prefix, txt = 'textrec2', ['"This is a test"',
+ '"and this is a test, too"']
+ p = self.make_txt_update(prefix, txt)
+ response = self.dns_transaction_udp(p)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.check_query_txt(prefix, txt)
+ self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+ self.get_dns_domain(),
+ "%s.%s" % (prefix, self.get_dns_domain()),
+ dnsp.DNS_TYPE_TXT, '"\\"This is a test\\""' +
+ ' "\\"and this is a test, too\\""'))
+
+ def test_update_add_two_rpc_to_dns(self):
+ prefix, txt = 'textrec2', ['"This is a test"',
+ '"and this is a test, too"']
+ prefix = 'rpc' + prefix
+ name = "%s.%s" % (prefix, self.get_dns_domain())
+
+ rec = data_to_dns_record(dnsp.DNS_TYPE_TXT,
+ '"\\"This is a test\\""' +
+ ' "\\"and this is a test, too\\""')
+ add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+ add_rec_buf.rec = rec
+ try:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, add_rec_buf, None)
+
+ self.check_query_txt(prefix, txt)
+ finally:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, None, add_rec_buf)
+
+ def test_update_add_empty_txt_records(self):
+ "test adding two txt records works"
+ prefix, txt = 'emptytextrec', []
+ p = self.make_txt_update(prefix, txt)
+ response = self.dns_transaction_udp(p)
+ self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+ self.check_query_txt(prefix, txt)
+ self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+ self.get_dns_domain(),
+ "%s.%s" % (prefix, self.get_dns_domain()),
+ dnsp.DNS_TYPE_TXT, ''))
+
+ def test_update_add_empty_rpc_to_dns(self):
+ prefix, txt = 'rpcemptytextrec', []
+
+ name = "%s.%s" % (prefix, self.get_dns_domain())
+
+ rec = data_to_dns_record(dnsp.DNS_TYPE_TXT, '')
+ add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+ add_rec_buf.rec = rec
+ try:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, add_rec_buf, None)
+
+ self.check_query_txt(prefix, txt)
+ finally:
+ self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, self.server_ip, self.get_dns_domain(),
+ name, None, add_rec_buf)
-if __name__ == "__main__":
- import unittest
- unittest.main()
+TestProgram(module=__name__, opts=subunitopts)
diff --git a/python/samba/tests/getopt.py b/python/samba/tests/get_opt.py
similarity index 100%
rename from python/samba/tests/getopt.py
rename to python/samba/tests/get_opt.py
diff --git a/selftest/knownfail b/selftest/knownfail
index 0d74933..d9e2823 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -16,6 +16,8 @@
^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).UID-REGRESSION-TEST # Fails against the s4 ntvfs server
^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).SHORTNAME-TEST # Fails against the s4 ntvfs server
^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).POSIX-APPEND # Fails against the s4 ntvfs server
+^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).POSIX-SYMLINK-ACL # Fails against the s4 ntvfs server
+^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).POSIX-SYMLINK-EA # Fails against the s4 ntvfs server
^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).NTTRANS-FSCTL # Fails against the s4 ntvfs server
^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).SMB2-NEGPROT # Fails against the s4 ntvfs server
^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).BAD-NBT-SESSION # Fails against the s4 ntvfs server
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 931667e..d16c440 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -590,6 +590,8 @@ sub setup_fileserver($$)
my $dfree_share_dir="$share_dir/dfree";
push(@dirs, $dfree_share_dir);
+ push(@dirs, "$dfree_share_dir/subdir1");
+ push(@dirs, "$dfree_share_dir/subdir2");
my $fileserver_options = "
[lowercase]
@@ -1092,6 +1094,15 @@ sub provision($$$$$$$$)
my $manglenames_shrdir="$shrdir/manglenames";
push(@dirs,$manglenames_shrdir);
+ my $shadow_tstdir="$shrdir/shadow";
+ push(@dirs,$shadow_tstdir);
+ my $shadow_mntdir="$shadow_tstdir/mount";
+ push(@dirs,$shadow_mntdir);
+ my $shadow_basedir="$shadow_mntdir/base";
+ push(@dirs,$shadow_basedir);
+ my $shadow_shrdir="$shadow_basedir/share";
+ push(@dirs,$shadow_shrdir);
+
# this gets autocreated by winbindd
my $wbsockdir="$prefix_abs/winbindd";
my $wbsockprivdir="$lockdir/winbindd_privileged";
@@ -1336,6 +1347,10 @@ sub provision($$$$$$$$)
# fruit:copyfile is a global option
fruit:copyfile = yes
+ #this does not mean that we use non-secure test env,
+ #it just means we ALLOW one to be configured.
+ allow insecure wide links = yes
+
# Begin extra options
$extra_options
# End extra options
@@ -1492,6 +1507,62 @@ sub provision($$$$$$$$)
shell_snap:delete command = $fake_snap_pl --delete
# a relative path here fails, the snapshot dir is no longer found
shadow:snapdir = $shrdir/.snapshots
+
+[shadow1]
+ path = $shadow_shrdir
+ comment = previous versions snapshots under mount point
+ vfs objects = shadow_copy2
+ shadow:mountpoint = $shadow_mntdir
+
+[shadow2]
+ path = $shadow_shrdir
+ comment = previous versions snapshots outside mount point
+ vfs objects = shadow_copy2
+ shadow:mountpoint = $shadow_mntdir
+ shadow:snapdir = $shadow_tstdir/.snapshots
+
+[shadow3]
+ path = $shadow_shrdir
+ comment = previous versions with subvolume snapshots, snapshots under base dir
+ vfs objects = shadow_copy2
+ shadow:mountpoint = $shadow_mntdir
+ shadow:basedir = $shadow_basedir
+ shadow:snapdir = $shadow_basedir/.snapshots
+
+[shadow4]
+ path = $shadow_shrdir
+ comment = previous versions with subvolume snapshots, snapshots outside mount point
+ vfs objects = shadow_copy2
+ shadow:mountpoint = $shadow_mntdir
+ shadow:basedir = $shadow_basedir
+ shadow:snapdir = $shadow_tstdir/.snapshots
+
+[shadow5]
+ path = $shadow_shrdir
+ comment = previous versions at volume root snapshots under mount point
+ vfs objects = shadow_copy2
+ shadow:mountpoint = $shadow_shrdir
+
+[shadow6]
+ path = $shadow_shrdir
+ comment = previous versions at volume root snapshots outside mount point
+ vfs objects = shadow_copy2
+ shadow:mountpoint = $shadow_shrdir
+ shadow:snapdir = $shadow_tstdir/.snapshots
+
+[shadow7]
+ path = $shadow_shrdir
+ comment = previous versions snapshots everywhere
+ vfs objects = shadow_copy2
+ shadow:mountpoint = $shadow_mntdir
+ shadow:snapdirseverywhere = yes
+
+[shadow_wl]
+ path = $shadow_shrdir
+ comment = previous versions with wide links allowed
+ vfs objects = shadow_copy2
+ shadow:mountpoint = $shadow_mntdir
+ wide links = yes
";
close(CONF);
diff --git a/selftest/tests.py b/selftest/tests.py
index 872fbaf..2a07f9e 100644
--- a/selftest/tests.py
+++ b/selftest/tests.py
@@ -48,7 +48,7 @@ planpythontestsuite("none", "api", name="ldb.python", extra_path=['lib/ldb/tests
planpythontestsuite("none", "samba.tests.credentials")
planpythontestsuite("none", "samba.tests.registry")
planpythontestsuite("none", "samba.tests.auth")
-planpythontestsuite("none", "samba.tests.getopt")
+planpythontestsuite("none", "samba.tests.get_opt")
planpythontestsuite("none", "samba.tests.security")
planpythontestsuite("none", "samba.tests.dcerpc.misc")
planpythontestsuite("none", "samba.tests.dcerpc.integer")
diff --git a/source3/client/README.smbspool b/source3/client/README.smbspool
new file mode 100644
index 0000000..f73167a
--- /dev/null
+++ b/source3/client/README.smbspool
@@ -0,0 +1,17 @@
+smbspool
+=========
+
+smbspool is a very small print spooling program that sends a print file to an
+SMB printer. The command-line arguments are position-dependent for
+compatibility with the CUPS.
+
+For printing support with Kerberos, CUPS 1.5+ needs a wrapper for the backend
+which sets the correct location of the Kerberos credential cache.
+
+smbspool_krb5_wrapper
+======================
+
+This tool can be used to print using Kerberos credentials. To get this working
+smbspool_krb5_wrapper needs to be the smb backend of CUPS. It needs to be owned
+by root and the permissions for the binary need to be 0700. Once
+smbspool_krb5_wrapper switched to the user trying to print it executes smbspool.
diff --git a/source3/client/client.c b/source3/client/client.c
index 034b48a..831b9bc 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -312,7 +312,7 @@ static int do_dskattr(void)
return 1;
}
- status = cli_disk_size(targetcli, &bsize, &total, &avail);
+ status = cli_disk_size(targetcli, targetpath, &bsize, &total, &avail);
if (!NT_STATUS_IS_OK(status)) {
d_printf("Error in dskattr: %s\n", nt_errstr(status));
return 1;
@@ -3376,7 +3376,7 @@ static int cmd_getfacl(void)
return 1;
}
- status = cli_posix_getfacl(targetcli, targetname, ctx, &rb_size, &retbuf);
+ status = cli_posix_getacl(targetcli, targetname, ctx, &rb_size, &retbuf);
if (!NT_STATUS_IS_OK(status)) {
d_printf("%s getfacl file %s\n",
nt_errstr(status), src);
diff --git a/source3/client/smbspool_krb5_wrapper.c b/source3/client/smbspool_krb5_wrapper.c
new file mode 100644
index 0000000..e19fd92
--- /dev/null
+++ b/source3/client/smbspool_krb5_wrapper.c
@@ -0,0 +1,210 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * CUPS printing backend helper to execute smbspool
+ *
+ * Copyright (C) 2010-2011 Andreas Schneider <asn at samba.org>
+ *
+ * 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
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "system/filesys.h"
+#include "system/passwd.h"
+
+#include <errno.h>
+#include <string.h>
+
+#include <cups/backend.h>
+
+#include "dynconfig/dynconfig.h"
+
+enum cups_smb_dbglvl_e {
+ CUPS_SMB_LOG_DEBUG = 0,
+ CUPS_SMB_LOG_ERROR,
+};
+static void cups_smb_debug(enum cups_smb_dbglvl_e lvl, const char *format, ...);
+
+#define CUPS_SMB_DEBUG(...) cups_smb_debug(CUPS_SMB_LOG_DEBUG, __VA_ARGS__)
+#define CUPS_SMB_ERROR(...) cups_smb_debug(CUPS_SMB_LOG_DEBUG, __VA_ARGS__)
+
+static void cups_smb_debug(enum cups_smb_dbglvl_e lvl, const char *format, ...)
+{
+ const char *prefix = "DEBUG";
+ char buffer[1024];
+ va_list va;
+
+ va_start(va, format);
+ vsnprintf(buffer, sizeof(buffer), format, va);
+ va_end(va);
+
+ switch (lvl) {
+ case CUPS_SMB_LOG_DEBUG:
+ prefix = "DEBUG";
+ break;
+ case CUPS_SMB_LOG_ERROR:
+ prefix = "ERROR";
+ break;
+ }
+
+ fprintf(stderr,
+ "%s: SMBSPOOL_KRB5 - %s\n",
+ prefix,
+ buffer);
+}
+
+/*
+ * This is a helper binary to execute smbspool.
+ *
+ * It needs to be installed or symlinked as:
+ * /usr/lib/cups/backend/smb
+ *
+ * The permissions of the binary need to be set to 0700 so that it is executed
+ * as root. The binary switches to the user which is passed via the environment
+ * variable AUTH_UID, so we can access the kerberos ticket.
+ */
+int main(int argc, char *argv[])
+{
+ char smbspool_cmd[PATH_MAX] = {0};
+ struct passwd *pwd;
+ char gen_cc[PATH_MAX] = {0};
+ struct stat sb;
+ char *env;
+ uid_t uid = (uid_t)-1;
+ gid_t gid = (gid_t)-1;
+ unsigned long tmp;
+ int cmp;
+ int rc;
+
+ uid = getuid();
+
+ CUPS_SMB_DEBUG("Started with uid=%d\n", uid);
+ if (uid != 0) {
+ goto smbspool;
+ }
+
+ /* Check if AuthInfoRequired is set to negotiate */
+ env = getenv("AUTH_INFO_REQUIRED");
+ if (env == NULL) {
+ CUPS_SMB_ERROR("AUTH_INFO_REQUIRED is not set");
+ fprintf(stderr, "ATTR: auth-info-required=negotiate\n");
+ return CUPS_BACKEND_AUTH_REQUIRED;
+ }
+
+ CUPS_SMB_DEBUG("AUTH_INFO_REQUIRED=%s", env);
+ cmp = strcmp(env, "negotiate");
+ if (cmp != 0) {
+ CUPS_SMB_ERROR("AUTH_INFO_REQUIRED is not set to negotiate");
+ fprintf(stderr, "ATTR: auth-info-required=negotiate\n");
+ return CUPS_BACKEND_AUTH_REQUIRED;
+ }
+
+ /*
+ * AUTH_UID gets only set if we have an incoming connection over the
+ * CUPS unix domain socket.
+ */
+ env = getenv("AUTH_UID");
+ if (env == NULL) {
+ CUPS_SMB_ERROR("AUTH_UID is not set");
+ fprintf(stderr, "ATTR: auth-info-required=negotiate\n");
+ return CUPS_BACKEND_AUTH_REQUIRED;
+ }
+
+ if (strlen(env) > 10) {
+ CUPS_SMB_ERROR("Invalid AUTH_UID");
+ return CUPS_BACKEND_FAILED;
+ }
+
+ errno = 0;
+ tmp = strtoul(env, NULL, 10);
+ if (errno != 0 || tmp >= UINT32_MAX) {
+ CUPS_SMB_ERROR("Failed to convert AUTH_UID=%s", env);
+ return CUPS_BACKEND_FAILED;
+ }
+ uid = (uid_t)tmp;
+
+ pwd = getpwuid(uid);
+ if (pwd == NULL) {
+ CUPS_SMB_ERROR("Failed to find system user: %u - %s",
+ uid, strerror(errno));
+ return CUPS_BACKEND_FAILED;
+ }
+ gid = pwd->pw_gid;
+
+ rc = setgroups(0, NULL);
+ if (rc != 0) {
+ CUPS_SMB_ERROR("Failed to clear groups - %s",
+ strerror(errno));
+ return CUPS_BACKEND_FAILED;
+ }
+
+ CUPS_SMB_DEBUG("Switching to gid=%d", gid);
+ rc = setgid(gid);
+ if (rc != 0) {
+ CUPS_SMB_ERROR("Failed to switch to gid=%u",
+ gid,
+ strerror(errno));
+ return CUPS_BACKEND_FAILED;
+ }
+
+ CUPS_SMB_DEBUG("Switching to uid=%u", uid);
+ rc = setuid(uid);
+ if (rc != 0) {
+ CUPS_SMB_ERROR("Failed to switch to uid=%u",
+ uid,
+ strerror(errno));
+ return CUPS_BACKEND_FAILED;
+ }
+
+ snprintf(gen_cc, sizeof(gen_cc), "/tmp/krb5cc_%d", uid);
+
+ rc = lstat(gen_cc, &sb);
+ if (rc == 0) {
+ snprintf(gen_cc, sizeof(gen_cc), "FILE:/tmp/krb5cc_%d", uid);
+ } else {
+ snprintf(gen_cc, sizeof(gen_cc), "/run/user/%d/krb5cc", uid);
+
+ rc = lstat(gen_cc, &sb);
+ if (rc == 0 && S_ISDIR(sb.st_mode)) {
+ snprintf(gen_cc,
+ sizeof(gen_cc),
+ "DIR:/run/user/%d/krb5cc",
+ uid);
+ } else {
+#if defined(__linux__)
+ snprintf(gen_cc,
+ sizeof(gen_cc),
+ "KEYRING:persistent:%d",
+ uid);
+#endif
+ }
+ }
+
+ /*
+ * Make sure we do not have LD_PRELOAD or other security relevant
+ * environment variables set.
+ */
+ clearenv();
+
+ CUPS_SMB_DEBUG("Setting KRB5CCNAME to '%s'", gen_cc);
+ setenv("KRB5CCNAME", gen_cc, 1);
+
+smbspool:
+ snprintf(smbspool_cmd,
+ sizeof(smbspool_cmd),
+ "%s/smbspool",
+ get_dyn_BINDIR());
+
+ return execv(smbspool_cmd, argv);
+}
diff --git a/source3/include/proto.h b/source3/include/proto.h
index b8f4a67..4b86db0 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -1094,7 +1094,6 @@ uint32_t lp_get_spoolss_state( void );
struct smb_signing_state;
bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state);
void set_use_sendfile(int snum, bool val);
-void set_store_dos_attributes(int snum, bool val);
void lp_set_mangling_method(const char *new_method);
bool lp_posix_pathnames(void);
void lp_set_posix_pathnames(void);
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 9945375..d839be4 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -218,6 +218,9 @@ struct fsp_lease {
struct smb2_lease lease;
};
+/* VFS ABI stability hack */
+#define posix_flags posix_open
+
typedef struct files_struct {
struct files_struct *next, *prev;
uint64_t fnum;
@@ -255,7 +258,7 @@ typedef struct files_struct {
bool aio_write_behind;
bool initial_delete_on_close; /* Only set at NTCreateX if file was created. */
bool delete_on_close;
- bool posix_open;
+ uint8_t posix_flags;
bool is_sparse;
bool backup_intent; /* Handle was successfully opened with backup intent
and opener has privilege to do so. */
@@ -297,6 +300,13 @@ typedef struct files_struct {
struct tevent_req *deferred_close;
} files_struct;
+#define FSP_POSIX_FLAGS_OPEN 0x01
+#define FSP_POSIX_FLAGS_RENAME 0x02
+
+#define FSP_POSIX_FLAGS_ALL \
+ (FSP_POSIX_FLAGS_OPEN | \
+ FSP_POSIX_FLAGS_RENAME)
+
struct vuid_cache_entry {
struct auth_session_info *session_info;
uint64_t vuid; /* SMB2 compat */
diff --git a/source3/lib/errmap_unix.c b/source3/lib/errmap_unix.c
index 56d3f00..f572b99 100644
--- a/source3/lib/errmap_unix.c
+++ b/source3/lib/errmap_unix.c
@@ -115,6 +115,9 @@ static const struct {
#ifdef ETXTBSY
{ ETXTBSY, NT_STATUS_SHARING_VIOLATION },
#endif
+#ifdef EOVERFLOW
+ { EOVERFLOW, NT_STATUS_ALLOTTED_SPACE_EXCEEDED },
+#endif
};
/*********************************************************************
diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c
index 816ad13..c9f4060 100644
--- a/source3/libsmb/cli_smb2_fnum.c
+++ b/source3/libsmb/cli_smb2_fnum.c
@@ -1592,7 +1592,8 @@ NTSTATUS cli_smb2_setattrE(struct cli_state *cli,
Synchronous only.
***************************************************************/
-NTSTATUS cli_smb2_dskattr(struct cli_state *cli, uint64_t *bsize, uint64_t *total, uint64_t *avail)
+NTSTATUS cli_smb2_dskattr(struct cli_state *cli, const char *path,
+ uint64_t *bsize, uint64_t *total, uint64_t *avail)
{
NTSTATUS status;
uint16_t fnum = 0xffff;
@@ -1619,7 +1620,7 @@ NTSTATUS cli_smb2_dskattr(struct cli_state *cli, uint64_t *bsize, uint64_t *tota
/* First open the top level directory. */
status = cli_smb2_create_fnum(cli,
- "",
+ path,
0, /* create_flags */
FILE_READ_ATTRIBUTES, /* desired_access */
FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
diff --git a/source3/libsmb/cli_smb2_fnum.h b/source3/libsmb/cli_smb2_fnum.h
index c97bc76..ceb5629 100644
--- a/source3/libsmb/cli_smb2_fnum.h
+++ b/source3/libsmb/cli_smb2_fnum.h
@@ -117,6 +117,7 @@ NTSTATUS cli_smb2_setattrE(struct cli_state *cli,
time_t access_time,
time_t write_time);
NTSTATUS cli_smb2_dskattr(struct cli_state *cli,
+ const char *path,
uint64_t *bsize,
uint64_t *total,
uint64_t *avail);
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index 9e1975b..0e790cd 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -587,25 +587,25 @@ NTSTATUS cli_posix_hardlink(struct cli_state *cli,
}
/****************************************************************************
- Do a POSIX getfacl (UNIX extensions).
+ Do a POSIX getacl - pathname based ACL get (UNIX extensions).
****************************************************************************/
-struct getfacl_state {
+struct getacl_state {
uint32_t num_data;
uint8_t *data;
};
-static void cli_posix_getfacl_done(struct tevent_req *subreq);
+static void cli_posix_getacl_done(struct tevent_req *subreq);
-struct tevent_req *cli_posix_getfacl_send(TALLOC_CTX *mem_ctx,
+struct tevent_req *cli_posix_getacl_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct cli_state *cli,
const char *fname)
{
struct tevent_req *req = NULL, *subreq = NULL;
- struct getfacl_state *state = NULL;
+ struct getacl_state *state = NULL;
- req = tevent_req_create(mem_ctx, &state, struct getfacl_state);
+ req = tevent_req_create(mem_ctx, &state, struct getacl_state);
if (req == NULL) {
return NULL;
}
@@ -614,16 +614,16 @@ struct tevent_req *cli_posix_getfacl_send(TALLOC_CTX *mem_ctx,
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
- tevent_req_set_callback(subreq, cli_posix_getfacl_done, req);
+ tevent_req_set_callback(subreq, cli_posix_getacl_done, req);
return req;
}
-static void cli_posix_getfacl_done(struct tevent_req *subreq)
+static void cli_posix_getacl_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req);
- struct getfacl_state *state = tevent_req_data(
- req, struct getfacl_state);
+ struct getacl_state *state = tevent_req_data(
+ req, struct getacl_state);
NTSTATUS status;
status = cli_qpathinfo_recv(subreq, state, &state->data,
@@ -635,12 +635,12 @@ static void cli_posix_getfacl_done(struct tevent_req *subreq)
tevent_req_done(req);
}
-NTSTATUS cli_posix_getfacl_recv(struct tevent_req *req,
+NTSTATUS cli_posix_getacl_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
size_t *prb_size,
char **retbuf)
{
- struct getfacl_state *state = tevent_req_data(req, struct getfacl_state);
+ struct getacl_state *state = tevent_req_data(req, struct getacl_state);
NTSTATUS status;
if (tevent_req_is_nterror(req, &status)) {
@@ -651,7 +651,7 @@ NTSTATUS cli_posix_getfacl_recv(struct tevent_req *req,
return NT_STATUS_OK;
}
-NTSTATUS cli_posix_getfacl(struct cli_state *cli,
+NTSTATUS cli_posix_getacl(struct cli_state *cli,
const char *fname,
TALLOC_CTX *mem_ctx,
size_t *prb_size,
@@ -676,7 +676,7 @@ NTSTATUS cli_posix_getfacl(struct cli_state *cli,
goto fail;
}
- req = cli_posix_getfacl_send(frame,
+ req = cli_posix_getacl_send(frame,
ev,
cli,
fname);
@@ -689,7 +689,107 @@ NTSTATUS cli_posix_getfacl(struct cli_state *cli,
goto fail;
}
- status = cli_posix_getfacl_recv(req, mem_ctx, prb_size, retbuf);
+ status = cli_posix_getacl_recv(req, mem_ctx, prb_size, retbuf);
+
+ fail:
+ TALLOC_FREE(frame);
+ return status;
+}
+
+/****************************************************************************
+ Do a POSIX setacl - pathname based ACL set (UNIX extensions).
+****************************************************************************/
+
+struct setacl_state {
+ uint8_t *data;
+};
+
+static void cli_posix_setacl_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_posix_setacl_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli,
+ const char *fname,
+ const void *data,
+ size_t num_data)
+{
+ struct tevent_req *req = NULL, *subreq = NULL;
+ struct setacl_state *state = NULL;
+
+ req = tevent_req_create(mem_ctx, &state, struct setacl_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->data = talloc_memdup(state, data, num_data);
+ if (tevent_req_nomem(state->data, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = cli_setpathinfo_send(state,
+ ev,
+ cli,
+ SMB_SET_POSIX_ACL,
+ fname,
+ state->data,
+ num_data);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_posix_setacl_done, req);
+ return req;
+}
+
+static void cli_posix_setacl_done(struct tevent_req *subreq)
+{
+ NTSTATUS status = cli_setpathinfo_recv(subreq);
+ tevent_req_simple_finish_ntstatus(subreq, status);
+}
+
+NTSTATUS cli_posix_setacl_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
+}
+
+NTSTATUS cli_posix_setacl(struct cli_state *cli,
+ const char *fname,
+ const void *acl_buf,
+ size_t acl_buf_size)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct tevent_context *ev = NULL;
+ struct tevent_req *req = NULL;
+ NTSTATUS status = NT_STATUS_OK;
+
+ if (smbXcli_conn_has_async_calls(cli->conn)) {
+ /*
+ * Can't use sync call while an async call is in flight
+ */
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto fail;
+ }
+
+ ev = samba_tevent_context_init(frame);
+ if (ev == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ req = cli_posix_setacl_send(frame,
+ ev,
+ cli,
+ fname,
+ acl_buf,
+ acl_buf_size);
+ if (req == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+ goto fail;
+ }
+
+ status = cli_posix_setacl_recv(req);
fail:
TALLOC_FREE(frame);
@@ -4199,7 +4299,8 @@ NTSTATUS cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
return status;
}
-NTSTATUS cli_disk_size(struct cli_state *cli, uint64_t *bsize, uint64_t *total, uint64_t *avail)
+NTSTATUS cli_disk_size(struct cli_state *cli, const char *path, uint64_t *bsize,
+ uint64_t *total, uint64_t *avail)
{
uint64_t sectors_per_block;
uint64_t bytes_per_sector;
@@ -4207,7 +4308,7 @@ NTSTATUS cli_disk_size(struct cli_state *cli, uint64_t *bsize, uint64_t *total,
NTSTATUS status;
if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
- return cli_smb2_dskattr(cli, bsize, total, avail);
+ return cli_smb2_dskattr(cli, path, bsize, total, avail);
}
/*
diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c
index 2abd37e..06c0211 100644
--- a/source3/libsmb/libsmb_server.c
+++ b/source3/libsmb/libsmb_server.c
@@ -620,7 +620,7 @@ SMBC_server_internal(TALLOC_CTX *ctx,
}
ZERO_STRUCTP(srv);
- srv->cli = c;
+ DLIST_ADD(srv->cli, c);
srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
srv->no_pathinfo = False;
srv->no_pathinfo2 = False;
@@ -816,7 +816,7 @@ SMBC_attr_server(TALLOC_CTX *ctx,
}
ZERO_STRUCTP(ipc_srv);
- ipc_srv->cli = ipc_cli;
+ DLIST_ADD(ipc_srv->cli, ipc_cli);
nt_status = cli_rpc_pipe_open_noauth(
ipc_srv->cli, &ndr_table_lsarpc, &pipe_hnd);
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index 5ebcf5f..dc9aa17 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -252,19 +252,30 @@ NTSTATUS cli_posix_hardlink(struct cli_state *cli,
const char *newname);
uint32_t unix_perms_to_wire(mode_t perms);
mode_t wire_perms_to_unix(uint32_t perms);
-struct tevent_req *cli_posix_getfacl_send(TALLOC_CTX *mem_ctx,
+struct tevent_req *cli_posix_getacl_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct cli_state *cli,
const char *fname);
-NTSTATUS cli_posix_getfacl_recv(struct tevent_req *req,
+NTSTATUS cli_posix_getacl_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
size_t *prb_size,
char **retbuf);
-NTSTATUS cli_posix_getfacl(struct cli_state *cli,
+NTSTATUS cli_posix_getacl(struct cli_state *cli,
const char *fname,
TALLOC_CTX *mem_ctx,
size_t *prb_size,
char **retbuf);
+struct tevent_req *cli_posix_setacl_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli,
+ const char *fname,
+ const void *acl_buf,
+ size_t acl_buf_size);
+NTSTATUS cli_posix_setacl_recv(struct tevent_req *req);
+NTSTATUS cli_posix_setacl(struct cli_state *cli,
+ const char *fname,
+ const void *acl_buf,
+ size_t acl_buf_size);
struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct cli_state *cli,
@@ -513,7 +524,8 @@ struct tevent_req *cli_dskattr_send(TALLOC_CTX *mem_ctx,
NTSTATUS cli_dskattr_recv(struct tevent_req *req, int *bsize, int *total,
int *avail);
NTSTATUS cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail);
-NTSTATUS cli_disk_size(struct cli_state *cli, uint64_t *bsize, uint64_t *total, uint64_t *avail);
+NTSTATUS cli_disk_size(struct cli_state *cli, const char *path, uint64_t *bsize,
+ uint64_t *total, uint64_t *avail);
struct tevent_req *cli_ctemp_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct cli_state *cli,
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index 7b8bc84..5a97460 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -847,7 +847,8 @@ bool set_share_mode(struct share_mode_lock *lck, struct files_struct *fsp,
e->id = fsp->file_id;
e->share_file_id = fsp->fh->gen_id;
e->uid = (uint32_t)uid;
- e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0;
+ e->flags = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
+ SHARE_MODE_FLAG_POSIX_OPEN : 0;
e->name_hash = fsp->name_hash;
return true;
diff --git a/source3/modules/vfs_acl_common.c b/source3/modules/vfs_acl_common.c
index 625e7cb..f73e80c 100644
--- a/source3/modules/vfs_acl_common.c
+++ b/source3/modules/vfs_acl_common.c
@@ -1089,7 +1089,7 @@ static int chmod_acl_module_common(struct vfs_handle_struct *handle,
static int fchmod_acl_module_common(struct vfs_handle_struct *handle,
struct files_struct *fsp, mode_t mode)
{
- if (fsp->posix_open) {
+ if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
/* Only allow this on POSIX opens. */
return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
}
@@ -1109,7 +1109,7 @@ static int chmod_acl_acl_module_common(struct vfs_handle_struct *handle,
static int fchmod_acl_acl_module_common(struct vfs_handle_struct *handle,
struct files_struct *fsp, mode_t mode)
{
- if (fsp->posix_open) {
+ if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
/* Only allow this on POSIX opens. */
return SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, mode);
}
diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index ecce85d..d87afa6 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -104,11 +104,12 @@ static int vfs_fruit_debug_level = DBGC_VFS;
* REVIEW:
* This is hokey, but what else can we do?
*/
+#define NETATALK_META_XATTR "org.netatalk.Metadata"
#if defined(HAVE_ATTROPEN) || defined(FREEBSD)
-#define AFPINFO_EA_NETATALK "org.netatalk.Metadata"
+#define AFPINFO_EA_NETATALK NETATALK_META_XATTR
#define AFPRESOURCE_EA_NETATALK "org.netatalk.ResourceFork"
#else
-#define AFPINFO_EA_NETATALK "user.org.netatalk.Metadata"
+#define AFPINFO_EA_NETATALK "user." NETATALK_META_XATTR
#define AFPRESOURCE_EA_NETATALK "user.org.netatalk.ResourceFork"
#endif
@@ -124,7 +125,8 @@ struct fruit_config_data {
enum fruit_meta meta;
enum fruit_locking locking;
enum fruit_encoding encoding;
- bool use_aapl;
+ bool use_aapl; /* config from smb.conf */
+ bool nego_aapl; /* client negotiated AAPL */
bool use_copyfile;
bool readdir_attr_enabled;
bool unix_info_enabled;
@@ -1522,6 +1524,37 @@ static bool add_fruit_stream(TALLOC_CTX *mem_ctx, unsigned int *num_streams,
return true;
}
+static bool del_fruit_stream(TALLOC_CTX *mem_ctx, unsigned int *num_streams,
+ struct stream_struct **streams,
+ const char *name)
+{
+ struct stream_struct *tmp = *streams;
+ int i;
+
+ if (*num_streams == 0) {
+ return true;
+ }
+
+ for (i = 0; i < *num_streams; i++) {
+ if (strequal_m(tmp[i].name, name)) {
+ break;
+ }
+ }
+
+ if (i == *num_streams) {
+ return true;
+ }
+
+ TALLOC_FREE(tmp[i].name);
+ if (*num_streams - 1 > i) {
+ memmove(&tmp[i], &tmp[i+1],
+ (*num_streams - i - 1) * sizeof(struct stream_struct));
+ }
+
+ *num_streams -= 1;
+ return true;
+}
+
static bool empty_finderinfo(const struct adouble *ad)
{
@@ -1894,6 +1927,9 @@ static NTSTATUS check_aapl(vfs_handle_struct *handle,
out_context_blobs,
SMB2_CREATE_TAG_AAPL,
blob);
+ if (NT_STATUS_IS_OK(status)) {
+ config->nego_aapl = true;
+ }
return status;
}
@@ -2419,7 +2455,7 @@ static int fruit_unlink(vfs_handle_struct *handle,
}
/* FIXME: direct unlink(), missing smb_fname */
- DEBUG(1,("fruit_unlink: %s\n", adp));
+ DBG_DEBUG("fruit_unlink: %s\n", adp);
rc = unlink(adp);
if ((rc == -1) && (errno == ENOENT)) {
rc = 0;
@@ -2442,27 +2478,8 @@ static int fruit_unlink(vfs_handle_struct *handle,
}
if (is_afpresource_stream(smb_fname)) {
- if (config->rsrc == FRUIT_RSRC_ADFILE) {
- char *adp = NULL;
-
- rc = adouble_path(talloc_tos(),
- smb_fname->base_name, &adp);
- if (rc != 0) {
- return -1;
- }
- /* FIXME: direct unlink(), missing smb_fname */
- rc = unlink(adp);
- if ((rc == -1) && (errno == ENOENT)) {
- rc = 0;
- }
- TALLOC_FREE(adp);
- } else {
- rc = SMB_VFS_REMOVEXATTR(handle->conn,
- smb_fname->base_name,
- AFPRESOURCE_EA_NETATALK);
- }
-
- return rc;
+ /* OS X ignores deletes on the AFP_Resource stream */
+ return 0;
}
return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
@@ -2664,13 +2681,19 @@ static ssize_t fruit_pread(vfs_handle_struct *handle,
char afpinfo_buf[AFP_INFO_SIZE];
size_t to_return;
- if ((offset < 0) || (offset >= AFP_INFO_SIZE)) {
+ /*
+ * OS X has a off-by-1 error in the offset calculation, so we're
+ * bug compatible here. It won't hurt, as any relevant real
+ * world read requests from the AFP_AfpInfo stream will be
+ * offset=0 n=60. offset is ignored anyway, see below.
+ */
+ if ((offset < 0) || (offset >= AFP_INFO_SIZE + 1)) {
len = 0;
rc = 0;
goto exit;
}
- to_return = AFP_INFO_SIZE - offset;
+ to_return = MIN(n, AFP_INFO_SIZE);
ai = afpinfo_new(talloc_tos());
if (ai == NULL) {
@@ -2693,7 +2716,10 @@ static ssize_t fruit_pread(vfs_handle_struct *handle,
goto exit;
}
- memcpy(data, afpinfo_buf + offset, to_return);
+ /*
+ * OS X ignores offset when reading from AFP_AfpInfo stream!
+ */
+ memcpy(data, afpinfo_buf, to_return);
len = to_return;
} else {
len = SMB_VFS_NEXT_PREAD(
@@ -2784,6 +2810,23 @@ static ssize_t fruit_pwrite(vfs_handle_struct *handle,
}
memcpy(ad_entry(ad, ADEID_FINDERI),
&ai->afpi_FinderInfo[0], ADEDLEN_FINDERI);
+ if (empty_finderinfo(ad)) {
+ /* Discard metadata */
+ if (config->meta == FRUIT_META_STREAM) {
+ rc = SMB_VFS_FTRUNCATE(fsp, 0);
+ } else {
+ rc = SMB_VFS_REMOVEXATTR(handle->conn,
+ fsp->fsp_name->base_name,
+ AFPINFO_EA_NETATALK);
+ }
+ if (rc != 0 && errno != ENOENT && errno != ENOATTR) {
+ DBG_WARNING("Can't delete metadata for %s: %s\n",
+ fsp->fsp_name->base_name, strerror(errno));
+ goto exit;
+ }
+ rc = 0;
+ goto exit;
+ }
rc = ad_write(ad, name);
} else {
len = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n,
@@ -2842,6 +2885,17 @@ static int fruit_stat_meta(vfs_handle_struct *handle,
struct smb_filename *smb_fname,
bool follow_links)
{
+ struct adouble *ad = NULL;
+
+ ad = ad_get(talloc_tos(), handle, smb_fname->base_name, ADOUBLE_META);
+ if (ad == NULL) {
+ DBG_INFO("fruit_stat_meta %s: %s\n",
+ smb_fname_str_dbg(smb_fname), strerror(errno));
+ errno = ENOENT;
+ return -1;
+ }
+ TALLOC_FREE(ad);
+
/* Populate the stat struct with info from the base file. */
if (fruit_stat_base(handle, smb_fname, follow_links) == -1) {
return -1;
@@ -3095,6 +3149,7 @@ static NTSTATUS fruit_streaminfo(vfs_handle_struct *handle,
struct fruit_config_data *config = NULL;
struct smb_filename *smb_fname = NULL;
struct adouble *ad = NULL;
+ NTSTATUS status;
SMB_VFS_HANDLE_GET_DATA(handle, config, struct fruit_config_data,
return NT_STATUS_UNSUCCESSFUL);
@@ -3143,8 +3198,23 @@ static NTSTATUS fruit_streaminfo(vfs_handle_struct *handle,
TALLOC_FREE(smb_fname);
- return SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx,
- pnum_streams, pstreams);
+ status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx,
+ pnum_streams, pstreams);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (config->meta == FRUIT_META_NETATALK) {
+ /* Remove the Netatalk xattr from the list */
+ if (!del_fruit_stream(mem_ctx, pnum_streams, pstreams,
+ ":" NETATALK_META_XATTR ":$DATA")) {
+ TALLOC_FREE(ad);
+ TALLOC_FREE(smb_fname);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ return NT_STATUS_OK;
}
static int fruit_ntimes(vfs_handle_struct *handle,
@@ -3208,19 +3278,23 @@ static int fruit_ftruncate_meta(struct vfs_handle_struct *handle,
off_t offset,
struct adouble *ad)
{
- /*
- * As this request hasn't been seen in the wild,
- * the only sensible use I can imagine is the client
- * truncating the stream to 0 bytes size.
- * We simply remove the metadata on such a request.
- */
- if (offset != 0) {
+ struct fruit_config_data *config;
+
+ SMB_VFS_HANDLE_GET_DATA(handle, config,
+ struct fruit_config_data, return -1);
+
+ if (offset > 60) {
DBG_WARNING("ftruncate %s to %jd",
fsp_str_dbg(fsp), (intmax_t)offset);
+ /* OS X returns NT_STATUS_ALLOTTED_SPACE_EXCEEDED */
+ errno = EOVERFLOW;
return -1;
}
- return SMB_VFS_FREMOVEXATTR(fsp, AFPRESOURCE_EA_NETATALK);
+ DBG_WARNING("ignoring ftruncate %s to %jd",
+ fsp_str_dbg(fsp), (intmax_t)offset);
+ /* OS X returns success but does nothing */
+ return 0;
}
static int fruit_ftruncate_rsrc(struct vfs_handle_struct *handle,
@@ -3267,8 +3341,8 @@ static int fruit_ftruncate(struct vfs_handle_struct *handle,
struct adouble *ad =
(struct adouble *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
- DEBUG(10, ("streams_xattr_ftruncate called for file %s offset %.0f\n",
- fsp_str_dbg(fsp), (double)offset));
+ DBG_DEBUG("fruit_ftruncate called for file %s offset %.0f\n",
+ fsp_str_dbg(fsp), (double)offset);
if (ad == NULL) {
return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset);
@@ -3338,16 +3412,27 @@ static NTSTATUS fruit_create_file(vfs_handle_struct *handle,
if (!NT_STATUS_IS_OK(status)) {
return status;
}
+
fsp = *result;
- if (config->copyfile_enabled) {
- /*
- * Set a flag in the fsp. Gets used in copychunk to
- * check whether the special Apple copyfile semantics
- * for copychunk should be allowed in a copychunk
- * request with a count of 0.
- */
- fsp->aapl_copyfile_supported = true;
+ if (config->nego_aapl) {
+ if (config->copyfile_enabled) {
+ /*
+ * Set a flag in the fsp. Gets used in
+ * copychunk to check whether the special
+ * Apple copyfile semantics for copychunk
+ * should be allowed in a copychunk request
+ * with a count of 0.
+ */
+ fsp->aapl_copyfile_supported = true;
+ }
+
+ if (fsp->is_directory) {
+ /*
+ * Enable POSIX directory rename behaviour
+ */
+ fsp->posix_flags |= FSP_POSIX_FLAGS_RENAME;
+ }
}
/*
@@ -3538,7 +3623,7 @@ static NTSTATUS fruit_fset_nt_acl(vfs_handle_struct *handle,
mode_t ms_nfs_mode;
int result;
- DEBUG(1, ("fruit_fset_nt_acl: %s\n", fsp_str_dbg(fsp)));
+ DBG_DEBUG("fruit_fset_nt_acl: %s\n", fsp_str_dbg(fsp));
status = check_ms_nfs(handle, fsp, psd, &ms_nfs_mode, &do_chmod);
if (!NT_STATUS_IS_OK(status)) {
@@ -3554,10 +3639,8 @@ static NTSTATUS fruit_fset_nt_acl(vfs_handle_struct *handle,
if (do_chmod) {
if (fsp->fh->fd != -1) {
- DEBUG(1, ("fchmod: %s\n", fsp_str_dbg(fsp)));
result = SMB_VFS_FCHMOD(fsp, ms_nfs_mode);
} else {
- DEBUG(1, ("chmod: %s\n", fsp_str_dbg(fsp)));
result = SMB_VFS_CHMOD(fsp->conn,
fsp->fsp_name->base_name,
ms_nfs_mode);
diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index d1673a4..7ecdda5 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -434,10 +434,13 @@ static char *shadow_copy2_find_mount_point(TALLOC_CTX *mem_ctx,
* Convert from a name as handed in via the SMB layer
* and a timestamp into the local path of the snapshot
* of the provided file at the provided time.
+ * Also return the path in the snapshot corresponding
+ * to the file's share root.
*/
-static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
- struct vfs_handle_struct *handle,
- const char *name, time_t timestamp)
+static char *shadow_copy2_do_convert(TALLOC_CTX *mem_ctx,
+ struct vfs_handle_struct *handle,
+ const char *name, time_t timestamp,
+ size_t *snaproot_len)
{
struct smb_filename converted_fname;
char *result = NULL;
@@ -447,10 +450,11 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
size_t pathlen;
char *insert = NULL;
char *converted = NULL;
- size_t insertlen;
+ size_t insertlen, connectlen = 0;
int i, saved_errno;
size_t min_offset;
struct shadow_copy2_config *config;
+ size_t in_share_offset = 0;
SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
return NULL);
@@ -492,6 +496,13 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
DEBUG(10, ("Found %s\n", converted));
result = converted;
converted = NULL;
+ if (snaproot_len != NULL) {
+ *snaproot_len = strlen(snapshot_path);
+ if (config->rel_connectpath != NULL) {
+ *snaproot_len +=
+ strlen(config->rel_connectpath) + 1;
+ }
+ }
goto fail;
} else {
errno = ENOENT;
@@ -500,6 +511,7 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
/* never reached ... */
}
+ connectlen = strlen(handle->conn->connectpath);
if (name[0] == 0) {
path = talloc_strdup(mem_ctx, handle->conn->connectpath);
} else {
@@ -575,6 +587,10 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
goto fail;
}
+ if (offset >= connectlen) {
+ in_share_offset = offset;
+ }
+
memcpy(converted+offset, insert, insertlen);
offset += insertlen;
@@ -588,6 +604,9 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
ret, ret == 0 ? "ok" : strerror(errno)));
if (ret == 0) {
/* success */
+ if (snaproot_len != NULL) {
+ *snaproot_len = in_share_offset + insertlen;
+ }
break;
}
if (errno == ENOTDIR) {
@@ -624,6 +643,18 @@ fail:
return result;
}
+/**
+ * Convert from a name as handed in via the SMB layer
+ * and a timestamp into the local path of the snapshot
+ * of the provided file at the provided time.
+ */
+static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
+ struct vfs_handle_struct *handle,
+ const char *name, time_t timestamp)
+{
+ return shadow_copy2_do_convert(mem_ctx, handle, name, timestamp, NULL);
+}
+
/*
modify a sbuf return to ensure that inodes in the shadow directory
are different from those in the main directory
@@ -1103,8 +1134,6 @@ static char *shadow_copy2_realpath(vfs_handle_struct *handle,
char *stripped = NULL;
char *tmp = NULL;
char *result = NULL;
- char *inserted = NULL;
- char *inserted_to, *inserted_end;
int saved_errno;
if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
@@ -1121,29 +1150,9 @@ static char *shadow_copy2_realpath(vfs_handle_struct *handle,
}
result = SMB_VFS_NEXT_REALPATH(handle, tmp);
- if (result == NULL) {
- goto done;
- }
-
- /*
- * Take away what we've inserted. This removes the @GMT-thingy
- * completely, but will give a path under the share root.
- */
- inserted = shadow_copy2_insert_string(talloc_tos(), handle, timestamp);
- if (inserted == NULL) {
- goto done;
- }
- inserted_to = strstr_m(result, inserted);
- if (inserted_to == NULL) {
- DEBUG(2, ("SMB_VFS_NEXT_REALPATH removed %s\n", inserted));
- goto done;
- }
- inserted_end = inserted_to + talloc_get_size(inserted) - 1;
- memmove(inserted_to, inserted_end, strlen(inserted_end)+1);
done:
saved_errno = errno;
- TALLOC_FREE(inserted);
TALLOC_FREE(tmp);
TALLOC_FREE(stripped);
errno = saved_errno;
@@ -1777,6 +1786,51 @@ static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle,
return ret;
}
+static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle,
+ const char *fname)
+{
+ time_t timestamp;
+ char *stripped = NULL;
+ char *tmp = NULL;
+ char *result = NULL;
+ int saved_errno;
+ size_t rootpath_len = 0;
+
+ DBG_DEBUG("Calc connect path for [%s]\n", fname);
+
+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
+ ×tamp, &stripped)) {
+ goto done;
+ }
+ if (timestamp == 0) {
+ return SMB_VFS_NEXT_CONNECTPATH(handle, fname);
+ }
+
+ tmp = shadow_copy2_do_convert(talloc_tos(), handle, stripped, timestamp,
+ &rootpath_len);
+ if (tmp == NULL) {
+ goto done;
+ }
+
+ DBG_DEBUG("converted path is [%s] root path is [%.*s]\n", tmp,
+ (int)rootpath_len, tmp);
+
+ tmp[rootpath_len] = '\0';
+ result = SMB_VFS_NEXT_REALPATH(handle, tmp);
+ if (result == NULL) {
+ goto done;
+ }
+
+ DBG_DEBUG("connect path is [%s]\n", result);
+
+done:
+ saved_errno = errno;
+ TALLOC_FREE(tmp);
+ TALLOC_FREE(stripped);
+ errno = saved_errno;
+ return result;
+}
+
static uint64_t shadow_copy2_disk_free(vfs_handle_struct *handle,
const char *path, uint64_t *bsize,
uint64_t *dfree, uint64_t *dsize)
@@ -2078,6 +2132,7 @@ static struct vfs_fn_pointers vfs_shadow_copy2_fns = {
.chmod_acl_fn = shadow_copy2_chmod_acl,
.chflags_fn = shadow_copy2_chflags,
.get_real_filename_fn = shadow_copy2_get_real_filename,
+ .connectpath_fn = shadow_copy2_connectpath,
};
NTSTATUS vfs_shadow_copy2_init(void);
diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c
index 92bd1c9..b54809f 100644
--- a/source3/modules/vfs_streams_xattr.c
+++ b/source3/modules/vfs_streams_xattr.c
@@ -106,12 +106,18 @@ static NTSTATUS streams_xattr_get_name(vfs_handle_struct *handle,
const char *stream_name,
char **xattr_name)
{
+ char *sname;
char *stype;
struct streams_xattr_config *config;
SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
return NT_STATUS_UNSUCCESSFUL);
+ sname = talloc_strdup(ctx, stream_name + 1);
+ if (sname == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
/*
* With vfs_fruit option "fruit:encoding = native" we're
* already converting stream names that contain illegal NTFS
@@ -126,41 +132,34 @@ static NTSTATUS streams_xattr_get_name(vfs_handle_struct *handle,
* In check_path_syntax() we've already ensured the streamname
* we got from the client is valid.
*/
- stype = strrchr_m(stream_name + 1, ':');
+ stype = strrchr_m(sname, ':');
if (stype) {
+ /*
+ * We only support one stream type: "$DATA"
+ */
if (strcasecmp_m(stype, ":$DATA") != 0) {
+ talloc_free(sname);
return NT_STATUS_INVALID_PARAMETER;
}
+
+ /* Split name and type */
+ stype[0] = '\0';
}
- *xattr_name = talloc_asprintf(ctx, "%s%s",
+ *xattr_name = talloc_asprintf(ctx, "%s%s%s",
config->prefix,
- stream_name + 1);
+ sname,
+ config->store_stream_type ? ":$DATA" : "");
if (*xattr_name == NULL) {
+ talloc_free(sname);
return NT_STATUS_NO_MEMORY;
}
- if (stype != NULL) {
- /* Normalize the stream type to upercase. */
- if (!strupper_m(strrchr_m(*xattr_name, ':') + 1)) {
- return NT_STATUS_INVALID_PARAMETER;
- }
- } else if (config->store_stream_type) {
- /*
- * Append an explicit stream type if one wasn't
- * specified.
- */
- *xattr_name = talloc_asprintf(ctx, "%s%s",
- *xattr_name, ":$DATA");
- if (*xattr_name == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- }
-
DEBUG(10, ("xattr_name: %s, stream_name: %s\n", *xattr_name,
stream_name));
+ talloc_free(sname);
return NT_STATUS_OK;
}
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 2f53a74..c576b22 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -266,44 +266,6 @@ static void set_allowed_client_auth(void);
static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue);
static void free_param_opts(struct parmlist_entry **popts);
-/* this is used to prevent lots of mallocs of size 1 */
-static const char null_string[] = "";
-
-/**
- Free a string value.
-**/
-
-static void string_free(char **s)
-{
- if (!s || !(*s))
- return;
- if (*s == null_string)
- *s = NULL;
- TALLOC_FREE(*s);
-}
-
-/**
- Set a string value, deallocating any existing space, and allocing the space
- for the string
-**/
-
-static bool string_set(TALLOC_CTX *mem_ctx, char **dest,const char *src)
-{
- string_free(dest);
-
- if (!src) {
- src = "";
- }
-
- (*dest) = talloc_strdup(mem_ctx, src);
- if ((*dest) == NULL) {
- DEBUG(0,("Out of memory in string_init\n"));
- return false;
- }
-
- return true;
-}
-
/**
* Function to return the default value for the maximum number of open
* file descriptors permitted. This function tries to consult the
@@ -367,7 +329,7 @@ static void free_one_parameter_common(void *parm_ptr,
if ((parm.type == P_STRING) ||
(parm.type == P_USTRING))
{
- string_free((char**)parm_ptr);
+ lpcfg_string_free((char**)parm_ptr);
} else if (parm.type == P_LIST || parm.type == P_CMDLIST) {
TALLOC_FREE(*((char***)parm_ptr));
}
@@ -441,8 +403,25 @@ static void free_parameters_by_snum(int snum)
*/
static void free_global_parameters(void)
{
+ uint32_t i;
+ struct parm_struct *parm;
+
free_param_opts(&Globals.param_opt);
free_parameters_by_snum(GLOBAL_SECTION_SNUM);
+
+ /* Reset references in the defaults because the context is going to be freed */
+ for (i=0; parm_table[i].label; i++) {
+ parm = &parm_table[i];
+ if ((parm->type == P_STRING) ||
+ (parm->type == P_USTRING)) {
+ if ((parm->def.svalue != NULL) &&
+ (*(parm->def.svalue) != '\0')) {
+ if (talloc_parent(parm->def.svalue) == Globals.ctx) {
+ parm->def.svalue = NULL;
+ }
+ }
+ }
+ }
TALLOC_FREE(Globals.ctx);
}
@@ -524,10 +503,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
if (!done_init) {
/* The logfile can be set before this is invoked. Free it if so. */
- if (Globals.logfile != NULL) {
- string_free(&Globals.logfile);
- Globals.logfile = NULL;
- }
+ lpcfg_string_free(&Globals.logfile);
done_init = true;
} else {
free_global_parameters();
@@ -550,13 +526,16 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
if ((parm_table[i].type == P_STRING ||
parm_table[i].type == P_USTRING))
{
- string_set(Globals.ctx, (char **)lp_parm_ptr(NULL, &parm_table[i]), "");
+ lpcfg_string_set(
+ Globals.ctx,
+ (char **)lp_parm_ptr(NULL, &parm_table[i]),
+ "");
}
}
- string_set(Globals.ctx, &sDefault.fstype, FSTYPE_STRING);
- string_set(Globals.ctx, &sDefault.printjob_username, "%U");
+ lpcfg_string_set(Globals.ctx, &sDefault.fstype, FSTYPE_STRING);
+ lpcfg_string_set(Globals.ctx, &sDefault.printjob_username, "%U");
init_printer_values(lp_ctx, Globals.ctx, &sDefault);
@@ -565,61 +544,75 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
DEBUG(3, ("Initialising global parameters\n"));
/* Must manually force to upper case here, as this does not go via the handler */
- string_set(Globals.ctx, &Globals.netbios_name, myhostname_upper());
+ lpcfg_string_set(Globals.ctx, &Globals.netbios_name,
+ myhostname_upper());
- string_set(Globals.ctx, &Globals.smb_passwd_file, get_dyn_SMB_PASSWD_FILE());
- string_set(Globals.ctx, &Globals.private_dir, get_dyn_PRIVATE_DIR());
+ lpcfg_string_set(Globals.ctx, &Globals.smb_passwd_file,
+ get_dyn_SMB_PASSWD_FILE());
+ lpcfg_string_set(Globals.ctx, &Globals.private_dir,
+ get_dyn_PRIVATE_DIR());
/* use the new 'hash2' method by default, with a prefix of 1 */
- string_set(Globals.ctx, &Globals.mangling_method, "hash2");
+ lpcfg_string_set(Globals.ctx, &Globals.mangling_method, "hash2");
Globals.mangle_prefix = 1;
- string_set(Globals.ctx, &Globals.guest_account, GUEST_ACCOUNT);
+ lpcfg_string_set(Globals.ctx, &Globals.guest_account, GUEST_ACCOUNT);
/* using UTF8 by default allows us to support all chars */
- string_set(Globals.ctx, &Globals.unix_charset, DEFAULT_UNIX_CHARSET);
+ lpcfg_string_set(Globals.ctx, &Globals.unix_charset,
+ DEFAULT_UNIX_CHARSET);
/* Use codepage 850 as a default for the dos character set */
- string_set(Globals.ctx, &Globals.dos_charset, DEFAULT_DOS_CHARSET);
+ lpcfg_string_set(Globals.ctx, &Globals.dos_charset,
+ DEFAULT_DOS_CHARSET);
/*
* Allow the default PASSWD_CHAT to be overridden in local.h.
*/
- string_set(Globals.ctx, &Globals.passwd_chat, DEFAULT_PASSWD_CHAT);
-
- string_set(Globals.ctx, &Globals.workgroup, DEFAULT_WORKGROUP);
-
- string_set(Globals.ctx, &Globals.passwd_program, "");
- string_set(Globals.ctx, &Globals.lock_directory, get_dyn_LOCKDIR());
- string_set(Globals.ctx, &Globals.state_directory, get_dyn_STATEDIR());
- string_set(Globals.ctx, &Globals.cache_directory, get_dyn_CACHEDIR());
- string_set(Globals.ctx, &Globals.pid_directory, get_dyn_PIDDIR());
- string_set(Globals.ctx, &Globals.nbt_client_socket_address, "0.0.0.0");
+ lpcfg_string_set(Globals.ctx, &Globals.passwd_chat,
+ DEFAULT_PASSWD_CHAT);
+
+ lpcfg_string_set(Globals.ctx, &Globals.workgroup, DEFAULT_WORKGROUP);
+
+ lpcfg_string_set(Globals.ctx, &Globals.passwd_program, "");
+ lpcfg_string_set(Globals.ctx, &Globals.lock_directory,
+ get_dyn_LOCKDIR());
+ lpcfg_string_set(Globals.ctx, &Globals.state_directory,
+ get_dyn_STATEDIR());
+ lpcfg_string_set(Globals.ctx, &Globals.cache_directory,
+ get_dyn_CACHEDIR());
+ lpcfg_string_set(Globals.ctx, &Globals.pid_directory,
+ get_dyn_PIDDIR());
+ lpcfg_string_set(Globals.ctx, &Globals.nbt_client_socket_address,
+ "0.0.0.0");
/*
* By default support explicit binding to broadcast
* addresses.
- */
+ */
Globals.nmbd_bind_explicit_broadcast = true;
s = talloc_asprintf(talloc_tos(), "Samba %s", samba_version_string());
if (s == NULL) {
smb_panic("init_globals: ENOMEM");
}
- string_set(Globals.ctx, &Globals.server_string, s);
+ lpcfg_string_set(Globals.ctx, &Globals.server_string, s);
TALLOC_FREE(s);
#ifdef DEVELOPER
- string_set(Globals.ctx, &Globals.panic_action, "/bin/sleep 999999999");
+ lpcfg_string_set(Globals.ctx, &Globals.panic_action,
+ "/bin/sleep 999999999");
#endif
- string_set(Globals.ctx, &Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
+ lpcfg_string_set(Globals.ctx, &Globals.socket_options,
+ DEFAULT_SOCKET_OPTIONS);
- string_set(Globals.ctx, &Globals.logon_drive, "");
+ lpcfg_string_set(Globals.ctx, &Globals.logon_drive, "");
/* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
- string_set(Globals.ctx, &Globals.logon_home, "\\\\%N\\%U");
- string_set(Globals.ctx, &Globals.logon_path, "\\\\%N\\%U\\profile");
+ lpcfg_string_set(Globals.ctx, &Globals.logon_home, "\\\\%N\\%U");
+ lpcfg_string_set(Globals.ctx, &Globals.logon_path,
+ "\\\\%N\\%U\\profile");
Globals.name_resolve_order = str_list_make_v3_const(NULL, "lmhosts wins host bcast", NULL);
- string_set(Globals.ctx, &Globals.password_server, "*");
+ lpcfg_string_set(Globals.ctx, &Globals.password_server, "*");
Globals.algorithmic_rid_base = BASE_RID;
@@ -660,7 +653,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
Globals.syslog = 1;
Globals.syslog_only = false;
Globals.timestamp_logs = true;
- string_set(Globals.ctx, &Globals.log_level, "0");
+ lpcfg_string_set(Globals.ctx, &Globals.log_level, "0");
Globals.debug_prefix_timestamp = false;
Globals.debug_hires_timestamp = true;
Globals.debug_pid = false;
@@ -676,9 +669,10 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
#if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
Globals.nis_homedir = false;
#ifdef WITH_NISPLUS_HOME
- string_set(Globals.ctx, &Globals.homedir_map, "auto_home.org_dir");
+ lpcfg_string_set(Globals.ctx, &Globals.homedir_map,
+ "auto_home.org_dir");
#else
- string_set(Globals.ctx, &Globals.homedir_map, "auto.home");
+ lpcfg_string_set(Globals.ctx, &Globals.homedir_map, "auto.home");
#endif
#endif
Globals.time_server = false;
@@ -723,14 +717,14 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
Globals.change_notify = true,
Globals.kernel_change_notify = true,
- string_set(Globals.ctx, &Globals.passdb_backend, "tdbsam");
- string_set(Globals.ctx, &Globals.ldap_suffix, "");
- string_set(Globals.ctx, &Globals.szLdapMachineSuffix, "");
- string_set(Globals.ctx, &Globals.szLdapUserSuffix, "");
- string_set(Globals.ctx, &Globals.szLdapGroupSuffix, "");
- string_set(Globals.ctx, &Globals.szLdapIdmapSuffix, "");
+ lpcfg_string_set(Globals.ctx, &Globals.passdb_backend, "tdbsam");
+ lpcfg_string_set(Globals.ctx, &Globals.ldap_suffix, "");
+ lpcfg_string_set(Globals.ctx, &Globals.szLdapMachineSuffix, "");
+ lpcfg_string_set(Globals.ctx, &Globals.szLdapUserSuffix, "");
+ lpcfg_string_set(Globals.ctx, &Globals.szLdapGroupSuffix, "");
+ lpcfg_string_set(Globals.ctx, &Globals.szLdapIdmapSuffix, "");
- string_set(Globals.ctx, &Globals.ldap_admin_dn, "");
+ lpcfg_string_set(Globals.ctx, &Globals.ldap_admin_dn, "");
Globals.ldap_ssl = LDAP_SSL_START_TLS;
Globals.ldap_ssl_ads = false;
Globals.ldap_deref = -1;
@@ -780,17 +774,17 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
Globals.wins_dns_proxy = true;
Globals.allow_trusted_domains = true;
- string_set(Globals.ctx, &Globals.szIdmapBackend, "tdb");
+ lpcfg_string_set(Globals.ctx, &Globals.szIdmapBackend, "tdb");
- string_set(Globals.ctx, &Globals.template_shell, "/bin/false");
- string_set(Globals.ctx, &Globals.template_homedir, "/home/%D/%U");
- string_set(Globals.ctx, &Globals.winbind_separator, "\\");
- string_set(Globals.ctx, &Globals.winbindd_socket_directory, dyn_WINBINDD_SOCKET_DIR);
+ lpcfg_string_set(Globals.ctx, &Globals.template_shell, "/bin/false");
+ lpcfg_string_set(Globals.ctx, &Globals.template_homedir, "/home/%D/%U");
+ lpcfg_string_set(Globals.ctx, &Globals.winbind_separator, "\\");
+ lpcfg_string_set(Globals.ctx, &Globals.winbindd_socket_directory, dyn_WINBINDD_SOCKET_DIR);
- string_set(Globals.ctx, &Globals.cups_server, "");
- string_set(Globals.ctx, &Globals.iprint_server, "");
+ lpcfg_string_set(Globals.ctx, &Globals.cups_server, "");
+ lpcfg_string_set(Globals.ctx, &Globals.iprint_server, "");
- string_set(Globals.ctx, &Globals._ctdbd_socket, "");
+ lpcfg_string_set(Globals.ctx, &Globals._ctdbd_socket, "");
Globals.cluster_addresses = NULL;
Globals.clustering = false;
@@ -836,9 +830,9 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
if (s == NULL) {
smb_panic("init_globals: ENOMEM");
}
- string_set(Globals.ctx, &Globals.usershare_path, s);
+ lpcfg_string_set(Globals.ctx, &Globals.usershare_path, s);
TALLOC_FREE(s);
- string_set(Globals.ctx, &Globals.usershare_template_share, "");
+ lpcfg_string_set(Globals.ctx, &Globals.usershare_template_share, "");
Globals.usershare_max_shares = 0;
/* By default disallow sharing of directories not owned by the sharer. */
Globals.usershare_owner_only = true;
@@ -861,7 +855,8 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
Globals.smb2_leases = false;
- string_set(Globals.ctx, &Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
+ lpcfg_string_set(Globals.ctx, &Globals.ncalrpc_dir,
+ get_dyn_NCALRPCDIR());
Globals.server_services = str_list_make_v3_const(NULL, "s3fs rpc nbt wrepl ldap cldap kdc drepl winbindd ntp_signd kcc dnsupdate dns", NULL);
@@ -869,20 +864,23 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
Globals.tls_enabled = true;
- string_set(Globals.ctx, &Globals._tls_keyfile, "tls/key.pem");
- string_set(Globals.ctx, &Globals._tls_certfile, "tls/cert.pem");
- string_set(Globals.ctx, &Globals._tls_cafile, "tls/ca.pem");
- string_set(Globals.ctx, &Globals.tls_priority, "NORMAL:-VERS-SSL3.0");
+ lpcfg_string_set(Globals.ctx, &Globals._tls_keyfile, "tls/key.pem");
+ lpcfg_string_set(Globals.ctx, &Globals._tls_certfile, "tls/cert.pem");
+ lpcfg_string_set(Globals.ctx, &Globals._tls_cafile, "tls/ca.pem");
+ lpcfg_string_set(Globals.ctx, &Globals.tls_priority, "NORMAL:-VERS-SSL3.0");
- string_set(Globals.ctx, &Globals.share_backend, "classic");
+ lpcfg_string_set(Globals.ctx, &Globals.share_backend, "classic");
Globals.iPreferredMaster = Auto;
Globals.allow_dns_updates = DNS_UPDATE_SIGNED;
- string_set(Globals.ctx, &Globals.ntp_signd_socket_directory, get_dyn_NTP_SIGND_SOCKET_DIR());
+ lpcfg_string_set(Globals.ctx, &Globals.ntp_signd_socket_directory,
+ get_dyn_NTP_SIGND_SOCKET_DIR());
- string_set(Globals.ctx, &Globals.winbindd_privileged_socket_directory, get_dyn_WINBINDD_PRIVILEGED_SOCKET_DIR());
+ lpcfg_string_set(Globals.ctx,
+ &Globals.winbindd_privileged_socket_directory,
+ get_dyn_WINBINDD_PRIVILEGED_SOCKET_DIR());
s = talloc_asprintf(talloc_tos(), "%s/samba_kcc", get_dyn_SCRIPTSBINDIR());
if (s == NULL) {
@@ -1314,8 +1312,8 @@ static void free_param_opts(struct parmlist_entry **popts)
}
opt = *popts;
while (opt != NULL) {
- string_free(&opt->key);
- string_free(&opt->value);
+ lpcfg_string_free(&opt->key);
+ lpcfg_string_free(&opt->value);
TALLOC_FREE(opt->list);
next_opt = opt->next;
TALLOC_FREE(opt);
@@ -1339,7 +1337,7 @@ static void free_service(struct loadparm_service *pservice)
free_parameters(pservice);
- string_free(&pservice->szService);
+ lpcfg_string_free(&pservice->szService);
TALLOC_FREE(pservice->copymap);
free_param_opts(&pservice->param_opt);
@@ -1402,7 +1400,7 @@ static int add_a_service(const struct loadparm_service *pservice, const char *na
return (-1);
}
ServicePtrs = tsp;
- ServicePtrs[iNumServices] = talloc_zero(NULL, struct loadparm_service);
+ ServicePtrs[iNumServices] = talloc_zero(ServicePtrs, struct loadparm_service);
if (!ServicePtrs[iNumServices]) {
DEBUG(0,("add_a_service: out of memory!\n"));
return (-1);
@@ -1413,7 +1411,8 @@ static int add_a_service(const struct loadparm_service *pservice, const char *na
copy_service(ServicePtrs[i], pservice, NULL);
if (name)
- string_set(ServicePtrs[i], &ServicePtrs[i]->szService, name);
+ lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->szService,
+ name);
DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
i, ServicePtrs[i]->szService));
@@ -1502,7 +1501,8 @@ bool lp_add_home(const char *pszHomename, int iDefaultService,
if (!(*(ServicePtrs[iDefaultService]->path))
|| strequal(ServicePtrs[iDefaultService]->path,
lp_path(talloc_tos(), GLOBAL_SECTION_SNUM))) {
- string_set(ServicePtrs[i], &ServicePtrs[i]->path, pszHomedir);
+ lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->path,
+ pszHomedir);
}
if (!(*(ServicePtrs[i]->comment))) {
@@ -1510,7 +1510,8 @@ bool lp_add_home(const char *pszHomename, int iDefaultService,
if (comment == NULL) {
return false;
}
- string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
+ lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment,
+ comment);
TALLOC_FREE(comment);
}
@@ -1558,10 +1559,10 @@ static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
return false;
}
- string_set(ServicePtrs[i], &ServicePtrs[i]->path, tmpdir());
- string_set(ServicePtrs[i], &ServicePtrs[i]->username, "");
- string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
- string_set(ServicePtrs[i], &ServicePtrs[i]->fstype, "IPC");
+ lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->path, tmpdir());
+ lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->username, "");
+ lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
+ lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->fstype, "IPC");
ServicePtrs[i]->max_connections = 0;
ServicePtrs[i]->bAvailable = true;
ServicePtrs[i]->read_only = true;
@@ -1595,8 +1596,9 @@ bool lp_add_printer(const char *pszPrintername, int iDefaultService)
/* entry (if/when the 'available' keyword is implemented!). */
/* the printer name is set to the service name. */
- string_set(ServicePtrs[i], &ServicePtrs[i]->_printername, pszPrintername);
- string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
+ lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->_printername,
+ pszPrintername);
+ lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
/* set the browseable flag from the gloabl default */
ServicePtrs[i]->browseable = sDefault.browseable;
@@ -2318,9 +2320,9 @@ bool lp_include(struct loadparm_context *lp_ctx, struct loadparm_service *servic
add_to_file_list(NULL, &file_lists, pszParmValue, fname);
if (service == NULL) {
- string_set(Globals.ctx, ptr, fname);
+ lpcfg_string_set(Globals.ctx, ptr, fname);
} else {
- string_set(service, ptr, fname);
+ lpcfg_string_set(service, ptr, fname);
}
if (file_exist(fname)) {
@@ -2791,7 +2793,8 @@ void lp_add_one_printer(const char *name, const char *comment,
if (lp_servicenumber(name) < 0) {
lp_add_printer(name, printers);
if ((i = lp_servicenumber(name)) >= 0) {
- string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
+ lpcfg_string_set(ServicePtrs[i],
+ &ServicePtrs[i]->comment, comment);
ServicePtrs[i]->autoloaded = true;
}
}
@@ -2875,9 +2878,13 @@ static void lp_save_defaults(void)
break;
case P_STRING:
case P_USTRING:
- parm_table[i].def.svalue = talloc_strdup(Globals.ctx, *(char **)lp_parm_ptr(NULL, &parm_table[i]));
+ lpcfg_string_set(
+ Globals.ctx,
+ &parm_table[i].def.svalue,
+ *(char **)lp_parm_ptr(
+ NULL, &parm_table[i]));
if (parm_table[i].def.svalue == NULL) {
- smb_panic("talloc_strdup failed");
+ smb_panic("lpcfg_string_set() failed");
}
break;
case P_BOOL:
@@ -3353,8 +3360,10 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
/* And note when it was loaded. */
ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
- string_set(ServicePtrs[iService], &ServicePtrs[iService]->path, sharepath);
- string_set(ServicePtrs[iService], &ServicePtrs[iService]->comment, comment);
+ lpcfg_string_set(ServicePtrs[iService], &ServicePtrs[iService]->path,
+ sharepath);
+ lpcfg_string_set(ServicePtrs[iService],
+ &ServicePtrs[iService]->comment, comment);
ret = iService;
@@ -4206,7 +4215,7 @@ const char *lp_printername(TALLOC_CTX *ctx, int snum)
void lp_set_logfile(const char *name)
{
- string_set(Globals.ctx, &Globals.logfile, name);
+ lpcfg_string_set(Globals.ctx, &Globals.logfile, name);
debug_set_logfile(name);
}
@@ -4293,20 +4302,9 @@ void set_use_sendfile(int snum, bool val)
sDefault._use_sendfile = val;
}
-/*******************************************************************
- Turn off storing DOS attributes if this share doesn't support it.
-********************************************************************/
-
-void set_store_dos_attributes(int snum, bool val)
-{
- if (!LP_SNUM_OK(snum))
- return;
- ServicePtrs[(snum)]->store_dos_attributes = val;
-}
-
void lp_set_mangling_method(const char *new_method)
{
- string_set(Globals.ctx, &Globals.mangling_method, new_method);
+ lpcfg_string_set(Globals.ctx, &Globals.mangling_method, new_method);
}
/*******************************************************************
@@ -4342,7 +4340,8 @@ enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
if (posix_default_lock_was_set) {
return posix_cifsx_locktype;
} else {
- return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
+ return (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
+ POSIX_LOCK : WINDOWS_LOCK;
}
}
diff --git a/source3/script/tests/test_dfree_command.sh b/source3/script/tests/test_dfree_command.sh
index c9c3aa6..a60a52d 100755
--- a/source3/script/tests/test_dfree_command.sh
+++ b/source3/script/tests/test_dfree_command.sh
@@ -1,6 +1,7 @@
#!/bin/sh
#
-# Blackbox test for 'dfree command'
+# Blackbox test for 'dfree command' and smbclient "l"
+# command disk free printout.
#
if [ $# -lt 6 ]; then
@@ -26,15 +27,16 @@ test_smbclient_dfree() {
name="$1"
share="$2"
cmd="$3"
+ expected="$4"
shift
shift
+ shift
subunit_start_test "$name"
output=$($VALGRIND $smbclient //$SERVER/$share -c "$cmd" $@ 2>&1)
status=$?
if [ x$status = x0 ]; then
- echo "$output" | grep "2000 blocks of size 1024. 20 blocks available" >/dev/null
- status=$?
- if [ x$status = x0 ]; then
+ received=$(echo "$output" | awk '/blocks of size/ {print $1, $5, $6}')
+ if [ "$expected" = "$received" ]; then
subunit_pass_test "$name"
else
echo "$output" | subunit_fail_test "$name"
@@ -46,6 +48,11 @@ test_smbclient_dfree() {
}
-test_smbclient_dfree "Test dfree command" dfree "l" -U$USERNAME%$PASSWORD || failed=`expr $failed + 1`
+test_smbclient_dfree "Test dfree command share root SMB3" dfree "l" "2000 1024. 20" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
+test_smbclient_dfree "Test dfree command share root NT1" dfree "l" "2000 1024. 20" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=NT1 || failed=`expr $failed + 1`
+test_smbclient_dfree "Test dfree command subdir1 SMB3" dfree "cd subdir1; l" "8000 1024. 80" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
+test_smbclient_dfree "Test dfree command subdir2 SMB3" dfree "cd subdir2; l" "32000 1024. 320" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
+#SMB1 queries disk usage stat on the share's root, regardless of working directory
+test_smbclient_dfree "Test dfree command subdir1 NT1" dfree "cd subdir1; l" "2000 1024. 20" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=NT1 || failed=`expr $failed + 1`
exit $failed
diff --git a/source3/script/tests/test_shadow_copy.sh b/source3/script/tests/test_shadow_copy.sh
new file mode 100755
index 0000000..eecd5b8
--- /dev/null
+++ b/source3/script/tests/test_shadow_copy.sh
@@ -0,0 +1,290 @@
+#!/bin/bash
+#
+# Blackbox test for shadow_copy2 VFS.
+#
+
+if [ $# -lt 7 ]; then
+cat <<EOF
+Usage: test_shadow_copy SERVER SERVER_IP DOMAIN USERNAME PASSWORD WORKDIR SMBCLIENT
+EOF
+exit 1;
+fi
+
+SERVER=${1}
+SERVER_IP=${2}
+DOMAIN=${3}
+USERNAME=${4}
+PASSWORD=${5}
+WORKDIR=${6}
+SMBCLIENT=${7}
+shift 7
+SMBCLIENT="$VALGRIND ${SMBCLIENT}"
+ADDARGS="$*"
+
+incdir=`dirname $0`/../../../testprogs/blackbox
+. $incdir/subunit.sh
+
+SNAPSHOTS[0]='@GMT-2015.10.31-19.40.30'
+SNAPSHOTS[1]='@GMT-2016.10.31-19.40.30'
+SNAPSHOTS[2]='@GMT-2017.10.31-19.40.30'
+SNAPSHOTS[3]='@GMT-2018.10.31-19.40.30'
+SNAPSHOTS[4]='@GMT-2019.10.31-19.40.30'
+SNAPSHOTS[5]='@GMT-2020.10.31-19.40.30'
+SNAPSHOTS[6]='@GMT-2021.10.31-19.40.30'
+SNAPSHOTS[7]='@GMT-2022.10.31-19.40.30'
+SNAPSHOTS[8]='@GMT-2023.10.31-19.40.30'
+SNAPSHOTS[9]='@GMT-2024.10.31-19.40.30'
+
+# build a hierarchy of files, symlinks, and directories
+build_files()
+{
+ local rootdir
+ local prefix
+ local version
+ local destdir
+ rootdir=$1
+ prefix=$2
+ version=$3
+ if [ -n "$prefix" ] ; then
+ destdir=$rootdir/$prefix
+ else
+ destdir=$rootdir
+ fi
+
+ mkdir -p $destdir
+ if [ "$version" = "latest" ] ; then
+ #non-snapshot files
+ # for non-snapshot version, create legit files
+ # so that wide-link checks focus on snapshot files
+ touch $destdir/foo
+ mkdir -p $destdir/bar
+ touch $destdir/bar/baz
+ touch $destdir/bar/lfoo
+ touch $destdir/bar/letcpasswd
+ touch $destdir/bar/loutside
+ elif [ "$version" = "fullsnap" ] ; then
+ #snapshot files
+ touch $destdir/foo
+ mkdir -p $destdir/bar
+ touch $destdir/bar/baz
+ ln -fs ../foo $destdir/bar/lfoo
+ ln -fs /etc/passwd $destdir/bar/letcpasswd
+ ln -fs ../../outside $destdir/bar/loutside
+ touch `dirname $destdir`/outside
+ else #subshare snapshot - at bar
+ touch $destdir/baz
+ ln -fs ../foo $destdir/lfoo
+ ln -fs /etc/passwd $destdir/letcpasswd
+ ln -fs ../../outside $destdir/loutside
+ touch `dirname $destdir`/../outside
+ fi
+
+}
+
+# build a snapshots directory
+build_snapshots()
+{
+ local where #where to build snapshots
+ local prefix #prefix from snapshot dir to share root
+ local start #timestamp index of first snapshot
+ local end #timestamp index of last snapshot
+ local sub #creat a snapshot of subtree of share
+ local snapdir
+ local snapname
+ local i
+ local version
+
+ where=$1
+ prefix=$2
+ start=$3
+ end=$4
+ sub=$5
+
+ snapdir=$where/.snapshots
+ mkdir -p $snapdir
+
+ version="fullsnap"
+ if [ "$sub" = "1" ] ; then
+ version="subsnap"
+ prefix=""
+
+ # a valid link target for an inner symlink -
+ # the link is not broken yet should be blocked
+ # by wide link checks
+ touch $snapdir/foo
+ fi
+
+ for i in `seq $start $end` ; do
+ snapname=${SNAPSHOTS[$i]}
+ mkdir $snapdir/$snapname
+ build_files $snapdir/$snapname "$prefix" $version
+ done
+}
+
+# Test listing previous versions of a file
+test_count_versions()
+{
+ local share
+ local path
+ local expected_count
+ local versions
+
+ share=$1
+ path=$2
+ expected_count=$3
+ versions=`$SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | grep "^create_time:" | wc -l`
+ if [ "$versions" = "$expected_count" ] ; then
+ true
+ else
+ echo "expected $expected_count versions of $path, got $versions"
+ false
+ fi
+}
+
+# Test fetching a previous version of a file
+test_fetch_snap_file()
+{
+ local share
+ local path
+ local snapidx
+
+ share=$1
+ path=$2
+ snapidx=$3
+ $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP \
+ -c "get ${SNAPSHOTS[$snapidx]}/$path $WORKDIR/foo"
+}
+
+test_shadow_copy_fixed()
+{
+ local share #share to contact
+ local where #where to place snapshots
+ local prefix #prefix to files inside snapshot
+ local msg
+ local allow_wl
+ local ncopies_allowd
+ local ncopies_blocked
+
+ share=$1
+ where=$2
+ prefix=$3
+ msg=$4
+ allow_wl=$5
+
+ ncopies_allowed=4
+ ncopies_blocked=1
+ if [ -n "$allow_wl" ] ; then
+ ncopies_blocked=4
+ fi
+
+ #delete snapshots from previous tests
+ find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1
+ build_snapshots $WORKDIR/$where "$prefix" 0 2
+
+ testit "$msg - regular file" \
+ test_count_versions $share foo $ncopies_allowed || \
+ failed=`expr $failed + 1`
+
+ testit "$msg - regular file in subdir" \
+ test_count_versions $share bar/baz $ncopies_allowed || \
+ failed=`expr $failed + 1`
+
+ testit "$msg - local symlink" \
+ test_count_versions $share bar/lfoo $ncopies_allowed || \
+ failed=`expr $failed + 1`
+
+ testit "$msg - abs symlink outside" \
+ test_count_versions $share bar/letcpasswd $ncopies_blocked || \
+ failed=`expr $failed + 1`
+
+ testit "$msg - rel symlink outside" \
+ test_count_versions $share bar/loutside $ncopies_blocked || \
+ failed=`expr $failed + 1`
+}
+
+test_shadow_copy_everywhere()
+{
+ local share #share to contact
+
+ share=$1
+
+ #delete snapshots from previous tests
+ find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1
+ build_snapshots "$WORKDIR/mount" "base/share" 0 0
+ build_snapshots "$WORKDIR/mount/base" "share" 1 2
+ build_snapshots "$WORKDIR/mount/base/share" "" 3 5
+ build_snapshots "$WORKDIR/mount/base/share/bar" "" 6 9 1
+
+ testit "snapshots in each dir - regular file" \
+ test_count_versions $share foo 4 || \
+ failed=`expr $failed + 1`
+
+ testit "snapshots in each dir - regular file in subdir" \
+ test_count_versions $share bar/baz 5 || \
+ failed=`expr $failed + 1`
+
+ testit "snapshots in each dir - local symlink (but outside snapshot)" \
+ test_count_versions $share bar/lfoo 1 || \
+ failed=`expr $failed + 1`
+
+ testit "snapshots in each dir - abs symlink outside" \
+ test_count_versions $share bar/letcpasswd 1 || \
+ failed=`expr $failed + 1`
+
+ testit "snapshots in each dir - rel symlink outside" \
+ test_count_versions $share bar/loutside 1 || \
+ failed=`expr $failed + 1`
+
+ #the previous versions of the file bar/lfoo points to are outside its
+ #snapshot, and are not reachable. However, but previous versions
+ #taken at different, non-overlapping times higher up the
+ #hierarchy are still reachable.
+ testit "fetch a previous version of a regular file" \
+ test_fetch_snap_file $share "bar/baz" 6 || \
+ failed=`expr $failed + 1`
+
+ testit_expect_failure "fetch a (non-existent) previous version of a symlink" \
+ test_fetch_snap_file $share "bar/lfoo" 6 || \
+ failed=`expr $failed + 1`
+
+ testit "fetch a previous version of a symlink via browsing (1)" \
+ test_fetch_snap_file $share "bar/lfoo" 0 || \
+ failed=`expr $failed + 1`
+
+ testit "fetch a previous version of a symlink via browsing (2)" \
+ test_fetch_snap_file $share "bar/lfoo" 1 || \
+ failed=`expr $failed + 1`
+
+ testit "fetch a previous version of a symlink via browsing (3)" \
+ test_fetch_snap_file $share "bar/lfoo" 3 || \
+ failed=`expr $failed + 1`
+
+}
+
+#build "latest" files
+build_files $WORKDIR/mount base/share "latest"
+
+failed=0
+
+# a test with wide links allowed - also to verify that what's later
+# being blocked is a result of server security measures and not
+# a testing artifact.
+test_shadow_copy_fixed shadow_wl mount base/share "shadow copies with wide links allowed" 1
+
+# tests for a fixed snapshot location
+test_shadow_copy_fixed shadow1 mount base/share "full volume snapshots mounted under volume"
+test_shadow_copy_fixed shadow2 . base/share "full volume snapshots mounted outside volume"
+test_shadow_copy_fixed shadow3 mount/base share "sub volume snapshots mounted under snapshot point"
+test_shadow_copy_fixed shadow4 . share "sub volume snapshots mounted outside"
+test_shadow_copy_fixed shadow5 mount/base/share "" "full volume snapshots and share mounted under volume"
+test_shadow_copy_fixed shadow6 . "" "full volume snapshots and share mounted outside"
+
+# tests for snapshot everywhere - one snapshot location
+test_shadow_copy_fixed shadow7 mount base/share "'everywhere' full volume snapshots"
+test_shadow_copy_fixed shadow7 mount/base share "'everywhere' sub volume snapshots"
+test_shadow_copy_fixed shadow7 mount/base/share "" "'everywhere' share snapshots"
+
+# a test for snapshots everywhere - multiple snapshot locations
+test_shadow_copy_everywhere shadow7
+
+exit $failed
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 630927b..79db4b5 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -78,7 +78,7 @@ tests = ["RW1", "RW2", "RW3"]
for t in tests:
plantestsuite("samba3.smbtorture_s3.vfs_aio_fork(simpleserver).%s" % t, "simpleserver", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/vfs_aio_fork', '$USERNAME', '$PASSWORD', smbtorture3, "", "-l $LOCAL_PATH"])
-posix_tests = ["POSIX", "POSIX-APPEND"]
+posix_tests = ["POSIX", "POSIX-APPEND", "POSIX-SYMLINK-ACL", "POSIX-SYMLINK-EA"]
for t in posix_tests:
plantestsuite("samba3.smbtorture_s3.plain(nt4_dc).%s" % t, "nt4_dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/posix_share', '$USERNAME', '$PASSWORD', smbtorture3, "", "-l $LOCAL_PATH"])
@@ -177,6 +177,7 @@ for env in ["nt4_dc"]:
for env in ["fileserver"]:
plantestsuite("samba3.blackbox.preserve_case (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_preserve_case.sh"), '$SERVER', '$DOMAIN', '$USERNAME', '$PASSWORD', '$PREFIX', smbclient3])
plantestsuite("samba3.blackbox.dfree_command (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_dfree_command.sh"), '$SERVER', '$DOMAIN', '$USERNAME', '$PASSWORD', '$PREFIX', smbclient3])
+ plantestsuite("samba3.blackbox.shadow_copy2 (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_shadow_copy.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/shadow', smbclient3])
#
# tar command tests
@@ -380,8 +381,8 @@ for t in tests:
plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmpsort -U$USERNAME%$PASSWORD')
plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD')
elif t == "vfs.fruit":
- plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD --option=torture:share1=vfs_fruit --option=torture:share2=tmp --option=torture:localdir=$SELFTEST_PREFIX/nt4_dc/share')
- plansmbtorture4testsuite(t, "ad_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD --option=torture:share1=vfs_fruit --option=torture:share2=tmp --option=torture:localdir=$SELFTEST_PREFIX/ad_dc/share')
+ plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/vfs_fruit -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/nt4_dc/share')
+ plansmbtorture4testsuite(t, "ad_dc", '//$SERVER_IP/vfs_fruit -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/ad_dc/share')
elif t == "rpc.schannel_anon_setpw":
plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$%', description="anonymous password set")
plansmbtorture4testsuite(t, "nt4_dc_schannel", '//$SERVER_IP/tmp -U$%', description="anonymous password set (schannel enforced server-side)")
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index 0e75bf0..1cb5460 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -327,7 +327,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
if (e->name_hash != fsp->name_hash) {
continue;
}
- if (fsp->posix_open
+ if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)
&& (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
continue;
}
@@ -1103,7 +1103,9 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
struct share_mode_entry *e = &lck->data->share_modes[i];
if (is_valid_share_mode_entry(e) &&
e->name_hash == fsp->name_hash) {
- if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
+ if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) &&
+ (e->flags & SHARE_MODE_FLAG_POSIX_OPEN))
+ {
continue;
}
if (serverid_equal(&self, &e->pid) &&
diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c
index 32a3a69..0c38837 100644
--- a/source3/smbd/dfree.c
+++ b/source3/smbd/dfree.c
@@ -123,7 +123,14 @@ uint64_t sys_disk_free(connection_struct *conn, const char *path,
}
if (disk_quotas(path, &bsize_q, &dfree_q, &dsize_q)) {
- (*bsize) = bsize_q;
+ uint64_t min_bsize = MIN(*bsize, bsize_q);
+
+ (*dfree) = (*dfree) * (*bsize) / min_bsize;
+ (*dsize) = (*dsize) * (*bsize) / min_bsize;
+ dfree_q = dfree_q * bsize_q / min_bsize;
+ dsize_q = dsize_q * bsize_q / min_bsize;
+
+ (*bsize) = min_bsize;
(*dfree) = MIN(*dfree,dfree_q);
(*dsize) = MIN(*dsize,dsize_q);
}
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 72acd4e..907f3f9 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -279,18 +279,9 @@ static bool get_ea_dos_attribute(connection_struct *conn,
SAMBA_XATTR_DOS_ATTRIB, attrstr,
sizeof(attrstr));
if (sizeret == -1) {
- if (errno == ENOSYS
-#if defined(ENOTSUP)
- || errno == ENOTSUP) {
-#else
- ) {
-#endif
- DEBUG(1,("get_ea_dos_attribute: Cannot get attribute "
- "from EA on file %s: Error = %s\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno)));
- set_store_dos_attributes(SNUM(conn), False);
- }
+ DBG_INFO("get_ea_dos_attribute: Cannot get attribute "
+ "from EA on file %s: Error = %s\n",
+ smb_fname_str_dbg(smb_fname), strerror(errno));
return False;
}
@@ -365,7 +356,7 @@ static bool get_ea_dos_attribute(connection_struct *conn,
dosattr |= FILE_ATTRIBUTE_DIRECTORY;
}
/* FILE_ATTRIBUTE_SPARSE is valid on get but not on set. */
- *pattr = (uint32_t)(dosattr & (SAMBA_ATTRIBUTES_MASK|FILE_ATTRIBUTE_SPARSE));
+ *pattr |= (uint32_t)(dosattr & (SAMBA_ATTRIBUTES_MASK|FILE_ATTRIBUTE_SPARSE));
DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr));
@@ -430,18 +421,9 @@ static bool set_ea_dos_attribute(connection_struct *conn,
files_struct *fsp = NULL;
if((errno != EPERM) && (errno != EACCES)) {
- if (errno == ENOSYS
-#if defined(ENOTSUP)
- || errno == ENOTSUP) {
-#else
- ) {
-#endif
- DEBUG(1,("set_ea_dos_attributes: Cannot set "
- "attribute EA on file %s: Error = %s\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno) ));
- set_store_dos_attributes(SNUM(conn), False);
- }
+ DBG_INFO("set_ea_dos_attributes: Cannot set "
+ "attribute EA on file %s: Error = %s\n",
+ smb_fname_str_dbg(smb_fname), strerror(errno));
return false;
}
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index 2fe0432..156c139 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -193,7 +193,7 @@ void trigger_write_time_update(struct files_struct *fsp)
{
int delay;
- if (fsp->posix_open) {
+ if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
/* Don't use delayed writes on POSIX files. */
return;
}
@@ -238,7 +238,7 @@ void trigger_write_time_update_immediate(struct files_struct *fsp)
{
struct smb_file_time ft;
- if (fsp->posix_open) {
+ if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
/* Don't use delayed writes on POSIX files. */
return;
}
@@ -284,7 +284,7 @@ void mark_file_modified(files_struct *fsp)
}
trigger_write_time_update(fsp);
- if (fsp->posix_open) {
+ if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
return;
}
if (!(lp_store_dos_attributes(SNUM(fsp->conn)) ||
@@ -1047,7 +1047,7 @@ NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_throug
int fsp_stat(files_struct *fsp)
{
if (fsp->fh->fd == -1) {
- if (fsp->posix_open) {
+ if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
return SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
} else {
return SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 04dddee..9233738 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -875,6 +875,12 @@ NTSTATUS set_sd(files_struct *fsp, struct security_descriptor *psd,
return NT_STATUS_OK;
}
+ if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
+ DEBUG(10, ("ACL set on symlink %s denied.\n",
+ fsp_str_dbg(fsp)));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
if (psd->owner_sid == NULL) {
security_info_sent &= ~SECINFO_OWNER;
}
@@ -1905,6 +1911,13 @@ NTSTATUS smbd_do_query_security_desc(connection_struct *conn,
return NT_STATUS_ACCESS_DENIED;
}
+ if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
+ DEBUG(10, ("ACL get on symlink %s denied.\n",
+ fsp_str_dbg(fsp)));
+ TALLOC_FREE(frame);
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
if (security_info_wanted & (SECINFO_DACL|SECINFO_OWNER|
SECINFO_GROUP|SECINFO_SACL)) {
/* Don't return SECINFO_LABEL if anything else was
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 162e834..eb6058f 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -362,7 +362,7 @@ NTSTATUS fd_open(struct connection_struct *conn,
* client should be doing this.
*/
- if (fsp->posix_open || !lp_follow_symlinks(SNUM(conn))) {
+ if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) || !lp_follow_symlinks(SNUM(conn))) {
flags |= O_NOFOLLOW;
}
#endif
@@ -945,7 +945,7 @@ static NTSTATUS open_file(files_struct *fsp,
access_mask);
if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
- fsp->posix_open &&
+ (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) &&
S_ISLNK(smb_fname->st.st_ex_mode)) {
/* This is a POSIX stat open for delete
* or rename on a symlink that points
@@ -2705,7 +2705,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
fsp->access_mask = open_access_mask; /* We change this to the
* requested access_mask after
* the open is done. */
- fsp->posix_open = posix_open;
+ fsp->posix_flags |= posix_open ? FSP_POSIX_FLAGS_OPEN : 0;
if (timeval_is_zero(&request_time)) {
request_time = fsp->open_time;
@@ -3167,8 +3167,8 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
}
if (info != FILE_WAS_OPENED) {
- /* Files should be initially set as archive */
- if (lp_map_archive(SNUM(conn)) ||
+ /* Overwritten files should be initially set as archive */
+ if ((info == FILE_WAS_OVERWRITTEN && lp_map_archive(SNUM(conn))) ||
lp_store_dos_attributes(SNUM(conn))) {
if (!posix_open) {
if (file_set_dosmode(conn, smb_fname,
@@ -3571,7 +3571,9 @@ static NTSTATUS open_directory(connection_struct *conn,
fsp->oplock_type = NO_OPLOCK;
fsp->sent_oplock_break = NO_BREAK_SENT;
fsp->is_directory = True;
- fsp->posix_open = (file_attributes & FILE_FLAG_POSIX_SEMANTICS) ? True : False;
+ if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
+ fsp->posix_flags |= FSP_POSIX_FLAGS_ALL;
+ }
status = fsp_set_smb_fname(fsp, smb_dname);
if (!NT_STATUS_IS_OK(status)) {
file_free(req, fsp);
@@ -4704,15 +4706,11 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
/* Save the requested allocation size. */
if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) {
- if (allocation_size
- && (allocation_size > fsp->fsp_name->st.st_ex_size)) {
+ if ((allocation_size > fsp->fsp_name->st.st_ex_size)
+ && !(fsp->is_directory))
+ {
fsp->initial_allocation_size = smb_roundup(
fsp->conn, allocation_size);
- if (fsp->is_directory) {
- /* Can't set allocation size on a directory. */
- status = NT_STATUS_ACCESS_DENIED;
- goto fail;
- }
if (vfs_allocate_file_space(
fsp, fsp->initial_allocation_size) == -1) {
status = NT_STATUS_DISK_FULL;
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index 4d84347..4f108d9 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -96,9 +96,10 @@ static void release_file_oplock(files_struct *fsp)
{
struct smbd_server_connection *sconn = fsp->conn->sconn;
struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
+ bool use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) && koplocks;
if ((fsp->oplock_type != NO_OPLOCK) &&
- koplocks) {
+ use_kernel) {
koplocks->ops->release_oplock(koplocks, fsp, NO_OPLOCK);
}
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index b69e5b4..80d4fea 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -3085,7 +3085,7 @@ static bool convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file
canon_ace *group_ace = NULL;
canon_ace *other_ace = NULL;
- if (ace_count != 3) {
+ if (ace_count > 5) {
DEBUG(3,("convert_canon_ace_to_posix_perms: Too many ACE "
"entries for file %s to convert to posix perms.\n",
fsp_str_dbg(fsp)));
@@ -3107,6 +3107,43 @@ static bool convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file
return False;
}
+ /*
+ * Ensure all ACE entries are owner, group or other.
+ * We can't set if there are any other SIDs.
+ */
+ for (ace_p = file_ace_list; ace_p; ace_p = ace_p->next) {
+ if (ace_p == owner_ace || ace_p == group_ace ||
+ ace_p == other_ace) {
+ continue;
+ }
+ if (ace_p->owner_type == UID_ACE) {
+ if (ace_p->unix_ug.id != owner_ace->unix_ug.id) {
+ DEBUG(3,("Invalid uid %u in ACE for file %s.\n",
+ (unsigned int)ace_p->unix_ug.id,
+ fsp_str_dbg(fsp)));
+ return false;
+ }
+ } else if (ace_p->owner_type == GID_ACE) {
+ if (ace_p->unix_ug.id != group_ace->unix_ug.id) {
+ DEBUG(3,("Invalid gid %u in ACE for file %s.\n",
+ (unsigned int)ace_p->unix_ug.id,
+ fsp_str_dbg(fsp)));
+ return false;
+ }
+ } else {
+ /*
+ * There should be no duplicate WORLD_ACE entries.
+ */
+
+ DEBUG(3,("Invalid type %u, uid %u in "
+ "ACE for file %s.\n",
+ (unsigned int)ace_p->owner_type,
+ (unsigned int)ace_p->unix_ug.id,
+ fsp_str_dbg(fsp)));
+ return false;
+ }
+ }
+
*posix_perms = (mode_t)0;
*posix_perms |= owner_ace->perms;
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index b6f9992..c9d0d81 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -2669,7 +2669,7 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
}
if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
- if (fsp->posix_open) {
+ if (fsp->posix_flags & (FSP_POSIX_FLAGS_OPEN|FSP_POSIX_FLAGS_RENAME)) {
return NT_STATUS_OK;
}
diff --git a/source3/smbd/smb2_close.c b/source3/smbd/smb2_close.c
index ed53e1b..367c9fa 100644
--- a/source3/smbd/smb2_close.c
+++ b/source3/smbd/smb2_close.c
@@ -231,7 +231,7 @@ static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
return NT_STATUS_NO_MEMORY;
}
- posix_open = fsp->posix_open;
+ posix_open = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN);
smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
if (smb_fname == NULL) {
return NT_STATUS_NO_MEMORY;
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index ad21533..76d6d69 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -1281,6 +1281,14 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
state->out_last_write_ts = result->fsp_name->st.st_ex_mtime;
state->out_change_ts = get_change_timespec(smb1req->conn,
result, result->fsp_name);
+
+ if (lp_dos_filetime_resolution(SNUM(smb2req->tcon->compat))) {
+ dos_filetime_timespec(&state->out_creation_ts);
+ dos_filetime_timespec(&state->out_last_access_ts);
+ dos_filetime_timespec(&state->out_last_write_ts);
+ dos_filetime_timespec(&state->out_change_ts);
+ }
+
state->out_allocation_size =
SMB_VFS_GET_ALLOC_SIZE(smb1req->conn, result,
&(result->fsp_name->st));
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index d5a38d4..ff1ef15 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -54,6 +54,34 @@ static char *store_file_unix_basic_info2(connection_struct *conn,
files_struct *fsp,
const SMB_STRUCT_STAT *psbuf);
+/****************************************************************************
+ Check if an open file handle or pathname is a symlink.
+****************************************************************************/
+
+static NTSTATUS refuse_symlink(connection_struct *conn,
+ const files_struct *fsp,
+ const char *name)
+{
+ SMB_STRUCT_STAT sbuf;
+ const SMB_STRUCT_STAT *pst = NULL;
+
+ if (fsp) {
+ pst = &fsp->fsp_name->st;
+ } else {
+ int ret = vfs_stat_smb_basename(conn,
+ name,
+ &sbuf);
+ if (ret == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+ pst = &sbuf;
+ }
+ if (S_ISLNK(pst->st_ex_mode)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ return NT_STATUS_OK;
+}
+
/********************************************************************
The canonical "check access" based on object handle or path function.
********************************************************************/
@@ -209,12 +237,22 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
char **names, **tmp;
size_t num_names;
ssize_t sizeret = -1;
+ NTSTATUS status;
+
+ if (pnames) {
+ *pnames = NULL;
+ }
+ *pnum_names = 0;
if (!lp_ea_support(SNUM(conn))) {
- if (pnames) {
- *pnames = NULL;
- }
- *pnum_names = 0;
+ return NT_STATUS_OK;
+ }
+
+ status = refuse_symlink(conn, fsp, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ /*
+ * Just return no EA's on a symlink.
+ */
return NT_STATUS_OK;
}
@@ -264,10 +302,6 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
if (sizeret == 0) {
TALLOC_FREE(names);
- if (pnames) {
- *pnames = NULL;
- }
- *pnum_names = 0;
return NT_STATUS_OK;
}
@@ -625,6 +659,11 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
return NT_STATUS_EAS_NOT_SUPPORTED;
}
+ status = refuse_symlink(conn, fsp, smb_fname->base_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -5251,6 +5290,13 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
uint16_t num_file_acls = 0;
uint16_t num_def_acls = 0;
+ status = refuse_symlink(conn,
+ fsp,
+ smb_fname->base_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
if (fsp && fsp->fh->fd != -1) {
file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
talloc_tos());
@@ -6748,6 +6794,7 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
uint16_t num_def_acls;
bool valid_file_acls = True;
bool valid_def_acls = True;
+ NTSTATUS status;
if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
return NT_STATUS_INVALID_PARAMETER;
@@ -6775,6 +6822,11 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
+ status = refuse_symlink(conn, fsp, smb_fname->base_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
(unsigned int)num_file_acls,
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index f14ecbe..1a2ee3d 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -982,7 +982,6 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
struct smb_filename *smb_fname_cwd = NULL;
struct privilege_paths *priv_paths = NULL;
int ret;
- bool matched;
DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
fname,
@@ -1077,18 +1076,32 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
}
rootdir_len = strlen(conn_rootdir);
- matched = (strncmp(conn_rootdir, resolved_name, rootdir_len) == 0);
-
- if (!matched || (resolved_name[rootdir_len] != '/' &&
- resolved_name[rootdir_len] != '\0')) {
- DEBUG(2, ("check_reduced_name_with_privilege: Bad access "
- "attempt: %s is a symlink outside the "
- "share path\n",
- dir_name));
- DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
- DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
- status = NT_STATUS_ACCESS_DENIED;
- goto err;
+
+ /*
+ * In the case of rootdir_len == 1, we know that conn_rootdir is
+ * "/", and we also know that resolved_name starts with a slash.
+ * So, in this corner case, resolved_name is automatically a
+ * sub-directory of the conn_rootdir. Thus we can skip the string
+ * comparison and the next character checks (which are even
+ * wrong in this case).
+ */
+ if (rootdir_len != 1) {
+ bool matched;
+
+ matched = (strncmp(conn_rootdir, resolved_name,
+ rootdir_len) == 0);
+
+ if (!matched || (resolved_name[rootdir_len] != '/' &&
+ resolved_name[rootdir_len] != '\0')) {
+ DEBUG(2, ("check_reduced_name_with_privilege: Bad "
+ "access attempt: %s is a symlink outside the "
+ "share path\n",
+ dir_name));
+ DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
+ DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
+ status = NT_STATUS_ACCESS_DENIED;
+ goto err;
+ }
}
/* Now ensure that the last component either doesn't
@@ -1220,7 +1233,6 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
if (!allow_widelinks || !allow_symlinks) {
const char *conn_rootdir;
size_t rootdir_len;
- bool matched;
conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
if (conn_rootdir == NULL) {
@@ -1231,17 +1243,33 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
}
rootdir_len = strlen(conn_rootdir);
- matched = (strncmp(conn_rootdir, resolved_name,
- rootdir_len) == 0);
- if (!matched || (resolved_name[rootdir_len] != '/' &&
- resolved_name[rootdir_len] != '\0')) {
- DEBUG(2, ("check_reduced_name: Bad access "
- "attempt: %s is a symlink outside the "
- "share path\n", fname));
- DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
- DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
- SAFE_FREE(resolved_name);
- return NT_STATUS_ACCESS_DENIED;
+
+ /*
+ * In the case of rootdir_len == 1, we know that
+ * conn_rootdir is "/", and we also know that
+ * resolved_name starts with a slash. So, in this
+ * corner case, resolved_name is automatically a
+ * sub-directory of the conn_rootdir. Thus we can skip
+ * the string comparison and the next character checks
+ * (which are even wrong in this case).
+ */
+ if (rootdir_len != 1) {
+ bool matched;
+
+ matched = (strncmp(conn_rootdir, resolved_name,
+ rootdir_len) == 0);
+ if (!matched || (resolved_name[rootdir_len] != '/' &&
+ resolved_name[rootdir_len] != '\0')) {
+ DEBUG(2, ("check_reduced_name: Bad access "
+ "attempt: %s is a symlink outside the "
+ "share path\n", fname));
+ DEBUGADD(2, ("conn_rootdir =%s\n",
+ conn_rootdir));
+ DEBUGADD(2, ("resolved_name=%s\n",
+ resolved_name));
+ SAFE_FREE(resolved_name);
+ return NT_STATUS_ACCESS_DENIED;
+ }
}
/* Extra checks if all symlinks are disallowed. */
@@ -1316,7 +1344,7 @@ NTSTATUS vfs_stat_fsp(files_struct *fsp)
int ret;
if(fsp->fh->fd == -1) {
- if (fsp->posix_open) {
+ if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
} else {
ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
@@ -1946,7 +1974,7 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
path = fsp->fsp_name->base_name;
}
- if (fsp->posix_open || as_root) {
+ if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) || as_root) {
ret = SMB_VFS_LCHOWN(fsp->conn,
path,
uid, gid);
diff --git a/source3/torture/nbio.c b/source3/torture/nbio.c
index 6373a10..6c87f9a 100644
--- a/source3/torture/nbio.c
+++ b/source3/torture/nbio.c
@@ -287,7 +287,7 @@ void nb_qfsinfo(int level)
{
uint64_t bsize, total, avail;
/* this is not the right call - we need cli_qfsinfo() */
- cli_disk_size(c, &bsize, &total, &avail);
+ cli_disk_size(c, "", &bsize, &total, &avail);
}
static NTSTATUS find_fn(const char *mnt, struct file_info *finfo, const char *name,
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 7bb776f..e75f2aa 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -5816,6 +5816,380 @@ static bool run_simple_posix_open_test(int dummy)
return correct;
}
+/*
+ Test POSIX and Windows ACLs are rejected on symlinks.
+ */
+static bool run_acl_symlink_test(int dummy)
+{
+ static struct cli_state *cli;
+ const char *fname = "posix_file";
+ const char *sname = "posix_symlink";
+ uint16_t fnum = (uint16_t)-1;
+ bool correct = false;
+ NTSTATUS status;
+ char *posix_acl = NULL;
+ size_t posix_acl_len = 0;
+ char *posix_acl_sym = NULL;
+ size_t posix_acl_len_sym = 0;
+ struct security_descriptor *sd = NULL;
+ struct security_descriptor *sd_sym = NULL;
+ TALLOC_CTX *frame = NULL;
+
+ frame = talloc_stackframe();
+
+ printf("Starting acl symlink test\n");
+
+ if (!torture_open_connection(&cli, 0)) {
+ TALLOC_FREE(frame);
+ return false;
+ }
+
+ smbXcli_conn_set_sockopt(cli->conn, sockops);
+
+ status = torture_setup_unix_extensions(cli);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(frame);
+ return false;
+ }
+
+ cli_setatr(cli, fname, 0, 0);
+ cli_posix_unlink(cli, fname);
+ cli_setatr(cli, sname, 0, 0);
+ cli_posix_unlink(cli, sname);
+
+ status = cli_ntcreate(cli,
+ fname,
+ 0,
+ READ_CONTROL_ACCESS,
+ 0,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ FILE_CREATE,
+ 0x0,
+ 0x0,
+ &fnum,
+ NULL);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("cli_ntcreate of %s failed (%s)\n",
+ fname,
+ nt_errstr(status));
+ goto out;
+ }
+
+ /* Get the Windows ACL on the file. */
+ status = cli_query_secdesc(cli,
+ fnum,
+ frame,
+ &sd);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("cli_query_secdesc failed (%s)\n",
+ nt_errstr(status));
+ goto out;
+ }
+
+ /* Get the POSIX ACL on the file. */
+ status = cli_posix_getacl(cli,
+ fname,
+ frame,
+ &posix_acl_len,
+ &posix_acl);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("cli_posix_getacl failed (%s)\n",
+ nt_errstr(status));
+ goto out;
+ }
+
+ status = cli_close(cli, fnum);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("close failed (%s)\n", nt_errstr(status));
+ goto out;
+ }
+ fnum = (uint16_t)-1;
+
+ /* Now create a symlink. */
+ status = cli_posix_symlink(cli, fname, sname);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("cli_posix_symlink of %s -> %s failed (%s)\n",
+ sname,
+ fname,
+ nt_errstr(status));
+ goto out;
+ }
+
+ /* Open a handle on the symlink. */
+ status = cli_ntcreate(cli,
+ sname,
+ 0,
+ READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
+ 0,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ FILE_OPEN,
+ 0x0,
+ 0x0,
+ &fnum,
+ NULL);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("cli_posix_open of %s failed (%s)\n",
+ sname,
+ nt_errstr(status));
+ goto out;
+ }
+
+ /* Get the Windows ACL on the symlink handle. Should fail */
+ status = cli_query_secdesc(cli,
+ fnum,
+ frame,
+ &sd_sym);
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+ printf("cli_query_secdesc on a symlink gave %s. "
+ "Should be NT_STATUS_ACCESS_DENIED.\n",
+ nt_errstr(status));
+ goto out;
+ }
+
+ /* Get the POSIX ACL on the symlink pathname. Should fail. */
+ status = cli_posix_getacl(cli,
+ sname,
+ frame,
+ &posix_acl_len_sym,
+ &posix_acl_sym);
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+ printf("cli_posix_getacl on a symlink gave %s. "
+ "Should be NT_STATUS_ACCESS_DENIED.\n",
+ nt_errstr(status));
+ goto out;
+ }
+
+ /* Set the Windows ACL on the symlink handle. Should fail */
+ status = cli_set_security_descriptor(cli,
+ fnum,
+ SECINFO_DACL,
+ sd);
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+ printf("cli_query_secdesc on a symlink gave %s. "
+ "Should be NT_STATUS_ACCESS_DENIED.\n",
+ nt_errstr(status));
+ goto out;
+ }
+
+ /* Set the POSIX ACL on the symlink pathname. Should fail. */
+ status = cli_posix_setacl(cli,
+ sname,
+ posix_acl,
+ posix_acl_len);
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+ printf("cli_posix_getacl on a symlink gave %s. "
+ "Should be NT_STATUS_ACCESS_DENIED.\n",
+ nt_errstr(status));
+ goto out;
+ }
+
+ printf("ACL symlink test passed\n");
+ correct = true;
+
+ out:
+
+ if (fnum != (uint16_t)-1) {
+ cli_close(cli, fnum);
+ fnum = (uint16_t)-1;
+ }
+
+ cli_setatr(cli, sname, 0, 0);
+ cli_posix_unlink(cli, sname);
+ cli_setatr(cli, fname, 0, 0);
+ cli_posix_unlink(cli, fname);
+
+ if (!torture_close_connection(cli)) {
+ correct = false;
+ }
+
+ TALLOC_FREE(frame);
+ return correct;
+}
+
+/*
+ Test setting EA's are rejected on symlinks.
+ */
+static bool run_ea_symlink_test(int dummy)
+{
+ static struct cli_state *cli;
+ const char *fname = "posix_file_ea";
+ const char *sname = "posix_symlink_ea";
+ const char *ea_name = "testea_name";
+ const char *ea_value = "testea_value";
+ uint16_t fnum = (uint16_t)-1;
+ bool correct = false;
+ NTSTATUS status;
+ size_t i, num_eas;
+ struct ea_struct *eas = NULL;
+ TALLOC_CTX *frame = NULL;
+
+ frame = talloc_stackframe();
+
+ printf("Starting EA symlink test\n");
+
+ if (!torture_open_connection(&cli, 0)) {
+ TALLOC_FREE(frame);
+ return false;
+ }
+
+ smbXcli_conn_set_sockopt(cli->conn, sockops);
+
+ status = torture_setup_unix_extensions(cli);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(frame);
+ return false;
+ }
+
+ cli_setatr(cli, fname, 0, 0);
+ cli_posix_unlink(cli, fname);
+ cli_setatr(cli, sname, 0, 0);
+ cli_posix_unlink(cli, sname);
+
+ status = cli_ntcreate(cli,
+ fname,
+ 0,
+ READ_CONTROL_ACCESS,
+ 0,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ FILE_CREATE,
+ 0x0,
+ 0x0,
+ &fnum,
+ NULL);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("cli_ntcreate of %s failed (%s)\n",
+ fname,
+ nt_errstr(status));
+ goto out;
+ }
+
+ status = cli_close(cli, fnum);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("close failed (%s)\n",
+ nt_errstr(status));
+ goto out;
+ }
+ fnum = (uint16_t)-1;
+
+ /* Set an EA on the path. */
+ status = cli_set_ea_path(cli,
+ fname,
+ ea_name,
+ ea_value,
+ strlen(ea_value)+1);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("cli_set_ea_path failed (%s)\n",
+ nt_errstr(status));
+ goto out;
+ }
+
+ /* Now create a symlink. */
+ status = cli_posix_symlink(cli, fname, sname);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("cli_posix_symlink of %s -> %s failed (%s)\n",
+ sname,
+ fname,
+ nt_errstr(status));
+ goto out;
+ }
+
+ /* Get the EA list on the path. Should return value set. */
+ status = cli_get_ea_list_path(cli,
+ fname,
+ frame,
+ &num_eas,
+ &eas);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("cli_get_ea_list_path failed (%s)\n",
+ nt_errstr(status));
+ goto out;
+ }
+
+ /* Ensure the EA we set is there. */
+ for (i=0; i<num_eas; i++) {
+ if (strcmp(eas[i].name, ea_name) == 0 &&
+ eas[i].value.length == strlen(ea_value)+1 &&
+ memcmp(eas[i].value.data,
+ ea_value,
+ eas[i].value.length) == 0) {
+ break;
+ }
+ }
+
+ if (i == num_eas) {
+ printf("Didn't find EA on pathname %s\n",
+ fname);
+ goto out;
+ }
+
+ num_eas = 0;
+ TALLOC_FREE(eas);
+
+ /* Get the EA list on the symlink. Should return empty list. */
+ status = cli_get_ea_list_path(cli,
+ sname,
+ frame,
+ &num_eas,
+ &eas);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("cli_get_ea_list_path failed (%s)\n",
+ nt_errstr(status));
+ goto out;
+ }
+
+ if (num_eas != 0) {
+ printf("cli_get_ea_list_path failed (%s)\n",
+ nt_errstr(status));
+ goto out;
+ }
+
+ /* Set an EA on the symlink. Should fail. */
+ status = cli_set_ea_path(cli,
+ sname,
+ ea_name,
+ ea_value,
+ strlen(ea_value)+1);
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+ printf("cli_set_ea_path on a symlink gave %s. "
+ "Should be NT_STATUS_ACCESS_DENIED.\n",
+ nt_errstr(status));
+ goto out;
+ }
+
+ printf("EA symlink test passed\n");
+ correct = true;
+
+ out:
+
+ if (fnum != (uint16_t)-1) {
+ cli_close(cli, fnum);
+ fnum = (uint16_t)-1;
+ }
+
+ cli_setatr(cli, sname, 0, 0);
+ cli_posix_unlink(cli, sname);
+ cli_setatr(cli, fname, 0, 0);
+ cli_posix_unlink(cli, fname);
+
+ if (!torture_close_connection(cli)) {
+ correct = false;
+ }
+
+ TALLOC_FREE(frame);
+ return correct;
+}
static uint32_t open_attrs_table[] = {
FILE_ATTRIBUTE_NORMAL,
@@ -8348,11 +8722,29 @@ static bool rbt_testval(struct db_context *db, const char *key,
return ret;
}
+static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
+{
+ int *count2 = (int *)private_data;
+ (*count2)++;
+ return 0;
+}
+
+static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
+{
+ int *count2 = (int *)private_data;
+ (*count2)++;
+ dbwrap_record_delete(rec);
+ return 0;
+}
+
static bool run_local_rbtree(int dummy)
{
struct db_context *db;
bool ret = false;
int i;
+ NTSTATUS status;
+ int count = 0;
+ int count2 = 0;
db = db_open_rbt(NULL);
@@ -8395,6 +8787,27 @@ static bool run_local_rbtree(int dummy)
}
ret = true;
+ count = 0; count2 = 0;
+ status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
+ &count2, &count);
+ printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
+ if ((count != count2) || (count != 1000)) {
+ ret = false;
+ }
+ count = 0; count2 = 0;
+ status = dbwrap_traverse(db, local_rbtree_traverse_delete,
+ &count2, &count);
+ printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
+ if ((count != count2) || (count != 1000)) {
+ ret = false;
+ }
+ count = 0; count2 = 0;
+ status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
+ &count2, &count);
+ printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
+ if ((count != count2) || (count != 0)) {
+ ret = false;
+ }
done:
TALLOC_FREE(db);
@@ -9604,6 +10017,8 @@ static struct {
{"OPEN", run_opentest, 0},
{"POSIX", run_simple_posix_open_test, 0},
{"POSIX-APPEND", run_posix_append, 0},
+ {"POSIX-SYMLINK-ACL", run_acl_symlink_test, 0},
+ {"POSIX-SYMLINK-EA", run_ea_symlink_test, 0},
{"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
{"ASYNC-ECHO", run_async_echo, 0},
{ "UID-REGRESSION-TEST", run_uid_regression_test, 0},
diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c
index 2596069..d50219c 100644
--- a/source3/utils/smbcacls.c
+++ b/source3/utils/smbcacls.c
@@ -791,7 +791,7 @@ int main(int argc, char *argv[])
poptContext pc;
/* numeric is set when the user wants numeric SIDs and ACEs rather
than going via LSA calls to resolve them */
- int numeric;
+ int numeric = 0;
struct poptOption long_options[] = {
POPT_AUTOHELP
diff --git a/source3/utils/smbget.c b/source3/utils/smbget.c
index c3eb471..127d6b1 100644
--- a/source3/utils/smbget.c
+++ b/source3/utils/smbget.c
@@ -91,10 +91,18 @@ static void human_readable(off_t s, char *buffer, int l)
static void get_auth_data(const char *srv, const char *shr, char *wg, int wglen, char *un, int unlen, char *pw, int pwlen)
{
static char hasasked = 0;
+ static char *savedwg;
+ static char *savedun;
+ static char *savedpw;
char *wgtmp, *usertmp;
char tmp[128];
- if(hasasked) return;
+ if (hasasked) {
+ strncpy(wg, savedwg, wglen - 1);
+ strncpy(un, savedun, unlen - 1);
+ strncpy(pw, savedpw, pwlen - 1);
+ return;
+ }
hasasked = 1;
if(!nonprompt && !username) {
@@ -119,6 +127,11 @@ static void get_auth_data(const char *srv, const char *shr, char *wg, int wglen,
if(workgroup)strncpy(wg, workgroup, wglen-1);
+ /* save the values found for later */
+ savedwg = SMB_STRDUP(wg);
+ savedun = SMB_STRDUP(un);
+ savedpw = SMB_STRDUP(pw);
+
wgtmp = SMB_STRNDUP(wg, wglen);
usertmp = SMB_STRNDUP(un, unlen);
if(!quiet)printf("Using workgroup %s, %s%s\n", wgtmp, *usertmp?"user ":"guest user", usertmp);
diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c
index 78350fd..791b05f 100644
--- a/source3/winbindd/winbindd_ads.c
+++ b/source3/winbindd/winbindd_ads.c
@@ -38,6 +38,7 @@
#define DBGC_CLASS DBGC_WINBIND
extern struct winbindd_methods reconnect_methods;
+extern struct winbindd_methods msrpc_methods;
#define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
@@ -563,9 +564,8 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
struct dom_sid *sid,
enum lsa_SidType *type)
{
- return reconnect_methods.name_to_sid(domain, mem_ctx,
- domain_name, name, flags,
- sid, type);
+ return msrpc_methods.name_to_sid(domain, mem_ctx, domain_name, name,
+ flags, sid, type);
}
/* convert a domain SID to a user or group name - use rpc methods */
@@ -576,8 +576,8 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
char **name,
enum lsa_SidType *type)
{
- return reconnect_methods.sid_to_name(domain, mem_ctx, sid,
- domain_name, name, type);
+ return msrpc_methods.sid_to_name(domain, mem_ctx, sid,
+ domain_name, name, type);
}
/* convert a list of rids to names - use rpc methods */
@@ -590,9 +590,9 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
char ***names,
enum lsa_SidType **types)
{
- return reconnect_methods.rids_to_names(domain, mem_ctx, sid,
- rids, num_rids,
- domain_name, names, types);
+ return msrpc_methods.rids_to_names(domain, mem_ctx, sid,
+ rids, num_rids,
+ domain_name, names, types);
}
/* If you are looking for "dn_lookup": Yes, it used to be here!
@@ -1142,10 +1142,8 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
uint32_t num_sids, const struct dom_sid *sids,
uint32_t *num_aliases, uint32_t **alias_rids)
{
- return reconnect_methods.lookup_useraliases(domain, mem_ctx,
- num_sids, sids,
- num_aliases,
- alias_rids);
+ return msrpc_methods.lookup_useraliases(domain, mem_ctx, num_sids, sids,
+ num_aliases, alias_rids);
}
static NTSTATUS add_primary_group_members(
@@ -1527,7 +1525,7 @@ static NTSTATUS lockout_policy(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
struct samr_DomInfo12 *policy)
{
- return reconnect_methods.lockout_policy(domain, mem_ctx, policy);
+ return msrpc_methods.lockout_policy(domain, mem_ctx, policy);
}
/* find the password policy of a domain - use rpc methods */
@@ -1535,7 +1533,7 @@ static NTSTATUS password_policy(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
struct samr_DomInfo1 *policy)
{
- return reconnect_methods.password_policy(domain, mem_ctx, policy);
+ return msrpc_methods.password_policy(domain, mem_ctx, policy);
}
/* get a list of trusted domains */
diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c
index 4e270ca..3562217 100644
--- a/source3/winbindd/winbindd_cache.c
+++ b/source3/winbindd/winbindd_cache.c
@@ -46,7 +46,7 @@
extern struct winbindd_methods reconnect_methods;
#ifdef HAVE_ADS
-extern struct winbindd_methods ads_methods;
+extern struct winbindd_methods reconnect_ads_methods;
#endif
extern struct winbindd_methods builtin_passdb_methods;
extern struct winbindd_methods sam_passdb_methods;
@@ -168,7 +168,7 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain)
&& domain->active_directory
&& !lp_winbind_rpc_only()) {
DEBUG(5,("get_cache: Setting ADS methods for domain %s\n", domain->name));
- domain->backend = &ads_methods;
+ domain->backend = &reconnect_ads_methods;
} else {
#endif /* HAVE_ADS */
DEBUG(5,("get_cache: Setting MS-RPC methods for domain %s\n", domain->name));
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index 842307f..1964fcff 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -2683,6 +2683,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
NTSTATUS status, result;
struct netlogon_creds_cli_context *p_creds;
struct cli_credentials *creds = NULL;
+ bool retry = false; /* allow one retry attempt for expired session */
if (sid_check_is_our_sam(&domain->sid)) {
if (domain->rodc == false || need_rw_dc == false) {
@@ -2690,6 +2691,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
}
}
+retry:
status = init_dc_connection_rpc(domain, need_rw_dc);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -2733,6 +2735,14 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
smbXcli_conn_remote_name(conn->cli->conn),
creds,
&conn->samr_pipe);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
+ && !retry) {
+ invalidate_cm_connection(domain);
+ retry = true;
+ goto retry;
+ }
+
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
"pipe for domain %s using NTLMSSP "
@@ -2753,6 +2763,14 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
SEC_FLAG_MAXIMUM_ALLOWED,
&conn->sam_connect_handle,
&result);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
+ invalidate_cm_connection(domain);
+ TALLOC_FREE(conn->samr_pipe);
+ retry = true;
+ goto retry;
+ }
+
if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
goto open_domain;
}
@@ -2790,6 +2808,13 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
(conn->cli, &ndr_table_samr, NCACN_NP,
creds, p_creds, &conn->samr_pipe);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
+ && !retry) {
+ invalidate_cm_connection(domain);
+ retry = true;
+ goto retry;
+ }
+
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
"domain %s using schannel. Error was %s\n",
@@ -2804,6 +2829,14 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
SEC_FLAG_MAXIMUM_ALLOWED,
&conn->sam_connect_handle,
&result);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
+ invalidate_cm_connection(domain);
+ TALLOC_FREE(conn->samr_pipe);
+ retry = true;
+ goto retry;
+ }
+
if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
goto open_domain;
}
@@ -2830,6 +2863,13 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
&conn->samr_pipe);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
+ && !retry) {
+ invalidate_cm_connection(domain);
+ retry = true;
+ goto retry;
+ }
+
if (!NT_STATUS_IS_OK(status)) {
goto done;
}
@@ -2839,6 +2879,14 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
SEC_FLAG_MAXIMUM_ALLOWED,
&conn->sam_connect_handle,
&result);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
+ invalidate_cm_connection(domain);
+ TALLOC_FREE(conn->samr_pipe);
+ retry = true;
+ goto retry;
+ }
+
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
"for domain %s Error was %s\n",
@@ -2960,7 +3008,9 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
struct netlogon_creds_cli_context *p_creds;
struct cli_credentials *creds = NULL;
+ bool retry = false; /* allow one retry attempt for expired session */
+retry:
result = init_dc_connection_rpc(domain, false);
if (!NT_STATUS_IS_OK(result))
return result;
@@ -2995,6 +3045,14 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
smbXcli_conn_remote_name(conn->cli->conn),
creds,
&conn->lsa_pipe);
+
+ if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
+ && !retry) {
+ invalidate_cm_connection(domain);
+ retry = true;
+ goto retry;
+ }
+
if (!NT_STATUS_IS_OK(result)) {
DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
"domain %s using NTLMSSP authenticated pipe: user "
@@ -3012,6 +3070,13 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
SEC_FLAG_MAXIMUM_ALLOWED,
&conn->lsa_policy);
+ if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
+ invalidate_cm_connection(domain);
+ TALLOC_FREE(conn->lsa_pipe);
+ retry = true;
+ goto retry;
+ }
+
if (NT_STATUS_IS_OK(result)) {
goto done;
}
@@ -3047,6 +3112,13 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
(conn->cli, &ndr_table_lsarpc, NCACN_NP,
creds, p_creds, &conn->lsa_pipe);
+ if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
+ && !retry) {
+ invalidate_cm_connection(domain);
+ retry = true;
+ goto retry;
+ }
+
if (!NT_STATUS_IS_OK(result)) {
DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
"domain %s using schannel. Error was %s\n",
@@ -3059,6 +3131,14 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
SEC_FLAG_MAXIMUM_ALLOWED,
&conn->lsa_policy);
+
+ if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
+ invalidate_cm_connection(domain);
+ TALLOC_FREE(conn->lsa_pipe);
+ retry = true;
+ goto retry;
+ }
+
if (NT_STATUS_IS_OK(result)) {
goto done;
}
@@ -3083,6 +3163,14 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
result = cli_rpc_pipe_open_noauth(conn->cli,
&ndr_table_lsarpc,
&conn->lsa_pipe);
+
+ if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
+ && !retry) {
+ invalidate_cm_connection(domain);
+ retry = true;
+ goto retry;
+ }
+
if (!NT_STATUS_IS_OK(result)) {
goto done;
}
@@ -3090,6 +3178,14 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
SEC_FLAG_MAXIMUM_ALLOWED,
&conn->lsa_policy);
+
+ if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
+ invalidate_cm_connection(domain);
+ TALLOC_FREE(conn->lsa_pipe);
+ retry = true;
+ goto retry;
+ }
+
done:
if (!NT_STATUS_IS_OK(result)) {
invalidate_cm_connection(domain);
@@ -3312,6 +3408,14 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
}
status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
+ /*
+ * SMB2 session expired, needs reauthentication. Drop
+ * connection and retry.
+ */
+ invalidate_cm_connection(domain);
+ status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
+ }
return status;
}
diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
index 44e4842..cdd9bbd 100644
--- a/source3/winbindd/winbindd_dual_srv.c
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -741,14 +741,6 @@ NTSTATUS _wbint_PingDc(struct pipes_struct *p, struct wbint_PingDc *r)
reconnect:
status = cm_connect_netlogon(domain, &netlogon_pipe);
- if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
- /*
- * Retry to open new connection with new kerberos ticket.
- */
- invalidate_cm_connection(domain);
- status = cm_connect_netlogon(domain, &netlogon_pipe);
- }
-
reset_cm_connection_on_error(domain, status);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n",
diff --git a/source3/winbindd/winbindd_ndr.c b/source3/winbindd/winbindd_ndr.c
index 37b7e02..029e883 100644
--- a/source3/winbindd/winbindd_ndr.c
+++ b/source3/winbindd/winbindd_ndr.c
@@ -75,6 +75,7 @@ void ndr_print_winbindd_cm_conn(struct ndr_print *ndr,
#ifdef HAVE_ADS
extern struct winbindd_methods ads_methods;
+extern struct winbindd_methods reconnect_ads_methods;
#endif
extern struct winbindd_methods msrpc_methods;
extern struct winbindd_methods builtin_passdb_methods;
@@ -100,6 +101,8 @@ void ndr_print_winbindd_methods(struct ndr_print *ndr,
#ifdef HAVE_ADS
} else if (r == &ads_methods) {
ndr_print_string(ndr, name, "ads_methods");
+ } else if (r == &reconnect_ads_methods) {
+ ndr_print_string(ndr, name, "reconnect_ads_methods");
#endif
} else if (r == &builtin_passdb_methods) {
ndr_print_string(ndr, name, "builtin_passdb_methods");
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 9920a3f..6e50718 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -933,4 +933,8 @@ ADS_STATUS ads_idmap_cached_connection(ADS_STRUCT **adsp, const char *dom_name);
/* The following definitions come from winbindd/winbindd_irpc.c */
NTSTATUS wb_irpc_register(void);
+
+/* The following definitions come from winbindd/winbindd_reconnect.c */
+bool reconnect_need_retry(NTSTATUS status, struct winbindd_domain *domain);
+
#endif /* _WINBINDD_PROTO_H_ */
diff --git a/source3/winbindd/winbindd_reconnect.c b/source3/winbindd/winbindd_reconnect.c
index e45f9b1..f7dd805 100644
--- a/source3/winbindd/winbindd_reconnect.c
+++ b/source3/winbindd/winbindd_reconnect.c
@@ -27,7 +27,7 @@
extern struct winbindd_methods msrpc_methods;
-static bool reconnect_need_retry(NTSTATUS status)
+bool reconnect_need_retry(NTSTATUS status, struct winbindd_domain *domain)
{
if (NT_STATUS_IS_OK(status)) {
return false;
@@ -69,6 +69,14 @@ static bool reconnect_need_retry(NTSTATUS status)
return false;
}
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR)) {
+ /*
+ * RPC call sent on expired session, needs
+ * reauthentication.
+ */
+ invalidate_cm_connection(domain);
+ }
+
return true;
}
@@ -83,7 +91,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
result = msrpc_methods.query_user_list(domain, mem_ctx,
num_entries, info);
- if (reconnect_need_retry(result))
+ if (reconnect_need_retry(result, domain))
result = msrpc_methods.query_user_list(domain, mem_ctx,
num_entries, info);
return result;
@@ -100,7 +108,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
result = msrpc_methods.enum_dom_groups(domain, mem_ctx,
num_entries, info);
- if (reconnect_need_retry(result))
+ if (reconnect_need_retry(result, domain))
result = msrpc_methods.enum_dom_groups(domain, mem_ctx,
num_entries, info);
return result;
@@ -118,7 +126,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
result = msrpc_methods.enum_local_groups(domain, mem_ctx,
num_entries, info);
- if (reconnect_need_retry(result))
+ if (reconnect_need_retry(result, domain))
result = msrpc_methods.enum_local_groups(domain, mem_ctx,
num_entries, info);
@@ -139,7 +147,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
result = msrpc_methods.name_to_sid(domain, mem_ctx, domain_name, name,
flags, sid, type);
- if (reconnect_need_retry(result))
+ if (reconnect_need_retry(result, domain))
result = msrpc_methods.name_to_sid(domain, mem_ctx,
domain_name, name, flags,
sid, type);
@@ -162,7 +170,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
result = msrpc_methods.sid_to_name(domain, mem_ctx, sid,
domain_name, name, type);
- if (reconnect_need_retry(result))
+ if (reconnect_need_retry(result, domain))
result = msrpc_methods.sid_to_name(domain, mem_ctx, sid,
domain_name, name, type);
@@ -183,7 +191,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
result = msrpc_methods.rids_to_names(domain, mem_ctx, sid,
rids, num_rids,
domain_name, names, types);
- if (reconnect_need_retry(result)) {
+ if (reconnect_need_retry(result, domain)) {
result = msrpc_methods.rids_to_names(domain, mem_ctx, sid,
rids, num_rids,
domain_name, names,
@@ -204,7 +212,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
result = msrpc_methods.query_user(domain, mem_ctx, user_sid,
user_info);
- if (reconnect_need_retry(result))
+ if (reconnect_need_retry(result, domain))
result = msrpc_methods.query_user(domain, mem_ctx, user_sid,
user_info);
@@ -223,7 +231,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
user_sid, num_groups,
user_gids);
- if (reconnect_need_retry(result))
+ if (reconnect_need_retry(result, domain))
result = msrpc_methods.lookup_usergroups(domain, mem_ctx,
user_sid, num_groups,
user_gids);
@@ -243,7 +251,7 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
num_aliases,
alias_rids);
- if (reconnect_need_retry(result))
+ if (reconnect_need_retry(result, domain))
result = msrpc_methods.lookup_useraliases(domain, mem_ctx,
num_sids, sids,
num_aliases,
@@ -268,7 +276,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
sid_mem, names,
name_types);
- if (reconnect_need_retry(result))
+ if (reconnect_need_retry(result, domain))
result = msrpc_methods.lookup_groupmem(domain, mem_ctx,
group_sid, type,
num_names,
@@ -285,7 +293,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32_t *seq)
result = msrpc_methods.sequence_number(domain, seq);
- if (reconnect_need_retry(result))
+ if (reconnect_need_retry(result, domain))
result = msrpc_methods.sequence_number(domain, seq);
return result;
@@ -300,7 +308,7 @@ static NTSTATUS lockout_policy(struct winbindd_domain *domain,
result = msrpc_methods.lockout_policy(domain, mem_ctx, policy);
- if (reconnect_need_retry(result))
+ if (reconnect_need_retry(result, domain))
result = msrpc_methods.lockout_policy(domain, mem_ctx, policy);
return result;
@@ -315,7 +323,7 @@ static NTSTATUS password_policy(struct winbindd_domain *domain,
result = msrpc_methods.password_policy(domain, mem_ctx, policy);
- if (reconnect_need_retry(result))
+ if (reconnect_need_retry(result, domain))
result = msrpc_methods.password_policy(domain, mem_ctx, policy);
return result;
@@ -330,7 +338,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
result = msrpc_methods.trusted_domains(domain, mem_ctx, trusts);
- if (reconnect_need_retry(result))
+ if (reconnect_need_retry(result, domain))
result = msrpc_methods.trusted_domains(domain, mem_ctx,
trusts);
diff --git a/source3/winbindd/winbindd_reconnect.c b/source3/winbindd/winbindd_reconnect_ads.c
similarity index 50%
copy from source3/winbindd/winbindd_reconnect.c
copy to source3/winbindd/winbindd_reconnect_ads.c
index e45f9b1..7ea8298 100644
--- a/source3/winbindd/winbindd_reconnect.c
+++ b/source3/winbindd/winbindd_reconnect_ads.c
@@ -1,20 +1,22 @@
-/*
+/*
Unix SMB/CIFS implementation.
- Wrapper around winbindd_rpc.c to centralize retry logic.
+ Wrapper around winbindd_ads.c to centralize retry logic.
+ Copyright (C) Christof Schmitt 2016
+ Based on winbindd_reconnect.c
Copyright (C) Volker Lendecke 2005
-
+
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
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -22,55 +24,12 @@
#include "includes.h"
#include "winbindd.h"
+#ifdef HAVE_ADS
+
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
-extern struct winbindd_methods msrpc_methods;
-
-static bool reconnect_need_retry(NTSTATUS status)
-{
- if (NT_STATUS_IS_OK(status)) {
- return false;
- }
-
- if (!NT_STATUS_IS_ERR(status)) {
- return false;
- }
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
- return false;
- }
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
- return false;
- }
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_GROUP)) {
- return false;
- }
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_ALIAS)) {
- return false;
- }
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_MEMBER)) {
- return false;
- }
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN)) {
- return false;
- }
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_PRIVILEGE)) {
- return false;
- }
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
- return false;
- }
-
- return true;
-}
+extern struct winbindd_methods ads_methods;
/* List all users */
static NTSTATUS query_user_list(struct winbindd_domain *domain,
@@ -80,12 +39,14 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
{
NTSTATUS result;
- result = msrpc_methods.query_user_list(domain, mem_ctx,
- num_entries, info);
+ result = ads_methods.query_user_list(domain, mem_ctx,
+ num_entries, info);
+
+ if (reconnect_need_retry(result, domain)) {
+ result = ads_methods.query_user_list(domain, mem_ctx,
+ num_entries, info);
+ }
- if (reconnect_need_retry(result))
- result = msrpc_methods.query_user_list(domain, mem_ctx,
- num_entries, info);
return result;
}
@@ -97,17 +58,18 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
{
NTSTATUS result;
- result = msrpc_methods.enum_dom_groups(domain, mem_ctx,
- num_entries, info);
+ result = ads_methods.enum_dom_groups(domain, mem_ctx,
+ num_entries, info);
+
+ if (reconnect_need_retry(result, domain)) {
+ result = ads_methods.enum_dom_groups(domain, mem_ctx,
+ num_entries, info);
+ }
- if (reconnect_need_retry(result))
- result = msrpc_methods.enum_dom_groups(domain, mem_ctx,
- num_entries, info);
return result;
}
/* List all domain groups */
-
static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32_t *num_entries,
@@ -115,12 +77,13 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
{
NTSTATUS result;
- result = msrpc_methods.enum_local_groups(domain, mem_ctx,
- num_entries, info);
+ result = ads_methods.enum_local_groups(domain, mem_ctx,
+ num_entries, info);
- if (reconnect_need_retry(result))
- result = msrpc_methods.enum_local_groups(domain, mem_ctx,
- num_entries, info);
+ if (reconnect_need_retry(result, domain)) {
+ result = ads_methods.enum_local_groups(domain, mem_ctx,
+ num_entries, info);
+ }
return result;
}
@@ -136,13 +99,14 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
{
NTSTATUS result;
- result = msrpc_methods.name_to_sid(domain, mem_ctx, domain_name, name,
- flags, sid, type);
+ result = ads_methods.name_to_sid(domain, mem_ctx, domain_name, name,
+ flags, sid, type);
- if (reconnect_need_retry(result))
- result = msrpc_methods.name_to_sid(domain, mem_ctx,
- domain_name, name, flags,
- sid, type);
+ if (reconnect_need_retry(result, domain)) {
+ result = ads_methods.name_to_sid(domain, mem_ctx,
+ domain_name, name, flags,
+ sid, type);
+ }
return result;
}
@@ -159,12 +123,12 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
{
NTSTATUS result;
- result = msrpc_methods.sid_to_name(domain, mem_ctx, sid,
- domain_name, name, type);
+ result = ads_methods.sid_to_name(domain, mem_ctx, sid,
+ domain_name, name, type);
- if (reconnect_need_retry(result))
- result = msrpc_methods.sid_to_name(domain, mem_ctx, sid,
- domain_name, name, type);
+ if (reconnect_need_retry(result, domain))
+ result = ads_methods.sid_to_name(domain, mem_ctx, sid,
+ domain_name, name, type);
return result;
}
@@ -180,33 +144,32 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
{
NTSTATUS result;
- result = msrpc_methods.rids_to_names(domain, mem_ctx, sid,
- rids, num_rids,
- domain_name, names, types);
- if (reconnect_need_retry(result)) {
- result = msrpc_methods.rids_to_names(domain, mem_ctx, sid,
- rids, num_rids,
- domain_name, names,
- types);
+ result = ads_methods.rids_to_names(domain, mem_ctx, sid,
+ rids, num_rids,
+ domain_name, names, types);
+ if (reconnect_need_retry(result, domain)) {
+ result = ads_methods.rids_to_names(domain, mem_ctx, sid,
+ rids, num_rids, domain_name,
+ names, types);
}
return result;
}
/* Lookup user information from a rid or username. */
-static NTSTATUS query_user(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
+static NTSTATUS query_user(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
const struct dom_sid *user_sid,
struct wbint_userinfo *user_info)
{
NTSTATUS result;
- result = msrpc_methods.query_user(domain, mem_ctx, user_sid,
- user_info);
+ result = ads_methods.query_user(domain, mem_ctx, user_sid, user_info);
- if (reconnect_need_retry(result))
- result = msrpc_methods.query_user(domain, mem_ctx, user_sid,
- user_info);
+ if (reconnect_need_retry(result, domain)) {
+ result = ads_methods.query_user(domain, mem_ctx, user_sid,
+ user_info);
+ }
return result;
}
@@ -215,39 +178,40 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const struct dom_sid *user_sid,
- uint32_t *num_groups, struct dom_sid **user_gids)
+ uint32_t *num_groups,
+ struct dom_sid **user_gids)
{
NTSTATUS result;
- result = msrpc_methods.lookup_usergroups(domain, mem_ctx,
- user_sid, num_groups,
- user_gids);
+ result = ads_methods.lookup_usergroups(domain, mem_ctx, user_sid,
+ num_groups, user_gids);
- if (reconnect_need_retry(result))
- result = msrpc_methods.lookup_usergroups(domain, mem_ctx,
- user_sid, num_groups,
- user_gids);
+ if (reconnect_need_retry(result, domain)) {
+ result = ads_methods.lookup_usergroups(domain, mem_ctx,
+ user_sid, num_groups,
+ user_gids);
+ }
return result;
}
static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- uint32_t num_sids, const struct dom_sid *sids,
+ uint32_t num_sids,
+ const struct dom_sid *sids,
uint32_t *num_aliases, uint32_t **alias_rids)
{
NTSTATUS result;
- result = msrpc_methods.lookup_useraliases(domain, mem_ctx,
- num_sids, sids,
- num_aliases,
- alias_rids);
+ result = ads_methods.lookup_useraliases(domain, mem_ctx, num_sids, sids,
+ num_aliases, alias_rids);
- if (reconnect_need_retry(result))
- result = msrpc_methods.lookup_useraliases(domain, mem_ctx,
- num_sids, sids,
- num_aliases,
- alias_rids);
+ if (reconnect_need_retry(result, domain)) {
+ result = ads_methods.lookup_useraliases(domain, mem_ctx,
+ num_sids, sids,
+ num_aliases,
+ alias_rids);
+ }
return result;
}
@@ -263,17 +227,15 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
{
NTSTATUS result;
- result = msrpc_methods.lookup_groupmem(domain, mem_ctx,
- group_sid, type, num_names,
- sid_mem, names,
- name_types);
+ result = ads_methods.lookup_groupmem(domain, mem_ctx, group_sid, type,
+ num_names, sid_mem, names,
+ name_types);
- if (reconnect_need_retry(result))
- result = msrpc_methods.lookup_groupmem(domain, mem_ctx,
- group_sid, type,
- num_names,
- sid_mem, names,
- name_types);
+ if (reconnect_need_retry(result, domain)) {
+ result = ads_methods.lookup_groupmem(domain, mem_ctx, group_sid,
+ type, num_names, sid_mem,
+ names, name_types);
+ }
return result;
}
@@ -283,41 +245,44 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32_t *seq)
{
NTSTATUS result;
- result = msrpc_methods.sequence_number(domain, seq);
+ result = ads_methods.sequence_number(domain, seq);
- if (reconnect_need_retry(result))
- result = msrpc_methods.sequence_number(domain, seq);
+ if (reconnect_need_retry(result, domain)) {
+ result = ads_methods.sequence_number(domain, seq);
+ }
return result;
}
/* find the lockout policy of a domain */
-static NTSTATUS lockout_policy(struct winbindd_domain *domain,
+static NTSTATUS lockout_policy(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
struct samr_DomInfo12 *policy)
{
NTSTATUS result;
- result = msrpc_methods.lockout_policy(domain, mem_ctx, policy);
+ result = ads_methods.lockout_policy(domain, mem_ctx, policy);
- if (reconnect_need_retry(result))
- result = msrpc_methods.lockout_policy(domain, mem_ctx, policy);
+ if (reconnect_need_retry(result, domain)) {
+ result = ads_methods.lockout_policy(domain, mem_ctx, policy);
+ }
return result;
}
/* find the password policy of a domain */
-static NTSTATUS password_policy(struct winbindd_domain *domain,
+static NTSTATUS password_policy(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
struct samr_DomInfo1 *policy)
{
- NTSTATUS result;
-
- result = msrpc_methods.password_policy(domain, mem_ctx, policy);
+ NTSTATUS result;
+
+ result = ads_methods.password_policy(domain, mem_ctx, policy);
+
+ if (reconnect_need_retry(result, domain)) {
+ result = ads_methods.password_policy(domain, mem_ctx, policy);
+ }
- if (reconnect_need_retry(result))
- result = msrpc_methods.password_policy(domain, mem_ctx, policy);
-
return result;
}
@@ -328,18 +293,18 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
{
NTSTATUS result;
- result = msrpc_methods.trusted_domains(domain, mem_ctx, trusts);
+ result = ads_methods.trusted_domains(domain, mem_ctx, trusts);
- if (reconnect_need_retry(result))
- result = msrpc_methods.trusted_domains(domain, mem_ctx,
- trusts);
+ if (reconnect_need_retry(result, domain)) {
+ result = ads_methods.trusted_domains(domain, mem_ctx, trusts);
+ }
return result;
}
/* the rpc backend methods are exposed via this structure */
-struct winbindd_methods reconnect_methods = {
- False,
+struct winbindd_methods reconnect_ads_methods = {
+ true,
query_user_list,
enum_dom_groups,
enum_local_groups,
@@ -355,3 +320,5 @@ struct winbindd_methods reconnect_methods = {
password_policy,
trusted_domains,
};
+
+#endif
diff --git a/source3/wscript_build b/source3/wscript_build
index ace4b99..ba670d3 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -908,6 +908,7 @@ bld.SAMBA3_BINARY('winbindd/winbindd',
winbindd/winbindd_msrpc.c
winbindd/winbindd_rpc.c
winbindd/winbindd_reconnect.c
+ winbindd/winbindd_reconnect_ads.c
winbindd/winbindd_ads.c
winbindd/winbindd_samr.c
winbindd/winbindd_dual.c
@@ -1185,6 +1186,14 @@ bld.SAMBA3_BINARY('smbspool',
libsmb
samba3core''')
+bld.SAMBA3_BINARY('smbspool_krb5_wrapper',
+ source='client/smbspool_krb5_wrapper.c',
+ deps='''
+ DYNCONFIG
+ cups
+ ''',
+ enabled=bld.CONFIG_SET('HAVE_CUPS'))
+
bld.SAMBA3_BINARY('testparm',
source='utils/testparm.c',
deps='''
diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c
index 17f3cfc..43c7a3d 100644
--- a/source4/auth/ntlm/auth_sam.c
+++ b/source4/auth/ntlm/auth_sam.c
@@ -294,6 +294,7 @@ static NTSTATUS authsam_password_check_and_record(struct auth4_context *auth_con
struct samr_Password *nt_history_pwd = NULL;
struct samr_Password *lm_history_pwd = NULL;
NTTIME pwdLastSet;
+ struct timeval tv_now;
NTTIME now;
int allowed_period_mins;
NTTIME allowed_period;
@@ -414,7 +415,8 @@ static NTSTATUS authsam_password_check_and_record(struct auth4_context *auth_con
*/
allowed_period = allowed_period_mins * 60 * 1000*1000*10;
pwdLastSet = samdb_result_nttime(msg, "pwdLastSet", 0);
- unix_to_nt_time(&now, time(NULL));
+ tv_now = timeval_current();
+ now = timeval_to_nttime(&tv_now);
if (now < pwdLastSet) {
/*
@@ -491,6 +493,7 @@ static NTSTATUS authsam_authenticate(struct auth4_context *auth_context,
DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key)
{
NTSTATUS nt_status;
+ bool interactive = (user_info->password_state == AUTH_PASSWORD_HASH);
uint16_t acct_flags = samdb_result_acct_flags(msg, NULL);
TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
if (!tmp_ctx) {
@@ -526,7 +529,9 @@ static NTSTATUS authsam_authenticate(struct auth4_context *auth_context,
return nt_status;
}
- nt_status = authsam_zero_bad_pwd_count(auth_context->sam_ctx, msg);
+ nt_status = authsam_logon_success_accounting(auth_context->sam_ctx,
+ msg, domain_dn,
+ interactive);
if (!NT_STATUS_IS_OK(nt_status)) {
TALLOC_FREE(tmp_ctx);
return nt_status;
diff --git a/source4/auth/sam.c b/source4/auth/sam.c
index f7bc693..cdfe8dd 100644
--- a/source4/auth/sam.c
+++ b/source4/auth/sam.c
@@ -83,6 +83,7 @@ const char *user_attrs[] = {
"homeDirectory",
"homeDrive",
"lastLogon",
+ "lastLogonTimestamp",
"lastLogoff",
"accountExpires",
"badPwdCount",
@@ -691,20 +692,132 @@ NTSTATUS authsam_update_bad_pwd_count(struct ldb_context *sam_ctx,
return NT_STATUS_OK;
}
-NTSTATUS authsam_zero_bad_pwd_count(struct ldb_context *sam_ctx,
- const struct ldb_message *msg)
+
+static NTSTATUS authsam_update_lastlogon_timestamp(struct ldb_context *sam_ctx,
+ struct ldb_message *msg_mod,
+ struct ldb_dn *domain_dn,
+ NTTIME old_timestamp,
+ NTTIME now)
+{
+ /*
+ * We only set lastLogonTimestamp if the current value is older than
+ * now - msDS-LogonTimeSyncInterval days.
+ *
+ * msDS-LogonTimeSyncInterval is an int32_t number of days, while
+ * lastLogonTimestamp is in the 64 bit 100ns NTTIME format.
+ *
+ * The docs say: "the initial update, after the domain functional
+ * level is raised to DS_BEHAVIOR_WIN2003 or higher, is calculated as
+ * 14 days minus a random percentage of 5 days", but we aren't doing
+ * that. The blogosphere seems to think that this randomised update
+ * happens everytime, but [MS-ADA1] doesn't agree.
+ *
+ * Dochelp referred us to the following blog post:
+ * http://blogs.technet.com/b/askds/archive/2009/04/15/the-lastlogontimestamp-attribute-what-it-was-designed-for-and-how-it-works.aspx
+ *
+ * en msDS-LogonTimeSyncInterval is zero, the lastLogonTimestamp is
+ * not changed.
+ */
+ static const char *attrs[] = { "msDS-LogonTimeSyncInterval",
+ NULL };
+ int ret;
+ struct ldb_result *domain_res = NULL;
+ TALLOC_CTX *mem_ctx = NULL;
+ int32_t sync_interval;
+ NTTIME sync_interval_nt;
+
+ mem_ctx = talloc_new(msg_mod);
+ if (mem_ctx == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = dsdb_search_dn(sam_ctx, mem_ctx, &domain_res, domain_dn, attrs,
+ 0);
+ if (ret != LDB_SUCCESS || domain_res->count != 1) {
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ sync_interval = ldb_msg_find_attr_as_int(domain_res->msgs[0],
+ "msDS-LogonTimeSyncInterval",
+ 14);
+ DEBUG(5, ("sync interval is %d\n", sync_interval));
+ if (sync_interval == 0){
+ /*
+ * Setting msDS-LogonTimeSyncInterval to zero is how you ask
+ * that nothing happens here.
+ */
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_OK;
+ }
+ else if (sync_interval >= 5){
+ /*
+ * Subtract "a random percentage of 5" days. Presumably this
+ * percentage is between 0 and 100, and modulus is accurate
+ * enough.
+ */
+ uint32_t r = generate_random() % 6;
+ sync_interval -= r;
+ DEBUG(5, ("randomised sync interval is %d (-%d)\n", sync_interval, r));
+ }
+ /* In the case where sync_interval < 5 there is no randomisation */
+
+ sync_interval_nt = sync_interval * 24LL * 3600LL * 10000000LL;
+
+ DEBUG(5, ("old timestamp is %lld, threshold %lld, diff %lld\n",
+ (long long int)old_timestamp,
+ (long long int)(now - sync_interval_nt),
+ (long long int)(old_timestamp - now + sync_interval_nt)));
+
+ if (old_timestamp > now){
+ DEBUG(0, ("lastLogonTimestamp is in the future! (%lld > %lld)\n",
+ (long long int)old_timestamp, (long long int)now));
+ /* then what? */
+
+ } else if (old_timestamp < now - sync_interval_nt){
+ DEBUG(5, ("updating lastLogonTimestamp to %lld\n",
+ (long long int)now));
+
+ /* The time has come to update lastLogonTimestamp */
+ ret = samdb_msg_add_int64(sam_ctx, msg_mod, msg_mod,
+ "lastLogonTimestamp", now);
+
+ if (ret != LDB_SUCCESS) {
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_OK;
+}
+
+
+
+/* Reset the badPwdCount to zero and update the lastLogon time. */
+NTSTATUS authsam_logon_success_accounting(struct ldb_context *sam_ctx,
+ const struct ldb_message *msg,
+ struct ldb_dn *domain_dn,
+ bool interactive_or_kerberos)
{
int ret;
+ NTSTATUS status;
int badPwdCount;
int64_t lockoutTime;
struct ldb_message *msg_mod;
TALLOC_CTX *mem_ctx;
+ struct timeval tv_now;
+ NTTIME now;
+ NTTIME lastLogonTimestamp;
+ NTTIME lastLogon;
lockoutTime = ldb_msg_find_attr_as_int64(msg, "lockoutTime", 0);
badPwdCount = ldb_msg_find_attr_as_int(msg, "badPwdCount", 0);
- if (lockoutTime == 0 && badPwdCount == 0) {
- return NT_STATUS_OK;
- }
+ lastLogonTimestamp = \
+ ldb_msg_find_attr_as_int64(msg, "lastLogonTimestamp", 0);
+ lastLogon = ldb_msg_find_attr_as_int64(msg, "lastLogon", 0);
+
+ DEBUG(5, ("lastLogonTimestamp is %lld\n",
+ (long long int)lastLogonTimestamp));
mem_ctx = talloc_new(msg);
if (mem_ctx == NULL) {
@@ -726,7 +839,7 @@ NTSTATUS authsam_zero_bad_pwd_count(struct ldb_context *sam_ctx,
TALLOC_FREE(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
- } else {
+ } else if (badPwdCount != 0) {
ret = samdb_msg_add_int(sam_ctx, msg_mod, msg_mod, "badPwdCount", 0);
if (ret != LDB_SUCCESS) {
TALLOC_FREE(mem_ctx);
@@ -734,14 +847,37 @@ NTSTATUS authsam_zero_bad_pwd_count(struct ldb_context *sam_ctx,
}
}
- ret = dsdb_replace(sam_ctx, msg_mod, 0);
- if (ret != LDB_SUCCESS) {
- DEBUG(0, ("Failed to set badPwdCount and lockoutTime to 0 on %s: %s\n",
- ldb_dn_get_linearized(msg_mod->dn), ldb_errstring(sam_ctx)));
+ tv_now = timeval_current();
+ now = timeval_to_nttime(&tv_now);
+
+ if (interactive_or_kerberos || lastLogon == 0 ||
+ (badPwdCount != 0 && lockoutTime == 0)) {
+ ret = samdb_msg_add_int64(sam_ctx, msg_mod, msg_mod,
+ "lastLogon", now);
+ if (ret != LDB_SUCCESS) {
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+ status = authsam_update_lastlogon_timestamp(sam_ctx, msg_mod, domain_dn,
+ lastLogonTimestamp, now);
+ if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(mem_ctx);
- return NT_STATUS_INTERNAL_ERROR;
+ return NT_STATUS_NO_MEMORY;
}
+ if (msg_mod->num_elements > 0) {
+ ret = dsdb_replace(sam_ctx, msg_mod, 0);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("Failed to set badPwdCount and lockoutTime "
+ "to 0 and/or lastlogon to now (%lld) "
+ "%s: %s\n", (long long int)now,
+ ldb_dn_get_linearized(msg_mod->dn),
+ ldb_errstring(sam_ctx)));
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ }
TALLOC_FREE(mem_ctx);
return NT_STATUS_OK;
}
diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c
index 4e3c6cc..9e30b71 100644
--- a/source4/dns_server/dns_query.c
+++ b/source4/dns_server/dns_query.c
@@ -46,8 +46,7 @@ static WERROR create_response_rr(const struct dns_name_question *question,
{
struct dns_res_rec *ans = *answers;
uint16_t ai = *ancount;
- char *tmp;
- uint32_t i;
+ enum ndr_err_code ndr_err;
ZERO_STRUCT(ans[ai]);
@@ -101,14 +100,12 @@ static WERROR create_response_rr(const struct dns_name_question *question,
}
break;
case DNS_QTYPE_TXT:
- tmp = talloc_asprintf(ans, "\"%s\"", rec->data.txt.str[0]);
- W_ERROR_HAVE_NO_MEMORY(tmp);
- for (i=1; i<rec->data.txt.count; i++) {
- tmp = talloc_asprintf_append_buffer(
- tmp, " \"%s\"", rec->data.txt.str[i]);
- W_ERROR_HAVE_NO_MEMORY(tmp);
+ ndr_err = ndr_dnsp_string_list_copy(ans,
+ &rec->data.txt,
+ &ans[ai].rdata.txt_record.txt);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return WERR_NOMEM;
}
- ans[ai].rdata.txt_record.txt = tmp;
break;
default:
DEBUG(0, ("Got unhandled type %u query.\n", rec->wType));
diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c
index c002b4d..60a4b36 100644
--- a/source4/dns_server/dns_update.c
+++ b/source4/dns_server/dns_update.c
@@ -299,9 +299,7 @@ static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx,
const struct dns_res_rec *rrec,
struct dnsp_DnssrvRpcRecord *r)
{
- char *tmp;
- char *txt_record_txt;
- char *saveptr = NULL;
+ enum ndr_err_code ndr_err;
if (rrec->rr_type == DNS_QTYPE_ALL) {
return DNS_ERR(FORMAT_ERROR);
@@ -354,28 +352,11 @@ static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx,
W_ERROR_HAVE_NO_MEMORY(r->data.mx.nameTarget);
break;
case DNS_QTYPE_TXT:
- r->data.txt.count = 0;
- r->data.txt.str = talloc_array(mem_ctx, const char *,
- r->data.txt.count);
- W_ERROR_HAVE_NO_MEMORY(r->data.txt.str);
-
- txt_record_txt = talloc_strdup(r->data.txt.str,
- rrec->rdata.txt_record.txt);
- W_ERROR_HAVE_NO_MEMORY(txt_record_txt);
-
- tmp = strtok_r(txt_record_txt, "\"", &saveptr);
- while (tmp) {
- if (strcmp(tmp, " ") == 0) {
- tmp = strtok_r(NULL, "\"", &saveptr);
- continue;
- }
- r->data.txt.str = talloc_realloc(mem_ctx, r->data.txt.str, const char *,
- r->data.txt.count+1);
- r->data.txt.str[r->data.txt.count] = talloc_strdup(r->data.txt.str, tmp);
- W_ERROR_HAVE_NO_MEMORY(r->data.txt.str[r->data.txt.count]);
-
- r->data.txt.count++;
- tmp = strtok_r(NULL, "\"", &saveptr);
+ ndr_err = ndr_dnsp_string_list_copy(mem_ctx,
+ &rrec->rdata.txt_record.txt,
+ &r->data.txt);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return WERR_NOMEM;
}
break;
diff --git a/source4/dsdb/tests/python/password_lockout.py b/source4/dsdb/tests/python/password_lockout.py
index 133b40b..e6badbc 100755
--- a/source4/dsdb/tests/python/password_lockout.py
+++ b/source4/dsdb/tests/python/password_lockout.py
@@ -51,10 +51,24 @@ if len(args) < 1:
host = args[0]
lp = sambaopts.get_loadparm()
-creds = credopts.get_credentials(lp)
+global_creds = credopts.get_credentials(lp)
# Force an encrypted connection
-creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
+global_creds.set_gensec_features(global_creds.get_gensec_features() |
+ gensec.FEATURE_SEAL)
+
+def insta_creds(template=global_creds):
+ # get a copy of the global creds or a the passed in creds
+ c = Credentials()
+ c.set_username("testuser")
+ c.set_password("thatsAcomplPASS1")
+ c.set_domain(template.get_domain())
+ c.set_realm(template.get_realm())
+ c.set_workstation(template.get_workstation())
+ c.set_gensec_features(c.get_gensec_features()
+ | gensec.FEATURE_SEAL)
+ c.set_kerberos_state(template.get_kerberos_state())
+ return c
#
# Tests start here
@@ -129,6 +143,12 @@ userAccountControl: %d
if mode == "ignore":
return
+ if mode == "absent":
+ self.assertFalse(name in res[0],
+ msg="attr[%s] not missing on dn[%s]" %
+ (name, res[0].dn))
+ return
+
self.assertTrue(name in res[0],
msg="attr[%s] missing on dn[%s]" %
(name, res[0].dn))
@@ -136,39 +156,56 @@ userAccountControl: %d
msg="attr[%s]=%r on dn[%s]" %
(name, res[0][name], res[0].dn))
+
+ print "%s = '%s'" % (name, res[0][name][0])
+
if mode == "present":
return
+
if mode == "equal":
- self.assertTrue(str(res[0][name][0]) == str(value),
- msg="attr[%s]=[%s] != [%s] on dn[%s]" %
- (name, str(res[0][name][0]), str(value), res[0].dn))
+ v = int(res[0][name][0])
+ value = int(value)
+ msg = ("attr[%s]=[%s] != [%s] on dn[%s]\n"
+ "(diff %d; actual value is %s than expected)" %
+ (name, v, value, res[0].dn, v - value,
+ ('less' if v < value else 'greater')))
+
+ self.assertTrue(v == value, msg)
return
+
if mode == "greater":
v = int(res[0][name][0])
self.assertTrue(v > int(value),
- msg="attr[%s]=[%s] <= [%s] on dn[%s]" %
- (name, v, int(value), res[0].dn))
+ msg="attr[%s]=[%s] <= [%s] on dn[%s] (diff %d)" %
+ (name, v, int(value), res[0].dn, v - int(value)))
return
if mode == "less":
v = int(res[0][name][0])
self.assertTrue(v < int(value),
- msg="attr[%s]=[%s] >= [%s] on dn[%s]" %
- (name, v, int(value), res[0].dn))
+ msg="attr[%s]=[%s] >= [%s] on dn[%s] (diff %d)" %
+ (name, v, int(value), res[0].dn, v - int(value)))
return
self.assertEqual(mode, not mode, "Invalid Mode[%s]" % mode)
def _check_account(self, dn,
badPwdCount=None,
badPasswordTime=None,
+ lastLogon=None,
+ lastLogonTimestamp=None,
lockoutTime=None,
userAccountControl=None,
msDSUserAccountControlComputed=None,
- effective_bad_password_count=None):
-
+ effective_bad_password_count=None,
+ msg=None):
+ print '-=' * 36
+ if msg is not None:
+ print "\033[01;32m %s \033[00m\n" % msg
attrs = [
"objectSid",
"badPwdCount",
"badPasswordTime",
+ "lastLogon",
+ "lastLogonTimestamp",
"lockoutTime",
"userAccountControl",
"msDS-User-Account-Control-Computed"
@@ -182,6 +219,8 @@ userAccountControl: %d
self.assertTrue(len(res) == 1)
self._check_attribute(res, "badPwdCount", badPwdCount)
self._check_attribute(res, "badPasswordTime", badPasswordTime)
+ self._check_attribute(res, "lastLogon", lastLogon)
+ self._check_attribute(res, "lastLogonTimestamp", lastLogonTimestamp)
self._check_attribute(res, "lockoutTime", lockoutTime)
self._check_attribute(res, "userAccountControl", userAccountControl)
self._check_attribute(res, "msDS-User-Account-Control-Computed",
@@ -233,10 +272,21 @@ userAccountControl: %d
time.sleep(0.01)
return res
+ def assertLoginFailure(self, url, creds, lp, errno=ERR_INVALID_CREDENTIALS):
+ try:
+ ldb = SamDB(url=url, credentials=creds, lp=lp)
+ self.fail("Login unexpectedly succeeded")
+ except LdbError, (num, msg):
+ if errno is not None:
+ self.assertEquals(num, errno, ("Login failed in the wrong way"
+ "(got err %d, expected %d)" %
+ (num, errno)))
+
def setUp(self):
super(PasswordTests, self).setUp()
- self.ldb = SamDB(url=host_url, session_info=system_session(lp), credentials=creds, lp=lp)
+ self.ldb = SamDB(url=host_url, session_info=system_session(lp),
+ credentials=global_creds, lp=lp)
# Gets back the basedn
base_dn = self.ldb.domain_dn()
@@ -315,7 +365,7 @@ lockoutThreshold: """ + str(lockoutThreshold) + """
self.base_dn = self.ldb.domain_dn()
self.domain_sid = security.dom_sid(self.ldb.get_domain_sid())
- self.samr = samr.samr("ncacn_ip_tcp:%s[sign]" % host, lp, creds)
+ self.samr = samr.samr("ncacn_ip_tcp:%s[sign]" % host, lp, global_creds)
self.samr_handle = self.samr.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED)
self.samr_domain = self.samr.OpenDomain(self.samr_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, self.domain_sid)
@@ -329,6 +379,8 @@ lockoutThreshold: """ + str(lockoutThreshold) + """
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=0,
badPasswordTime=0,
+ lastLogon=0,
+ lastLogonTimestamp=('absent', None),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT |
dsdb.UF_ACCOUNTDISABLE |
@@ -343,6 +395,8 @@ lockoutThreshold: """ + str(lockoutThreshold) + """
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=0,
badPasswordTime=0,
+ lastLogon=0,
+ lastLogonTimestamp=('absent', None),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT |
dsdb.UF_ACCOUNTDISABLE |
@@ -371,6 +425,8 @@ userPassword: thatsAcomplPASS2
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=1,
badPasswordTime=("greater", 0),
+ lastLogon=0,
+ lastLogonTimestamp=('absent', None),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT |
dsdb.UF_ACCOUNTDISABLE |
@@ -394,6 +450,8 @@ userPassword: thatsAcomplPASS1
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=1,
badPasswordTime=badPasswordTime,
+ lastLogon=0,
+ lastLogonTimestamp=('absent', None),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT |
dsdb.UF_ACCOUNTDISABLE |
@@ -406,6 +464,8 @@ userPassword: thatsAcomplPASS1
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=1,
badPasswordTime=badPasswordTime,
+ lastLogon=0,
+ lastLogonTimestamp=('absent', None),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -413,24 +473,22 @@ userPassword: thatsAcomplPASS1
# Open a second LDB connection with the user credentials. Use the
# command line credentials for informations like the domain, the realm
# and the workstation.
- creds2 = Credentials()
- creds2.set_username("testuser")
- creds2.set_password("thatsAcomplPASS1")
- creds2.set_domain(creds.get_domain())
- creds2.set_realm(creds.get_realm())
- creds2.set_workstation(creds.get_workstation())
- creds2.set_gensec_features(creds2.get_gensec_features()
- | gensec.FEATURE_SEAL)
+ creds2 = insta_creds()
self.ldb2 = SamDB(url=host_url, credentials=creds2, lp=lp)
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=0,
badPasswordTime=badPasswordTime,
+ lastLogon=('greater', 0),
+ lastLogonTimestamp=('greater', 0),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
+ lastLogon = int(res[0]["lastLogon"][0])
+ self.assertGreater(lastLogon, badPasswordTime)
+
# (Re)adds the test user "testuser3" with no password atm
delete_force(self.ldb, "cn=testuser3,cn=users," + self.base_dn)
self.ldb.add({
@@ -441,6 +499,8 @@ userPassword: thatsAcomplPASS1
res = self._check_account("cn=testuser3,cn=users," + self.base_dn,
badPwdCount=0,
badPasswordTime=0,
+ lastLogon=0,
+ lastLogonTimestamp=('absent', None),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT |
dsdb.UF_ACCOUNTDISABLE |
@@ -469,6 +529,8 @@ userPassword: thatsAcomplPASS2
res = self._check_account("cn=testuser3,cn=users," + self.base_dn,
badPwdCount=1,
badPasswordTime=("greater", 0),
+ lastLogon=0,
+ lastLogonTimestamp=('absent', None),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT |
dsdb.UF_ACCOUNTDISABLE |
@@ -492,6 +554,8 @@ userPassword: thatsAcomplPASS1
res = self._check_account("cn=testuser3,cn=users," + self.base_dn,
badPwdCount=1,
badPasswordTime=badPasswordTime3,
+ lastLogon=0,
+ lastLogonTimestamp=('absent', None),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT |
dsdb.UF_ACCOUNTDISABLE |
@@ -504,6 +568,8 @@ userPassword: thatsAcomplPASS1
res = self._check_account("cn=testuser3,cn=users," + self.base_dn,
badPwdCount=1,
badPasswordTime=badPasswordTime3,
+ lastLogon=0,
+ lastLogonTimestamp=('absent', None),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -511,19 +577,16 @@ userPassword: thatsAcomplPASS1
# Open a second LDB connection with the user credentials. Use the
# command line credentials for informations like the domain, the realm
# and the workstation.
- creds3 = Credentials()
+ creds3 = insta_creds()
creds3.set_username("testuser3")
creds3.set_password("thatsAcomplPASS1")
- creds3.set_domain(creds.get_domain())
- creds3.set_realm(creds.get_realm())
- creds3.set_workstation(creds.get_workstation())
- creds3.set_gensec_features(creds3.get_gensec_features()
- | gensec.FEATURE_SEAL)
self.ldb3 = SamDB(url=host_url, credentials=creds3, lp=lp)
res = self._check_account("cn=testuser3,cn=users," + self.base_dn,
badPwdCount=0,
badPasswordTime=badPasswordTime3,
+ lastLogon=('greater', badPasswordTime3),
+ lastLogonTimestamp=('greater', badPasswordTime3),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -536,10 +599,14 @@ userPassword: thatsAcomplPASS1
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=0,
badPasswordTime=("greater", 0),
+ lastLogon=('greater', 0),
+ lastLogonTimestamp=('greater', 0),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
badPasswordTime = int(res[0]["badPasswordTime"][0])
+ lastLogon = int(res[0]["lastLogon"][0])
+ lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
# Change password on a connection as another user
@@ -561,6 +628,8 @@ userPassword: thatsAcomplPASS2
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=1,
badPasswordTime=("greater", badPasswordTime),
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -579,6 +648,8 @@ userPassword: thatsAcomplPASS2
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=1,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -601,6 +672,8 @@ userPassword: thatsAcomplPASS2
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=2,
badPasswordTime=("greater", badPasswordTime),
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -626,6 +699,8 @@ userPassword: thatsAcomplPASS2
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3,
badPasswordTime=("greater", badPasswordTime),
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=("greater", badPasswordTime),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -651,6 +726,8 @@ userPassword: thatsAcomplPASS2
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -675,6 +752,8 @@ userPassword: thatsAcomplPASS2
badPwdCount=3,
badPasswordTime=badPasswordTime,
lockoutTime=lockoutTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
@@ -697,6 +776,8 @@ userPassword: thatsAcomplPASS2x
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -713,6 +794,8 @@ userPassword: thatsAcomplPASS2
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -736,6 +819,8 @@ userPassword: thatsAcomplPASS2x
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -753,6 +838,8 @@ userPassword: thatsAcomplPASS2x
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -778,16 +865,21 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le'))
badPwdCount=3,
badPasswordTime=badPasswordTime,
lockoutTime=lockoutTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
self._reset_by_method(res, method)
+ # Here bad password counts are reset without logon success.
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=0,
badPasswordTime=badPasswordTime,
lockoutTime=0,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -807,6 +899,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le'))
badPwdCount=0,
badPasswordTime=badPasswordTime,
lockoutTime=0,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -830,6 +924,8 @@ userPassword: thatsAcomplPASS2XYZ
badPwdCount=1,
badPasswordTime=("greater", badPasswordTime),
lockoutTime=0,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -854,6 +950,8 @@ userPassword: thatsAcomplPASS2XYZ
badPwdCount=2,
badPasswordTime=("greater", badPasswordTime),
lockoutTime=0,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -864,6 +962,8 @@ userPassword: thatsAcomplPASS2XYZ
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=0,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=0,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -885,10 +985,13 @@ userPassword: thatsAcomplPASS2XYZ
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=0,
badPasswordTime=("greater", 0),
+ lastLogon=("greater", 0),
+ lastLogonTimestamp=("greater", 0),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
badPasswordTime = int(res[0]["badPasswordTime"][0])
+ lastLogon = int(res[0]["lastLogon"][0])
# Change password on a connection as another user
@@ -910,6 +1013,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=1,
badPasswordTime=("greater", badPasswordTime),
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogon,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -928,6 +1033,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=1,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogon,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -950,6 +1057,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=2,
badPasswordTime=("greater", badPasswordTime),
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogon,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -963,6 +1072,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=2,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogon,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -988,6 +1099,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3,
badPasswordTime=("greater", badPasswordTime),
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogon,
lockoutTime=("greater", badPasswordTime),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -1013,6 +1126,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogon,
lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -1036,6 +1151,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogon,
lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -1059,6 +1176,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogon,
lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -1070,6 +1189,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=0,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogon,
lockoutTime=0,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -1088,6 +1209,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=0,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogon,
lockoutTime=0,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -1111,6 +1234,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=1,
badPasswordTime=("greater", badPasswordTime),
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogon,
lockoutTime=0,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -1135,6 +1260,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=2,
badPasswordTime=("greater", badPasswordTime),
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogon,
lockoutTime=0,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -1148,6 +1275,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=2,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogon,
lockoutTime=0,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -1171,6 +1300,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3,
badPasswordTime=("greater", badPasswordTime),
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogon,
lockoutTime=("greater", badPasswordTime),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -1183,6 +1314,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3, effective_bad_password_count=0,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogon,
lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -1197,51 +1330,60 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
badPwdCount=3, effective_bad_password_count=0,
badPasswordTime=badPasswordTime,
lockoutTime=lockoutTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogon,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
def _test_login_lockout(self, use_kerberos):
# This unlocks by waiting for account_lockout_duration
- print "Performs a lockout attempt against LDAP using NTLM or Kerberos"
+ if use_kerberos == MUST_USE_KERBEROS:
+ lastlogon_relation = 'greater'
+ print "Performs a lockout attempt against LDAP using Kerberos"
+ else:
+ lastlogon_relation = 'equal'
+ print "Performs a lockout attempt against LDAP using NTLM"
# Change password on a connection as another user
-
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=0,
badPasswordTime=("greater", 0),
+ lastLogon=("greater", 0),
+ lastLogonTimestamp=("greater", 0),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
badPasswordTime = int(res[0]["badPasswordTime"][0])
+ lastLogon = int(res[0]["lastLogon"][0])
+ firstLogon = lastLogon
+ lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
+ print firstLogon
+ print lastLogonTimestamp
+
+
+ self.assertGreater(lastLogon, badPasswordTime)
# Open a second LDB connection with the user credentials. Use the
# command line credentials for informations like the domain, the realm
# and the workstation.
- creds_lockout = Credentials()
- creds_lockout.set_username("testuser")
- creds_lockout.set_domain(creds.get_domain())
- creds_lockout.set_realm(creds.get_realm())
- creds_lockout.set_workstation(creds.get_workstation())
- creds_lockout.set_gensec_features(creds_lockout.get_gensec_features()
- | gensec.FEATURE_SEAL)
+ creds_lockout = insta_creds()
creds_lockout.set_kerberos_state(use_kerberos)
# The wrong password
creds_lockout.set_password("thatsAcomplPASS1x")
- try:
- ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
-
- except LdbError, (num, msg):
- self.assertEquals(num, ERR_INVALID_CREDENTIALS)
+ self.assertLoginFailure(host_url, creds_lockout, lp)
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=1,
badPasswordTime=("greater", badPasswordTime),
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0)
+ msDSUserAccountControlComputed=0,
+ msg='lastlogontimestamp with wrong password')
badPasswordTime = int(res[0]["badPasswordTime"][0])
# Correct old password
@@ -1249,25 +1391,31 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
+ # lastLogonTimestamp should not change
+ # lastLogon increases if badPwdCount is non-zero (!)
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=0,
badPasswordTime=badPasswordTime,
+ lastLogon=('greater', lastLogon),
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0)
+ msDSUserAccountControlComputed=0,
+ msg='LLTimestamp is updated to lastlogon')
+
+ lastLogon = int(res[0]["lastLogon"][0])
+ self.assertGreater(lastLogon, badPasswordTime)
# The wrong password
creds_lockout.set_password("thatsAcomplPASS1x")
- try:
- ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
-
- except LdbError, (num, msg):
- self.assertEquals(num, ERR_INVALID_CREDENTIALS)
+ self.assertLoginFailure(host_url, creds_lockout, lp)
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=1,
badPasswordTime=("greater", badPasswordTime),
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -1286,6 +1434,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=2,
badPasswordTime=("greater", badPasswordTime),
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -1306,6 +1456,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3,
badPasswordTime=("greater", badPasswordTime),
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=("greater", badPasswordTime),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -1324,6 +1476,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
@@ -1340,12 +1494,14 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
- # The correct password
+ # The correct password, but we are locked out
creds_lockout.set_password("thatsAcomplPASS1")
try:
ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
@@ -1356,32 +1512,50 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
+ # wait for the lockout to end
time.sleep(self.account_lockout_duration + 1)
+ print self.account_lockout_duration + 1
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=3, effective_bad_password_count=0,
badPasswordTime=badPasswordTime,
lockoutTime=lockoutTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
+ lastLogon = int(res[0]["lastLogon"][0])
+
# The correct password after letting the timeout expire
+
creds_lockout.set_password("thatsAcomplPASS1")
- ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
+
+ creds_lockout2 = insta_creds(creds_lockout)
+
+ ldb_lockout = SamDB(url=host_url, credentials=creds_lockout2, lp=lp)
+ time.sleep(3)
res = self._check_account("cn=testuser,cn=users," + self.base_dn,
badPwdCount=0,
badPasswordTime=badPasswordTime,
+ lastLogon=(lastlogon_relation, lastLogon),
+ lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=0,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0)
+ msDSUserAccountControlComputed=0,
+ msg="lastLogon is way off")
+
+ lastLogon = int(res[0]["lastLogon"][0])
# The wrong password
creds_lockout.set_password("thatsAcomplPASS1x")
@@ -1395,6 +1569,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
badPwdCount=1,
badPasswordTime=("greater", badPasswordTime),
lockoutTime=0,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -1412,6 +1588,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
badPwdCount=2,
badPasswordTime=("greater", badPasswordTime),
lockoutTime=0,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -1423,6 +1601,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
badPwdCount=2, effective_bad_password_count=0,
badPasswordTime=badPasswordTime,
lockoutTime=0,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -1439,6 +1619,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
badPwdCount=1,
badPasswordTime=("greater", badPasswordTime),
lockoutTime=0,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -1452,6 +1634,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
badPwdCount=0,
badPasswordTime=badPasswordTime,
lockoutTime=0,
+ lastLogon=("greater", lastLogon),
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
@@ -1462,6 +1646,79 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
def test_login_lockout_kerberos(self):
self._test_login_lockout(MUST_USE_KERBEROS)
+ def _test_multiple_logon(self, use_kerberos):
+ # Test the happy case in which a user logs on correctly, then
+ # logs on correctly again, so that the bad password and
+ # lockout times are both zero the second time. The lastlogon
+ # time should increase.
+
+ # Open a second LDB connection with the user credentials. Use the
+ # command line credentials for informations like the domain, the realm
+ # and the workstation.
+ creds2 = insta_creds()
+ creds2.set_kerberos_state(use_kerberos)
+ self.assertEqual(creds2.get_kerberos_state(), use_kerberos)
+
+ if use_kerberos == MUST_USE_KERBEROS:
+ print "Testing multiple logon with Kerberos"
+ lastlogon_relation = 'greater'
+ else:
+ print "Testing multiple logon with NTLM"
+ lastlogon_relation = 'equal'
+
+ SamDB(url=host_url, credentials=insta_creds(creds2), lp=lp)
+
+ res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ badPwdCount=0,
+ badPasswordTime=("greater", 0),
+ lastLogon=("greater", 0),
+ lastLogonTimestamp=("greater", 0),
+ userAccountControl=
+ dsdb.UF_NORMAL_ACCOUNT,
+ msDSUserAccountControlComputed=0)
+ badPasswordTime = int(res[0]["badPasswordTime"][0])
+ lastLogon = int(res[0]["lastLogon"][0])
+ lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
+ firstLogon = lastLogon
+ print "last logon is %d" % lastLogon
+ self.assertGreater(lastLogon, badPasswordTime)
+
+ time.sleep(1)
+ SamDB(url=host_url, credentials=insta_creds(creds2), lp=lp)
+
+ res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ badPwdCount=0,
+ badPasswordTime=badPasswordTime,
+ lastLogon=(lastlogon_relation, lastLogon),
+ lastLogonTimestamp=lastLogonTimestamp,
+ userAccountControl=
+ dsdb.UF_NORMAL_ACCOUNT,
+ msDSUserAccountControlComputed=0,
+ msg=("second logon, firstlogon was %s" %
+ firstLogon))
+
+
+ lastLogon = int(res[0]["lastLogon"][0])
+
+ time.sleep(1)
+
+ SamDB(url=host_url, credentials=insta_creds(creds2), lp=lp)
+
+ res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ badPwdCount=0,
+ badPasswordTime=badPasswordTime,
+ lastLogon=(lastlogon_relation, lastLogon),
+ lastLogonTimestamp=lastLogonTimestamp,
+ userAccountControl=
+ dsdb.UF_NORMAL_ACCOUNT,
+ msDSUserAccountControlComputed=0)
+
+ def test_multiple_logon_ntlm(self):
+ self._test_multiple_logon(DONT_USE_KERBEROS)
+
+ def test_multiple_logon_kerberos(self):
+ self._test_multiple_logon(MUST_USE_KERBEROS)
+
def tearDown(self):
super(PasswordTests, self).tearDown()
delete_force(self.ldb, "cn=testuser,cn=users," + self.base_dn)
diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c
index 77f6a90..c4a4bb4 100644
--- a/source4/kdc/hdb-samba4.c
+++ b/source4/kdc/hdb-samba4.c
@@ -184,10 +184,13 @@ static krb5_error_code hdb_samba4_auth_status(krb5_context context, HDB *db,
struct samba_kdc_db_context);
struct samba_kdc_entry *p = talloc_get_type(entry->ctx, struct samba_kdc_entry);
+ struct ldb_dn *domain_dn = ldb_get_default_basedn(kdc_db_ctx->samdb);
+
if (hdb_auth_status == HDB_AUTH_WRONG_PASSWORD) {
- authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, ldb_get_default_basedn(kdc_db_ctx->samdb));
+ authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, domain_dn);
} else if (hdb_auth_status == HDB_AUTH_SUCCESS) {
- authsam_zero_bad_pwd_count(kdc_db_ctx->samdb, p->msg);
+ authsam_logon_success_accounting(kdc_db_ctx->samdb, p->msg,
+ domain_dn, true);
}
return 0;
}
diff --git a/source4/librpc/wscript_build b/source4/librpc/wscript_build
index 781611e..4da3eaa 100755
--- a/source4/librpc/wscript_build
+++ b/source4/librpc/wscript_build
@@ -167,7 +167,7 @@ bld.SAMBA_PYTHON('python_echo',
bld.SAMBA_PYTHON('python_dns',
source='../../librpc/gen_ndr/py_dns.c',
- deps='RPC_NDR_DNS pytalloc-util pyrpc_util',
+ deps='NDR_DNS pytalloc-util pyrpc_util',
realname='samba/dcerpc/dns.so'
)
@@ -324,7 +324,7 @@ bld.SAMBA_PYTHON('python_dcerpc_drsblobs',
bld.SAMBA_PYTHON('python_dcerpc_dnsp',
source='../../librpc/gen_ndr/py_dnsp.c',
- deps='pytalloc-util pyrpc_util NDR_SECURITY RPC_NDR_DNSP',
+ deps='pytalloc-util pyrpc_util NDR_SECURITY NDR_DNSP',
realname='samba/dcerpc/dnsp.so'
)
diff --git a/source4/scripting/devel/createtrust b/source4/scripting/devel/createtrust
index 7f1ba33..6c0de1c 100755
--- a/source4/scripting/devel/createtrust
+++ b/source4/scripting/devel/createtrust
@@ -11,21 +11,9 @@ import samba
import samba.getopt as options
from samba.dcerpc import lsa, security, drsblobs
from samba.ndr import ndr_pack
+from samba import arcfour_encrypt, string_to_byte_array
import random
-def arcfour_encrypt(key, data):
- from Crypto.Cipher import ARC4
- c = ARC4.new(key)
- return c.encrypt(data)
-
-def string_to_array(string):
- blob = [0] * len(string)
-
- for i in range(len(string)):
- blob[i] = ord(string[i])
-
- return blob
-
########### main code ###########
if __name__ == "__main__":
parser = OptionParser("createtrust [options] server")
@@ -73,7 +61,7 @@ if __name__ == "__main__":
info.trust_type = lsa.LSA_TRUST_TYPE_UPLEVEL
info.trust_attributes = lsa.LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
- password_blob = string_to_array("password".encode('utf-16-le'))
+ password_blob = string_to_byte_array("password".encode('utf-16-le'))
clear_value = drsblobs.AuthInfoClear()
clear_value.size = len(password_blob)
@@ -123,7 +111,7 @@ if __name__ == "__main__":
auth_blob = lsa.DATA_BUF2()
auth_blob.size = len(encrypted_trustpass)
- auth_blob.data = string_to_array(encrypted_trustpass)
+ auth_blob.data = string_to_byte_array(encrypted_trustpass)
auth_info = lsa.TrustDomainInfoAuthInfoInternal()
auth_info.auth_blob = auth_blob
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index e284c2c..69330f2 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -290,7 +290,8 @@ for f in sorted(os.listdir(os.path.join(samba4srcdir, "../pidl/tests"))):
planperltestsuite("pidl.%s" % f[:-3], os.path.normpath(os.path.join(samba4srcdir, "../pidl/tests", f)))
# DNS tests
-planpythontestsuite("fl2003dc:local", "samba.tests.dns")
+plantestsuite_loadlist("samba.tests.dns", "fl2003dc:local", [python, os.path.join(srcdir(), "python/samba/tests/dns.py"), '$SERVER', '$SERVER_IP', '--machine-pass', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT'])
+
for t in smbtorture4_testsuites("dns_internal."):
plansmbtorture4testsuite(t, "ad_dc_ntvfs:local", '//$SERVER/whavever')
diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c
index 68dbbc1..1275aa8 100644
--- a/source4/torture/smb2/create.c
+++ b/source4/torture/smb2/create.c
@@ -1666,6 +1666,69 @@ done:
return ret;
}
+/*
+ test directory creation with an initial allocation size > 0
+*/
+static bool test_dir_alloc_size(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ const char *dname = DNAME "\\torture_alloc_size.dir";
+ NTSTATUS status;
+ struct smb2_create c;
+ struct smb2_handle h1 = {{0}}, h2;
+
+ torture_comment(tctx, "Checking initial allocation size on directories\n");
+
+ smb2_deltree(tree, dname);
+
+ status = torture_smb2_testdir(tree, DNAME, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
+
+ ZERO_STRUCT(c);
+ c.in.create_disposition = NTCREATEX_DISP_CREATE;
+ c.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
+ c.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+ c.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+ c.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ c.in.fname = dname;
+ /*
+ * An insanely large value so we can check the value is
+ * ignored: Samba either returns 0 (current behaviour), or,
+ * once vfswrap_get_alloc_size() is fixed to allow retrieving
+ * the allocated size for directories, returns
+ * smb_roundup(..., stat.st_size) which would be 1 MB by
+ * default.
+ *
+ * Windows returns 0 for emtpy directories, once directories
+ * have a few entries it starts replying with values > 0.
+ */
+ c.in.alloc_size = 1024*1024*1024;
+
+ status = smb2_create(tree, tctx, &c);
+ h2 = c.out.file.handle;
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "dir create with initial alloc size failed");
+
+ smb2_util_close(tree, h2);
+
+ torture_comment(tctx, "Got directory alloc size: %ju\n", (uintmax_t)c.out.alloc_size);
+
+ /*
+ * See above for the rational for this test
+ */
+ if (c.out.alloc_size > 1024*1024) {
+ torture_fail_goto(tctx, done, talloc_asprintf(tctx, "bad alloc size: %ju",
+ (uintmax_t)c.out.alloc_size));
+ }
+
+done:
+ if (!smb2_util_handle_empty(h1)) {
+ smb2_util_close(tree, h1);
+ }
+ smb2_deltree(tree, DNAME);
+ return ret;
+}
/*
basic testing of SMB2 read
@@ -1686,6 +1749,7 @@ struct torture_suite *torture_smb2_create_init(void)
torture_suite_add_1smb2_test(suite, "acldir", test_create_acl_dir);
torture_suite_add_1smb2_test(suite, "nulldacl", test_create_null_dacl);
torture_suite_add_1smb2_test(suite, "mkdir-dup", test_mkdir_dup);
+ torture_suite_add_1smb2_test(suite, "dir-alloc-size", test_dir_alloc_size);
suite->description = talloc_strdup(suite, "SMB2-CREATE tests");
diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c
index 1c1d4ad..d74eb65 100644
--- a/source4/torture/vfs/fruit.c
+++ b/source4/torture/vfs/fruit.c
@@ -64,7 +64,7 @@ static bool check_stream_list(struct smb2_tree *tree,
const char *fname,
int num_exp,
const char **exp,
- struct smb2_handle h);
+ bool is_dir);
static int qsort_string(char * const *s1, char * const *s2)
{
@@ -849,7 +849,7 @@ static bool torture_write_afpinfo(struct smb2_tree *tree,
char *infobuf;
bool ret = true;
- full_name = talloc_asprintf(mem_ctx, "%s%s", fname, AFPINFO_STREAM);
+ full_name = talloc_asprintf(mem_ctx, "%s%s", fname, AFPINFO_STREAM_NAME);
if (full_name == NULL) {
torture_comment(tctx, "talloc_asprintf error\n");
return false;
@@ -900,7 +900,8 @@ static bool check_stream(struct smb2_tree *tree,
struct smb2_create create;
struct smb2_read r;
NTSTATUS status;
- const char *full_name;
+ char *full_name;
+ bool ret = true;
full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname);
if (full_name == NULL) {
@@ -917,22 +918,21 @@ static bool check_stream(struct smb2_tree *tree,
status = smb2_create(tree, mem_ctx, &create);
if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(full_name);
if (value == NULL) {
return true;
- } else {
- torture_comment(tctx, "Unable to open stream %s\n",
- full_name);
- sleep(10000000);
- return false;
}
+ torture_comment(tctx, "Unable to open stream %s\n", full_name);
+ return false;
}
handle = create.out.file.handle;
if (value == NULL) {
+ TALLOC_FREE(full_name);
+ smb2_util_close(tree, handle);
return true;
}
-
ZERO_STRUCT(r);
r.in.file.handle = handle;
r.in.length = read_count;
@@ -940,19 +940,24 @@ static bool check_stream(struct smb2_tree *tree,
status = smb2_read(tree, tree, &r);
- if (!NT_STATUS_IS_OK(status)) {
- torture_comment(tctx, "(%s) Failed to read %lu bytes from "
- "stream '%s'\n", location, (long)strlen(value), full_name);
- return false;
- }
+ torture_assert_ntstatus_ok_goto(
+ tctx, status, ret, done,
+ talloc_asprintf(tctx, "(%s) Failed to read %lu bytes from stream '%s'\n",
+ location, (long)strlen(value), full_name));
- if (memcmp(r.out.data.data + comp_offset, value, comp_count) != 0) {
- torture_comment(tctx, "(%s) Bad data in stream\n", location);
- return false;
- }
+ torture_assert_goto(tctx, r.out.data.length == read_count, ret, done,
+ talloc_asprintf(tctx, "smb2_read returned %jd bytes, expected %jd\n",
+ (intmax_t)r.out.data.length, (intmax_t)read_count));
+ torture_assert_goto(
+ tctx, memcmp(r.out.data.data + comp_offset, value, comp_count) == 0,
+ ret, done,
+ talloc_asprintf(tctx, "(%s) Bad data in stream\n", location));
+
+done:
+ TALLOC_FREE(full_name);
smb2_util_close(tree, handle);
- return true;
+ return ret;
}
/**
@@ -1188,9 +1193,79 @@ static bool torture_setup_file(TALLOC_CTX *mem_ctx, struct smb2_tree *tree,
return true;
}
-static bool test_read_atalk_metadata(struct torture_context *tctx,
- struct smb2_tree *tree1,
- struct smb2_tree *tree2)
+static bool enable_aapl(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ NTSTATUS status;
+ bool ret = true;
+ struct smb2_create io;
+ DATA_BLOB data;
+ struct smb2_create_blob *aapl = NULL;
+ uint32_t aapl_server_caps;
+ uint32_t expexted_scaps = (SMB2_CRTCTX_AAPL_UNIX_BASED |
+ SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
+ SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE |
+ SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE);
+ bool is_osx_server = torture_setting_bool(tctx, "osx", false);
+
+ ZERO_STRUCT(io);
+ io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
+ io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+ io.in.create_disposition = NTCREATEX_DISP_OPEN;
+ io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
+ NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE);
+ io.in.fname = "";
+
+ /*
+ * Issuing an SMB2/CREATE with a suitably formed AAPL context,
+ * controls behaviour of Apple's SMB2 extensions for the whole
+ * session!
+ */
+
+ data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
+ SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
+ SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS |
+ SMB2_CRTCTX_AAPL_VOLUME_CAPS |
+ SMB2_CRTCTX_AAPL_MODEL_INFO));
+ SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
+ SMB2_CRTCTX_AAPL_UNIX_BASED |
+ SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
+
+ status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_blob_add");
+
+ status = smb2_create(tree, tctx, &io);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
+
+ status = smb2_util_close(tree, io.out.file.handle);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close");
+
+ /*
+ * Now check returned AAPL context
+ */
+ torture_comment(tctx, "Comparing returned AAPL capabilities\n");
+
+ aapl = smb2_create_blob_find(&io.out.blobs,
+ SMB2_CREATE_TAG_AAPL);
+ torture_assert_goto(tctx, aapl != NULL, ret, done, "missing AAPL context");
+
+ if (!is_osx_server) {
+ torture_assert_goto(tctx, aapl->data.length == 50, ret, done, "bad AAPL size");
+ }
+
+ aapl_server_caps = BVAL(aapl->data.data, 16);
+ torture_assert_goto(tctx, aapl_server_caps == expexted_scaps,
+ ret, done, "bad AAPL caps");
+
+done:
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static bool test_read_netatalk_metadata(struct torture_context *tctx,
+ struct smb2_tree *tree)
{
TALLOC_CTX *mem_ctx = talloc_new(tctx);
const char *fname = BASEDIR "\\torture_read_metadata";
@@ -1198,16 +1273,22 @@ static bool test_read_atalk_metadata(struct torture_context *tctx,
struct smb2_handle testdirh;
bool ret = true;
ssize_t len;
+ const char *localdir = NULL;
torture_comment(tctx, "Checking metadata access\n");
- smb2_util_unlink(tree1, fname);
+ localdir = torture_setting_string(tctx, "localdir", NULL);
+ if (localdir == NULL) {
+ torture_skip(tctx, "Need localdir for test");
+ }
+
+ smb2_util_unlink(tree, fname);
- status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
CHECK_STATUS(status, NT_STATUS_OK);
- smb2_util_close(tree1, testdirh);
+ smb2_util_close(tree, testdirh);
- ret = torture_setup_file(mem_ctx, tree1, fname, false);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
if (ret == false) {
goto done;
}
@@ -1220,42 +1301,122 @@ static bool test_read_atalk_metadata(struct torture_context *tctx,
goto done;
}
- ret &= check_stream(tree1, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
- 0, 60, 0, 4, "AFP");
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 0, 60, 0, 4, "AFP");
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
- ret &= check_stream(tree1, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
- 0, 60, 16, 8, "BARRFOOO");
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 0, 60, 16, 8, "BARRFOOO");
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
- ret &= check_stream(tree1, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
- 16, 8, 0, 8, "BARRFOOO");
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 16, 8, 0, 3, "AFP");
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
/* Check reading offset and read size > sizeof(AFPINFO_STREAM) */
- len = read_stream(tree1, __location__, tctx, mem_ctx, fname,
+ len = read_stream(tree, __location__, tctx, mem_ctx, fname,
AFPINFO_STREAM, 0, 61);
CHECK_VALUE(len, 60);
- len = read_stream(tree1, __location__, tctx, mem_ctx, fname,
+ len = read_stream(tree, __location__, tctx, mem_ctx, fname,
AFPINFO_STREAM, 59, 2);
- CHECK_VALUE(len, 1);
+ CHECK_VALUE(len, 2);
- len = read_stream(tree1, __location__, tctx, mem_ctx, fname,
+ len = read_stream(tree, __location__, tctx, mem_ctx, fname,
AFPINFO_STREAM, 60, 1);
- CHECK_VALUE(len, 0);
+ CHECK_VALUE(len, 1);
- len = read_stream(tree1, __location__, tctx, mem_ctx, fname,
+ len = read_stream(tree, __location__, tctx, mem_ctx, fname,
AFPINFO_STREAM, 61, 1);
CHECK_VALUE(len, 0);
done:
- smb2_deltree(tree1, BASEDIR);
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static bool test_read_afpinfo(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\torture_read_metadata";
+ NTSTATUS status;
+ struct smb2_handle testdirh;
+ bool ret = true;
+ ssize_t len;
+ AfpInfo *info;
+ const char *type_creator = "SMB,OLE!";
+
+ torture_comment(tctx, "Checking metadata access\n");
+
+ smb2_util_unlink(tree, fname);
+
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
+ smb2_util_close(tree, testdirh);
+
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
+
+ info = torture_afpinfo_new(mem_ctx);
+ torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
+
+ memcpy(info->afpi_FinderInfo, type_creator, 8);
+ ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 0, 60, 0, 4, "AFP");
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 0, 60, 16, 8, type_creator);
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+ /*
+ * OS X ignores offset <= 60 and treats the as
+ * offset=0. Reading from offsets > 60 returns EOF=0.
+ */
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 16, 8, 0, 8, "AFP\0\0\0\001\0");
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+ len = read_stream(tree, __location__, tctx, mem_ctx, fname,
+ AFPINFO_STREAM, 0, 61);
+ torture_assert_goto(tctx, len == 60, ret, done, "read_stream failed");
+
+ len = read_stream(tree, __location__, tctx, mem_ctx, fname,
+ AFPINFO_STREAM, 59, 2);
+ torture_assert_goto(tctx, len == 2, ret, done, "read_stream failed");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 59, 2, 0, 2, "AF");
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+ len = read_stream(tree, __location__, tctx, mem_ctx, fname,
+ AFPINFO_STREAM, 60, 1);
+ torture_assert_goto(tctx, len == 1, ret, done, "read_stream failed");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 60, 1, 0, 1, "A");
+ torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+ len = read_stream(tree, __location__, tctx, mem_ctx, fname,
+ AFPINFO_STREAM, 61, 1);
+ torture_assert_goto(tctx, len == 0, ret, done, "read_stream failed");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
talloc_free(mem_ctx);
return ret;
}
static bool test_write_atalk_metadata(struct torture_context *tctx,
- struct smb2_tree *tree1,
- struct smb2_tree *tree2)
+ struct smb2_tree *tree)
{
TALLOC_CTX *mem_ctx = talloc_new(tctx);
const char *fname = BASEDIR "\\torture_write_metadata";
@@ -1265,13 +1426,12 @@ static bool test_write_atalk_metadata(struct torture_context *tctx,
bool ret = true;
AfpInfo *info;
- smb2_util_unlink(tree1, fname);
-
- status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
CHECK_STATUS(status, NT_STATUS_OK);
- smb2_util_close(tree1, testdirh);
+ smb2_util_close(tree, testdirh);
- ret = torture_setup_file(mem_ctx, tree1, fname, false);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
if (ret == false) {
goto done;
}
@@ -1282,23 +1442,23 @@ static bool test_write_atalk_metadata(struct torture_context *tctx,
}
memcpy(info->afpi_FinderInfo, type_creator, 8);
- ret = torture_write_afpinfo(tree1, tctx, mem_ctx, fname, info);
- ret &= check_stream(tree1, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+ ret &= check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
0, 60, 16, 8, type_creator);
done:
- smb2_deltree(tree1, BASEDIR);
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
talloc_free(mem_ctx);
return ret;
}
static bool test_write_atalk_rfork_io(struct torture_context *tctx,
- struct smb2_tree *tree1,
- struct smb2_tree *tree2)
+ struct smb2_tree *tree)
{
TALLOC_CTX *mem_ctx = talloc_new(tctx);
const char *fname = BASEDIR "\\torture_write_rfork_io";
- const char *rfork = BASEDIR "\\torture_write_rfork_io" AFPRESOURCE_STREAM;
+ const char *rfork = BASEDIR "\\torture_write_rfork_io" AFPRESOURCE_STREAM_NAME;
const char *rfork_content = "1234567890";
NTSTATUS status;
struct smb2_handle testdirh;
@@ -1309,13 +1469,13 @@ static bool test_write_atalk_rfork_io(struct torture_context *tctx,
union smb_fileinfo finfo;
union smb_setfileinfo sinfo;
- smb2_util_unlink(tree1, fname);
+ smb2_util_unlink(tree, fname);
- status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
CHECK_STATUS(status, NT_STATUS_OK);
- smb2_util_close(tree1, testdirh);
+ smb2_util_close(tree, testdirh);
- ret = torture_setup_file(mem_ctx, tree1, fname, false);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
if (ret == false) {
goto done;
}
@@ -1323,12 +1483,12 @@ static bool test_write_atalk_rfork_io(struct torture_context *tctx,
torture_comment(tctx, "(%s) writing to resource fork\n",
__location__);
- ret &= write_stream(tree1, __location__, tctx, mem_ctx,
- fname, AFPRESOURCE_STREAM,
+ ret &= write_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
10, 10, rfork_content);
- ret &= check_stream(tree1, __location__, tctx, mem_ctx,
- fname, AFPRESOURCE_STREAM,
+ ret &= check_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
0, 20, 10, 10, rfork_content);
/* Check size after write */
@@ -1338,7 +1498,7 @@ static bool test_write_atalk_rfork_io(struct torture_context *tctx,
io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
SEC_FILE_WRITE_ATTRIBUTE;
io.smb2.in.fname = rfork;
- status = smb2_create(tree1, mem_ctx, &(io.smb2));
+ status = smb2_create(tree, mem_ctx, &(io.smb2));
CHECK_STATUS(status, NT_STATUS_OK);
filehandle = io.smb2.out.file.handle;
@@ -1348,29 +1508,29 @@ static bool test_write_atalk_rfork_io(struct torture_context *tctx,
ZERO_STRUCT(finfo);
finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
finfo.generic.in.file.handle = filehandle;
- status = smb2_getinfo_file(tree1, mem_ctx, &finfo);
+ status = smb2_getinfo_file(tree, mem_ctx, &finfo);
CHECK_STATUS(status, NT_STATUS_OK);
if (finfo.all_info.out.size != 20) {
torture_result(tctx, TORTURE_FAIL,
"(%s) Incorrect resource fork size\n",
__location__);
ret = false;
- smb2_util_close(tree1, filehandle);
+ smb2_util_close(tree, filehandle);
goto done;
}
- smb2_util_close(tree1, filehandle);
+ smb2_util_close(tree, filehandle);
/* Write at large offset */
torture_comment(tctx, "(%s) writing to resource fork at large offset\n",
__location__);
- ret &= write_stream(tree1, __location__, tctx, mem_ctx,
- fname, AFPRESOURCE_STREAM,
+ ret &= write_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
(off_t)1<<32, 10, rfork_content);
- ret &= check_stream(tree1, __location__, tctx, mem_ctx,
- fname, AFPRESOURCE_STREAM,
+ ret &= check_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
(off_t)1<<32, 10, 0, 10, rfork_content);
/* Truncate back to size of 1 byte */
@@ -1380,10 +1540,9 @@ static bool test_write_atalk_rfork_io(struct torture_context *tctx,
ZERO_STRUCT(io);
io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
- io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
- SEC_FILE_WRITE_ATTRIBUTE;
+ io.smb2.in.desired_access = SEC_FILE_ALL;
io.smb2.in.fname = rfork;
- status = smb2_create(tree1, mem_ctx, &(io.smb2));
+ status = smb2_create(tree, mem_ctx, &(io.smb2));
CHECK_STATUS(status, NT_STATUS_OK);
filehandle = io.smb2.out.file.handle;
@@ -1392,10 +1551,10 @@ static bool test_write_atalk_rfork_io(struct torture_context *tctx,
RAW_SFILEINFO_END_OF_FILE_INFORMATION;
sinfo.end_of_file_info.in.file.handle = filehandle;
sinfo.end_of_file_info.in.size = 1;
- status = smb2_setinfo_file(tree1, &sinfo);
+ status = smb2_setinfo_file(tree, &sinfo);
CHECK_STATUS(status, NT_STATUS_OK);
- smb2_util_close(tree1, filehandle);
+ smb2_util_close(tree, filehandle);
/* Now check size */
ZERO_STRUCT(io);
@@ -1403,34 +1562,34 @@ static bool test_write_atalk_rfork_io(struct torture_context *tctx,
io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
SEC_FILE_WRITE_ATTRIBUTE;
io.smb2.in.fname = rfork;
- status = smb2_create(tree1, mem_ctx, &(io.smb2));
+ status = smb2_create(tree, mem_ctx, &(io.smb2));
CHECK_STATUS(status, NT_STATUS_OK);
filehandle = io.smb2.out.file.handle;
ZERO_STRUCT(finfo);
finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
finfo.generic.in.file.handle = filehandle;
- status = smb2_getinfo_file(tree1, mem_ctx, &finfo);
+ status = smb2_getinfo_file(tree, mem_ctx, &finfo);
CHECK_STATUS(status, NT_STATUS_OK);
if (finfo.all_info.out.size != 1) {
torture_result(tctx, TORTURE_FAIL,
"(%s) Incorrect resource fork size\n",
__location__);
ret = false;
- smb2_util_close(tree1, filehandle);
+ smb2_util_close(tree, filehandle);
goto done;
}
- smb2_util_close(tree1, filehandle);
+ smb2_util_close(tree, filehandle);
done:
- smb2_deltree(tree1, BASEDIR);
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
talloc_free(mem_ctx);
return ret;
}
static bool test_rfork_truncate(struct torture_context *tctx,
- struct smb2_tree *tree1,
- struct smb2_tree *tree2)
+ struct smb2_tree *tree)
{
TALLOC_CTX *mem_ctx = talloc_new(tctx);
const char *fname = BASEDIR "\\torture_rfork_truncate";
@@ -1443,18 +1602,18 @@ static bool test_rfork_truncate(struct torture_context *tctx,
struct smb2_handle fh1, fh2, fh3;
union smb_setfileinfo sinfo;
- smb2_util_unlink(tree1, fname);
+ smb2_util_unlink(tree, fname);
- status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
- smb2_util_close(tree1, testdirh);
+ smb2_util_close(tree, testdirh);
- ret = torture_setup_file(mem_ctx, tree1, fname, false);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
if (ret == false) {
goto done;
}
- ret &= write_stream(tree1, __location__, tctx, mem_ctx,
+ ret &= write_stream(tree, __location__, tctx, mem_ctx,
fname, AFPRESOURCE_STREAM,
10, 10, rfork_content);
@@ -1471,7 +1630,7 @@ static bool test_rfork_truncate(struct torture_context *tctx,
create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE;
- status = smb2_create(tree1, mem_ctx, &create);
+ status = smb2_create(tree, mem_ctx, &create);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
fh1 = create.out.file.handle;
@@ -1483,7 +1642,7 @@ static bool test_rfork_truncate(struct torture_context *tctx,
create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE;
- status = smb2_create(tree1, mem_ctx, &create);
+ status = smb2_create(tree, mem_ctx, &create);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
fh2 = create.out.file.handle;
@@ -1491,7 +1650,7 @@ static bool test_rfork_truncate(struct torture_context *tctx,
sinfo.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
sinfo.end_of_file_info.in.file.handle = fh2;
sinfo.end_of_file_info.in.size = 0;
- status = smb2_setinfo_file(tree1, &sinfo);
+ status = smb2_setinfo_file(tree, &sinfo);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file");
/*
@@ -1505,7 +1664,7 @@ static bool test_rfork_truncate(struct torture_context *tctx,
create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE;
- status = smb2_create(tree1, mem_ctx, &create);
+ status = smb2_create(tree, mem_ctx, &create);
torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
/*
@@ -1523,31 +1682,30 @@ static bool test_rfork_truncate(struct torture_context *tctx,
create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE;
- status = smb2_create(tree1, mem_ctx, &create);
+ status = smb2_create(tree, mem_ctx, &create);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
fh3 = create.out.file.handle;
- status = smb2_util_write(tree1, fh3, "foo", 0, 3);
+ status = smb2_util_write(tree, fh3, "foo", 0, 3);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write");
- smb2_util_close(tree1, fh3);
- smb2_util_close(tree1, fh2);
- smb2_util_close(tree1, fh1);
+ smb2_util_close(tree, fh3);
+ smb2_util_close(tree, fh2);
+ smb2_util_close(tree, fh1);
- ret = check_stream(tree1, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM,
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM,
0, 3, 0, 3, "foo");
torture_assert_goto(tctx, ret == true, ret, done, "check_stream");
done:
- smb2_util_unlink(tree1, fname);
- smb2_deltree(tree1, BASEDIR);
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
talloc_free(mem_ctx);
return ret;
}
static bool test_rfork_create(struct torture_context *tctx,
- struct smb2_tree *tree1,
- struct smb2_tree *tree2)
+ struct smb2_tree *tree)
{
TALLOC_CTX *mem_ctx = talloc_new(tctx);
const char *fname = BASEDIR "\\torture_rfork_create";
@@ -1562,13 +1720,13 @@ static bool test_rfork_create(struct torture_context *tctx,
};
union smb_fileinfo finfo;
- smb2_util_unlink(tree1, fname);
+ smb2_util_unlink(tree, fname);
- status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
- smb2_util_close(tree1, testdirh);
+ smb2_util_close(tree, testdirh);
- ret = torture_setup_file(mem_ctx, tree1, fname, false);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
if (ret == false) {
goto done;
}
@@ -1584,7 +1742,7 @@ static bool test_rfork_create(struct torture_context *tctx,
create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE;
- status = smb2_create(tree1, mem_ctx, &create);
+ status = smb2_create(tree, mem_ctx, &create);
torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
torture_comment(tctx, "(%s) create resource fork\n", __location__);
@@ -1597,7 +1755,7 @@ static bool test_rfork_create(struct torture_context *tctx,
create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE;
- status = smb2_create(tree1, mem_ctx, &create);
+ status = smb2_create(tree, mem_ctx, &create);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
fh1 = create.out.file.handle;
@@ -1607,14 +1765,14 @@ static bool test_rfork_create(struct torture_context *tctx,
ZERO_STRUCT(finfo);
finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
finfo.generic.in.file.handle = fh1;
- status = smb2_getinfo_file(tree1, mem_ctx, &finfo);
+ status = smb2_getinfo_file(tree, mem_ctx, &finfo);
torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file");
if (finfo.all_info.out.size != 0) {
torture_result(tctx, TORTURE_FAIL,
"(%s) Incorrect resource fork size\n",
__location__);
ret = false;
- smb2_util_close(tree1, fh1);
+ smb2_util_close(tree, fh1);
goto done;
}
@@ -1629,25 +1787,15 @@ static bool test_rfork_create(struct torture_context *tctx,
create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE;
- status = smb2_create(tree1, mem_ctx, &create);
+ status = smb2_create(tree, mem_ctx, &create);
torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
- ZERO_STRUCT(create);
- create.in.fname = fname;
- create.in.create_disposition = NTCREATEX_DISP_OPEN;
- create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
- create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
- status = smb2_create(tree1, mem_ctx, &create);
- torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
-
- ret = check_stream_list(tree1, tctx, fname, 1, streams,
- create.out.file.handle);
+ ret = check_stream_list(tree, tctx, fname, 1, streams, false);
torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
- smb2_util_close(tree1, create.out.file.handle);
torture_comment(tctx, "(%s) close empty created rfork, open should return ENOENT\n",
__location__);
- smb2_util_close(tree1, fh1);
+
ZERO_STRUCT(create);
create.in.create_disposition = NTCREATEX_DISP_OPEN;
create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
@@ -1656,19 +1804,18 @@ static bool test_rfork_create(struct torture_context *tctx,
create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE;
- status = smb2_create(tree1, mem_ctx, &create);
+ status = smb2_create(tree, mem_ctx, &create);
torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
done:
- smb2_util_unlink(tree1, fname);
- smb2_deltree(tree1, BASEDIR);
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
talloc_free(mem_ctx);
return ret;
}
static bool test_adouble_conversion(struct torture_context *tctx,
- struct smb2_tree *tree1,
- struct smb2_tree *tree2)
+ struct smb2_tree *tree)
{
TALLOC_CTX *mem_ctx = talloc_new(tctx);
const char *fname = BASEDIR "\\test_adouble_conversion";
@@ -1679,12 +1826,18 @@ static bool test_adouble_conversion(struct torture_context *tctx,
bool ret = true;
const char *data = "This resource fork intentionally left blank";
size_t datalen = strlen(data);
+ const char *localdir = NULL;
- smb2_util_unlink(tree1, fname);
+ localdir = torture_setting_string(tctx, "localdir", NULL);
+ if (localdir == NULL) {
+ torture_skip(tctx, "Need localdir for test");
+ }
+
+ smb2_util_unlink(tree, fname);
- status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
CHECK_STATUS(status, NT_STATUS_OK);
- smb2_util_close(tree1, testdirh);
+ smb2_util_close(tree, testdirh);
ret = torture_setup_local_file(tctx, "localdir", fname_local,
NULL, 0);
@@ -1702,19 +1855,18 @@ static bool test_adouble_conversion(struct torture_context *tctx,
torture_comment(tctx, "(%s) test OS X AppleDouble conversion\n",
__location__);
- ret &= check_stream(tree1, __location__, tctx, mem_ctx,
+ ret &= check_stream(tree, __location__, tctx, mem_ctx,
fname, AFPRESOURCE_STREAM,
16, datalen, 0, datalen, data);
done:
- smb2_deltree(tree1, BASEDIR);
+ smb2_deltree(tree, BASEDIR);
talloc_free(mem_ctx);
return ret;
}
static bool test_aapl(struct torture_context *tctx,
- struct smb2_tree *tree1,
- struct smb2_tree *tree2)
+ struct smb2_tree *tree)
{
TALLOC_CTX *mem_ctx = talloc_new(tctx);
const char *fname = BASEDIR "\\test_aapl";
@@ -1737,11 +1889,11 @@ static bool test_aapl(struct torture_context *tctx,
union smb_search_data *d;
uint64_t rfork_len;
- smb2_deltree(tree1, BASEDIR);
+ smb2_deltree(tree, BASEDIR);
- status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
+ status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
CHECK_STATUS(status, NT_STATUS_OK);
- smb2_util_close(tree1, testdirh);
+ smb2_util_close(tree, testdirh);
ZERO_STRUCT(io);
io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
@@ -1771,9 +1923,9 @@ static bool test_aapl(struct torture_context *tctx,
status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
CHECK_STATUS(status, NT_STATUS_OK);
- status = smb2_create(tree1, tctx, &io);
+ status = smb2_create(tree, tctx, &io);
CHECK_STATUS(status, NT_STATUS_OK);
- status = smb2_util_close(tree1, io.out.file.handle);
+ status = smb2_util_close(tree, io.out.file.handle);
CHECK_STATUS(status, NT_STATUS_OK);
/*
@@ -1799,8 +1951,9 @@ static bool test_aapl(struct torture_context *tctx,
* uint32_t ModelStringLen = 10;
* ucs2_t ModelString[5] = "Samba";
*/
- ret = false;
- goto done;
+ torture_warning(tctx,
+ "(%s) unexpected AAPL context length: %zd, expected 50",
+ __location__, aapl->data.length);
}
aapl_cmd = IVAL(aapl->data.data, 0);
@@ -1838,11 +1991,9 @@ static bool test_aapl(struct torture_context *tctx,
aapl_vol_caps = BVAL(aapl->data.data, 24);
if (aapl_vol_caps != SMB2_CRTCTX_AAPL_CASE_SENSITIVE) {
/* this will fail on a case insensitive fs ... */
- torture_result(tctx, TORTURE_FAIL,
- "(%s) unexpected vol_caps: %d",
- __location__, (int)aapl_vol_caps);
- ret = false;
- goto done;
+ torture_warning(tctx,
+ "(%s) unexpected vol_caps: %d",
+ __location__, (int)aapl_vol_caps);
}
ret = convert_string_talloc(mem_ctx,
@@ -1861,7 +2012,7 @@ static bool test_aapl(struct torture_context *tctx,
* Now that Requested AAPL extensions are enabled, setup some
* Mac files with metadata and resource fork
*/
- ret = torture_setup_file(mem_ctx, tree1, fname, false);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
if (ret == false) {
torture_result(tctx, TORTURE_FAIL,
"(%s) torture_setup_file() failed",
@@ -1879,7 +2030,7 @@ static bool test_aapl(struct torture_context *tctx,
}
memcpy(info->afpi_FinderInfo, type_creator, 8);
- ret = torture_write_afpinfo(tree1, tctx, mem_ctx, fname, info);
+ ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
if (ret == false) {
torture_result(tctx, TORTURE_FAIL,
"(%s) torture_write_afpinfo() failed",
@@ -1887,8 +2038,8 @@ static bool test_aapl(struct torture_context *tctx,
goto done;
}
- ret = write_stream(tree1, __location__, tctx, mem_ctx,
- fname, AFPRESOURCE_STREAM,
+ ret = write_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
0, 3, "foo");
if (ret == false) {
torture_result(tctx, TORTURE_FAIL,
@@ -1902,7 +2053,7 @@ static bool test_aapl(struct torture_context *tctx,
*/
ZERO_STRUCT(io);
- io.in.desired_access = SEC_RIGHTS_DIR_ALL;
+ io.in.desired_access = SEC_RIGHTS_DIR_READ;
io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
@@ -1910,7 +2061,7 @@ static bool test_aapl(struct torture_context *tctx,
NTCREATEX_SHARE_ACCESS_DELETE);
io.in.create_disposition = NTCREATEX_DISP_OPEN;
io.in.fname = BASEDIR;
- status = smb2_create(tree1, tctx, &io);
+ status = smb2_create(tree, tctx, &io);
CHECK_STATUS(status, NT_STATUS_OK);
ZERO_STRUCT(f);
@@ -1920,10 +2071,10 @@ static bool test_aapl(struct torture_context *tctx,
f.in.max_response_size = 0x1000;
f.in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
- status = smb2_find_level(tree1, tree1, &f, &count, &d);
+ status = smb2_find_level(tree, tree, &f, &count, &d);
CHECK_STATUS(status, NT_STATUS_OK);
- status = smb2_util_close(tree1, io.out.file.handle);
+ status = smb2_util_close(tree, io.out.file.handle);
CHECK_STATUS(status, NT_STATUS_OK);
if (strcmp(d[0].id_both_directory_info.name.s, "test_aapl") != 0) {
@@ -1974,6 +2125,8 @@ static bool test_aapl(struct torture_context *tctx,
}
done:
+ smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
talloc_free(mem_ctx);
return ret;
}
@@ -2426,58 +2579,76 @@ static bool check_stream_list(struct smb2_tree *tree,
const char *fname,
int num_exp,
const char **exp,
- struct smb2_handle h)
+ bool is_dir)
{
+ bool ret = true;
union smb_fileinfo finfo;
NTSTATUS status;
int i;
TALLOC_CTX *tmp_ctx = talloc_new(tctx);
char **exp_sort;
struct stream_struct *stream_sort;
+ struct smb2_create create;
+ struct smb2_handle h;
+
+ ZERO_STRUCT(h);
+ torture_assert_goto(tctx, tmp_ctx != NULL, ret, done, "talloc_new failed");
+
+ ZERO_STRUCT(create);
+ create.in.fname = fname;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.create_options = is_dir ? NTCREATEX_OPTIONS_DIRECTORY : 0;
+ create.in.file_attributes = is_dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
+ status = smb2_create(tree, tmp_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
+ h = create.out.file.handle;
finfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
finfo.generic.in.file.handle = h;
status = smb2_getinfo_file(tree, tctx, &finfo);
- torture_assert_ntstatus_ok(tctx, status, "get stream info");
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "get stream info");
+
+ smb2_util_close(tree, h);
- torture_assert_int_equal(tctx, finfo.stream_info.out.num_streams, num_exp,
- "stream count");
+ torture_assert_int_equal_goto(tctx, finfo.stream_info.out.num_streams, num_exp,
+ ret, done, "stream count");
if (num_exp == 0) {
TALLOC_FREE(tmp_ctx);
- return true;
+ goto done;
}
exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp));
- torture_assert(tctx, exp_sort != NULL, __location__);
+ torture_assert_goto(tctx, exp_sort != NULL, ret, done, __location__);
TYPESAFE_QSORT(exp_sort, num_exp, qsort_string);
stream_sort = talloc_memdup(tmp_ctx, finfo.stream_info.out.streams,
finfo.stream_info.out.num_streams *
sizeof(*stream_sort));
- torture_assert(tctx, stream_sort != NULL, __location__);
+ torture_assert_goto(tctx, stream_sort != NULL, ret, done, __location__);
TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream);
for (i=0; i<num_exp; i++) {
torture_comment(tctx, "i[%d] exp[%s] got[%s]\n",
i, exp_sort[i], stream_sort[i].stream_name.s);
- torture_assert_str_equal(tctx, stream_sort[i].stream_name.s, exp_sort[i],
- "stream name");
+ torture_assert_str_equal_goto(tctx, stream_sort[i].stream_name.s, exp_sort[i],
+ ret, done, "stream name");
}
+done:
TALLOC_FREE(tmp_ctx);
- return true;
+ return ret;
}
/*
test stream names
*/
static bool test_stream_names(struct torture_context *tctx,
- struct smb2_tree *tree,
- struct smb2_tree *tree2)
+ struct smb2_tree *tree)
{
TALLOC_CTX *mem_ctx = talloc_new(tctx);
NTSTATUS status;
@@ -2492,6 +2663,12 @@ static bool test_stream_names(struct torture_context *tctx,
":bar" "\xef\x80\xa2" "baz:$DATA", /* "bar:baz:$DATA" */
"::$DATA"
};
+ const char *localdir = NULL;
+
+ localdir = torture_setting_string(tctx, "localdir", NULL);
+ if (localdir == NULL) {
+ torture_skip(tctx, "Need localdir for test");
+ }
sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
@@ -2525,35 +2702,829 @@ static bool test_stream_names(struct torture_context *tctx,
"data", strlen("data"));
CHECK_VALUE(ret, true);
+ ret = check_stream_list(tree, tctx, fname, 3, streams, false);
+ CHECK_VALUE(ret, true);
+
+done:
+ status = smb2_util_unlink(tree, fname);
+ smb2_deltree(tree, BASEDIR);
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+/* Renaming a directory with open file, should work for OS X AAPL clients */
+static bool test_rename_dir_openfile(struct torture_context *torture,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ union smb_open io;
+ union smb_close cl;
+ union smb_setfileinfo sinfo;
+ struct smb2_handle d1, h1;
+ const char *renamedir = BASEDIR "-new";
+ bool server_is_osx = torture_setting_bool(torture, "osx", false);
+
+ smb2_deltree(tree, BASEDIR);
+ smb2_util_rmdir(tree, BASEDIR);
+ smb2_deltree(tree, renamedir);
+
+ ZERO_STRUCT(io.smb2);
+ io.generic.level = RAW_OPEN_SMB2;
+ io.smb2.in.create_flags = 0;
+ io.smb2.in.desired_access = 0x0017019f;
+ io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+ io.smb2.in.share_access = 0;
+ io.smb2.in.alloc_size = 0;
+ io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
+ io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+ io.smb2.in.security_flags = 0;
+ io.smb2.in.fname = BASEDIR;
+
+ status = smb2_create(tree, torture, &(io.smb2));
+ torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
+ d1 = io.smb2.out.file.handle;
+
+ ZERO_STRUCT(io.smb2);
+ io.generic.level = RAW_OPEN_SMB2;
+ io.smb2.in.create_flags = 0;
+ io.smb2.in.desired_access = 0x0017019f;
+ io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
+ io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ io.smb2.in.share_access = 0;
+ io.smb2.in.alloc_size = 0;
+ io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
+ io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+ io.smb2.in.security_flags = 0;
+ io.smb2.in.fname = BASEDIR "\\file.txt";
+
+ status = smb2_create(tree, torture, &(io.smb2));
+ torture_assert_ntstatus_ok(torture, status, "smb2_create file");
+ h1 = io.smb2.out.file.handle;
+
+ if (!server_is_osx) {
+ torture_comment(torture, "Renaming directory without AAPL, must fail\n");
+
+ ZERO_STRUCT(sinfo);
+ sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
+ sinfo.rename_information.in.file.handle = d1;
+ sinfo.rename_information.in.overwrite = 0;
+ sinfo.rename_information.in.root_fid = 0;
+ sinfo.rename_information.in.new_name = renamedir;
+ status = smb2_setinfo_file(tree, &sinfo);
+
+ torture_assert_ntstatus_equal(torture, status,
+ NT_STATUS_ACCESS_DENIED,
+ "smb2_setinfo_file");
+
+ ZERO_STRUCT(cl.smb2);
+ cl.smb2.level = RAW_CLOSE_SMB2;
+ cl.smb2.in.file.handle = d1;
+ status = smb2_close(tree, &(cl.smb2));
+ torture_assert_ntstatus_ok(torture, status, "smb2_close");
+ ZERO_STRUCT(d1);
+ }
+
+ torture_comment(torture, "Enabling AAPL\n");
+
+ ret = enable_aapl(torture, tree);
+ torture_assert(torture, ret == true, "enable_aapl failed");
+
+ torture_comment(torture, "Renaming directory with AAPL\n");
+
+ ZERO_STRUCT(io.smb2);
+ io.generic.level = RAW_OPEN_SMB2;
+ io.smb2.in.desired_access = 0x0017019f;
+ io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+ io.smb2.in.share_access = 0;
+ io.smb2.in.alloc_size = 0;
+ io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
+ io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+ io.smb2.in.security_flags = 0;
+ io.smb2.in.fname = BASEDIR;
+
+ status = smb2_create(tree, torture, &(io.smb2));
+ torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
+ d1 = io.smb2.out.file.handle;
+
+ ZERO_STRUCT(sinfo);
+ sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
+ sinfo.rename_information.in.file.handle = d1;
+ sinfo.rename_information.in.overwrite = 0;
+ sinfo.rename_information.in.root_fid = 0;
+ sinfo.rename_information.in.new_name = renamedir;
+
+ status = smb2_setinfo_file(tree, &sinfo);
+ torture_assert_ntstatus_ok(torture, status, "smb2_setinfo_file");
+
+ ZERO_STRUCT(cl.smb2);
+ cl.smb2.level = RAW_CLOSE_SMB2;
+ cl.smb2.in.file.handle = d1;
+ status = smb2_close(tree, &(cl.smb2));
+ torture_assert_ntstatus_ok(torture, status, "smb2_close");
+ ZERO_STRUCT(d1);
+
+ cl.smb2.in.file.handle = h1;
+ status = smb2_close(tree, &(cl.smb2));
+ torture_assert_ntstatus_ok(torture, status, "smb2_close");
+ ZERO_STRUCT(h1);
+
+ torture_comment(torture, "Cleaning up\n");
+
+ if (h1.data) {
+ ZERO_STRUCT(cl.smb2);
+ cl.smb2.level = RAW_CLOSE_SMB2;
+ cl.smb2.in.file.handle = h1;
+ status = smb2_close(tree, &(cl.smb2));
+ }
+
+ smb2_util_unlink(tree, BASEDIR "\\file.txt");
+ smb2_util_unlink(tree, BASEDIR "-new\\file.txt");
+ smb2_deltree(tree, renamedir);
+ smb2_deltree(tree, BASEDIR);
+ return ret;
+}
+
+static bool test_afpinfo_enoent(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create;
+ struct smb2_handle h1;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
+
+ torture_comment(tctx, "Opening file without AFP_AfpInfo\n");
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+ smb2_util_close(tree, h1);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
+
ZERO_STRUCT(create);
- create.in.fname = fname;
create.in.create_disposition = NTCREATEX_DISP_OPEN;
- create.in.desired_access = SEC_RIGHTS_FILE_ALL;
- create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
- create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
+ create.in.fname = sname;
+
status = smb2_create(tree, mem_ctx, &create);
- CHECK_STATUS(status, NT_STATUS_OK);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "Got unexpected AFP_AfpInfo stream");
- ret = check_stream_list(tree, tctx, fname, 3, streams,
- create.out.file.handle);
- CHECK_VALUE(ret, true);
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
+ return ret;
+}
- smb2_util_close(tree, create.out.file.handle);
+static bool test_create_delete_on_close(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create;
+ struct smb2_handle h1;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
+ const char *type_creator = "SMB,OLE!";
+ AfpInfo *info = NULL;
+ const char *streams_basic[] = {
+ "::$DATA"
+ };
+ const char *streams_afpinfo[] = {
+ "::$DATA",
+ AFPINFO_STREAM
+ };
+
+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+ torture_comment(tctx, "Checking whether create with delete-on-close work with AFP_AfpInfo\n");
-done:
- status = smb2_util_unlink(tree, fname);
smb2_deltree(tree, BASEDIR);
- talloc_free(mem_ctx);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+ smb2_util_close(tree, h1);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
+ create.in.fname = sname;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "Got unexpected AFP_AfpInfo stream");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "Got unexpected AFP_AfpInfo stream");
+
+ ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ torture_comment(tctx, "Deleting AFP_AfpInfo via create with delete-on-close\n");
+
+ info = torture_afpinfo_new(mem_ctx);
+ torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
+
+ memcpy(info->afpi_FinderInfo, type_creator, 8);
+ ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 0, 60, 16, 8, type_creator);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad type/creator in AFP_AfpInfo");
+
+ ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+ smb2_util_close(tree, h1);
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "Got unexpected AFP_AfpInfo stream");
+
+ ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
+ return ret;
+}
+
+static bool test_setinfo_delete_on_close(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create;
+ union smb_setfileinfo sfinfo;
+ struct smb2_handle h1;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
+ const char *type_creator = "SMB,OLE!";
+ AfpInfo *info = NULL;
+ const char *streams_basic[] = {
+ "::$DATA"
+ };
+
+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+ torture_comment(tctx, "Deleting AFP_AfpInfo via setinfo with delete-on-close\n");
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+ smb2_util_close(tree, h1);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ info = torture_afpinfo_new(mem_ctx);
+ torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
+ memcpy(info->afpi_FinderInfo, type_creator, 8);
+ ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+
+ /* Delete stream via setinfo delete-on-close */
+ ZERO_STRUCT(sfinfo);
+ sfinfo.disposition_info.in.delete_on_close = 1;
+ sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
+ sfinfo.generic.in.file.handle = h1;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
+
+ smb2_util_close(tree, h1);
+
+ ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "Got unexpected AFP_AfpInfo stream");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
+ return ret;
+}
+
+static bool test_setinfo_eof(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create;
+ union smb_setfileinfo sfinfo;
+ struct smb2_handle h1;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
+ const char *type_creator = "SMB,OLE!";
+ AfpInfo *info = NULL;
+ const char *streams_afpinfo[] = {
+ "::$DATA",
+ AFPINFO_STREAM
+ };
+
+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+ torture_comment(tctx, "Set AFP_AfpInfo EOF to 61, 1 and 0\n");
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+ smb2_util_close(tree, h1);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ info = torture_afpinfo_new(mem_ctx);
+ torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
+ memcpy(info->afpi_FinderInfo, type_creator, 8);
+ ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+
+ torture_comment(tctx, "Set AFP_AfpInfo EOF to 61\n");
+
+ /* Test setinfo end-of-file info */
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.position_information.in.position = 61;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ALLOTTED_SPACE_EXCEEDED,
+ ret, done, "set eof 61 failed");
+
+ torture_comment(tctx, "Set AFP_AfpInfo EOF to 1\n");
+
+ /* Truncation returns success, but has no effect */
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.position_information.in.position = 1;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status,
+ ret, done, "set eof 1 failed");
+ smb2_util_close(tree, h1);
+
+ ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 0, 60, 16, 8, type_creator);
+ torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+
+ /*
+ * Delete stream via setinfo end-of-file info to 0, should
+ * return success but stream MUST NOT deleted
+ */
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.position_information.in.position = 0;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
+
+ smb2_util_close(tree, h1);
+
+ ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+ 0, 60, 16, 8, type_creator);
+ torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
+ return ret;
+}
+
+static bool test_afpinfo_all0(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_handle h1;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *type_creator = "SMB,OLE!";
+ AfpInfo *info = NULL;
+ const char *streams_basic[] = {
+ "::$DATA"
+ };
+ const char *streams_afpinfo[] = {
+ "::$DATA",
+ AFPINFO_STREAM
+ };
+
+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+ torture_comment(tctx, "Write all 0 to AFP_AfpInfo and see what happens\n");
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+ smb2_util_close(tree, h1);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ info = torture_afpinfo_new(mem_ctx);
+ torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
+ memcpy(info->afpi_FinderInfo, type_creator, 8);
+ ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+ ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ /* Write all 0 to AFP_AfpInfo */
+ memset(info->afpi_FinderInfo, 0, AFP_FinderSize);
+ ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+ ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
+ return ret;
+}
+
+static bool test_create_delete_on_close_resource(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create;
+ struct smb2_handle h1;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
+ const char *streams_basic[] = {
+ "::$DATA"
+ };
+ const char *streams_afpresource[] = {
+ "::$DATA",
+ AFPRESOURCE_STREAM
+ };
+
+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+ torture_comment(tctx, "Checking whether create with delete-on-close is ignored for AFP_AfpResource\n");
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok(tctx, status, "torture_smb2_testdir");
+ smb2_util_close(tree, h1);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ torture_comment(tctx, "Opening not existing AFP_AfpResource\n");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
+ create.in.fname = sname;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "Got unexpected AFP_AfpResource stream");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "Got unexpected AFP_AfpResource stream");
+
+ ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ torture_comment(tctx, "Trying to delete AFP_AfpResource via create with delete-on-close\n");
+
+ ret = write_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
+ 0, 10, "1234567890");
+ torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
+ 0, 10, 0, 10, "1234567890");
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
+
+ ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+ smb2_util_close(tree, h1);
+
+ ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
+ 0, 10, 0, 10, "1234567890");
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
+ return ret;
+}
+
+static bool test_setinfo_delete_on_close_resource(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create;
+ union smb_setfileinfo sfinfo;
+ struct smb2_handle h1;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
+ const char *streams_afpresource[] = {
+ "::$DATA",
+ AFPRESOURCE_STREAM
+ };
+
+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+ torture_comment(tctx, "Trying to delete AFP_AfpResource via setinfo with delete-on-close\n");
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+ smb2_util_close(tree, h1);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ ret = write_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
+ 10, 10, "1234567890");
+ torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+
+ /* Try to delete stream via setinfo delete-on-close */
+ ZERO_STRUCT(sfinfo);
+ sfinfo.disposition_info.in.delete_on_close = 1;
+ sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
+ sfinfo.generic.in.file.handle = h1;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
+
+ smb2_util_close(tree, h1);
+
+ ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+ "Got unexpected AFP_AfpResource stream");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
+ return ret;
+}
+
+static bool test_setinfo_eof_resource(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ bool ret = true;
+ NTSTATUS status;
+ struct smb2_create create;
+ union smb_setfileinfo sfinfo;
+ union smb_fileinfo finfo;
+ struct smb2_handle h1;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ const char *fname = BASEDIR "\\file";
+ const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
+ const char *streams_basic[] = {
+ "::$DATA"
+ };
+
+ torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+ torture_comment(tctx, "Set AFP_AfpResource EOF to 1 and 0\n");
+
+ smb2_deltree(tree, BASEDIR);
+ status = torture_smb2_testdir(tree, BASEDIR, &h1);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+ smb2_util_close(tree, h1);
+ ret = torture_setup_file(mem_ctx, tree, fname, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+ ret = write_stream(tree, __location__, tctx, mem_ctx,
+ fname, AFPRESOURCE_STREAM_NAME,
+ 10, 10, "1234567890");
+ torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+
+ torture_comment(tctx, "Set AFP_AfpResource EOF to 1\n");
+
+ /* Test setinfo end-of-file info */
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.position_information.in.position = 1;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status,
+ ret, done, "set eof 1 failed");
+
+ smb2_util_close(tree, h1);
+
+ /* Check size == 1 */
+ ZERO_STRUCT(create);
+ create.in.fname = sname;
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+
+ ZERO_STRUCT(finfo);
+ finfo.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
+ finfo.generic.in.file.handle = h1;
+ status = smb2_getinfo_file(tree, mem_ctx, &finfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file failed");
+
+ smb2_util_close(tree, h1);
+
+ torture_assert_goto(tctx, finfo.all_info.out.size == 1, ret, done, "size != 1");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+ h1 = create.out.file.handle;
+
+ /*
+ * Delete stream via setinfo end-of-file info to 0, this
+ * should delete the stream.
+ */
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+ sfinfo.position_information.in.position = 0;
+ status = smb2_setinfo_file(tree, &sfinfo);
+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
+
+ smb2_util_close(tree, h1);
+
+ ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+ torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+ ZERO_STRUCT(create);
+ create.in.create_disposition = NTCREATEX_DISP_OPEN;
+ create.in.desired_access = SEC_FILE_ALL;
+ create.in.fname = sname;
+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+ status = smb2_create(tree, mem_ctx, &create);
+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ret, done, "smb2_create failed");
+
+done:
+ smb2_util_unlink(tree, fname);
+ smb2_util_rmdir(tree, BASEDIR);
return ret;
}
/*
- * Note: This test depends on "vfs objects = catia fruit
- * streams_xattr". Note: To run this test, use
- * "--option=torture:share1=<SHARENAME1>
- * --option=torture:share2=<SHARENAME2>
- * --option=torture:localdir=<SHAREPATH>"
+ * Note: This test depends on "vfs objects = catia fruit streams_xattr". For
+ * some tests torture must be run on the host it tests and takes an additional
+ * argument with the local path to the share:
+ * "--option=torture:localdir=<SHAREPATH>".
+ *
+ * When running against an OS X SMB server add "--option=torture:osx=true"
*/
struct torture_suite *torture_vfs_fruit(void)
{
@@ -2563,14 +3534,24 @@ struct torture_suite *torture_vfs_fruit(void)
suite->description = talloc_strdup(suite, "vfs_fruit tests");
torture_suite_add_1smb2_test(suite, "copyfile", test_copyfile);
- torture_suite_add_2ns_smb2_test(suite, "read metadata", test_read_atalk_metadata);
- torture_suite_add_2ns_smb2_test(suite, "write metadata", test_write_atalk_metadata);
- torture_suite_add_2ns_smb2_test(suite, "resource fork IO", test_write_atalk_rfork_io);
- torture_suite_add_2ns_smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion);
- torture_suite_add_2ns_smb2_test(suite, "SMB2/CREATE context AAPL", test_aapl);
- torture_suite_add_2ns_smb2_test(suite, "stream names", test_stream_names);
- torture_suite_add_2ns_smb2_test(suite, "truncate resource fork to 0 bytes", test_rfork_truncate);
- torture_suite_add_2ns_smb2_test(suite, "opening and creating resource fork", test_rfork_create);
+ torture_suite_add_1smb2_test(suite, "read netatalk metadata", test_read_netatalk_metadata);
+ torture_suite_add_1smb2_test(suite, "read metadata", test_read_afpinfo);
+ torture_suite_add_1smb2_test(suite, "write metadata", test_write_atalk_metadata);
+ torture_suite_add_1smb2_test(suite, "resource fork IO", test_write_atalk_rfork_io);
+ torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion);
+ torture_suite_add_1smb2_test(suite, "SMB2/CREATE context AAPL", test_aapl);
+ torture_suite_add_1smb2_test(suite, "stream names", test_stream_names);
+ torture_suite_add_1smb2_test(suite, "truncate resource fork to 0 bytes", test_rfork_truncate);
+ torture_suite_add_1smb2_test(suite, "opening and creating resource fork", test_rfork_create);
+ torture_suite_add_1smb2_test(suite, "rename_dir_openfile", test_rename_dir_openfile);
+ torture_suite_add_1smb2_test(suite, "File without AFP_AfpInfo", test_afpinfo_enoent);
+ torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpInfo", test_create_delete_on_close);
+ torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpInfo", test_setinfo_delete_on_close);
+ torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpInfo", test_setinfo_eof);
+ torture_suite_add_1smb2_test(suite, "delete AFP_AfpInfo by writing all 0", test_afpinfo_all0);
+ torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpResource", test_create_delete_on_close_resource);
+ torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpResource", test_setinfo_delete_on_close_resource);
+ torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpResource", test_setinfo_eof_resource);
return suite;
}
diff --git a/testprogs/blackbox/dfree.sh b/testprogs/blackbox/dfree.sh
index 2da3cbd..64845cd 100755
--- a/testprogs/blackbox/dfree.sh
+++ b/testprogs/blackbox/dfree.sh
@@ -1,2 +1,8 @@
#!/bin/sh
-echo "1000 10 2048"
+if [ "$1" = "." ] ; then
+ echo "1000 10 2048"
+elif [ "$1" = "subdir1" ] ; then
+ echo "2000 20 4096"
+else
+ echo "4000 40 8192"
+fi
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-samba/samba.git
More information about the Pkg-samba-maint
mailing list