[SCM] Samba Shared Repository - branch v4-7-test updated

Karolin Seeger kseeger at samba.org
Mon May 14 12:59:02 UTC 2018


The branch, v4-7-test has been updated
       via  91edd9c winbindd: Do re-connect if the RPC call fails in the passdb case
       via  6a41a0d winbindd: Add a cache of the samr and lsa handles for the passdb domain
       via  139743e vfs_ceph: add fake async pwrite/pread send/recv hooks
      from  bf466d2 s3: libsmbclient: Fix hard-coded connection error return of ETIMEDOUT.

https://git.samba.org/?p=samba.git;a=shortlog;h=v4-7-test


- Log -----------------------------------------------------------------
commit 91edd9c30f2545519844e3413e43626b3ca0c321
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Mar 21 20:44:31 2018 +1300

    winbindd: Do re-connect if the RPC call fails in the passdb case
    
    This is very, very unlikely but possible as in the AD case the RPC server is in
    another process that may eventually be able to restart.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13430
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit fc9150dcab231fe9beb72e198b0c2742d5f2505f)
    
    Autobuild-User(v4-7-test): Karolin Seeger <kseeger at samba.org>
    Autobuild-Date(v4-7-test): Mon May 14 14:58:22 CEST 2018 on sn-devel-144

commit 6a41a0dcbec9644f2661c919c669144c67bf9394
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Mar 21 20:43:10 2018 +1300

    winbindd: Add a cache of the samr and lsa handles for the passdb domain
    
    This domain is very close, in AD DC configurations over a internal ncacn_np pipe
    and otherwise in the same process via C linking.  It is however very expensive
    to re-create the binding handle per SID->name lookup, so keep a cache.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13430
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit d418d0ca33afb41a793a2fff19ca68871aa5e9ef)

commit 139743ec1ed9078be0891e416c536305b6dd1b33
Author: David Disseldorp <ddiss at samba.org>
Date:   Wed May 9 16:51:34 2018 +0200

    vfs_ceph: add fake async pwrite/pread send/recv hooks
    
    As found by Jeremy, VFS modules that don't provide pread_send() or
    pwrite_send() hooks result in vfs_default fallback, which is
    catastrophic for VFS modules with non-mounted filesystems such as
    vfs_ceph.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=13425
    
    Reported-by: Jeremy Allison <jra at samba.org>
    Signed-off-by: David Disseldorp <ddiss at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit f0e6453b0420fe9d062936d4ddc05f44b40cf2ba)

-----------------------------------------------------------------------

Summary of changes:
 source3/modules/vfs_ceph.c       | 109 ++++++++++-
 source3/winbindd/winbindd_samr.c | 395 ++++++++++++++++++++++++++++-----------
 2 files changed, 395 insertions(+), 109 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c
index 87d3c00..a27b762 100644
--- a/source3/modules/vfs_ceph.c
+++ b/source3/modules/vfs_ceph.c
@@ -482,6 +482,57 @@ static ssize_t cephwrap_pread(struct vfs_handle_struct *handle, files_struct *fs
 	WRAP_RETURN(result);
 }
 
+struct cephwrap_pread_state {
+	ssize_t bytes_read;
+	struct vfs_aio_state vfs_aio_state;
+};
+
+/*
+ * Fake up an async ceph read by calling the synchronous API.
+ */
+static struct tevent_req *cephwrap_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;
+	struct cephwrap_pread_state *state = NULL;
+	int ret = -1;
+
+	DBG_DEBUG("[CEPH] %s\n", __func__);
+	req = tevent_req_create(mem_ctx, &state, struct cephwrap_pread_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	ret = ceph_read(handle->data, fsp->fh->fd, data, n, offset);
+	if (ret < 0) {
+		/* ceph returns -errno on error. */
+		tevent_req_error(req, -ret);
+		return tevent_req_post(req, ev);
+	}
+
+	state->bytes_read = ret;
+	tevent_req_done(req);
+	/* Return and schedule the completion of the call. */
+	return tevent_req_post(req, ev);
+}
+
+static ssize_t cephwrap_pread_recv(struct tevent_req *req,
+				   struct vfs_aio_state *vfs_aio_state)
+{
+	struct cephwrap_pread_state *state =
+		tevent_req_data(req, struct cephwrap_pread_state);
+
+	DBG_DEBUG("[CEPH] %s\n", __func__);
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
+		return -1;
+	}
+	*vfs_aio_state = state->vfs_aio_state;
+	return state->bytes_read;
+}
 
 static ssize_t cephwrap_write(struct vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
 {
@@ -510,6 +561,58 @@ static ssize_t cephwrap_pwrite(struct vfs_handle_struct *handle, files_struct *f
 	WRAP_RETURN(result);
 }
 
+struct cephwrap_pwrite_state {
+	ssize_t bytes_written;
+	struct vfs_aio_state vfs_aio_state;
+};
+
+/*
+ * Fake up an async ceph write by calling the synchronous API.
+ */
+static struct tevent_req *cephwrap_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;
+	struct cephwrap_pwrite_state *state = NULL;
+	int ret = -1;
+
+	DBG_DEBUG("[CEPH] %s\n", __func__);
+	req = tevent_req_create(mem_ctx, &state, struct cephwrap_pwrite_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	ret = ceph_write(handle->data, fsp->fh->fd, data, n, offset);
+	if (ret < 0) {
+		/* ceph returns -errno on error. */
+		tevent_req_error(req, -ret);
+		return tevent_req_post(req, ev);
+	}
+
+	state->bytes_written = ret;
+	tevent_req_done(req);
+	/* Return and schedule the completion of the call. */
+	return tevent_req_post(req, ev);
+}
+
+static ssize_t cephwrap_pwrite_recv(struct tevent_req *req,
+				    struct vfs_aio_state *vfs_aio_state)
+{
+	struct cephwrap_pwrite_state *state =
+		tevent_req_data(req, struct cephwrap_pwrite_state);
+
+	DBG_DEBUG("[CEPH] %s\n", __func__);
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
+		return -1;
+	}
+	*vfs_aio_state = state->vfs_aio_state;
+	return state->bytes_written;
+}
+
 static off_t cephwrap_lseek(struct vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
 {
 	off_t result = 0;
@@ -571,7 +674,7 @@ static int cephwrap_fsync(struct vfs_handle_struct *handle, files_struct *fsp)
 }
 
 /*
- * Fake up an async ceph fsync by calling the sychronous API.
+ * Fake up an async ceph fsync by calling the synchronous API.
  */
 
 static struct tevent_req *cephwrap_fsync_send(struct vfs_handle_struct *handle,
@@ -1484,8 +1587,12 @@ static struct vfs_fn_pointers ceph_fns = {
 	.close_fn = cephwrap_close,
 	.read_fn = cephwrap_read,
 	.pread_fn = cephwrap_pread,
+	.pread_send_fn = cephwrap_pread_send,
+	.pread_recv_fn = cephwrap_pread_recv,
 	.write_fn = cephwrap_write,
 	.pwrite_fn = cephwrap_pwrite,
+	.pwrite_send_fn = cephwrap_pwrite_send,
+	.pwrite_recv_fn = cephwrap_pwrite_recv,
 	.lseek_fn = cephwrap_lseek,
 	.sendfile_fn = cephwrap_sendfile,
 	.recvfile_fn = cephwrap_recvfile,
diff --git a/source3/winbindd/winbindd_samr.c b/source3/winbindd/winbindd_samr.c
index aedb77b..31720d5 100644
--- a/source3/winbindd/winbindd_samr.c
+++ b/source3/winbindd/winbindd_samr.c
@@ -28,6 +28,7 @@
 #include "winbindd_rpc.h"
 #include "lib/util_unixsids.h"
 #include "rpc_client/rpc_client.h"
+#include "rpc_client/cli_pipe.h"
 #include "../librpc/gen_ndr/ndr_samr_c.h"
 #include "rpc_client/cli_samr.h"
 #include "../librpc/gen_ndr/ndr_lsa_c.h"
@@ -40,6 +41,20 @@
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
+/*
+ * The other end of this won't go away easily, so we can trust it
+ *
+ * It is either a long-lived process with the same lifetime as
+ * winbindd or a part of this process
+ */
+struct winbind_internal_pipes {
+	struct rpc_pipe_client *samr_pipe;
+	struct policy_handle samr_domain_hnd;
+	struct rpc_pipe_client *lsa_pipe;
+	struct policy_handle lsa_hnd;
+};
+
+
 NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
 				 struct winbindd_domain *domain,
 				 struct rpc_pipe_client **samr_pipe,
@@ -101,6 +116,96 @@ NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
 	return status;
 }
 
+
+static NTSTATUS open_cached_internal_pipe_conn(
+	struct winbindd_domain *domain,
+	struct rpc_pipe_client **samr_pipe,
+	struct policy_handle *samr_domain_hnd,
+	struct rpc_pipe_client **lsa_pipe,
+	struct policy_handle *lsa_hnd)
+{
+	struct winbind_internal_pipes *internal_pipes = NULL;
+
+	if (domain->private_data == NULL) {
+		TALLOC_CTX *frame = talloc_stackframe();
+		NTSTATUS status;
+
+		internal_pipes = talloc_zero(frame,
+					     struct winbind_internal_pipes);
+
+		status = open_internal_samr_conn(
+			internal_pipes,
+			domain,
+			&internal_pipes->samr_pipe,
+			&internal_pipes->samr_domain_hnd);
+		if (!NT_STATUS_IS_OK(status)) {
+			TALLOC_FREE(frame);
+			return status;
+		}
+
+		status = open_internal_lsa_conn(internal_pipes,
+						&internal_pipes->lsa_pipe,
+						&internal_pipes->lsa_hnd);
+
+		if (!NT_STATUS_IS_OK(status)) {
+			TALLOC_FREE(frame);
+			return status;
+		}
+
+		domain->private_data = talloc_move(domain, &internal_pipes);
+
+		TALLOC_FREE(frame);
+
+	}
+
+	internal_pipes = talloc_get_type_abort(
+		domain->private_data, struct winbind_internal_pipes);
+
+	if (samr_domain_hnd) {
+		*samr_domain_hnd = internal_pipes->samr_domain_hnd;
+	}
+
+	if (samr_pipe) {
+		*samr_pipe = internal_pipes->samr_pipe;
+	}
+
+	if (lsa_hnd) {
+		*lsa_hnd = internal_pipes->lsa_hnd;
+	}
+
+	if (lsa_pipe) {
+		*lsa_pipe = internal_pipes->lsa_pipe;
+	}
+
+	return NT_STATUS_OK;
+}
+
+static bool reset_connection_on_error(struct winbindd_domain *domain,
+				      struct rpc_pipe_client *p,
+				      NTSTATUS status)
+{
+	struct winbind_internal_pipes *internal_pipes = NULL;
+
+	internal_pipes = talloc_get_type_abort(
+		domain->private_data, struct winbind_internal_pipes);
+
+	if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
+	    NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR))
+	{
+		TALLOC_FREE(internal_pipes);
+		domain->private_data = NULL;
+		return true;
+	}
+
+	if (!rpccli_is_connected(p)) {
+		TALLOC_FREE(internal_pipes);
+		domain->private_data = NULL;
+		return true;
+	}
+
+	return false;
+}
+
 /*********************************************************************
  SAM specific functions.
 *********************************************************************/
@@ -116,8 +221,8 @@ static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
 	struct wb_acct_info *info = NULL;
 	uint32_t num_info = 0;
 	TALLOC_CTX *tmp_ctx;
-	NTSTATUS status, result;
-	struct dcerpc_binding_handle *b = NULL;
+	NTSTATUS status;
+	bool retry = false;
 
 	DEBUG(3,("sam_enum_dom_groups\n"));
 
@@ -130,20 +235,31 @@ static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
+again:
+	status = open_cached_internal_pipe_conn(domain,
+						&samr_pipe,
+						&dom_pol,
+						NULL,
+						NULL);
 	if (!NT_STATUS_IS_OK(status)) {
-		goto error;
+		TALLOC_FREE(tmp_ctx);
+		return status;
 	}
 
-	b = samr_pipe->binding_handle;
-
 	status = rpc_enum_dom_groups(tmp_ctx,
 				     samr_pipe,
 				     &dom_pol,
 				     &num_info,
 				     &info);
+
+	if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
+		retry = true;
+		goto again;
+	}
+
 	if (!NT_STATUS_IS_OK(status)) {
-		goto error;
+		TALLOC_FREE(tmp_ctx);
+		return status;
 	}
 
 	if (pnum_info) {
@@ -154,10 +270,6 @@ static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
 		*pinfo = talloc_move(mem_ctx, &info);
 	}
 
-error:
-	if (b && is_valid_policy_hnd(&dom_pol)) {
-		dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
-	}
 	TALLOC_FREE(tmp_ctx);
 	return status;
 }
@@ -171,8 +283,8 @@ static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
 	struct policy_handle dom_pol = { 0 };
 	uint32_t *rids = NULL;
 	TALLOC_CTX *tmp_ctx;
-	NTSTATUS status, result;
-	struct dcerpc_binding_handle *b = NULL;
+	NTSTATUS status;
+	bool retry = false;
 
 	DEBUG(3,("samr_query_user_list\n"));
 
@@ -181,18 +293,26 @@ static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
+again:
+	status = open_cached_internal_pipe_conn(domain,
+						&samr_pipe,
+						&dom_pol,
+						NULL,
+						NULL);
 	if (!NT_STATUS_IS_OK(status)) {
 		goto done;
 	}
 
-	b = samr_pipe->binding_handle;
-
 	status = rpc_query_user_list(tmp_ctx,
 				     samr_pipe,
 				     &dom_pol,
 				     &domain->sid,
 				     &rids);
+	if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
+		retry = true;
+		goto again;
+	}
+
 	if (!NT_STATUS_IS_OK(status)) {
 		goto done;
 	}
@@ -202,10 +322,6 @@ static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
 	}
 
 done:
-	if (b && is_valid_policy_hnd(&dom_pol)) {
-		dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
-	}
-
 	TALLOC_FREE(rids);
 	TALLOC_FREE(tmp_ctx);
 	return status;
@@ -221,8 +337,8 @@ static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
 	struct netr_DomainTrust *trusts = NULL;
 	uint32_t num_trusts = 0;
 	TALLOC_CTX *tmp_ctx;
-	NTSTATUS status, result;
-	struct dcerpc_binding_handle *b = NULL;
+	NTSTATUS status;
+	bool retry = false;
 
 	DEBUG(3,("samr: trusted domains\n"));
 
@@ -235,18 +351,27 @@ static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
+again:
+	status = open_cached_internal_pipe_conn(domain,
+						NULL,
+						NULL,
+						&lsa_pipe,
+						&lsa_policy);
 	if (!NT_STATUS_IS_OK(status)) {
 		goto done;
 	}
 
-	b = lsa_pipe->binding_handle;
-
 	status = rpc_trusted_domains(tmp_ctx,
 				     lsa_pipe,
 				     &lsa_policy,
 				     &num_trusts,
 				     &trusts);
+
+	if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
+		retry = true;
+		goto again;
+	}
+
 	if (!NT_STATUS_IS_OK(status)) {
 		goto done;
 	}
@@ -257,10 +382,6 @@ static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
 	}
 
 done:
-	if (b && is_valid_policy_hnd(&lsa_policy)) {
-		dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
-	}
-
 	TALLOC_FREE(tmp_ctx);
 	return status;
 }
@@ -284,8 +405,8 @@ static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
 	uint32_t *name_types = NULL;
 
 	TALLOC_CTX *tmp_ctx;
-	NTSTATUS status, result;
-	struct dcerpc_binding_handle *b = NULL;
+	NTSTATUS status;
+	bool retry = false;
 
 	DEBUG(3,("sam_lookup_groupmem\n"));
 
@@ -304,13 +425,16 @@ static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
+again:
+	status = open_cached_internal_pipe_conn(domain,
+						&samr_pipe,
+						&dom_pol,
+						NULL,
+						NULL);
 	if (!NT_STATUS_IS_OK(status)) {
 		goto done;
 	}
 
-	b = samr_pipe->binding_handle;
-
 	status = rpc_lookup_groupmem(tmp_ctx,
 				     samr_pipe,
 				     &dom_pol,
@@ -323,6 +447,11 @@ static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
 				     &names,
 				     &name_types);
 
+	if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
+		retry = true;
+		goto again;
+	}
+
 	if (pnum_names) {
 		*pnum_names = num_names;
 	}
@@ -340,10 +469,6 @@ static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
 	}
 
 done:
-	if (b && is_valid_policy_hnd(&dom_pol)) {
-		dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
-	}
-
 	TALLOC_FREE(tmp_ctx);
 	return status;
 }
@@ -398,8 +523,8 @@ static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain,
 	struct wb_acct_info *info = NULL;
 	uint32_t num_info = 0;
 	TALLOC_CTX *tmp_ctx;
-	NTSTATUS status, result;
-	struct dcerpc_binding_handle *b = NULL;
+	NTSTATUS status;
+	bool retry = false;
 


-- 
Samba Shared Repository



More information about the samba-cvs mailing list