[Pkg-samba-maint] Bug#857339: unblock: samba/2:4.5.6+dfsg-1

Mathieu Parent sathieu at debian.org
Fri Mar 10 08:37:38 UTC 2017


Package: release.debian.org
Severity: normal
User: release.debian.org at packages.debian.org
Usertags: unblock

Please unblock package samba

This includes all latest stability fixes from upstream in the 4.5 branch
and a fix for a typo in smbd.service and winbind.service (#857232):
  s/nmb.service/nmbd.service

See attached (big) debdiff.

unblock samba/2:4.5.6+dfsg-1

-- System Information:
Debian Release: 9.0
  APT prefers testing-debug
  APT policy: (500, 'testing-debug'), (500, 'testing')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.9.0-1-amd64 (SMP w/2 CPU cores)
Locale: LANG=fr_FR.utf8, LC_CTYPE=fr_FR.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
-------------- next part --------------
diff -Nru samba-4.5.5+dfsg/auth/credentials/credentials_secrets.c samba-4.5.6+dfsg/auth/credentials/credentials_secrets.c
--- samba-4.5.5+dfsg/auth/credentials/credentials_secrets.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/auth/credentials/credentials_secrets.c	2017-03-09 10:21:43.000000000 +0100
@@ -39,7 +39,7 @@
 #include "dbwrap/dbwrap.h"
 #include "dbwrap/dbwrap_open.h"
 #include "lib/util/util_tdb.h"
-
+#include "libds/common/roles.h"
 
 /**
  * Fill in credentials for the machine trust account, from the secrets database.
@@ -276,6 +276,8 @@
 	char *secrets_tdb_password = NULL;
 	char *secrets_tdb_old_password = NULL;
 	uint32_t secrets_tdb_secure_channel_type = SEC_CHAN_NULL;
+	int server_role = lpcfg_server_role(lp_ctx);
+	int security = lpcfg_security(lp_ctx);
 	char *keystr;
 	char *keystr_upper = NULL;
 	TALLOC_CTX *tmp_ctx = talloc_named(cred, 0, "cli_credentials_set_secrets from ldb");
@@ -354,13 +356,26 @@
 	}
 
 	if (secrets_tdb_password_more_recent) {
+		enum credentials_use_kerberos use_kerberos = CRED_DONT_USE_KERBEROS;
 		char *machine_account = talloc_asprintf(tmp_ctx, "%s$", lpcfg_netbios_name(lp_ctx));
 		cli_credentials_set_password(cred, secrets_tdb_password, CRED_SPECIFIED);
 		cli_credentials_set_old_password(cred, secrets_tdb_old_password, CRED_SPECIFIED);
 		cli_credentials_set_domain(cred, domain, CRED_SPECIFIED);
 		if (strequal(domain, lpcfg_workgroup(lp_ctx))) {
 			cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx), CRED_SPECIFIED);
+
+			switch (server_role) {
+			case ROLE_DOMAIN_MEMBER:
+				if (security != SEC_ADS) {
+					break;
+				}
+				/* fall through */
+			case ROLE_ACTIVE_DIRECTORY_DC:
+				use_kerberos = CRED_AUTO_USE_KERBEROS;
+				break;
+			}
 		}
+		cli_credentials_set_kerberos_state(cred, use_kerberos);
 		cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED);
 		cli_credentials_set_password_last_changed_time(cred, secrets_tdb_lct);
 		cli_credentials_set_secure_channel_type(cred, secrets_tdb_secure_channel_type);
diff -Nru samba-4.5.5+dfsg/ctdb/common/comm.c samba-4.5.6+dfsg/ctdb/common/comm.c
--- samba-4.5.5+dfsg/ctdb/common/comm.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/ctdb/common/comm.c	2017-03-09 10:21:43.000000000 +0100
@@ -251,14 +251,22 @@
  * Write packets
  */
 
+struct comm_write_entry {
+	struct comm_context *comm;
+	struct tevent_queue_entry *qentry;
+	struct tevent_req *req;
+};
+
 struct comm_write_state {
 	struct tevent_context *ev;
 	struct comm_context *comm;
+	struct comm_write_entry *entry;
 	struct tevent_req *subreq;
 	uint8_t *buf;
 	size_t buflen, nwritten;
 };
 
+static int comm_write_entry_destructor(struct comm_write_entry *entry);
 static void comm_write_trigger(struct tevent_req *req, void *private_data);
 static void comm_write_done(struct tevent_req *subreq);
 
@@ -269,6 +277,7 @@
 {
 	struct tevent_req *req;
 	struct comm_write_state *state;
+	struct comm_write_entry *entry;
 
 	req = tevent_req_create(mem_ctx, &state, struct comm_write_state);
 	if (req == NULL) {
@@ -280,15 +289,38 @@
 	state->buf = buf;
 	state->buflen = buflen;
 
-	if (!tevent_queue_add_entry(comm->queue, ev, req,
-				    comm_write_trigger, NULL)) {
-		talloc_free(req);
-		return NULL;
+	entry = talloc_zero(state, struct comm_write_entry);
+	if (tevent_req_nomem(entry, req)) {
+		return tevent_req_post(req, ev);
+	}
+
+	entry->comm = comm;
+	entry->req = req;
+	entry->qentry = tevent_queue_add_entry(comm->queue, ev, req,
+					       comm_write_trigger, NULL);
+	if (tevent_req_nomem(entry->qentry, req)) {
+		return tevent_req_post(req, ev);
 	}
 
+	state->entry = entry;
+	talloc_set_destructor(entry, comm_write_entry_destructor);
+
 	return req;
 }
 
+static int comm_write_entry_destructor(struct comm_write_entry *entry)
+{
+	struct comm_context *comm = entry->comm;
+
+	if (comm->write_req == entry->req) {
+		comm->write_req = NULL;
+		TEVENT_FD_NOT_WRITEABLE(comm->fde);
+	}
+
+	TALLOC_FREE(entry->qentry);
+	return 0;
+}
+
 static void comm_write_trigger(struct tevent_req *req, void *private_data)
 {
 	struct comm_write_state *state = tevent_req_data(
@@ -333,6 +365,8 @@
 	}
 
 	state->nwritten = nwritten;
+	state->entry->qentry = NULL;
+	TALLOC_FREE(state->entry);
 	tevent_req_done(req);
 }
 
@@ -382,8 +416,8 @@
 		struct comm_write_state *write_state;
 
 		if (comm->write_req == NULL) {
-			/* This should never happen */
-			abort();
+			TEVENT_FD_NOT_WRITEABLE(comm->fde);
+			return;
 		}
 
 		write_state = tevent_req_data(comm->write_req,
diff -Nru samba-4.5.5+dfsg/ctdb/config/statd-callout samba-4.5.6+dfsg/ctdb/config/statd-callout
--- samba-4.5.5+dfsg/ctdb/config/statd-callout	2016-12-05 09:18:44.000000000 +0100
+++ samba-4.5.6+dfsg/ctdb/config/statd-callout	2017-03-09 10:21:43.000000000 +0100
@@ -128,6 +128,7 @@
 	# where the lock manager will respond "strangely" immediately
 	# after restarting it, which causes clients to fail to reclaim
 	# their locks.
+	nfs_callout_init
 	"$CTDB_NFS_CALLOUT" "stop" "nlockmgr" >/dev/null 2>&1
         sleep 2
 	"$CTDB_NFS_CALLOUT" "start" "nlockmgr" >/dev/null 2>&1
diff -Nru samba-4.5.5+dfsg/ctdb/tests/cunit/comm_test_001.sh samba-4.5.6+dfsg/ctdb/tests/cunit/comm_test_001.sh
--- samba-4.5.5+dfsg/ctdb/tests/cunit/comm_test_001.sh	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/ctdb/tests/cunit/comm_test_001.sh	2017-03-09 10:21:43.000000000 +0100
@@ -2,6 +2,12 @@
 
 . "${TEST_SCRIPTS_DIR}/unit.sh"
 
-ok "100 2048 500 4096 1024 8192 200 16384 300 32768 400 65536 1048576 "
 
-unit_test comm_test
+ok_null
+unit_test comm_test 1
+
+ok_null
+unit_test comm_test 2
+
+ok "100 2048 500 4096 1024 8192 200 16384 300 32768 400 65536 1048576 "
+unit_test comm_test 3
diff -Nru samba-4.5.5+dfsg/ctdb/tests/eventscripts/etc-ctdb/statd-callout samba-4.5.6+dfsg/ctdb/tests/eventscripts/etc-ctdb/statd-callout
--- samba-4.5.5+dfsg/ctdb/tests/eventscripts/etc-ctdb/statd-callout	2016-12-05 09:18:44.000000000 +0100
+++ samba-4.5.6+dfsg/ctdb/tests/eventscripts/etc-ctdb/statd-callout	2017-03-09 10:21:43.000000000 +0100
@@ -128,6 +128,7 @@
 	# where the lock manager will respond "strangely" immediately
 	# after restarting it, which causes clients to fail to reclaim
 	# their locks.
+	nfs_callout_init
 	"$CTDB_NFS_CALLOUT" "stop" "nlockmgr" >/dev/null 2>&1
         sleep 2
 	"$CTDB_NFS_CALLOUT" "start" "nlockmgr" >/dev/null 2>&1
diff -Nru samba-4.5.5+dfsg/ctdb/tests/src/comm_test.c samba-4.5.6+dfsg/ctdb/tests/src/comm_test.c
--- samba-4.5.5+dfsg/ctdb/tests/src/comm_test.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/ctdb/tests/src/comm_test.c	2017-03-09 10:21:43.000000000 +0100
@@ -26,7 +26,218 @@
 #include "common/pkt_write.c"
 #include "common/comm.c"
 
-static void dead_handler(void *private_data)
+/*
+ * Test read_handler and dead_handler
+ */
+
+static void test1_read_handler(uint8_t *buf, size_t buflen,
+			       void *private_data)
+{
+	int *result = (int *)private_data;
+
+	*result = -1;
+}
+
+static void test1_dead_handler(void *private_data)
+{
+	int *result = (int *)private_data;
+
+	*result = 1;
+}
+
+static void test1(void)
+{
+	TALLOC_CTX *mem_ctx;
+	struct tevent_context *ev;
+	struct comm_context *comm;
+	int fd[2];
+	int result = 0;
+	uint32_t data[2];
+	int ret;
+	ssize_t n;
+
+	mem_ctx = talloc_new(NULL);
+	assert(mem_ctx != NULL);
+
+	ev = tevent_context_init(mem_ctx);
+	assert(ev != NULL);
+
+	ret = pipe(fd);
+	assert(ret == 0);
+
+	ret = comm_setup(ev, ev, fd[0], test1_read_handler, &result,
+			 test1_dead_handler, &result, &comm);
+	assert(ret == 0);
+
+	data[0] = 2 * sizeof(uint32_t);
+	data[1] = 0;
+
+	n = write(fd[1], (void *)&data, data[0]);
+	assert(n == data[0]);
+
+	while (result == 0) {
+		tevent_loop_once(ev);
+	}
+
+	assert(result == -1);
+
+	result = 0;
+	close(fd[1]);
+
+	while (result == 0) {
+		tevent_loop_once(ev);
+	}
+
+	assert(result == 1);
+
+	talloc_free(mem_ctx);
+}
+
+/*
+ * Test that the tevent_req returned by comm_write_send() can be free'd.
+ */
+
+struct test2_state {
+	TALLOC_CTX *mem_ctx;
+	bool done;
+};
+
+static void test2_read_handler(uint8_t *buf, size_t buflen,
+			       void *private_data)
+{
+	struct test2_state *state = (struct test2_state *)private_data;
+
+	TALLOC_FREE(state->mem_ctx);
+}
+
+static void test2_dead_handler(void *private_data)
+{
+	abort();
+}
+
+struct test2_write_state {
+	int count;
+};
+
+static void test2_write_done(struct tevent_req *subreq);
+
+static struct tevent_req *test2_write_send(TALLOC_CTX *mem_ctx,
+					   struct tevent_context *ev,
+					   struct comm_context *comm,
+					   uint8_t *buf, size_t buflen)
+{
+	struct tevent_req *req, *subreq;
+	struct test2_write_state *state;
+	int i;
+
+	req = tevent_req_create(mem_ctx, &state, struct test2_write_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	state->count = 0;
+
+	for (i=0; i<10; i++) {
+		subreq = comm_write_send(state, ev, comm, buf, buflen);
+		if (tevent_req_nomem(subreq, req)) {
+			return tevent_req_post(req, ev);
+		}
+		tevent_req_set_callback(subreq, test2_write_done, req);
+	}
+
+	return req;
+}
+
+static void test2_write_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct test2_write_state *state = tevent_req_data(
+		req, struct test2_write_state);
+	bool status;
+	int ret;
+
+	status = comm_write_recv(subreq, &ret);
+	TALLOC_FREE(subreq);
+	if (! status) {
+		tevent_req_error(req, ret);
+		return;
+	}
+
+	state->count += 1;
+
+	if (state->count == 10) {
+		tevent_req_done(req);
+	}
+}
+
+static void test2_timer_handler(struct tevent_context *ev,
+				struct tevent_timer *te,
+				struct timeval cur_time,
+				void *private_data)
+{
+	struct test2_state *state = (struct test2_state *)private_data;
+
+	state->done = true;
+}
+
+static void test2(void)
+{
+	TALLOC_CTX *mem_ctx;
+	struct tevent_context *ev;
+	struct comm_context *comm_reader, *comm_writer;
+	struct test2_state test2_state;
+	struct tevent_req *req;
+	struct tevent_timer *te;
+	int fd[2];
+	uint32_t data[2];
+	int ret;
+
+	mem_ctx = talloc_new(NULL);
+	assert(mem_ctx != NULL);
+
+	test2_state.mem_ctx = talloc_new(mem_ctx);
+	assert(test2_state.mem_ctx != NULL);
+
+	test2_state.done = false;
+
+	ev = tevent_context_init(mem_ctx);
+	assert(ev != NULL);
+
+	ret = pipe(fd);
+	assert(ret == 0);
+
+	ret = comm_setup(ev, ev, fd[0], test2_read_handler, &test2_state,
+			 test2_dead_handler, NULL, &comm_reader);
+	assert(ret == 0);
+
+	ret = comm_setup(ev, ev, fd[1], NULL, NULL, test2_dead_handler, NULL,
+			 &comm_writer);
+	assert(ret == 0);
+
+	data[0] = 2 * sizeof(uint32_t);
+	data[1] = 0;
+
+	req = test2_write_send(test2_state.mem_ctx, ev, comm_writer,
+			       (uint8_t *)data, data[0]);
+	assert(req != NULL);
+
+	te = tevent_add_timer(ev, ev, tevent_timeval_current_ofs(5,0),
+			      test2_timer_handler, &test2_state);
+	assert(te != NULL);
+
+	while (! test2_state.done) {
+		tevent_loop_once(ev);
+	}
+
+	talloc_free(mem_ctx);
+}
+
+/*
+ * Test that data is written and read correctly.
+ */
+
+static void test3_dead_handler(void *private_data)
 {
 	int dead_data = *(int *)private_data;
 
@@ -34,14 +245,14 @@
 
 	if (dead_data == 1) {
 		/* reader */
-		printf("writer closed pipe\n");
+		fprintf(stderr, "writer closed pipe\n");
 	} else {
 		/* writer */
-		printf("reader closed pipe\n");
+		fprintf(stderr, "reader closed pipe\n");
 	}
 }
 
-struct writer_state {
+struct test3_writer_state {
 	struct tevent_context *ev;
 	struct comm_context *comm;
 	uint8_t *buf;
@@ -49,15 +260,15 @@
 	int count, id;
 };
 
-static void writer_next(struct tevent_req *subreq);
+static void test3_writer_next(struct tevent_req *subreq);
 
-static struct tevent_req *writer_send(TALLOC_CTX *mem_ctx,
-				      struct tevent_context *ev,
-				      struct comm_context *comm,
-				      size_t *pkt_size, int count)
+static struct tevent_req *test3_writer_send(TALLOC_CTX *mem_ctx,
+					    struct tevent_context *ev,
+					    struct comm_context *comm,
+					    size_t *pkt_size, int count)
 {
 	struct tevent_req *req, *subreq;
-	struct writer_state *state;
+	struct test3_writer_state *state;
 	size_t max_size = 0, buflen;
 	int i;
 
@@ -67,7 +278,7 @@
 		}
 	}
 
-	req = tevent_req_create(mem_ctx, &state, struct writer_state);
+	req = tevent_req_create(mem_ctx, &state, struct test3_writer_state);
 	if (req == NULL) {
 		return NULL;
 	}
@@ -95,16 +306,16 @@
 		return tevent_req_post(req, ev);
 	}
 
-	tevent_req_set_callback(subreq, writer_next, req);
+	tevent_req_set_callback(subreq, test3_writer_next, req);
 	return req;
 }
 
-static void writer_next(struct tevent_req *subreq)
+static void test3_writer_next(struct tevent_req *subreq)
 {
 	struct tevent_req *req = tevent_req_callback_data(
 		subreq, struct tevent_req);
-	struct writer_state *state = tevent_req_data(
-		req, struct writer_state);
+	struct test3_writer_state *state = tevent_req_data(
+		req, struct test3_writer_state);
 	bool ret;
 	int err;
 	size_t buflen;
@@ -130,10 +341,10 @@
 		return;
 	}
 
-	tevent_req_set_callback(subreq, writer_next, req);
+	tevent_req_set_callback(subreq, test3_writer_next, req);
 }
 
-static void writer_recv(struct tevent_req *req, int *perr)
+static void test3_writer_recv(struct tevent_req *req, int *perr)
 {
 	if (tevent_req_is_unix_error(req, perr)) {
 		return;
@@ -141,7 +352,7 @@
 	*perr = 0;
 }
 
-static void writer(int fd, size_t *pkt_size, int count)
+static void test3_writer(int fd, size_t *pkt_size, int count)
 {
 	TALLOC_CTX *mem_ctx;
 	struct tevent_context *ev;
@@ -157,31 +368,32 @@
 	assert(ev != NULL);
 
 	err = comm_setup(mem_ctx, ev, fd, NULL, NULL,
-			 dead_handler, &dead_data, &comm);
+			 test3_dead_handler, &dead_data, &comm);
 	assert(err == 0);
 	assert(comm != NULL);
 
-	req = writer_send(mem_ctx, ev, comm, pkt_size, count);
+	req = test3_writer_send(mem_ctx, ev, comm, pkt_size, count);
 	assert(req != NULL);
 
 	tevent_req_poll(req, ev);
 
-	writer_recv(req, &err);
+	test3_writer_recv(req, &err);
 	assert(err == 0);
 
 	talloc_free(mem_ctx);
 }
 
-struct reader_state {
+struct test3_reader_state {
 	size_t *pkt_size;
 	int count, received;
 	bool done;
 };
 
-static void reader_handler(uint8_t *buf, size_t buflen, void *private_data)
+static void test3_reader_handler(uint8_t *buf, size_t buflen,
+				 void *private_data)
 {
-	struct reader_state *state = talloc_get_type_abort(
-		private_data, struct reader_state);
+	struct test3_reader_state *state = talloc_get_type_abort(
+		private_data, struct test3_reader_state);
 
 	assert(buflen == state->pkt_size[state->received]);
 	printf("%zi ", buflen);
@@ -193,12 +405,12 @@
 	}
 }
 
-static void reader(int fd, size_t *pkt_size, int count)
+static void test3_reader(int fd, size_t *pkt_size, int count)
 {
 	TALLOC_CTX *mem_ctx;
 	struct tevent_context *ev;
 	struct comm_context *comm;
-	struct reader_state *state;
+	struct test3_reader_state *state;
 	int dead_data = 1;
 	int err;
 
@@ -208,7 +420,7 @@
 	ev = tevent_context_init(mem_ctx);
 	assert(ev != NULL);
 
-	state = talloc_zero(mem_ctx, struct reader_state);
+	state = talloc_zero(mem_ctx, struct test3_reader_state);
 	assert(state != NULL);
 
 	state->pkt_size = pkt_size;
@@ -216,8 +428,8 @@
 	state->received = 0;
 	state->done = false;
 
-	err = comm_setup(mem_ctx, ev, fd, reader_handler, state,
-			 dead_handler, &dead_data, &comm);
+	err = comm_setup(mem_ctx, ev, fd, test3_reader_handler, state,
+			 test3_dead_handler, &dead_data, &comm);
 	assert(err == 0);
 	assert(comm != NULL);
 
@@ -228,7 +440,7 @@
 	talloc_free(mem_ctx);
 }
 
-int main(void)
+static void test3(void)
 {
 	int fd[2];
 	int ret;
@@ -237,7 +449,6 @@
 			      200, 16384, 300, 32768, 400, 65536,
 			      1024*1024 };
 
-
 	ret = pipe(fd);
 	assert(ret == 0);
 
@@ -247,14 +458,44 @@
 	if (pid == 0) {
 		/* Child process */
 		close(fd[0]);
-		writer(fd[1], pkt_size, 13);
+		test3_writer(fd[1], pkt_size, 13);
 		close(fd[1]);
 		exit(0);
 	}
 
 	close(fd[1]);
-	reader(fd[0], pkt_size, 13);
+	test3_reader(fd[0], pkt_size, 13);
 	close(fd[0]);
+}
+
+
+int main(int argc, const char **argv)
+{
+	int num;
+
+	if (argc != 2) {
+		fprintf(stderr, "%s <testnum>\n", argv[0]);
+		exit(1);
+	}
+
+	num = atoi(argv[1]);
+
+	switch (num) {
+	case 1:
+		test1();
+		break;
+
+	case 2:
+		test2();
+		break;
+
+	case 3:
+		test3();
+		break;
+
+	default:
+		fprintf(stderr, "Unknown test number %s\n", argv[1]);
+	}
 
 	return 0;
 }
diff -Nru samba-4.5.5+dfsg/ctdb/tests/src/test_mutex_raw.c samba-4.5.6+dfsg/ctdb/tests/src/test_mutex_raw.c
--- samba-4.5.5+dfsg/ctdb/tests/src/test_mutex_raw.c	2017-01-30 10:56:26.000000000 +0100
+++ samba-4.5.6+dfsg/ctdb/tests/src/test_mutex_raw.c	2017-03-09 10:21:43.000000000 +0100
@@ -38,21 +38,11 @@
  *  If no pid is printed, then no process is holding the mutex.
  */
 
-#include <stdio.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/wait.h>
-#include <sched.h>
-#include <sys/mman.h>
-#include <pthread.h>
-#include <errno.h>
-#include <stdbool.h>
-
-int pthread_mutex_consistent_np(pthread_mutex_t *);
+#include "replace.h"
+#include "system/filesys.h"
+#include "system/wait.h"
+#include "system/shmem.h"
+#include "system/threads.h"
 
 static void set_realtime(void)
 {
@@ -99,7 +89,7 @@
 again:
 	ret = pthread_mutex_lock(mutex);
 	if (ret == EOWNERDEAD) {
-		ret = pthread_mutex_consistent_np(mutex);
+		ret = pthread_mutex_consistent(mutex);
 	} else if (ret == EAGAIN) {
 		goto again;
 	}
@@ -172,7 +162,7 @@
 	if (strcmp(argv[2], "debug") == 0) {
 		ret = pthread_mutex_trylock(mutex);
 		if (ret == EOWNERDEAD) {
-			ret = pthread_mutex_consistent_np(mutex);
+			ret = pthread_mutex_consistent(mutex);
 			if (ret == 0) {
 				pthread_mutex_unlock(mutex);
 			}
diff -Nru samba-4.5.5+dfsg/ctdb/wscript samba-4.5.6+dfsg/ctdb/wscript
--- samba-4.5.5+dfsg/ctdb/wscript	2017-01-30 10:56:26.000000000 +0100
+++ samba-4.5.6+dfsg/ctdb/wscript	2017-03-09 10:21:43.000000000 +0100
@@ -750,10 +750,11 @@
                               ib_deps,
                          install_path='${CTDB_TEST_LIBEXECDIR}')
 
-    bld.SAMBA_BINARY('test_mutex_raw',
-                     source='tests/src/test_mutex_raw.c',
-                     deps='pthread',
-                     install_path='${CTDB_TEST_LIBEXECDIR}')
+    if bld.env.HAVE_ROBUST_MUTEXES:
+        bld.SAMBA_BINARY('test_mutex_raw',
+                         source='tests/src/test_mutex_raw.c',
+                         deps='pthread',
+                         install_path='${CTDB_TEST_LIBEXECDIR}')
 
     test_subdirs = [
         'complex',
@@ -767,8 +768,13 @@
         'tool'
     ]
 
+    if bld.env.standalone_ctdb:
+        testdir = 'tests'
+    else:
+        testdir = 'ctdb/tests'
+
     for t in test_subdirs:
-        files = SUBDIR_MODE('tests/%s' % t, trim_path='tests')
+        files = SUBDIR_MODE('%s/%s' % (testdir, t), trim_path=testdir)
         for fmode in files:
             bld.INSTALL_FILES(bld.env.CTDB_TEST_DATADIR, 'tests/%s' % fmode[0],
                               destname=fmode[0], chmod=fmode[1])
diff -Nru samba-4.5.5+dfsg/debian/changelog samba-4.5.6+dfsg/debian/changelog
--- samba-4.5.5+dfsg/debian/changelog	2017-03-05 23:21:09.000000000 +0100
+++ samba-4.5.6+dfsg/debian/changelog	2017-03-09 15:42:37.000000000 +0100
@@ -1,3 +1,11 @@
+samba (2:4.5.6+dfsg-1) unstable; urgency=medium
+
+  * New upstream version
+  * Fix typo in smbd.service and winbind.service (s/nmb.service/nmbd.service)
+    (Closes: #857232)
+
+ -- Mathieu Parent <sathieu at debian.org>  Thu, 09 Mar 2017 15:42:37 +0100
+
 samba (2:4.5.5+dfsg-1) unstable; urgency=medium
 
   * New upstream version
diff -Nru samba-4.5.5+dfsg/debian/rules samba-4.5.6+dfsg/debian/rules
--- samba-4.5.5+dfsg/debian/rules	2017-03-05 22:37:17.000000000 +0100
+++ samba-4.5.6+dfsg/debian/rules	2017-03-08 22:53:03.000000000 +0100
@@ -180,9 +180,9 @@
 	mv $(DESTDIR)/lib/systemd/system/samba.service $(DESTDIR)/lib/systemd/system/samba-ad-dc.service
 	sed -i \
 	  -e 's|/etc/sysconfig/|/etc/default/|' \
-	  -e 's|/nmb\.service|nmbd.service|' \
-	  -e 's|/smb\.service|smbd.service|' \
-	  -e 's|/samba\.service|samba-ad-dc.service|' \
+	  -e 's|nmb\.service|nmbd.service|' \
+	  -e 's|smb\.service|smbd.service|' \
+	  -e 's|samba\.service|samba-ad-dc.service|' \
 	  -e 's|^PIDFile=/run/|PIDFile=/var/run/samba/|' \
 	  $(DESTDIR)/lib/systemd/system/nmbd.service \
 	  $(DESTDIR)/lib/systemd/system/samba-ad-dc.service \
diff -Nru samba-4.5.5+dfsg/docs/manpages/cifsdd.8 samba-4.5.6+dfsg/docs/manpages/cifsdd.8
--- samba-4.5.5+dfsg/docs/manpages/cifsdd.8	2017-01-30 11:15:43.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/cifsdd.8	2017-03-09 10:24:56.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: cifsdd
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "CIFSDD" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "CIFSDD" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/dbwrap_tool.1 samba-4.5.6+dfsg/docs/manpages/dbwrap_tool.1
--- samba-4.5.5+dfsg/docs/manpages/dbwrap_tool.1	2017-01-30 11:15:43.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/dbwrap_tool.1	2017-03-09 10:24:56.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: dbwrap_tool
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "DBWRAP_TOOL" "1" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "DBWRAP_TOOL" "1" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/eventlogadm.8 samba-4.5.6+dfsg/docs/manpages/eventlogadm.8
--- samba-4.5.5+dfsg/docs/manpages/eventlogadm.8	2017-01-30 11:15:43.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/eventlogadm.8	2017-03-09 10:24:56.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: eventlogadm
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "EVENTLOGADM" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "EVENTLOGADM" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/findsmb.1 samba-4.5.6+dfsg/docs/manpages/findsmb.1
--- samba-4.5.5+dfsg/docs/manpages/findsmb.1	2017-01-30 11:15:44.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/findsmb.1	2017-03-09 10:24:57.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: findsmb
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "FINDSMB" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "FINDSMB" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/idmap_ad.8 samba-4.5.6+dfsg/docs/manpages/idmap_ad.8
--- samba-4.5.5+dfsg/docs/manpages/idmap_ad.8	2017-01-30 11:15:44.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/idmap_ad.8	2017-03-09 10:24:57.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: idmap_ad
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "IDMAP_AD" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "IDMAP_AD" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/idmap_autorid.8 samba-4.5.6+dfsg/docs/manpages/idmap_autorid.8
--- samba-4.5.5+dfsg/docs/manpages/idmap_autorid.8	2017-01-30 11:15:44.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/idmap_autorid.8	2017-03-09 10:24:57.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: idmap_autorid
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "IDMAP_AUTORID" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "IDMAP_AUTORID" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/idmap_hash.8 samba-4.5.6+dfsg/docs/manpages/idmap_hash.8
--- samba-4.5.5+dfsg/docs/manpages/idmap_hash.8	2017-01-30 11:15:44.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/idmap_hash.8	2017-03-09 10:24:57.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: idmap_hash
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "IDMAP_HASH" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "IDMAP_HASH" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/idmap_ldap.8 samba-4.5.6+dfsg/docs/manpages/idmap_ldap.8
--- samba-4.5.5+dfsg/docs/manpages/idmap_ldap.8	2017-01-30 11:15:44.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/idmap_ldap.8	2017-03-09 10:24:58.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: idmap_ldap
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "IDMAP_LDAP" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "IDMAP_LDAP" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/idmap_nss.8 samba-4.5.6+dfsg/docs/manpages/idmap_nss.8
--- samba-4.5.5+dfsg/docs/manpages/idmap_nss.8	2017-01-30 11:15:45.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/idmap_nss.8	2017-03-09 10:24:58.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: idmap_nss
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "IDMAP_NSS" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "IDMAP_NSS" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/idmap_rfc2307.8 samba-4.5.6+dfsg/docs/manpages/idmap_rfc2307.8
--- samba-4.5.5+dfsg/docs/manpages/idmap_rfc2307.8	2017-01-30 11:15:45.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/idmap_rfc2307.8	2017-03-09 10:24:58.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: idmap_rfc2307
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "IDMAP_RFC2307" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "IDMAP_RFC2307" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/idmap_rid.8 samba-4.5.6+dfsg/docs/manpages/idmap_rid.8
--- samba-4.5.5+dfsg/docs/manpages/idmap_rid.8	2017-01-30 11:15:45.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/idmap_rid.8	2017-03-09 10:24:58.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: idmap_rid
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "IDMAP_RID" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "IDMAP_RID" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/idmap_script.8 samba-4.5.6+dfsg/docs/manpages/idmap_script.8
--- samba-4.5.5+dfsg/docs/manpages/idmap_script.8	2017-01-30 11:15:45.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/idmap_script.8	2017-03-09 10:24:58.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: idmap_script
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "IDMAP_SCRIPT" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "IDMAP_SCRIPT" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/idmap_tdb2.8 samba-4.5.6+dfsg/docs/manpages/idmap_tdb2.8
--- samba-4.5.5+dfsg/docs/manpages/idmap_tdb2.8	2017-01-30 11:15:46.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/idmap_tdb2.8	2017-03-09 10:24:59.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: idmap_tdb2
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "IDMAP_TDB2" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "IDMAP_TDB2" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/idmap_tdb.8 samba-4.5.6+dfsg/docs/manpages/idmap_tdb.8
--- samba-4.5.5+dfsg/docs/manpages/idmap_tdb.8	2017-01-30 11:15:46.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/idmap_tdb.8	2017-03-09 10:24:59.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: idmap_tdb
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "IDMAP_TDB" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "IDMAP_TDB" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/libsmbclient.7 samba-4.5.6+dfsg/docs/manpages/libsmbclient.7
--- samba-4.5.5+dfsg/docs/manpages/libsmbclient.7	2017-01-30 11:15:46.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/libsmbclient.7	2017-03-09 10:24:59.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: libsmbclient
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: 7
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "LIBSMBCLIENT" "7" "01/30/2017" "Samba 4\&.5" "7"
+.TH "LIBSMBCLIENT" "7" "03/09/2017" "Samba 4\&.5" "7"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/lmhosts.5 samba-4.5.6+dfsg/docs/manpages/lmhosts.5
--- samba-4.5.5+dfsg/docs/manpages/lmhosts.5	2017-01-30 11:15:46.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/lmhosts.5	2017-03-09 10:24:59.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: lmhosts
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: File Formats and Conventions
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "LMHOSTS" "5" "01/30/2017" "Samba 4\&.5" "File Formats and Conventions"
+.TH "LMHOSTS" "5" "03/09/2017" "Samba 4\&.5" "File Formats and Conventions"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/log2pcap.1 samba-4.5.6+dfsg/docs/manpages/log2pcap.1
--- samba-4.5.5+dfsg/docs/manpages/log2pcap.1	2017-01-30 11:15:47.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/log2pcap.1	2017-03-09 10:25:00.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: log2pcap
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "LOG2PCAP" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "LOG2PCAP" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/net.8 samba-4.5.6+dfsg/docs/manpages/net.8
--- samba-4.5.5+dfsg/docs/manpages/net.8	2017-01-30 11:15:47.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/net.8	2017-03-09 10:25:00.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: net
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "NET" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "NET" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/nmbd.8 samba-4.5.6+dfsg/docs/manpages/nmbd.8
--- samba-4.5.5+dfsg/docs/manpages/nmbd.8	2017-01-30 11:15:47.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/nmbd.8	2017-03-09 10:25:00.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: nmbd
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "NMBD" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "NMBD" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/nmblookup.1 samba-4.5.6+dfsg/docs/manpages/nmblookup.1
--- samba-4.5.5+dfsg/docs/manpages/nmblookup.1	2017-01-30 11:15:47.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/nmblookup.1	2017-03-09 10:25:00.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: nmblookup
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "NMBLOOKUP" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "NMBLOOKUP" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/ntlm_auth.1 samba-4.5.6+dfsg/docs/manpages/ntlm_auth.1
--- samba-4.5.5+dfsg/docs/manpages/ntlm_auth.1	2017-01-30 11:15:48.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/ntlm_auth.1	2017-03-09 10:25:01.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: ntlm_auth
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "NTLM_AUTH" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "NTLM_AUTH" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/pam_winbind.8 samba-4.5.6+dfsg/docs/manpages/pam_winbind.8
--- samba-4.5.5+dfsg/docs/manpages/pam_winbind.8	2017-01-30 11:15:48.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/pam_winbind.8	2017-03-09 10:25:01.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: pam_winbind
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: 8
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "PAM_WINBIND" "8" "01/30/2017" "Samba 4\&.5" "8"
+.TH "PAM_WINBIND" "8" "03/09/2017" "Samba 4\&.5" "8"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/pam_winbind.conf.5 samba-4.5.6+dfsg/docs/manpages/pam_winbind.conf.5
--- samba-4.5.5+dfsg/docs/manpages/pam_winbind.conf.5	2017-01-30 11:15:48.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/pam_winbind.conf.5	2017-03-09 10:25:01.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: 5
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "PAM_WINBIND\&.CONF" "5" "01/30/2017" "Samba 4\&.5" "5"
+.TH "PAM_WINBIND\&.CONF" "5" "03/09/2017" "Samba 4\&.5" "5"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/pdbedit.8 samba-4.5.6+dfsg/docs/manpages/pdbedit.8
--- samba-4.5.5+dfsg/docs/manpages/pdbedit.8	2017-01-30 11:15:48.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/pdbedit.8	2017-03-09 10:25:01.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: pdbedit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "PDBEDIT" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "PDBEDIT" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/profiles.1 samba-4.5.6+dfsg/docs/manpages/profiles.1
--- samba-4.5.5+dfsg/docs/manpages/profiles.1	2017-01-30 11:15:49.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/profiles.1	2017-03-09 10:25:01.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: profiles
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "PROFILES" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "PROFILES" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/rpcclient.1 samba-4.5.6+dfsg/docs/manpages/rpcclient.1
--- samba-4.5.5+dfsg/docs/manpages/rpcclient.1	2017-01-30 11:15:49.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/rpcclient.1	2017-03-09 10:25:02.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: rpcclient
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "RPCCLIENT" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "RPCCLIENT" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/samba.7 samba-4.5.6+dfsg/docs/manpages/samba.7
--- samba-4.5.5+dfsg/docs/manpages/samba.7	2017-01-30 11:15:50.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/samba.7	2017-03-09 10:25:02.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: samba
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: Miscellanea
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SAMBA" "7" "01/30/2017" "Samba 4\&.5" "Miscellanea"
+.TH "SAMBA" "7" "03/09/2017" "Samba 4\&.5" "Miscellanea"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/samba.8 samba-4.5.6+dfsg/docs/manpages/samba.8
--- samba-4.5.5+dfsg/docs/manpages/samba.8	2017-01-30 11:15:50.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/samba.8	2017-03-09 10:25:03.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: samba
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SAMBA" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "SAMBA" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/samba-regedit.8 samba-4.5.6+dfsg/docs/manpages/samba-regedit.8
--- samba-4.5.5+dfsg/docs/manpages/samba-regedit.8	2017-01-30 11:15:49.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/samba-regedit.8	2017-03-09 10:25:02.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: samba-regedit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SAMBA\-REGEDIT" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "SAMBA\-REGEDIT" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/samba-tool.8 samba-4.5.6+dfsg/docs/manpages/samba-tool.8
--- samba-4.5.5+dfsg/docs/manpages/samba-tool.8	2017-01-30 11:15:49.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/samba-tool.8	2017-03-09 10:25:02.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: samba-tool
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SAMBA\-TOOL" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "SAMBA\-TOOL" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/sharesec.1 samba-4.5.6+dfsg/docs/manpages/sharesec.1
--- samba-4.5.5+dfsg/docs/manpages/sharesec.1	2017-01-30 11:15:50.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/sharesec.1	2017-03-09 10:25:03.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: sharesec
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SHARESEC" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "SHARESEC" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/smbcacls.1 samba-4.5.6+dfsg/docs/manpages/smbcacls.1
--- samba-4.5.5+dfsg/docs/manpages/smbcacls.1	2017-01-30 11:15:54.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/smbcacls.1	2017-03-09 10:25:07.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: smbcacls
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SMBCACLS" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "SMBCACLS" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/smbclient.1 samba-4.5.6+dfsg/docs/manpages/smbclient.1
--- samba-4.5.5+dfsg/docs/manpages/smbclient.1	2017-01-30 11:15:54.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/smbclient.1	2017-03-09 10:25:07.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: smbclient
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SMBCLIENT" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "SMBCLIENT" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/smb.conf.5 samba-4.5.6+dfsg/docs/manpages/smb.conf.5
--- samba-4.5.5+dfsg/docs/manpages/smb.conf.5	2017-01-30 11:15:53.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/smb.conf.5	2017-03-09 10:25:06.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: smb.conf
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: File Formats and Conventions
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SMB\&.CONF" "5" "01/30/2017" "Samba 4\&.5" "File Formats and Conventions"
+.TH "SMB\&.CONF" "5" "03/09/2017" "Samba 4\&.5" "File Formats and Conventions"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -10473,7 +10473,9 @@
 .\}
 Setting it to
 \fIoff\fR
-globally will completely disable the encryption feature\&.
+globally will completely disable the encryption feature for all connections\&. Setting
+\fIsmb encrypt = required\fR
+for individual shares (while it\*(Aqs globally off) will deny access to this shares for all clients\&.
 .RE
 .sp
 .RS 4
diff -Nru samba-4.5.5+dfsg/docs/manpages/smbcontrol.1 samba-4.5.6+dfsg/docs/manpages/smbcontrol.1
--- samba-4.5.5+dfsg/docs/manpages/smbcontrol.1	2017-01-30 11:15:54.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/smbcontrol.1	2017-03-09 10:25:07.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: smbcontrol
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SMBCONTROL" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "SMBCONTROL" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/smbcquotas.1 samba-4.5.6+dfsg/docs/manpages/smbcquotas.1
--- samba-4.5.5+dfsg/docs/manpages/smbcquotas.1	2017-01-30 11:15:54.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/smbcquotas.1	2017-03-09 10:25:07.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: smbcquotas
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SMBCQUOTAS" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "SMBCQUOTAS" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/smbd.8 samba-4.5.6+dfsg/docs/manpages/smbd.8
--- samba-4.5.5+dfsg/docs/manpages/smbd.8	2017-01-30 11:15:55.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/smbd.8	2017-03-09 10:25:08.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: smbd
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SMBD" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "SMBD" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/smbget.1 samba-4.5.6+dfsg/docs/manpages/smbget.1
--- samba-4.5.5+dfsg/docs/manpages/smbget.1	2017-01-30 11:15:55.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/smbget.1	2017-03-09 10:25:08.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: smbget
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SMBGET" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "SMBGET" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/smbgetrc.5 samba-4.5.6+dfsg/docs/manpages/smbgetrc.5
--- samba-4.5.5+dfsg/docs/manpages/smbgetrc.5	2017-01-30 11:15:55.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/smbgetrc.5	2017-03-09 10:25:08.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: smbgetrc
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: File Formats and Conventions
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SMBGETRC" "5" "01/30/2017" "Samba 4\&.5" "File Formats and Conventions"
+.TH "SMBGETRC" "5" "03/09/2017" "Samba 4\&.5" "File Formats and Conventions"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/smbpasswd.5 samba-4.5.6+dfsg/docs/manpages/smbpasswd.5
--- samba-4.5.5+dfsg/docs/manpages/smbpasswd.5	2017-01-30 11:15:55.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/smbpasswd.5	2017-03-09 10:25:08.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: smbpasswd
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: File Formats and Conventions
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SMBPASSWD" "5" "01/30/2017" "Samba 4\&.5" "File Formats and Conventions"
+.TH "SMBPASSWD" "5" "03/09/2017" "Samba 4\&.5" "File Formats and Conventions"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/smbpasswd.8 samba-4.5.6+dfsg/docs/manpages/smbpasswd.8
--- samba-4.5.5+dfsg/docs/manpages/smbpasswd.8	2017-01-30 11:15:56.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/smbpasswd.8	2017-03-09 10:25:09.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: smbpasswd
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SMBPASSWD" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "SMBPASSWD" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/smbspool.8 samba-4.5.6+dfsg/docs/manpages/smbspool.8
--- samba-4.5.5+dfsg/docs/manpages/smbspool.8	2017-01-30 11:15:56.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/smbspool.8	2017-03-09 10:25:09.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: smbspool
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SMBSPOOL" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "SMBSPOOL" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/smbspool_krb5_wrapper.8 samba-4.5.6+dfsg/docs/manpages/smbspool_krb5_wrapper.8
--- samba-4.5.5+dfsg/docs/manpages/smbspool_krb5_wrapper.8	2017-01-30 11:15:56.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/smbspool_krb5_wrapper.8	2017-03-09 10:25:09.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: smbspool_krb5_wrapper
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SMBSPOOL_KRB5_WRAPPE" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "SMBSPOOL_KRB5_WRAPPE" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/smbstatus.1 samba-4.5.6+dfsg/docs/manpages/smbstatus.1
--- samba-4.5.5+dfsg/docs/manpages/smbstatus.1	2017-01-30 11:15:56.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/smbstatus.1	2017-03-09 10:25:09.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: smbstatus
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SMBSTATUS" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "SMBSTATUS" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/smbtar.1 samba-4.5.6+dfsg/docs/manpages/smbtar.1
--- samba-4.5.5+dfsg/docs/manpages/smbtar.1	2017-01-30 11:15:56.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/smbtar.1	2017-03-09 10:25:09.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: smbtar
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SMBTAR" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "SMBTAR" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/smbtree.1 samba-4.5.6+dfsg/docs/manpages/smbtree.1
--- samba-4.5.5+dfsg/docs/manpages/smbtree.1	2017-01-30 11:15:57.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/smbtree.1	2017-03-09 10:25:10.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: smbtree
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "SMBTREE" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "SMBTREE" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/testparm.1 samba-4.5.6+dfsg/docs/manpages/testparm.1
--- samba-4.5.5+dfsg/docs/manpages/testparm.1	2017-01-30 11:15:57.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/testparm.1	2017-03-09 10:25:10.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: testparm
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "TESTPARM" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "TESTPARM" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_acl_tdb.8 samba-4.5.6+dfsg/docs/manpages/vfs_acl_tdb.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_acl_tdb.8	2017-01-30 11:15:57.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_acl_tdb.8	2017-03-09 10:25:10.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_ACL_TDB" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_ACL_TDB" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_acl_xattr.8 samba-4.5.6+dfsg/docs/manpages/vfs_acl_xattr.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_acl_xattr.8	2017-01-30 11:15:57.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_acl_xattr.8	2017-03-09 10:25:10.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_ACL_XATTR" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_ACL_XATTR" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_aio_fork.8 samba-4.5.6+dfsg/docs/manpages/vfs_aio_fork.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_aio_fork.8	2017-01-30 11:15:58.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_aio_fork.8	2017-03-09 10:25:11.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_AIO_FORK" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_AIO_FORK" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_aio_linux.8 samba-4.5.6+dfsg/docs/manpages/vfs_aio_linux.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_aio_linux.8	2017-01-30 11:15:58.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_aio_linux.8	2017-03-09 10:25:11.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_AIO_LINUX" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_AIO_LINUX" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_aio_pthread.8 samba-4.5.6+dfsg/docs/manpages/vfs_aio_pthread.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_aio_pthread.8	2017-01-30 11:15:58.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_aio_pthread.8	2017-03-09 10:25:11.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_AIO_PTHREAD" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_AIO_PTHREAD" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_audit.8 samba-4.5.6+dfsg/docs/manpages/vfs_audit.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_audit.8	2017-01-30 11:15:58.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_audit.8	2017-03-09 10:25:11.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_audit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_AUDIT" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_AUDIT" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_btrfs.8 samba-4.5.6+dfsg/docs/manpages/vfs_btrfs.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_btrfs.8	2017-01-30 11:15:59.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_btrfs.8	2017-03-09 10:25:11.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_btrfs
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_BTRFS" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_BTRFS" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_cacheprime.8 samba-4.5.6+dfsg/docs/manpages/vfs_cacheprime.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_cacheprime.8	2017-01-30 11:15:59.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_cacheprime.8	2017-03-09 10:25:12.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_cacheprime
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_CACHEPRIME" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_CACHEPRIME" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_cap.8 samba-4.5.6+dfsg/docs/manpages/vfs_cap.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_cap.8	2017-01-30 11:15:59.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_cap.8	2017-03-09 10:25:12.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_cap
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_CAP" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_CAP" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_catia.8 samba-4.5.6+dfsg/docs/manpages/vfs_catia.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_catia.8	2017-01-30 11:15:59.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_catia.8	2017-03-09 10:25:12.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_catia
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_CATIA" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_CATIA" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_ceph.8 samba-4.5.6+dfsg/docs/manpages/vfs_ceph.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_ceph.8	2017-01-30 11:15:59.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_ceph.8	2017-03-09 10:25:12.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_ceph
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_CEPH" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_CEPH" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_commit.8 samba-4.5.6+dfsg/docs/manpages/vfs_commit.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_commit.8	2017-01-30 11:16:00.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_commit.8	2017-03-09 10:25:13.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_commit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_COMMIT" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_COMMIT" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_crossrename.8 samba-4.5.6+dfsg/docs/manpages/vfs_crossrename.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_crossrename.8	2017-01-30 11:16:00.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_crossrename.8	2017-03-09 10:25:13.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_crossrename
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_CROSSRENAME" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_CROSSRENAME" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_default_quota.8 samba-4.5.6+dfsg/docs/manpages/vfs_default_quota.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_default_quota.8	2017-01-30 11:16:00.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_default_quota.8	2017-03-09 10:25:13.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_DEFAULT_QUOTA" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_DEFAULT_QUOTA" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_dirsort.8 samba-4.5.6+dfsg/docs/manpages/vfs_dirsort.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_dirsort.8	2017-01-30 11:16:00.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_dirsort.8	2017-03-09 10:25:13.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_dirsort
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_DIRSORT" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_DIRSORT" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_extd_audit.8 samba-4.5.6+dfsg/docs/manpages/vfs_extd_audit.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_extd_audit.8	2017-01-30 11:16:01.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_extd_audit.8	2017-03-09 10:25:13.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_EXTD_AUDIT" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_EXTD_AUDIT" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_fake_perms.8 samba-4.5.6+dfsg/docs/manpages/vfs_fake_perms.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_fake_perms.8	2017-01-30 11:16:01.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_fake_perms.8	2017-03-09 10:25:14.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_FAKE_PERMS" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_FAKE_PERMS" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_fileid.8 samba-4.5.6+dfsg/docs/manpages/vfs_fileid.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_fileid.8	2017-01-30 11:16:01.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_fileid.8	2017-03-09 10:25:14.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_fileid
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_FILEID" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_FILEID" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_fruit.8 samba-4.5.6+dfsg/docs/manpages/vfs_fruit.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_fruit.8	2017-01-30 11:16:01.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_fruit.8	2017-03-09 10:25:14.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_fruit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_FRUIT" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_FRUIT" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -197,7 +197,13 @@
 .PP
 fruit:encoding = [ native | private ]
 .RS 4
-Controls how the set of illegal NTFS ASCII character, commonly used by OS X clients, are stored in the filesystem:
+Controls how the set of illegal NTFS ASCII character, commonly used by OS X clients, are stored in the filesystem\&.
+.sp
+\fIImportant:\fR
+this is known to not fully work with
+\fIfruit:metadata=stream\fR
+or
+\fIfruit:resource=stream\fR\&.
 .sp
 .RS 4
 .ie n \{\
@@ -300,7 +306,17 @@
 .PP
 fruit:veto_appledouble = yes | no
 .RS 4
-Whether \&._ AppleDouble files are vetoed which prevents the client from seing and accessing internal AppleDouble files created by vfs_fruit itself for the purpose of storing a Mac resource fork\&.
+\fINote:\fR
+this option only applies when
+\fIfruit:resource\fR
+is set to
+\fIfile\fR
+(the default)\&.
+.sp
+When
+\fIfruit:resource\fR
+is set to
+\fIfile\fR, vfs_fruit may create \&._ AppleDouble files\&. This options controls whether these \&._ AppleDouble files are vetoed which prevents the client from accessing them\&.
 .sp
 Vetoing \&._ files may break some applications, eg extracting Mac ZIP archives from Mac clients failes, because they contain \&._ files\&. Setting this option to false will fix this, but the abstraction leak of exposing the internally created \&._ files may have other unknown side effects\&.
 .sp
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_full_audit.8 samba-4.5.6+dfsg/docs/manpages/vfs_full_audit.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_full_audit.8	2017-01-30 11:16:02.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_full_audit.8	2017-03-09 10:25:14.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_FULL_AUDIT" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_FULL_AUDIT" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_glusterfs.8 samba-4.5.6+dfsg/docs/manpages/vfs_glusterfs.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_glusterfs.8	2017-01-30 11:16:02.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_glusterfs.8	2017-03-09 10:25:15.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_glusterfs
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_GLUSTERFS" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_GLUSTERFS" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_gpfs.8 samba-4.5.6+dfsg/docs/manpages/vfs_gpfs.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_gpfs.8	2017-01-30 11:16:02.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_gpfs.8	2017-03-09 10:25:15.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_gpfs
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_GPFS" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_GPFS" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_linux_xfs_sgid.8 samba-4.5.6+dfsg/docs/manpages/vfs_linux_xfs_sgid.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_linux_xfs_sgid.8	2017-01-30 11:16:02.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_linux_xfs_sgid.8	2017-03-09 10:25:15.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_syncops
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_SYNCOPS" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_SYNCOPS" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_media_harmony.8 samba-4.5.6+dfsg/docs/manpages/vfs_media_harmony.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_media_harmony.8	2017-01-30 11:16:03.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_media_harmony.8	2017-03-09 10:25:15.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_MEDIA_HARMONY" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_MEDIA_HARMONY" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_netatalk.8 samba-4.5.6+dfsg/docs/manpages/vfs_netatalk.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_netatalk.8	2017-01-30 11:16:03.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_netatalk.8	2017-03-09 10:25:16.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_netatalk
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_NETATALK" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_NETATALK" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_offline.8 samba-4.5.6+dfsg/docs/manpages/vfs_offline.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_offline.8	2017-01-30 11:16:03.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_offline.8	2017-03-09 10:25:16.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_offline
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_OFFLINE" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_OFFLINE" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_prealloc.8 samba-4.5.6+dfsg/docs/manpages/vfs_prealloc.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_prealloc.8	2017-01-30 11:16:03.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_prealloc.8	2017-03-09 10:25:16.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_prealloc
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_PREALLOC" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_PREALLOC" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_preopen.8 samba-4.5.6+dfsg/docs/manpages/vfs_preopen.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_preopen.8	2017-01-30 11:16:04.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_preopen.8	2017-03-09 10:25:16.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_preopen
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_PREOPEN" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_PREOPEN" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_readahead.8 samba-4.5.6+dfsg/docs/manpages/vfs_readahead.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_readahead.8	2017-01-30 11:16:04.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_readahead.8	2017-03-09 10:25:16.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_readahead
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_READAHEAD" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_READAHEAD" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_readonly.8 samba-4.5.6+dfsg/docs/manpages/vfs_readonly.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_readonly.8	2017-01-30 11:16:04.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_readonly.8	2017-03-09 10:25:17.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_readonly
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_READONLY" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_READONLY" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_recycle.8 samba-4.5.6+dfsg/docs/manpages/vfs_recycle.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_recycle.8	2017-01-30 11:16:04.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_recycle.8	2017-03-09 10:25:17.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_recycle
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_RECYCLE" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_RECYCLE" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_shadow_copy2.8 samba-4.5.6+dfsg/docs/manpages/vfs_shadow_copy2.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_shadow_copy2.8	2017-01-30 11:16:05.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_shadow_copy2.8	2017-03-09 10:25:17.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_SHADOW_COPY2" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_SHADOW_COPY2" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_shadow_copy.8 samba-4.5.6+dfsg/docs/manpages/vfs_shadow_copy.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_shadow_copy.8	2017-01-30 11:16:04.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_shadow_copy.8	2017-03-09 10:25:17.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_SHADOW_COPY" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_SHADOW_COPY" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_shell_snap.8 samba-4.5.6+dfsg/docs/manpages/vfs_shell_snap.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_shell_snap.8	2017-01-30 11:16:05.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_shell_snap.8	2017-03-09 10:25:18.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_SHELL_SNAP" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_SHELL_SNAP" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_snapper.8 samba-4.5.6+dfsg/docs/manpages/vfs_snapper.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_snapper.8	2017-01-30 11:16:05.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_snapper.8	2017-03-09 10:25:18.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_snapper
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_SNAPPER" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_SNAPPER" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_streams_depot.8 samba-4.5.6+dfsg/docs/manpages/vfs_streams_depot.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_streams_depot.8	2017-01-30 11:16:05.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_streams_depot.8	2017-03-09 10:25:18.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_STREAMS_DEPOT" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_STREAMS_DEPOT" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_streams_xattr.8 samba-4.5.6+dfsg/docs/manpages/vfs_streams_xattr.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_streams_xattr.8	2017-01-30 11:16:06.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_streams_xattr.8	2017-03-09 10:25:18.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_STREAMS_XATTR" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_STREAMS_XATTR" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_syncops.8 samba-4.5.6+dfsg/docs/manpages/vfs_syncops.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_syncops.8	2017-01-30 11:16:06.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_syncops.8	2017-03-09 10:25:18.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_syncops
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_SYNCOPS" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_SYNCOPS" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfstest.1 samba-4.5.6+dfsg/docs/manpages/vfstest.1
--- samba-4.5.5+dfsg/docs/manpages/vfstest.1	2017-01-30 11:16:08.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfstest.1	2017-03-09 10:25:20.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfstest
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFSTEST" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "VFSTEST" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_time_audit.8 samba-4.5.6+dfsg/docs/manpages/vfs_time_audit.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_time_audit.8	2017-01-30 11:16:06.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_time_audit.8	2017-03-09 10:25:19.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_TIME_AUDIT" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_TIME_AUDIT" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_tsmsm.8 samba-4.5.6+dfsg/docs/manpages/vfs_tsmsm.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_tsmsm.8	2017-01-30 11:16:06.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_tsmsm.8	2017-03-09 10:25:19.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_tsmsm
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_TSMSM" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_TSMSM" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_unityed_media.8 samba-4.5.6+dfsg/docs/manpages/vfs_unityed_media.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_unityed_media.8	2017-01-30 11:16:07.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_unityed_media.8	2017-03-09 10:25:19.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_UNITYED_MEDIA" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_UNITYED_MEDIA" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_worm.8 samba-4.5.6+dfsg/docs/manpages/vfs_worm.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_worm.8	2017-01-30 11:16:07.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_worm.8	2017-03-09 10:25:19.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_worm
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_WORM" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_WORM" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_xattr_tdb.8 samba-4.5.6+dfsg/docs/manpages/vfs_xattr_tdb.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_xattr_tdb.8	2017-01-30 11:16:07.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_xattr_tdb.8	2017-03-09 10:25:20.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_XATTR_TDB" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_XATTR_TDB" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/vfs_zfsacl.8 samba-4.5.6+dfsg/docs/manpages/vfs_zfsacl.8
--- samba-4.5.5+dfsg/docs/manpages/vfs_zfsacl.8	2017-01-30 11:16:07.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/vfs_zfsacl.8	2017-03-09 10:25:20.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: vfs_zfsacl
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "VFS_ZFSACL" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "VFS_ZFSACL" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/wbinfo.1 samba-4.5.6+dfsg/docs/manpages/wbinfo.1
--- samba-4.5.5+dfsg/docs/manpages/wbinfo.1	2017-01-30 11:16:08.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/wbinfo.1	2017-03-09 10:25:20.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: wbinfo
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: User Commands
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "WBINFO" "1" "01/30/2017" "Samba 4\&.5" "User Commands"
+.TH "WBINFO" "1" "03/09/2017" "Samba 4\&.5" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/winbindd.8 samba-4.5.6+dfsg/docs/manpages/winbindd.8
--- samba-4.5.5+dfsg/docs/manpages/winbindd.8	2017-01-30 11:16:08.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/winbindd.8	2017-03-09 10:25:21.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: winbindd
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "WINBINDD" "8" "01/30/2017" "Samba 4\&.5" "System Administration tools"
+.TH "WINBINDD" "8" "03/09/2017" "Samba 4\&.5" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs/manpages/winbind_krb5_locator.7 samba-4.5.6+dfsg/docs/manpages/winbind_krb5_locator.7
--- samba-4.5.5+dfsg/docs/manpages/winbind_krb5_locator.7	2017-01-30 11:16:08.000000000 +0100
+++ samba-4.5.6+dfsg/docs/manpages/winbind_krb5_locator.7	2017-03-09 10:25:20.000000000 +0100
@@ -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: 01/30/2017
+.\"      Date: 03/09/2017
 .\"    Manual: 7
 .\"    Source: Samba 4.5
 .\"  Language: English
 .\"
-.TH "WINBIND_KRB5_LOCATOR" "7" "01/30/2017" "Samba 4\&.5" "7"
+.TH "WINBIND_KRB5_LOCATOR" "7" "03/09/2017" "Samba 4\&.5" "7"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -Nru samba-4.5.5+dfsg/docs-xml/manpages/vfs_fruit.8.xml samba-4.5.6+dfsg/docs-xml/manpages/vfs_fruit.8.xml
--- samba-4.5.5+dfsg/docs-xml/manpages/vfs_fruit.8.xml	2017-01-30 10:56:26.000000000 +0100
+++ samba-4.5.6+dfsg/docs-xml/manpages/vfs_fruit.8.xml	2017-03-09 10:21:43.000000000 +0100
@@ -168,9 +168,13 @@
 
 	      <para>Controls how the set of illegal NTFS ASCII
 	      character, commonly used by OS X clients, are stored in
-	      the filesystem:</para>
+	      the filesystem.</para>
 
-	      <itemizedlist>
+	      <para><emphasis>Important:</emphasis> this is known to not fully
+	      work with <emphasis>fruit:metadata=stream</emphasis> or
+	      <emphasis>fruit:resource=stream</emphasis>.</para>
+
+ 	      <itemizedlist>
 
 		<listitem><para><command>private (default)</command> -
 		store characters as encoded by the OS X client: mapped
@@ -231,10 +235,14 @@
 	  <varlistentry>
 	    <term>fruit:veto_appledouble = yes | no</term>
 	    <listitem>
-	      <para>Whether ._ AppleDouble files are vetoed which
-	      prevents the client from seing and accessing internal
-	      AppleDouble files created by vfs_fruit itself for the
-	      purpose of storing a Mac resource fork.</para>
+	      <para><emphasis>Note:</emphasis> this option only applies when
+	      <parameter>fruit:resource</parameter> is set to
+	      <parameter>file</parameter> (the default).</para>
+
+	      <para>When <parameter>fruit:resource</parameter> is set to
+	      <parameter>file</parameter>, vfs_fruit may create ._ AppleDouble
+	      files. This options controls whether these ._ AppleDouble files
+	      are vetoed which prevents the client from accessing them.</para>
 	      <para>Vetoing ._ files may break some applications, eg
 	      extracting Mac ZIP archives from Mac clients failes,
 	      because they contain ._ files. Setting this option to
diff -Nru samba-4.5.5+dfsg/docs-xml/smbdotconf/security/smbencrypt.xml samba-4.5.6+dfsg/docs-xml/smbdotconf/security/smbencrypt.xml
--- samba-4.5.5+dfsg/docs-xml/smbdotconf/security/smbencrypt.xml	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/docs-xml/smbdotconf/security/smbencrypt.xml	2017-03-09 10:21:43.000000000 +0100
@@ -180,7 +180,11 @@
 			<listitem>
 			<para>
 			Setting it to <emphasis>off</emphasis> globally will
-			completely disable the encryption feature.
+			completely disable the encryption feature for all
+			connections. Setting <parameter>smb encrypt =
+			required</parameter> for individual shares (while it's
+			globally off) will deny access to this shares for all
+			clients.
 			</para>
 			</listitem>
 
diff -Nru samba-4.5.5+dfsg/lib/krb5_wrap/krb5_samba.c samba-4.5.6+dfsg/lib/krb5_wrap/krb5_samba.c
--- samba-4.5.5+dfsg/lib/krb5_wrap/krb5_samba.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/lib/krb5_wrap/krb5_samba.c	2017-03-09 10:21:43.000000000 +0100
@@ -24,6 +24,7 @@
 #include "system/filesys.h"
 #include "krb5_samba.h"
 #include "lib/util/asn1.h"
+#include "lib/crypto/crypto.h"
 
 #ifdef HAVE_COM_ERR_H
 #include <com_err.h>
@@ -202,6 +203,42 @@
 		return -1;
 	}
 
+	if ((int)enctype == (int)ENCTYPE_ARCFOUR_HMAC) {
+		TALLOC_CTX *frame = talloc_stackframe();
+		uint8_t *utf16 = NULL;
+		size_t utf16_size = 0;
+		uint8_t nt_hash[16];
+		bool ok;
+
+		ok = convert_string_talloc(frame, CH_UNIX, CH_UTF16LE,
+					   password->data, password->length,
+					   (void **)&utf16, &utf16_size);
+		if (!ok) {
+			if (errno == 0) {
+				errno = EINVAL;
+			}
+			ret = errno;
+			TALLOC_FREE(frame);
+			return ret;
+		}
+
+		mdfour(nt_hash, utf16, utf16_size);
+		memset(utf16, 0, utf16_size);
+		ret = smb_krb5_keyblock_init_contents(context,
+						      ENCTYPE_ARCFOUR_HMAC,
+						      nt_hash,
+						      sizeof(nt_hash),
+						      key);
+		ZERO_STRUCT(nt_hash);
+		if (ret != 0) {
+			TALLOC_FREE(frame);
+			return ret;
+		}
+
+		TALLOC_FREE(frame);
+		return 0;
+	}
+
 #if defined(HAVE_KRB5_PRINCIPAL2SALT) && defined(HAVE_KRB5_C_STRING_TO_KEY)
 {/* MIT */
 	krb5_data _salt;
diff -Nru samba-4.5.5+dfsg/lib/ldb-samba/ldb_ildap.c samba-4.5.6+dfsg/lib/ldb-samba/ldb_ildap.c
--- samba-4.5.5+dfsg/lib/ldb-samba/ldb_ildap.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/lib/ldb-samba/ldb_ildap.c	2017-03-09 10:21:43.000000000 +0100
@@ -863,6 +863,7 @@
 	return LDB_SUCCESS;
 
 failed:
+	ldb_set_errstring(ldb, ldap_errstr(ildb->ldap, module, status));
 	talloc_free(module);
 	if (NT_STATUS_IS_LDAP(status)) {
 		return NT_STATUS_LDAP_CODE(status);
diff -Nru samba-4.5.5+dfsg/lib/torture/torture.h samba-4.5.6+dfsg/lib/torture/torture.h
--- samba-4.5.5+dfsg/lib/torture/torture.h	2017-01-30 10:56:26.000000000 +0100
+++ samba-4.5.6+dfsg/lib/torture/torture.h	2017-03-09 10:21:43.000000000 +0100
@@ -357,6 +357,16 @@
 	} \
 	} while(0)
 
+#define torture_assert_mem_equal_goto(torture_ctx,got,expected,len,ret,label,cmt) \
+	do { const void *__got = (got), *__expected = (expected); \
+	if (memcmp(__got, __expected, len) != 0) { \
+		torture_result(torture_ctx, TORTURE_FAIL, \
+			       __location__": "#got" of len %d did not match "#expected": %s", (int)len, cmt); \
+		ret = false; \
+		goto label; \
+	} \
+	} while(0)
+
 static inline void torture_dump_data_str_cb(const char *buf, void *private_data)
 {
 	char **dump = (char **)private_data;
diff -Nru samba-4.5.5+dfsg/lib/util/genrand_util.c samba-4.5.6+dfsg/lib/util/genrand_util.c
--- samba-4.5.5+dfsg/lib/util/genrand_util.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/lib/util/genrand_util.c	2017-03-09 10:21:43.000000000 +0100
@@ -210,7 +210,7 @@
 }
 
 /**
- * Generate a random text password.
+ * Generate a random text password (based on printable ascii characters).
  */
 
 _PUBLIC_ char *generate_random_password(TALLOC_CTX *mem_ctx, size_t min, size_t max)
@@ -258,6 +258,172 @@
 }
 
 /**
+ * Generate a random machine password (based on random utf16 characters,
+ * converted to utf8). min must be at least 14, max must be at most 255.
+ *
+ * If 'unix charset' is not utf8, the password consist of random ascii
+ * values!
+ */
+
+_PUBLIC_ char *generate_random_machine_password(TALLOC_CTX *mem_ctx, size_t min, size_t max)
+{
+	TALLOC_CTX *frame = NULL;
+	struct generate_random_machine_password_state {
+		uint8_t password_buffer[256 * 2];
+		uint8_t tmp;
+	} *state;
+	char *new_pw = NULL;
+	size_t len = max;
+	char *utf8_pw = NULL;
+	size_t utf8_len = 0;
+	char *unix_pw = NULL;
+	size_t unix_len = 0;
+	size_t diff;
+	size_t i;
+	bool ok;
+	int cmp;
+
+	if (max > 255) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	if (min < 14) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	if (min > max) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	frame = talloc_stackframe_pool(2048);
+	state = talloc_zero(frame, struct generate_random_machine_password_state);
+
+	diff = max - min;
+
+	if (diff > 0) {
+		size_t tmp;
+
+		generate_random_buffer((uint8_t *)&tmp, sizeof(tmp));
+
+		tmp %= diff;
+
+		len = min + tmp;
+	}
+
+	/*
+	 * Create a random machine account password
+	 * We create a random buffer and convert that to utf8.
+	 * This is similar to what windows is doing.
+	 *
+	 * In future we may store the raw random buffer,
+	 * but for now we need to pass the password as
+	 * char pointer through some layers.
+	 *
+	 * As most kerberos keys are derived from the
+	 * utf8 password we need to fallback to
+	 * ASCII passwords if "unix charset" is not utf8.
+	 */
+	generate_secret_buffer(state->password_buffer, len * 2);
+	for (i = 0; i < len; i++) {
+		size_t idx = i*2;
+		uint16_t c;
+
+		/*
+		 * both MIT krb5 and HEIMDAL only
+		 * handle codepoints up to 0xffff.
+		 *
+		 * It means we need to avoid
+		 * 0xD800 - 0xDBFF (high surrogate)
+		 * and
+		 * 0xDC00 - 0xDFFF (low surrogate)
+		 * in the random utf16 data.
+		 *
+		 * 55296 0xD800 0154000 0b1101100000000000
+		 * 57343 0xDFFF 0157777 0b1101111111111111
+		 * 8192  0x2000  020000   0b10000000000000
+		 *
+		 * The above values show that we can check
+		 * for 0xD800 and just add 0x2000 to avoid
+		 * the surrogate ranges.
+		 *
+		 * The rest will be handled by CH_UTF16MUNGED
+		 * see utf16_munged_pull().
+		 */
+		c = SVAL(state->password_buffer, idx);
+		if (c & 0xD800) {
+			c |= 0x2000;
+		}
+		SSVAL(state->password_buffer, idx, c);
+	}
+	ok = convert_string_talloc(frame,
+				   CH_UTF16MUNGED, CH_UTF8,
+				   state->password_buffer, len * 2,
+				   (void *)&utf8_pw, &utf8_len);
+	if (!ok) {
+		DEBUG(0, ("%s: convert_string_talloc() failed\n",
+			  __func__));
+		TALLOC_FREE(frame);
+		return NULL;
+	}
+
+	ok = convert_string_talloc(frame,
+				   CH_UTF16MUNGED, CH_UNIX,
+				   state->password_buffer, len * 2,
+				   (void *)&unix_pw, &unix_len);
+	if (!ok) {
+		goto ascii_fallback;
+	}
+
+	if (utf8_len != unix_len) {
+		goto ascii_fallback;
+	}
+
+	cmp = memcmp((const uint8_t *)utf8_pw,
+		     (const uint8_t *)unix_pw,
+		     utf8_len);
+	if (cmp != 0) {
+		goto ascii_fallback;
+	}
+
+	new_pw = talloc_strdup(mem_ctx, utf8_pw);
+	if (new_pw == NULL) {
+		TALLOC_FREE(frame);
+		return NULL;
+	}
+	talloc_set_name_const(new_pw, __func__);
+	TALLOC_FREE(frame);
+	return new_pw;
+
+ascii_fallback:
+	for (i = 0; i < len; i++) {
+		/*
+		 * truncate to ascii
+		 */
+		state->tmp = state->password_buffer[i] & 0x7f;
+		if (state->tmp == 0) {
+			state->tmp = state->password_buffer[i] >> 1;
+		}
+		if (state->tmp == 0) {
+			state->tmp = 0x01;
+		}
+		state->password_buffer[i] = state->tmp;
+	}
+	state->password_buffer[i] = '\0';
+
+	new_pw = talloc_strdup(mem_ctx, (const char *)state->password_buffer);
+	if (new_pw == NULL) {
+		TALLOC_FREE(frame);
+		return NULL;
+	}
+	talloc_set_name_const(new_pw, __func__);
+	TALLOC_FREE(frame);
+	return new_pw;
+}
+
+/**
  * Generate an array of unique text strings all of the same length.
  * The returned string will be allocated.
  * Returns NULL if the number of unique combinations cannot be created.
diff -Nru samba-4.5.5+dfsg/lib/util/samba_util.h samba-4.5.6+dfsg/lib/util/samba_util.h
--- samba-4.5.5+dfsg/lib/util/samba_util.h	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/lib/util/samba_util.h	2017-03-09 10:21:43.000000000 +0100
@@ -103,11 +103,41 @@
 _PUBLIC_ bool check_password_quality(const char *s);
 
 /**
- * Generate a random text password.
+ * Generate a random text password (based on printable ascii characters).
+ * This function is designed to provide a password that
+ * meats the complexity requirements of UF_NORMAL_ACCOUNT objects
+ * and they should be human readable and writeable on any keyboard layout.
+ *
+ * Characters used are:
+ * ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,@$%&!?:;<=>()[]~
  */
 _PUBLIC_ char *generate_random_password(TALLOC_CTX *mem_ctx, size_t min, size_t max);
 
 /**
+ * Generate a random machine password
+ *
+ * min and max are the number of utf16 characters used
+ * to generate on utf8 compatible password.
+ *
+ * Note: if 'unix charset' is not 'utf8' (the default)
+ * then each utf16 character is only filled with
+ * values from 0x01 to 0x7f (ascii values without 0x00).
+ * This is important as the password neets to be
+ * a valid value as utf8 string and at the same time
+ * a valid value in the 'unix charset'.
+ *
+ * If 'unix charset' is 'utf8' (the default) then
+ * each utf16 character is a random value from 0x0000
+ * 0xFFFF (exluding the surrogate ranges from 0xD800-0xDFFF)
+ * while the translation from CH_UTF16MUNGED
+ * to CH_UTF8 replaces invalid values (see utf16_munged_pull()).
+ *
+ * Note: these passwords may not pass the complexity requirements
+ * for UF_NORMAL_ACCOUNT objects (except krbtgt accounts).
+ */
+_PUBLIC_ char *generate_random_machine_password(TALLOC_CTX *mem_ctx, size_t min, size_t max);
+
+/**
  Use the random number generator to generate a random string.
 **/
 _PUBLIC_ char *generate_random_str_list(TALLOC_CTX *mem_ctx, size_t len, const char *list);
diff -Nru samba-4.5.5+dfsg/libcli/auth/netlogon_creds_cli.c samba-4.5.6+dfsg/libcli/auth/netlogon_creds_cli.c
--- samba-4.5.5+dfsg/libcli/auth/netlogon_creds_cli.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/libcli/auth/netlogon_creds_cli.c	2017-03-09 10:21:43.000000000 +0100
@@ -484,6 +484,14 @@
 	return NT_STATUS_OK;
 }
 
+char *netlogon_creds_cli_debug_string(
+		const struct netlogon_creds_cli_context *context,
+		TALLOC_CTX *mem_ctx)
+{
+	return talloc_asprintf(mem_ctx, "netlogon_creds_cli:%s",
+			       context->db.key_name);
+}
+
 enum dcerpc_AuthLevel netlogon_creds_cli_auth_level(
 		struct netlogon_creds_cli_context *context)
 {
@@ -1747,7 +1755,11 @@
 	/*
 	 * netr_ServerPasswordSet
 	 */
-	E_md4hash(new_password, state->samr_password.hash);
+	ok = E_md4hash(new_password, state->samr_password.hash);
+	if (!ok) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
+		return tevent_req_post(req, ev);
+	}
 
 	/*
 	 * netr_ServerPasswordSet2
@@ -2075,11 +2087,24 @@
 
 	/*
 	 * the read only credentials before we started the operation
+	 * used for netr_LogonSamLogonEx() if required (validation_level = 3).
 	 */
 	struct netlogon_creds_CredentialState *ro_creds;
 
+	/*
+	 * The (locked) credentials used for the credential chain
+	 * used for netr_LogonSamLogonWithFlags() or
+	 * netr_LogonSamLogonWith().
+	 */
 	struct netlogon_creds_CredentialState *lk_creds;
 
+	/*
+	 * While we have locked the global credentials (lk_creds above)
+	 * we operate an a temporary copy, because a server
+	 * may not support netr_LogonSamLogonWithFlags() and
+	 * didn't process our netr_Authenticator, so we need to
+	 * restart from lk_creds.
+	 */
 	struct netlogon_creds_CredentialState tmp_creds;
 	struct netr_Authenticator req_auth;
 	struct netr_Authenticator rep_auth;
@@ -2311,7 +2336,7 @@
 		return;
 	}
 
-	netlogon_creds_encrypt_samlogon_logon(state->ro_creds,
+	netlogon_creds_encrypt_samlogon_logon(&state->tmp_creds,
 					      state->logon_level,
 					      state->logon);
 
@@ -2414,8 +2439,10 @@
 			/*
 			 * We got a race, lets retry with on authenticator
 			 * protection.
+			 *
+			 * netlogon_creds_cli_LogonSamLogon_start()
+			 * will TALLOC_FREE(state->ro_creds);
 			 */
-			TALLOC_FREE(state->ro_creds);
 			state->try_logon_ex = false;
 			netlogon_creds_cli_LogonSamLogon_start(req);
 			return;
diff -Nru samba-4.5.5+dfsg/libcli/auth/netlogon_creds_cli.h samba-4.5.6+dfsg/libcli/auth/netlogon_creds_cli.h
--- samba-4.5.5+dfsg/libcli/auth/netlogon_creds_cli.h	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/libcli/auth/netlogon_creds_cli.h	2017-03-09 10:21:43.000000000 +0100
@@ -52,6 +52,10 @@
 				TALLOC_CTX *mem_ctx,
 				struct netlogon_creds_cli_context **_context);
 
+char *netlogon_creds_cli_debug_string(
+		const struct netlogon_creds_cli_context *context,
+		TALLOC_CTX *mem_ctx);
+
 enum dcerpc_AuthLevel netlogon_creds_cli_auth_level(
 		struct netlogon_creds_cli_context *context);
 
diff -Nru samba-4.5.5+dfsg/librpc/rpc/dcerpc_error.c samba-4.5.6+dfsg/librpc/rpc/dcerpc_error.c
--- samba-4.5.5+dfsg/librpc/rpc/dcerpc_error.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/librpc/rpc/dcerpc_error.c	2017-03-09 10:21:43.000000000 +0100
@@ -50,12 +50,10 @@
 	_FAULT_STR(DCERPC_NCA_S_FAULT_INT_DIV_BY_ZERO, NT_STATUS_RPC_FP_DIV_ZERO),
 	_FAULT_STR(DCERPC_NCA_S_FAULT_INT_OVERFLOW, NT_STATUS_RPC_FP_OVERFLOW),
 	/*
-	 * What's the difference between NT_STATUS_RPC_INVALID_TAG
-	 * and NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE ???
-	 *
-	 * Our callers expect NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE.
+	 * Our callers expect NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE
+	 * instead of NT_STATUS_RPC_INVALID_TAG.
 	 */
-	_FAULT_STR(DCERPC_NCA_S_FAULT_INVALID_TAG, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE),
+	_FAULT_STR(DCERPC_NCA_S_FAULT_INVALID_TAG, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE),
 	_FAULT_STR(DCERPC_NCA_S_FAULT_INVALID_TAG, NT_STATUS_RPC_INVALID_TAG),
 	_FAULT_STR(DCERPC_NCA_S_FAULT_INVALID_BOUND, NT_STATUS_RPC_INVALID_BOUND),
 	_FAULT_STR(DCERPC_NCA_S_FAULT_RPC_VERSION_MISMATCH, NT_STATUS_RPC_PROTOCOL_ERROR),
diff -Nru samba-4.5.5+dfsg/python/pyglue.c samba-4.5.6+dfsg/python/pyglue.c
--- samba-4.5.5+dfsg/python/pyglue.c	2016-12-05 09:18:44.000000000 +0100
+++ samba-4.5.6+dfsg/python/pyglue.c	2017-03-09 10:21:43.000000000 +0100
@@ -60,6 +60,23 @@
 	return ret;
 }
 
+static PyObject *py_generate_random_machine_password(PyObject *self, PyObject *args)
+{
+	int min, max;
+	PyObject *ret;
+	char *retstr;
+	if (!PyArg_ParseTuple(args, "ii", &min, &max))
+		return NULL;
+
+	retstr = generate_random_machine_password(NULL, min, max);
+	if (retstr == NULL) {
+		return NULL;
+	}
+	ret = PyUnicode_FromString(retstr);
+	talloc_free(retstr);
+	return ret;
+}
+
 static PyObject *py_unix2nttime(PyObject *self, PyObject *args)
 {
 	time_t t;
@@ -261,7 +278,14 @@
 		"Generate random string with specified length." },
 	{ "generate_random_password", (PyCFunction)py_generate_random_password,
 		METH_VARARGS, "generate_random_password(min, max) -> string\n"
-		"Generate random password with a length >= min and <= max." },
+		"Generate random password (based on printable ascii characters) "
+		"with a length >= min and <= max." },
+	{ "generate_random_machine_password", (PyCFunction)py_generate_random_machine_password,
+		METH_VARARGS, "generate_random_machine_password(min, max) -> string\n"
+		"Generate random password "
+		"(based on random utf16 characters converted to utf8 or "
+		"random ascii characters if 'unix charset' is not 'utf8')"
+		"with a length >= min (at least 14) and <= max (at most 255)." },
 	{ "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
 		"unix2nttime(timestamp) -> nttime" },
 	{ "nttime2unix", (PyCFunction)py_nttime2unix, METH_VARARGS,
diff -Nru samba-4.5.5+dfsg/python/samba/dbchecker.py samba-4.5.6+dfsg/python/samba/dbchecker.py
--- samba-4.5.5+dfsg/python/samba/dbchecker.py	2016-12-05 09:18:44.000000000 +0100
+++ samba-4.5.6+dfsg/python/samba/dbchecker.py	2017-03-09 10:21:43.000000000 +0100
@@ -59,6 +59,7 @@
         self.fix_all_string_dn_component_mismatch = False
         self.fix_all_GUID_dn_component_mismatch = False
         self.fix_all_SID_dn_component_mismatch = False
+        self.fix_all_old_dn_string_component_mismatch = False
         self.fix_all_metadata = False
         self.fix_time_metadata = False
         self.fix_undead_linked_attributes = False
@@ -574,6 +575,23 @@
                           "Failed to fix %s on attribute %s" % (errstr, attrname)):
             self.report("Fixed %s on attribute %s" % (errstr, attrname))
 
+    def err_dn_string_component_old(self, dn, attrname, val, dsdb_dn, correct_dn):
+        """handle a DN string being incorrect"""
+        self.report("NOTE: old (due to rename or delete) DN string component for %s in object %s - %s" % (attrname, dn, val))
+        dsdb_dn.dn = correct_dn
+
+        if not self.confirm_all('Change DN to %s?' % str(dsdb_dn),
+                                'fix_all_old_dn_string_component_mismatch'):
+            self.report("Not fixing old string component")
+            return
+        m = ldb.Message()
+        m.dn = dn
+        m['old_value'] = ldb.MessageElement(val, ldb.FLAG_MOD_DELETE, attrname)
+        m['new_value'] = ldb.MessageElement(str(dsdb_dn), ldb.FLAG_MOD_ADD, attrname)
+        if self.do_modify(m, ["show_recycled:1"],
+                          "Failed to fix old DN string on attribute %s" % (attrname)):
+            self.report("Fixed old DN string on attribute %s" % (attrname))
+
     def err_dn_component_target_mismatch(self, dn, attrname, val, dsdb_dn, correct_dn, mismatch_type):
         """handle a DN string being incorrect"""
         self.report("ERROR: incorrect DN %s component for %s in object %s - %s" % (mismatch_type, attrname, dn, val))
@@ -627,10 +645,9 @@
             self.report("Not fixing missing backlink %s" % backlink_name)
             return
         m = ldb.Message()
-        m.dn = obj.dn
-        m['old_value'] = ldb.MessageElement(val, ldb.FLAG_MOD_DELETE, attrname)
-        m['new_value'] = ldb.MessageElement(val, ldb.FLAG_MOD_ADD, attrname)
-        if self.do_modify(m, ["show_recycled:1"],
+        m.dn = target_dn
+        m['new_value'] = ldb.MessageElement(val, ldb.FLAG_MOD_ADD, backlink_name)
+        if self.do_modify(m, ["show_recycled:1", "relax:0"],
                           "Failed to fix missing backlink %s" % backlink_name):
             self.report("Fixed missing backlink %s" % (backlink_name))
 
@@ -914,12 +931,16 @@
                 if rmd_flags & 1:
                     continue
 
-            # check the DN matches in string form
-            if str(res[0].dn) != str(dsdb_dn.dn):
-                error_count += 1
-                self.err_dn_component_target_mismatch(obj.dn, attrname, val, dsdb_dn,
-                                                      res[0].dn, "string")
-                continue
+            # assert the DN matches in string form, where a reverse
+            # link exists, otherwise (below) offer to fix it as a non-error.
+            # The string form is essentially only kept for forensics,
+            # as we always re-resolve by GUID in normal operations.
+            if reverse_link_name is not None:
+                if str(res[0].dn) != str(dsdb_dn.dn):
+                    error_count += 1
+                    self.err_dn_component_target_mismatch(obj.dn, attrname, val, dsdb_dn,
+                                                          res[0].dn, "string")
+                    continue
 
             if res[0].dn.get_extended_component("GUID") != dsdb_dn.dn.get_extended_component("GUID"):
                 error_count += 1
@@ -933,9 +954,18 @@
                                                       res[0].dn, "SID")
                 continue
 
+            # Now we have checked the GUID and SID, offer to fix old
+            # DN strings as a non-error (for forward links with no
+            # backlink).  Samba does not maintain this string
+            # otherwise, so we don't increment error_count.
+            if reverse_link_name is None:
+                if str(res[0].dn) != str(dsdb_dn.dn):
+                    self.err_dn_string_component_old(obj.dn, attrname, val, dsdb_dn,
+                                                     res[0].dn)
+                continue
 
-            # check the reverse_link is correct if there should be one
-            if reverse_link_name is not None:
+            else:
+                # check the reverse_link is correct if there should be one
                 match_count = 0
                 if reverse_link_name in res[0]:
                     for v in res[0][reverse_link_name]:
@@ -943,12 +973,16 @@
                         if v_guid == obj_guid:
                             match_count += 1
                 if match_count != 1:
-                    if target_is_deleted:
-                        error_count += 1
-                        if linkID & 1:
-                            self.err_missing_backlink(obj, attrname, val, reverse_link_name, dsdb_dn.dn)
-                        else:
-                            self.err_orphaned_backlink(obj, attrname, val, reverse_link_name, dsdb_dn.dn)
+                    error_count += 1
+                    if linkID & 1:
+                        # Backlink exists, but forward link does not
+                        # Delete the hanging backlink
+                        self.err_orphaned_backlink(obj, attrname, val, reverse_link_name, dsdb_dn.dn)
+                    else:
+                        # Forward link exists, but backlink does not
+                        # Add the missing backlink (if the target object is not Deleted Objects?)
+                        if not target_is_deleted:
+                            self.err_missing_backlink(obj, attrname, obj.dn.extended_str(), reverse_link_name, dsdb_dn.dn)
                     continue
 
 
diff -Nru samba-4.5.5+dfsg/python/samba/__init__.py samba-4.5.6+dfsg/python/samba/__init__.py
--- samba-4.5.5+dfsg/python/samba/__init__.py	2016-12-05 09:18:44.000000000 +0100
+++ samba-4.5.6+dfsg/python/samba/__init__.py	2017-03-09 10:21:43.000000000 +0100
@@ -396,6 +396,7 @@
 nttime2unix = _glue.nttime2unix
 unix2nttime = _glue.unix2nttime
 generate_random_password = _glue.generate_random_password
+generate_random_machine_password = _glue.generate_random_machine_password
 strcasecmp_m = _glue.strcasecmp_m
 strstr_m = _glue.strstr_m
 is_ntvfs_fileserver_built = _glue.is_ntvfs_fileserver_built
diff -Nru samba-4.5.5+dfsg/python/samba/join.py samba-4.5.6+dfsg/python/samba/join.py
--- samba-4.5.5+dfsg/python/samba/join.py	2016-10-24 21:37:30.000000000 +0200
+++ samba-4.5.6+dfsg/python/samba/join.py	2017-03-09 10:21:43.000000000 +0100
@@ -104,7 +104,7 @@
         if machinepass is not None:
             ctx.acct_pass = machinepass
         else:
-            ctx.acct_pass = samba.generate_random_password(32, 40)
+            ctx.acct_pass = samba.generate_random_machine_password(128, 255)
 
         ctx.dnsdomain = ctx.samdb.domain_dns_name()
         if clone_only:
@@ -667,7 +667,7 @@
                     pass
                 ctx.net.set_password(account_name=ctx.samname,
                                      domain_name=ctx.domain_name,
-                                     newpassword=ctx.acct_pass)
+                                     newpassword=ctx.acct_pass.encode('utf-8'))
 
             res = ctx.samdb.search(base=ctx.acct_dn, scope=ldb.SCOPE_BASE,
                                    attrs=["msDS-KeyVersionNumber"])
@@ -691,7 +691,7 @@
                                                                 {"DNSDOMAIN": ctx.dnsdomain,
                                                                  "DOMAINDN": ctx.base_dn,
                                                                  "HOSTNAME" : ctx.myname,
-                                                                 "DNSPASS_B64": b64encode(ctx.dnspass),
+                                                                 "DNSPASS_B64": b64encode(ctx.dnspass.encode('utf-16-le')),
                                                                  "DNSNAME" : ctx.dnshostname}))
             for changetype, msg in recs:
                 assert changetype == ldb.CHANGETYPE_NONE
@@ -863,7 +863,7 @@
                 repl_creds.guess(ctx.lp)
                 repl_creds.set_kerberos_state(DONT_USE_KERBEROS)
                 repl_creds.set_username(ctx.samname)
-                repl_creds.set_password(ctx.acct_pass)
+                repl_creds.set_password(ctx.acct_pass.encode('utf-8'))
             else:
                 repl_creds = ctx.creds
 
@@ -1314,7 +1314,8 @@
     ctx.domsid = security.random_sid()
     ctx.acct_dn = None
     ctx.dnshostname = "%s.%s" % (ctx.myname.lower(), ctx.dnsdomain)
-    ctx.trustdom_pass = samba.generate_random_password(128, 128)
+    # Windows uses 240 bytes as UTF16 so we do
+    ctx.trustdom_pass = samba.generate_random_machine_password(120, 120)
 
     ctx.userAccountControl = samba.dsdb.UF_SERVER_TRUST_ACCOUNT | samba.dsdb.UF_TRUSTED_FOR_DELEGATION
 
diff -Nru samba-4.5.5+dfsg/python/samba/netcmd/domain.py samba-4.5.6+dfsg/python/samba/netcmd/domain.py
--- samba-4.5.5+dfsg/python/samba/netcmd/domain.py	2016-10-24 21:37:30.000000000 +0200
+++ samba-4.5.6+dfsg/python/samba/netcmd/domain.py	2017-03-09 10:21:43.000000000 +0100
@@ -2254,33 +2254,14 @@
             # needs to pass the NL_PASSWORD_VERSION structure within the
             # 512 bytes and a 2 bytes confounder is required.
             #
-            def random_trust_secret(length, use_aes_keys=True):
-                secret = [0] * length
-
-                pw1 = samba.generate_random_password(length/2, length/2)
-                if not use_aes_keys:
-                    # With arcfour-hmac-md5 we have to use valid utf16
-                    # in order to generate the correct pre-auth key
-                    # based on a utf8 password.
-                    #
-                    # We can remove this once our client libraries
-                    # support using the correct NTHASH.
-                    return string_to_byte_array(pw1.encode('utf-16-le'))
-
-                # We mix characters from generate_random_password
-                # with random numbers from random.randint()
-                for i in range(len(secret)):
-                    if len(pw1) > i:
-                        secret[i] = ord(pw1[i])
-                    else:
-                        secret[i] = random.randint(0, 255)
-
-                return secret
+            def random_trust_secret(length):
+                pw = samba.generate_random_machine_password(length/2, length/2)
+                return string_to_byte_array(pw.encode('utf-16-le'))
 
             if local_trust_info.trust_direction & lsa.LSA_TRUST_DIRECTION_INBOUND:
-                incoming_secret = random_trust_secret(240, use_aes_keys=use_aes_keys)
+                incoming_secret = random_trust_secret(240)
             if local_trust_info.trust_direction & lsa.LSA_TRUST_DIRECTION_OUTBOUND:
-                outgoing_secret = random_trust_secret(240, use_aes_keys=use_aes_keys)
+                outgoing_secret = random_trust_secret(240)
 
             remote_policy_access |= lsa.LSA_POLICY_TRUST_ADMIN
             remote_policy_access |= lsa.LSA_POLICY_CREATE_SECRET
diff -Nru samba-4.5.5+dfsg/python/samba/netcmd/user.py samba-4.5.6+dfsg/python/samba/netcmd/user.py
--- samba-4.5.5+dfsg/python/samba/netcmd/user.py	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/python/samba/netcmd/user.py	2017-03-09 10:21:43.000000000 +0100
@@ -670,7 +670,7 @@
                 self.outf.write("Sorry, passwords do not match.\n")
 
         try:
-            net.change_password(password)
+            net.change_password(password.encode('utf-8'))
         except Exception, msg:
             # FIXME: catch more specific exception
             raise CommandError("Failed to change password : %s" % msg)
diff -Nru samba-4.5.5+dfsg/python/samba/provision/__init__.py samba-4.5.6+dfsg/python/samba/provision/__init__.py
--- samba-4.5.5+dfsg/python/samba/provision/__init__.py	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/python/samba/provision/__init__.py	2017-03-09 10:21:43.000000000 +0100
@@ -877,7 +877,7 @@
         msg["msDS-KeyVersionNumber"] = [str(key_version_number)]
         msg["privateKeytab"] = ["secrets.keytab"]
 
-    msg["secret"] = [machinepass]
+    msg["secret"] = [machinepass.encode('utf-8')]
     msg["samAccountName"] = ["%s$" % netbiosname]
     msg["secureChannelType"] = [str(secure_channel_type)]
     if domainsid is not None:
@@ -1768,9 +1768,9 @@
         invocationid = str(uuid.uuid4())
 
     if krbtgtpass is None:
-        krbtgtpass = samba.generate_random_password(128, 255)
+        krbtgtpass = samba.generate_random_machine_password(128, 255)
     if machinepass is None:
-        machinepass  = samba.generate_random_password(128, 255)
+        machinepass = samba.generate_random_machine_password(128, 255)
     if dnspass is None:
         dnspass = samba.generate_random_password(128, 255)
 
diff -Nru samba-4.5.5+dfsg/python/samba/provision/sambadns.py samba-4.5.6+dfsg/python/samba/provision/sambadns.py
--- samba-4.5.5+dfsg/python/samba/provision/sambadns.py	2016-12-05 09:18:44.000000000 +0100
+++ samba-4.5.6+dfsg/python/samba/provision/sambadns.py	2017-03-09 10:21:43.000000000 +0100
@@ -661,7 +661,7 @@
             "REALM": realm,
             "DNSDOMAIN": dnsdomain,
             "DNS_KEYTAB": dns_keytab_path,
-            "DNSPASS_B64": b64encode(dnspass),
+            "DNSPASS_B64": b64encode(dnspass.encode('utf-8')),
             "KEY_VERSION_NUMBER": str(key_version_number),
             "HOSTNAME": names.hostname,
             "DNSNAME" : '%s.%s' % (
diff -Nru samba-4.5.5+dfsg/python/samba/samdb.py samba-4.5.6+dfsg/python/samba/samdb.py
--- samba-4.5.5+dfsg/python/samba/samdb.py	2016-12-05 09:18:44.000000000 +0100
+++ samba-4.5.6+dfsg/python/samba/samdb.py	2017-03-09 10:21:43.000000000 +0100
@@ -503,7 +503,7 @@
             if len(res) > 1:
                 raise Exception('Matched %u multiple users with filter "%s"' % (len(res), search_filter))
             user_dn = res[0].dn
-            pw = unicode('"' + password + '"', 'utf-8').encode('utf-16-le')
+            pw = unicode('"' + password.encode('utf-8') + '"', 'utf-8').encode('utf-16-le')
             setpw = """
 dn: %s
 changetype: modify
diff -Nru samba-4.5.5+dfsg/python/samba/upgradehelpers.py samba-4.5.6+dfsg/python/samba/upgradehelpers.py
--- samba-4.5.5+dfsg/python/samba/upgradehelpers.py	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/python/samba/upgradehelpers.py	2017-03-09 10:21:43.000000000 +0100
@@ -573,7 +573,7 @@
         assert(len(res) == 1)
 
         msg = ldb.Message(res[0].dn)
-        machinepass = samba.generate_random_password(128, 255)
+        machinepass = samba.generate_random_machine_password(128, 255)
         mputf16 = machinepass.encode('utf-16-le')
         msg["clearTextPassword"] = ldb.MessageElement(mputf16,
                                                 ldb.FLAG_MOD_REPLACE,
@@ -648,7 +648,7 @@
     assert(len(res) == 1)
 
     msg = ldb.Message(res[0].dn)
-    machinepass = samba.generate_random_password(128, 255)
+    machinepass = samba.generate_random_machine_password(128, 255)
     mputf16 = machinepass.encode('utf-16-le')
     msg["clearTextPassword"] = ldb.MessageElement(mputf16,
                                                   ldb.FLAG_MOD_REPLACE,
diff -Nru samba-4.5.5+dfsg/selftest/skip samba-4.5.6+dfsg/selftest/skip
--- samba-4.5.5+dfsg/selftest/skip	2017-01-17 20:55:44.000000000 +0100
+++ samba-4.5.6+dfsg/selftest/skip	2017-03-09 10:21:43.000000000 +0100
@@ -48,6 +48,7 @@
 ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).POSIX-SYMLINK-EA # Fails against the s4 ntvfs server
 ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).POSIX-OFD-LOCK # Fails against the s4 ntvfs server
 ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).POSIX-STREAM-DELETE # Fails against the s4 ntvfs server
+^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).WINDOWS-BAD-SYMLINK # Fails against the s4 ntvfs server
 ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).RENAME-ACCESS # Fails against the s4 ntvfs server
 ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).OWNER-RIGHTS # Don't test against the s4 ntvfs server anymore
 ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).PIDHIGH # Fails against the s4 ntvfs server
diff -Nru samba-4.5.5+dfsg/selftest/target/Samba3.pm samba-4.5.6+dfsg/selftest/target/Samba3.pm
--- samba-4.5.5+dfsg/selftest/target/Samba3.pm	2017-01-30 10:56:26.000000000 +0100
+++ samba-4.5.6+dfsg/selftest/target/Samba3.pm	2017-03-09 10:21:43.000000000 +0100
@@ -554,6 +554,7 @@
 	ntlm auth = yes
 	vfs objects = xattr_tdb streams_depot time_audit full_audit
 	change notify = no
+	smb encrypt = off
 
 	full_audit:syslog = no
 	full_audit:success = none
@@ -571,6 +572,11 @@
 	store dos attributes = yes
 	hide files = /hidefile/
 	hide dot files = yes
+
+[enc_desired]
+	path = $prefix_abs/share
+	vfs objects =
+	smb encrypt = desired
 ";
 
 	my $vars = $self->provision($path,
@@ -757,6 +763,8 @@
 	security = ads
         username map = $prefix/lib/username.map
         server signing = required
+	server min protocol = SMB3_00
+	client max protocol = SMB3
 ";
 
 	my $ret = $self->provision($prefix,
@@ -1615,6 +1623,30 @@
 	fruit:locking = netatalk
 	fruit:encoding = native
 
+[vfs_fruit_metadata_stream]
+	path = $shrdir
+	vfs objects = fruit streams_xattr acl_xattr
+	ea support = yes
+	fruit:resource = file
+	fruit:metadata = stream
+
+[vfs_fruit_stream_depot]
+	path = $shrdir
+	vfs objects = fruit streams_depot acl_xattr
+	ea support = yes
+	fruit:resource = stream
+	fruit:metadata = stream
+
+[vfs_wo_fruit]
+	path = $shrdir
+	vfs objects = streams_xattr acl_xattr
+	ea support = yes
+
+[vfs_wo_fruit_stream_depot]
+	path = $shrdir
+	vfs objects = streams_depot acl_xattr
+	ea support = yes
+
 [badname-tmp]
 	path = $badnames_shrdir
 	guest ok = yes
diff -Nru samba-4.5.5+dfsg/source3/include/MacExtensions.h samba-4.5.6+dfsg/source3/include/MacExtensions.h
--- samba-4.5.5+dfsg/source3/include/MacExtensions.h	2017-01-30 10:56:26.000000000 +0100
+++ samba-4.5.6+dfsg/source3/include/MacExtensions.h	2017-03-09 10:21:43.000000000 +0100
@@ -51,6 +51,9 @@
 #define AFP_Version			0x00000100
 #define AFP_BackupTime		0x80000000
 #define AFP_FinderSize		32
+
+#define AFP_OFF_FinderInfo	16
+
 /*
 ** Orginal AFP_AfpInfo stream used by NT 
 ** We needed a way to store the create date so SAMBA
diff -Nru samba-4.5.5+dfsg/source3/include/proto.h samba-4.5.6+dfsg/source3/include/proto.h
--- samba-4.5.5+dfsg/source3/include/proto.h	2016-09-13 10:21:35.000000000 +0200
+++ samba-4.5.6+dfsg/source3/include/proto.h	2017-03-09 10:21:43.000000000 +0100
@@ -880,6 +880,9 @@
 struct netlogon_creds_cli_context;
 struct messaging_context;
 struct dcerpc_binding_handle;
+char *trust_pw_new_value(TALLOC_CTX *mem_ctx,
+			 enum netr_SchannelType sec_channel_type,
+			 int security);
 NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
 			 struct messaging_context *msg_ctx,
 			 struct dcerpc_binding_handle *b,
diff -Nru samba-4.5.5+dfsg/source3/include/smb.h samba-4.5.6+dfsg/source3/include/smb.h
--- samba-4.5.5+dfsg/source3/include/smb.h	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/include/smb.h	2017-03-09 10:21:43.000000000 +0100
@@ -733,12 +733,6 @@
 
 #define SAFE_NETBIOS_CHARS ". -_"
 
-/* The maximum length of a trust account password.
-   Used when we randomly create it, 15 char passwords
-   exceed NT4's max password length */
-
-#define DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH 14
-
 #define PORT_NONE	0
 #ifndef LDAP_PORT
 #define LDAP_PORT	389
diff -Nru samba-4.5.5+dfsg/source3/lib/util_path.c samba-4.5.6+dfsg/source3/lib/util_path.c
--- samba-4.5.5+dfsg/source3/lib/util_path.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/lib/util_path.c	2017-03-09 10:21:43.000000000 +0100
@@ -93,3 +93,142 @@
 {
 	return xx_path(name, lp_cache_directory());
 }
+
+/**
+ * @brief Removes any invalid path components in an absolute POSIX path.
+ *
+ * @param ctx Talloc context to return string.
+ *
+ * @param abs_path Absolute path string to process.
+ *
+ * @retval Pointer to a talloc'ed string containing the absolute full path.
+ **/
+
+char *canonicalize_absolute_path(TALLOC_CTX *ctx, const char *abs_path)
+{
+	char *destname;
+	char *d;
+	const char *s = abs_path;
+	bool start_of_name_component = true;
+
+	/* Allocate for strlen + '\0' + possible leading '/' */
+	destname = (char *)talloc_size(ctx, strlen(abs_path) + 2);
+	if (destname == NULL) {
+		return NULL;
+        }
+	d = destname;
+
+	*d++ = '/'; /* Always start with root. */
+
+	while (*s) {
+		if (*s == '/') {
+			/* Eat multiple '/' */
+			while (*s == '/') {
+				s++;
+			}
+			if ((d > destname + 1) && (*s != '\0')) {
+				*d++ = '/';
+			}
+			start_of_name_component = true;
+			continue;
+		}
+
+		if (start_of_name_component) {
+			if ((s[0] == '.') && (s[1] == '.') &&
+					(s[2] == '/' || s[2] == '\0')) {
+				/* Uh oh - "/../" or "/..\0" ! */
+
+				/* Go past the .. leaving us on the / or '\0' */
+				s += 2;
+
+				/* If  we just added a '/' - delete it */
+				if ((d > destname) && (*(d-1) == '/')) {
+					*(d-1) = '\0';
+					d--;
+				}
+
+				/*
+				 * Are we at the start ?
+				 * Can't go back further if so.
+				 */
+				if (d <= destname) {
+					*d++ = '/'; /* Can't delete root */
+					continue;
+				}
+				/* Go back one level... */
+				/*
+				 * Decrement d first as d points to
+				 * the *next* char to write into.
+				 */
+				for (d--; d > destname; d--) {
+					if (*d == '/') {
+						break;
+					}
+				}
+
+				/*
+				 * Are we at the start ?
+				 * Can't go back further if so.
+				 */
+				if (d <= destname) {
+					*d++ = '/'; /* Can't delete root */
+					continue;
+				}
+
+				/*
+				 * We're still at the start of a name
+				 * component, just the previous one.
+				 */
+				continue;
+			} else if ((s[0] == '.') &&
+					((s[1] == '\0') || s[1] == '/')) {
+				/*
+				 * Component of pathname can't be "." only.
+				 * Skip the '.' .
+				 */
+				if (s[1] == '/') {
+					s += 2;
+				} else {
+					s++;
+				}
+				continue;
+			}
+		}
+
+		if (!(*s & 0x80)) {
+			*d++ = *s++;
+		} else {
+			size_t siz;
+			/* Get the size of the next MB character. */
+			next_codepoint(s,&siz);
+			switch(siz) {
+				case 5:
+					*d++ = *s++;
+					/*fall through*/
+				case 4:
+					*d++ = *s++;
+					/*fall through*/
+				case 3:
+					*d++ = *s++;
+					/*fall through*/
+				case 2:
+					*d++ = *s++;
+					/*fall through*/
+				case 1:
+					*d++ = *s++;
+					break;
+				default:
+					break;
+			}
+		}
+		start_of_name_component = false;
+	}
+	*d = '\0';
+
+	/* And must not end in '/' */
+	if (d > destname + 1 && (*(d-1) == '/')) {
+		*(d-1) = '\0';
+	}
+
+	return destname;
+}
diff -Nru samba-4.5.5+dfsg/source3/lib/util_path.h samba-4.5.6+dfsg/source3/lib/util_path.h
--- samba-4.5.5+dfsg/source3/lib/util_path.h	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/lib/util_path.h	2017-03-09 10:21:43.000000000 +0100
@@ -27,5 +27,6 @@
 char *lock_path(const char *name);
 char *state_path(const char *name);
 char *cache_path(const char *name);
+char *canonicalize_absolute_path(TALLOC_CTX *ctx, const char *abs_path);
 
 #endif
diff -Nru samba-4.5.5+dfsg/source3/libads/sasl.c samba-4.5.6+dfsg/source3/libads/sasl.c
--- samba-4.5.5+dfsg/source3/libads/sasl.c	2016-10-24 21:37:30.000000000 +0200
+++ samba-4.5.6+dfsg/source3/libads/sasl.c	2017-03-09 10:21:43.000000000 +0100
@@ -703,6 +703,7 @@
 #ifdef HAVE_KRB5
 	bool got_kerberos_mechanism = False;
 #endif
+	const char *mech = NULL;
 
 	rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", NULL, NULL, NULL, &scred);
 
@@ -749,6 +750,8 @@
 	if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
 	    got_kerberos_mechanism) 
 	{
+		mech = "KRB5";
+
 		if (ads->auth.password == NULL ||
 		    ads->auth.password[0] == '\0')
 		{
@@ -775,7 +778,11 @@
 							blob);
 			if (!ADS_ERR_OK(status)) {
 				DEBUG(0,("kinit succeeded but "
-					"ads_sasl_spnego_gensec_bind(KRB5) failed: %s\n",
+					"ads_sasl_spnego_gensec_bind(KRB5) failed: "
+					"for %s/%s user[%s] realm[%s]: %s\n",
+					p.service, p.hostname,
+					ads->auth.user_name,
+					ads->auth.realm,
 					ads_errstr(status)));
 			}
 		}
@@ -785,17 +792,33 @@
 		    !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
 			goto done;
 		}
+
+		DEBUG(1,("ads_sasl_spnego_gensec_bind(KRB5) failed for %s/%s "
+			 "with user[%s] realm[%s]: %s, fallback to NTLMSSP\n",
+			 p.service, p.hostname,
+			 ads->auth.user_name,
+			 ads->auth.realm,
+			 ads_errstr(status)));
 	}
 #endif
 
 	/* lets do NTLMSSP ... this has the big advantage that we don't need
 	   to sync clocks, and we don't rely on special versions of the krb5 
 	   library for HMAC_MD4 encryption */
+	mech = "NTLMSSP";
 	status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
 					     CRED_DONT_USE_KERBEROS,
 					     p.service, p.hostname,
 					     data_blob_null);
 done:
+	if (!ADS_ERR_OK(status)) {
+		DEBUG(1,("ads_sasl_spnego_gensec_bind(%s) failed for %s/%s "
+			 "with user[%s] realm=[%s]: %s\n", mech,
+			  p.service, p.hostname,
+			  ads->auth.user_name,
+			  ads->auth.realm,
+			  ads_errstr(status)));
+	}
 	ads_free_service_principal(&p);
 	TALLOC_FREE(frame);
 	if (blob.data != NULL) {
diff -Nru samba-4.5.5+dfsg/source3/libads/util.c samba-4.5.6+dfsg/source3/libads/util.c
--- samba-4.5.5+dfsg/source3/libads/util.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/libads/util.c	2017-03-09 10:21:43.000000000 +0100
@@ -35,9 +35,12 @@
 		return ADS_ERROR_SYSTEM(ENOENT);
 	}
 
-	new_password = generate_random_password(talloc_tos(),
-				DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH,
-				DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
+	new_password = trust_pw_new_value(talloc_tos(), SEC_CHAN_WKSTA, SEC_ADS);
+	if (new_password == NULL) {
+		ret = ADS_ERROR_SYSTEM(errno);
+		DEBUG(1,("Failed to generate machine password\n"));
+		goto failed;
+	}
 
 	ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password, host_principal, new_password, ads->auth.time_offset);
 
diff -Nru samba-4.5.5+dfsg/source3/libnet/libnet_join.c samba-4.5.6+dfsg/source3/libnet/libnet_join.c
--- samba-4.5.5+dfsg/source3/libnet/libnet_join.c	2016-09-13 10:21:35.000000000 +0200
+++ samba-4.5.6+dfsg/source3/libnet/libnet_join.c	2017-03-09 10:21:43.000000000 +0100
@@ -1138,9 +1138,11 @@
 	}
 
 	if (!r->in.machine_password) {
-		r->in.machine_password = generate_random_password(mem_ctx,
-				DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH,
-				DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
+		int security = r->in.ads ? SEC_ADS : SEC_DOMAIN;
+
+		r->in.machine_password = trust_pw_new_value(mem_ctx,
+						r->in.secure_channel_type,
+						security);
 		if (r->in.machine_password == NULL) {
 			TALLOC_FREE(frame);
 			return NT_STATUS_NO_MEMORY;
@@ -1233,9 +1235,11 @@
 	}
 
 	if (!r->in.machine_password) {
-		r->in.machine_password = generate_random_password(mem_ctx,
-				DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH,
-				DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
+		int security = r->in.ads ? SEC_ADS : SEC_DOMAIN;
+
+		r->in.machine_password = trust_pw_new_value(mem_ctx,
+						r->in.secure_channel_type,
+						security);
 		NT_STATUS_HAVE_NO_MEMORY(r->in.machine_password);
 	}
 
diff -Nru samba-4.5.5+dfsg/source3/librpc/rpc/dcerpc.h samba-4.5.6+dfsg/source3/librpc/rpc/dcerpc.h
--- samba-4.5.5+dfsg/source3/librpc/rpc/dcerpc.h	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/librpc/rpc/dcerpc.h	2017-03-09 10:21:43.000000000 +0100
@@ -61,8 +61,7 @@
 				  DATA_BLOB *blob);
 NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx,
 				  const DATA_BLOB *blob,
-				  struct ncacn_packet *r,
-				  bool bigendian);
+				  struct ncacn_packet *r);
 NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx,
 				 enum dcerpc_AuthType auth_type,
 				 enum dcerpc_AuthLevel auth_level,
diff -Nru samba-4.5.5+dfsg/source3/librpc/rpc/dcerpc_helpers.c samba-4.5.6+dfsg/source3/librpc/rpc/dcerpc_helpers.c
--- samba-4.5.5+dfsg/source3/librpc/rpc/dcerpc_helpers.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/librpc/rpc/dcerpc_helpers.c	2017-03-09 10:21:43.000000000 +0100
@@ -88,14 +88,12 @@
 *			elements
 * @param blob		The blob of data to decode
 * @param r		An empty ncacn_packet, must not be NULL
-* @param bigendian	Whether the packet is bignedian encoded
 *
 * @return a NTSTATUS error code
 */
 NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx,
 				  const DATA_BLOB *blob,
-				  struct ncacn_packet *r,
-				  bool bigendian)
+				  struct ncacn_packet *r)
 {
 	enum ndr_err_code ndr_err;
 	struct ndr_pull *ndr;
@@ -104,11 +102,12 @@
 	if (!ndr) {
 		return NT_STATUS_NO_MEMORY;
 	}
-	if (bigendian) {
+
+	if (!(CVAL(ndr->data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) {
 		ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
 	}
 
-	if (CVAL(blob->data, DCERPC_PFC_OFFSET) & DCERPC_PFC_FLAG_OBJECT_UUID) {
+	if (CVAL(ndr->data, DCERPC_PFC_OFFSET) & DCERPC_PFC_FLAG_OBJECT_UUID) {
 		ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
 	}
 
diff -Nru samba-4.5.5+dfsg/source3/libsmb/trusts_util.c samba-4.5.6+dfsg/source3/libsmb/trusts_util.c
--- samba-4.5.5+dfsg/source3/libsmb/trusts_util.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/libsmb/trusts_util.c	2017-03-09 10:21:43.000000000 +0100
@@ -47,6 +47,62 @@
 	return 0;
 }
 
+char *trust_pw_new_value(TALLOC_CTX *mem_ctx,
+			 enum netr_SchannelType sec_channel_type,
+			 int security)
+{
+	/*
+	 * use secure defaults.
+	 */
+	size_t min = 128;
+	size_t max = 255;
+
+	switch (sec_channel_type) {
+	case SEC_CHAN_WKSTA:
+	case SEC_CHAN_BDC:
+		if (security == SEC_DOMAIN) {
+			/*
+			 * The maximum length of a trust account password.
+			 * Used when we randomly create it, 15 char passwords
+			 * exceed NT4's max password length.
+			 */
+			min = 14;
+			max = 14;
+		}
+		break;
+	case SEC_CHAN_DNS_DOMAIN:
+		/*
+		 * new_len * 2 = 498 bytes is the largest possible length
+		 * NL_PASSWORD_VERSION consumes the rest of the possible 512 bytes
+		 * and a confounder with at least 2 bytes is required.
+		 *
+		 * Windows uses new_len = 120 => 240 bytes (utf16)
+		 */
+		min = 120;
+		max = 120;
+		break;
+		/* fall through */
+	case SEC_CHAN_DOMAIN:
+		/*
+		 * The maximum length of a trust account password.
+		 * Used when we randomly create it, 15 char passwords
+		 * exceed NT4's max password length.
+		 */
+		min = 14;
+		max = 14;
+		break;
+	default:
+		break;
+	}
+
+	/*
+	 * Create a random machine account password
+	 * We create a random buffer and convert that to utf8.
+	 * This is similar to what windows is doing.
+	 */
+	return generate_random_machine_password(mem_ctx, min, max);
+}
+
 NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
 			 struct messaging_context *msg_ctx,
 			 struct dcerpc_binding_handle *b,
@@ -54,6 +110,7 @@
 			 bool force)
 {
 	TALLOC_CTX *frame = talloc_stackframe();
+	const char *context_name = NULL;
 	struct trust_pw_change_state *state;
 	struct cli_credentials *creds = NULL;
 	const struct samr_Password *current_nt_hash = NULL;
@@ -65,10 +122,7 @@
 	struct timeval g_timeout = { 0, };
 	int timeout = 0;
 	struct timeval tv = { 0, };
-	size_t new_len = DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH;
-	uint8_t new_password_buffer[256 * 2] = { 0, };
 	char *new_trust_passwd = NULL;
-	size_t len = 0;
 	uint32_t new_version = 0;
 	uint32_t *new_trust_version = NULL;
 	NTSTATUS status;
@@ -134,16 +188,6 @@
 	case SEC_CHAN_BDC:
 		break;
 	case SEC_CHAN_DNS_DOMAIN:
-		/*
-		 * new_len * 2 = 498 bytes is the largest possible length
-		 * NL_PASSWORD_VERSION consumes the rest of the possible 512 bytes
-		 * and a confounder with at least 2 bytes is required.
-		 *
-		 * Windows uses new_len = 120 => 240 bytes.
-		 */
-		new_len = 120;
-
-		/* fall through */
 	case SEC_CHAN_DOMAIN:
 		status = pdb_get_trusted_domain(frame, domain, &td);
 		if (!NT_STATUS_IS_OK(status)) {
@@ -181,19 +225,21 @@
 		return NT_STATUS_OK;
 	}
 
+	context_name = netlogon_creds_cli_debug_string(context, talloc_tos());
+	if (context_name == NULL) {
+		TALLOC_FREE(frame);
+		return NT_STATUS_NO_MEMORY;
+	}
+
 	/*
 	 * Create a random machine account password
 	 * We create a random buffer and convert that to utf8.
 	 * This is similar to what windows is doing.
 	 */
-	generate_secret_buffer(new_password_buffer, new_len * 2);
-	ok = convert_string_talloc(frame,
-				   CH_UTF16MUNGED, CH_UTF8,
-				   new_password_buffer, new_len * 2,
-				   (void *)&new_trust_passwd, &len);
-	ZERO_STRUCT(new_password_buffer);
-	if (!ok) {
-		DEBUG(0, ("convert_string_talloc failed\n"));
+	new_trust_passwd = trust_pw_new_value(frame, sec_channel_type,
+					      lp_security());
+	if (new_trust_passwd == NULL) {
+		DEBUG(0, ("trust_pw_new_value() failed\n"));
 		TALLOC_FREE(frame);
 		return NT_STATUS_NO_MEMORY;
 	}
@@ -215,12 +261,16 @@
 					 *current_nt_hash,
 					 previous_nt_hash);
 	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(0, ("netlogon_creds_cli_auth for domain %s - %s!\n",
-			  domain, nt_errstr(status)));
+		DEBUG(0, ("netlogon_creds_cli_auth(%s) failed for old password - %s!\n",
+			  context_name, nt_errstr(status)));
 		TALLOC_FREE(frame);
 		return status;
 	}
 
+	DEBUG(0,("%s : %s(%s): Verified old password remotely using %s\n",
+		 current_timestring(talloc_tos(), false),
+		 __func__, domain, context_name));
+
 	/*
 	 * Return the result of trying to write the new password
 	 * back into the trust account file.
@@ -260,22 +310,57 @@
 		break;
 	}
 
-	DEBUG(1,("%s : %s(%s): Changed password locally\n",
+	DEBUG(0,("%s : %s(%s): Changed password locally\n",
 		 current_timestring(talloc_tos(), false), __func__, domain));
 
 	status = netlogon_creds_cli_ServerPasswordSet(context, b,
 						      new_trust_passwd,
 						      new_trust_version);
 	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(0,("%s : %s(%s) remote password change set failed - %s\n",
-			 current_timestring(talloc_tos(), false), __func__,
-			 domain, nt_errstr(status)));
+		DEBUG(0,("%s : %s(%s) remote password change set with %s failed - %s\n",
+			 current_timestring(talloc_tos(), false),
+			 __func__, domain, context_name,
+			 nt_errstr(status)));
 		TALLOC_FREE(frame);
 		return status;
 	}
 
-	DEBUG(1,("%s : %s(%s): Changed password remotely.\n",
-		 current_timestring(talloc_tos(), false), __func__, domain));
+	DEBUG(0,("%s : %s(%s): Changed password remotely using %s\n",
+		 current_timestring(talloc_tos(), false),
+		 __func__, domain, context_name));
+
+	ok = cli_credentials_set_password(creds, new_trust_passwd, CRED_SPECIFIED);
+	if (!ok) {
+		DEBUG(0, ("cli_credentials_set_password failed for domain %s!\n",
+			  domain));
+		TALLOC_FREE(frame);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	current_nt_hash = cli_credentials_get_nt_hash(creds, frame);
+	if (current_nt_hash == NULL) {
+		DEBUG(0, ("cli_credentials_get_nt_hash failed for domain %s!\n",
+			  domain));
+		TALLOC_FREE(frame);
+		return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE;
+	}
+
+	/*
+	 * Now we verify the new password.
+	 */
+	status = netlogon_creds_cli_auth(context, b,
+					 *current_nt_hash,
+					 NULL); /* previous_nt_hash */
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(0, ("netlogon_creds_cli_auth(%s) failed for new password - %s!\n",
+			  context_name, nt_errstr(status)));
+		TALLOC_FREE(frame);
+		return status;
+	}
+
+	DEBUG(0,("%s : %s(%s): Verified new password remotely using %s\n",
+		 current_timestring(talloc_tos(), false),
+		 __func__, domain, context_name));
 
 	TALLOC_FREE(frame);
 	return NT_STATUS_OK;
diff -Nru samba-4.5.5+dfsg/source3/modules/vfs_catia.c samba-4.5.6+dfsg/source3/modules/vfs_catia.c
--- samba-4.5.5+dfsg/source3/modules/vfs_catia.c	2017-01-30 10:56:26.000000000 +0100
+++ samba-4.5.6+dfsg/source3/modules/vfs_catia.c	2017-03-09 10:21:43.000000000 +0100
@@ -4,13 +4,13 @@
  * Implement a fixed mapping of forbidden NT characters in filenames that are
  * used a lot by the CAD package Catia.
  *
- * Yes, this a BAD BAD UGLY INCOMPLETE hack, but it helps quite some people
- * out there. Catia V4 on AIX uses characters like "<*$ a *lot*, all forbidden
- * under Windows...
+ * Catia V4 on AIX uses characters like "<*$ a *lot*, all forbidden under
+ * Windows...
  *
  * Copyright (C) Volker Lendecke, 2005
  * Copyright (C) Aravind Srinivasan, 2009
  * Copyright (C) Guenter Kukkukk, 2013
+ * Copyright (C) Ralph Boehme, 2017
  *
  * 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
@@ -29,6 +29,8 @@
 
 #include "includes.h"
 #include "smbd/smbd.h"
+#include "lib/util/tevent_unix.h"
+#include "lib/util/tevent_ntstatus.h"
 
 static int vfs_catia_debug_level = DBGC_VFS;
 
@@ -52,6 +54,15 @@
 	struct char_mappings **mappings;
 };
 
+struct catia_cache {
+	bool is_fsp_ext;
+	const struct catia_cache * const *busy;
+	char *orig_fname;
+	char *fname;
+	char *orig_base_fname;
+	char *base_fname;
+};
+
 struct share_mapping_entry *srt_head = NULL;
 
 static bool build_table(struct char_mappings **cmaps, int value)
@@ -353,30 +364,305 @@
 	return ret;
 }
 
+#define CATIA_DEBUG_CC(lvl, cc, fsp) \
+	catia_debug_cc((lvl), (cc), (fsp), __location__);
+
+static void catia_debug_cc(int lvl,
+			   struct catia_cache *cc,
+			   files_struct *fsp,
+			   const char *location)
+{
+	DEBUG(lvl, ("%s: cc [0x%p] cc->busy [0x%p] "
+		    "is_fsp_ext [%s] "
+		    "fsp [0x%p] fsp name [%s] "
+		    "orig_fname [%s] "
+		    "fname [%s] "
+		    "orig_base_fname [%s] "
+		    "base_fname [%s]\n",
+		    location,
+		    cc, cc->busy,
+		    cc->is_fsp_ext ? "yes" : "no",
+		    fsp, fsp_str_dbg(fsp),
+		    cc->orig_fname, cc->fname,
+		    cc->orig_base_fname, cc->base_fname));
+}
+
+static void catia_free_cc(struct catia_cache **_cc,
+			  vfs_handle_struct *handle,
+			  files_struct *fsp)
+{
+	struct catia_cache *cc = *_cc;
+
+	if (cc->is_fsp_ext) {
+		VFS_REMOVE_FSP_EXTENSION(handle, fsp);
+		cc = NULL;
+	} else {
+		TALLOC_FREE(cc);
+	}
+
+	*_cc = NULL;
+}
+
+static struct catia_cache *catia_validate_and_apply_cc(
+				       vfs_handle_struct *handle,
+				       files_struct *fsp,
+				       const struct catia_cache * const *busy,
+				       bool *make_tmp_cache)
+{
+	struct catia_cache *cc = NULL;
+
+	*make_tmp_cache = false;
+
+	cc = (struct catia_cache *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+	if (cc == NULL) {
+		return NULL;
+	}
+
+	if (cc->busy != NULL) {
+		if (cc->busy == busy) {
+			/* This should never happen */
+			CATIA_DEBUG_CC(0, cc, fsp);
+			smb_panic(__location__);
+		}
+
+		/*
+		 * Recursion. Validate names, the names in the fsp's should be
+		 * the translated names we had set.
+		 */
+
+		if ((cc->fname != fsp->fsp_name->base_name)
+		    ||
+		    ((fsp->base_fsp != NULL) &&
+		     (cc->base_fname != fsp->base_fsp->fsp_name->base_name)))
+		{
+			CATIA_DEBUG_CC(10, cc, fsp);
+
+			/*
+			 * Names changed. Setting don't expose the cache on the
+			 * fsp and ask the caller to create a temporary cache.
+			 */
+			*make_tmp_cache = true;
+			return NULL;
+		}
+
+		/*
+		 * Ok, a validated cache while in a recursion, just let the
+		 * caller detect that cc->busy is != busy and there's
+		 * nothing else to do.
+		 */
+		CATIA_DEBUG_CC(10, cc, fsp);
+		return cc;
+	}
+
+	/* Not in a recursion */
+
+	if ((cc->orig_fname != fsp->fsp_name->base_name)
+	    ||
+	    ((fsp->base_fsp != NULL) &&
+	     (cc->orig_base_fname != fsp->base_fsp->fsp_name->base_name)))
+	{
+		/*
+		 * fsp names changed, this can happen in an rename op.
+		 * Trigger recreation as a full fledged fsp extension.
+		 */
+
+		CATIA_DEBUG_CC(10, cc, fsp);
+		catia_free_cc(&cc, handle, fsp);
+		return NULL;
+	}
+
+
+	/*
+	 * Ok, we found a valid cache entry, no recursion. Just set translated
+	 * names from the cache and mark the cc as busy.
+	 */
+	fsp->fsp_name->base_name = cc->fname;
+	if (fsp->base_fsp != NULL) {
+		fsp->base_fsp->fsp_name->base_name = cc->base_fname;
+	}
+
+	cc->busy = busy;
+	CATIA_DEBUG_CC(10, cc, fsp);
+	return cc;
+}
+
+#define CATIA_FETCH_FSP_PRE_NEXT(mem_ctx, handle, fsp, _cc) \
+	catia_fetch_fsp_pre_next((mem_ctx), (handle), (fsp), (_cc), __func__);
+
+static int catia_fetch_fsp_pre_next(TALLOC_CTX *mem_ctx,
+				    vfs_handle_struct *handle,
+				    files_struct *fsp,
+				    struct catia_cache **_cc,
+				    const char *function)
+{
+	const struct catia_cache * const *busy =
+		(const struct catia_cache * const *)_cc;
+	struct catia_cache *cc = NULL;
+	NTSTATUS status;
+	bool make_tmp_cache = false;
+
+	*_cc = NULL;
+
+	DBG_DEBUG("Called from [%s]\n", function);
+
+	cc = catia_validate_and_apply_cc(handle,
+					 fsp,
+					 busy,
+					 &make_tmp_cache);
+	if (cc != NULL) {
+		if (cc->busy != busy) {
+			return 0;
+		}
+		*_cc = cc;
+		return 0;
+	}
+
+	if (!make_tmp_cache) {
+		cc = (struct catia_cache *)VFS_ADD_FSP_EXTENSION(
+			handle, fsp, struct catia_cache, NULL);
+		if (cc == NULL) {
+			return -1;
+		}
+		*cc = (struct catia_cache) {
+			.is_fsp_ext = true,
+		};
+
+		mem_ctx = VFS_MEMCTX_FSP_EXTENSION(handle, fsp);
+		if (mem_ctx == NULL) {
+			DBG_ERR("VFS_MEMCTX_FSP_EXTENSION failed\n");
+			catia_free_cc(&cc, handle, fsp);
+			return -1;
+		}
+	} else {
+		cc = talloc_zero(mem_ctx, struct catia_cache);
+		if (cc == NULL) {
+			return -1;
+		}
+		mem_ctx = cc;
+	}
+
+
+	status = catia_string_replace_allocate(handle->conn,
+					       fsp->fsp_name->base_name,
+					       &cc->fname,
+					       vfs_translate_to_unix);
+	if (!NT_STATUS_IS_OK(status)) {
+		catia_free_cc(&cc, handle, fsp);
+		errno = map_errno_from_nt_status(status);
+		return -1;
+	}
+	talloc_steal(mem_ctx, cc->fname);
+
+	if (fsp->base_fsp != NULL) {
+		status = catia_string_replace_allocate(
+			handle->conn,
+			fsp->base_fsp->fsp_name->base_name,
+			&cc->base_fname,
+			vfs_translate_to_unix);
+		if (!NT_STATUS_IS_OK(status)) {
+			catia_free_cc(&cc, handle, fsp);
+			errno = map_errno_from_nt_status(status);
+			return -1;
+		}
+		talloc_steal(mem_ctx, cc->base_fname);
+	}
+
+	cc->orig_fname = fsp->fsp_name->base_name;
+	fsp->fsp_name->base_name = cc->fname;
+
+	if (fsp->base_fsp != NULL) {
+		cc->orig_base_fname = fsp->base_fsp->fsp_name->base_name;
+		fsp->base_fsp->fsp_name->base_name = cc->base_fname;
+	}
+
+	cc->busy = busy;
+	CATIA_DEBUG_CC(10, cc, fsp);
+
+	*_cc = cc;
+
+	return 0;
+}
+
+#define CATIA_FETCH_FSP_POST_NEXT(_cc, fsp) do { \
+	int saved_errno = errno; \
+	catia_fetch_fsp_post_next((_cc), (fsp), __func__); \
+	errno = saved_errno; \
+} while(0)
+
+static void catia_fetch_fsp_post_next(struct catia_cache **_cc,
+				      files_struct *fsp,
+				      const char *function)
+{
+	const struct catia_cache * const *busy =
+		(const struct catia_cache * const *)_cc;
+	struct catia_cache *cc = *_cc;
+
+	DBG_DEBUG("Called from [%s]\n", function);
+
+	if (cc == NULL) {
+		/*
+		 * This can happen when recursing in the VFS on the fsp when the
+		 * pre_next func noticed the recursion and set out cc pointer to
+		 * NULL.
+		 */
+		return;
+	}
+
+	if (cc->busy != busy) {
+		CATIA_DEBUG_CC(0, cc, fsp);
+		smb_panic(__location__);
+		return;
+	}
+
+	cc->busy = NULL;
+	*_cc = NULL;
+
+	fsp->fsp_name->base_name = cc->orig_fname;
+	if (fsp->base_fsp != NULL) {
+		fsp->base_fsp->fsp_name->base_name = cc->orig_base_fname;
+	}
+
+	CATIA_DEBUG_CC(10, cc, fsp);
+
+	if (!cc->is_fsp_ext) {
+		TALLOC_FREE(cc);
+	}
+
+	return;
+}
+
 static int catia_open(vfs_handle_struct *handle,
 		      struct smb_filename *smb_fname,
 		      files_struct *fsp,
 		      int flags,
 		      mode_t mode)
 {
-	char *name_mapped = NULL;
-	char *tmp_base_name;
-	int ret;
+	struct catia_cache *cc = NULL;
+	char *orig_smb_fname = smb_fname->base_name;
+	char *mapped_smb_fname = NULL;
 	NTSTATUS status;
+	int ret;
 
-	tmp_base_name = smb_fname->base_name;
 	status = catia_string_replace_allocate(handle->conn,
-					smb_fname->base_name,
-					&name_mapped, vfs_translate_to_unix);
+					       smb_fname->base_name,
+					       &mapped_smb_fname,
+					       vfs_translate_to_unix);
 	if (!NT_STATUS_IS_OK(status)) {
-		errno = map_errno_from_nt_status(status);
 		return -1;
 	}
 
-	smb_fname->base_name = name_mapped;
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		TALLOC_FREE(mapped_smb_fname);
+		return ret;
+	}
+
+	smb_fname->base_name = mapped_smb_fname;
 	ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
-	smb_fname->base_name = tmp_base_name;
-	TALLOC_FREE(name_mapped);
+	smb_fname->base_name = orig_smb_fname;
+
+	TALLOC_FREE(mapped_smb_fname);
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
 
 	return ret;
 }
@@ -1114,33 +1400,1030 @@
 	return ret;
 }
 
+static int catia_fstat(vfs_handle_struct *handle,
+		       files_struct *fsp,
+		       SMB_STRUCT_STAT *sbuf)
+{
+	struct catia_cache *cc = NULL;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return ret;
+}
+
+static ssize_t catia_pread(vfs_handle_struct *handle,
+			   files_struct *fsp, void *data,
+			   size_t n, off_t offset)
+{
+	struct catia_cache *cc = NULL;
+	ssize_t result;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return ret;
+	}
+
+	result = SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return result;
+}
+
+static ssize_t catia_pwrite(vfs_handle_struct *handle,
+			    files_struct *fsp, const void *data,
+			    size_t n, off_t offset)
+{
+	struct catia_cache *cc = NULL;
+	ssize_t result;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return ret;
+	}
+
+	result = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return result;
+}
+
+static int catia_ftruncate(struct vfs_handle_struct *handle,
+			   struct files_struct *fsp,
+			   off_t offset)
+{
+	struct catia_cache *cc = NULL;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return ret;
+}
+
+static int catia_fallocate(struct vfs_handle_struct *handle,
+			   struct files_struct *fsp,
+			   uint32_t mode,
+			   off_t offset,
+			   off_t len)
+{
+	struct catia_cache *cc = NULL;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = SMB_VFS_NEXT_FALLOCATE(handle, fsp, mode, offset, len);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return ret;
+}
+
+static ssize_t catia_fgetxattr(struct vfs_handle_struct *handle,
+			       struct files_struct *fsp,
+			       const char *name,
+			       void *value,
+			       size_t size)
+{
+	char *mapped_xattr_name = NULL;
+	NTSTATUS status;
+	ssize_t result;
+
+	status = catia_string_replace_allocate(handle->conn,
+					       name, &mapped_xattr_name,
+					       vfs_translate_to_unix);
+	if (!NT_STATUS_IS_OK(status)) {
+		errno = map_errno_from_nt_status(status);
+		return -1;
+	}
+
+	result = SMB_VFS_NEXT_FGETXATTR(handle, fsp, mapped_xattr_name,
+					value, size);
+
+	TALLOC_FREE(mapped_xattr_name);
+
+	return result;
+}
+
+static ssize_t catia_flistxattr(struct vfs_handle_struct *handle,
+				struct files_struct *fsp,
+				char *list,
+				size_t size)
+{
+	struct catia_cache *cc = NULL;
+	ssize_t result;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return ret;
+	}
+
+	result = SMB_VFS_NEXT_FLISTXATTR(handle, fsp, list, size);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return result;
+}
+
+static int catia_fremovexattr(struct vfs_handle_struct *handle,
+			      struct files_struct *fsp,
+			      const char *name)
+{
+	char *mapped_name = NULL;
+	NTSTATUS status;
+	int ret;
+
+	status = catia_string_replace_allocate(handle->conn,
+				name, &mapped_name, vfs_translate_to_unix);
+	if (!NT_STATUS_IS_OK(status)) {
+		errno = map_errno_from_nt_status(status);
+		return -1;
+	}
+
+	ret = SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, mapped_name);
+
+	TALLOC_FREE(mapped_name);
+
+	return ret;
+}
+
+static int catia_fsetxattr(struct vfs_handle_struct *handle,
+			   struct files_struct *fsp,
+			   const char *name,
+			   const void *value,
+			   size_t size,
+			   int flags)
+{
+	char *mapped_xattr_name = NULL;
+	NTSTATUS status;
+	int ret;
+
+	status = catia_string_replace_allocate(
+		handle->conn, name, &mapped_xattr_name, vfs_translate_to_unix);
+	if (!NT_STATUS_IS_OK(status)) {
+		errno = map_errno_from_nt_status(status);
+		return -1;
+	}
+
+	ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, mapped_xattr_name,
+				     value, size, flags);
+
+	TALLOC_FREE(mapped_xattr_name);
+
+	return ret;
+}
+
+static SMB_ACL_T catia_sys_acl_get_fd(vfs_handle_struct *handle,
+				      files_struct *fsp,
+				      TALLOC_CTX *mem_ctx)
+{
+	struct catia_cache *cc = NULL;
+	struct smb_acl_t *result = NULL;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return NULL;
+	}
+
+	result = SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp, mem_ctx);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return result;
+}
+
+static int catia_sys_acl_blob_get_fd(vfs_handle_struct *handle,
+				     files_struct *fsp,
+				     TALLOC_CTX *mem_ctx,
+				     char **blob_description,
+				     DATA_BLOB *blob)
+{
+	struct catia_cache *cc = NULL;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle, fsp, mem_ctx,
+					       blob_description, blob);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return ret;
+}
+
+static int catia_sys_acl_set_fd(vfs_handle_struct *handle,
+				files_struct *fsp,
+				SMB_ACL_T theacl)
+{
+	struct catia_cache *cc = NULL;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, theacl);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return ret;
+}
+
+static int catia_fchmod_acl(vfs_handle_struct *handle,
+			    files_struct *fsp,
+			    mode_t mode)
+{
+	struct catia_cache *cc = NULL;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, mode);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return ret;
+}
+
+static NTSTATUS catia_fget_nt_acl(vfs_handle_struct *handle,
+				  files_struct *fsp,
+				  uint32_t security_info,
+				  TALLOC_CTX *mem_ctx,
+				  struct security_descriptor **ppdesc)
+{
+	struct catia_cache *cc = NULL;
+	NTSTATUS status;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return map_nt_error_from_unix(errno);
+	}
+
+	status = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
+					  mem_ctx, ppdesc);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return status;
+}
+
+static NTSTATUS catia_fset_nt_acl(vfs_handle_struct *handle,
+				  files_struct *fsp,
+				  uint32_t security_info_sent,
+				  const struct security_descriptor *psd)
+{
+	struct catia_cache *cc = NULL;
+	NTSTATUS status;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return map_nt_error_from_unix(errno);
+	}
+
+	status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return status;
+}
+
+static NTSTATUS catia_fset_dos_attributes(struct vfs_handle_struct *handle,
+					  struct files_struct *fsp,
+					  uint32_t dosmode)
+{
+	struct catia_cache *cc = NULL;
+	NTSTATUS status;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return map_nt_error_from_unix(errno);
+	}
+
+	status = SMB_VFS_NEXT_FSET_DOS_ATTRIBUTES(handle, fsp, dosmode);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return status;
+}
+
+static NTSTATUS catia_fget_dos_attributes(struct vfs_handle_struct *handle,
+					  struct files_struct *fsp,
+					  uint32_t *dosmode)
+{
+	struct catia_cache *cc = NULL;
+	NTSTATUS status;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return map_nt_error_from_unix(errno);
+	}
+
+	status = SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES(handle, fsp, dosmode);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return status;
+}
+
+static int catia_fchown(vfs_handle_struct *handle,
+			files_struct *fsp,
+			uid_t uid,
+			gid_t gid)
+{
+	struct catia_cache *cc = NULL;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = SMB_VFS_NEXT_FCHOWN(handle, fsp, uid, gid);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return ret;
+}
+
+static int catia_fchmod(vfs_handle_struct *handle,
+			files_struct *fsp,
+			mode_t mode)
+{
+	struct catia_cache *cc = NULL;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return ret;
+}
+
+struct catia_pread_state {
+	ssize_t ret;
+	struct vfs_aio_state vfs_aio_state;
+	struct files_struct *fsp;
+	struct catia_cache *cc;
+};
+
+static void catia_pread_done(struct tevent_req *subreq);
+
+static struct tevent_req *catia_pread_send(struct vfs_handle_struct *handle,
+					   TALLOC_CTX *mem_ctx,
+					   struct tevent_context *ev,
+					   struct files_struct *fsp,
+					   void *data,
+					   size_t n,
+					   off_t offset)
+{
+	struct tevent_req *req = NULL, *subreq = NULL;
+	struct catia_pread_state *state = NULL;
+	int ret;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct catia_pread_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	state->fsp = fsp;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(state, handle, fsp, &state->cc);
+	if (ret != 0) {
+		tevent_req_error(req, errno);
+		return tevent_req_post(req, ev);
+	}
+
+	subreq = SMB_VFS_NEXT_PREAD_SEND(state, ev, handle, fsp, data,
+					 n, offset);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, catia_pread_done, req);
+
+	return req;
+}
+
+static void catia_pread_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct catia_pread_state *state = tevent_req_data(
+		req, struct catia_pread_state);
+
+	state->ret = SMB_VFS_PREAD_RECV(subreq, &state->vfs_aio_state);
+	TALLOC_FREE(subreq);
+
+	CATIA_FETCH_FSP_POST_NEXT(&state->cc, state->fsp);
+
+	tevent_req_done(req);
+}
+
+static ssize_t catia_pread_recv(struct tevent_req *req,
+				struct vfs_aio_state *vfs_aio_state)
+{
+	struct catia_pread_state *state = tevent_req_data(
+		req, struct catia_pread_state);
+
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
+		return -1;
+	}
+
+	*vfs_aio_state = state->vfs_aio_state;
+	return state->ret;
+}
+
+struct catia_pwrite_state {
+	ssize_t ret;
+	struct vfs_aio_state vfs_aio_state;
+	struct files_struct *fsp;
+	struct catia_cache *cc;
+};
+
+static void catia_pwrite_done(struct tevent_req *subreq);
+
+static struct tevent_req *catia_pwrite_send(struct vfs_handle_struct *handle,
+					    TALLOC_CTX *mem_ctx,
+					    struct tevent_context *ev,
+					    struct files_struct *fsp,
+					    const void *data,
+					    size_t n,
+					    off_t offset)
+{
+	struct tevent_req *req = NULL, *subreq = NULL;
+	struct catia_pwrite_state *state = NULL;
+	int ret;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct catia_pwrite_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	state->fsp = fsp;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(state, handle, fsp, &state->cc);
+	if (ret != 0) {
+		tevent_req_error(req, errno);
+		return tevent_req_post(req, ev);
+	}
+
+	subreq = SMB_VFS_NEXT_PWRITE_SEND(state, ev, handle, fsp, data,
+					  n, offset);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, catia_pwrite_done, req);
+
+	return req;
+}
+
+static void catia_pwrite_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct catia_pwrite_state *state = tevent_req_data(
+		req, struct catia_pwrite_state);
+
+	state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->vfs_aio_state);
+	TALLOC_FREE(subreq);
+
+	CATIA_FETCH_FSP_POST_NEXT(&state->cc, state->fsp);
+
+	tevent_req_done(req);
+}
+
+static ssize_t catia_pwrite_recv(struct tevent_req *req,
+				struct vfs_aio_state *vfs_aio_state)
+{
+	struct catia_pwrite_state *state = tevent_req_data(
+		req, struct catia_pwrite_state);
+
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
+		return -1;
+	}
+
+	*vfs_aio_state = state->vfs_aio_state;
+	return state->ret;
+}
+
+static off_t catia_lseek(vfs_handle_struct *handle,
+			 files_struct *fsp,
+			 off_t offset,
+			 int whence)
+{
+	struct catia_cache *cc = NULL;
+	ssize_t result;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return -1;
+	}
+
+	result = SMB_VFS_NEXT_LSEEK(handle, fsp, offset, whence);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return result;
+}
+
+static int catia_fsync(vfs_handle_struct *handle, files_struct *fsp)
+{
+	struct catia_cache *cc = NULL;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return -1;
+	}
+
+	ret = SMB_VFS_NEXT_FSYNC(handle, fsp);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return ret;
+}
+
+struct catia_fsync_state {
+	int ret;
+	struct vfs_aio_state vfs_aio_state;
+	struct files_struct *fsp;
+	struct catia_cache *cc;
+};
+
+static void catia_fsync_done(struct tevent_req *subreq);
+
+static struct tevent_req *catia_fsync_send(struct vfs_handle_struct *handle,
+					   TALLOC_CTX *mem_ctx,
+					   struct tevent_context *ev,
+					   struct files_struct *fsp)
+{
+	struct tevent_req *req = NULL, *subreq = NULL;
+	struct catia_fsync_state *state = NULL;
+	int ret;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct catia_fsync_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	state->fsp = fsp;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(state, handle, fsp, &state->cc);
+	if (ret != 0) {
+		tevent_req_error(req, errno);
+		return tevent_req_post(req, ev);
+	}
+
+	subreq = SMB_VFS_NEXT_FSYNC_SEND(state, ev, handle, fsp);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, catia_fsync_done, req);
+
+	return req;
+}
+
+static void catia_fsync_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct catia_fsync_state *state = tevent_req_data(
+		req, struct catia_fsync_state);
+
+	state->ret = SMB_VFS_FSYNC_RECV(subreq, &state->vfs_aio_state);
+	TALLOC_FREE(subreq);
+
+	CATIA_FETCH_FSP_POST_NEXT(&state->cc, state->fsp);
+
+	tevent_req_done(req);
+}
+
+static int catia_fsync_recv(struct tevent_req *req,
+			    struct vfs_aio_state *vfs_aio_state)
+{
+	struct catia_fsync_state *state = tevent_req_data(
+		req, struct catia_fsync_state);
+
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
+		return -1;
+	}
+
+	*vfs_aio_state = state->vfs_aio_state;
+	return state->ret;
+}
+
+static bool catia_lock(vfs_handle_struct *handle,
+		       files_struct *fsp,
+		       int op,
+		       off_t offset,
+		       off_t count,
+		       int type)
+{
+	struct catia_cache *cc = NULL;
+	bool ok;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return -1;
+	}
+
+	ok = SMB_VFS_NEXT_LOCK(handle, fsp, op, offset, count, type);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return ok;
+}
+
+static int catia_kernel_flock(struct vfs_handle_struct *handle,
+			      struct files_struct *fsp,
+			      uint32_t share_mode,
+			      uint32_t access_mask)
+{
+	struct catia_cache *cc = NULL;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return -1;
+	}
+
+	ret = SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, share_mode, access_mask);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return ret;
+}
+
+static int catia_linux_setlease(vfs_handle_struct *handle,
+				files_struct *fsp,
+				int leasetype)
+{
+	struct catia_cache *cc = NULL;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return -1;
+	}
+
+	ret = SMB_VFS_NEXT_LINUX_SETLEASE(handle, fsp, leasetype);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return ret;
+}
+
+static bool catia_getlock(vfs_handle_struct *handle,
+			  files_struct *fsp,
+			  off_t *poffset,
+			  off_t *pcount,
+			  int *ptype,
+			  pid_t *ppid)
+{
+	struct catia_cache *cc = NULL;
+	int ret;
+	bool ok;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return -1;
+	}
+
+	ok = SMB_VFS_NEXT_GETLOCK(handle, fsp, poffset, pcount, ptype, ppid);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return ok;
+}
+
+static bool catia_strict_lock(struct vfs_handle_struct *handle,
+			      struct files_struct *fsp,
+			      struct lock_struct *plock)
+{
+	struct catia_cache *cc = NULL;
+	int ret;
+	bool ok;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return -1;
+	}
+
+	ok = SMB_VFS_NEXT_STRICT_LOCK(handle, fsp, plock);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return ok;
+}
+
+static void catia_strict_unlock(struct vfs_handle_struct *handle,
+				struct files_struct *fsp,
+				struct lock_struct *plock)
+{
+	struct catia_cache *cc = NULL;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		smb_panic("CATIA_FETCH_FSP_PRE_NEXT failed\n");
+	}
+
+	SMB_VFS_NEXT_STRICT_UNLOCK(handle, fsp, plock);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+}
+
+static NTSTATUS catia_fsctl(struct vfs_handle_struct *handle,
+			    struct files_struct *fsp,
+			    TALLOC_CTX *ctx,
+			    uint32_t function,
+			    uint16_t req_flags,
+			    const uint8_t *_in_data,
+			    uint32_t in_len,
+			    uint8_t **_out_data,
+			    uint32_t max_out_len,
+			    uint32_t *out_len)
+{
+	NTSTATUS result;
+	struct catia_cache *cc = NULL;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return map_nt_error_from_unix(errno);
+	}
+
+	result = SMB_VFS_NEXT_FSCTL(handle,
+				fsp,
+				ctx,
+				function,
+				req_flags,
+				_in_data,
+				in_len,
+				_out_data,
+				max_out_len,
+				out_len);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return result;
+}
+
+static NTSTATUS catia_get_compression(vfs_handle_struct *handle,
+				      TALLOC_CTX *mem_ctx,
+				      struct files_struct *fsp,
+				      struct smb_filename *smb_fname,
+				      uint16_t *_compression_fmt)
+{
+	NTSTATUS result;
+	struct catia_cache *cc = NULL;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return map_nt_error_from_unix(errno);
+	}
+
+	result = SMB_VFS_NEXT_GET_COMPRESSION(handle, mem_ctx, fsp, smb_fname,
+					      _compression_fmt);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return result;
+}
+
+static NTSTATUS catia_set_compression(vfs_handle_struct *handle,
+				      TALLOC_CTX *mem_ctx,
+				      struct files_struct *fsp,
+				      uint16_t compression_fmt)
+{
+	NTSTATUS result;
+	struct catia_cache *cc = NULL;
+	int ret;
+
+	ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
+	if (ret != 0) {
+		return map_nt_error_from_unix(errno);
+	}
+
+	result = SMB_VFS_NEXT_SET_COMPRESSION(handle, mem_ctx, fsp,
+					      compression_fmt);
+
+	CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
+
+	return result;
+}
+
+static NTSTATUS catia_readdir_attr(struct vfs_handle_struct *handle,
+				   const struct smb_filename *smb_fname_in,
+				   TALLOC_CTX *mem_ctx,
+				   struct readdir_attr_data **pattr_data)
+{
+	struct smb_filename *smb_fname;
+	char *fname = NULL;
+	NTSTATUS status;
+
+	status = catia_string_replace_allocate(handle->conn,
+					       smb_fname_in->base_name,
+					       &fname,
+					       vfs_translate_to_unix);
+	if (!NT_STATUS_IS_OK(status)) {
+		errno = map_errno_from_nt_status(status);
+		return status;
+	}
+
+	smb_fname = synthetic_smb_fname(talloc_tos(), fname, NULL,
+					&smb_fname_in->st, 0);
+
+	status = SMB_VFS_NEXT_READDIR_ATTR(handle, smb_fname, mem_ctx, pattr_data);
+
+	TALLOC_FREE(smb_fname);
+	return status;
+}
+
+static NTSTATUS catia_get_dos_attributes(struct vfs_handle_struct *handle,
+					 struct smb_filename *smb_fname,
+					 uint32_t *dosmode)
+{
+	char *mapped_name = NULL;
+	const char *path = smb_fname->base_name;
+	struct smb_filename *mapped_smb_fname = NULL;
+	NTSTATUS status;
+
+	status = catia_string_replace_allocate(handle->conn,
+				path, &mapped_name, vfs_translate_to_unix);
+	if (!NT_STATUS_IS_OK(status)) {
+		errno = map_errno_from_nt_status(status);
+		return status;
+	}
+	mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
+					mapped_name,
+					NULL,
+					NULL,
+					smb_fname->flags);
+	if (mapped_smb_fname == NULL) {
+		TALLOC_FREE(mapped_name);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	status = SMB_VFS_NEXT_GET_DOS_ATTRIBUTES(handle,
+						 mapped_smb_fname,
+						 dosmode);
+	TALLOC_FREE(mapped_name);
+	TALLOC_FREE(mapped_smb_fname);
+
+	return status;
+}
+
+static NTSTATUS catia_set_dos_attributes(struct vfs_handle_struct *handle,
+					 const struct smb_filename *smb_fname,
+					 uint32_t dosmode)
+{
+	char *mapped_name = NULL;
+	const char *path = smb_fname->base_name;
+	struct smb_filename *mapped_smb_fname = NULL;
+	NTSTATUS status;
+
+	status = catia_string_replace_allocate(handle->conn,
+				path, &mapped_name, vfs_translate_to_unix);
+	if (!NT_STATUS_IS_OK(status)) {
+		errno = map_errno_from_nt_status(status);
+		return status;
+	}
+	mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
+					mapped_name,
+					NULL,
+					NULL,
+					smb_fname->flags);
+	if (mapped_smb_fname == NULL) {
+		TALLOC_FREE(mapped_name);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	status = SMB_VFS_NEXT_SET_DOS_ATTRIBUTES(handle,
+						 mapped_smb_fname,
+						 dosmode);
+	TALLOC_FREE(mapped_name);
+	TALLOC_FREE(mapped_smb_fname);
+
+	return status;
+}
+
 static struct vfs_fn_pointers vfs_catia_fns = {
+	/* Directory operations */
 	.mkdir_fn = catia_mkdir,
 	.rmdir_fn = catia_rmdir,
 	.opendir_fn = catia_opendir,
+	.readdir_attr_fn = catia_readdir_attr,
+
+	/* File operations */
 	.open_fn = catia_open,
+	.pread_fn = catia_pread,
+	.pread_send_fn = catia_pread_send,
+	.pread_recv_fn = catia_pread_recv,
+	.pwrite_fn = catia_pwrite,
+	.pwrite_send_fn = catia_pwrite_send,
+	.pwrite_recv_fn = catia_pwrite_recv,
+	.lseek_fn = catia_lseek,
 	.rename_fn = catia_rename,
+	.fsync_fn = catia_fsync,
+	.fsync_send_fn = catia_fsync_send,
+	.fsync_recv_fn = catia_fsync_recv,
 	.stat_fn = catia_stat,
+	.fstat_fn = catia_fstat,
 	.lstat_fn = catia_lstat,
 	.unlink_fn = catia_unlink,
+	.chmod_fn = catia_chmod,
+	.fchmod_fn = catia_fchmod,
 	.chown_fn = catia_chown,
+	.fchown_fn = catia_fchown,
 	.lchown_fn = catia_lchown,
-	.chmod_fn = catia_chmod,
 	.chdir_fn = catia_chdir,
 	.ntimes_fn = catia_ntimes,
+	.ftruncate_fn = catia_ftruncate,
+	.fallocate_fn = catia_fallocate,
+	.lock_fn = catia_lock,
+	.kernel_flock_fn = catia_kernel_flock,
+	.linux_setlease_fn = catia_linux_setlease,
+	.getlock_fn = catia_getlock,
 	.realpath_fn = catia_realpath,
 	.chflags_fn = catia_chflags,
 	.streaminfo_fn = catia_streaminfo,
+	.strict_lock_fn = catia_strict_lock,
+	.strict_unlock_fn = catia_strict_unlock,
 	.translate_name_fn = catia_translate_name,
+	.fsctl_fn = catia_fsctl,
+	.get_dos_attributes_fn = catia_get_dos_attributes,
+	.set_dos_attributes_fn = catia_set_dos_attributes,
+	.fset_dos_attributes_fn = catia_fset_dos_attributes,
+	.fget_dos_attributes_fn = catia_fget_dos_attributes,
+	.get_compression_fn = catia_get_compression,
+	.set_compression_fn = catia_set_compression,
+
+	/* NT ACL operations. */
 	.get_nt_acl_fn = catia_get_nt_acl,
+	.fget_nt_acl_fn = catia_fget_nt_acl,
+	.fset_nt_acl_fn = catia_fset_nt_acl,
+
+	/* POSIX ACL operations. */
 	.chmod_acl_fn = catia_chmod_acl,
+	.fchmod_acl_fn = catia_fchmod_acl,
+
 	.sys_acl_get_file_fn = catia_sys_acl_get_file,
+	.sys_acl_get_fd_fn = catia_sys_acl_get_fd,
+	.sys_acl_blob_get_fd_fn = catia_sys_acl_blob_get_fd,
 	.sys_acl_set_file_fn = catia_sys_acl_set_file,
+	.sys_acl_set_fd_fn = catia_sys_acl_set_fd,
 	.sys_acl_delete_def_file_fn = catia_sys_acl_delete_def_file,
+
+	/* EA operations. */
 	.getxattr_fn = catia_getxattr,
 	.listxattr_fn = catia_listxattr,
 	.removexattr_fn = catia_removexattr,
 	.setxattr_fn = catia_setxattr,
+	.fgetxattr_fn = catia_fgetxattr,
+	.flistxattr_fn = catia_flistxattr,
+	.fremovexattr_fn = catia_fremovexattr,
+	.fsetxattr_fn = catia_fsetxattr,
 };
 
 static_decl_vfs;
diff -Nru samba-4.5.5+dfsg/source3/modules/vfs_dirsort.c samba-4.5.6+dfsg/source3/modules/vfs_dirsort.c
--- samba-4.5.5+dfsg/source3/modules/vfs_dirsort.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/modules/vfs_dirsort.c	2017-03-09 10:21:43.000000000 +0100
@@ -65,8 +65,10 @@
 static bool open_and_sort_dir(vfs_handle_struct *handle,
 				struct dirsort_privates *data)
 {
-	unsigned int i = 0;
-	unsigned int total_count = 0;
+	uint32_t total_count = 0;
+	/* This should be enough for most use cases */
+	uint32_t dirent_allocated = 64;
+	struct dirent *dp;
 
 	data->number_of_entries = 0;
 
@@ -74,38 +76,51 @@
 		return false;
 	}
 
-	while (SMB_VFS_NEXT_READDIR(handle, data->source_directory, NULL)
-	       != NULL) {
-		total_count++;
-	}
-
-	if (total_count == 0) {
+	dp = SMB_VFS_NEXT_READDIR(handle, data->source_directory, NULL);
+	if (dp == NULL) {
 		return false;
 	}
 
-	/* Open the underlying directory and count the number of entries
-	   Skip back to the beginning as we'll read it again */
-	SMB_VFS_NEXT_REWINDDIR(handle, data->source_directory);
-
 	/* Set up an array and read the directory entries into it */
 	TALLOC_FREE(data->directory_list); /* destroy previous cache if needed */
 	data->directory_list = talloc_zero_array(data,
-					struct dirent,
-					total_count);
-	if (!data->directory_list) {
+						 struct dirent,
+						 dirent_allocated);
+	if (data->directory_list == NULL) {
 		return false;
 	}
-	for (i = 0; i < total_count; i++) {
-		struct dirent *dp = SMB_VFS_NEXT_READDIR(handle,
-						data->source_directory,
-						NULL);
-		if (dp == NULL) {
-			break;
+
+	do {
+		if (total_count >= dirent_allocated) {
+			struct dirent *dlist;
+
+			/*
+			 * Be memory friendly.
+			 *
+			 * We should not double the amount of memory. With a lot
+			 * of files we reach easily 50MB, and doubling will
+			 * get much bigger just for a few files more.
+			 *
+			 * For 200k files this means 50 memory reallocations.
+			 */
+			dirent_allocated += 4096;
+
+			dlist = talloc_realloc(data,
+					       data->directory_list,
+					       struct dirent,
+					       dirent_allocated);
+			if (dlist == NULL) {
+				break;
+			}
+			data->directory_list = dlist;
 		}
-		data->directory_list[i] = *dp;
-	}
+		data->directory_list[total_count] = *dp;
+
+		total_count++;
+		dp = SMB_VFS_NEXT_READDIR(handle, data->source_directory, NULL);
+	} while (dp != NULL);
 
-	data->number_of_entries = i;
+	data->number_of_entries = total_count;
 
 	/* Sort the directory entries by name */
 	TYPESAFE_QSORT(data->directory_list, data->number_of_entries, compare_dirent);
@@ -138,6 +153,10 @@
 		return NULL;
 	}
 
+	if (ISDOT(data->smb_fname->base_name)) {
+		data->smb_fname->base_name = vfs_GetWd(data, handle->conn);
+	}
+
 	/* Open the underlying directory and count the number of entries */
 	data->source_directory = SMB_VFS_NEXT_OPENDIR(handle, smb_fname, mask,
 						      attr);
diff -Nru samba-4.5.5+dfsg/source3/modules/vfs_fruit.c samba-4.5.6+dfsg/source3/modules/vfs_fruit.c
--- samba-4.5.5+dfsg/source3/modules/vfs_fruit.c	2017-01-30 10:56:26.000000000 +0100
+++ samba-4.5.6+dfsg/source3/modules/vfs_fruit.c	2017-03-09 10:21:43.000000000 +0100
@@ -94,6 +94,11 @@
 
 static int vfs_fruit_debug_level = DBGC_VFS;
 
+static struct global_fruit_config {
+	bool nego_aapl;	/* client negotiated AAPL */
+
+} global_fruit_config;
+
 #undef DBGC_CLASS
 #define DBGC_CLASS vfs_fruit_debug_level
 
@@ -126,7 +131,6 @@
 	enum fruit_locking locking;
 	enum fruit_encoding encoding;
 	bool use_aapl;		/* config from smb.conf */
-	bool nego_aapl;		/* client negotiated AAPL */
 	bool use_copyfile;
 	bool readdir_attr_enabled;
 	bool unix_info_enabled;
@@ -343,7 +347,6 @@
 #define ad_getentryoff(ad,eid)     ((ad)->ad_eid[(eid)].ade_off)
 #define ad_setentrylen(ad,eid,len) ((ad)->ad_eid[(eid)].ade_len = (len))
 #define ad_setentryoff(ad,eid,off) ((ad)->ad_eid[(eid)].ade_off = (off))
-#define ad_entry(ad,eid)           ((ad)->ad_data + ad_getentryoff((ad),(eid)))
 
 struct ad_entry {
 	size_t ade_off;
@@ -352,7 +355,8 @@
 
 struct adouble {
 	vfs_handle_struct        *ad_handle;
-	files_struct             *ad_fsp;
+	int                       ad_fd;
+	bool                      ad_opened;
 	adouble_type_t            ad_type;
 	uint32_t                  ad_magic;
 	uint32_t                  ad_version;
@@ -405,15 +409,41 @@
 	AD_DEV, AD_INO, AD_SYN, AD_ID
 };
 
+struct fio {
+	/* tcon config handle */
+	struct fruit_config_data *config;
+
+	/* Denote stream type, meta or rsrc */
+	adouble_type_t type;
+};
+
 /*
  * Forward declarations
  */
 static struct adouble *ad_init(TALLOC_CTX *ctx, vfs_handle_struct *handle,
-			       adouble_type_t type, files_struct *fsp);
-static int ad_write(struct adouble *ad, const char *path);
+			       adouble_type_t type);
+static int ad_set(struct adouble *ad, const char *path);
+static int ad_fset(struct adouble *ad, files_struct *fsp);
 static int adouble_path(TALLOC_CTX *ctx, const char *path_in, char **path_out);
 
 /**
+ * Return a pointer to an AppleDouble entry
+ *
+ * Returns NULL if the entry is not present
+ **/
+static char *ad_get_entry(const struct adouble *ad, int eid)
+{
+	off_t off = ad_getentryoff(ad, eid);
+	size_t len = ad_getentrylen(ad, eid);
+
+	if (off == 0 || len == 0) {
+		return NULL;
+	}
+
+	return ad->ad_data + off;
+}
+
+/**
  * Get a date
  **/
 static int ad_getdate(const struct adouble *ad,
@@ -421,18 +451,19 @@
 		      uint32_t *date)
 {
 	bool xlate = (dateoff & AD_DATE_UNIX);
+	char *p = NULL;
 
 	dateoff &= AD_DATE_MASK;
-	if (!ad_getentryoff(ad, ADEID_FILEDATESI)) {
+	p = ad_get_entry(ad, ADEID_FILEDATESI);
+	if (p == NULL) {
 		return -1;
 	}
 
 	if (dateoff > AD_DATE_ACCESS) {
 	    return -1;
 	}
-	memcpy(date,
-	       ad_entry(ad, ADEID_FILEDATESI) + dateoff,
-	       sizeof(uint32_t));
+
+	memcpy(date, p + dateoff, sizeof(uint32_t));
 
 	if (xlate) {
 		*date = AD_DATE_TO_UNIX(*date);
@@ -446,9 +477,11 @@
 static int ad_setdate(struct adouble *ad, unsigned int dateoff, uint32_t date)
 {
 	bool xlate = (dateoff & AD_DATE_UNIX);
+	char *p = NULL;
 
-	if (!ad_getentryoff(ad, ADEID_FILEDATESI)) {
-		return 0;
+	p = ad_get_entry(ad, ADEID_FILEDATESI);
+	if (p == NULL) {
+		return -1;
 	}
 
 	dateoff &= AD_DATE_MASK;
@@ -460,7 +493,7 @@
 		return -1;
 	}
 
-	memcpy(ad_entry(ad, ADEID_FILEDATESI) + dateoff, &date, sizeof(date));
+	memcpy(p + dateoff, &date, sizeof(date));
 
 	return 0;
 }
@@ -752,7 +785,7 @@
 /**
  * Read and parse Netatalk AppleDouble metadata xattr
  **/
-static ssize_t ad_header_read_meta(struct adouble *ad, const char *path)
+static ssize_t ad_read_meta(struct adouble *ad, const char *path)
 {
 	int      rc = 0;
 	ssize_t  ealen;
@@ -824,184 +857,220 @@
 	return ealen;
 }
 
-/**
- * Read and parse resource fork, either ._ AppleDouble file or xattr
- **/
-static ssize_t ad_header_read_rsrc(struct adouble *ad, const char *path)
+static int ad_open_meta(const char *path, int flags, mode_t mode)
+{
+	return open(path, flags, mode);
+}
+
+static int ad_open_rsrc_xattr(const char *path, int flags, mode_t mode)
+{
+#ifdef HAVE_ATTROPEN
+	/* FIXME: direct Solaris xattr syscall */
+	return attropen(path, AFPRESOURCE_EA_NETATALK, flags, mode);
+#else
+	errno = ENOSYS;
+	return -1;
+#endif
+}
+
+static int ad_open_rsrc_adouble(const char *path, int flags, mode_t mode)
+{
+	char *adp = NULL;
+	int ret;
+	int fd;
+
+	ret = adouble_path(talloc_tos(), path, &adp);
+	if (ret != 0) {
+		return -1;
+	}
+
+	fd = open(adp, flags, mode);
+	TALLOC_FREE(adp);
+
+	return fd;
+}
+
+static int ad_open_rsrc(vfs_handle_struct *handle,
+			const char *path,
+			int flags,
+			mode_t mode)
 {
 	struct fruit_config_data *config = NULL;
-	int fd = -1;
-	int rc = 0;
-	ssize_t len;
-	char *adpath = NULL;
-	bool opened = false;
-	int mode;
-	struct adouble *meta_ad = NULL;
-	SMB_STRUCT_STAT sbuf;
-	bool ok;
-	int saved_errno = 0;
+	int fd;
 
-	SMB_VFS_HANDLE_GET_DATA(ad->ad_handle, config,
+	SMB_VFS_HANDLE_GET_DATA(handle, config,
 				struct fruit_config_data, return -1);
 
-	/* Try rw first so we can use the fd in ad_convert() */
-	mode = O_RDWR;
-
-	if (ad->ad_fsp && ad->ad_fsp->fh && (ad->ad_fsp->fh->fd != -1)) {
-		fd = ad->ad_fsp->fh->fd;
+	if (config->rsrc == FRUIT_RSRC_XATTR) {
+		fd = ad_open_rsrc_xattr(path, flags, mode);
 	} else {
-		if (config->rsrc == FRUIT_RSRC_XATTR) {
-			adpath = talloc_strdup(talloc_tos(), path);
-		} else {
-			rc = adouble_path(talloc_tos(), path, &adpath);
-			if (rc != 0) {
-				goto exit;
-			}
-		}
+		fd = ad_open_rsrc_adouble(path, flags, mode);
+	}
 
-	retry:
-		if (config->rsrc == FRUIT_RSRC_XATTR) {
-#ifndef HAVE_ATTROPEN
-			errno = ENOSYS;
-			rc = -1;
-			goto exit;
-#else
-			/* FIXME: direct Solaris xattr syscall */
-			fd = attropen(adpath, AFPRESOURCE_EA_NETATALK,
-				      mode, 0);
-#endif
-		} else {
-			/* FIXME: direct open(), don't have an fsp */
-			fd = open(adpath, mode);
-		}
+	return fd;
+}
 
-		if (fd == -1) {
-			switch (errno) {
-			case EROFS:
-			case EACCES:
-				if (mode == O_RDWR) {
-					mode = O_RDONLY;
-					goto retry;
-				}
-				/* fall through ... */
-			default:
-				DEBUG(2, ("open AppleDouble: %s, %s\n",
-					  adpath, strerror(errno)));
-				rc = -1;
-				goto exit;
-			}
-		}
-		opened = true;
+static int ad_open(vfs_handle_struct *handle,
+		   struct adouble *ad,
+		   const char *path,
+		   adouble_type_t t,
+		   int flags,
+		   mode_t mode)
+{
+	int fd;
+
+	DBG_DEBUG("Path [%s] type [%s]\n",
+		  path, t == ADOUBLE_META ? "meta" : "rsrc");
+
+	if (t == ADOUBLE_META) {
+		fd = ad_open_meta(path, flags, mode);
+	} else {
+		fd = ad_open_rsrc(handle, path, flags, mode);
 	}
 
-	if (config->rsrc == FRUIT_RSRC_XATTR) {
-		/* FIXME: direct sys_fstat(), don't have an fsp */
-		rc = sys_fstat(
-			fd, &sbuf,
+	if (fd != -1) {
+		ad->ad_opened = true;
+		ad->ad_fd = fd;
+	}
+
+	DBG_DEBUG("Path [%s] type [%s] fd [%d]\n",
+		  path, t == ADOUBLE_META ? "meta" : "rsrc", fd);
+
+	return fd;
+}
+
+static ssize_t ad_read_rsrc_xattr(struct adouble *ad,
+				  const char *path)
+{
+	int ret;
+	SMB_STRUCT_STAT st;
+
+	/* FIXME: direct sys_fstat(), don't have an fsp */
+	ret = sys_fstat(ad->ad_fd, &st,
 			lp_fake_directory_create_times(
 				SNUM(ad->ad_handle->conn)));
-		if (rc != 0) {
-			goto exit;
-		}
-		len = sbuf.st_ex_size;
-		ad_setentrylen(ad, ADEID_RFORK, len);
-	} else {
-		/* FIXME: direct sys_pread(), don't have an fsp */
-		len = sys_pread(fd, ad->ad_data, AD_DATASZ_DOT_UND, 0);
-		if (len != AD_DATASZ_DOT_UND) {
-			DEBUG(2, ("%s: bad size: %zd\n",
-				  strerror(errno), len));
-			rc = -1;
-			goto exit;
-		}
+	if (ret != 0) {
+		return -1;
+	}
 
-		/* FIXME: direct sys_fstat(), we don't have an fsp */
-		rc = sys_fstat(fd, &sbuf,
-			       lp_fake_directory_create_times(
-				       SNUM(ad->ad_handle->conn)));
-		if (rc != 0) {
-			goto exit;
-		}
+	ad_setentrylen(ad, ADEID_RFORK, st.st_ex_size);
+	return st.st_ex_size;
+}
 
-		/* Now parse entries */
-		ok = ad_unpack(ad, ADEID_NUM_DOT_UND, sbuf.st_ex_size);
-		if (!ok) {
-			DEBUG(1, ("invalid AppleDouble ressource %s\n", path));
-			errno = EINVAL;
-			rc = -1;
-			goto exit;
-		}
+static ssize_t ad_read_rsrc_adouble(struct adouble *ad,
+				    const char *path)
+{
+	struct adouble *meta_ad = NULL;
+	SMB_STRUCT_STAT sbuf;
+	char *p_ad = NULL;
+	char *p_meta_ad = NULL;
+	ssize_t len;
+	int ret;
+	bool ok;
 
-		if ((ad_getentryoff(ad, ADEID_FINDERI)
-		     != ADEDOFF_FINDERI_DOT_UND)
-		    || (ad_getentrylen(ad, ADEID_FINDERI)
-			< ADEDLEN_FINDERI)
-		    || (ad_getentryoff(ad, ADEID_RFORK)
-			< ADEDOFF_RFORK_DOT_UND)) {
-			DEBUG(2, ("invalid AppleDouble ressource %s\n", path));
-			errno = EINVAL;
-			rc = -1;
-			goto exit;
-		}
+	len = sys_pread(ad->ad_fd, ad->ad_data, AD_DATASZ_DOT_UND, 0);
+	if (len != AD_DATASZ_DOT_UND) {
+		DBG_NOTICE("%s %s: bad size: %zd\n",
+			   path, strerror(errno), len);
+		return -1;
+	}
 
-		if ((mode == O_RDWR)
-		    && (ad_getentrylen(ad, ADEID_FINDERI) > ADEDLEN_FINDERI)) {
-			rc = ad_convert(ad, fd);
-			if (rc != 0) {
-				rc = -1;
-				goto exit;
-			}
-			/*
-			 * Can't use ad_write() because we might not have a fsp
-			 */
-			ok = ad_pack(ad);
-			if (!ok) {
-				rc = -1;
-				goto exit;
-			}
-			/* FIXME: direct sys_pwrite(), don't have an fsp */
-			len = sys_pwrite(fd, ad->ad_data,
-					 AD_DATASZ_DOT_UND, 0);
-			if (len != AD_DATASZ_DOT_UND) {
-				DEBUG(2, ("%s: bad size: %zd\n", adpath, len));
-				rc = -1;
-				goto exit;
-			}
+	ret = sys_fstat(ad->ad_fd, &sbuf, lp_fake_directory_create_times(
+				SNUM(ad->ad_handle->conn)));
+	if (ret != 0) {
+		return -1;
+	}
 
-			meta_ad = ad_init(talloc_tos(), ad->ad_handle,
-					  ADOUBLE_META, NULL);
-			if (meta_ad == NULL) {
-				rc = -1;
-				goto exit;
-			}
+	/* Now parse entries */
+	ok = ad_unpack(ad, ADEID_NUM_DOT_UND, sbuf.st_ex_size);
+	if (!ok) {
+		DBG_ERR("invalid AppleDouble resource %s\n", path);
+		errno = EINVAL;
+		return -1;
+	}
 
-			memcpy(ad_entry(meta_ad, ADEID_FINDERI),
-			       ad_entry(ad, ADEID_FINDERI),
-			       ADEDLEN_FINDERI);
+	if ((ad_getentryoff(ad, ADEID_FINDERI) != ADEDOFF_FINDERI_DOT_UND)
+	    || (ad_getentrylen(ad, ADEID_FINDERI) < ADEDLEN_FINDERI)
+	    || (ad_getentryoff(ad, ADEID_RFORK)	< ADEDOFF_RFORK_DOT_UND)) {
+		DBG_ERR("invalid AppleDouble resource %s\n", path);
+		errno = EINVAL;
+		return -1;
+	}
 
-			rc = ad_write(meta_ad, path);
-			if (rc != 0) {
-				rc = -1;
-				goto exit;
-			}
-		}
+	if (ad_getentrylen(ad, ADEID_FINDERI) == ADEDLEN_FINDERI) {
+		return len;
 	}
 
-	DEBUG(10, ("opened AppleDouble: %s\n", path));
+	/*
+	 * Try to fixup AppleDouble files created by OS X with xattrs
+	 * appended to the ADEID_FINDERI entry. We simply remove the
+	 * xattrs blob, this means any fancy xattr that was stored
+	 * there is lost.
+	 */
 
-exit:
-	if (rc != 0) {
-		saved_errno = errno;
-		len = -1;
+	ret = ad_convert(ad, ad->ad_fd);
+	if (ret != 0) {
+		DBG_WARNING("Failed to convert [%s]\n", path);
+		return len;
 	}
-	if (opened && fd != -1) {
-		close(fd);
+
+	ok = ad_pack(ad);
+	if (!ok) {
+		DBG_WARNING("ad_pack [%s] failed\n", path);
+		return -1;
 	}
-	TALLOC_FREE(adpath);
+
+	len = sys_pwrite(ad->ad_fd, ad->ad_data, AD_DATASZ_DOT_UND, 0);
+	if (len != AD_DATASZ_DOT_UND) {
+		DBG_ERR("%s: bad size: %zd\n", path, len);
+		return -1;
+	}
+
+	meta_ad = ad_init(talloc_tos(), ad->ad_handle, ADOUBLE_META);
+	if (meta_ad == NULL) {
+		return -1;
+	}
+
+	p_ad = ad_get_entry(ad, ADEID_FINDERI);
+	if (p_ad == NULL) {
+		TALLOC_FREE(meta_ad);
+		return -1;
+	}
+	p_meta_ad = ad_get_entry(meta_ad, ADEID_FINDERI);
+	if (p_meta_ad == NULL) {
+		TALLOC_FREE(meta_ad);
+		return -1;
+	}
+
+	memcpy(p_meta_ad, p_ad, ADEDLEN_FINDERI);
+
+	ret = ad_set(meta_ad, path);
 	TALLOC_FREE(meta_ad);
-	if (rc != 0) {
-		errno = saved_errno;
+	if (ret != 0) {
+		return -1;
+	}
+
+	return len;
+}
+
+/**
+ * Read and parse resource fork, either ._ AppleDouble file or xattr
+ **/
+static ssize_t ad_read_rsrc(struct adouble *ad,
+			    const char *path)
+{
+	struct fruit_config_data *config = NULL;
+	ssize_t len;
+
+	SMB_VFS_HANDLE_GET_DATA(ad->ad_handle, config,
+				struct fruit_config_data, return -1);
+
+	if (config->rsrc == FRUIT_RSRC_XATTR) {
+		len = ad_read_rsrc_xattr(ad, path);
+	} else {
+		len = ad_read_rsrc_adouble(ad, path);
 	}
+
 	return len;
 }
 
@@ -1012,14 +1081,23 @@
 {
 	switch (ad->ad_type) {
 	case ADOUBLE_META:
-		return ad_header_read_meta(ad, path);
+		return ad_read_meta(ad, path);
 	case ADOUBLE_RSRC:
-		return ad_header_read_rsrc(ad, path);
+		return ad_read_rsrc(ad, path);
 	default:
 		return -1;
 	}
 }
 
+static int adouble_destructor(struct adouble *ad)
+{
+	if ((ad->ad_fd != -1) && ad->ad_opened) {
+		close(ad->ad_fd);
+		ad->ad_fd = -1;
+	}
+	return 0;
+}
+
 /**
  * Allocate a struct adouble without initialiing it
  *
@@ -1029,14 +1107,11 @@
  * @param[in] ctx        talloc context
  * @param[in] handle     vfs handle
  * @param[in] type       type of AppleDouble, ADOUBLE_META or ADOUBLE_RSRC
-
- * @param[in] fsp        if not NULL (for stream IO), the adouble handle is
- *                       added as an fsp extension
  *
  * @return               adouble handle
  **/
 static struct adouble *ad_alloc(TALLOC_CTX *ctx, vfs_handle_struct *handle,
-				adouble_type_t type, files_struct *fsp)
+				adouble_type_t type)
 {
 	int rc = 0;
 	size_t adsize = 0;
@@ -1059,39 +1134,27 @@
 		return NULL;
 	}
 
-	if (!fsp) {
-		ad = talloc_zero(ctx, struct adouble);
-		if (ad == NULL) {
-			rc = -1;
-			goto exit;
-		}
-		if (adsize) {
-			ad->ad_data = talloc_zero_array(ad, char, adsize);
-		}
-	} else {
-		ad = (struct adouble *)VFS_ADD_FSP_EXTENSION(handle, fsp,
-							     struct adouble,
-							     NULL);
-		if (ad == NULL) {
+	ad = talloc_zero(ctx, struct adouble);
+	if (ad == NULL) {
+		rc = -1;
+		goto exit;
+	}
+
+	if (adsize) {
+		ad->ad_data = talloc_zero_array(ad, char, adsize);
+		if (ad->ad_data == NULL) {
 			rc = -1;
 			goto exit;
 		}
-		if (adsize) {
-			ad->ad_data = talloc_zero_array(
-				VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
-				char, adsize);
-		}
-		ad->ad_fsp = fsp;
 	}
 
-	if (adsize && ad->ad_data == NULL) {
-		rc = -1;
-		goto exit;
-	}
 	ad->ad_handle = handle;
 	ad->ad_type = type;
 	ad->ad_magic = AD_MAGIC;
 	ad->ad_version = AD_VERSION;
+	ad->ad_fd = -1;
+
+	talloc_set_destructor(ad, adouble_destructor);
 
 exit:
 	if (rc != 0) {
@@ -1106,12 +1169,11 @@
  * @param[in] ctx        talloc context
  * @param[in] handle     vfs handle
  * @param[in] type       type of AppleDouble, ADOUBLE_META or ADOUBLE_RSRC
- * @param[in] fsp        file handle, may be NULL for a type of e_ad_meta
  *
  * @return               adouble handle, initialized
  **/
 static struct adouble *ad_init(TALLOC_CTX *ctx, vfs_handle_struct *handle,
-			       adouble_type_t type, files_struct *fsp)
+			       adouble_type_t type)
 {
 	int rc = 0;
 	const struct ad_entry_order  *eid;
@@ -1137,7 +1199,7 @@
 		return NULL;
 	}
 
-	ad = ad_alloc(ctx, handle, type, fsp);
+	ad = ad_alloc(ctx, handle, type);
 	if (ad == NULL) {
 		return NULL;
 	}
@@ -1176,16 +1238,42 @@
 	int rc = 0;
 	ssize_t len;
 	struct adouble *ad = NULL;
+	int fd;
+	int mode;
 
 	DEBUG(10, ("ad_get(%s) called for %s\n",
 		   type == ADOUBLE_META ? "meta" : "rsrc", path));
 
-	ad = ad_alloc(ctx, handle, type, NULL);
+	ad = ad_alloc(ctx, handle, type);
 	if (ad == NULL) {
 		rc = -1;
 		goto exit;
 	}
 
+	/*
+	 * Here's the deal: for ADOUBLE_META we can do without an fd
+	 * as we can issue path based xattr calls. For ADOUBLE_RSRC
+	 * however we need a full-fledged fd for file IO on the ._
+	 * file.
+	 */
+	if (type == ADOUBLE_RSRC) {
+		/* Try rw first so we can use the fd in ad_convert() */
+		mode = O_RDWR;
+
+		fd = ad_open(handle, ad, path, ADOUBLE_RSRC, mode, 0);
+		if (fd == -1 && ((errno == EROFS) || (errno == EACCES))) {
+			mode = O_RDONLY;
+			fd = ad_open(handle, ad, path, ADOUBLE_RSRC, mode, 0);
+		}
+
+		if (fd == -1) {
+			DBG_DEBUG("ad_open [%s] error [%s]\n",
+				  path, strerror(errno));
+			rc = -1;
+			goto exit;
+		}
+	}
+
 	len = ad_read(ad, path);
 	if (len == -1) {
 		DEBUG(10, ("error reading AppleDouble for %s\n", path));
@@ -1204,21 +1292,144 @@
 }
 
 /**
+ * Return AppleDouble data for a file
+ *
+ * @param[in] ctx      talloc context
+ * @param[in] handle   vfs handle
+ * @param[in] fsp      fsp to use for IO
+ * @param[in] type     type of AppleDouble, ADOUBLE_META or ADOUBLE_RSRC
+ *
+ * @return             talloced struct adouble or NULL on error
+ **/
+static struct adouble *ad_fget(TALLOC_CTX *ctx, vfs_handle_struct *handle,
+			       files_struct *fsp, adouble_type_t type)
+{
+	int rc = 0;
+	ssize_t len;
+	struct adouble *ad = NULL;
+	char *path = fsp->base_fsp->fsp_name->base_name;
+
+	DBG_DEBUG("ad_get(%s) path [%s]\n",
+		  type == ADOUBLE_META ? "meta" : "rsrc",
+		  fsp_str_dbg(fsp));
+
+	ad = ad_alloc(ctx, handle, type);
+	if (ad == NULL) {
+		rc = -1;
+		goto exit;
+	}
+
+	if ((fsp->fh != NULL) && (fsp->fh->fd != -1)) {
+		ad->ad_fd = fsp->fh->fd;
+	} else {
+		/*
+		 * Here's the deal: for ADOUBLE_META we can do without an fd
+		 * as we can issue path based xattr calls. For ADOUBLE_RSRC
+		 * however we need a full-fledged fd for file IO on the ._
+		 * file.
+		 */
+		int fd;
+		int mode;
+
+		if (type == ADOUBLE_RSRC) {
+			/* Try rw first so we can use the fd in ad_convert() */
+			mode = O_RDWR;
+
+			fd = ad_open(handle, ad, path, ADOUBLE_RSRC, mode, 0);
+			if (fd == -1 &&
+			    ((errno == EROFS) || (errno == EACCES)))
+			{
+				mode = O_RDONLY;
+				fd = ad_open(handle, ad, path, ADOUBLE_RSRC,
+					     mode, 0);
+			}
+
+			if (fd == -1) {
+				DBG_DEBUG("error opening AppleDouble for %s\n", path);
+				rc = -1;
+				goto exit;
+			}
+		}
+	}
+
+	len = ad_read(ad, path);
+	if (len == -1) {
+		DBG_DEBUG("error reading AppleDouble for %s\n", path);
+		rc = -1;
+		goto exit;
+	}
+
+exit:
+	DBG_DEBUG("ad_get(%s) path [%s] rc [%d]\n",
+		  type == ADOUBLE_META ? "meta" : "rsrc",
+		  fsp_str_dbg(fsp), rc);
+
+	if (rc != 0) {
+		TALLOC_FREE(ad);
+	}
+	return ad;
+}
+
+/**
  * Set AppleDouble metadata on a file or directory
  *
  * @param[in] ad      adouble handle
+ *
+ * @param[in] path    pathname to file or directory
+ *
+ * @return            status code, 0 means success
+ **/
+static int ad_set(struct adouble *ad, const char *path)
+{
+	bool ok;
+	int ret;
+
+	DBG_DEBUG("Path [%s]\n", path);
+
+	if (ad->ad_type != ADOUBLE_META) {
+		DBG_ERR("ad_set on [%s] used with ADOUBLE_RSRC\n", path);
+		return -1;
+	}
+
+	ok = ad_pack(ad);
+	if (!ok) {
+		return -1;
+	}
+
+	ret = SMB_VFS_SETXATTR(ad->ad_handle->conn,
+			       path,
+			       AFPINFO_EA_NETATALK,
+			       ad->ad_data,
+			       AD_DATASZ_XATTR, 0);
+
+	DBG_DEBUG("Path [%s] ret [%d]\n", path, ret);
+
+	return ret;
+}
 
- * @param[in] path    pathname to file or directory, may be NULL for a
- *                    resource fork
+/**
+ * Set AppleDouble metadata on a file or directory
+ *
+ * @param[in] ad      adouble handle
+ * @param[in] fsp     file handle
  *
  * @return            status code, 0 means success
  **/
-static int ad_write(struct adouble *ad, const char *path)
+static int ad_fset(struct adouble *ad, files_struct *fsp)
 {
-	int rc = 0;
+	int rc = -1;
 	ssize_t len;
 	bool ok;
 
+	DBG_DEBUG("Path [%s]\n", fsp_str_dbg(fsp));
+
+	if ((fsp == NULL)
+	    || (fsp->fh == NULL)
+	    || (fsp->fh->fd == -1))
+	{
+		smb_panic("bad fsp");
+	}
+
 	ok = ad_pack(ad);
 	if (!ok) {
 		return -1;
@@ -1226,31 +1437,32 @@
 
 	switch (ad->ad_type) {
 	case ADOUBLE_META:
-		rc = SMB_VFS_SETXATTR(ad->ad_handle->conn, path,
-				      AFPINFO_EA_NETATALK, ad->ad_data,
-				      AD_DATASZ_XATTR, 0);
+		rc = SMB_VFS_NEXT_FSETXATTR(ad->ad_handle,
+					    fsp,
+					    AFPINFO_EA_NETATALK,
+					    ad->ad_data,
+					    AD_DATASZ_XATTR, 0);
 		break;
+
 	case ADOUBLE_RSRC:
-		if ((ad->ad_fsp == NULL)
-		    || (ad->ad_fsp->fh == NULL)
-		    || (ad->ad_fsp->fh->fd == -1)) {
-			rc = -1;
-			goto exit;
-		}
-		/* FIXME: direct sys_pwrite(), don't have an fsp */
-		len = sys_pwrite(ad->ad_fsp->fh->fd, ad->ad_data,
-				 talloc_get_size(ad->ad_data), 0);
-		if (len != talloc_get_size(ad->ad_data)) {
-			DEBUG(1, ("short write on %s: %zd",
-				  fsp_str_dbg(ad->ad_fsp), len));
-			rc = -1;
-			goto exit;
+		len = SMB_VFS_NEXT_PWRITE(ad->ad_handle,
+					  fsp,
+					  ad->ad_data,
+					  talloc_get_size(ad->ad_data),
+					  0);
+		if (len != (ssize_t)talloc_get_size(ad->ad_data)) {
+			DBG_ERR("short write on %s: %zd", fsp_str_dbg(fsp), len);
+			return -1;
 		}
+		rc = 0;
 		break;
+
 	default:
 		return -1;
 	}
-exit:
+
+	DBG_DEBUG("Path [%s] rc [%d]\n", fsp_str_dbg(fsp), rc);
+
 	return rc;
 }
 
@@ -1345,9 +1557,12 @@
 	}
 	config->encoding = (enum fruit_encoding)enumval;
 
-	config->veto_appledouble = lp_parm_bool(
-		SNUM(handle->conn), FRUIT_PARAM_TYPE_NAME,
-		"veto_appledouble", true);
+	if (config->rsrc == FRUIT_RSRC_ADFILE) {
+		config->veto_appledouble = lp_parm_bool(SNUM(handle->conn),
+							FRUIT_PARAM_TYPE_NAME,
+							"veto_appledouble",
+							true);
+	}
 
 	config->use_aapl = lp_parm_bool(
 		-1, FRUIT_PARAM_TYPE_NAME, "aapl", true);
@@ -1491,19 +1706,6 @@
 	return result;
 }
 
-/**
- * Ensure ad_fsp is still valid
- **/
-static bool fruit_fsp_recheck(struct adouble *ad, files_struct *fsp)
-{
-	if (ad->ad_fsp == fsp) {
-		return true;
-	}
-	ad->ad_fsp = fsp;
-
-	return true;
-}
-
 static bool add_fruit_stream(TALLOC_CTX *mem_ctx, unsigned int *num_streams,
 			     struct stream_struct **streams,
 			     const char *name, off_t size,
@@ -1530,6 +1732,40 @@
 	return true;
 }
 
+static bool filter_empty_rsrc_stream(unsigned int *num_streams,
+				     struct stream_struct **streams)
+{
+	struct stream_struct *tmp = *streams;
+	unsigned int i;
+
+	if (*num_streams == 0) {
+		return true;
+	}
+
+	for (i = 0; i < *num_streams; i++) {
+		if (strequal_m(tmp[i].name, AFPRESOURCE_STREAM)) {
+			break;
+		}
+	}
+
+	if (i == *num_streams) {
+		return true;
+	}
+
+	if (tmp[i].size > 0) {
+		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 del_fruit_stream(TALLOC_CTX *mem_ctx, unsigned int *num_streams,
 			     struct stream_struct **streams,
 			     const char *name)
@@ -1561,16 +1797,29 @@
 	return true;
 }
 
-static bool empty_finderinfo(const struct adouble *ad)
+static bool ad_empty_finderinfo(const struct adouble *ad)
 {
-
+	int cmp;
 	char emptybuf[ADEDLEN_FINDERI] = {0};
-	if (memcmp(emptybuf,
-		   ad_entry(ad, ADEID_FINDERI),
-		   ADEDLEN_FINDERI) == 0) {
-		return true;
+	char *fi = NULL;
+
+	fi = ad_get_entry(ad, ADEID_FINDERI);
+	if (fi == NULL) {
+		DBG_ERR("Missing FinderInfo in struct adouble [%p]\n", ad);
+		return false;
 	}
-	return false;
+
+	cmp = memcmp(emptybuf, fi, ADEDLEN_FINDERI);
+	return (cmp == 0);
+}
+
+static bool ai_empty_finderinfo(const AfpInfo *ai)
+{
+	int cmp;
+	char emptybuf[ADEDLEN_FINDERI] = {0};
+
+	cmp = memcmp(emptybuf, &ai->afpi_FinderInfo[0], ADEDLEN_FINDERI);
+	return (cmp == 0);
 }
 
 /**
@@ -1582,6 +1831,21 @@
 	uint32_t t;
 	struct timespec creation_time = {0};
 	struct adouble *ad;
+	struct fruit_config_data *config = NULL;
+
+	SMB_VFS_HANDLE_GET_DATA(handle, config, struct fruit_config_data,
+				return);
+
+	switch (config->meta) {
+	case FRUIT_META_STREAM:
+		return;
+	case FRUIT_META_NETATALK:
+		/* Handled below */
+		break;
+	default:
+		DBG_ERR("Unexpected meta config [%d]\n", config->meta);
+		return;
+	}
 
 	ad = ad_get(talloc_tos(), handle, smb_fname->base_name, ADOUBLE_META);
 	if (ad == NULL) {
@@ -1697,6 +1961,8 @@
 	struct byte_range_lock *br_lck = NULL;
 	bool open_for_reading, open_for_writing, deny_read, deny_write;
 	off_t off;
+	bool have_read = false;
+	int flags;
 
 	/* FIXME: hardcoded data fork, add resource fork */
 	enum apple_fork fork_type = APPLE_FORK_DATA;
@@ -1708,6 +1974,26 @@
 		  deny_mode & DENY_READ ? "DENY_READ" : "-",
 		  deny_mode & DENY_WRITE ? "DENY_WRITE" : "-"));
 
+	if (fsp->fh->fd == -1) {
+		return NT_STATUS_OK;
+	}
+
+	flags = fcntl(fsp->fh->fd, F_GETFL);
+	if (flags == -1) {
+		DBG_ERR("fcntl get flags [%s] fd [%d] failed [%s]\n",
+			fsp_str_dbg(fsp), fsp->fh->fd, strerror(errno));
+		return map_nt_error_from_unix(errno);
+	}
+
+	if (flags & (O_RDONLY|O_RDWR)) {
+		/*
+		 * Applying fcntl read locks requires an fd opened for
+		 * reading. This means we won't be applying locks for
+		 * files openend write-only, but what can we do...
+		 */
+		have_read = true;
+	}
+
 	/*
 	 * Check read access and deny read mode
 	 */
@@ -1729,7 +2015,7 @@
 		}
 
 		/* Set locks */
-		if (access_mask & FILE_READ_DATA) {
+		if ((access_mask & FILE_READ_DATA) && have_read) {
 			off = access_to_netatalk_brl(fork_type, FILE_READ_DATA);
 			br_lck = do_lock(
 				handle->conn->sconn->msg_ctx, fsp,
@@ -1743,7 +2029,7 @@
 			TALLOC_FREE(br_lck);
 		}
 
-		if (deny_mode & DENY_READ) {
+		if ((deny_mode & DENY_READ) && have_read) {
 			off = denymode_to_netatalk_brl(fork_type, DENY_READ);
 			br_lck = do_lock(
 				handle->conn->sconn->msg_ctx, fsp,
@@ -1779,7 +2065,7 @@
 		}
 
 		/* Set locks */
-		if (access_mask & FILE_WRITE_DATA) {
+		if ((access_mask & FILE_WRITE_DATA) && have_read) {
 			off = access_to_netatalk_brl(fork_type, FILE_WRITE_DATA);
 			br_lck = do_lock(
 				handle->conn->sconn->msg_ctx, fsp,
@@ -1793,7 +2079,7 @@
 			TALLOC_FREE(br_lck);
 
 		}
-		if (deny_mode & DENY_WRITE) {
+		if ((deny_mode & DENY_WRITE) && have_read) {
 			off = denymode_to_netatalk_brl(fork_type, DENY_WRITE);
 			br_lck = do_lock(
 				handle->conn->sconn->msg_ctx, fsp,
@@ -1934,20 +2220,257 @@
 				      SMB2_CREATE_TAG_AAPL,
 				      blob);
 	if (NT_STATUS_IS_OK(status)) {
-		config->nego_aapl = true;
+		global_fruit_config.nego_aapl = true;
 	}
 
 	return status;
 }
 
+static bool readdir_attr_meta_finderi_stream(
+	struct vfs_handle_struct *handle,
+	const struct smb_filename *smb_fname,
+	AfpInfo *ai)
+{
+	struct smb_filename *stream_name = NULL;
+	files_struct *fsp = NULL;
+	ssize_t nread;
+	NTSTATUS status;
+	int ret;
+	bool ok;
+	uint8_t buf[AFP_INFO_SIZE];
+
+	stream_name = synthetic_smb_fname(talloc_tos(),
+					  smb_fname->base_name,
+					  AFPINFO_STREAM_NAME,
+					  NULL, smb_fname->flags);
+	if (stream_name == NULL) {
+		return false;
+	}
+
+	ret = SMB_VFS_STAT(handle->conn, stream_name);
+	if (ret != 0) {
+		return false;
+	}
+
+	status = SMB_VFS_CREATE_FILE(
+		handle->conn,                           /* conn */
+		NULL,                                   /* req */
+		0,                                      /* root_dir_fid */
+		stream_name,				/* fname */
+		FILE_READ_DATA,                         /* access_mask */
+		(FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
+			FILE_SHARE_DELETE),
+		FILE_OPEN,                              /* create_disposition*/
+		0,                                      /* create_options */
+		0,                                      /* file_attributes */
+		INTERNAL_OPEN_ONLY,                     /* oplock_request */
+		NULL,					/* lease */
+                0,                                      /* allocation_size */
+		0,                                      /* private_flags */
+		NULL,                                   /* sd */
+		NULL,                                   /* ea_list */
+		&fsp,                                   /* result */
+		NULL,                                   /* pinfo */
+		NULL, NULL);				/* create context */
+
+	TALLOC_FREE(stream_name);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		return false;
+	}
+
+	nread = SMB_VFS_PREAD(fsp, &buf[0], AFP_INFO_SIZE, 0);
+	if (nread != AFP_INFO_SIZE) {
+		DBG_ERR("short read [%s] [%zd/%d]\n",
+			smb_fname_str_dbg(stream_name), nread, AFP_INFO_SIZE);
+		ok = false;
+		goto fail;
+	}
+
+	memcpy(&ai->afpi_FinderInfo[0], &buf[AFP_OFF_FinderInfo],
+	       AFP_FinderSize);
+
+	ok = true;
+
+fail:
+	if (fsp != NULL) {
+		close_file(NULL, fsp, NORMAL_CLOSE);
+	}
+
+	return ok;
+}
+
+static bool readdir_attr_meta_finderi_netatalk(
+	struct vfs_handle_struct *handle,
+	const struct smb_filename *smb_fname,
+	AfpInfo *ai)
+{
+	struct adouble *ad = NULL;
+	char *p = NULL;
+
+	ad = ad_get(talloc_tos(), handle, smb_fname->base_name, ADOUBLE_META);
+	if (ad == NULL) {
+		return false;
+	}
+
+	p = ad_get_entry(ad, ADEID_FINDERI);
+	if (p == NULL) {
+		DBG_ERR("No ADEID_FINDERI for [%s]\n", smb_fname->base_name);
+		TALLOC_FREE(ad);
+		return false;
+	}
+
+	memcpy(&ai->afpi_FinderInfo[0], p, AFP_FinderSize);
+	TALLOC_FREE(ad);
+	return true;
+}
+
+static bool readdir_attr_meta_finderi(struct vfs_handle_struct *handle,
+				      const struct smb_filename *smb_fname,
+				      struct readdir_attr_data *attr_data)
+{
+	struct fruit_config_data *config = NULL;
+	uint32_t date_added;
+	AfpInfo ai = {0};
+	bool ok;
+
+	SMB_VFS_HANDLE_GET_DATA(handle, config,
+				struct fruit_config_data,
+				return false);
+
+	switch (config->meta) {
+	case FRUIT_META_NETATALK:
+		ok = readdir_attr_meta_finderi_netatalk(
+			handle, smb_fname, &ai);
+		break;
+
+	case FRUIT_META_STREAM:
+		ok = readdir_attr_meta_finderi_stream(
+			handle, smb_fname, &ai);
+		break;
+
+	default:
+		DBG_ERR("Unexpected meta config [%d]\n", config->meta);
+		return false;
+	}
+
+	if (!ok) {
+		/* Don't bother with errors, it's likely ENOENT */
+		return true;
+	}
+
+	if (S_ISREG(smb_fname->st.st_ex_mode)) {
+		/* finder_type */
+		memcpy(&attr_data->attr_data.aapl.finder_info[0],
+		       &ai.afpi_FinderInfo[0], 4);
+
+		/* finder_creator */
+		memcpy(&attr_data->attr_data.aapl.finder_info[0] + 4,
+		       &ai.afpi_FinderInfo[4], 4);
+	}
+
+	/* finder_flags */
+	memcpy(&attr_data->attr_data.aapl.finder_info[0] + 8,
+	       &ai.afpi_FinderInfo[8], 2);
+
+	/* finder_ext_flags */
+	memcpy(&attr_data->attr_data.aapl.finder_info[0] + 10,
+	       &ai.afpi_FinderInfo[24], 2);
+
+	/* creation date */
+	date_added = convert_time_t_to_uint32_t(
+		smb_fname->st.st_ex_btime.tv_sec - AD_DATE_DELTA);
+
+	RSIVAL(&attr_data->attr_data.aapl.finder_info[0], 12, date_added);
+
+	return true;
+}
+
+static uint64_t readdir_attr_rfork_size_adouble(
+	struct vfs_handle_struct *handle,
+	const struct smb_filename *smb_fname)
+{
+	struct adouble *ad = NULL;
+	uint64_t rfork_size;
+
+	ad = ad_get(talloc_tos(), handle, smb_fname->base_name,
+		    ADOUBLE_RSRC);
+	if (ad == NULL) {
+		return 0;
+	}
+
+	rfork_size = ad_getentrylen(ad, ADEID_RFORK);
+	TALLOC_FREE(ad);
+
+	return rfork_size;
+}
+
+static uint64_t readdir_attr_rfork_size_stream(
+	struct vfs_handle_struct *handle,
+	const struct smb_filename *smb_fname)
+{
+	struct smb_filename *stream_name = NULL;
+	int ret;
+	uint64_t rfork_size;
+
+	stream_name = synthetic_smb_fname(talloc_tos(),
+					  smb_fname->base_name,
+					  AFPRESOURCE_STREAM_NAME,
+					  NULL, 0);
+	if (stream_name == NULL) {
+		return 0;
+	}
+
+	ret = SMB_VFS_STAT(handle->conn, stream_name);
+	if (ret != 0) {
+		TALLOC_FREE(stream_name);
+		return 0;
+	}
+
+	rfork_size = stream_name->st.st_ex_size;
+	TALLOC_FREE(stream_name);
+
+	return rfork_size;
+}
+
+static uint64_t readdir_attr_rfork_size(struct vfs_handle_struct *handle,
+					const struct smb_filename *smb_fname)
+{
+	struct fruit_config_data *config = NULL;
+	uint64_t rfork_size;
+
+	SMB_VFS_HANDLE_GET_DATA(handle, config,
+				struct fruit_config_data,
+				return 0);
+
+	switch (config->rsrc) {
+	case FRUIT_RSRC_ADFILE:
+	case FRUIT_RSRC_XATTR:
+		rfork_size = readdir_attr_rfork_size_adouble(handle,
+							     smb_fname);
+		break;
+
+	case FRUIT_META_STREAM:
+		rfork_size = readdir_attr_rfork_size_stream(handle,
+							    smb_fname);
+		break;
+
+	default:
+		DBG_ERR("Unexpected rsrc config [%d]\n", config->rsrc);
+		rfork_size = 0;
+		break;
+	}
+
+	return rfork_size;
+}
+
 static NTSTATUS readdir_attr_macmeta(struct vfs_handle_struct *handle,
 				     const struct smb_filename *smb_fname,
 				     struct readdir_attr_data *attr_data)
 {
 	NTSTATUS status = NT_STATUS_OK;
-	uint32_t date_added;
-	struct adouble *ad = NULL;
 	struct fruit_config_data *config = NULL;
+	bool ok;
 
 	SMB_VFS_HANDLE_GET_DATA(handle, config,
 				struct fruit_config_data,
@@ -1962,13 +2485,10 @@
 	 */
 
 	if (config->readdir_attr_rsize) {
-		ad = ad_get(talloc_tos(), handle, smb_fname->base_name,
-			    ADOUBLE_RSRC);
-		if (ad) {
-			attr_data->attr_data.aapl.rfork_size = ad_getentrylen(
-				ad, ADEID_RFORK);
-			TALLOC_FREE(ad);
-		}
+		uint64_t rfork_size;
+
+		rfork_size = readdir_attr_rfork_size(handle, smb_fname);
+		attr_data->attr_data.aapl.rfork_size = rfork_size;
 	}
 
 	/*
@@ -1976,37 +2496,12 @@
 	 */
 
 	if (config->readdir_attr_finder_info) {
-		ad = ad_get(talloc_tos(), handle, smb_fname->base_name,
-			    ADOUBLE_META);
-		if (ad) {
-			if (S_ISREG(smb_fname->st.st_ex_mode)) {
-				/* finder_type */
-				memcpy(&attr_data->attr_data.aapl.finder_info[0],
-				       ad_entry(ad, ADEID_FINDERI), 4);
-
-				/* finder_creator */
-				memcpy(&attr_data->attr_data.aapl.finder_info[0] + 4,
-				       ad_entry(ad, ADEID_FINDERI) + 4, 4);
-			}
-
-			/* finder_flags */
-			memcpy(&attr_data->attr_data.aapl.finder_info[0] + 8,
-			       ad_entry(ad, ADEID_FINDERI) + 8, 2);
-
-			/* finder_ext_flags */
-			memcpy(&attr_data->attr_data.aapl.finder_info[0] + 10,
-			       ad_entry(ad, ADEID_FINDERI) + 24, 2);
-
-			/* creation date */
-			date_added = convert_time_t_to_uint32_t(
-				smb_fname->st.st_ex_btime.tv_sec - AD_DATE_DELTA);
-			RSIVAL(&attr_data->attr_data.aapl.finder_info[0], 12, date_added);
-
-			TALLOC_FREE(ad);
+		ok = readdir_attr_meta_finderi(handle, smb_fname, attr_data);
+		if (!ok) {
+			status = NT_STATUS_INTERNAL_ERROR;
 		}
 	}
 
-	TALLOC_FREE(ad);
 	return status;
 }
 
@@ -2116,25 +2611,81 @@
 	return rc;
 }
 
-static int fruit_open_meta(vfs_handle_struct *handle,
-			   struct smb_filename *smb_fname,
-			   files_struct *fsp, int flags, mode_t mode)
+static int fruit_open_meta_stream(vfs_handle_struct *handle,
+				  struct smb_filename *smb_fname,
+				  files_struct *fsp,
+				  int flags,
+				  mode_t mode)
+{
+	AfpInfo *ai = NULL;
+	char afpinfo_buf[AFP_INFO_SIZE];
+	ssize_t len, written;
+	int hostfd = -1;
+	int rc = -1;
+
+	hostfd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
+	if (hostfd == -1) {
+		return -1;
+	}
+
+	if (!(flags & (O_CREAT | O_TRUNC))) {
+		return hostfd;
+	}
+
+	ai = afpinfo_new(talloc_tos());
+	if (ai == NULL) {
+		rc = -1;
+		goto fail;
+	}
+
+	len = afpinfo_pack(ai, afpinfo_buf);
+	if (len != AFP_INFO_SIZE) {
+		rc = -1;
+		goto fail;
+	}
+
+	/* Set fd, needed in SMB_VFS_NEXT_PWRITE() */
+	fsp->fh->fd = hostfd;
+
+	written = SMB_VFS_NEXT_PWRITE(handle, fsp, afpinfo_buf,
+				      AFP_INFO_SIZE, 0);
+	fsp->fh->fd = -1;
+	if (written != AFP_INFO_SIZE) {
+		DBG_ERR("bad write [%zd/%d]\n", written, AFP_INFO_SIZE);
+		rc = -1;
+		goto fail;
+	}
+
+	rc = 0;
+
+fail:
+	DBG_DEBUG("rc=%d, fd=%d\n", rc, hostfd);
+
+	if (rc != 0) {
+		int saved_errno = errno;
+		if (hostfd >= 0) {
+			fsp->fh->fd = hostfd;
+			SMB_VFS_NEXT_CLOSE(handle, fsp);
+		}
+		hostfd = -1;
+		errno = saved_errno;
+	}
+	return hostfd;
+}
+
+static int fruit_open_meta_netatalk(vfs_handle_struct *handle,
+				    struct smb_filename *smb_fname,
+				    files_struct *fsp,
+				    int flags,
+				    mode_t mode)
 {
 	int rc = 0;
-	struct fruit_config_data *config = NULL;
 	struct smb_filename *smb_fname_base = NULL;
 	int baseflags;
 	int hostfd = -1;
 	struct adouble *ad = NULL;
 
-	DEBUG(10, ("fruit_open_meta for %s\n", smb_fname_str_dbg(smb_fname)));
-
-	SMB_VFS_HANDLE_GET_DATA(handle, config,
-				struct fruit_config_data, return -1);
-
-	if (config->meta == FRUIT_META_STREAM) {
-		return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
-	}
+	DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname));
 
 	/* Create an smb_filename with stream_name == NULL. */
 	smb_fname_base = synthetic_smb_fname(talloc_tos(),
@@ -2158,8 +2709,8 @@
 	baseflags &= ~O_EXCL;
 	baseflags &= ~O_CREAT;
 
-	hostfd = SMB_VFS_OPEN(handle->conn, smb_fname_base, fsp,
-			      baseflags, mode);
+	hostfd = SMB_VFS_NEXT_OPEN(handle, smb_fname_base, fsp,
+				   baseflags, mode);
 
 	/*
 	 * It is legit to open a stream on a directory, but the base
@@ -2168,8 +2719,8 @@
 	if ((hostfd == -1) && (errno == EISDIR)) {
 		baseflags &= ~O_ACCMODE;
 		baseflags |= O_RDONLY;
-		hostfd = SMB_VFS_OPEN(handle->conn, smb_fname_base, fsp,
-				      baseflags, mode);
+		hostfd = SMB_VFS_NEXT_OPEN(handle, smb_fname_base, fsp,
+					   baseflags, mode);
 	}
 
 	TALLOC_FREE(smb_fname_base);
@@ -2184,29 +2735,22 @@
 		 * The attribute does not exist or needs to be truncated,
 		 * create an AppleDouble EA
 		 */
-		ad = ad_init(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
-			     handle, ADOUBLE_META, fsp);
+		ad = ad_init(fsp, handle, ADOUBLE_META);
 		if (ad == NULL) {
 			rc = -1;
 			goto exit;
 		}
 
-		rc = ad_write(ad, smb_fname->base_name);
+		fsp->fh->fd = hostfd;
+
+		rc = ad_fset(ad, fsp);
+		fsp->fh->fd = -1;
 		if (rc != 0) {
 			rc = -1;
 			goto exit;
 		}
-	} else {
-		ad = ad_alloc(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
-			      handle, ADOUBLE_META, fsp);
-		if (ad == NULL) {
-			rc = -1;
-			goto exit;
-		}
-		if (ad_read(ad, smb_fname->base_name) == -1) {
-			rc = -1;
-			goto exit;
-		}
+
+		TALLOC_FREE(ad);
 	}
 
 exit:
@@ -2220,7 +2764,7 @@
 			 * full fsp yet
 			 */
 			fsp->fh->fd = hostfd;
-			SMB_VFS_CLOSE(fsp);
+			SMB_VFS_NEXT_CLOSE(handle, fsp);
 		}
 		hostfd = -1;
 		errno = saved_errno;
@@ -2228,56 +2772,67 @@
 	return hostfd;
 }
 
-static int fruit_open_rsrc(vfs_handle_struct *handle,
+static int fruit_open_meta(vfs_handle_struct *handle,
 			   struct smb_filename *smb_fname,
 			   files_struct *fsp, int flags, mode_t mode)
 {
-	int rc = 0;
+	int fd;
 	struct fruit_config_data *config = NULL;
-	struct adouble *ad = NULL;
-	struct smb_filename *smb_fname_base = NULL;
-	char *adpath = NULL;
-	int hostfd = -1;
+	struct fio *fio = NULL;
 
-	DEBUG(10, ("fruit_open_rsrc for %s\n", smb_fname_str_dbg(smb_fname)));
+	DBG_DEBUG("path [%s]\n", smb_fname_str_dbg(smb_fname));
 
 	SMB_VFS_HANDLE_GET_DATA(handle, config,
 				struct fruit_config_data, return -1);
 
-	switch (config->rsrc) {
-	case FRUIT_RSRC_STREAM:
-		return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
-	case FRUIT_RSRC_XATTR:
-#ifdef HAVE_ATTROPEN
-		hostfd = attropen(smb_fname->base_name,
-				  AFPRESOURCE_EA_NETATALK, flags, mode);
-		if (hostfd == -1) {
-			return -1;
-		}
-		ad = ad_init(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
-			     handle, ADOUBLE_RSRC, fsp);
-		if (ad == NULL) {
-			rc = -1;
-			goto exit;
-		}
-		goto exit;
-#else
-		errno = ENOTSUP;
-		return -1;
-#endif
-	default:
+	switch (config->meta) {
+	case FRUIT_META_STREAM:
+		fd = fruit_open_meta_stream(handle, smb_fname,
+					    fsp, flags, mode);
+		break;
+
+	case FRUIT_META_NETATALK:
+		fd = fruit_open_meta_netatalk(handle, smb_fname,
+					      fsp, flags, mode);
 		break;
+
+	default:
+		DBG_ERR("Unexpected meta config [%d]\n", config->meta);
+		return -1;
 	}
 
-	if (!(flags & O_CREAT) && !VALID_STAT(smb_fname->st)) {
-		rc = SMB_VFS_NEXT_STAT(handle, smb_fname);
-		if (rc != 0) {
-			rc = -1;
-			goto exit;
-		}
+	DBG_DEBUG("path [%s] fd [%d]\n", smb_fname_str_dbg(smb_fname), fd);
+
+	if (fd == -1) {
+		return -1;
 	}
 
-	if (VALID_STAT(smb_fname->st) && S_ISDIR(smb_fname->st.st_ex_mode)) {
+	fio = (struct fio *)VFS_ADD_FSP_EXTENSION(handle, fsp, struct fio, NULL);
+	fio->type = ADOUBLE_META;
+	fio->config = config;
+
+	return fd;
+}
+
+static int fruit_open_rsrc_adouble(vfs_handle_struct *handle,
+				   struct smb_filename *smb_fname,
+				   files_struct *fsp,
+				   int flags,
+				   mode_t mode)
+{
+	int rc = 0;
+	struct adouble *ad = NULL;
+	struct smb_filename *smb_fname_base = NULL;
+	struct fruit_config_data *config = NULL;
+	char *adpath = NULL;
+	int hostfd = -1;
+
+	SMB_VFS_HANDLE_GET_DATA(handle, config,
+				struct fruit_config_data, return -1);
+
+	if ((!(flags & O_CREAT)) &&
+	    S_ISDIR(fsp->base_fsp->fsp_name->st.st_ex_mode))
+	{
 		/* sorry, but directories don't habe a resource fork */
 		rc = -1;
 		goto exit;
@@ -2307,39 +2862,29 @@
 		flags |= O_RDWR;
 	}
 
-	hostfd = SMB_VFS_OPEN(handle->conn, smb_fname_base, fsp,
-			      flags, mode);
+	hostfd = SMB_VFS_NEXT_OPEN(handle, smb_fname_base, fsp,
+				   flags, mode);
 	if (hostfd == -1) {
 		rc = -1;
 		goto exit;
 	}
 
-	/* REVIEW: we need this in ad_write() */
-	fsp->fh->fd = hostfd;
-
 	if (flags & (O_CREAT | O_TRUNC)) {
-		ad = ad_init(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
-			     handle, ADOUBLE_RSRC, fsp);
+		ad = ad_init(fsp, handle, ADOUBLE_RSRC);
 		if (ad == NULL) {
 			rc = -1;
 			goto exit;
 		}
-		rc = ad_write(ad, smb_fname->base_name);
+
+		fsp->fh->fd = hostfd;
+
+		rc = ad_fset(ad, fsp);
+		fsp->fh->fd = -1;
 		if (rc != 0) {
 			rc = -1;
 			goto exit;
 		}
-	} else {
-		ad = ad_alloc(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
-			      handle, ADOUBLE_RSRC, fsp);
-		if (ad == NULL) {
-			rc = -1;
-			goto exit;
-		}
-		if (ad_read(ad, smb_fname->base_name) == -1) {
-			rc = -1;
-			goto exit;
-		}
+		TALLOC_FREE(ad);
 	}
 
 exit:
@@ -2365,24 +2910,100 @@
 	return hostfd;
 }
 
+static int fruit_open_rsrc_xattr(vfs_handle_struct *handle,
+				 struct smb_filename *smb_fname,
+				 files_struct *fsp,
+				 int flags,
+				 mode_t mode)
+{
+#ifdef HAVE_ATTROPEN
+	int fd = -1;
+
+	fd = attropen(smb_fname->base_name,
+		      AFPRESOURCE_EA_NETATALK,
+		      flags,
+		      mode);
+	if (fd == -1) {
+		return -1;
+	}
+
+	return fd;
+
+#else
+	errno = ENOSYS;
+	return -1;
+#endif
+}
+
+static int fruit_open_rsrc(vfs_handle_struct *handle,
+			   struct smb_filename *smb_fname,
+			   files_struct *fsp, int flags, mode_t mode)
+{
+	int fd;
+	struct fruit_config_data *config = NULL;
+	struct fio *fio = NULL;
+
+	DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname));
+
+	SMB_VFS_HANDLE_GET_DATA(handle, config,
+				struct fruit_config_data, return -1);
+
+	switch (config->rsrc) {
+	case FRUIT_RSRC_STREAM:
+		fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
+		break;
+
+	case FRUIT_RSRC_ADFILE:
+		fd = fruit_open_rsrc_adouble(handle, smb_fname,
+					     fsp, flags, mode);
+		break;
+
+	case FRUIT_RSRC_XATTR:
+		fd = fruit_open_rsrc_xattr(handle, smb_fname,
+					   fsp, flags, mode);
+		break;
+
+	default:
+		DBG_ERR("Unexpected rsrc config [%d]\n", config->rsrc);
+		return -1;
+	}
+
+	DBG_DEBUG("Path [%s] fd [%d]\n", smb_fname_str_dbg(smb_fname), fd);
+
+	if (fd == -1) {
+		return -1;
+	}
+
+	fio = (struct fio *)VFS_ADD_FSP_EXTENSION(handle, fsp, struct fio, NULL);
+	fio->type = ADOUBLE_RSRC;
+	fio->config = config;
+
+	return fd;
+}
+
 static int fruit_open(vfs_handle_struct *handle,
                       struct smb_filename *smb_fname,
                       files_struct *fsp, int flags, mode_t mode)
 {
-	DEBUG(10, ("fruit_open called for %s\n",
-		   smb_fname_str_dbg(smb_fname)));
+	int fd;
+
+	DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname));
 
 	if (!is_ntfs_stream_smb_fname(smb_fname)) {
 		return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
 	}
 
 	if (is_afpinfo_stream(smb_fname)) {
-		return fruit_open_meta(handle, smb_fname, fsp, flags, mode);
+		fd = fruit_open_meta(handle, smb_fname, fsp, flags, mode);
 	} else if (is_afpresource_stream(smb_fname)) {
-		return fruit_open_rsrc(handle, smb_fname, fsp, flags, mode);
+		fd = fruit_open_rsrc(handle, smb_fname, fsp, flags, mode);
+	} else {
+		fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
 	}
 
-	return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
+	DBG_DEBUG("Path [%s] fd [%d]\n", smb_fname_str_dbg(smb_fname), fd);
+
+	return fd;
 }
 
 static int fruit_rename(struct vfs_handle_struct *handle,
@@ -2393,19 +3014,27 @@
 	char *src_adouble_path = NULL;
 	char *dst_adouble_path = NULL;
 	struct fruit_config_data *config = NULL;
+	struct smb_filename *src_adp_smb_fname = NULL;
+	struct smb_filename *dst_adp_smb_fname = NULL;
 
-	rc = SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst);
+	SMB_VFS_HANDLE_GET_DATA(handle, config,
+				struct fruit_config_data, return -1);
 
-	if (!VALID_STAT(smb_fname_src->st)
-	    || !S_ISREG(smb_fname_src->st.st_ex_mode)) {
-		return rc;
+	if (!VALID_STAT(smb_fname_src->st)) {
+		DBG_ERR("Need valid stat for [%s]\n",
+			smb_fname_str_dbg(smb_fname_src));
+		return -1;
 	}
 
-	SMB_VFS_HANDLE_GET_DATA(handle, config,
-				struct fruit_config_data, return -1);
+	rc = SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst);
+	if (rc != 0) {
+		return -1;
+	}
 
-	if (config->rsrc == FRUIT_RSRC_XATTR) {
-		return rc;
+	if ((config->rsrc != FRUIT_RSRC_ADFILE) ||
+	    (!S_ISREG(smb_fname_src->st.st_ex_mode)))
+	{
+		return 0;
 	}
 
 	rc = adouble_path(talloc_tos(), smb_fname_src->base_name,
@@ -2413,46 +3042,99 @@
 	if (rc != 0) {
 		goto done;
 	}
+	src_adp_smb_fname = synthetic_smb_fname(talloc_tos(),
+						src_adouble_path,
+						NULL, NULL,
+						smb_fname_src->flags);
+	TALLOC_FREE(src_adouble_path);
+	if (src_adp_smb_fname == NULL) {
+		rc = -1;
+		goto done;
+	}
+
 	rc = adouble_path(talloc_tos(), smb_fname_dst->base_name,
 			  &dst_adouble_path);
 	if (rc != 0) {
 		goto done;
 	}
+	dst_adp_smb_fname = synthetic_smb_fname(talloc_tos(),
+						dst_adouble_path,
+						NULL, NULL,
+						smb_fname_dst->flags);
+	TALLOC_FREE(dst_adouble_path);
+	if (dst_adp_smb_fname == NULL) {
+		rc = -1;
+		goto done;
+	}
 
-	DEBUG(10, ("fruit_rename: %s -> %s\n",
-		   src_adouble_path, dst_adouble_path));
+	DBG_DEBUG("%s -> %s\n",
+		  smb_fname_str_dbg(src_adp_smb_fname),
+		  smb_fname_str_dbg(dst_adp_smb_fname));
 
-	rc = rename(src_adouble_path, dst_adouble_path);
+	rc = SMB_VFS_NEXT_RENAME(handle, src_adp_smb_fname, dst_adp_smb_fname);
 	if (errno == ENOENT) {
 		rc = 0;
 	}
 
-	TALLOC_FREE(src_adouble_path);
-	TALLOC_FREE(dst_adouble_path);
-
 done:
+	TALLOC_FREE(src_adp_smb_fname);
+	TALLOC_FREE(dst_adp_smb_fname);
 	return rc;
 }
 
-static int fruit_unlink(vfs_handle_struct *handle,
-			const struct smb_filename *smb_fname)
+static int fruit_unlink_meta_stream(vfs_handle_struct *handle,
+				    const struct smb_filename *smb_fname)
+{
+	return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
+}
+
+static int fruit_unlink_meta_netatalk(vfs_handle_struct *handle,
+				      const struct smb_filename *smb_fname)
+{
+	return SMB_VFS_REMOVEXATTR(handle->conn,
+				   smb_fname->base_name,
+				   AFPINFO_EA_NETATALK);
+}
+
+static int fruit_unlink_meta(vfs_handle_struct *handle,
+			     const struct smb_filename *smb_fname)
 {
-	int rc = -1;
 	struct fruit_config_data *config = NULL;
+	int rc;
 
 	SMB_VFS_HANDLE_GET_DATA(handle, config,
 				struct fruit_config_data, return -1);
 
-	if (!is_ntfs_stream_smb_fname(smb_fname)) {
-		char *adp = NULL;
+	switch (config->meta) {
+	case FRUIT_META_STREAM:
+		rc = fruit_unlink_meta_stream(handle, smb_fname);
+		break;
 
-		rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
-		if (rc != 0) {
-			return -1;
-		}
+	case FRUIT_META_NETATALK:
+		rc = fruit_unlink_meta_netatalk(handle, smb_fname);
+		break;
 
-		if (config->rsrc != FRUIT_RSRC_ADFILE) {
-			return 0;
+	default:
+		DBG_ERR("Unsupported meta config [%d]\n", config->meta);
+		return -1;
+	}
+
+	return rc;
+}
+
+static int fruit_unlink_rsrc_stream(vfs_handle_struct *handle,
+				    const struct smb_filename *smb_fname,
+				    bool force_unlink)
+{
+	int ret;
+
+	if (!force_unlink) {
+		struct smb_filename *smb_fname_cp = NULL;
+		off_t size;
+
+		smb_fname_cp = cp_smb_filename(talloc_tos(), smb_fname);
+		if (smb_fname_cp == NULL) {
+			return -1;
 		}
 
 		/*
@@ -2460,46 +3142,176 @@
 		 * vfs_streaminfo, as a result stream cleanup/deletion of file
 		 * deletion doesn't remove the resourcefork stream.
 		 */
-		rc = adouble_path(talloc_tos(),
-				  smb_fname->base_name, &adp);
-		if (rc != 0) {
+
+		ret = SMB_VFS_NEXT_STAT(handle, smb_fname_cp);
+		if (ret != 0) {
+			TALLOC_FREE(smb_fname_cp);
+			DBG_ERR("stat [%s] failed [%s]\n",
+				smb_fname_str_dbg(smb_fname_cp), strerror(errno));
 			return -1;
 		}
 
-		/* FIXME: direct unlink(), missing smb_fname */
-		DBG_DEBUG("fruit_unlink: %s\n", adp);
-		rc = unlink(adp);
-		if ((rc == -1) && (errno == ENOENT)) {
-			rc = 0;
+		size = smb_fname_cp->st.st_ex_size;
+		TALLOC_FREE(smb_fname_cp);
+
+		if (size > 0) {
+			/* OS X ignores resource fork stream delete requests */
+			return 0;
 		}
+	}
 
-		TALLOC_FREE(adp);
-		return 0;
+	ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
+	if ((ret != 0) && (errno == ENOENT) && force_unlink) {
+		ret = 0;
 	}
 
-	if (is_afpinfo_stream(smb_fname)) {
-		if (config->meta == FRUIT_META_STREAM) {
-			rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
-		} else {
-			rc = SMB_VFS_REMOVEXATTR(handle->conn,
-						 smb_fname->base_name,
-						 AFPINFO_EA_NETATALK);
+	return ret;
+}
+
+static int fruit_unlink_rsrc_adouble(vfs_handle_struct *handle,
+				     const struct smb_filename *smb_fname,
+				     bool force_unlink)
+{
+	int rc;
+	char *adp = NULL;
+	struct adouble *ad = NULL;
+	struct smb_filename *adp_smb_fname = NULL;
+
+	if (!force_unlink) {
+		ad = ad_get(talloc_tos(), handle, smb_fname->base_name,
+			    ADOUBLE_RSRC);
+		if (ad == NULL) {
+			errno = ENOENT;
+			return -1;
 		}
 
-		return rc;
+
+		/*
+		 * 0 byte resource fork streams are not listed by
+		 * vfs_streaminfo, as a result stream cleanup/deletion of file
+		 * deletion doesn't remove the resourcefork stream.
+		 */
+
+		if (ad_getentrylen(ad, ADEID_RFORK) > 0) {
+			/* OS X ignores resource fork stream delete requests */
+			TALLOC_FREE(ad);
+			return 0;
+		}
+
+		TALLOC_FREE(ad);
 	}
 
-	if (is_afpresource_stream(smb_fname)) {
-		/* OS X ignores deletes on the AFP_Resource stream */
-		return 0;
+	rc = adouble_path(talloc_tos(), smb_fname->base_name, &adp);
+	if (rc != 0) {
+		return -1;
 	}
 
-	return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
+	adp_smb_fname = synthetic_smb_fname(talloc_tos(), adp,
+					    NULL, NULL,
+					    smb_fname->flags);
+	TALLOC_FREE(adp);
+	if (adp_smb_fname == NULL) {
+		return -1;
+	}
+
+	rc = SMB_VFS_NEXT_UNLINK(handle, adp_smb_fname);
+	TALLOC_FREE(adp_smb_fname);
+	if ((rc != 0) && (errno == ENOENT) && force_unlink) {
+		rc = 0;
+	}
 
+	return rc;
+}
 
+static int fruit_unlink_rsrc_xattr(vfs_handle_struct *handle,
+				   const struct smb_filename *smb_fname,
+				   bool force_unlink)
+{
+	/*
+	 * OS X ignores resource fork stream delete requests, so nothing to do
+	 * here. Removing the file will remove the xattr anyway, so we don't
+	 * have to take care of removing 0 byte resource forks that could be
+	 * left behind.
+	 */
 	return 0;
 }
 
+static int fruit_unlink_rsrc(vfs_handle_struct *handle,
+			     const struct smb_filename *smb_fname,
+			     bool force_unlink)
+{
+	struct fruit_config_data *config = NULL;
+	int rc;
+
+	SMB_VFS_HANDLE_GET_DATA(handle, config,
+				struct fruit_config_data, return -1);
+
+	switch (config->rsrc) {
+	case FRUIT_RSRC_STREAM:
+		rc = fruit_unlink_rsrc_stream(handle, smb_fname, force_unlink);
+		break;
+
+	case FRUIT_RSRC_ADFILE:
+		rc = fruit_unlink_rsrc_adouble(handle, smb_fname, force_unlink);
+		break;
+
+	case FRUIT_RSRC_XATTR:
+		rc = fruit_unlink_rsrc_xattr(handle, smb_fname, force_unlink);
+		break;
+
+	default:
+		DBG_ERR("Unsupported rsrc config [%d]\n", config->rsrc);
+		return -1;
+	}
+
+	return rc;
+}
+
+static int fruit_unlink(vfs_handle_struct *handle,
+			const struct smb_filename *smb_fname)
+{
+	int rc;
+	struct fruit_config_data *config = NULL;
+	struct smb_filename *rsrc_smb_fname = NULL;
+
+	SMB_VFS_HANDLE_GET_DATA(handle, config,
+				struct fruit_config_data, return -1);
+
+	if (is_afpinfo_stream(smb_fname)) {
+		return fruit_unlink_meta(handle, smb_fname);
+	} else if (is_afpresource_stream(smb_fname)) {
+		return fruit_unlink_rsrc(handle, smb_fname, false);
+	} if (is_ntfs_stream_smb_fname(smb_fname)) {
+		return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
+	}
+
+	/*
+	 * A request to delete the base file. Because 0 byte resource
+	 * fork streams are not listed by fruit_streaminfo,
+	 * delete_all_streams() can't remove 0 byte resource fork
+	 * streams, so we have to cleanup this here.
+	 */
+	rsrc_smb_fname = synthetic_smb_fname(talloc_tos(),
+					     smb_fname->base_name,
+					     AFPRESOURCE_STREAM_NAME,
+					     NULL,
+					     smb_fname->flags);
+	if (rsrc_smb_fname == NULL) {
+		return -1;
+	}
+
+	rc = fruit_unlink_rsrc(handle, rsrc_smb_fname, true);
+	if ((rc != 0) && (errno != ENOENT)) {
+		DBG_ERR("Forced unlink of [%s] failed [%s]\n",
+			smb_fname_str_dbg(rsrc_smb_fname), strerror(errno));
+		TALLOC_FREE(rsrc_smb_fname);
+		return -1;
+	}
+	TALLOC_FREE(rsrc_smb_fname);
+
+	return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
+}
+
 static int fruit_chmod(vfs_handle_struct *handle,
 		       const struct smb_filename *smb_fname,
 		       mode_t mode)
@@ -2507,7 +3319,6 @@
 	int rc = -1;
 	char *adp = NULL;
 	struct fruit_config_data *config = NULL;
-	SMB_STRUCT_STAT sb;
 	const char *path = smb_fname->base_name;
 	struct smb_filename *smb_fname_adp = NULL;
 
@@ -2519,14 +3330,16 @@
 	SMB_VFS_HANDLE_GET_DATA(handle, config,
 				struct fruit_config_data, return -1);
 
-	if (config->rsrc == FRUIT_RSRC_XATTR) {
+	if (config->rsrc != FRUIT_RSRC_ADFILE) {
 		return 0;
 	}
 
-	/* FIXME: direct sys_lstat(), missing smb_fname */
-	rc = sys_lstat(path, &sb, false);
-	if (rc != 0 || !S_ISREG(sb.st_ex_mode)) {
-		return rc;
+	if (!VALID_STAT(smb_fname->st)) {
+		return 0;
+	}
+
+	if (!S_ISREG(smb_fname->st.st_ex_mode)) {
+		return 0;
 	}
 
 	rc = adouble_path(talloc_tos(), path, &adp);
@@ -2566,7 +3379,6 @@
 	char *adp = NULL;
 	struct fruit_config_data *config = NULL;
 	struct smb_filename *adp_smb_fname = NULL;
-	SMB_STRUCT_STAT sb;
 
 	rc = SMB_VFS_NEXT_CHOWN(handle, smb_fname, uid, gid);
 	if (rc != 0) {
@@ -2576,14 +3388,16 @@
 	SMB_VFS_HANDLE_GET_DATA(handle, config,
 				struct fruit_config_data, return -1);
 
-	if (config->rsrc == FRUIT_RSRC_XATTR) {
-		return rc;
+	if (config->rsrc != FRUIT_RSRC_ADFILE) {
+		return 0;
 	}
 
-	/* FIXME: direct sys_lstat(), need non-const smb_fname */
-	rc = sys_lstat(smb_fname->base_name, &sb, false);
-	if (rc != 0 || !S_ISREG(sb.st_ex_mode)) {
-		return rc;
+	if (!VALID_STAT(smb_fname->st)) {
+		return 0;
+	}
+
+	if (!S_ISREG(smb_fname->st.st_ex_mode)) {
+		return 0;
 	}
 
 	rc = adouble_path(talloc_tos(), smb_fname->base_name, &adp);
@@ -2621,12 +3435,11 @@
 	DIR *dh = NULL;
 	struct dirent *de;
 	struct fruit_config_data *config;
-	const char *path = smb_fname->base_name;
 
 	SMB_VFS_HANDLE_GET_DATA(handle, config,
 				struct fruit_config_data, return -1);
 
-	if (!handle->conn->cwd || !path || (config->rsrc == FRUIT_RSRC_XATTR)) {
+	if (config->rsrc != FRUIT_RSRC_ADFILE) {
 		goto exit_rmdir;
 	}
 
@@ -2634,24 +3447,58 @@
 	 * Due to there is no way to change bDeleteVetoFiles variable
 	 * from this module, need to clean up ourselves
 	 */
-	dh = opendir(path);
+
+	dh = SMB_VFS_OPENDIR(handle->conn, smb_fname, NULL, 0);
 	if (dh == NULL) {
 		goto exit_rmdir;
 	}
 
-	while ((de = readdir(dh)) != NULL) {
-		if ((strncmp(de->d_name,
-			     ADOUBLE_NAME_PREFIX,
-			     strlen(ADOUBLE_NAME_PREFIX))) == 0) {
-			char *p = talloc_asprintf(talloc_tos(),
-						  "%s/%s",
-						  path, de->d_name);
-			if (p == NULL) {
-				goto exit_rmdir;
-			}
-			DEBUG(10, ("fruit_rmdir: delete %s\n", p));
-			(void)unlink(p);
+	while ((de = SMB_VFS_READDIR(handle->conn, dh, NULL)) != NULL) {
+		int match;
+		struct adouble *ad = NULL;
+		char *p = NULL;
+		struct smb_filename *ad_smb_fname = NULL;
+		int ret;
+
+		match = strncmp(de->d_name,
+				ADOUBLE_NAME_PREFIX,
+				strlen(ADOUBLE_NAME_PREFIX));
+		if (match != 0) {
+			continue;
+		}
+
+		p = talloc_asprintf(talloc_tos(), "%s/%s",
+				    smb_fname->base_name, de->d_name);
+		if (p == NULL) {
+			DBG_ERR("talloc_asprintf failed\n");
+			return -1;
+		}
+
+		/*
+		 * Check whether it's a valid AppleDouble file, if
+		 * yes, delete it, ignore it otherwise.
+		 */
+		ad = ad_get(talloc_tos(), handle, p, ADOUBLE_RSRC);
+		if (ad == NULL) {
 			TALLOC_FREE(p);
+			continue;
+		}
+		TALLOC_FREE(ad);
+
+		ad_smb_fname = synthetic_smb_fname(talloc_tos(), p,
+						    NULL, NULL,
+						    smb_fname->flags);
+		TALLOC_FREE(p);
+		if (ad_smb_fname == NULL) {
+			DBG_ERR("synthetic_smb_fname failed\n");
+			return -1;
+		}
+
+		ret = SMB_VFS_NEXT_UNLINK(handle, ad_smb_fname);
+		TALLOC_FREE(ad_smb_fname);
+		if (ret != 0) {
+			DBG_ERR("Deleting [%s] failed\n",
+				smb_fname_str_dbg(ad_smb_fname));
 		}
 	}
 
@@ -2662,245 +3509,426 @@
 	return SMB_VFS_NEXT_RMDIR(handle, smb_fname);
 }
 
-static ssize_t fruit_pread(vfs_handle_struct *handle,
-			   files_struct *fsp, void *data,
-			   size_t n, off_t offset)
+static ssize_t fruit_pread_meta_stream(vfs_handle_struct *handle,
+				       files_struct *fsp, void *data,
+				       size_t n, off_t offset)
 {
-	int rc = 0;
-        struct adouble *ad = (struct adouble *)VFS_FETCH_FSP_EXTENSION(
-		handle, fsp);
-	struct fruit_config_data *config = NULL;
-	AfpInfo *ai = NULL;
-	ssize_t len = -1;
-	char *name = NULL;
-	char *tmp_base_name = NULL;
-	NTSTATUS status;
+	ssize_t nread;
+	int ret;
 
-	DEBUG(10, ("fruit_pread: offset=%d, size=%d\n", (int)offset, (int)n));
+	nread = SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
 
-	if (!fsp->base_fsp) {
-		return SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
+	if (nread == n) {
+		return nread;
 	}
 
-	SMB_VFS_HANDLE_GET_DATA(handle, config,
-				struct fruit_config_data, return -1);
+	DBG_ERR("Removing [%s] after short read [%zd]\n",
+		fsp_str_dbg(fsp), nread);
 
-	/* fsp_name is not converted with vfs_catia */
-	tmp_base_name = fsp->base_fsp->fsp_name->base_name;
-	status = SMB_VFS_TRANSLATE_NAME(handle->conn,
-					fsp->base_fsp->fsp_name->base_name,
-					vfs_translate_to_unix,
-					talloc_tos(), &name);
-	if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
-		name = talloc_strdup(talloc_tos(), tmp_base_name);
-		if (name == NULL) {
-			rc = -1;
-			goto exit;
-		}
-	} else if (!NT_STATUS_IS_OK(status)) {
-		errno = map_errno_from_nt_status(status);
-		rc = -1;
-		goto exit;
+	ret = SMB_VFS_NEXT_UNLINK(handle, fsp->fsp_name);
+	if (ret != 0) {
+		DBG_ERR("Removing [%s] failed\n", fsp_str_dbg(fsp));
+		return -1;
+	}
+
+	errno = EINVAL;
+	return -1;
+}
+
+static ssize_t fruit_pread_meta_adouble(vfs_handle_struct *handle,
+					files_struct *fsp, void *data,
+					size_t n, off_t offset)
+{
+	AfpInfo *ai = NULL;
+	struct adouble *ad = NULL;
+	char afpinfo_buf[AFP_INFO_SIZE];
+	char *p = NULL;
+	ssize_t nread;
+
+	ai = afpinfo_new(talloc_tos());
+	if (ai == NULL) {
+		return -1;
 	}
-	fsp->base_fsp->fsp_name->base_name = name;
 
+	ad = ad_fget(talloc_tos(), handle, fsp, ADOUBLE_META);
 	if (ad == NULL) {
-		len = SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
-		if (len == -1) {
-			rc = -1;
-			goto exit;
-		}
-		goto exit;
+		nread = -1;
+		goto fail;
 	}
 
-	if (!fruit_fsp_recheck(ad, fsp)) {
-		rc = -1;
-		goto exit;
+	p = ad_get_entry(ad, ADEID_FINDERI);
+	if (p == NULL) {
+		DBG_ERR("No ADEID_FINDERI for [%s]\n", fsp_str_dbg(fsp));
+		nread = -1;
+		goto fail;
 	}
 
-	if (ad->ad_type == ADOUBLE_META) {
-		char afpinfo_buf[AFP_INFO_SIZE];
-		size_t to_return;
+	memcpy(&ai->afpi_FinderInfo[0], p, ADEDLEN_FINDERI);
 
-		/*
-		 * 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;
-		}
+	nread = afpinfo_pack(ai, afpinfo_buf);
+	if (nread != AFP_INFO_SIZE) {
+		nread = -1;
+		goto fail;
+	}
 
-		to_return = MIN(n, AFP_INFO_SIZE);
+	memcpy(data, afpinfo_buf, n);
+	nread = n;
 
-		ai = afpinfo_new(talloc_tos());
-		if (ai == NULL) {
-			rc = -1;
-			goto exit;
-		}
+fail:
+	TALLOC_FREE(ai);
+	return nread;
+}
 
-		len = ad_read(ad, fsp->base_fsp->fsp_name->base_name);
-		if (len == -1) {
-			rc = -1;
-			goto exit;
-		}
+static ssize_t fruit_pread_meta(vfs_handle_struct *handle,
+				files_struct *fsp, void *data,
+				size_t n, off_t offset)
+{
+	struct fio *fio = (struct fio *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+	ssize_t nread;
+	ssize_t to_return;
 
-		memcpy(&ai->afpi_FinderInfo[0],
-		       ad_entry(ad, ADEID_FINDERI),
-		       ADEDLEN_FINDERI);
-		len = afpinfo_pack(ai, afpinfo_buf);
-		if (len != AFP_INFO_SIZE) {
-			rc = -1;
-			goto exit;
-		}
+	/*
+	 * 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)) {
+		return 0;
+	}
 
-		/*
-		 * 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(
-			handle, fsp, data, n,
-			offset + ad_getentryoff(ad, ADEID_RFORK));
-		if (len == -1) {
-			rc = -1;
-			goto exit;
-		}
+	/* Yes, macOS always reads from offset 0 */
+	offset = 0;
+	to_return = MIN(n, AFP_INFO_SIZE);
+
+	switch (fio->config->meta) {
+	case FRUIT_META_STREAM:
+		nread = fruit_pread_meta_stream(handle, fsp, data,
+						to_return, offset);
+		break;
+
+	case FRUIT_META_NETATALK:
+		nread = fruit_pread_meta_adouble(handle, fsp, data,
+						 to_return, offset);
+		break;
+
+	default:
+		DBG_ERR("Unexpected meta config [%d]\n", fio->config->meta);
+		return -1;
 	}
-exit:
-	fsp->base_fsp->fsp_name->base_name = tmp_base_name;
-	TALLOC_FREE(name);
-	TALLOC_FREE(ai);
-	if (rc != 0) {
-		len = -1;
+
+	return nread;
+}
+
+static ssize_t fruit_pread_rsrc_stream(vfs_handle_struct *handle,
+				       files_struct *fsp, void *data,
+				       size_t n, off_t offset)
+{
+	return SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
+}
+
+static ssize_t fruit_pread_rsrc_xattr(vfs_handle_struct *handle,
+				      files_struct *fsp, void *data,
+				      size_t n, off_t offset)
+{
+	return SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
+}
+
+static ssize_t fruit_pread_rsrc_adouble(vfs_handle_struct *handle,
+					files_struct *fsp, void *data,
+					size_t n, off_t offset)
+{
+	struct adouble *ad = NULL;
+	ssize_t nread;
+
+	ad = ad_fget(talloc_tos(), handle, fsp, ADOUBLE_RSRC);
+	if (ad == NULL) {
+		return -1;
 	}
-	DEBUG(10, ("fruit_pread: rc=%d, len=%zd\n", rc, len));
-	return len;
+
+	nread = SMB_VFS_NEXT_PREAD(handle, fsp, data, n,
+				   offset + ad_getentryoff(ad, ADEID_RFORK));
+
+	TALLOC_FREE(ad);
+	return nread;
 }
 
-static ssize_t fruit_pwrite(vfs_handle_struct *handle,
-			    files_struct *fsp, const void *data,
-			    size_t n, off_t offset)
+static ssize_t fruit_pread_rsrc(vfs_handle_struct *handle,
+				files_struct *fsp, void *data,
+				size_t n, off_t offset)
+{
+	struct fio *fio = (struct fio *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+	ssize_t nread;
+
+	switch (fio->config->rsrc) {
+	case FRUIT_RSRC_STREAM:
+		nread = fruit_pread_rsrc_stream(handle, fsp, data, n, offset);
+		break;
+
+	case FRUIT_RSRC_ADFILE:
+		nread = fruit_pread_rsrc_adouble(handle, fsp, data, n, offset);
+		break;
+
+	case FRUIT_RSRC_XATTR:
+		nread = fruit_pread_rsrc_xattr(handle, fsp, data, n, offset);
+		break;
+
+	default:
+		DBG_ERR("Unexpected rsrc config [%d]\n", fio->config->rsrc);
+		return -1;
+	}
+
+	return nread;
+}
+
+static ssize_t fruit_pread(vfs_handle_struct *handle,
+			   files_struct *fsp, void *data,
+			   size_t n, off_t offset)
+{
+	struct fio *fio = (struct fio *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+	ssize_t nread;
+
+	DBG_DEBUG("Path [%s] offset=%zd, size=%zd\n",
+		  fsp_str_dbg(fsp), offset, n);
+
+	if (fio == NULL) {
+		return SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
+	}
+
+	if (fio->type == ADOUBLE_META) {
+		nread = fruit_pread_meta(handle, fsp, data, n, offset);
+	} else {
+		nread = fruit_pread_rsrc(handle, fsp, data, n, offset);
+	}
+
+	DBG_DEBUG("Path [%s] nread [%zd]\n", fsp_str_dbg(fsp), nread);
+	return nread;
+}
+
+static ssize_t fruit_pwrite_meta_stream(vfs_handle_struct *handle,
+					files_struct *fsp, const void *data,
+					size_t n, off_t offset)
 {
-	int rc = 0;
-	struct adouble *ad = (struct adouble *)VFS_FETCH_FSP_EXTENSION(
-		handle, fsp);
-	struct fruit_config_data *config = NULL;
 	AfpInfo *ai = NULL;
-	ssize_t len;
-	char *name = NULL;
-	char *tmp_base_name = NULL;
-	NTSTATUS status;
+	int ret;
 
-	DEBUG(10, ("fruit_pwrite: offset=%d, size=%d\n", (int)offset, (int)n));
+	ai = afpinfo_unpack(talloc_tos(), data);
+	if (ai == NULL) {
+		return -1;
+	}
 
-	if (!fsp->base_fsp) {
-		return SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
+	if (ai_empty_finderinfo(ai)) {
+		ret = SMB_VFS_NEXT_UNLINK(handle, fsp->fsp_name);
+		if (ret != 0 && errno != ENOENT && errno != ENOATTR) {
+			DBG_ERR("Can't delete metadata for %s: %s\n",
+				fsp_str_dbg(fsp), strerror(errno));
+			TALLOC_FREE(ai);
+			return -1;
+		}
+
+		return n;
 	}
 
-	SMB_VFS_HANDLE_GET_DATA(handle, config,
-				struct fruit_config_data, return -1);
+	return SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
+}
 
-	tmp_base_name = fsp->base_fsp->fsp_name->base_name;
-	status = SMB_VFS_TRANSLATE_NAME(handle->conn,
-					fsp->base_fsp->fsp_name->base_name,
-					vfs_translate_to_unix,
-					talloc_tos(), &name);
-	if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
-		name = talloc_strdup(talloc_tos(), tmp_base_name);
-		if (name == NULL) {
-			rc = -1;
-			goto exit;
+static ssize_t fruit_pwrite_meta_netatalk(vfs_handle_struct *handle,
+					  files_struct *fsp, const void *data,
+					  size_t n, off_t offset)
+{
+	struct adouble *ad = NULL;
+	AfpInfo *ai = NULL;
+	char *p = NULL;
+	int ret;
+
+	ai = afpinfo_unpack(talloc_tos(), data);
+	if (ai == NULL) {
+		return -1;
+	}
+
+	if (ai_empty_finderinfo(ai)) {
+		ret = SMB_VFS_REMOVEXATTR(handle->conn,
+					  fsp->fsp_name->base_name,
+					  AFPINFO_EA_NETATALK);
+
+		if (ret != 0 && errno != ENOENT && errno != ENOATTR) {
+			DBG_ERR("Can't delete metadata for %s: %s\n",
+				fsp_str_dbg(fsp), strerror(errno));
+			return -1;
 		}
-	} else if (!NT_STATUS_IS_OK(status)) {
-		errno = map_errno_from_nt_status(status);
-		rc = -1;
-		goto exit;
+
+		return n;
 	}
-	fsp->base_fsp->fsp_name->base_name = name;
 
+	ad = ad_fget(talloc_tos(), handle, fsp, ADOUBLE_META);
 	if (ad == NULL) {
-		len = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
-		if (len != n) {
-			rc = -1;
-			goto exit;
+		ad = ad_init(talloc_tos(), handle, ADOUBLE_META);
+		if (ad == NULL) {
+			return -1;
 		}
-		goto exit;
+	}
+	p = ad_get_entry(ad, ADEID_FINDERI);
+	if (p == NULL) {
+		DBG_ERR("No ADEID_FINDERI for [%s]\n", fsp_str_dbg(fsp));
+		TALLOC_FREE(ad);
+		return -1;
 	}
 
-	if (!fruit_fsp_recheck(ad, fsp)) {
-		rc = -1;
-		goto exit;
+	memcpy(p, &ai->afpi_FinderInfo[0], ADEDLEN_FINDERI);
+
+	ret = ad_fset(ad, fsp);
+	if (ret != 0) {
+		DBG_ERR("ad_pwrite [%s] failed\n", fsp_str_dbg(fsp));
+		TALLOC_FREE(ad);
+		return -1;
 	}
 
-	if (ad->ad_type == ADOUBLE_META) {
-		if (n != AFP_INFO_SIZE || offset != 0) {
-			DEBUG(1, ("unexpected offset=%jd or size=%jd\n",
-				  (intmax_t)offset, (intmax_t)n));
-			rc = -1;
-			goto exit;
-		}
-		ai = afpinfo_unpack(talloc_tos(), data);
-		if (ai == NULL) {
-			rc = -1;
-			goto exit;
-		}
-		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,
-                                   offset + ad_getentryoff(ad, ADEID_RFORK));
-		if (len != n) {
-			rc = -1;
-			goto exit;
-		}
+	TALLOC_FREE(ad);
+	return n;
+}
 
-		if (config->rsrc == FRUIT_RSRC_ADFILE) {
-			rc = ad_read(ad, name);
-			if (rc == -1) {
-				goto exit;
-			}
-			rc = 0;
+static ssize_t fruit_pwrite_meta(vfs_handle_struct *handle,
+				 files_struct *fsp, const void *data,
+				 size_t n, off_t offset)
+{
+	struct fio *fio = (struct fio *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+	ssize_t nwritten;
 
-			if ((len + offset) > ad_getentrylen(ad, ADEID_RFORK)) {
-				ad_setentrylen(ad, ADEID_RFORK, len + offset);
-				rc = ad_write(ad, name);
-			}
-		}
+	/*
+	 * Writing an all 0 blob to the metadata stream
+	 * results in the stream being removed on a macOS
+	 * server. This ensures we behave the same and it
+	 * verified by the "delete AFP_AfpInfo by writing all
+	 * 0" test.
+	 */
+	if (n != AFP_INFO_SIZE || offset != 0) {
+		DBG_ERR("unexpected offset=%jd or size=%jd\n",
+			(intmax_t)offset, (intmax_t)n);
+		return -1;
 	}
 
-exit:
-	fsp->base_fsp->fsp_name->base_name = tmp_base_name;
-	TALLOC_FREE(name);
-	TALLOC_FREE(ai);
-	if (rc != 0) {
+	switch (fio->config->meta) {
+	case FRUIT_META_STREAM:
+		nwritten = fruit_pwrite_meta_stream(handle, fsp, data,
+						    n, offset);
+		break;
+
+	case FRUIT_META_NETATALK:
+		nwritten = fruit_pwrite_meta_netatalk(handle, fsp, data,
+						      n, offset);
+		break;
+
+	default:
+		DBG_ERR("Unexpected meta config [%d]\n", fio->config->meta);
+		return -1;
+	}
+
+	return nwritten;
+}
+
+static ssize_t fruit_pwrite_rsrc_stream(vfs_handle_struct *handle,
+					files_struct *fsp, const void *data,
+					size_t n, off_t offset)
+{
+	return SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
+}
+
+static ssize_t fruit_pwrite_rsrc_xattr(vfs_handle_struct *handle,
+				       files_struct *fsp, const void *data,
+				       size_t n, off_t offset)
+{
+	return SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
+}
+
+static ssize_t fruit_pwrite_rsrc_adouble(vfs_handle_struct *handle,
+					 files_struct *fsp, const void *data,
+					 size_t n, off_t offset)
+{
+	struct adouble *ad = NULL;
+	ssize_t nwritten;
+	int ret;
+
+	ad = ad_fget(talloc_tos(), handle, fsp, ADOUBLE_RSRC);
+	if (ad == NULL) {
+		DBG_ERR("ad_get [%s] failed\n", fsp_str_dbg(fsp));
+		return -1;
+	}
+
+	nwritten = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n,
+				       offset + ad_getentryoff(ad, ADEID_RFORK));
+	if (nwritten != n) {
+		DBG_ERR("Short write on [%s] [%zd/%zd]\n",
+			fsp_str_dbg(fsp), nwritten, n);
+		TALLOC_FREE(ad);
 		return -1;
 	}
+
+	if ((n + offset) > ad_getentrylen(ad, ADEID_RFORK)) {
+		ad_setentrylen(ad, ADEID_RFORK, n + offset);
+		ret = ad_fset(ad, fsp);
+		if (ret != 0) {
+			DBG_ERR("ad_pwrite [%s] failed\n", fsp_str_dbg(fsp));
+			TALLOC_FREE(ad);
+			return -1;
+		}
+	}
+
+	TALLOC_FREE(ad);
 	return n;
 }
 
+static ssize_t fruit_pwrite_rsrc(vfs_handle_struct *handle,
+				 files_struct *fsp, const void *data,
+				 size_t n, off_t offset)
+{
+	struct fio *fio = (struct fio *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+	ssize_t nwritten;
+
+	switch (fio->config->rsrc) {
+	case FRUIT_RSRC_STREAM:
+		nwritten = fruit_pwrite_rsrc_stream(handle, fsp, data, n, offset);
+		break;
+
+	case FRUIT_RSRC_ADFILE:
+		nwritten = fruit_pwrite_rsrc_adouble(handle, fsp, data, n, offset);
+		break;
+
+	case FRUIT_RSRC_XATTR:
+		nwritten = fruit_pwrite_rsrc_xattr(handle, fsp, data, n, offset);
+		break;
+
+	default:
+		DBG_ERR("Unexpected rsrc config [%d]\n", fio->config->rsrc);
+		return -1;
+	}
+
+	return nwritten;
+}
+
+static ssize_t fruit_pwrite(vfs_handle_struct *handle,
+			    files_struct *fsp, const void *data,
+			    size_t n, off_t offset)
+{
+	struct fio *fio = (struct fio *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+	ssize_t nwritten;
+
+	DBG_DEBUG("Path [%s] offset=%zd, size=%zd\n",
+		  fsp_str_dbg(fsp), offset, n);
+
+	if (fio == NULL) {
+		return SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
+	}
+
+	if (fio->type == ADOUBLE_META) {
+		nwritten = fruit_pwrite_meta(handle, fsp, data, n, offset);
+	} else {
+		nwritten = fruit_pwrite_rsrc(handle, fsp, data, n, offset);
+	}
+
+	DBG_DEBUG("Path [%s] nwritten=%zd\n", fsp_str_dbg(fsp), nwritten);
+	return nwritten;
+}
+
 /**
  * Helper to stat/lstat the base file of an smb_fname.
  */
@@ -2922,9 +3950,24 @@
 	return rc;
 }
 
-static int fruit_stat_meta(vfs_handle_struct *handle,
-			   struct smb_filename *smb_fname,
-			   bool follow_links)
+static int fruit_stat_meta_stream(vfs_handle_struct *handle,
+				  struct smb_filename *smb_fname,
+				  bool follow_links)
+{
+	int ret;
+
+	if (follow_links) {
+		ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
+	} else {
+		ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
+	}
+
+	return ret;
+}
+
+static int fruit_stat_meta_netatalk(vfs_handle_struct *handle,
+				    struct smb_filename *smb_fname,
+				    bool follow_links)
 {
 	struct adouble *ad = NULL;
 
@@ -2947,15 +3990,39 @@
 	return 0;
 }
 
-static int fruit_stat_rsrc(vfs_handle_struct *handle,
+static int fruit_stat_meta(vfs_handle_struct *handle,
 			   struct smb_filename *smb_fname,
 			   bool follow_links)
+{
+	struct fruit_config_data *config = NULL;
+	int ret;
+
+	SMB_VFS_HANDLE_GET_DATA(handle, config,
+				struct fruit_config_data, return -1);
+
+	switch (config->meta) {
+	case FRUIT_META_STREAM:
+		ret = fruit_stat_meta_stream(handle, smb_fname, follow_links);
+		break;
+
+	case FRUIT_META_NETATALK:
+		ret = fruit_stat_meta_netatalk(handle, smb_fname, follow_links);
+		break;
+
+	default:
+		DBG_ERR("Unexpected meta config [%d]\n", config->meta);
+		return -1;
+	}
+
+	return ret;
+}
 
+static int fruit_stat_rsrc_netatalk(vfs_handle_struct *handle,
+				    struct smb_filename *smb_fname,
+				    bool follow_links)
 {
 	struct adouble *ad = NULL;
-
-	DEBUG(10, ("fruit_stat_rsrc called for %s\n",
-		   smb_fname_str_dbg(smb_fname)));
+	int ret;
 
 	ad = ad_get(talloc_tos(), handle, smb_fname->base_name, ADOUBLE_RSRC);
 	if (ad == NULL) {
@@ -2964,7 +4031,8 @@
 	}
 
 	/* Populate the stat struct with info from the base file. */
-	if (fruit_stat_base(handle, smb_fname, follow_links) == -1) {
+	ret = fruit_stat_base(handle, smb_fname, follow_links);
+	if (ret != 0) {
 		TALLOC_FREE(ad);
 		return -1;
 	}
@@ -2976,6 +4044,96 @@
 	return 0;
 }
 
+static int fruit_stat_rsrc_stream(vfs_handle_struct *handle,
+				  struct smb_filename *smb_fname,
+				  bool follow_links)
+{
+	int ret;
+
+	if (follow_links) {
+		ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
+	} else {
+		ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
+	}
+
+	return ret;
+}
+
+static int fruit_stat_rsrc_xattr(vfs_handle_struct *handle,
+				 struct smb_filename *smb_fname,
+				 bool follow_links)
+{
+#ifdef HAVE_ATTROPEN
+	int ret;
+	int fd = -1;
+
+	/* Populate the stat struct with info from the base file. */
+	ret = fruit_stat_base(handle, smb_fname, follow_links);
+	if (ret != 0) {
+		return -1;
+	}
+
+	fd = attropen(smb_fname->base_name,
+		      AFPRESOURCE_EA_NETATALK,
+		      O_RDONLY);
+	if (fd == -1) {
+		return 0;
+	}
+
+	ret = sys_fstat(fd, &smb_fname->st, false);
+	if (ret != 0) {
+		close(fd);
+		DBG_ERR("fstat [%s:%s] failed\n", smb_fname->base_name,
+			AFPRESOURCE_EA_NETATALK);
+		return -1;
+	}
+	close(fd);
+	fd = -1;
+
+	smb_fname->st.st_ex_ino = fruit_inode(&smb_fname->st,
+					      smb_fname->stream_name);
+
+	return ret;
+
+#else
+	errno = ENOSYS;
+	return -1;
+#endif
+}
+
+static int fruit_stat_rsrc(vfs_handle_struct *handle,
+			   struct smb_filename *smb_fname,
+			   bool follow_links)
+{
+	struct fruit_config_data *config = NULL;
+	int ret;
+
+	DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname));
+
+	SMB_VFS_HANDLE_GET_DATA(handle, config,
+				struct fruit_config_data, return -1);
+
+	switch (config->rsrc) {
+	case FRUIT_RSRC_STREAM:
+		ret = fruit_stat_rsrc_stream(handle, smb_fname, follow_links);
+		break;
+
+	case FRUIT_RSRC_XATTR:
+		ret = fruit_stat_rsrc_xattr(handle, smb_fname, follow_links);
+		break;
+
+	case FRUIT_RSRC_ADFILE:
+		ret = fruit_stat_rsrc_netatalk(handle, smb_fname, follow_links);
+		break;
+
+	default:
+		DBG_ERR("Unexpected rsrc config [%d]\n", config->rsrc);
+		return -1;
+	}
+
+	return ret;
+}
+
 static int fruit_stat(vfs_handle_struct *handle,
 		      struct smb_filename *smb_fname)
 {
@@ -3053,17 +4211,24 @@
 	return rc;
 }
 
-static int fruit_fstat_meta(vfs_handle_struct *handle,
-			    files_struct *fsp,
-			    SMB_STRUCT_STAT *sbuf)
+static int fruit_fstat_meta_stream(vfs_handle_struct *handle,
+				   files_struct *fsp,
+				   SMB_STRUCT_STAT *sbuf)
+{
+	return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
+}
+
+static int fruit_fstat_meta_netatalk(vfs_handle_struct *handle,
+				     files_struct *fsp,
+				     SMB_STRUCT_STAT *sbuf)
 {
-	DEBUG(10, ("fruit_fstat_meta called for %s\n",
-		   smb_fname_str_dbg(fsp->base_fsp->fsp_name)));
+	int ret;
 
-	/* Populate the stat struct with info from the base file. */
-	if (fruit_stat_base(handle, fsp->base_fsp->fsp_name, false) == -1) {
+	ret = fruit_stat_base(handle, fsp->base_fsp->fsp_name, false);
+	if (ret != 0) {
 		return -1;
 	}
+
 	*sbuf = fsp->base_fsp->fsp_name->st;
 	sbuf->st_ex_size = AFP_INFO_SIZE;
 	sbuf->st_ex_ino = fruit_inode(sbuf, fsp->fsp_name->stream_name);
@@ -3071,113 +4236,418 @@
 	return 0;
 }
 
-static int fruit_fstat_rsrc(vfs_handle_struct *handle, files_struct *fsp,
-			    SMB_STRUCT_STAT *sbuf)
+static int fruit_fstat_meta(vfs_handle_struct *handle,
+			    files_struct *fsp,
+			    SMB_STRUCT_STAT *sbuf,
+			    struct fio *fio)
 {
-	struct fruit_config_data *config;
-	struct adouble *ad = (struct adouble *)VFS_FETCH_FSP_EXTENSION(
-		handle, fsp);
+	int ret;
 
-	DEBUG(10, ("fruit_fstat_rsrc called for %s\n",
-		   smb_fname_str_dbg(fsp->base_fsp->fsp_name)));
+	DBG_DEBUG("Path [%s]\n", fsp_str_dbg(fsp));
 
-	SMB_VFS_HANDLE_GET_DATA(handle, config,
-				struct fruit_config_data, return -1);
+	switch (fio->config->meta) {
+	case FRUIT_META_STREAM:
+		ret = fruit_fstat_meta_stream(handle, fsp, sbuf);
+		break;
 
-	if (config->rsrc == FRUIT_RSRC_STREAM) {
-		return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
+	case FRUIT_META_NETATALK:
+		ret = fruit_fstat_meta_netatalk(handle, fsp, sbuf);
+		break;
+
+	default:
+		DBG_ERR("Unexpected meta config [%d]\n", fio->config->meta);
+		return -1;
 	}
 
+	DBG_DEBUG("Path [%s] ret [%d]\n", fsp_str_dbg(fsp), ret);
+	return ret;
+}
+
+static int fruit_fstat_rsrc_xattr(vfs_handle_struct *handle,
+				  files_struct *fsp,
+				  SMB_STRUCT_STAT *sbuf)
+{
+	return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
+}
+
+static int fruit_fstat_rsrc_stream(vfs_handle_struct *handle,
+				   files_struct *fsp,
+				   SMB_STRUCT_STAT *sbuf)
+{
+	return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
+}
+
+static int fruit_fstat_rsrc_adouble(vfs_handle_struct *handle,
+				    files_struct *fsp,
+				    SMB_STRUCT_STAT *sbuf)
+{
+	struct adouble *ad = NULL;
+	int ret;
+
 	/* Populate the stat struct with info from the base file. */
-	if (fruit_stat_base(handle, fsp->base_fsp->fsp_name, false) == -1) {
+	ret = fruit_stat_base(handle, fsp->base_fsp->fsp_name, false);
+	if (ret == -1) {
+		return -1;
+	}
+
+	ad = ad_get(talloc_tos(), handle,
+		    fsp->base_fsp->fsp_name->base_name,
+		    ADOUBLE_RSRC);
+	if (ad == NULL) {
+		DBG_ERR("ad_get [%s] failed [%s]\n",
+			fsp_str_dbg(fsp), strerror(errno));
 		return -1;
 	}
+
 	*sbuf = fsp->base_fsp->fsp_name->st;
 	sbuf->st_ex_size = ad_getentrylen(ad, ADEID_RFORK);
 	sbuf->st_ex_ino = fruit_inode(sbuf, fsp->fsp_name->stream_name);
 
-	DEBUG(10, ("fruit_fstat_rsrc %s, size: %zd\n",
-		   smb_fname_str_dbg(fsp->fsp_name),
-		   (ssize_t)sbuf->st_ex_size));
-
+	TALLOC_FREE(ad);
 	return 0;
 }
 
+static int fruit_fstat_rsrc(vfs_handle_struct *handle, files_struct *fsp,
+			    SMB_STRUCT_STAT *sbuf, struct fio *fio)
+{
+	int ret;
+
+	switch (fio->config->rsrc) {
+	case FRUIT_RSRC_STREAM:
+		ret = fruit_fstat_rsrc_stream(handle, fsp, sbuf);
+		break;
+
+	case FRUIT_RSRC_ADFILE:
+		ret = fruit_fstat_rsrc_adouble(handle, fsp, sbuf);
+		break;
+
+	case FRUIT_RSRC_XATTR:
+		ret = fruit_fstat_rsrc_xattr(handle, fsp, sbuf);
+		break;
+
+	default:
+		DBG_ERR("Unexpected rsrc config [%d]\n", fio->config->rsrc);
+		return -1;
+	}
+
+	return ret;
+}
+
 static int fruit_fstat(vfs_handle_struct *handle, files_struct *fsp,
 		       SMB_STRUCT_STAT *sbuf)
 {
+	struct fio *fio = (struct fio *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
 	int rc;
-	char *name = NULL;
-	char *tmp_base_name = NULL;
-	NTSTATUS status;
-	struct adouble *ad = (struct adouble *)
-		VFS_FETCH_FSP_EXTENSION(handle, fsp);
 
-	DEBUG(10, ("fruit_fstat called for %s\n",
-		   smb_fname_str_dbg(fsp->fsp_name)));
+	if (fio == NULL) {
+		return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
+	}
 
-	if (fsp->base_fsp) {
-		tmp_base_name = fsp->base_fsp->fsp_name->base_name;
-		/* fsp_name is not converted with vfs_catia */
-		status = SMB_VFS_TRANSLATE_NAME(
-			handle->conn,
-			fsp->base_fsp->fsp_name->base_name,
-			vfs_translate_to_unix,
-			talloc_tos(), &name);
-
-		if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
-			name = talloc_strdup(talloc_tos(), tmp_base_name);
-			if (name == NULL) {
-				rc = -1;
-				goto exit;
-			}
-		} else if (!NT_STATUS_IS_OK(status)) {
-			errno = map_errno_from_nt_status(status);
-			rc = -1;
-			goto exit;
+	DBG_DEBUG("Path [%s]\n", fsp_str_dbg(fsp));
+
+	if (fio->type == ADOUBLE_META) {
+		rc = fruit_fstat_meta(handle, fsp, sbuf, fio);
+	} else {
+		rc = fruit_fstat_rsrc(handle, fsp, sbuf, fio);
+	}
+
+	if (rc == 0) {
+		sbuf->st_ex_mode &= ~S_IFMT;
+		sbuf->st_ex_mode |= S_IFREG;
+		sbuf->st_ex_blocks = sbuf->st_ex_size / STAT_ST_BLOCKSIZE + 1;
+	}
+
+	DBG_DEBUG("Path [%s] rc [%d] size [%zd]\n",
+		  fsp_str_dbg(fsp), rc, sbuf->st_ex_size);
+	return rc;
+}
+
+static NTSTATUS fruit_streaminfo_meta_stream(
+	vfs_handle_struct *handle,
+	struct files_struct *fsp,
+	const struct smb_filename *smb_fname,
+	TALLOC_CTX *mem_ctx,
+	unsigned int *pnum_streams,
+	struct stream_struct **pstreams)
+{
+	struct stream_struct *stream = *pstreams;
+	unsigned int num_streams = *pnum_streams;
+	struct smb_filename *sname = NULL;
+	int i;
+	int ret;
+	bool ok;
+
+	for (i = 0; i < num_streams; i++) {
+		if (strequal_m(stream[i].name, AFPINFO_STREAM)) {
+			break;
 		}
-		fsp->base_fsp->fsp_name->base_name = name;
 	}
 
-	if (ad == NULL || fsp->base_fsp == NULL) {
-		rc = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
-		goto exit;
+	if (i == num_streams) {
+		return NT_STATUS_OK;
 	}
 
-	if (!fruit_fsp_recheck(ad, fsp)) {
-		rc = -1;
-		goto exit;
+	if (stream[i].size == AFP_INFO_SIZE) {
+		return NT_STATUS_OK;
 	}
 
-	switch (ad->ad_type) {
-	case ADOUBLE_META:
-		rc = fruit_fstat_meta(handle, fsp, sbuf);
+	DBG_ERR("Removing invalid AFPINFO_STREAM size [%zd] from [%s]\n",
+		stream[i].size, smb_fname_str_dbg(smb_fname));
+
+	ok = del_fruit_stream(mem_ctx, pnum_streams, pstreams, AFPINFO_STREAM);
+	if (!ok) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	sname = synthetic_smb_fname(talloc_tos(),
+				    smb_fname->base_name,
+				    AFPINFO_STREAM_NAME,
+				    NULL, 0);
+	if (sname == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	ret = SMB_VFS_NEXT_UNLINK(handle, sname);
+	TALLOC_FREE(sname);
+	if (ret != 0) {
+		DBG_ERR("Removing [%s] failed\n", smb_fname_str_dbg(sname));
+		return map_nt_error_from_unix(errno);
+	}
+
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS fruit_streaminfo_meta_netatalk(
+	vfs_handle_struct *handle,
+	struct files_struct *fsp,
+	const struct smb_filename *smb_fname,
+	TALLOC_CTX *mem_ctx,
+	unsigned int *pnum_streams,
+	struct stream_struct **pstreams)
+{
+	struct stream_struct *stream = *pstreams;
+	unsigned int num_streams = *pnum_streams;
+	struct adouble *ad = NULL;
+	bool is_fi_empty;
+	int i;
+	bool ok;
+
+	/* Remove the Netatalk xattr from the list */
+	ok = del_fruit_stream(mem_ctx, pnum_streams, pstreams,
+			      ":" NETATALK_META_XATTR ":$DATA");
+	if (!ok) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	/*
+	 * Check if there's a AFPINFO_STREAM from the VFS streams
+	 * backend and if yes, remove it from the list
+	 */
+	for (i = 0; i < num_streams; i++) {
+		if (strequal_m(stream[i].name, AFPINFO_STREAM)) {
+			break;
+		}
+	}
+
+	if (i < num_streams) {
+		DBG_WARNING("Unexpected AFPINFO_STREAM on [%s]\n",
+			    smb_fname_str_dbg(smb_fname));
+
+		ok = del_fruit_stream(mem_ctx, pnum_streams, pstreams,
+				      AFPINFO_STREAM);
+		if (!ok) {
+			return NT_STATUS_INTERNAL_ERROR;
+		}
+	}
+
+	ad = ad_get(talloc_tos(), handle,
+		    smb_fname->base_name, ADOUBLE_META);
+	if (ad == NULL) {
+		return NT_STATUS_OK;
+	}
+
+	is_fi_empty = ad_empty_finderinfo(ad);
+	TALLOC_FREE(ad);
+
+	if (is_fi_empty) {
+		return NT_STATUS_OK;
+	}
+
+	ok = add_fruit_stream(mem_ctx, pnum_streams, pstreams,
+			      AFPINFO_STREAM_NAME, AFP_INFO_SIZE,
+			      smb_roundup(handle->conn, AFP_INFO_SIZE));
+	if (!ok) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS fruit_streaminfo_meta(vfs_handle_struct *handle,
+				      struct files_struct *fsp,
+				      const struct smb_filename *smb_fname,
+				      TALLOC_CTX *mem_ctx,
+				      unsigned int *pnum_streams,
+				      struct stream_struct **pstreams)
+{
+	struct fruit_config_data *config = NULL;
+	NTSTATUS status;
+
+	SMB_VFS_HANDLE_GET_DATA(handle, config, struct fruit_config_data,
+				return NT_STATUS_INTERNAL_ERROR);
+
+	switch (config->meta) {
+	case FRUIT_META_NETATALK:
+		status = fruit_streaminfo_meta_netatalk(handle, fsp, smb_fname,
+							mem_ctx, pnum_streams,
+							pstreams);
 		break;
-	case ADOUBLE_RSRC:
-		rc = fruit_fstat_rsrc(handle, fsp, sbuf);
+
+	case FRUIT_META_STREAM:
+		status = fruit_streaminfo_meta_stream(handle, fsp, smb_fname,
+						      mem_ctx, pnum_streams,
+						      pstreams);
 		break;
+
 	default:
-		DEBUG(10, ("fruit_fstat %s: bad type\n",
-			   smb_fname_str_dbg(fsp->fsp_name)));
-		rc = -1;
-		goto exit;
+		return NT_STATUS_INTERNAL_ERROR;
 	}
 
-	if (rc == 0) {
-		sbuf->st_ex_mode &= ~S_IFMT;
-		sbuf->st_ex_mode |= S_IFREG;
-		sbuf->st_ex_blocks = sbuf->st_ex_size / STAT_ST_BLOCKSIZE + 1;
+	return status;
+}
+
+static NTSTATUS fruit_streaminfo_rsrc_stream(
+	vfs_handle_struct *handle,
+	struct files_struct *fsp,
+	const struct smb_filename *smb_fname,
+	TALLOC_CTX *mem_ctx,
+	unsigned int *pnum_streams,
+	struct stream_struct **pstreams)
+{
+	bool ok;
+
+	ok = filter_empty_rsrc_stream(pnum_streams, pstreams);
+	if (!ok) {
+		DBG_ERR("Filtering resource stream failed\n");
+		return NT_STATUS_INTERNAL_ERROR;
 	}
+	return NT_STATUS_OK;
+}
 
-exit:
-	DEBUG(10, ("fruit_fstat %s, size: %zd\n",
-		   smb_fname_str_dbg(fsp->fsp_name),
-		   (ssize_t)sbuf->st_ex_size));
-	if (tmp_base_name) {
-		fsp->base_fsp->fsp_name->base_name = tmp_base_name;
+static NTSTATUS fruit_streaminfo_rsrc_xattr(
+	vfs_handle_struct *handle,
+	struct files_struct *fsp,
+	const struct smb_filename *smb_fname,
+	TALLOC_CTX *mem_ctx,
+	unsigned int *pnum_streams,
+	struct stream_struct **pstreams)
+{
+	bool ok;
+
+	ok = filter_empty_rsrc_stream(pnum_streams, pstreams);
+	if (!ok) {
+		DBG_ERR("Filtering resource stream failed\n");
+		return NT_STATUS_INTERNAL_ERROR;
 	}
-	TALLOC_FREE(name);
-	return rc;
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS fruit_streaminfo_rsrc_adouble(
+	vfs_handle_struct *handle,
+	struct files_struct *fsp,
+	const struct smb_filename *smb_fname,
+	TALLOC_CTX *mem_ctx,
+	unsigned int *pnum_streams,
+	struct stream_struct **pstreams)
+{
+	struct stream_struct *stream = *pstreams;
+	unsigned int num_streams = *pnum_streams;
+	struct adouble *ad = NULL;
+	bool ok;
+	size_t rlen;
+	int i;
+
+	/*
+	 * Check if there's a AFPRESOURCE_STREAM from the VFS streams backend
+	 * and if yes, remove it from the list
+	 */
+	for (i = 0; i < num_streams; i++) {
+		if (strequal_m(stream[i].name, AFPRESOURCE_STREAM)) {
+			break;
+		}
+	}
+
+	if (i < num_streams) {
+		DBG_WARNING("Unexpected AFPRESOURCE_STREAM on [%s]\n",
+			    smb_fname_str_dbg(smb_fname));
+
+		ok = del_fruit_stream(mem_ctx, pnum_streams, pstreams,
+				      AFPRESOURCE_STREAM);
+		if (!ok) {
+			return NT_STATUS_INTERNAL_ERROR;
+		}
+	}
+
+	ad = ad_get(talloc_tos(), handle, smb_fname->base_name,
+		    ADOUBLE_RSRC);
+	if (ad == NULL) {
+		return NT_STATUS_OK;
+	}
+
+	rlen = ad_getentrylen(ad, ADEID_RFORK);
+	TALLOC_FREE(ad);
+
+	if (rlen == 0) {
+		return NT_STATUS_OK;
+	}
+
+	ok = add_fruit_stream(mem_ctx, pnum_streams, pstreams,
+			      AFPRESOURCE_STREAM_NAME, rlen,
+			      smb_roundup(handle->conn, rlen));
+	if (!ok) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS fruit_streaminfo_rsrc(vfs_handle_struct *handle,
+				      struct files_struct *fsp,
+				      const struct smb_filename *smb_fname,
+				      TALLOC_CTX *mem_ctx,
+				      unsigned int *pnum_streams,
+				      struct stream_struct **pstreams)
+{
+	struct fruit_config_data *config = NULL;
+	NTSTATUS status;
+
+	SMB_VFS_HANDLE_GET_DATA(handle, config, struct fruit_config_data,
+				return NT_STATUS_INTERNAL_ERROR);
+
+	switch (config->rsrc) {
+	case FRUIT_RSRC_STREAM:
+		status = fruit_streaminfo_rsrc_stream(handle, fsp, smb_fname,
+						      mem_ctx, pnum_streams,
+						      pstreams);
+		break;
+
+	case FRUIT_RSRC_XATTR:
+		status = fruit_streaminfo_rsrc_xattr(handle, fsp, smb_fname,
+						     mem_ctx, pnum_streams,
+						     pstreams);
+		break;
+
+	case FRUIT_RSRC_ADFILE:
+		status = fruit_streaminfo_rsrc_adouble(handle, fsp, smb_fname,
+						       mem_ctx, pnum_streams,
+						       pstreams);
+		break;
+
+	default:
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	return status;
 }
 
 static NTSTATUS fruit_streaminfo(vfs_handle_struct *handle,
@@ -3188,46 +4658,12 @@
 				 struct stream_struct **pstreams)
 {
 	struct fruit_config_data *config = NULL;
-	struct adouble *ad = NULL;
 	NTSTATUS status;
 
 	SMB_VFS_HANDLE_GET_DATA(handle, config, struct fruit_config_data,
 				return NT_STATUS_UNSUCCESSFUL);
-	DEBUG(10, ("fruit_streaminfo called for %s\n", smb_fname->base_name));
-
-	if (config->meta == FRUIT_META_NETATALK) {
-		ad = ad_get(talloc_tos(), handle,
-			    smb_fname->base_name, ADOUBLE_META);
-		if (ad && !empty_finderinfo(ad)) {
-			if (!add_fruit_stream(
-				    mem_ctx, pnum_streams, pstreams,
-				    AFPINFO_STREAM_NAME, AFP_INFO_SIZE,
-				    smb_roundup(handle->conn,
-						AFP_INFO_SIZE))) {
-				TALLOC_FREE(ad);
-				return NT_STATUS_NO_MEMORY;
-			}
-		}
-		TALLOC_FREE(ad);
-	}
 
-	if (config->rsrc != FRUIT_RSRC_STREAM) {
-		ad = ad_get(talloc_tos(), handle, smb_fname->base_name,
-			    ADOUBLE_RSRC);
-		if (ad && (ad_getentrylen(ad, ADEID_RFORK) > 0)) {
-			if (!add_fruit_stream(
-				    mem_ctx, pnum_streams, pstreams,
-				    AFPRESOURCE_STREAM_NAME,
-				    ad_getentrylen(ad, ADEID_RFORK),
-				    smb_roundup(handle->conn,
-						ad_getentrylen(
-							ad, ADEID_RFORK)))) {
-				TALLOC_FREE(ad);
-				return NT_STATUS_NO_MEMORY;
-			}
-		}
-		TALLOC_FREE(ad);
-	}
+	DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname));
 
 	status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, smb_fname, mem_ctx,
 					 pnum_streams, pstreams);
@@ -3235,13 +4671,16 @@
 		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);
-				return NT_STATUS_NO_MEMORY;
-		}
+	status = fruit_streaminfo_meta(handle, fsp, smb_fname,
+				       mem_ctx, pnum_streams, pstreams);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	status = fruit_streaminfo_rsrc(handle, fsp, smb_fname,
+				       mem_ctx, pnum_streams, pstreams);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
 	}
 
 	return NT_STATUS_OK;
@@ -3253,9 +4692,15 @@
 {
 	int rc = 0;
 	struct adouble *ad = NULL;
+	struct fruit_config_data *config = NULL;
 
-	if (null_timespec(ft->create_time)) {
-		goto exit;
+	SMB_VFS_HANDLE_GET_DATA(handle, config, struct fruit_config_data,
+				return -1);
+
+	if ((config->meta != FRUIT_META_NETATALK) ||
+	    null_timespec(ft->create_time))
+	{
+		return SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft);
 	}
 
 	DEBUG(10,("set btime for %s to %s\n", smb_fname_str_dbg(smb_fname),
@@ -3269,7 +4714,7 @@
 	ad_setdate(ad, AD_DATE_CREATE | AD_DATE_UNIX,
 		   convert_time_t_to_uint32_t(ft->create_time.tv_sec));
 
-	rc = ad_write(ad, smb_fname->base_name);
+	rc = ad_set(ad, smb_fname->base_name);
 
 exit:
 
@@ -3287,79 +4732,123 @@
 			   off_t offset,
 			   off_t len)
 {
-        struct adouble *ad =
-		(struct adouble *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+	struct fio *fio = (struct fio *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
 
-	if (ad == NULL) {
+	if (fio == NULL) {
 		return SMB_VFS_NEXT_FALLOCATE(handle, fsp, mode, offset, len);
 	}
 
-	if (!fruit_fsp_recheck(ad, fsp)) {
-		return -1;
-	}
-
 	/* Let the pwrite code path handle it. */
 	errno = ENOSYS;
 	return -1;
 }
 
-static int fruit_ftruncate_meta(struct vfs_handle_struct *handle,
-				struct files_struct *fsp,
-				off_t offset,
-				struct adouble *ad)
+static int fruit_ftruncate_rsrc_xattr(struct vfs_handle_struct *handle,
+				      struct files_struct *fsp,
+				      off_t offset)
 {
-	struct fruit_config_data *config;
+	if (offset == 0) {
+		return SMB_VFS_FREMOVEXATTR(fsp, AFPRESOURCE_EA_NETATALK);
+	}
 
-	SMB_VFS_HANDLE_GET_DATA(handle, config,
-				struct fruit_config_data, return -1);
+#ifdef HAVE_ATTROPEN
+	return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset);
+#endif
+	return 0;
+}
 
-	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;
+static int fruit_ftruncate_rsrc_adouble(struct vfs_handle_struct *handle,
+					struct files_struct *fsp,
+					off_t offset)
+{
+	int rc;
+	struct adouble *ad = NULL;
+	off_t ad_off;
+
+	ad = ad_fget(talloc_tos(), handle, fsp, ADOUBLE_RSRC);
+	if (ad == NULL) {
+		DBG_DEBUG("ad_get [%s] failed [%s]\n",
+			  fsp_str_dbg(fsp), strerror(errno));
 		return -1;
 	}
 
-	DBG_WARNING("ignoring ftruncate %s to %jd",
-		    fsp_str_dbg(fsp), (intmax_t)offset);
-	/* OS X returns success but does nothing  */
+	ad_off = ad_getentryoff(ad, ADEID_RFORK);
+
+	rc = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset + ad_off);
+	if (rc != 0) {
+		TALLOC_FREE(ad);
+		return -1;
+	}
+
+	ad_setentrylen(ad, ADEID_RFORK, offset);
+
+	rc = ad_fset(ad, fsp);
+	if (rc != 0) {
+		DBG_ERR("ad_fset [%s] failed [%s]\n",
+			fsp_str_dbg(fsp), strerror(errno));
+		TALLOC_FREE(ad);
+		return -1;
+	}
+
+	TALLOC_FREE(ad);
 	return 0;
 }
 
+static int fruit_ftruncate_rsrc_stream(struct vfs_handle_struct *handle,
+				       struct files_struct *fsp,
+				       off_t offset)
+{
+	if (offset == 0) {
+		return SMB_VFS_NEXT_UNLINK(handle, fsp->fsp_name);
+	}
+
+	return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset);
+}
+
 static int fruit_ftruncate_rsrc(struct vfs_handle_struct *handle,
 				struct files_struct *fsp,
-				off_t offset,
-				struct adouble *ad)
+				off_t offset)
 {
-	int rc;
-	struct fruit_config_data *config;
+	struct fio *fio = (struct fio *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+	int ret;
 
-	SMB_VFS_HANDLE_GET_DATA(handle, config,
-				struct fruit_config_data, return -1);
+	switch (fio->config->rsrc) {
+	case FRUIT_RSRC_XATTR:
+		ret = fruit_ftruncate_rsrc_xattr(handle, fsp, offset);
+		break;
 
-	if (config->rsrc == FRUIT_RSRC_XATTR && offset == 0) {
-		return SMB_VFS_FREMOVEXATTR(fsp,
-					    AFPRESOURCE_EA_NETATALK);
-	}
+	case FRUIT_RSRC_ADFILE:
+		ret = fruit_ftruncate_rsrc_adouble(handle, fsp, offset);
+		break;
 
-	rc = SMB_VFS_NEXT_FTRUNCATE(
-		handle, fsp,
-		offset + ad_getentryoff(ad, ADEID_RFORK));
-	if (rc != 0) {
+	case FRUIT_RSRC_STREAM:
+		ret = fruit_ftruncate_rsrc_stream(handle, fsp, offset);
+		break;
+
+	default:
+		DBG_ERR("Unexpected rsrc config [%d]\n", fio->config->rsrc);
 		return -1;
 	}
 
-	if (config->rsrc == FRUIT_RSRC_ADFILE) {
-		ad_setentrylen(ad, ADEID_RFORK, offset);
-		rc = ad_write(ad, NULL);
-		if (rc != 0) {
-			return -1;
-		}
-		DEBUG(10, ("fruit_ftruncate_rsrc file %s offset %jd\n",
-			   fsp_str_dbg(fsp), (intmax_t)offset));
+
+	return ret;
+}
+
+static int fruit_ftruncate_meta(struct vfs_handle_struct *handle,
+				struct files_struct *fsp,
+				off_t offset)
+{
+	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;
 	}
 
+	/* OS X returns success but does nothing  */
+	DBG_INFO("ignoring ftruncate %s to %jd\n",
+		 fsp_str_dbg(fsp), (intmax_t)offset);
 	return 0;
 }
 
@@ -3367,35 +4856,23 @@
 			   struct files_struct *fsp,
 			   off_t offset)
 {
-	int rc = 0;
-        struct adouble *ad =
-		(struct adouble *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+	struct fio *fio = (struct fio *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+	int ret;
 
-	DBG_DEBUG("fruit_ftruncate called for file %s offset %.0f\n",
-		   fsp_str_dbg(fsp), (double)offset);
+	DBG_DEBUG("Path [%s] offset [%zd]\n", fsp_str_dbg(fsp), offset);
 
-	if (ad == NULL) {
+	if (fio == NULL) {
 		return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset);
 	}
 
-	if (!fruit_fsp_recheck(ad, fsp)) {
-		return -1;
-	}
-
-	switch (ad->ad_type) {
-	case ADOUBLE_META:
-		rc = fruit_ftruncate_meta(handle, fsp, offset, ad);
-		break;
-
-	case ADOUBLE_RSRC:
-		rc = fruit_ftruncate_rsrc(handle, fsp, offset, ad);
-		break;
-
-	default:
-		return -1;
+	if (fio->type == ADOUBLE_META) {
+		ret = fruit_ftruncate_meta(handle, fsp, offset);
+	} else {
+		ret = fruit_ftruncate_rsrc(handle, fsp, offset);
 	}
 
-	return rc;
+	DBG_DEBUG("Path [%s] result [%d]\n", fsp_str_dbg(fsp), ret);
+	return ret;
 }
 
 static NTSTATUS fruit_create_file(vfs_handle_struct *handle,
@@ -3445,7 +4922,7 @@
 
 	fsp = *result;
 
-	if (config->nego_aapl) {
+	if (global_fruit_config.nego_aapl) {
 		if (config->copyfile_enabled) {
 			/*
 			 * Set a flag in the fsp. Gets used in
@@ -3522,7 +4999,7 @@
 				struct fruit_config_data,
 				return NT_STATUS_UNSUCCESSFUL);
 
-	if (!config->use_aapl) {
+	if (!global_fruit_config.nego_aapl) {
 		return SMB_VFS_NEXT_READDIR_ATTR(handle, fname, mem_ctx, pattr_data);
 	}
 
diff -Nru samba-4.5.5+dfsg/source3/modules/vfs_shadow_copy2.c samba-4.5.6+dfsg/source3/modules/vfs_shadow_copy2.c
--- samba-4.5.5+dfsg/source3/modules/vfs_shadow_copy2.c	2016-09-13 10:21:35.000000000 +0200
+++ samba-4.5.6+dfsg/source3/modules/vfs_shadow_copy2.c	2017-03-09 10:21:43.000000000 +0100
@@ -35,6 +35,7 @@
 #include "system/filesys.h"
 #include "include/ntioctl.h"
 #include "util_tdb.h"
+#include "lib/util_path.h"
 
 struct shadow_copy2_config {
 	char *gmt_format;
@@ -74,6 +75,11 @@
 struct shadow_copy2_private {
 	struct shadow_copy2_config *config;
 	struct shadow_copy2_snaplist_info *snaps;
+	char *shadow_cwd; /* Absolute $cwd path. */
+	/* Absolute connectpath - can vary depending on $cwd. */
+	char *shadow_connectpath;
+	/* malloc'ed realpath return. */
+	char *shadow_realpath;
 };
 
 static int shadow_copy2_get_shadow_copy_data(
@@ -404,79 +410,254 @@
 	return result;
 }
 
+static char *make_path_absolute(TALLOC_CTX *mem_ctx,
+				struct shadow_copy2_private *priv,
+				const char *name)
+{
+	char *newpath = NULL;
+	char *abs_path = NULL;
+
+	if (name[0] != '/') {
+		newpath = talloc_asprintf(mem_ctx,
+					"%s/%s",
+					priv->shadow_cwd,
+					name);
+		if (newpath == NULL) {
+			return NULL;
+		}
+		name = newpath;
+	}
+	abs_path = canonicalize_absolute_path(mem_ctx, name);
+	TALLOC_FREE(newpath);
+	return abs_path;
+}
+
+/* Return a $cwd-relative path. */
+static bool make_relative_path(const char *cwd, char *abs_path)
+{
+	size_t cwd_len = strlen(cwd);
+	size_t abs_len = strlen(abs_path);
+
+	if (abs_len < cwd_len) {
+		return false;
+	}
+	if (memcmp(abs_path, cwd, cwd_len) != 0) {
+		return false;
+	}
+	if (abs_path[cwd_len] != '/' && abs_path[cwd_len] != '\0') {
+		return false;
+	}
+	if (abs_path[cwd_len] == '/') {
+		cwd_len++;
+	}
+	memmove(abs_path, &abs_path[cwd_len], abs_len + 1 - cwd_len);
+	return true;
+}
+
+static bool shadow_copy2_snapshot_to_gmt(vfs_handle_struct *handle,
+					const char *name,
+					char *gmt, size_t gmt_len);
+
+/*
+ * Check if an incoming filename is already a snapshot converted pathname.
+ *
+ * If so, it returns the pathname truncated at the snapshot point which
+ * will be used as the connectpath.
+ */
+
+static int check_for_converted_path(TALLOC_CTX *mem_ctx,
+				struct vfs_handle_struct *handle,
+				struct shadow_copy2_private *priv,
+				char *abs_path,
+				bool *ppath_already_converted,
+				char **pconnectpath)
+{
+	size_t snapdirlen = 0;
+	char *p = strstr_m(abs_path, priv->config->snapdir);
+	char *q = NULL;
+	char *connect_path = NULL;
+	char snapshot[GMT_NAME_LEN+1];
+
+	*ppath_already_converted = false;
+
+	if (p == NULL) {
+		/* Must at least contain shadow:snapdir. */
+		return 0;
+	}
+
+	if (priv->config->snapdir[0] == '/' &&
+			p != abs_path) {
+		/* Absolute shadow:snapdir must be at the start. */
+		return 0;
+	}
+
+	snapdirlen = strlen(priv->config->snapdir);
+	if (p[snapdirlen] != '/') {
+		/* shadow:snapdir must end as a separate component. */
+		return 0;
+	}
+
+	if (p > abs_path && p[-1] != '/') {
+		/* shadow:snapdir must start as a separate component. */
+		return 0;
+	}
+
+	p += snapdirlen;
+	p++; /* Move past the / */
+
+	/*
+	 * Need to return up to the next path
+	 * component after the time.
+	 * This will be used as the connectpath.
+	 */
+	q = strchr(p, '/');
+	if (q == NULL) {
+		/*
+		 * No next path component.
+		 * Use entire string.
+		 */
+		connect_path = talloc_strdup(mem_ctx,
+					abs_path);
+	} else {
+		connect_path = talloc_strndup(mem_ctx,
+					abs_path,
+					q - abs_path);
+	}
+	if (connect_path == NULL) {
+		return ENOMEM;
+	}
+
+	/*
+	 * Point p at the same offset in connect_path as
+	 * it is in abs_path.
+	 */
+
+	p = &connect_path[p - abs_path];
+
+	/*
+	 * Now ensure there is a time string at p.
+	 * The SMB-format @GMT-token string is returned
+	 * in snapshot.
+	 */
+
+	if (!shadow_copy2_snapshot_to_gmt(handle,
+				p,
+				snapshot,
+				sizeof(snapshot))) {
+		TALLOC_FREE(connect_path);
+		return 0;
+	}
+
+	if (pconnectpath != NULL) {
+		*pconnectpath = connect_path;
+	}
+
+	*ppath_already_converted = true;
+
+	DBG_DEBUG("path |%s| is already converted. "
+		"connect path = |%s|\n",
+		abs_path,
+		connect_path);
+
+	return 0;
+}
+
 /**
- * Strip a snapshot component from a filename as
- * handed in via the smb layer.
- * Returns the parsed timestamp and the stripped filename.
+ * This function does two things.
+ *
+ * 1). Checks if an incoming filename is already a
+ * snapshot converted pathname.
+ *     If so, it returns the pathname truncated
+ *     at the snapshot point which will be used
+ *     as the connectpath, and then does an early return.
+ *
+ * 2). Checks if an incoming filename contains an
+ * SMB-layer @GMT- style timestamp.
+ *     If so, it strips the timestamp, and returns
+ *     both the timestamp and the stripped path
+ *     (making it cwd-relative).
  */
-static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx,
+
+static bool shadow_copy2_strip_snapshot_internal(TALLOC_CTX *mem_ctx,
 					struct vfs_handle_struct *handle,
-					const char *name,
+					const char *orig_name,
 					time_t *ptimestamp,
-					char **pstripped)
+					char **pstripped,
+					char **psnappath)
 {
 	struct tm tm;
-	time_t timestamp;
+	time_t timestamp = 0;
 	const char *p;
 	char *q;
-	char *stripped;
+	char *stripped = NULL;
 	size_t rest_len, dst_len;
 	struct shadow_copy2_private *priv;
-	const char *snapdir;
-	ssize_t snapdirlen;
 	ptrdiff_t len_before_gmt;
+	const char *name = orig_name;
+	char *abs_path = NULL;
+	bool ret = true;
+	bool already_converted = false;
+	int err = 0;
 
 	SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
 				return false);
 
 	DEBUG(10, (__location__ ": enter path '%s'\n", name));
 
+	abs_path = make_path_absolute(mem_ctx, priv, name);
+	if (abs_path == NULL) {
+		ret = false;
+		goto out;
+	}
+	name = abs_path;
+
+	DEBUG(10, (__location__ ": abs path '%s'\n", name));
+
+	err = check_for_converted_path(mem_ctx,
+					handle,
+					priv,
+					abs_path,
+					&already_converted,
+					psnappath);
+	if (err != 0) {
+		/* error in conversion. */
+		ret = false;
+		goto out;
+	}
+
+	if (already_converted) {
+		goto out;
+	}
+
+	/*
+	 * From here we're only looking to strip an
+	 * SMB-layer @GMT- token.
+	 */
+
 	p = strstr_m(name, "@GMT-");
 	if (p == NULL) {
 		DEBUG(11, ("@GMT not found\n"));
-		goto no_snapshot;
+		goto out;
 	}
 	if ((p > name) && (p[-1] != '/')) {
 		/* the GMT-token does not start a path-component */
 		DEBUG(10, ("not at start, p=%p, name=%p, p[-1]=%d\n",
 			   p, name, (int)p[-1]));
-		goto no_snapshot;
+		goto out;
 	}
 
-	/*
-	 * Figure out whether we got an already converted string. One
-	 * case where this happens is in a smb2 create call with the
-	 * mxac create blob set. We do the get_acl call on
-	 * fsp->fsp_name, which is already converted. We are converted
-	 * if we got a file name of the form ".snapshots/@GMT-",
-	 * i.e. ".snapshots/" precedes "p".
-	 */
-
-	snapdir = lp_parm_const_string(SNUM(handle->conn), "shadow", "snapdir",
-				       ".snapshots");
-	snapdirlen = strlen(snapdir);
 	len_before_gmt = p - name;
 
-	if ((len_before_gmt >= (snapdirlen + 1)) && (p[-1] == '/')) {
-		const char *parent_snapdir = p - (snapdirlen+1);
-
-		DEBUG(10, ("parent_snapdir = %s\n", parent_snapdir));
-
-		if (strncmp(parent_snapdir, snapdir, snapdirlen) == 0) {
-			DEBUG(10, ("name=%s is already converted\n", name));
-			goto no_snapshot;
-		}
-	}
 	q = strptime(p, GMT_FORMAT, &tm);
 	if (q == NULL) {
 		DEBUG(10, ("strptime failed\n"));
-		goto no_snapshot;
+		goto out;
 	}
 	tm.tm_isdst = -1;
 	timestamp = timegm(&tm);
 	if (timestamp == (time_t)-1) {
 		DEBUG(10, ("timestamp==-1\n"));
-		goto no_snapshot;
+		goto out;
 	}
 	if (q[0] == '\0') {
 		/*
@@ -496,12 +677,24 @@
 			stripped = talloc_strndup(mem_ctx, name,
 					len_before_gmt);
 			if (stripped == NULL) {
-				return false;
+				ret = false;
+				goto out;
+			}
+			if (orig_name[0] != '/') {
+				if (make_relative_path(priv->shadow_cwd,
+						stripped) == false) {
+					DEBUG(10, (__location__ ": path '%s' "
+						"doesn't start with cwd '%s\n",
+						stripped, priv->shadow_cwd));
+						ret = false;
+					errno = ENOENT;
+					goto out;
+				}
 			}
 			*pstripped = stripped;
 		}
 		*ptimestamp = timestamp;
-		return true;
+		goto out;
 	}
 	if (q[0] != '/') {
 		/*
@@ -509,75 +702,18 @@
 		 * component continues after the gmt-token.
 		 */
 		DEBUG(10, ("q[0] = %d\n", (int)q[0]));
-		goto no_snapshot;
+		goto out;
 	}
 	q += 1;
 
 	rest_len = strlen(q);
 	dst_len = len_before_gmt + rest_len;
 
-	if (priv->config->snapdirseverywhere) {
-		char *insert;
-		bool have_insert;
-		insert = shadow_copy2_insert_string(talloc_tos(), handle,
-						    timestamp);
-		if (insert == NULL) {
-			errno = ENOMEM;
-			return false;
-		}
-
-		DEBUG(10, (__location__ ": snapdirseverywhere mode.\n"
-			   "path '%s'.\n"
-			   "insert string '%s'\n", name, insert));
-
-		have_insert = (strstr(name, insert+1) != NULL);
-		DEBUG(10, ("have_insert=%d, name=%s, insert+1=%s\n",
-			   (int)have_insert, name, insert+1));
-		if (have_insert) {
-			DEBUG(10, (__location__ ": insert string '%s' found in "
-				   "path '%s' found in snapdirseverywhere mode "
-				   "==> already converted\n", insert, name));
-			TALLOC_FREE(insert);
-			goto no_snapshot;
-		}
-		TALLOC_FREE(insert);
-	} else {
-		char *snapshot_path;
-		char *s;
-
-		snapshot_path = shadow_copy2_snapshot_path(talloc_tos(),
-							   handle,
-							   timestamp);
-		if (snapshot_path == NULL) {
-			errno = ENOMEM;
-			return false;
-		}
-
-		DEBUG(10, (__location__ " path: '%s'.\n"
-			   "snapshot path: '%s'\n", name, snapshot_path));
-
-		s = strstr(name, snapshot_path);
-		if (s == name) {
-			/*
-			 * this starts with "snapshot_basepath/GMT-Token"
-			 * so it is already a converted absolute
-			 * path. Don't process further.
-			 */
-			DEBUG(10, (__location__ ": path '%s' starts with "
-				   "snapshot path '%s' (not in "
-				   "snapdirseverywhere mode) ==> "
-				   "already converted\n", name, snapshot_path));
-			talloc_free(snapshot_path);
-			goto no_snapshot;
-		}
-		talloc_free(snapshot_path);
-	}
-
 	if (pstripped != NULL) {
 		stripped = talloc_array(mem_ctx, char, dst_len+1);
 		if (stripped == NULL) {
-			errno = ENOMEM;
-			return false;
+			ret = false;
+			goto out;
 		}
 		if (p > name) {
 			memcpy(stripped, name, len_before_gmt);
@@ -586,13 +722,39 @@
 			memcpy(stripped + len_before_gmt, q, rest_len);
 		}
 		stripped[dst_len] = '\0';
+		if (orig_name[0] != '/') {
+			if (make_relative_path(priv->shadow_cwd,
+					stripped) == false) {
+				DEBUG(10, (__location__ ": path '%s' "
+					"doesn't start with cwd '%s\n",
+					stripped, priv->shadow_cwd));
+				ret = false;
+				errno = ENOENT;
+				goto out;
+			}
+		}
 		*pstripped = stripped;
 	}
 	*ptimestamp = timestamp;
-	return true;
-no_snapshot:
-	*ptimestamp = 0;
-	return true;
+	ret = true;
+
+  out:
+	TALLOC_FREE(abs_path);
+	return ret;
+}
+
+static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx,
+					struct vfs_handle_struct *handle,
+					const char *orig_name,
+					time_t *ptimestamp,
+					char **pstripped)
+{
+	return shadow_copy2_strip_snapshot_internal(mem_ctx,
+					handle,
+					orig_name,
+					ptimestamp,
+					pstripped,
+					NULL);
 }
 
 static char *shadow_copy2_find_mount_point(TALLOC_CTX *mem_ctx,
@@ -646,7 +808,8 @@
 	char *insert = NULL;
 	char *converted = NULL;
 	size_t insertlen, connectlen = 0;
-	int i, saved_errno;
+	int saved_errno = 0;
+	int i;
 	size_t min_offset;
 	struct shadow_copy2_config *config;
 	struct shadow_copy2_private *priv;
@@ -832,12 +995,16 @@
 		errno = ENOENT;
 	}
 fail:
-	saved_errno = errno;
+	if (result == NULL) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(converted);
 	TALLOC_FREE(insert);
 	TALLOC_FREE(slashes);
 	TALLOC_FREE(path);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return result;
 }
 
@@ -893,10 +1060,10 @@
 			const char *mask,
 			uint32_t attr)
 {
-	time_t timestamp;
-	char *stripped;
+	time_t timestamp = 0;
+	char *stripped = NULL;
 	DIR *ret;
-	int saved_errno;
+	int saved_errno = 0;
 	char *conv;
 	struct smb_filename *conv_smb_fname = NULL;
 
@@ -925,10 +1092,14 @@
 		return NULL;
 	}
 	ret = SMB_VFS_NEXT_OPENDIR(handle, conv_smb_fname, mask, attr);
-	saved_errno = errno;
+	if (ret == NULL) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
 	TALLOC_FREE(conv_smb_fname);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
@@ -936,16 +1107,19 @@
 			       const struct smb_filename *smb_fname_src,
 			       const struct smb_filename *smb_fname_dst)
 {
-	time_t timestamp_src, timestamp_dst;
+	time_t timestamp_src = 0;
+	time_t timestamp_dst = 0;
+	char *snappath_src = NULL;
+	char *snappath_dst = NULL;
 
-	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
+	if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle,
 					 smb_fname_src->base_name,
-					 &timestamp_src, NULL)) {
+					 &timestamp_src, NULL, &snappath_src)) {
 		return -1;
 	}
-	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
+	if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle,
 					 smb_fname_dst->base_name,
-					 &timestamp_dst, NULL)) {
+					 &timestamp_dst, NULL, &snappath_dst)) {
 		return -1;
 	}
 	if (timestamp_src != 0) {
@@ -956,55 +1130,88 @@
 		errno = EROFS;
 		return -1;
 	}
+	/*
+	 * Don't allow rename on already converted paths.
+	 */
+	if (snappath_src != NULL) {
+		errno = EXDEV;
+		return -1;
+	}
+	if (snappath_dst != NULL) {
+		errno = EROFS;
+		return -1;
+	}
 	return SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst);
 }
 
 static int shadow_copy2_symlink(vfs_handle_struct *handle,
 				const char *oldname, const char *newname)
 {
-	time_t timestamp_old, timestamp_new;
+	time_t timestamp_old = 0;
+	time_t timestamp_new = 0;
+	char *snappath_old = NULL;
+	char *snappath_new = NULL;
 
-	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, oldname,
-					 &timestamp_old, NULL)) {
+	if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, oldname,
+					 &timestamp_old, NULL, &snappath_old)) {
 		return -1;
 	}
-	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, newname,
-					 &timestamp_new, NULL)) {
+	if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, newname,
+					 &timestamp_new, NULL, &snappath_new)) {
 		return -1;
 	}
 	if ((timestamp_old != 0) || (timestamp_new != 0)) {
 		errno = EROFS;
 		return -1;
 	}
+	/*
+	 * Don't allow symlinks on already converted paths.
+	 */
+	if ((snappath_old != NULL) || (snappath_new != NULL)) {
+		errno = EROFS;
+		return -1;
+	}
 	return SMB_VFS_NEXT_SYMLINK(handle, oldname, newname);
 }
 
 static int shadow_copy2_link(vfs_handle_struct *handle,
 			     const char *oldname, const char *newname)
 {
-	time_t timestamp_old, timestamp_new;
+	time_t timestamp_old = 0;
+	time_t timestamp_new = 0;
+	char *snappath_old = NULL;
+	char *snappath_new = NULL;
 
-	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, oldname,
-					 &timestamp_old, NULL)) {
+	if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, oldname,
+					 &timestamp_old, NULL, &snappath_old)) {
 		return -1;
 	}
-	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, newname,
-					 &timestamp_new, NULL)) {
+	if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, newname,
+					 &timestamp_new, NULL, &snappath_new)) {
 		return -1;
 	}
 	if ((timestamp_old != 0) || (timestamp_new != 0)) {
 		errno = EROFS;
 		return -1;
 	}
+	/*
+	 * Don't allow links on already converted paths.
+	 */
+	if ((snappath_old != NULL) || (snappath_new != NULL)) {
+		errno = EROFS;
+		return -1;
+	}
 	return SMB_VFS_NEXT_LINK(handle, oldname, newname);
 }
 
 static int shadow_copy2_stat(vfs_handle_struct *handle,
 			     struct smb_filename *smb_fname)
 {
-	time_t timestamp;
-	char *stripped, *tmp;
-	int ret, saved_errno;
+	time_t timestamp = 0;
+	char *stripped = NULL;
+	char *tmp;
+	int saved_errno = 0;
+	int ret;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
 					 smb_fname->base_name,
@@ -1026,7 +1233,9 @@
 	}
 
 	ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 
 	TALLOC_FREE(smb_fname->base_name);
 	smb_fname->base_name = tmp;
@@ -1034,16 +1243,20 @@
 	if (ret == 0) {
 		convert_sbuf(handle, smb_fname->base_name, &smb_fname->st);
 	}
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
 static int shadow_copy2_lstat(vfs_handle_struct *handle,
 			      struct smb_filename *smb_fname)
 {
-	time_t timestamp;
-	char *stripped, *tmp;
-	int ret, saved_errno;
+	time_t timestamp = 0;
+	char *stripped = NULL;
+	char *tmp;
+	int saved_errno = 0;
+	int ret;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
 					 smb_fname->base_name,
@@ -1065,7 +1278,9 @@
 	}
 
 	ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 
 	TALLOC_FREE(smb_fname->base_name);
 	smb_fname->base_name = tmp;
@@ -1073,14 +1288,16 @@
 	if (ret == 0) {
 		convert_sbuf(handle, smb_fname->base_name, &smb_fname->st);
 	}
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
 static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp,
 			      SMB_STRUCT_STAT *sbuf)
 {
-	time_t timestamp;
+	time_t timestamp = 0;
 	int ret;
 
 	ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
@@ -1102,9 +1319,11 @@
 			     struct smb_filename *smb_fname, files_struct *fsp,
 			     int flags, mode_t mode)
 {
-	time_t timestamp;
-	char *stripped, *tmp;
-	int ret, saved_errno;
+	time_t timestamp = 0;
+	char *stripped = NULL;
+	char *tmp;
+	int saved_errno = 0;
+	int ret;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
 					 smb_fname->base_name,
@@ -1126,21 +1345,26 @@
 	}
 
 	ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 
 	TALLOC_FREE(smb_fname->base_name);
 	smb_fname->base_name = tmp;
 
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
 static int shadow_copy2_unlink(vfs_handle_struct *handle,
 			       const struct smb_filename *smb_fname)
 {
-	time_t timestamp;
-	char *stripped;
-	int ret, saved_errno;
+	time_t timestamp = 0;
+	char *stripped = NULL;
+	int saved_errno = 0;
+	int ret;
 	struct smb_filename *conv;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
@@ -1163,9 +1387,13 @@
 		return -1;
 	}
 	ret = SMB_VFS_NEXT_UNLINK(handle, conv);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
@@ -1173,9 +1401,10 @@
 			const struct smb_filename *smb_fname,
 			mode_t mode)
 {
-	time_t timestamp;
+	time_t timestamp = 0;
 	char *stripped = NULL;
-	int ret, saved_errno;
+	int saved_errno = 0;
+	int ret;
 	char *conv = NULL;
 	struct smb_filename *conv_smb_fname;
 
@@ -1207,10 +1436,14 @@
 	}
 
 	ret = SMB_VFS_NEXT_CHMOD(handle, conv_smb_fname, mode);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
 	TALLOC_FREE(conv_smb_fname);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
@@ -1219,9 +1452,10 @@
 			uid_t uid,
 			gid_t gid)
 {
-	time_t timestamp;
-	char *stripped;
-	int ret, saved_errno;
+	time_t timestamp = 0;
+	char *stripped = NULL;
+	int saved_errno = 0;
+	int ret;
 	char *conv = NULL;
 	struct smb_filename *conv_smb_fname = NULL;
 
@@ -1251,37 +1485,96 @@
 		return -1;
 	}
 	ret = SMB_VFS_NEXT_CHOWN(handle, conv_smb_fname, uid, gid);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
 	TALLOC_FREE(conv_smb_fname);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
+static void store_cwd_data(vfs_handle_struct *handle,
+				const char *connectpath)
+{
+	struct shadow_copy2_private *priv = NULL;
+	char *cwd = NULL;
+
+	SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
+				return);
+
+	TALLOC_FREE(priv->shadow_cwd);
+	cwd = SMB_VFS_NEXT_GETWD(handle);
+	if (cwd == NULL) {
+		smb_panic("getwd failed\n");
+	}
+	DBG_DEBUG("shadow cwd = %s\n", cwd);
+	priv->shadow_cwd = talloc_strdup(priv, cwd);
+	SAFE_FREE(cwd);
+	if (priv->shadow_cwd == NULL) {
+		smb_panic("talloc failed\n");
+	}
+	TALLOC_FREE(priv->shadow_connectpath);
+	if (connectpath) {
+		DBG_DEBUG("shadow conectpath = %s\n", connectpath);
+		priv->shadow_connectpath = talloc_strdup(priv, connectpath);
+		if (priv->shadow_connectpath == NULL) {
+			smb_panic("talloc failed\n");
+		}
+	}
+}
+
 static int shadow_copy2_chdir(vfs_handle_struct *handle,
 			      const char *fname)
 {
-	time_t timestamp;
-	char *stripped;
-	int ret, saved_errno;
-	char *conv;
+	time_t timestamp = 0;
+	char *stripped = NULL;
+	char *snappath = NULL;
+	int ret = -1;
+	int saved_errno = 0;
+	char *conv = NULL;
+	size_t rootpath_len = 0;
 
-	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
-					 &timestamp, &stripped)) {
+	if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, fname,
+					&timestamp, &stripped, &snappath)) {
 		return -1;
 	}
-	if (timestamp == 0) {
-		return SMB_VFS_NEXT_CHDIR(handle, fname);
+	if (stripped != NULL) {
+		conv = shadow_copy2_do_convert(talloc_tos(),
+						handle,
+						stripped,
+						timestamp,
+						&rootpath_len);
+		TALLOC_FREE(stripped);
+		if (conv == NULL) {
+			return -1;
+		}
+		fname = conv;
 	}
-	conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
-	TALLOC_FREE(stripped);
-	if (conv == NULL) {
-		return -1;
+
+	ret = SMB_VFS_NEXT_CHDIR(handle, fname);
+	if (ret == -1) {
+		saved_errno = errno;
 	}
-	ret = SMB_VFS_NEXT_CHDIR(handle, conv);
-	saved_errno = errno;
+
+	if (ret == 0) {
+		if (conv != NULL && rootpath_len != 0) {
+			conv[rootpath_len] = '\0';
+		} else if (snappath != 0) {
+			TALLOC_FREE(conv);
+			conv = snappath;
+		}
+		store_cwd_data(handle, conv);
+	}
+
+	TALLOC_FREE(stripped);
 	TALLOC_FREE(conv);
-	errno = saved_errno;
+
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
@@ -1289,9 +1582,10 @@
 			       const struct smb_filename *smb_fname,
 			       struct smb_file_time *ft)
 {
-	time_t timestamp;
-	char *stripped;
-	int ret, saved_errno;
+	time_t timestamp = 0;
+	char *stripped = NULL;
+	int saved_errno = 0;
+	int ret;
 	struct smb_filename *conv;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
@@ -1314,18 +1608,23 @@
 		return -1;
 	}
 	ret = SMB_VFS_NEXT_NTIMES(handle, conv, ft);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
 static int shadow_copy2_readlink(vfs_handle_struct *handle,
 				 const char *fname, char *buf, size_t bufsiz)
 {
-	time_t timestamp;
-	char *stripped;
-	int ret, saved_errno;
+	time_t timestamp = 0;
+	char *stripped = NULL;
+	int saved_errno = 0;
+	int ret;
 	char *conv;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
@@ -1341,18 +1640,23 @@
 		return -1;
 	}
 	ret = SMB_VFS_NEXT_READLINK(handle, conv, buf, bufsiz);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
 static int shadow_copy2_mknod(vfs_handle_struct *handle,
 			      const char *fname, mode_t mode, SMB_DEV_T dev)
 {
-	time_t timestamp;
-	char *stripped;
-	int ret, saved_errno;
+	time_t timestamp = 0;
+	char *stripped = NULL;
+	int saved_errno = 0;
+	int ret;
 	char *conv;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
@@ -1368,20 +1672,24 @@
 		return -1;
 	}
 	ret = SMB_VFS_NEXT_MKNOD(handle, conv, mode, dev);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
 static char *shadow_copy2_realpath(vfs_handle_struct *handle,
 				   const char *fname)
 {
-	time_t timestamp;
+	time_t timestamp = 0;
 	char *stripped = NULL;
 	char *tmp = NULL;
 	char *result = NULL;
-	int saved_errno;
+	int saved_errno = 0;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
 					 &timestamp, &stripped)) {
@@ -1399,10 +1707,14 @@
 	result = SMB_VFS_NEXT_REALPATH(handle, tmp);
 
 done:
-	saved_errno = errno;
+	if (result == NULL) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(tmp);
 	TALLOC_FREE(stripped);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return result;
 }
 
@@ -1805,8 +2117,8 @@
 					 TALLOC_CTX *mem_ctx,
 					struct security_descriptor **ppdesc)
 {
-	time_t timestamp;
-	char *stripped;
+	time_t timestamp = 0;
+	char *stripped = NULL;
 	NTSTATUS status;
 	char *conv;
 	struct smb_filename *smb_fname = NULL;
@@ -1849,8 +2161,8 @@
 					TALLOC_CTX *mem_ctx,
 					struct security_descriptor **ppdesc)
 {
-	time_t timestamp;
-	char *stripped;
+	time_t timestamp = 0;
+	char *stripped = NULL;
 	NTSTATUS status;
 	char *conv;
 	struct smb_filename *conv_smb_fname = NULL;
@@ -1891,9 +2203,10 @@
 				const struct smb_filename *smb_fname,
 				mode_t mode)
 {
-	time_t timestamp;
-	char *stripped;
-	int ret, saved_errno;
+	time_t timestamp = 0;
+	char *stripped = NULL;
+	int saved_errno = 0;
+	int ret;
 	char *conv;
 	struct smb_filename *conv_smb_fname = NULL;
 
@@ -1922,19 +2235,24 @@
 		return -1;
 	}
 	ret = SMB_VFS_NEXT_MKDIR(handle, conv_smb_fname, mode);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
 	TALLOC_FREE(conv_smb_fname);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
 static int shadow_copy2_rmdir(vfs_handle_struct *handle,
 				const struct smb_filename *smb_fname)
 {
-	time_t timestamp;
-	char *stripped;
-	int ret, saved_errno;
+	time_t timestamp = 0;
+	char *stripped = NULL;
+	int saved_errno = 0;
+	int ret;
 	char *conv;
 	struct smb_filename *conv_smb_fname = NULL;
 
@@ -1963,19 +2281,24 @@
 		return -1;
 	}
 	ret = SMB_VFS_NEXT_RMDIR(handle, conv_smb_fname);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv_smb_fname);
 	TALLOC_FREE(conv);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
 static int shadow_copy2_chflags(vfs_handle_struct *handle, const char *fname,
 				unsigned int flags)
 {
-	time_t timestamp;
-	char *stripped;
-	int ret, saved_errno;
+	time_t timestamp = 0;
+	char *stripped = NULL;
+	int saved_errno = 0;
+	int ret;
 	char *conv;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
@@ -1991,9 +2314,13 @@
 		return -1;
 	}
 	ret = SMB_VFS_NEXT_CHFLAGS(handle, conv, flags);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
@@ -2001,10 +2328,10 @@
 				     const char *fname, const char *aname,
 				     void *value, size_t size)
 {
-	time_t timestamp;
-	char *stripped;
+	time_t timestamp = 0;
+	char *stripped = NULL;
 	ssize_t ret;
-	int saved_errno;
+	int saved_errno = 0;
 	char *conv;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
@@ -2021,9 +2348,13 @@
 		return -1;
 	}
 	ret = SMB_VFS_NEXT_GETXATTR(handle, conv, aname, value, size);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
@@ -2031,10 +2362,10 @@
 				      const char *fname,
 				      char *list, size_t size)
 {
-	time_t timestamp;
-	char *stripped;
+	time_t timestamp = 0;
+	char *stripped = NULL;
 	ssize_t ret;
-	int saved_errno;
+	int saved_errno = 0;
 	char *conv;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
@@ -2050,18 +2381,23 @@
 		return -1;
 	}
 	ret = SMB_VFS_NEXT_LISTXATTR(handle, conv, list, size);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
 static int shadow_copy2_removexattr(vfs_handle_struct *handle,
 				    const char *fname, const char *aname)
 {
-	time_t timestamp;
-	char *stripped;
-	int ret, saved_errno;
+	time_t timestamp = 0;
+	char *stripped = NULL;
+	int saved_errno = 0;
+	int ret;
 	char *conv;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
@@ -2077,9 +2413,13 @@
 		return -1;
 	}
 	ret = SMB_VFS_NEXT_REMOVEXATTR(handle, conv, aname);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
@@ -2088,10 +2428,10 @@
 				 const char *aname, const void *value,
 				 size_t size, int flags)
 {
-	time_t timestamp;
-	char *stripped;
+	time_t timestamp = 0;
+	char *stripped = NULL;
 	ssize_t ret;
-	int saved_errno;
+	int saved_errno = 0;
 	char *conv;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
@@ -2108,9 +2448,13 @@
 		return -1;
 	}
 	ret = SMB_VFS_NEXT_SETXATTR(handle, conv, aname, value, size, flags);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
@@ -2118,10 +2462,10 @@
 			const struct smb_filename *smb_fname,
 			mode_t mode)
 {
-	time_t timestamp;
-	char *stripped;
+	time_t timestamp = 0;
+	char *stripped = NULL;
 	ssize_t ret;
-	int saved_errno;
+	int saved_errno = 0;
 	char *conv = NULL;
 	struct smb_filename *conv_smb_fname = NULL;
 
@@ -2151,10 +2495,14 @@
 		return -1;
 	}
 	ret = SMB_VFS_NEXT_CHMOD_ACL(handle, conv_smb_fname, mode);
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
 	TALLOC_FREE(conv_smb_fname);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
@@ -2164,10 +2512,10 @@
 					  TALLOC_CTX *mem_ctx,
 					  char **found_name)
 {
-	time_t timestamp;
-	char *stripped;
+	time_t timestamp = 0;
+	char *stripped = NULL;
 	ssize_t ret;
-	int saved_errno;
+	int saved_errno = 0;
 	char *conv;
 
 	DEBUG(10, ("shadow_copy2_get_real_filename called for path=[%s], "
@@ -2194,25 +2542,39 @@
 	ret = SMB_VFS_NEXT_GET_REAL_FILENAME(handle, conv, name,
 					     mem_ctx, found_name);
 	DEBUG(10, ("NEXT_REAL_FILE_NAME returned %d\n", (int)ret));
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return ret;
 }
 
 static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle,
 					    const char *fname)
 {
-	time_t timestamp;
+	time_t timestamp = 0;
 	char *stripped = NULL;
 	char *tmp = NULL;
 	char *result = NULL;
 	char *parent_dir = NULL;
-	int saved_errno;
+	int saved_errno = 0;
 	size_t rootpath_len = 0;
+	struct shadow_copy2_private *priv = NULL;
+
+	SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
+				return NULL);
 
 	DBG_DEBUG("Calc connect path for [%s]\n", fname);
 
+	if (priv->shadow_connectpath != NULL) {
+		DBG_DEBUG("cached connect path is [%s]\n",
+			priv->shadow_connectpath);
+		return priv->shadow_connectpath;
+	}
+
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
 					 &timestamp, &stripped)) {
 		goto done;
@@ -2263,14 +2625,25 @@
 		goto done;
 	}
 
+	/*
+	 * SMB_VFS_NEXT_REALPATH returns a malloc'ed string.
+	 * Don't leak memory.
+	 */
+	SAFE_FREE(priv->shadow_realpath);
+	priv->shadow_realpath = result;
+
 	DBG_DEBUG("connect path is [%s]\n", result);
 
 done:
-	saved_errno = errno;
+	if (result == NULL) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(tmp);
 	TALLOC_FREE(stripped);
 	TALLOC_FREE(parent_dir);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 	return result;
 }
 
@@ -2278,10 +2651,10 @@
 				       const char *path, uint64_t *bsize,
 				       uint64_t *dfree, uint64_t *dsize)
 {
-	time_t timestamp;
-	char *stripped;
+	time_t timestamp = 0;
+	char *stripped = NULL;
 	ssize_t ret;
-	int saved_errno;
+	int saved_errno = 0;
 	char *conv;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, path,
@@ -2301,9 +2674,13 @@
 
 	ret = SMB_VFS_NEXT_DISK_FREE(handle, conv, bsize, dfree, dsize);
 
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 
 	return ret;
 }
@@ -2312,10 +2689,10 @@
 				  enum SMB_QUOTA_TYPE qtype, unid_t id,
 				  SMB_DISK_QUOTA *dq)
 {
-	time_t timestamp;
-	char *stripped;
+	time_t timestamp = 0;
+	char *stripped = NULL;
 	int ret;
-	int saved_errno;
+	int saved_errno = 0;
 	char *conv;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, path, &timestamp,
@@ -2334,13 +2711,23 @@
 
 	ret = SMB_VFS_NEXT_GET_QUOTA(handle, conv, qtype, id, dq);
 
-	saved_errno = errno;
+	if (ret == -1) {
+		saved_errno = errno;
+	}
 	TALLOC_FREE(conv);
-	errno = saved_errno;
+	if (saved_errno != 0) {
+		errno = saved_errno;
+	}
 
 	return ret;
 }
 
+static int shadow_copy2_private_destructor(struct shadow_copy2_private *priv)
+{
+	SAFE_FREE(priv->shadow_realpath);
+	return 0;
+}
+
 static int shadow_copy2_connect(struct vfs_handle_struct *handle,
 				const char *service, const char *user)
 {
@@ -2372,6 +2759,8 @@
 		return -1;
 	}
 
+	talloc_set_destructor(priv, shadow_copy2_private_destructor);
+
 	priv->snaps = talloc_zero(priv, struct shadow_copy2_snaplist_info);
 	if (priv->snaps == NULL) {
 		DBG_ERR("talloc_zero() failed\n");
@@ -2398,6 +2787,15 @@
 		return -1;
 	}
 
+	/* config->gmt_format must not contain a path separator. */
+	if (strchr(config->gmt_format, '/') != NULL) {
+		DEBUG(0, ("shadow:format %s must not contain a /"
+			"character. Unable to initialize module.\n",
+			config->gmt_format));
+		errno = EINVAL;
+		return -1;
+	}
+
 	config->use_sscanf = lp_parm_bool(SNUM(handle->conn),
 					  "shadow", "sscanf", false);
 
@@ -2582,7 +2980,7 @@
 	}
 
 	if (config->rel_connectpath == NULL &&
-	    strlen(basedir) != strlen(handle->conn->connectpath)) {
+	    strlen(basedir) < strlen(handle->conn->connectpath)) {
 		config->rel_connectpath = talloc_strdup(config,
 			handle->conn->connectpath + strlen(basedir));
 		if (config->rel_connectpath == NULL) {
@@ -2620,6 +3018,11 @@
 		}
 	}
 
+	trim_string(config->mount_point, NULL, "/");
+	trim_string(config->rel_connectpath, "/", "/");
+	trim_string(config->snapdir, NULL, "/");
+	trim_string(config->snapshot_basepath, NULL, "/");
+
 	DEBUG(10, ("shadow_copy2_connect: configuration:\n"
 		   "  share root: '%s'\n"
 		   "  mountpoint: '%s'\n"
diff -Nru samba-4.5.5+dfsg/source3/modules/vfs_streams_xattr.c samba-4.5.6+dfsg/source3/modules/vfs_streams_xattr.c
--- samba-4.5.5+dfsg/source3/modules/vfs_streams_xattr.c	2017-01-30 10:56:26.000000000 +0100
+++ samba-4.5.6+dfsg/source3/modules/vfs_streams_xattr.c	2017-03-09 10:21:43.000000000 +0100
@@ -264,7 +264,7 @@
 		return -1;
 	}
 
-	sbuf->st_ex_size = get_xattr_size(handle->conn, fsp->base_fsp,
+	sbuf->st_ex_size = get_xattr_size(handle->conn, fsp,
 					io->base, io->xattr_name);
 	if (sbuf->st_ex_size == -1) {
 		return -1;
@@ -399,6 +399,7 @@
 	char *xattr_name = NULL;
 	int baseflags;
 	int hostfd = -1;
+	int ret;
 
 	DEBUG(10, ("streams_xattr_open called for %s with flags 0x%x\n",
 		   smb_fname_str_dbg(smb_fname), flags));
@@ -410,7 +411,6 @@
 	/* If the default stream is requested, just open the base file. */
 	if (is_ntfs_default_stream_smb_fname(smb_fname)) {
 		char *tmp_stream_name;
-		int ret;
 
 		tmp_stream_name = smb_fname->stream_name;
 		smb_fname->stream_name = NULL;
@@ -449,10 +449,8 @@
         baseflags &= ~O_EXCL;
         baseflags &= ~O_CREAT;
 
-        hostfd = SMB_VFS_OPEN(handle->conn, smb_fname_base, fsp,
-			      baseflags, mode);
-
-	TALLOC_FREE(smb_fname_base);
+        hostfd = SMB_VFS_NEXT_OPEN(handle, smb_fname_base, fsp,
+				   baseflags, mode);
 
         /* It is legit to open a stream on a directory, but the base
          * fd has to be read-only.
@@ -460,10 +458,12 @@
         if ((hostfd == -1) && (errno == EISDIR)) {
                 baseflags &= ~O_ACCMODE;
                 baseflags |= O_RDONLY;
-                hostfd = SMB_VFS_OPEN(handle->conn, smb_fname, fsp, baseflags,
-				      mode);
+                hostfd = SMB_VFS_NEXT_OPEN(handle, smb_fname_base, fsp, baseflags,
+					   mode);
         }
 
+	TALLOC_FREE(smb_fname_base);
+
         if (hostfd == -1) {
 		goto fail;
         }
@@ -500,20 +500,13 @@
 		DEBUG(10, ("creating or truncating attribute %s on file %s\n",
 			   xattr_name, smb_fname->base_name));
 
-		if (fsp->base_fsp->fh->fd != -1) {
-			if (SMB_VFS_FSETXATTR(
-					fsp->base_fsp, xattr_name,
+		fsp->fh->fd = hostfd;
+		ret = SMB_VFS_FSETXATTR(fsp, xattr_name,
 					&null, sizeof(null),
-					flags & O_EXCL ? XATTR_CREATE : 0) == -1) {
-				goto fail;
-			}
-		} else {
-			if (SMB_VFS_SETXATTR(
-					handle->conn, smb_fname->base_name,
-					xattr_name, &null, sizeof(null),
-					flags & O_EXCL ? XATTR_CREATE : 0) == -1) {
-				goto fail;
-			}
+					flags & O_EXCL ? XATTR_CREATE : 0);
+		fsp->fh->fd = -1;
+		if (ret != 0) {
+			goto fail;
 		}
 	}
 
@@ -527,8 +520,15 @@
 
         sio->xattr_name = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
 					xattr_name);
+	/*
+	 * so->base needs to be a copy of fsp->fsp_name->base_name,
+	 * making it identical to streams_xattr_recheck(). If the
+	 * open is changing directories, fsp->fsp_name->base_name
+	 * will be the full path from the share root, whilst
+	 * smb_fname will be relative to the $cwd.
+	 */
         sio->base = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
-				  smb_fname->base_name);
+				  fsp->fsp_name->base_name);
 	sio->fsp_name_ptr = fsp->fsp_name;
 	sio->handle = handle;
 	sio->fsp = fsp;
@@ -547,7 +547,7 @@
 		 * we don't have a full fsp yet
 		 */
 		fsp->fh->fd = hostfd;
-		SMB_VFS_CLOSE(fsp);
+		SMB_VFS_NEXT_CLOSE(handle, fsp);
 	}
 
 	return -1;
@@ -961,7 +961,7 @@
 		return -1;
 	}
 
-	status = get_ea_value(talloc_tos(), handle->conn, fsp->base_fsp,
+	status = get_ea_value(talloc_tos(), handle->conn, fsp,
 			      sio->base, sio->xattr_name, &ea);
 	if (!NT_STATUS_IS_OK(status)) {
 		return -1;
@@ -985,13 +985,13 @@
 
         memcpy(ea.value.data + offset, data, n);
 
-	if (fsp->base_fsp->fh->fd != -1) {
-		ret = SMB_VFS_FSETXATTR(fsp->base_fsp,
+	if (fsp->fh->fd != -1) {
+		ret = SMB_VFS_FSETXATTR(fsp,
 				sio->xattr_name,
 				ea.value.data, ea.value.length, 0);
 	} else {
 		ret = SMB_VFS_SETXATTR(fsp->conn,
-				       fsp->base_fsp->fsp_name->base_name,
+				       fsp->fsp_name->base_name,
 				sio->xattr_name,
 				ea.value.data, ea.value.length, 0);
 	}
@@ -1025,7 +1025,7 @@
 		return -1;
 	}
 
-	status = get_ea_value(talloc_tos(), handle->conn, fsp->base_fsp,
+	status = get_ea_value(talloc_tos(), handle->conn, fsp,
 			      sio->base, sio->xattr_name, &ea);
 	if (!NT_STATUS_IS_OK(status)) {
 		return -1;
@@ -1070,7 +1070,7 @@
 		return -1;
 	}
 
-	status = get_ea_value(talloc_tos(), handle->conn, fsp->base_fsp,
+	status = get_ea_value(talloc_tos(), handle->conn, fsp,
 			      sio->base, sio->xattr_name, &ea);
 	if (!NT_STATUS_IS_OK(status)) {
 		return -1;
@@ -1095,13 +1095,13 @@
 	ea.value.length = offset + 1;
 	ea.value.data[offset] = 0;
 
-	if (fsp->base_fsp->fh->fd != -1) {
-		ret = SMB_VFS_FSETXATTR(fsp->base_fsp,
+	if (fsp->fh->fd != -1) {
+		ret = SMB_VFS_FSETXATTR(fsp,
 				sio->xattr_name,
 				ea.value.data, ea.value.length, 0);
 	} else {
 		ret = SMB_VFS_SETXATTR(fsp->conn,
-				       fsp->base_fsp->fsp_name->base_name,
+				fsp->fsp_name->base_name,
 				sio->xattr_name,
 				ea.value.data, ea.value.length, 0);
 	}
diff -Nru samba-4.5.5+dfsg/source3/passdb/passdb.c samba-4.5.6+dfsg/source3/passdb/passdb.c
--- samba-4.5.5+dfsg/source3/passdb/passdb.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/passdb/passdb.c	2017-03-09 10:21:43.000000000 +0100
@@ -2621,6 +2621,19 @@
 			status = NT_STATUS_NO_MEMORY;
 			goto fail;
 		}
+
+		/*
+		 * It's not possible to use NTLMSSP with a domain trust account.
+		 */
+		cli_credentials_set_kerberos_state(creds, CRED_MUST_USE_KERBEROS);
+	} else {
+		/*
+		 * We can't use kerberos against an NT4 domain.
+		 *
+		 * We should have a mode that also disallows NTLMSSP here,
+		 * as only NETLOGON SCHANNEL is possible.
+		 */
+		cli_credentials_set_kerberos_state(creds, CRED_DONT_USE_KERBEROS);
 	}
 
 	ok = cli_credentials_set_username(creds, account_name, CRED_SPECIFIED);
@@ -2635,6 +2648,10 @@
 			status = NT_STATUS_NO_MEMORY;
 			goto fail;
 		}
+		/*
+		 * We currently can't do kerberos just with an NTHASH.
+		 */
+		cli_credentials_set_kerberos_state(creds, CRED_DONT_USE_KERBEROS);
 		goto done;
 	}
 
diff -Nru samba-4.5.5+dfsg/source3/rpc_client/cli_pipe.c samba-4.5.6+dfsg/source3/rpc_client/cli_pipe.c
--- samba-4.5.5+dfsg/source3/rpc_client/cli_pipe.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/rpc_client/cli_pipe.c	2017-03-09 10:21:43.000000000 +0100
@@ -948,8 +948,7 @@
 
 	status = dcerpc_pull_ncacn_packet(state->pkt,
 					  &state->incoming_frag,
-					  state->pkt,
-					  !state->endianess);
+					  state->pkt);
 	if (!NT_STATUS_IS_OK(status)) {
 		/*
 		 * TODO: do a real async disconnect ...
diff -Nru samba-4.5.5+dfsg/source3/rpc_server/mdssvc/sparql_mapping.c samba-4.5.6+dfsg/source3/rpc_server/mdssvc/sparql_mapping.c
--- samba-4.5.5+dfsg/source3/rpc_server/mdssvc/sparql_mapping.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/rpc_server/mdssvc/sparql_mapping.c	2017-03-09 10:21:43.000000000 +0100
@@ -133,6 +133,11 @@
 			.type = ssmt_type,
 			.sparql_attr = NULL,
 		},
+		{
+			.spotlight_attr = "kMDItemContentType",
+			.type = ssmt_type,
+			.sparql_attr = NULL,
+		},
 
 		/* Image metadata */
 		{
diff -Nru samba-4.5.5+dfsg/source3/rpc_server/rpc_service_setup.c samba-4.5.6+dfsg/source3/rpc_server/rpc_service_setup.c
--- samba-4.5.5+dfsg/source3/rpc_server/rpc_service_setup.c	2016-09-13 10:21:35.000000000 +0200
+++ samba-4.5.6+dfsg/source3/rpc_server/rpc_service_setup.c	2017-03-09 10:21:43.000000000 +0100
@@ -535,18 +535,15 @@
 
 	/* Initialize shared modules */
 	mod_init_fns = load_samba_modules(tmp_ctx, "rpc");
-	if (mod_init_fns == NULL) {
-		if (errno != ENOENT) {
-			/*
-			 * ENOENT means the directory doesn't exist
-			 * which can happen if all modules are
-			 * static. So ENOENT is ok, everything else is
-			 * not ok.
-			 */
-			DBG_ERR("Loading shared RPC modules failed [%s]\n",
-				strerror(errno));
-			ok = false;
-		}
+	if ((mod_init_fns == NULL) && (errno != ENOENT)) {
+		/*
+		 * ENOENT means the directory doesn't exist which can happen if
+		 * all modules are static. So ENOENT is ok, everything else is
+		 * not ok.
+		 */
+		DBG_ERR("Loading shared RPC modules failed [%s]\n",
+			strerror(errno));
+		ok = false;
 		goto done;
 	}
 
diff -Nru samba-4.5.5+dfsg/source3/rpc_server/wscript_build samba-4.5.6+dfsg/source3/rpc_server/wscript_build
--- samba-4.5.5+dfsg/source3/rpc_server/wscript_build	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/rpc_server/wscript_build	2017-03-09 10:21:43.000000000 +0100
@@ -39,6 +39,10 @@
                     NDR_NAMED_PIPE_AUTH
                     ''')
 
+bld.SAMBA3_SUBSYSTEM('RPC_MODULES',
+                    source='rpc_modules.c',
+                    deps='samba-util')
+
 ### RPC_SERVICES
 bld.SAMBA3_SUBSYSTEM('RPC_DSSETUP',
                     source='''dssetup/srv_dssetup_nt.c
@@ -150,11 +154,12 @@
                     deps='samba-util')
 
 bld.SAMBA3_SUBSYSTEM('RPC_SERVICE',
-                    source='rpc_service_setup.c rpc_modules.c',
+                    source='rpc_service_setup.c',
                     deps='''
                     rpc
                     RPC_SERVER
                     RPC_SERVER_REGISTER
+		    RPC_MODULES
                     RPC_SAMR
                     RPC_LSARPC
                     RPC_WINREG
@@ -192,6 +197,6 @@
                     deps='samba-util')
 
 bld.SAMBA3_SUBSYSTEM('MDSSD',
-                    source='mdssd.c rpc_modules.c',
-                    deps='RPC_SOCK_HELPER samba-util',
+                    source='mdssd.c',
+                    deps='RPC_SOCK_HELPER RPC_MODULES samba-util',
                     enabled=bld.env.with_spotlight)
diff -Nru samba-4.5.5+dfsg/source3/script/tests/test_smbclient_encryption_off.sh samba-4.5.6+dfsg/source3/script/tests/test_smbclient_encryption_off.sh
--- samba-4.5.5+dfsg/source3/script/tests/test_smbclient_encryption_off.sh	1970-01-01 01:00:00.000000000 +0100
+++ samba-4.5.6+dfsg/source3/script/tests/test_smbclient_encryption_off.sh	2017-03-09 10:21:43.000000000 +0100
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+if [ $# -lt 4 ]; then
+cat <<EOF
+Usage: test_smbclient_encryption_off.sh USERNAME PASSWORD SERVER SMBCLIENT
+EOF
+exit 1;
+fi
+
+USERNAME="$1"
+PASSWORD="$2"
+SERVER="$3"
+SMBCLIENT="$VALGRIND $4"
+
+incdir=`dirname $0`/../../../testprogs/blackbox
+. $incdir/subunit.sh
+
+failed=0
+
+#
+# Let me introduce you to the shares used in this test:
+#
+# "tmp" has the default "smb encrypt" (which is "enabled")
+# "tmpenc" has "smb encrypt = required"
+# "enc_desired" has "smb encrypt = desired"
+#
+
+# Unencrypted connections should work of course, let's test em to be sure...
+
+# SMB1
+testit "smbclient //$SERVER/enc_desired" $SMBCLIENT -U $USERNAME%$PASSWORD //$SERVER/enc_desired -c quit || failed=`expr $failed + 1`
+testit "smbclient //$SERVER/tmp" $SMBCLIENT -U $USERNAME%$PASSWORD //$SERVER/tmp -c quit || failed=`expr $failed + 1`
+# SMB3_02
+testit "smbclient -m smb3_02 //$SERVER/enc_desired" $SMBCLIENT -m smb3_02 -U $USERNAME%$PASSWORD //$SERVER/enc_desired -c quit || failed=`expr $failed + 1`
+testit "smbclient -m smb3_02 //$SERVER/tmp" $SMBCLIENT -m smb3_02 -U $USERNAME%$PASSWORD //$SERVER/tmp -c quit || failed=`expr $failed + 1`
+# SMB3_11
+testit "smbclient -m smb3_11 //$SERVER/enc_desired" $SMBCLIENT -m smb3_11 -U $USERNAME%$PASSWORD //$SERVER/enc_desired -c quit || failed=`expr $failed + 1`
+testit "smbclient -m smb3_11 //$SERVER/tmp" $SMBCLIENT -m smb3_11 -U $USERNAME%$PASSWORD //$SERVER/tmp -c quit || failed=`expr $failed + 1`
+
+# These tests must fail, as encryption is globally off and in combination with "smb
+# encrypt=required" on the share "tmpenc" the server *must* reject the tcon.
+
+# SMB1
+testit_expect_failure "smbclient //$SERVER/tmpenc" $SMBCLIENT -U $USERNAME%$PASSWORD //$SERVER/tmpenc -c quit && failed=`expr $failed + 1`
+testit_expect_failure "smbclient -e //$SERVER/tmpenc" $SMBCLIENT -e -U $USERNAME%$PASSWORD //$SERVER/tmpenc -c quit && failed=`expr $failed + 1`
+# SMB3_02
+testit_expect_failure "smbclient -m smb3_02 //$SERVER/tmpenc" $SMBCLIENT -m smb3_02 -U $USERNAME%$PASSWORD //$SERVER/tmpenc -c quit && failed=`expr $failed + 1`
+testit_expect_failure "smbclient -e -m smb3_02 //$SERVER/tmpenc" $SMBCLIENT -e -m smb3_02 -U $USERNAME%$PASSWORD //$SERVER/tmpenc -c quit && failed=`expr $failed + 1`
+# SMB3_11
+testit_expect_failure "smbclient -m smb3_11 //$SERVER/tmpenc" $SMBCLIENT -m smb3_11 -U $USERNAME%$PASSWORD //$SERVER/tmpenc -c quit && failed=`expr $failed + 1`
+testit_expect_failure "smbclient -e -m smb3_11 //$SERVER/tmpenc" $SMBCLIENT -e -m smb3_11 -U $USERNAME%$PASSWORD //$SERVER/tmpenc -c quit && failed=`expr $failed + 1`
+
+# These tests must fail, as the client requires encryption and it's off on the server
+
+# SMB1
+testit_expect_failure "smbclient -e //$SERVER/enc_desired" $SMBCLIENT -e -U $USERNAME%$PASSWORD //$SERVER/enc_desired -c quit && failed=`expr $failed + 1`
+testit_expect_failure "smbclient -e //$SERVER/tmp" $SMBCLIENT -e -U $USERNAME%$PASSWORD //$SERVER/tmp -c quit && failed=`expr $failed + 1`
+# SMB3_02
+testit_expect_failure "smbclient -e -m smb3_02 //$SERVER/enc_desired" $SMBCLIENT -e -m smb3_02 -U $USERNAME%$PASSWORD //$SERVER/enc_desired -c quit && failed=`expr $failed + 1`
+testit_expect_failure "smbclient -e -m smb3_02 //$SERVER/tmp" $SMBCLIENT -e -m smb3_02 -U $USERNAME%$PASSWORD //$SERVER/tmp -c quit && failed=`expr $failed + 1`
+# SMB3_11
+testit_expect_failure "smbclient -e -m smb3_11 //$SERVER/enc_desired" $SMBCLIENT -e -m smb3_11 -U $USERNAME%$PASSWORD //$SERVER/enc_desired -c quit && failed=`expr $failed + 1`
+testit_expect_failure "smbclient -e -m smb3_11 //$SERVER/tmp" $SMBCLIENT -e -m smb3_11 -U $USERNAME%$PASSWORD //$SERVER/tmp -c quit && failed=`expr $failed + 1`
+
+testok $0 $failed
diff -Nru samba-4.5.5+dfsg/source3/selftest/tests.py samba-4.5.6+dfsg/source3/selftest/tests.py
--- samba-4.5.5+dfsg/source3/selftest/tests.py	2017-01-30 10:56:26.000000000 +0100
+++ samba-4.5.6+dfsg/source3/selftest/tests.py	2017-03-09 10:21:43.000000000 +0100
@@ -84,7 +84,7 @@
     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-SYMLINK-ACL", "POSIX-SYMLINK-EA", "POSIX-OFD-LOCK",
-              "POSIX-STREAM-DELETE" ]
+              "POSIX-STREAM-DELETE", "WINDOWS-BAD-SYMLINK" ]
 
 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"])
@@ -119,6 +119,7 @@
     "LOCAL-MESSAGING-FDPASS2",
     "LOCAL-MESSAGING-FDPASS2a",
     "LOCAL-MESSAGING-FDPASS2b",
+    "LOCAL-CANONICALIZE-PATH",
     "LOCAL-hex_encode_buf",
     "LOCAL-remove_duplicate_addrs2"]
 
@@ -274,7 +275,7 @@
 
 #smbtorture4 tests
 
-base = ["base.attr", "base.charset", "base.chkpath", "base.defer_open", "base.delaywrite", "base.delete",
+base = ["base.attr", "base.charset", "base.chkpath", "base.createx_access", "base.defer_open", "base.delaywrite", "base.delete",
         "base.deny1", "base.deny2", "base.deny3", "base.denydos", "base.dir1", "base.dir2",
         "base.disconnect", "base.fdpass", "base.lock",
         "base.mangle", "base.negnowait", "base.ntdeny1",
@@ -323,13 +324,15 @@
 
 libsmbclient = ["libsmbclient"]
 
-vfs = ["vfs.fruit", "vfs.acl_xattr"]
+vfs = ["vfs.fruit", "vfs.acl_xattr", "vfs.fruit_netatalk"]
 
 tests= base + raw + smb2 + rpc + unix + local + rap + nbt + libsmbclient + idmap + vfs
 
 for t in tests:
     if t == "base.delaywrite":
         plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD -k yes --maximum-runtime=900')
+    if t == "base.createx_access":
+        plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD -k yes --maximum-runtime=900')
     elif t == "rap.sam":
         plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD --option=doscharset=ISO-8859-1')
         plansmbtorture4testsuite(t, "ad_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD --option=doscharset=ISO-8859-1')
@@ -404,8 +407,11 @@
         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/vfs_fruit -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/nt4_dc/share --option=torture:share2=vfs_wo_fruit', 'metadata_netatalk')
+        plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/vfs_fruit_metadata_stream --option=torture:share2=vfs_wo_fruit -U$USERNAME%$PASSWORD', 'metadata_stream')
+        plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/vfs_fruit_stream_depot --option=torture:share2=vfs_wo_fruit_stream_depot -U$USERNAME%$PASSWORD', 'streams_depot')
+    elif t == "vfs.fruit_netatalk":
         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)")
@@ -442,8 +448,12 @@
 
     # We should try more combinations in future, but this is all
     # the pre-calculated credentials cache supports at the moment
+    #
+    # As the ktest env requires SMB3_00 we need to use "smb2" until
+    # dcerpc client code in smbtorture support autonegotiation
+    # of any smb dialect.
     e = ""
-    a = ""
+    a = "smb2"
     binding_string = "ncacn_np:$SERVER[%s%s%s]" % (a, s, e)
     options = binding_string + " -k yes --krb5-ccache=$PREFIX/ktest/krb5_ccache-2"
     plansmbtorture4testsuite(test, "ktest", options, 'krb5 with old ccache ncacn_np with [%s%s%s] ' % (a, s, e))
@@ -483,6 +493,11 @@
                "$USERNAME", "$PASSWORD", "$SERVER",
                os.path.join(bindir(), "rpcclient")])
 
+plantestsuite("samba3.blackbox.smbclient.encryption_off", "simpleserver",
+              [os.path.join(samba3srcdir, "script/tests/test_smbclient_encryption_off.sh"),
+               "$USERNAME", "$PASSWORD", "$SERVER",
+               smbclient3])
+
 options_list = ["", "-e"]
 for options in options_list:
     plantestsuite("samba3.blackbox.smbclient_krb5 old ccache %s" % options, "ktest:local",
diff -Nru samba-4.5.5+dfsg/source3/smbd/filename.c samba-4.5.6+dfsg/source3/smbd/filename.c
--- samba-4.5.5+dfsg/source3/smbd/filename.c	2016-12-05 09:18:44.000000000 +0100
+++ samba-4.5.6+dfsg/source3/smbd/filename.c	2017-03-09 10:21:43.000000000 +0100
@@ -220,6 +220,148 @@
 	return NT_STATUS_OK;
 }
 
+/*
+ * Re-order a known good @GMT-token path.
+ */
+
+static NTSTATUS rearrange_snapshot_path(struct smb_filename *smb_fname,
+				char *startp,
+				char *endp)
+{
+	size_t endlen = 0;
+	size_t gmt_len = endp - startp;
+	char gmt_store[gmt_len + 1];
+	char *parent = NULL;
+	const char *last_component = NULL;
+	char *newstr;
+	bool ret;
+
+	DBG_DEBUG("|%s| -> ", smb_fname->base_name);
+
+	/* Save off the @GMT-token. */
+	memcpy(gmt_store, startp, gmt_len);
+	gmt_store[gmt_len] = '\0';
+
+	if (*endp == '/') {
+		/* Remove any trailing '/' */
+		endp++;
+	}
+
+	if (*endp == '\0') {
+		/*
+		 * @GMT-token was at end of path.
+		 * Remove any preceeding '/'
+		 */
+		if (startp > smb_fname->base_name && startp[-1] == '/') {
+			startp--;
+		}
+	}
+
+	/* Remove @GMT-token from the path. */
+	endlen = strlen(endp);
+	memmove(startp, endp, endlen + 1);
+
+	/* Split the remaining path into components. */
+	ret = parent_dirname(smb_fname,
+				smb_fname->base_name,
+				&parent,
+				&last_component);
+	if (ret == false) {
+		/* Must terminate debug with \n */
+		DBG_DEBUG("NT_STATUS_NO_MEMORY\n");
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	if (ISDOT(parent)) {
+		if (last_component[0] == '\0') {
+			newstr = talloc_strdup(smb_fname,
+					gmt_store);
+		} else {
+			newstr = talloc_asprintf(smb_fname,
+					"%s/%s",
+					gmt_store,
+					last_component);
+		}
+	} else {
+		newstr = talloc_asprintf(smb_fname,
+					"%s/%s/%s",
+					gmt_store,
+					parent,
+					last_component);
+	}
+
+	TALLOC_FREE(parent);
+	TALLOC_FREE(smb_fname->base_name);
+	smb_fname->base_name = newstr;
+
+	DBG_DEBUG("|%s|\n", newstr);
+
+	return NT_STATUS_OK;
+}
+
+/*
+ * Canonicalize any incoming pathname potentially containining
+ * a @GMT-token into a path that looks like:
+ *
+ * @GMT-YYYY-MM-DD-HH-MM-SS/path/name/components/last_component
+ *
+ * Leaves single path @GMT-token -component alone:
+ *
+ * @GMT-YYYY-MM-DD-HH-MM-SS -> @GMT-YYYY-MM-DD-HH-MM-SS
+ *
+ * Eventually when struct smb_filename is updated and the VFS
+ * ABI is changed this will remove the @GMT-YYYY-MM-DD-HH-MM-SS
+ * and store in the struct smb_filename as a struct timeval field
+ * instead.
+ */
+
+static NTSTATUS canonicalize_snapshot_path(struct smb_filename *smb_fname)
+{
+	char *startp = strchr_m(smb_fname->base_name, '@');
+	char *endp = NULL;
+	struct tm tm;
+
+	if (startp == NULL) {
+		/* No @ */
+		return NT_STATUS_OK;
+	}
+
+	startp = strstr_m(startp, "@GMT-");
+	if (startp == NULL) {
+		/* No @ */
+		return NT_STATUS_OK;
+	}
+
+	if ((startp > smb_fname->base_name) && (startp[-1] != '/')) {
+		/* the GMT-token does not start a path-component */
+		return NT_STATUS_OK;
+	}
+
+	endp = strptime(startp, GMT_FORMAT, &tm);
+	if (endp == NULL) {
+		/* Not a valid timestring. */
+		return NT_STATUS_OK;
+	}
+
+	if ( endp[0] == '\0') {
+		return rearrange_snapshot_path(smb_fname,
+					startp,
+					endp);
+	}
+
+	if (endp[0] != '/') {
+		/*
+		 * It is not a complete path component, i.e. the path
+		 * component continues after the gmt-token.
+		 */
+		return NT_STATUS_OK;
+	}
+
+	return rearrange_snapshot_path(smb_fname,
+				startp,
+				endp);
+}
+
 /****************************************************************************
 This routine is called to convert names from the dos namespace to unix
 namespace. It needs to handle any case conversions, mangling, format changes,
@@ -356,6 +498,14 @@
 		goto err;
 	}
 
+	/* Canonicalize any @GMT- paths. */
+	if (posix_pathnames == false) {
+		status = canonicalize_snapshot_path(smb_fname);
+		if (!NT_STATUS_IS_OK(status)) {
+			goto err;
+		}
+	}
+
 	/*
 	 * Large directory fix normalization. If we're case sensitive, and
 	 * the case preserving parameters are set to "no", normalize the case of
diff -Nru samba-4.5.5+dfsg/source3/smbd/negprot.c samba-4.5.6+dfsg/source3/smbd/negprot.c
--- samba-4.5.5+dfsg/source3/smbd/negprot.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/smbd/negprot.c	2017-03-09 10:21:43.000000000 +0100
@@ -544,6 +544,8 @@
 	struct smbXsrv_connection *xconn = req->xconn;
 	struct smbd_server_connection *sconn = req->sconn;
 	bool signing_required = true;
+	int max_proto;
+	int min_proto;
 
 	START_PROFILE(SMBnegprot);
 
@@ -688,11 +690,28 @@
 			  FLAG_MSG_GENERAL|FLAG_MSG_SMBD
 			  |FLAG_MSG_PRINT_GENERAL);
 
+	/*
+	 * Anything higher than PROTOCOL_SMB2_10 still
+	 * needs to go via "SMB 2.???", which is marked
+	 * as PROTOCOL_SMB2_10.
+	 *
+	 * The real negotiation happens via reply_smb20ff()
+	 * using SMB2 Negotiation.
+	 */
+	max_proto = lp_server_max_protocol();
+	if (max_proto > PROTOCOL_SMB2_10) {
+		max_proto = PROTOCOL_SMB2_10;
+	}
+	min_proto = lp_server_min_protocol();
+	if (min_proto > PROTOCOL_SMB2_10) {
+		min_proto = PROTOCOL_SMB2_10;
+	}
+
 	/* Check for protocols, most desirable first */
 	for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
 		i = 0;
-		if ((supported_protocols[protocol].protocol_level <= lp_server_max_protocol()) &&
-				(supported_protocols[protocol].protocol_level >= lp_server_min_protocol()))
+		if ((supported_protocols[protocol].protocol_level <= max_proto) &&
+		    (supported_protocols[protocol].protocol_level >= min_proto))
 			while (i < num_cliprotos) {
 				if (strequal(cliprotos[i],supported_protocols[protocol].proto_name)) {
 					choice = i;
diff -Nru samba-4.5.5+dfsg/source3/smbd/open.c samba-4.5.6+dfsg/source3/smbd/open.c
--- samba-4.5.5+dfsg/source3/smbd/open.c	2017-01-17 20:55:44.000000000 +0100
+++ samba-4.5.6+dfsg/source3/smbd/open.c	2017-03-09 10:21:43.000000000 +0100
@@ -639,7 +639,9 @@
 			bool *file_created)
 {
 	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+	NTSTATUS retry_status;
 	bool file_existed = VALID_STAT(fsp->fsp_name->st);
+	int curr_flags;
 
 	*file_created = false;
 
@@ -671,59 +673,65 @@
 	 * we can never call O_CREAT without O_EXCL. So if
 	 * we think the file existed, try without O_CREAT|O_EXCL.
 	 * If we think the file didn't exist, try with
-	 * O_CREAT|O_EXCL. Keep bouncing between these two
-	 * requests until either the file is created, or
-	 * opened. Either way, we keep going until we get
-	 * a returnable result (error, or open/create).
+	 * O_CREAT|O_EXCL.
+	 *
+	 * The big problem here is dangling symlinks. Opening
+	 * without O_NOFOLLOW means both bad symlink
+	 * and missing path return -1, ENOENT from open(). As POSIX
+	 * is pathname based it's not possible to tell
+	 * the difference between these two cases in a
+	 * non-racy way, so change to try only two attempts before
+	 * giving up.
+	 *
+	 * We don't have this problem for the O_NOFOLLOW
+	 * case as it just returns NT_STATUS_OBJECT_PATH_NOT_FOUND
+	 * mapped from the ELOOP POSIX error.
 	 */
 
-	while(1) {
-		int curr_flags = flags;
+	curr_flags = flags;
 
-		if (file_existed) {
-			/* Just try open, do not create. */
-			curr_flags &= ~(O_CREAT);
-			status = fd_open(conn, fsp, curr_flags, mode);
-			if (NT_STATUS_EQUAL(status,
-					NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
-				/*
-				 * Someone deleted it in the meantime.
-				 * Retry with O_EXCL.
-				 */
-				file_existed = false;
-				DEBUG(10,("fd_open_atomic: file %s existed. "
-					"Retry.\n",
-					smb_fname_str_dbg(fsp->fsp_name)));
-					continue;
-			}
-		} else {
-			/* Try create exclusively, fail if it exists. */
-			curr_flags |= O_EXCL;
-			status = fd_open(conn, fsp, curr_flags, mode);
-			if (NT_STATUS_EQUAL(status,
-					NT_STATUS_OBJECT_NAME_COLLISION)) {
-				/*
-				 * Someone created it in the meantime.
-				 * Retry without O_CREAT.
-				 */
-				file_existed = true;
-				DEBUG(10,("fd_open_atomic: file %s "
-					"did not exist. Retry.\n",
-					smb_fname_str_dbg(fsp->fsp_name)));
-				continue;
-			}
-			if (NT_STATUS_IS_OK(status)) {
-				/*
-				 * Here we've opened with O_CREAT|O_EXCL
-				 * and got success. We *know* we created
-				 * this file.
-				 */
-				*file_created = true;
-			}
+	if (file_existed) {
+		curr_flags &= ~(O_CREAT);
+		retry_status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+	} else {
+		curr_flags |= O_EXCL;
+		retry_status = NT_STATUS_OBJECT_NAME_COLLISION;
+	}
+
+	status = fd_open(conn, fsp, curr_flags, mode);
+	if (NT_STATUS_IS_OK(status)) {
+		if (!file_existed) {
+			*file_created = true;
 		}
-		/* Create is done, or failed. */
-		break;
+		return NT_STATUS_OK;
+	}
+	if (!NT_STATUS_EQUAL(status, retry_status)) {
+		return status;
+	}
+
+	curr_flags = flags;
+
+	/*
+	 * Keep file_existed up to date for clarity.
+	 */
+	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+		file_existed = false;
+		curr_flags |= O_EXCL;
+		DBG_DEBUG("file %s did not exist. Retry.\n",
+			smb_fname_str_dbg(fsp->fsp_name));
+	} else {
+		file_existed = true;
+		curr_flags &= ~(O_CREAT);
+		DBG_DEBUG("file %s existed. Retry.\n",
+			smb_fname_str_dbg(fsp->fsp_name));
 	}
+
+	status = fd_open(conn, fsp, curr_flags, mode);
+
+	if (NT_STATUS_IS_OK(status) && (!file_existed)) {
+		*file_created = true;
+	}
+
 	return status;
 }
 
@@ -2274,6 +2282,12 @@
 	uint32_t orig_access_mask = access_mask;
 	uint32_t rejected_share_access;
 
+	if (access_mask & SEC_MASK_INVALID) {
+		DBG_DEBUG("access_mask [%8x] contains invalid bits\n",
+			  access_mask);
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
 	/*
 	 * Convert GENERIC bits to specific bits.
 	 */
diff -Nru samba-4.5.5+dfsg/source3/smbd/posix_acls.c samba-4.5.6+dfsg/source3/smbd/posix_acls.c
--- samba-4.5.5+dfsg/source3/smbd/posix_acls.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/smbd/posix_acls.c	2017-03-09 10:21:43.000000000 +0100
@@ -2700,9 +2700,9 @@
 			.attr = ALLOW_ACE,
 			.trustee = sid,
 			.unix_ug = unix_ug,
-			.owner_type = owner_type,
-			.ace_flags = get_pai_flags(pal, ace, is_default_acl)
+			.owner_type = owner_type
 		};
+		ace->ace_flags = get_pai_flags(pal, ace, is_default_acl);
 
 		DLIST_ADD(l_head, ace);
 	}
diff -Nru samba-4.5.5+dfsg/source3/smbd/service.c samba-4.5.6+dfsg/source3/smbd/service.c
--- samba-4.5.5+dfsg/source3/smbd/service.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/smbd/service.c	2017-03-09 10:21:43.000000000 +0100
@@ -31,6 +31,7 @@
 #include "lib/param/loadparm.h"
 #include "messages.h"
 #include "lib/afs/afs_funcs.h"
+#include "lib/util_path.h"
 
 static bool canonicalize_connect_path(connection_struct *conn)
 {
@@ -47,118 +48,20 @@
 /****************************************************************************
  Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
  absolute path stating in / and not ending in /.
- Observent people will notice a similarity between this and check_path_syntax :-).
 ****************************************************************************/
 
 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
 {
 	char *destname;
-	char *d;
-	const char *s = connectpath;
-        bool start_of_name_component = true;
 
 	if (connectpath == NULL || connectpath[0] == '\0') {
 		return false;
 	}
 
-	/* Allocate for strlen + '\0' + possible leading '/' */
-	destname = (char *)talloc_size(conn, strlen(connectpath) + 2);
-	if (!destname) {
+	destname = canonicalize_absolute_path(conn, connectpath);
+	if (destname == NULL) {
 		return false;
 	}
-	d = destname;
-
-	*d++ = '/'; /* Always start with root. */
-
-	while (*s) {
-		if (*s == '/') {
-			/* Eat multiple '/' */
-			while (*s == '/') {
-                                s++;
-                        }
-			if ((d > destname + 1) && (*s != '\0')) {
-				*d++ = '/';
-			}
-			start_of_name_component = True;
-			continue;
-		}
-
-		if (start_of_name_component) {
-			if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
-				/* Uh oh - "/../" or "/..\0" ! */
-
-				/* Go past the ../ or .. */
-				if (s[2] == '/') {
-					s += 3;
-				} else {
-					s += 2; /* Go past the .. */
-				}
-
-				/* If  we just added a '/' - delete it */
-				if ((d > destname) && (*(d-1) == '/')) {
-					*(d-1) = '\0';
-					d--;
-				}
-
-				/* Are we at the start ? Can't go back further if so. */
-				if (d <= destname) {
-					*d++ = '/'; /* Can't delete root */
-					continue;
-				}
-				/* Go back one level... */
-				/* Decrement d first as d points to the *next* char to write into. */
-				for (d--; d > destname; d--) {
-					if (*d == '/') {
-						break;
-					}
-				}
-				/* We're still at the start of a name component, just the previous one. */
-				continue;
-			} else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
-				/* Component of pathname can't be "." only - skip the '.' . */
-				if (s[1] == '/') {
-					s += 2;
-				} else {
-					s++;
-				}
-				continue;
-			}
-		}
-
-		if (!(*s & 0x80)) {
-			*d++ = *s++;
-		} else {
-			size_t siz;
-			/* Get the size of the next MB character. */
-			next_codepoint(s,&siz);
-			switch(siz) {
-				case 5:
-					*d++ = *s++;
-					/*fall through*/
-				case 4:
-					*d++ = *s++;
-					/*fall through*/
-				case 3:
-					*d++ = *s++;
-					/*fall through*/
-				case 2:
-					*d++ = *s++;
-					/*fall through*/
-				case 1:
-					*d++ = *s++;
-					break;
-				default:
-					break;
-			}
-		}
-		start_of_name_component = false;
-	}
-	*d = '\0';
-
-	/* And must not end in '/' */
-	if (d > destname + 1 && (*(d-1) == '/')) {
-		*(d-1) = '\0';
-	}
 
 	DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
 		lp_servicename(talloc_tos(), SNUM(conn)), destname ));
@@ -623,6 +526,18 @@
 	conn->short_case_preserve = lp_short_preserve_case(snum);
 
 	conn->encrypt_level = lp_smb_encrypt(snum);
+	if (conn->encrypt_level > SMB_SIGNING_OFF) {
+		if (lp_smb_encrypt(-1) == SMB_SIGNING_OFF) {
+			if (conn->encrypt_level == SMB_SIGNING_REQUIRED) {
+				DBG_ERR("Service [%s] requires encryption, but "
+					"it is disabled globally!\n",
+					lp_servicename(talloc_tos(), snum));
+				status = NT_STATUS_ACCESS_DENIED;
+				goto err_root_exit;
+			}
+			conn->encrypt_level = SMB_SIGNING_OFF;
+		}
+	}
 
 	conn->veto_list = NULL;
 	conn->hide_list = NULL;
diff -Nru samba-4.5.5+dfsg/source3/smbd/smb2_negprot.c samba-4.5.6+dfsg/source3/smbd/smb2_negprot.c
--- samba-4.5.5+dfsg/source3/smbd/smb2_negprot.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/smbd/smb2_negprot.c	2017-03-09 10:21:43.000000000 +0100
@@ -441,7 +441,7 @@
 		req->preauth = &req->xconn->smb2.preauth;
 	}
 
-	if (in_cipher != NULL) {
+	if ((capabilities & SMB2_CAP_ENCRYPTION) && (in_cipher != NULL)) {
 		size_t needed = 2;
 		uint16_t cipher_count;
 		const uint8_t *p;
diff -Nru samba-4.5.5+dfsg/source3/smbd/smb2_server.c samba-4.5.6+dfsg/source3/smbd/smb2_server.c
--- samba-4.5.5+dfsg/source3/smbd/smb2_server.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/smbd/smb2_server.c	2017-03-09 10:21:43.000000000 +0100
@@ -3566,6 +3566,7 @@
 	int ret;
 	int err;
 	bool retry;
+	NTSTATUS status;
 
 	if (xconn->smb2.send_queue == NULL) {
 		TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
@@ -3577,11 +3578,12 @@
 		bool ok;
 
 		if (e->sendfile_header != NULL) {
-			NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
 			size_t size = 0;
 			size_t i = 0;
 			uint8_t *buf;
 
+			status = NT_STATUS_INTERNAL_ERROR;
+
 			for (i=0; i < e->count; i++) {
 				size += e->vector[i].iov_len;
 			}
@@ -3653,6 +3655,16 @@
 		talloc_free(e->mem_ctx);
 	}
 
+	/*
+	 * Restart reads if we were blocked on
+	 * draining the send queue.
+	 */
+
+	status = smbd_smb2_request_next_incoming(xconn);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
 	return NT_STATUS_OK;
 }
 
diff -Nru samba-4.5.5+dfsg/source3/smbd/smb2_tcon.c samba-4.5.6+dfsg/source3/smbd/smb2_tcon.c
--- samba-4.5.5+dfsg/source3/smbd/smb2_tcon.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/smbd/smb2_tcon.c	2017-03-09 10:21:43.000000000 +0100
@@ -268,7 +268,8 @@
 	}
 
 	if ((lp_smb_encrypt(snum) >= SMB_SIGNING_DESIRED) &&
-	    (conn->smb2.client.capabilities & SMB2_CAP_ENCRYPTION)) {
+	    (conn->smb2.server.cipher != 0))
+	{
 		encryption_desired = true;
 	}
 
diff -Nru samba-4.5.5+dfsg/source3/torture/torture.c samba-4.5.6+dfsg/source3/torture/torture.c
--- samba-4.5.5+dfsg/source3/torture/torture.c	2017-01-17 20:55:44.000000000 +0100
+++ samba-4.5.6+dfsg/source3/torture/torture.c	2017-03-09 10:21:43.000000000 +0100
@@ -9501,6 +9501,106 @@
 	return success;
 }
 
+/*
+  Test Windows open on a bad POSIX symlink.
+ */
+static bool run_symlink_open_test(int dummy)
+{
+	static struct cli_state *cli;
+	const char *fname = "non_existant_file";
+	const char *sname = "dangling_symlink";
+	uint16_t fnum = (uint16_t)-1;
+	bool correct = false;
+	NTSTATUS status;
+	TALLOC_CTX *frame = NULL;
+
+	frame = talloc_stackframe();
+
+	printf("Starting Windows bad symlink open 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;
+	}
+
+	/* Ensure nothing exists. */
+	cli_setatr(cli, fname, 0, 0);
+	cli_posix_unlink(cli, fname);
+	cli_setatr(cli, sname, 0, 0);
+	cli_posix_unlink(cli, sname);
+
+	/* Create a symlink pointing nowhere. */
+	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;
+	}
+
+	/* Now ensure that a Windows open doesn't hang. */
+	status = cli_ntcreate(cli,
+			sname,
+			0,
+			FILE_READ_DATA|FILE_WRITE_DATA,
+			0,
+			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+			FILE_OPEN_IF,
+			0x0,
+			0x0,
+			&fnum,
+			NULL);
+
+	/*
+	 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
+	 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
+	 * we use O_NOFOLLOW on the server or not.
+	 */
+	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
+	    NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
+	{
+		correct = true;
+	} else {
+		printf("cli_ntcreate of %s returned %s - should return"
+				" either (%s) or (%s)\n",
+			sname,
+			nt_errstr(status),
+			nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
+			nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
+		goto out;
+	}
+
+	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 bool run_local_substitute(int dummy)
 {
 	bool ok = true;
@@ -10878,6 +10978,49 @@
 	return true;
 }
 
+static bool run_local_canonicalize_path(int dummy)
+{
+	const char *src[] = {
+			"/foo/..",
+			"/..",
+			"/foo/bar/../baz",
+			"/foo/././",
+			"/../foo",
+			".././././",
+			".././././../../../boo",
+			"./..",
+			NULL
+			};
+	const char *dst[] = {
+			"/",
+			"/",
+			"/foo/baz",
+			"/foo",
+			"/foo",
+			"/",
+			"/boo",
+			"/",
+			NULL
+			};
+	unsigned int i;
+
+	for (i = 0; src[i] != NULL; i++) {
+		char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
+		if (d == NULL) {
+			perror("talloc fail\n");
+			return false;
+		}
+		if (strcmp(d, dst[i]) != 0) {
+			d_fprintf(stderr,
+				"canonicalize missmatch %s -> %s != %s",
+				src[i], d, dst[i]);
+			return false;
+		}
+		talloc_free(d);
+	}
+	return true;
+}
+
 static double create_procs(bool (*fn)(int), bool *result)
 {
 	int i, status;
@@ -11020,6 +11163,7 @@
 	{"POSIX-SYMLINK-EA", run_ea_symlink_test, 0},
 	{"POSIX-STREAM-DELETE", run_posix_stream_delete, 0},
 	{"POSIX-OFD-LOCK", run_posix_ofd_lock_test, 0},
+	{"WINDOWS-BAD-SYMLINK", run_symlink_open_test, 0},
 	{"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
 	{"ASYNC-ECHO", run_async_echo, 0},
 	{ "UID-REGRESSION-TEST", run_uid_regression_test, 0},
@@ -11112,6 +11256,7 @@
 	{ "local-tdb-writer", run_local_tdb_writer, 0 },
 	{ "LOCAL-DBWRAP-CTDB", run_local_dbwrap_ctdb, 0 },
 	{ "LOCAL-BENCH-PTHREADPOOL", run_bench_pthreadpool, 0 },
+	{ "LOCAL-CANONICALIZE-PATH", run_local_canonicalize_path, 0 },
 	{ "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
 	{NULL, NULL, 0}};
 
diff -Nru samba-4.5.5+dfsg/source3/utils/net_rpc_trust.c samba-4.5.6+dfsg/source3/utils/net_rpc_trust.c
--- samba-4.5.5+dfsg/source3/utils/net_rpc_trust.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/utils/net_rpc_trust.c	2017-03-09 10:21:43.000000000 +0100
@@ -518,9 +518,9 @@
 			}
 
 			DEBUG(0, ("Using random trust password.\n"));
-			trust_pw = generate_random_password(mem_ctx,
-					DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH,
-					DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
+			trust_pw = trust_pw_new_value(mem_ctx,
+						      SEC_CHAN_DOMAIN,
+						      SEC_DOMAIN);
 			if (trust_pw == NULL) {
 				DEBUG(0, ("generate_random_password failed.\n"));
 				goto done;
diff -Nru samba-4.5.5+dfsg/source3/winbindd/idmap_ad.c samba-4.5.6+dfsg/source3/winbindd/idmap_ad.c
--- samba-4.5.5+dfsg/source3/winbindd/idmap_ad.c	2016-10-24 21:37:30.000000000 +0200
+++ samba-4.5.6+dfsg/source3/winbindd/idmap_ad.c	2017-03-09 10:21:43.000000000 +0100
@@ -22,7 +22,7 @@
 #include "idmap.h"
 #include "tldap_gensec_bind.h"
 #include "tldap_util.h"
-#include "secrets.h"
+#include "passdb.h"
 #include "lib/param/param.h"
 #include "utils/net.h"
 #include "auth/gensec/gensec.h"
@@ -243,7 +243,6 @@
 				       const char *domname,
 				       struct tldap_context **pld)
 {
-	struct db_context *db_ctx;
 	struct netr_DsRGetDCNameInfo *dcinfo;
 	struct sockaddr_storage dcaddr;
 	struct cli_credentials *creds;
@@ -294,11 +293,19 @@
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	creds = cli_credentials_init(dcinfo);
-	if (creds == NULL) {
-		DBG_DEBUG("cli_credentials_init failed\n");
+	/*
+	 * Here we use or own machine account as
+	 * we run as domain member.
+	 */
+	status = pdb_get_trust_credentials(lp_workgroup(),
+					   lp_realm(),
+					   dcinfo,
+					   &creds);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_DEBUG("pdb_get_trust_credentials() failed - %s\n",
+			  nt_errstr(status));
 		TALLOC_FREE(dcinfo);
-		return NT_STATUS_NO_MEMORY;
+		return status;
 	}
 
 	lp_ctx = loadparm_init_s3(dcinfo, loadparm_s3_helpers());
@@ -308,23 +315,6 @@
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	cli_credentials_set_conf(creds, lp_ctx);
-
-	db_ctx = secrets_db_ctx();
-	if (db_ctx == NULL) {
-		DBG_DEBUG("Failed to open secrets.tdb.\n");
-		return NT_STATUS_INTERNAL_ERROR;
-	}
-
-	status = cli_credentials_set_machine_account_db_ctx(creds, lp_ctx,
-							    db_ctx);
-	if (!NT_STATUS_IS_OK(status)) {
-		DBG_DEBUG("cli_credentials_set_machine_account "
-			  "failed: %s\n", nt_errstr(status));
-		TALLOC_FREE(dcinfo);
-		return status;
-	}
-
 	rc = tldap_gensec_bind(ld, creds, "ldap", dcinfo->dc_unc, NULL, lp_ctx,
 			       GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
 	if (!TLDAP_RC_IS_SUCCESS(rc)) {
diff -Nru samba-4.5.5+dfsg/source3/winbindd/winbindd_ads.c samba-4.5.6+dfsg/source3/winbindd/winbindd_ads.c
--- samba-4.5.5+dfsg/source3/winbindd/winbindd_ads.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/winbindd/winbindd_ads.c	2017-03-09 10:21:43.000000000 +0100
@@ -119,6 +119,8 @@
 	ads->auth.renewable = renewable;
 	ads->auth.password = password;
 
+	ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
+
 	ads->auth.realm = SMB_STRDUP(auth_realm);
 	if (!strupper_m(ads->auth.realm)) {
 		ads_destroy(&ads);
@@ -1700,6 +1702,14 @@
 			}
 			TALLOC_FREE(parent);
 
+			/*
+			 * We need to pass the modified properties
+			 * to the caller.
+			 */
+			trust->trust_flags = d.domain_flags;
+			trust->trust_type = d.domain_type;
+			trust->trust_attributes = d.domain_trust_attribs;
+
 			wcache_tdc_add_domain( &d );
 			ret_count++;
 		}
diff -Nru samba-4.5.5+dfsg/source3/winbindd/winbindd_cm.c samba-4.5.6+dfsg/source3/winbindd/winbindd_cm.c
--- samba-4.5.5+dfsg/source3/winbindd/winbindd_cm.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source3/winbindd/winbindd_cm.c	2017-03-09 10:21:43.000000000 +0100
@@ -903,7 +903,6 @@
 	struct cli_credentials *creds;
 	NTSTATUS status;
 	bool force_machine_account = false;
-	bool ok;
 
 	/* If we are a DC and this is not our own domain */
 
@@ -937,24 +936,7 @@
 		goto ipc_fallback;
 	}
 
-	if (domain->primary && lp_security() == SEC_ADS) {
-		cli_credentials_set_kerberos_state(creds,
-						   CRED_AUTO_USE_KERBEROS);
-	} else if (domain->active_directory) {
-		cli_credentials_set_kerberos_state(creds,
-						   CRED_MUST_USE_KERBEROS);
-	} else {
-		cli_credentials_set_kerberos_state(creds,
-						   CRED_DONT_USE_KERBEROS);
-	}
-
-	/*
-	 * When we contact our own domain and get a list of the trusted domain
-	 * we have the information if we are able to contact the DC with
-	 * with our machine account password.
-	 */
-	ok = winbindd_can_contact_domain(domain);
-	if (!ok) {
+	if (creds_domain != domain) {
 		/*
 		 * We can only use schannel against a direct trust
 		 */
@@ -1002,6 +984,8 @@
 	struct named_mutex *mutex;
 
 	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+	NTSTATUS tmp_status;
+	NTSTATUS tcon_status = NT_STATUS_NETWORK_NAME_DELETED;
 
 	enum smb_signing_setting smb_sign_client_connections = lp_client_ipc_signing();
 
@@ -1103,6 +1087,10 @@
 		}
 	}
 
+	if (cli_credentials_is_anonymous(creds)) {
+		goto anon_fallback;
+	}
+
 	krb5_state = cli_credentials_get_kerberos_state(creds);
 
 	machine_krb5_principal = cli_credentials_get_principal(creds,
@@ -1138,8 +1126,10 @@
 			goto session_setup_done;
 		}
 
-		DEBUG(4,("failed kerberos session setup with %s\n",
-			 nt_errstr(result)));
+		DEBUG(1, ("Failed to use kerberos connecting to %s from %s "
+			  "with kerberos principal [%s]\n",
+			  controller, lp_netbios_name(),
+			  machine_krb5_principal));
 	}
 
 	if (krb5_state != CRED_MUST_USE_KERBEROS) {
@@ -1157,10 +1147,15 @@
 					   machine_password,
 					   strlen(machine_password)+1,
 					   machine_domain);
-	}
 
-	if (NT_STATUS_IS_OK(result)) {
-		goto session_setup_done;
+		if (NT_STATUS_IS_OK(result)) {
+			goto session_setup_done;
+		}
+
+		DEBUG(1, ("Failed to use NTLMSSP connecting to %s from %s "
+			  "with username [%s]\\[%s]\n",
+			  controller, lp_netbios_name(),
+			  machine_domain, machine_account));
 	}
 
 	/*
@@ -1174,10 +1169,6 @@
 	    || NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)
 	    || NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE))
 	{
-		if (cli_credentials_is_anonymous(creds)) {
-			goto done;
-		}
-
 		if (!cm_is_ipc_credentials(creds)) {
 			goto ipc_fallback;
 		}
@@ -1189,19 +1180,22 @@
 		goto anon_fallback;
 	}
 
-	DEBUG(4, ("authenticated session setup failed with %s\n",
-		nt_errstr(result)));
+	DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
+		  controller,
+		  cli_credentials_get_unparsed_name(creds, talloc_tos()),
+		  nt_errstr(result)));
 
 	goto done;
 
  ipc_fallback:
-	result = cm_get_ipc_credentials(talloc_tos(), &creds);
-	if (!NT_STATUS_IS_OK(result)) {
+	TALLOC_FREE(creds);
+	tmp_status = cm_get_ipc_credentials(talloc_tos(), &creds);
+	if (!NT_STATUS_IS_OK(tmp_status)) {
+		result = tmp_status;
 		goto done;
 	}
 
 	if (cli_credentials_is_anonymous(creds)) {
-		TALLOC_FREE(creds);
 		goto anon_fallback;
 	}
 
@@ -1228,6 +1222,11 @@
 		goto session_setup_done;
 	}
 
+	DEBUG(1, ("Failed to use NTLMSSP connecting to %s from %s "
+		  "with username "
+		  "[%s]\\[%s]\n",  controller, lp_netbios_name(),
+		  machine_domain, machine_account));
+
 	/*
 	 * If we are not going to validiate the conneciton
 	 * with SMB signing, then allow us to fall back to
@@ -1242,19 +1241,22 @@
 		goto anon_fallback;
 	}
 
-	DEBUG(4, ("authenticated session setup failed with %s\n",
-		nt_errstr(result)));
+	DEBUG(1, ("authenticated session setup to %s using %s failed with %s\n",
+		  controller,
+		  cli_credentials_get_unparsed_name(creds, talloc_tos()),
+		  nt_errstr(result)));
 
 	goto done;
 
  anon_fallback:
+	TALLOC_FREE(creds);
 
 	if (smb_sign_client_connections == SMB_SIGNING_REQUIRED) {
 		goto done;
 	}
 
 	/* Fall back to anonymous connection, this might fail later */
-	DEBUG(10,("cm_prepare_connection: falling back to anonymous "
+	DEBUG(5,("cm_prepare_connection: falling back to anonymous "
 		"connection for DC %s\n",
 		controller ));
 
@@ -1266,6 +1268,9 @@
 		goto session_setup_done;
 	}
 
+	DEBUG(1, ("anonymous session setup to %s failed with %s\n",
+		  controller, nt_errstr(result)));
+
 	/* We can't session setup */
 	goto done;
 
@@ -1283,11 +1288,11 @@
 	}
 
 	result = cli_tree_connect(*cli, "IPC$", "IPC", "", 0);
-
 	if (!NT_STATUS_IS_OK(result)) {
 		DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
 		goto done;
 	}
+	tcon_status = result;
 
 	/* cache the server name for later connections */
 
@@ -1306,7 +1311,13 @@
  done:
 	TALLOC_FREE(mutex);
 
+	if (NT_STATUS_IS_OK(result)) {
+		result = tcon_status;
+	}
+
 	if (!NT_STATUS_IS_OK(result)) {
+		DEBUG(1, ("Failed to prepare SMB connection to %s: %s\n",
+			  controller, nt_errstr(result)));
 		winbind_add_failed_connection_entry(domain, controller, result);
 		if ((*cli) != NULL) {
 			cli_shutdown(*cli);
@@ -3293,9 +3304,28 @@
 
 	sec_chan_type = cli_credentials_get_secure_channel_type(creds);
 	if (sec_chan_type == SEC_CHAN_NULL) {
-		DBG_WARNING("get_secure_channel_type gave SEC_CHAN_NULL for %s\n",
-			    domain->name);
-		return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+		if (transport == NCACN_IP_TCP) {
+			DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
+				   " deny NCACN_IP_TCP and let the caller fallback to NCACN_NP.\n",
+				   domain->name);
+			return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+		}
+
+		DBG_NOTICE("get_secure_channel_type gave SEC_CHAN_NULL for %s, "
+			   "fallback to noauth on NCACN_NP.\n",
+			   domain->name);
+
+		result = cli_rpc_pipe_open_noauth_transport(conn->cli,
+							    transport,
+							    &ndr_table_netlogon,
+							    &conn->netlogon_pipe);
+		if (!NT_STATUS_IS_OK(result)) {
+			invalidate_cm_connection(domain);
+			return result;
+		}
+
+		*cli = conn->netlogon_pipe;
+		return NT_STATUS_OK;
 	}
 
 	result = rpccli_create_netlogon_creds_with_creds(creds,
@@ -3334,11 +3364,6 @@
 	conn->netlogon_flags = netlogon_creds->negotiate_flags;
 	TALLOC_FREE(netlogon_creds);
 
-	/*
-	 * FIXME: Document in which case we are not able to contact
-	 * a DC without schannel. Which information do we try to get
-	 * from this DC?
-	 */
 	if (!(conn->netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
 		if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
 			result = NT_STATUS_DOWNGRADE_DETECTED;
diff -Nru samba-4.5.5+dfsg/source3/winbindd/winbindd_util.c samba-4.5.6+dfsg/source3/winbindd/winbindd_util.c
--- samba-4.5.5+dfsg/source3/winbindd/winbindd_util.c	2016-10-24 21:37:30.000000000 +0200
+++ samba-4.5.6+dfsg/source3/winbindd/winbindd_util.c	2017-03-09 10:21:43.000000000 +0100
@@ -345,6 +345,20 @@
 	char *p;
 	struct winbindd_tdc_domain trust_params = {0};
 	ptrdiff_t extra_len;
+	bool within_forest = false;
+
+	/*
+	 * Only when we enumerate our primary domain
+	 * or our forest root domain, we should keep
+	 * the NETR_TRUST_FLAG_IN_FOREST flag, in
+	 * all other cases we need to clear it as the domain
+	 * is not part of our forest.
+	 */
+	if (state->domain->primary) {
+		within_forest = true;
+	} else if (domain_is_forest_root(state->domain)) {
+		within_forest = true;
+	}
 
 	res = wb_domain_request_recv(req, state, &response, &err);
 	if ((res == -1) || (response->result != WINBINDD_OK)) {
@@ -430,6 +444,14 @@
 
 		trust_params.trust_attribs = (uint32_t)strtoul(q, NULL, 10);
 
+		if (!within_forest) {
+			trust_params.trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
+		}
+
+		if (!state->domain->primary) {
+			trust_params.trust_flags &= ~NETR_TRUST_FLAG_PRIMARY;
+		}
+
 		/*
 		 * We always call add_trusted_domain() cause on an existing
 		 * domain structure, it will update the SID if necessary.
diff -Nru samba-4.5.5+dfsg/source3/wscript_build samba-4.5.6+dfsg/source3/wscript_build
--- samba-4.5.5+dfsg/source3/wscript_build	2016-10-24 21:37:30.000000000 +0200
+++ samba-4.5.6+dfsg/source3/wscript_build	2017-03-09 10:21:43.000000000 +0100
@@ -455,7 +455,7 @@
                    libads/ldap_schema.c
                    libads/util.c
                    libads/ndr.c''',
-                   deps='cli-ldap-common krb5samba ldap lber KRBCLIENT param LIBNMB libsmb DCUTIL smbldap',
+                   deps='cli-ldap-common krb5samba ldap lber KRBCLIENT param LIBNMB libsmb DCUTIL smbldap trusts_util',
                    private_library=True)
 
 bld.SAMBA3_SUBSYSTEM('LIBADS_SERVER',
diff -Nru samba-4.5.5+dfsg/source4/dsdb/samdb/ldb_modules/password_hash.c samba-4.5.6+dfsg/source4/dsdb/samdb/ldb_modules/password_hash.c
--- samba-4.5.5+dfsg/source4/dsdb/samdb/ldb_modules/password_hash.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source4/dsdb/samdb/ldb_modules/password_hash.c	2017-03-09 10:21:43.000000000 +0100
@@ -35,6 +35,7 @@
 #include "includes.h"
 #include "ldb_module.h"
 #include "libcli/auth/libcli_auth.h"
+#include "libcli/security/dom_sid.h"
 #include "system/kerberos.h"
 #include "auth/kerberos/kerberos.h"
 #include "dsdb/samdb/samdb.h"
@@ -125,6 +126,7 @@
 		const char *sAMAccountName;
 		const char *user_principal_name;
 		bool is_computer;
+		bool is_krbtgt;
 		uint32_t restrictions;
 	} u;
 
@@ -2793,6 +2795,8 @@
 		ldb_get_opaque(ldb, "loadparm"), struct loadparm_context);
 	int ret;
 	const struct ldb_message *info_msg = NULL;
+	struct dom_sid *account_sid = NULL;
+	int rodc_krbtgt = 0;
 
 	ZERO_STRUCTP(io);
 
@@ -2837,6 +2841,26 @@
 								      "userPrincipalName", NULL);
 	io->u.is_computer		= ldb_msg_check_string_attribute(info_msg, "objectClass", "computer");
 
+	/* Ensure it has an objectSID too */
+	account_sid = samdb_result_dom_sid(ac, info_msg, "objectSid");
+	if (account_sid != NULL) {
+		NTSTATUS status;
+		uint32_t rid = 0;
+
+		status = dom_sid_split_rid(account_sid, account_sid, NULL, &rid);
+		if (NT_STATUS_IS_OK(status)) {
+			if (rid == DOMAIN_RID_KRBTGT) {
+				io->u.is_krbtgt = true;
+			}
+		}
+	}
+
+	rodc_krbtgt = ldb_msg_find_attr_as_int(info_msg,
+			"msDS-SecondaryKrbTgtNumber", 0);
+	if (rodc_krbtgt != 0) {
+		io->u.is_krbtgt = true;
+	}
+
 	if (io->u.sAMAccountName == NULL) {
 		ldb_asprintf_errstring(ldb,
 				       "setup_io: sAMAccountName attribute is missing on %s for attempted password set/change",
@@ -2867,6 +2891,12 @@
 		& (UF_INTERDOMAIN_TRUST_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT
 			| UF_SERVER_TRUST_ACCOUNT));
 
+	if (io->u.is_krbtgt) {
+		io->u.restrictions = 0;
+		io->ac->status->domain_data.pwdHistoryLength =
+			MAX(io->ac->status->domain_data.pwdHistoryLength, 3);
+	}
+
 	if (ac->userPassword) {
 		ret = msg_find_old_and_new_pwd_val(client_msg, "userPassword",
 						   ac->req->operation,
@@ -3172,6 +3202,59 @@
 		return ldb_operr(ldb);
 	}
 
+	if (io->u.is_krbtgt) {
+		size_t min = 196;
+		size_t max = 255;
+		size_t diff = max - min;
+		size_t len = max;
+		struct ldb_val *krbtgt_utf16 = NULL;
+
+		if (!ac->pwd_reset) {
+			return dsdb_module_werror(ac->module,
+					LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS,
+					WERR_DS_ATT_ALREADY_EXISTS,
+					"Password change on krbtgt not permitted!");
+		}
+
+		if (io->n.cleartext_utf16 == NULL) {
+			return dsdb_module_werror(ac->module,
+					LDB_ERR_UNWILLING_TO_PERFORM,
+					WERR_DS_INVALID_ATTRIBUTE_SYNTAX,
+					"Password reset on krbtgt requires UTF16!");
+		}
+
+		/*
+		 * Instead of taking the callers value,
+		 * we just generate a new random value here.
+		 *
+		 * Include null termination in the array.
+		 */
+		if (diff > 0) {
+			size_t tmp;
+
+			generate_random_buffer((uint8_t *)&tmp, sizeof(tmp));
+
+			tmp %= diff;
+
+			len = min + tmp;
+		}
+
+		krbtgt_utf16 = talloc_zero(io->ac, struct ldb_val);
+		if (krbtgt_utf16 == NULL) {
+			return ldb_oom(ldb);
+		}
+
+		*krbtgt_utf16 = data_blob_talloc_zero(krbtgt_utf16,
+						      (len+1)*2);
+		if (krbtgt_utf16->data == NULL) {
+			return ldb_oom(ldb);
+		}
+		krbtgt_utf16->length = len * 2;
+		generate_secret_buffer(krbtgt_utf16->data,
+				       krbtgt_utf16->length);
+		io->n.cleartext_utf16 = krbtgt_utf16;
+	}
+
 	if (existing_msg != NULL) {
 		NTSTATUS status;
 
@@ -4055,6 +4138,7 @@
 					      "badPasswordTime",
 					      "badPwdCount",
 					      "lockoutTime",
+					      "msDS-SecondaryKrbTgtNumber",
 					      NULL };
 	struct ldb_request *search_req;
 	int ret;
diff -Nru samba-4.5.5+dfsg/source4/dsdb/samdb/ldb_modules/repl_meta_data.c samba-4.5.6+dfsg/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
--- samba-4.5.5+dfsg/source4/dsdb/samdb/ldb_modules/repl_meta_data.c	2016-10-24 21:37:30.000000000 +0200
+++ samba-4.5.6+dfsg/source4/dsdb/samdb/ldb_modules/repl_meta_data.c	2017-03-09 10:21:43.000000000 +0100
@@ -1446,15 +1446,21 @@
 				       NTTIME now,
 				       bool is_schema_nc)
 {
+	const char *rdn_name = ldb_dn_get_rdn_name(msg->dn);
+	const struct dsdb_attribute *rdn_attr =
+		dsdb_attribute_by_lDAPDisplayName(ar->schema, rdn_name);
+	const char *attr_name = rdn_attr != NULL ?
+				rdn_attr->lDAPDisplayName :
+				rdn_name;
 	struct ldb_message_element new_el = {
 		.flags = LDB_FLAG_MOD_REPLACE,
-		.name = ldb_dn_get_rdn_name(msg->dn),
+		.name = attr_name,
 		.num_values = 1,
 		.values = discard_const_p(struct ldb_val, rdn_new)
 	};
 	struct ldb_message_element old_el = {
 		.flags = LDB_FLAG_MOD_REPLACE,
-		.name = ldb_dn_get_rdn_name(msg->dn),
+		.name = attr_name,
 		.num_values = rdn_old ? 1 : 0,
 		.values = discard_const_p(struct ldb_val, rdn_old)
 	};
diff -Nru samba-4.5.5+dfsg/source4/dsdb/samdb/ldb_modules/samba_dsdb.c samba-4.5.6+dfsg/source4/dsdb/samdb/ldb_modules/samba_dsdb.c
--- samba-4.5.5+dfsg/source4/dsdb/samdb/ldb_modules/samba_dsdb.c	2016-08-11 09:51:04.000000000 +0200
+++ samba-4.5.6+dfsg/source4/dsdb/samdb/ldb_modules/samba_dsdb.c	2017-03-09 10:21:43.000000000 +0100
@@ -231,7 +231,7 @@
 static int samba_dsdb_init(struct ldb_module *module)
 {
 	struct ldb_context *ldb = ldb_module_get_ctx(module);
-	int ret, len, i;
+	int ret, len, i, j;
 	TALLOC_CTX *tmp_ctx = talloc_new(module);
 	struct ldb_result *res;
 	struct ldb_message *rootdse_msg = NULL, *partition_msg;
@@ -317,11 +317,15 @@
 	static const char *openldap_backend_modules[] = {
 		"dsdb_flags_ignore", "entryuuid", "simple_dn", NULL };
 
-	static const char *samba_dsdb_attrs[] = { "backendType", NULL };
+	static const char *samba_dsdb_attrs[] = { "backendType",
+						  SAMBA_COMPATIBLE_FEATURES_ATTR,
+						  SAMBA_REQUIRED_FEATURES_ATTR, NULL };
 	static const char *partition_attrs[] = { "ldapBackend", NULL };
 	const char *backendType, *backendUrl;
 	bool use_sasl_external = false;
 
+	const char *current_supportedFeatures[] = {};
+
 	if (!tmp_ctx) {
 		return ldb_oom(ldb);
 	}
@@ -357,7 +361,77 @@
 	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
 		backendType = "ldb";
 	} else if (ret == LDB_SUCCESS) {
+		struct ldb_message_element *requiredFeatures;
+		struct ldb_message_element *old_compatibleFeatures;
+
 		backendType = ldb_msg_find_attr_as_string(res->msgs[0], "backendType", "ldb");
+
+		requiredFeatures = ldb_msg_find_element(res->msgs[0], SAMBA_REQUIRED_FEATURES_ATTR);
+		if (requiredFeatures != NULL) {
+			ldb_set_errstring(ldb, "This Samba database was created with "
+					  "a newer Samba version and is marked with "
+					  "requiredFeatures in @SAMBA_DSDB.  "
+					  "This database can not safely be read by this Samba version");
+			return LDB_ERR_OPERATIONS_ERROR;
+		}
+
+		old_compatibleFeatures = ldb_msg_find_element(res->msgs[0],
+							      SAMBA_COMPATIBLE_FEATURES_ATTR);
+
+		if (old_compatibleFeatures) {
+			struct ldb_message *features_msg;
+			struct ldb_message_element *features_el;
+
+			features_msg = ldb_msg_new(res);
+			if (features_msg == NULL) {
+				return ldb_module_operr(module);
+			}
+			features_msg->dn = samba_dsdb_dn;
+
+			ldb_msg_add_empty(features_msg, SAMBA_COMPATIBLE_FEATURES_ATTR,
+					  LDB_FLAG_MOD_DELETE, &features_el);
+
+			for (i = 0;
+			     old_compatibleFeatures && i < old_compatibleFeatures->num_values;
+			     i++) {
+				for (j = 0;
+				     j < ARRAY_SIZE(current_supportedFeatures); j++) {
+					if (strcmp((char *)old_compatibleFeatures->values[i].data,
+						   current_supportedFeatures[j]) == 0) {
+						break;
+					}
+				}
+				if (j == ARRAY_SIZE(current_supportedFeatures)) {
+					/*
+					 * Add to list of features to remove
+					 * (rather than all features)
+					 */
+					ret = ldb_msg_add_value(features_msg, SAMBA_COMPATIBLE_FEATURES_ATTR,
+								&old_compatibleFeatures->values[i],
+								NULL);
+					if (ret != LDB_SUCCESS) {
+						return ret;
+					}
+				}
+			}
+			if (features_el->num_values > 0) {
+				/* Delete by list */
+				ret = ldb_next_start_trans(module);
+				if (ret != LDB_SUCCESS) {
+					return ret;
+				}
+				ret = dsdb_module_modify(module, features_msg, DSDB_FLAG_NEXT_MODULE, NULL);
+				if (ret != LDB_SUCCESS) {
+					ldb_next_del_trans(module);
+					return ret;
+				}
+				ret = ldb_next_end_trans(module);
+				if (ret != LDB_SUCCESS) {
+					return ret;
+				}
+			}
+		}
+
 	} else {
 		talloc_free(tmp_ctx);
 		return ret;
diff -Nru samba-4.5.5+dfsg/source4/dsdb/samdb/ldb_modules/samldb.c samba-4.5.6+dfsg/source4/dsdb/samdb/ldb_modules/samldb.c
--- samba-4.5.5+dfsg/source4/dsdb/samdb/ldb_modules/samldb.c	2016-12-05 09:18:44.000000000 +0100
+++ samba-4.5.6+dfsg/source4/dsdb/samdb/ldb_modules/samldb.c	2017-03-09 10:21:43.000000000 +0100
@@ -386,7 +386,6 @@
 	struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
 	uint32_t krbtgt_number, i_start, i;
 	int ret;
-	char *newpass;
 	struct ldb_val newpass_utf16;
 
 	/* find a unused msDC-SecondaryKrbTgtNumber */
@@ -432,21 +431,17 @@
 		return ldb_operr(ldb);
 	}
 
-	newpass = generate_random_password(ac->msg, 128, 255);
-	if (newpass == NULL) {
-		return ldb_operr(ldb);
-	}
-
-	if (!convert_string_talloc(ac,
-				   CH_UNIX, CH_UTF16,
-				   newpass, strlen(newpass),
-				   (void *)&newpass_utf16.data,
-				   &newpass_utf16.length)) {
-		ldb_asprintf_errstring(ldb,
-				       "samldb_rodc_add: "
-				       "failed to generate UTF16 password from random password");
-		return LDB_ERR_OPERATIONS_ERROR;
-	}
+	newpass_utf16 = data_blob_talloc_zero(ac->module, 256);
+	if (newpass_utf16.data == NULL) {
+		return ldb_oom(ldb);
+	}
+	/*
+	 * Note that the password_hash module will ignore
+	 * this value and use it's own generate_secret_buffer()
+	 * that's why we can just use generate_random_buffer()
+	 * here.
+	 */
+	generate_random_buffer(newpass_utf16.data, newpass_utf16.length);
 	ret = ldb_msg_add_steal_value(ac->msg, "clearTextPassword", &newpass_utf16);
 	if (ret != LDB_SUCCESS) {
 		return ldb_operr(ldb);
diff -Nru samba-4.5.5+dfsg/source4/dsdb/samdb/samdb.h samba-4.5.6+dfsg/source4/dsdb/samdb/samdb.h
--- samba-4.5.5+dfsg/source4/dsdb/samdb/samdb.h	2016-12-05 09:18:44.000000000 +0100
+++ samba-4.5.6+dfsg/source4/dsdb/samdb/samdb.h	2017-03-09 10:21:43.000000000 +0100
@@ -314,4 +314,6 @@
  */
 #define DSDB_FLAG_INTERNAL_FORCE_META_DATA 0x10000
 
+#define SAMBA_COMPATIBLE_FEATURES_ATTR "compatibleFeatures"
+#define SAMBA_REQUIRED_FEATURES_ATTR "requiredFeatures"
 #endif /* __SAMDB_H__ */
diff -Nru samba-4.5.5+dfsg/source4/ldap_server/ldap_bind.c samba-4.5.6+dfsg/source4/ldap_server/ldap_bind.c
--- samba-4.5.5+dfsg/source4/ldap_server/ldap_bind.c	2016-08-11 09:51:05.000000000 +0200
+++ samba-4.5.6+dfsg/source4/ldap_server/ldap_bind.c	2017-03-09 10:21:43.000000000 +0100
@@ -29,6 +29,37 @@
 #include "param/param.h"
 #include "../lib/util/tevent_ntstatus.h"
 
+static char *ldapsrv_bind_error_msg(TALLOC_CTX *mem_ctx,
+				    HRESULT hresult,
+				    uint32_t DSID,
+				    NTSTATUS status)
+{
+	WERROR werr;
+	char *msg = NULL;
+
+	status = nt_status_squash(status);
+	werr = ntstatus_to_werror(status);
+
+	/*
+	 * There are 4 lower case hex digits following 'v' at the end,
+	 * but different Windows Versions return different values:
+	 *
+	 * Windows 2008R2 uses 'v1db1'
+	 * Windows 2012R2 uses 'v2580'
+	 *
+	 * We just match Windows 2008R2 as that's what was referenced
+	 * in https://bugzilla.samba.org/show_bug.cgi?id=9048
+	 */
+	msg = talloc_asprintf(mem_ctx, "%08X: LdapErr: DSID-%08X, comment: "
+			      "AcceptSecurityContext error, data %x, v1db1",
+			      (unsigned)HRES_ERROR_V(hresult),
+			      (unsigned)DSID,
+			      (unsigned)W_ERROR_V(werr));
+
+	return msg;
+}
+
+
 static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
 {
 	struct ldap_BindRequest *req = &call->request->r.BindRequest;
@@ -95,7 +126,8 @@
 		status = nt_status_squash(status);
 
 		result = LDAP_INVALID_CREDENTIALS;
-		errstr = talloc_asprintf(reply, "Simple Bind Failed: %s", nt_errstr(status));
+		errstr = ldapsrv_bind_error_msg(reply, HRES_SEC_E_INVALID_TOKEN,
+						0x0C0903A9, status);
 	}
 
 do_reply:
@@ -346,7 +378,8 @@
 		status = nt_status_squash(status);
 		if (result == 0) {
 			result = LDAP_INVALID_CREDENTIALS;
-			errstr = talloc_asprintf(reply, "SASL:[%s]: %s", req->creds.SASL.mechanism, nt_errstr(status));
+			errstr = ldapsrv_bind_error_msg(reply, HRES_SEC_E_LOGON_DENIED,
+							0x0C0904DC, status);
 		}
 		talloc_unlink(conn, conn->gensec);
 		conn->gensec = NULL;
diff -Nru samba-4.5.5+dfsg/source4/libcli/raw/smb.h samba-4.5.6+dfsg/source4/libcli/raw/smb.h
--- samba-4.5.5+dfsg/source4/libcli/raw/smb.h	2016-08-11 09:51:05.000000000 +0200
+++ samba-4.5.6+dfsg/source4/libcli/raw/smb.h	2017-03-09 10:21:43.000000000 +0100
@@ -297,13 +297,6 @@
 
 #define UID_FIELD_INVALID 0
 
-/* The maximum length of a trust account password.
-   Used when we randomly create it, 15 char passwords
-   exceed NT4's max password length */
-
-#define DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH 14
-
-
 /*
   filesystem attribute bits
 */
diff -Nru samba-4.5.5+dfsg/source4/libnet/libnet_vampire.c samba-4.5.6+dfsg/source4/libnet/libnet_vampire.c
--- samba-4.5.5+dfsg/source4/libnet/libnet_vampire.c	2016-12-05 09:18:44.000000000 +0100
+++ samba-4.5.6+dfsg/source4/libnet/libnet_vampire.c	2017-03-09 10:21:43.000000000 +0100
@@ -160,7 +160,7 @@
 	settings.realm = s->realm;
 	settings.domain = s->domain_name;
 	settings.server_dn_str = p->dest_dsa->server_dn_str;
-	settings.machine_password = generate_random_password(s, 16, 255);
+	settings.machine_password = generate_random_machine_password(s, 128, 255);
 	settings.targetdir = s->targetdir;
 	settings.use_ntvfs = true;
 	status = provision_bare(s, s->lp_ctx, &settings, &result);
diff -Nru samba-4.5.5+dfsg/source4/scripting/bin/renamedc samba-4.5.6+dfsg/source4/scripting/bin/renamedc
--- samba-4.5.5+dfsg/source4/scripting/bin/renamedc	2016-08-11 09:51:05.000000000 +0200
+++ samba-4.5.6+dfsg/source4/scripting/bin/renamedc	2017-03-09 10:21:43.000000000 +0100
@@ -95,7 +95,7 @@
 
     # Then change password and samaccountname and dnshostname
     msg = ldb.Message(newdn)
-    machinepass = samba.generate_random_password(128, 255)
+    machinepass = samba.generate_random_machine_password(128, 255)
     mputf16 = machinepass.encode('utf-16-le')
 
     account = "%s$" % opts.newname.upper()
diff -Nru samba-4.5.5+dfsg/source4/selftest/tests.py samba-4.5.6+dfsg/source4/selftest/tests.py
--- samba-4.5.5+dfsg/source4/selftest/tests.py	2016-12-05 09:18:44.000000000 +0100
+++ samba-4.5.6+dfsg/source4/selftest/tests.py	2017-03-09 10:21:43.000000000 +0100
@@ -625,6 +625,11 @@
 plantestsuite("samba4.blackbox.samba3dump", "none", [os.path.join(samba4srcdir, "selftest/test_samba3dump.sh")])
 plantestsuite("samba4.blackbox.upgrade", "none", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_s3upgrade.sh"), '$PREFIX/provision'])
 plantestsuite("samba4.blackbox.provision.py", "none", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_provision.sh"), '$PREFIX/provision'])
+plantestsuite("samba4.blackbox.supported_features", "none",
+              ["PYTHON=%s" % python,
+               os.path.join(samba4srcdir,
+                            "setup/tests/blackbox_supported_features.sh"),
+               '$PREFIX/provision'])
 plantestsuite("samba4.blackbox.upgradeprovision.current", "none", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_upgradeprovision.sh"), '$PREFIX/provision'])
 plantestsuite("samba4.blackbox.setpassword.py", "none", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_setpassword.sh"), '$PREFIX/provision'])
 plantestsuite("samba4.blackbox.newuser.py", "none", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_newuser.sh"), '$PREFIX/provision'])
diff -Nru samba-4.5.5+dfsg/source4/setup/tests/blackbox_supported_features.sh samba-4.5.6+dfsg/source4/setup/tests/blackbox_supported_features.sh
--- samba-4.5.5+dfsg/source4/setup/tests/blackbox_supported_features.sh	1970-01-01 01:00:00.000000000 +0100
+++ samba-4.5.6+dfsg/source4/setup/tests/blackbox_supported_features.sh	2017-03-09 10:21:43.000000000 +0100
@@ -0,0 +1,86 @@
+#!/bin/sh
+
+if [ $# -lt 1 ]; then
+cat <<EOF
+Usage: blackbox_supported_features.sh PREFIX
+EOF
+exit 1;
+fi
+
+PREFIX="$1"
+shift 1
+
+DBPATH=$PREFIX/supported-features
+
+. `dirname $0`/../../../testprogs/blackbox/subunit.sh
+
+ldbmodify="ldbmodify"
+if [ -x "$BINDIR/ldbmodify" ]; then
+    ldbmodify="$BINDIR/ldbmodify"
+fi
+
+ldbdel="ldbdel"
+if [ -x "$BINDIR/ldbdel" ]; then
+    ldbdel="$BINDIR/ldbdel"
+fi
+
+ldbsearch="ldbsearch"
+if [ -x "$BINDIR/ldbsearch" ]; then
+    ldbsearch="$BINDIR/ldbsearch"
+fi
+
+testit "provision" $PYTHON $BINDIR/samba-tool domain provision \
+       --domain=FOO --realm=foo.example.com \
+       --targetdir=$DBPATH --use-ntvfs
+
+testit "add-compatible-feature" $ldbmodify \
+       -H tdb://$DBPATH/private/sam.ldb <<EOF
+dn: @SAMBA_DSDB
+changetype: modify
+add: compatibleFeatures
+compatibleFeatures: non-existent-feature
+-
+
+EOF
+
+# The non-existent feature is not compatible with this version, so it
+# should not be listed in compatibleFeatures even though we tried to
+# put it there.
+
+ldb_search_fail() {
+    $ldbsearch -H tdb://$DBPATH/private/sam.ldb \
+               -s base -b "$1" "$2" \
+        |   grep -q "$3"
+}
+
+
+testit_expect_failure "find-compatible-feature" \
+                      ldb_search_fail '@SAMBA_DSDB' 'compatibleFeatures' non-existent-feature
+
+
+# just make sure the thing we're using is normally findable
+testit "find-test-feature" \
+       $ldbsearch -H tdb://$DBPATH/private/sam.ldb \
+       -b 'CN=LostAndFound,DC=foo,DC=example,DC=com'
+
+
+testit "add-required-feature" $ldbmodify \
+       -H tdb://$DBPATH/private/sam.ldb <<EOF
+dn: @SAMBA_DSDB
+changetype: modify
+add: requiredFeatures
+requiredFeatures: futuristic-feature
+-
+
+EOF
+
+# The futuristic-feature is not implemented in this version, but it is
+# required by this database. A search for anything should fail.
+
+testit_expect_failure "find-required-feature" \
+                      $ldbsearch -H tdb://$DBPATH/private/sam.ldb \
+                      -b 'CN=LostAndFound,DC=foo,DC=example,DC=com'
+
+rm -rf $DBPATH
+
+exit $failed
diff -Nru samba-4.5.5+dfsg/source4/torture/vfs/fruit.c samba-4.5.6+dfsg/source4/torture/vfs/fruit.c
--- samba-4.5.5+dfsg/source4/torture/vfs/fruit.c	2017-01-30 10:56:26.000000000 +0100
+++ samba-4.5.6+dfsg/source4/torture/vfs/fruit.c	2017-03-09 10:21:43.000000000 +0100
@@ -2451,6 +2451,7 @@
 	struct srv_copychunk_rsp cc_rsp;
 	enum ndr_err_code ndr_ret;
 	bool ok;
+	const char *sname = ":foo" "\xef\x80\xa2" "bar:$DATA";
 
 	/*
 	 * First test a copy_chunk with a 0 chunk count without having
@@ -2521,6 +2522,11 @@
 		torture_fail(torture, "setup stream error");
 	}
 
+	ok = write_stream(tree, __location__, torture, tmp_ctx,
+			    FNAME_CC_SRC, sname,
+			    10, 10, "abcdefghij");
+	torture_assert_goto(torture, ok == true, ok, done, "write_stream failed\n");
+
 	ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
 				   0, /* 0 chunks, copyfile semantics */
 				   &src_h, 4096, /* fill 4096 byte src file */
@@ -2573,6 +2579,11 @@
 		torture_fail_goto(torture, done, "inconsistent stream data");
 	}
 
+	ok = check_stream(tree, __location__, torture, tmp_ctx,
+			    FNAME_CC_DST, sname,
+			    0, 20, 10, 10, "abcdefghij");
+	torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
+
 done:
 	smb2_util_close(tree, src_h);
 	smb2_util_close(tree, dest_h);
@@ -3527,6 +3538,383 @@
 }
 
 /*
+ * This tests that right after creating the AFP_AfpInfo stream,
+ * reading from the stream returns an empty, default metadata blob of
+ * 60 bytes.
+ *
+ * NOTE: against OS X SMB server this only works if the read request
+ * is compounded with the create that created the stream, is fails
+ * otherwise. We don't care...
+ */
+static bool test_null_afpinfo(struct torture_context *tctx,
+			      struct smb2_tree *tree)
+{
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	const char *fname = "test_null_afpinfo";
+	const char *sname = "test_null_afpinfo" AFPINFO_STREAM_NAME;
+	NTSTATUS status;
+	bool ret = true;
+	struct smb2_request *req[3];
+	struct smb2_handle handle;
+	struct smb2_create create;
+	struct smb2_read read;
+	AfpInfo *afpinfo = NULL;
+	char *afpinfo_buf = NULL;
+	const char *type_creator = "SMB,OLE!";
+
+	torture_comment(tctx, "Checking create of AfpInfo stream\n");
+
+	smb2_util_unlink(tree, fname);
+
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
+
+	ZERO_STRUCT(create);
+	create.in.desired_access = SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA;
+	create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
+	create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
+	create.in.fname = sname;
+
+	smb2_transport_compound_start(tree->session->transport, 2);
+
+	req[0] = smb2_create_send(tree, &create);
+
+	handle.data[0] = UINT64_MAX;
+	handle.data[1] = UINT64_MAX;
+
+	smb2_transport_compound_set_related(tree->session->transport, true);
+
+	ZERO_STRUCT(read);
+	read.in.file.handle = handle;
+	read.in.length = AFP_INFO_SIZE;
+	req[1] = smb2_read_send(tree, &read);
+
+	status = smb2_create_recv(req[0], tree, &create);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_recv failed");
+
+	handle = create.out.file.handle;
+
+	status = smb2_read_recv(req[1], tree, &read);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_read_recv failed");
+
+	afpinfo = torture_afpinfo_new(mem_ctx);
+	torture_assert_goto(tctx, afpinfo != NULL, ret, done, "torture_afpinfo_new failed");
+
+	memcpy(afpinfo->afpi_FinderInfo, type_creator, 8);
+
+	afpinfo_buf = torture_afpinfo_pack(tctx, afpinfo);
+	torture_assert_goto(tctx, afpinfo_buf != NULL, ret, done, "torture_afpinfo_new failed");
+
+	status = smb2_util_write(tree, handle, afpinfo_buf, 0, AFP_INFO_SIZE);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write failed");
+
+	smb2_util_close(tree, handle);
+
+	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");
+
+done:
+	smb2_util_unlink(tree, fname);
+	talloc_free(mem_ctx);
+	return ret;
+}
+
+static bool test_delete_file_with_rfork(struct torture_context *tctx,
+					struct smb2_tree *tree)
+{
+	const char *fname = "torture_write_rfork_io";
+	const char *rfork_content = "1234567890";
+	NTSTATUS status;
+	bool ret = true;
+
+	smb2_util_unlink(tree, fname);
+
+	torture_comment(tctx, "Test deleting file with resource fork\n");
+
+	ret = torture_setup_file(tctx, tree, fname, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed\n");
+
+	ret = write_stream(tree, __location__, tctx, tctx,
+			   fname, AFPRESOURCE_STREAM_NAME,
+			   10, 10, rfork_content);
+	torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed\n");
+
+	ret = check_stream(tree, __location__, tctx, tctx,
+			   fname, AFPRESOURCE_STREAM_NAME,
+			   0, 20, 10, 10, rfork_content);
+	torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed\n");
+
+	status = smb2_util_unlink(tree, fname);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "check_stream failed\n");
+
+done:
+	return ret;
+}
+
+static bool test_rename_and_read_rsrc(struct torture_context *tctx,
+				      struct smb2_tree *tree)
+{
+	bool ret = true;
+	NTSTATUS status;
+	struct smb2_create create, create2;
+	struct smb2_handle h1, h2;
+	const char *fname = "test_rename_openfile";
+	const char *sname = "test_rename_openfile" AFPRESOURCE_STREAM_NAME;
+	const char *fname_renamed = "test_rename_openfile_renamed";
+	const char *data = "1234567890";
+	union smb_setfileinfo sinfo;
+	struct smb2_read r;
+
+	ret = enable_aapl(tctx, tree);
+	torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
+
+	torture_comment(tctx, "Create file with resource fork\n");
+
+	ret = torture_setup_file(tctx, tree, fname, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+	ret = write_stream(tree, __location__, tctx, tctx,
+			   fname, AFPRESOURCE_STREAM_NAME, 0, 10, data);
+	torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
+
+	torture_comment(tctx, "Open resource fork\n");
+
+	ZERO_STRUCT(create);
+	create.in.desired_access = SEC_FILE_ALL;
+	create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
+	create.in.fname = sname;
+
+	status = smb2_create(tree, tctx, &create);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+	h1 = create.out.file.handle;
+
+	torture_comment(tctx, "Rename base file\n");
+
+	ZERO_STRUCT(create2);
+	create2.in.desired_access = SEC_FILE_ALL;
+	create2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create2.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
+	create2.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
+	create2.in.fname = fname;
+
+	status = smb2_create(tree, tctx, &create2);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+	h2 = create2.out.file.handle;
+
+	ZERO_STRUCT(sinfo);
+	sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
+	sinfo.rename_information.in.file.handle = h2;
+	sinfo.rename_information.in.overwrite = 0;
+	sinfo.rename_information.in.root_fid = 0;
+	sinfo.rename_information.in.new_name = fname_renamed;
+
+	status = smb2_setinfo_file(tree, &sinfo);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file failed");
+
+	smb2_util_close(tree, h2);
+
+	ZERO_STRUCT(r);
+	r.in.file.handle = h1;
+	r.in.length      = 10;
+	r.in.offset      = 0;
+
+	torture_comment(tctx, "Read resource fork of renamed file\n");
+
+	status = smb2_read(tree, tree, &r);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_read failed");
+
+	smb2_util_close(tree, h1);
+
+	torture_assert_goto(tctx, r.out.data.length == 10, ret, done,
+			    talloc_asprintf(tctx, "smb2_read returned %jd bytes, expected 10\n",
+					    (intmax_t)r.out.data.length));
+
+	torture_assert_goto(tctx, memcmp(r.out.data.data, data, 10) == 0, ret, done,
+			    talloc_asprintf(tctx, "Bad data in stream\n"));
+
+done:
+	smb2_util_unlink(tree, fname);
+	smb2_util_unlink(tree, fname_renamed);
+
+	return ret;
+}
+
+static bool test_readdir_attr_illegal_ntfs(struct torture_context *tctx,
+					   struct smb2_tree *tree)
+{
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	const char *name = "test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
+	const char *fname = BASEDIR "\\test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
+	NTSTATUS status;
+	struct smb2_handle testdirh;
+	bool ret = true;
+	struct smb2_create io;
+	AfpInfo *info;
+	const char *type_creator = "SMB,OLE!";
+	struct smb2_find f;
+	unsigned int count;
+	union smb_search_data *d;
+	uint64_t rfork_len;
+	int i;
+
+	smb2_deltree(tree, BASEDIR);
+
+	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);
+
+	torture_comment(tctx, "Enabling AAPL\n");
+
+	ret = enable_aapl(tctx, tree);
+	torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
+
+	/*
+	 * Now that Requested AAPL extensions are enabled, setup some
+	 * Mac files with metadata and resource fork
+	 */
+
+	torture_comment(tctx, "Preparing file\n");
+
+	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_not_null_goto(tctx, info, 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 = write_stream(tree, __location__, tctx, mem_ctx,
+			   fname, AFPRESOURCE_STREAM_NAME,
+			   0, 3, "foo");
+	torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
+
+	/*
+	 * Ok, file is prepared, now call smb2/find
+	 */
+
+	torture_comment(tctx, "Issue find\n");
+
+	ZERO_STRUCT(io);
+	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 |
+			      NTCREATEX_SHARE_ACCESS_WRITE |
+			      NTCREATEX_SHARE_ACCESS_DELETE);
+	io.in.create_disposition = NTCREATEX_DISP_OPEN;
+	io.in.fname = BASEDIR;
+	status = smb2_create(tree, tctx, &io);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+	ZERO_STRUCT(f);
+	f.in.file.handle	= io.out.file.handle;
+	f.in.pattern		= "*";
+	f.in.max_response_size	= 0x1000;
+	f.in.level              = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
+
+	status = smb2_find_level(tree, tree, &f, &count, &d);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_find_level failed");
+
+	status = smb2_util_close(tree, io.out.file.handle);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close failed");
+
+	torture_comment(tctx, "Checking find response with enriched macOS metadata\n");
+
+	for (i = 0; i < count; i++) {
+		const char *found = d[i].id_both_directory_info.name.s;
+
+		if (!strcmp(found, ".") || !strcmp(found, ".."))
+			continue;
+		break;
+	}
+
+	torture_assert_str_equal_goto(tctx,
+				      d[i].id_both_directory_info.name.s, name,
+				      ret, done, "bad name");
+
+	rfork_len = BVAL(d[i].id_both_directory_info.short_name_buf, 0);
+	torture_assert_int_equal_goto(tctx, rfork_len, 3, ret, done, "bad resource fork length");
+
+	torture_assert_mem_equal_goto(tctx, type_creator,
+				      d[i].id_both_directory_info.short_name_buf + 8,
+				      8, ret, done, "Bad FinderInfo");
+done:
+	smb2_util_unlink(tree, fname);
+	smb2_deltree(tree, BASEDIR);
+	talloc_free(mem_ctx);
+	return ret;
+}
+
+static bool test_invalid_afpinfo(struct torture_context *tctx,
+				 struct smb2_tree *tree1,
+				 struct smb2_tree *tree2)
+{
+	const char *fname = "filtest_invalid_afpinfo";
+	const char *sname = "filtest_invalid_afpinfo" AFPINFO_STREAM_NAME;
+	struct smb2_create create;
+	const char *streams_basic[] = {
+		"::$DATA"
+	};
+	const char *streams_afpinfo[] = {
+		"::$DATA",
+		AFPINFO_STREAM
+	};
+	NTSTATUS status;
+	bool ret = true;
+
+	if (tree2 == NULL) {
+		torture_skip_goto(tctx, done, "need second share without fruit\n");
+	}
+
+	torture_comment(tctx, "Testing invalid AFP_AfpInfo stream\n");
+
+	ret = torture_setup_file(tctx, tree2, fname, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+	ret = write_stream(tree2, __location__, tctx, tctx,
+			   fname, AFPINFO_STREAM_NAME,
+			   0, 3, "foo");
+	torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
+
+	ret = check_stream_list(tree2, tctx, fname, 2, streams_afpinfo, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+	torture_comment(tctx, "Listing streams, bad AFPINFO stream must not be present\n");
+
+	ret = check_stream_list(tree1, tctx, fname, 1, streams_basic, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+	torture_comment(tctx, "Try to open AFPINFO stream, must fail\n");
+
+	ZERO_STRUCT(create);
+	create.in.desired_access = SEC_FILE_ALL;
+	create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
+	create.in.fname = sname;
+
+	status = smb2_create(tree1, tctx, &create);
+	torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+					   ret, done, "Stream still around?");
+
+done:
+	smb2_util_unlink(tree1, fname);
+	return ret;
+}
+
+/*
  * 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:
@@ -3542,11 +3930,9 @@
 	suite->description = talloc_strdup(suite, "vfs_fruit tests");
 
 	torture_suite_add_1smb2_test(suite, "copyfile", test_copyfile);
-	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);
@@ -3560,6 +3946,25 @@
 	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);
+	torture_suite_add_1smb2_test(suite, "null afpinfo", test_null_afpinfo);
+	torture_suite_add_1smb2_test(suite, "delete", test_delete_file_with_rfork);
+	torture_suite_add_1smb2_test(suite, "read open rsrc after rename", test_rename_and_read_rsrc);
+	torture_suite_add_1smb2_test(suite, "readdir_attr with names with illegal ntfs characters", test_readdir_attr_illegal_ntfs);
+
+	torture_suite_add_2ns_smb2_test(suite, "invalid AFP_AfpInfo", test_invalid_afpinfo);
+
+	return suite;
+}
+
+struct torture_suite *torture_vfs_fruit_netatalk(void)
+{
+	struct torture_suite *suite = torture_suite_create(
+		talloc_autofree_context(), "fruit_netatalk");
+
+	suite->description = talloc_strdup(suite, "vfs_fruit tests for Netatalk interop that require fruit:metadata=netatalk");
+
+	torture_suite_add_1smb2_test(suite, "read netatalk metadata", test_read_netatalk_metadata);
+	torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion);
 
 	return suite;
 }
diff -Nru samba-4.5.5+dfsg/source4/torture/vfs/vfs.c samba-4.5.6+dfsg/source4/torture/vfs/vfs.c
--- samba-4.5.5+dfsg/source4/torture/vfs/vfs.c	2017-01-30 10:56:26.000000000 +0100
+++ samba-4.5.6+dfsg/source4/torture/vfs/vfs.c	2017-03-09 10:21:43.000000000 +0100
@@ -38,42 +38,44 @@
 			       struct torture_test *test)
 {
 	bool (*fn) (struct torture_context *, struct smb2_tree *, struct smb2_tree *);
-	bool ret = false;
+	bool ok;
 
-	struct smb2_tree *tree1;
-	struct smb2_tree *tree2;
+	struct smb2_tree *tree1 = NULL;
+	struct smb2_tree *tree2 = NULL;
 	TALLOC_CTX *mem_ctx = talloc_new(torture_ctx);
 
-	if (!torture_smb2_con_sopt(torture_ctx, "share1", &tree1)) {
+	if (!torture_smb2_connection(torture_ctx, &tree1)) {
 		torture_fail(torture_ctx,
-		    "Establishing SMB2 connection failed\n");
-		goto done;
+			    "Establishing SMB2 connection failed\n");
+		return false;
 	}
 
+	/*
+	 * This is a trick:
+	 * The test might close the connection. If we steal the tree context
+	 * before that and free the parent instead of tree directly, we avoid
+	 * a double free error.
+	 */
 	talloc_steal(mem_ctx, tree1);
 
-	if (!torture_smb2_con_sopt(torture_ctx, "share2", &tree2)) {
-		torture_fail(torture_ctx,
-		    "Establishing SMB2 connection failed\n");
-		goto done;
+	ok = torture_smb2_con_sopt(torture_ctx, "share2", &tree2);
+	if (ok) {
+		talloc_steal(mem_ctx, tree2);
 	}
 
-	talloc_steal(mem_ctx, tree2);
-
 	fn = test->fn;
 
-	ret = fn(torture_ctx, tree1, tree2);
+	ok = fn(torture_ctx, tree1, tree2);
 
-done:
 	/* the test may already have closed some of the connections */
 	talloc_free(mem_ctx);
 
-	return ret;
+	return ok;
 }
 
 /*
- * Run a test with 2 connected trees, Share names to connect are taken
- * from option strings "torture:share1" and "torture:share2"
+ * Run a test with 2 connected trees, the default share and another
+ * taken from option strings "torture:share2"
  */
 struct torture_test *torture_suite_add_2ns_smb2_test(struct torture_suite *suite,
 						     const char *name,
@@ -107,6 +109,7 @@
 	suite->description = talloc_strdup(suite, "VFS modules tests");
 
 	torture_suite_add_suite(suite, torture_vfs_fruit());
+	torture_suite_add_suite(suite, torture_vfs_fruit_netatalk());
 	torture_suite_add_suite(suite, torture_acl_xattr());
 
 	torture_register_suite(suite);
diff -Nru samba-4.5.5+dfsg/testprogs/blackbox/dbcheck-links.sh samba-4.5.6+dfsg/testprogs/blackbox/dbcheck-links.sh
--- samba-4.5.5+dfsg/testprogs/blackbox/dbcheck-links.sh	2016-12-05 09:18:44.000000000 +0100
+++ samba-4.5.6+dfsg/testprogs/blackbox/dbcheck-links.sh	2017-03-09 10:21:43.000000000 +0100
@@ -91,6 +91,41 @@
     fi
 }
 
+add_dangling_link() {
+    ldif=$release_dir/add-dangling-forwardlink-user.ldif
+    TZ=UTC $ldbadd -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb $ldif
+    if [ "$?" != "0" ]; then
+	return 1
+    fi
+
+    ldif=$release_dir/add-initially-normal-link.ldif
+    TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb $ldif
+    if [ "$?" != "0" ]; then
+	return 1
+    fi
+    sleep 6
+
+    ldif=$release_dir/delete-only-backlink.ldif
+    TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb.d/DC%3DRELEASE-4-5-0-PRE1,DC%3DSAMBA,DC%3DCORP.ldb $ldif
+    if [ "$?" != "0" ]; then
+	return 1
+    fi
+}
+
+add_dangling_backlink() {
+    ldif=$release_dir/add-dangling-backlink-user.ldif
+    TZ=UTC $ldbadd -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb $ldif
+    if [ "$?" != "0" ]; then
+	return 1
+    fi
+
+    ldif=$release_dir/add-dangling-backlink.ldif
+    TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb.d/DC%3DRELEASE-4-5-0-PRE1,DC%3DSAMBA,DC%3DCORP.ldb $ldif
+    if [ "$?" != "0" ]; then
+	return 1
+    fi
+}
+
 add_two_more_users() {
     ldif=$release_dir/add-two-more-users.ldif
     TZ=UTC $ldbadd -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb $ldif
@@ -157,6 +192,14 @@
     fi
 }
 
+dangling_one_way() {
+    ldif=$release_dir/dangling-one-way-link.ldif
+    TZ=UTC $ldbmodify -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb $ldif
+    if [ "$?" != "0" ]; then
+        return 1
+    fi
+}
+
 if [ -d $release_dir ]; then
     testit $RELEASE undump
     testit "add_two_more_users" add_two_more_users
@@ -164,11 +207,15 @@
     testit "remove_one_link" remove_one_link
     testit "remove_one_user" remove_one_user
     testit "move_one_user" move_one_user
+    testit "add_dangling_link" add_dangling_link
+    testit "add_dangling_backlink" add_dangling_backlink
     testit "dbcheck" dbcheck
     testit "dbcheck_clean" dbcheck_clean
     testit "check_expected_after_deleted_links" check_expected_after_deleted_links
     testit "check_expected_after_links" check_expected_after_links
     testit "check_expected_after_objects" check_expected_after_objects
+    testit "dangling_one_way" dangling_one_way
+    testit "dbcheck_clean" dbcheck_clean
 else
     subunit_start_test $RELEASE
     subunit_skip_test $RELEASE <<EOF
diff -Nru samba-4.5.5+dfsg/testprogs/blackbox/renamedc.sh samba-4.5.6+dfsg/testprogs/blackbox/renamedc.sh
--- samba-4.5.5+dfsg/testprogs/blackbox/renamedc.sh	2016-08-11 09:51:05.000000000 +0200
+++ samba-4.5.6+dfsg/testprogs/blackbox/renamedc.sh	2017-03-09 10:21:43.000000000 +0100
@@ -65,8 +65,10 @@
 }
 
 dbcheck_fix() {
+        # Unlike most calls to dbcheck --fix, this will not trigger an error, as
+        # we do not flag an error count for this old DN string case.
 	$BINDIR/samba-tool dbcheck --cross-ncs -s $PREFIX/renamedc_test/etc/smb.conf --fix \
-		--quiet --yes fix_all_string_dn_component_mismatch \
+		--quiet --yes fix_all_old_dn_string_component_mismatch \
 		--attrs="fsmoRoleOwner interSiteTopologyGenerator msDS-NC-Replica-Locations"
 }
 
@@ -83,7 +85,7 @@
 testit "confirmrenamedc_dNSHostName" confirmrenamedc_dNSHostName || failed=`expr $failed + 1`
 testit "confirmrenamedc_rootdse_dnsHostName" confirmrenamedc_rootdse_dnsHostName || failed=`expr $failed + 1`
 testit "confirmrenamedc_rootdse_dsServiceName" confirmrenamedc_rootdse_dsServiceName || failed=`expr $failed + 1`
-testit_expect_failure "dbcheck_fix" dbcheck_fix || failed=`expr $failed + 1`
+testit "dbcheck_fix" dbcheck_fix || failed=`expr $failed + 1`
 testit "dbcheck" dbcheck || failed=`expr $failed + 1`
 testit "renamedc2" testrenamedc2 || failed=`expr $failed + 1`
 
diff -Nru samba-4.5.5+dfsg/third_party/waf/wafadmin/Tools/config_c.py samba-4.5.6+dfsg/third_party/waf/wafadmin/Tools/config_c.py
--- samba-4.5.5+dfsg/third_party/waf/wafadmin/Tools/config_c.py	2016-08-11 09:51:05.000000000 +0200
+++ samba-4.5.6+dfsg/third_party/waf/wafadmin/Tools/config_c.py	2017-03-09 10:21:43.000000000 +0100
@@ -106,7 +106,9 @@
 @conf
 def validate_cfg(self, kw):
 	if not 'path' in kw:
-		kw['path'] = 'pkg-config --errors-to-stdout --print-errors'
+		if not self.env.PKGCONFIG:
+			self.find_program('pkg-config', var='PKGCONFIG')
+		kw['path'] = self.env.PKGCONFIG
 
 	# pkg-config version
 	if 'atleast_pkgconfig_version' in kw:
diff -Nru samba-4.5.5+dfsg/VERSION samba-4.5.6+dfsg/VERSION
--- samba-4.5.5+dfsg/VERSION	2017-01-30 10:56:26.000000000 +0100
+++ samba-4.5.6+dfsg/VERSION	2017-03-09 10:21:43.000000000 +0100
@@ -25,7 +25,7 @@
 ########################################################
 SAMBA_VERSION_MAJOR=4
 SAMBA_VERSION_MINOR=5
-SAMBA_VERSION_RELEASE=5
+SAMBA_VERSION_RELEASE=6
 
 ########################################################
 # If a official release has a serious bug              #
diff -Nru samba-4.5.5+dfsg/WHATSNEW.txt samba-4.5.6+dfsg/WHATSNEW.txt
--- samba-4.5.5+dfsg/WHATSNEW.txt	2017-01-30 10:56:26.000000000 +0100
+++ samba-4.5.6+dfsg/WHATSNEW.txt	2017-03-09 10:21:43.000000000 +0100
@@ -1,4 +1,111 @@
                    =============================
+                   Release Notes for Samba 4.5.6
+                           March 9, 2017
+                   =============================
+
+
+This is the latest stable release of the Samba 4.5 release series.
+
+
+Changes since 4.5.5:
+--------------------
+
+o  Jeremy Allison <jra at samba.org>
+   * BUG 12499: s3: vfs: dirsort doesn't handle opendir of "." correctly.
+   * BUG 12531: vfs_shadow_copy2 doesn't cope with server changing directories.
+   * BUG 12546: vfs_streams_xattr doesn't cope with server changing directories.
+   * BUG 12572: s3: smbd: Don't loop infinitely on bad-symlink resolution.
+   * BUG 12608: s3: smbd: Restart reading the incoming SMB2 fd when the send
+     queue is drained.
+
+o  Andrew Bartlett <abartlet at samba.org>
+   * BUG 12573: Samba < 4.7 does not know about compatibleFeatures and
+     requiredFeatures.
+
+o  Ralph Boehme <slow at samba.org>
+   * BUG 12184: s3/rpc_server: Shared rpc modules loading.
+   * BUG 12427: vfs_fruit doesn't work with fruit:metadata=stream.
+   * BUG 12520: Ensure global "smb encrypt = off" is effective.
+   * BUG 12524: s3/rpc_server: move rpc_modules.c to its own subsystem.
+   * BUG 12536: s3/smbd: check for invalid access_mask
+     smbd_calculate_access_mask().
+   * BUG 12541: vfs_fruit: checks wrong AAPL config state and so always uses
+     readdirattr.
+   * BUG 12545: s3/rpc_server/mdssvc: add attribute "kMDItemContentType".
+   * BUG 12591: vfs_streams_xattr: use fsp, not base_fsp.
+   * BUG 12604: vfs_fruit: Enabling AAPL extensions must be a global switch.
+
+o  Amitay Isaacs <amitay at gmail.com>
+   * BUG 12469: ctdb-tests: Use replace headers instead of system headers.
+   * BUG 12547: ctdb-build: Install CTDB tests correctly from toplevel.
+   * BUG 12580: ctdb-common: Fix use-after-free error in comm_fd_handler().
+
+o  Volker Lendecke <vl at samba.org>
+   * BUG 12551: smbd: Fix "map acl inherit" = yes.
+
+o  Stefan Metzmacher <metze at samba.org>
+   * BUG 9048: s4:ldap_server: Match Windows in the error messages of failing
+     LDAP Bind requests.
+   * BUG 11830: s3:winbindd: Try a NETLOGON connection with noauth over NCACN_NP
+     against trusted domains.
+   * BUG 12262: 'net ads testjoin' and smb access fails after winbindd changed the
+     trust password.
+   * BUG 12399: s4:repl_meta_data: Normalize rdn attribute name via the schema.
+   * BUG 12540: s3:smbd: Allow "server min protocol = SMB3_00" to go via "SMB
+     2.???" negprot.
+   * BUG 12581: smbclient fails on bad endianess when listing shares from
+     Solaris kernel SMB server on SPARC.
+   * BUG 12585: librpc/rpc: fix regression in
+     NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE error mapping.
+   * BUG 12586: libcli/auth: Use the correct creds value against servers without
+     LogonSamLogonEx.
+   * BUG 12587: winbindd child segfaults on connect to an NT4 domain.
+   * BUG 12588: cm_prepare_connection may return NT_STATUS_OK without a valid
+     connection.
+   * BUG 12598: winbindd (as member) requires Kerberos against trusted ad
+     domain, while it shouldn't.
+   * BUG 12605: s3:winbindd: Fix endless forest trust scan.
+
+o  Garming Sam <garming at catalyst.net.nz>
+   * BUG 12577: dbcheck-links: Test that dbcheck against one-way links does not
+     error.
+   * BUG 12600: dbchecker: Stop ignoring linked cases where both objects are
+     alive.
+
+o  Andreas Schneider <asn at samba.org>
+   * BUG 12571: s3-vfs: Only walk the directory once in open_and_sort_dir().
+
+o  Martin Schwenke <martin at meltin.net>
+   * BUG 12589: ctdb-scripts: Initialise CTDB_NFS_CALLOUT in statd-callout.
+
+o  Uri Simchoni <uri at samba.org>
+   * BUG 12529: waf: backport finding of pkg-config.
+
+
+#######################################
+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 older releases follow:
+----------------------------------------
+
+                   =============================
                    Release Notes for Samba 4.5.5
                           January 30, 2017
                    =============================
@@ -22,7 +129,7 @@
 
 o  Martin Schwenke <martin at meltin.net>
    * BUG 12512: ctdb-scripts: Fix remaining uses of "ctdb gratiousarp".
-   * BUG 12516: /etc/iproute2/rt_tables gets populated with multiple
+   * BUG 12516: ctdb-scripts: /etc/iproute2/rt_tables gets populated with multiple
      'default' entries.
 
 
@@ -46,8 +153,8 @@
 ======================================================================
 
 
-Release notes for older releases follow:
-----------------------------------------
+----------------------------------------------------------------------
+
 
                    =============================
                    Release Notes for Samba 4.5.4


More information about the Pkg-samba-maint mailing list