[SCM] Samba Shared Repository - branch v3-2-test updated - release-3-2-0pre2-2666-g47be328

Jeremy Allison jra at samba.org
Mon Jun 30 18:28:06 GMT 2008


The branch, v3-2-test has been updated
       via  47be3281125392bb410da41cbfe2a2b4eebbc824 (commit)
       via  d05451c2c256e04870ebe6467f38585dad72f3a9 (commit)
      from  3d5872c64d5cefc3125702b4c1a3156161abfad2 (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-2-test


- Log -----------------------------------------------------------------
commit 47be3281125392bb410da41cbfe2a2b4eebbc824
Merge: d05451c2c256e04870ebe6467f38585dad72f3a9 3d5872c64d5cefc3125702b4c1a3156161abfad2
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Jun 30 11:27:40 2008 -0700

    Merge branch 'v3-2-test' of ssh://jra@git.samba.org/data/git/samba into v3-2-test

commit d05451c2c256e04870ebe6467f38585dad72f3a9
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Jun 30 11:23:05 2008 -0700

    After technical consultation, add Steven Danneman's <steven.danneman at isilon.com> patch to make winbindd enum users and groups async.
    We need this for 3.2.0 official.
    Jeremy.

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

Summary of changes:
 source/winbindd/winbindd.h        |    7 ++-
 source/winbindd/winbindd_ads.c    |    2 +-
 source/winbindd/winbindd_async.c  |  156 +++++++++++++++++++++++++++++++++++++
 source/winbindd/winbindd_cache.c  |    8 ++-
 source/winbindd/winbindd_domain.c |    8 ++
 source/winbindd/winbindd_group.c  |   87 +--------------------
 source/winbindd/winbindd_misc.c   |  123 +++++++++++++++++++++++++++++
 source/winbindd/winbindd_user.c   |   94 +----------------------
 8 files changed, 305 insertions(+), 180 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source/winbindd/winbindd.h b/source/winbindd/winbindd.h
index 0840e58..42a1100 100644
--- a/source/winbindd/winbindd.h
+++ b/source/winbindd/winbindd.h
@@ -362,7 +362,12 @@ struct winbindd_tdc_domain {
 	uint32 trust_type;
 };
 
-
+/* Switch for listing users or groups */
+enum ent_type {
+	LIST_USERS = 0,
+	LIST_GROUPS,
+};
+ 
 #include "winbindd/winbindd_proto.h"
 
 #define WINBINDD_ESTABLISH_LOOP 30
diff --git a/source/winbindd/winbindd_ads.c b/source/winbindd/winbindd_ads.c
index ae8ad9d..35ffe70 100644
--- a/source/winbindd/winbindd_ads.c
+++ b/source/winbindd/winbindd_ads.c
@@ -393,7 +393,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
 	 * using LDAP.
 	 *
 	 * if we ever need to enumerate domain local groups separately, 
-	 * then this the optimization in enum_dom_groups() will need 
+	 * then this optimization in enum_dom_groups() will need
 	 * to be split out
 	 */
 	*num_entries = 0;
diff --git a/source/winbindd/winbindd_async.c b/source/winbindd/winbindd_async.c
index 2ff5ef2..10b7e48 100644
--- a/source/winbindd/winbindd_async.c
+++ b/source/winbindd/winbindd_async.c
@@ -453,6 +453,162 @@ enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain,
 	return WINBINDD_OK;
 }
 
+/* This is the first callback after enumerating users/groups from a domain */
+static void listent_recv(TALLOC_CTX *mem_ctx, bool success,
+	                    struct winbindd_response *response,
+			    void *c, void *private_data)
+{
+	void (*cont)(void *priv, bool succ, fstring dom_name, char *data) =
+		(void (*)(void *, bool, fstring, char*))c;
+
+	if (!success || response->result != WINBINDD_OK) {
+		DEBUG(5, ("list_ent() failed!\n"));
+		cont(private_data, False, response->data.name.dom_name, NULL);
+		return;
+	}
+
+	cont(private_data, True, response->data.name.dom_name,
+	     response->extra_data.data);
+
+	SAFE_FREE(response->extra_data.data);
+}
+
+/* Request the name of all users/groups in a single domain */
+void winbindd_listent_async(TALLOC_CTX *mem_ctx,
+	                       struct winbindd_domain *domain,
+	                       void (*cont)(void *private_data, bool success,
+				     fstring dom_name, char* extra_data),
+			       void *private_data, enum ent_type type)
+{
+	struct winbindd_request request;
+
+	ZERO_STRUCT(request);
+	if (type == LIST_USERS)
+		request.cmd = WINBINDD_LIST_USERS;
+	else if (type == LIST_GROUPS)
+		request.cmd = WINBINDD_LIST_GROUPS;
+
+	do_async_domain(mem_ctx, domain, &request, listent_recv,
+		        (void *)cont, private_data);
+}
+ 
+enum winbindd_result winbindd_dual_list_users(struct winbindd_domain *domain,
+                                              struct winbindd_cli_state *state)
+{
+	WINBIND_USERINFO *info;
+	NTSTATUS status;
+	struct winbindd_methods *methods;
+	uint32 num_entries = 0;
+	char *extra_data = NULL;
+	uint32_t extra_data_len = 0, i;
+
+	/* Must copy domain into response first for debugging in parent */
+	fstrcpy(state->response.data.name.dom_name, domain->name);
+
+	/* Query user info */
+	methods = domain->methods;
+	status = methods->query_user_list(domain, state->mem_ctx, 
+					  &num_entries, &info);
+	
+	if (!NT_STATUS_IS_OK(status))
+		return WINBINDD_ERROR;
+
+	if (num_entries == 0)
+		return WINBINDD_OK;
+
+	/* Allocate some memory for extra data.  Note that we limit
+	   account names to sizeof(fstring) = 256 characters.		
+	   +1 for the ',' between group names */
+	extra_data = (char *)SMB_REALLOC(extra_data, 
+		(sizeof(fstring) + 1) * num_entries);
+ 
+	if (!extra_data) {
+		DEBUG(0,("failed to enlarge buffer!\n"));
+		return WINBINDD_ERROR;
+	}
+
+	/* Pack user list into extra data fields */
+	for (i = 0; i < num_entries; i++) {
+		fstring acct_name, name;
+		
+		if (info[i].acct_name == NULL)
+			fstrcpy(acct_name, "");
+		else
+			fstrcpy(acct_name, info[i].acct_name);
+		
+		fill_domain_username(name, domain->name, acct_name, True);
+		/* Append to extra data */
+		memcpy(&extra_data[extra_data_len], name, strlen(name));
+		extra_data_len += strlen(name);
+		extra_data[extra_data_len++] = ',';
+	}   
+
+	/* Assign extra_data fields in response structure */
+	if (extra_data) {
+		/* remove trailing ',' */
+		extra_data[extra_data_len - 1] = '\0';
+		state->response.extra_data.data = extra_data;
+		state->response.length += extra_data_len;
+	}
+
+	return WINBINDD_OK;
+}
+
+enum winbindd_result winbindd_dual_list_groups(struct winbindd_domain *domain,
+                                               struct winbindd_cli_state *state)
+{
+	struct getent_state groups = {};
+	char *extra_data = NULL;
+	uint32_t extra_data_len = 0, i;
+
+	/* Must copy domain into response first for debugging in parent */
+	fstrcpy(state->response.data.name.dom_name, domain->name);
+	fstrcpy(groups.domain_name, domain->name);
+
+	/* Get list of sam groups */
+	if (!get_sam_group_entries(&groups)) {
+		/* this domain is empty or in an error state */
+		return WINBINDD_ERROR;
+	}
+
+	/* Allocate some memory for extra data.  Note that we limit
+	   account names to sizeof(fstring) = 256 characters.
+	   +1 for the ',' between group names */
+	extra_data = (char *)SMB_REALLOC(extra_data,
+		(sizeof(fstring) + 1) * groups.num_sam_entries);
+
+	if (!extra_data) {
+		DEBUG(0,("failed to enlarge buffer!\n"));
+		SAFE_FREE(groups.sam_entries);
+		return WINBINDD_ERROR;
+	}
+
+	/* Pack group list into extra data fields */
+	for (i = 0; i < groups.num_sam_entries; i++) {
+		char *group_name = ((struct acct_info *)
+				    groups.sam_entries)[i].acct_name;
+		fstring name;
+
+		fill_domain_username(name, domain->name, group_name, True);
+		/* Append to extra data */
+		memcpy(&extra_data[extra_data_len], name, strlen(name));
+		extra_data_len += strlen(name);
+		extra_data[extra_data_len++] = ',';
+	}
+
+	SAFE_FREE(groups.sam_entries);
+
+	/* Assign extra_data fields in response structure */
+	if (extra_data) {
+		/* remove trailing ',' */
+		extra_data[extra_data_len - 1] = '\0';
+		state->response.extra_data.data = extra_data;
+		state->response.length += extra_data_len;
+	}
+
+	return WINBINDD_OK;
+}
+
 bool print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
 		   size_t num_sids, char **result, ssize_t *len)
 {
diff --git a/source/winbindd/winbindd_cache.c b/source/winbindd/winbindd_cache.c
index a11e96e..dda8b03 100644
--- a/source/winbindd/winbindd_cache.c
+++ b/source/winbindd/winbindd_cache.c
@@ -502,8 +502,14 @@ static void refresh_sequence_number(struct winbindd_domain *domain, bool force)
 	   mode domain or not.  And that we can contact it. */
 
 	if ( winbindd_can_contact_domain( domain ) ) {		
+		struct winbindd_methods *orig_backend = domain->backend;
 		status = domain->backend->sequence_number(domain, 
 							  &domain->sequence_number);
+		if (domain->backend != orig_backend) {
+			/* Try again. */
+			status = domain->backend->sequence_number(domain,
+                                                          &domain->sequence_number);
+		}
 	} else {
 		/* just use the current time */
 		status = NT_STATUS_OK;
@@ -524,7 +530,7 @@ static void refresh_sequence_number(struct winbindd_domain *domain, bool force)
 	domain->last_status = status;
 	domain->last_seq_check = time(NULL);
 	
-	/* save the new sequence number ni the cache */
+	/* save the new sequence number in the cache */
 	store_cache_seqnum( domain );
 
 done:
diff --git a/source/winbindd/winbindd_domain.c b/source/winbindd/winbindd_domain.c
index 1b758cd..2e8c617 100644
--- a/source/winbindd/winbindd_domain.c
+++ b/source/winbindd/winbindd_domain.c
@@ -50,6 +50,14 @@ static const struct winbindd_child_dispatch_table domain_dispatch_table[] = {
 		.struct_cmd	= WINBINDD_LOOKUPRIDS,
 		.struct_fn	= winbindd_dual_lookuprids,
 	},{
+		.name		= "LIST_USERS",
+		.struct_cmd	= WINBINDD_LIST_USERS,
+		.struct_fn	= winbindd_dual_list_users,
+	},{
+		.name		= "LIST_GROUPS",
+		.struct_cmd	= WINBINDD_LIST_GROUPS,
+		.struct_fn	= winbindd_dual_list_groups,
+	},{
 		.name		= "LIST_TRUSTDOM",
 		.struct_cmd	= WINBINDD_LIST_TRUSTDOM,
 		.struct_fn	= winbindd_dual_list_trusted_domains,
diff --git a/source/winbindd/winbindd_group.c b/source/winbindd/winbindd_group.c
index ce6ca37..20b90e3 100644
--- a/source/winbindd/winbindd_group.c
+++ b/source/winbindd/winbindd_group.c
@@ -971,10 +971,9 @@ void winbindd_endgrent(struct winbindd_cli_state *state)
 
 /* Get the list of domain groups and domain aliases for a domain.  We fill in
    the sam_entries and num_sam_entries fields with domain group information.  
-   The dispinfo_ndx field is incremented to the index of the next group to 
-   fetch. Return True if some groups were returned, False otherwise. */
+   Return True if some groups were returned, False otherwise. */
 
-static bool get_sam_group_entries(struct getent_state *ent)
+bool get_sam_group_entries(struct getent_state *ent)
 {
 	NTSTATUS status;
 	uint32 num_entries;
@@ -1341,89 +1340,9 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
 }
 
 /* List domain groups without mapping to unix ids */
-
 void winbindd_list_groups(struct winbindd_cli_state *state)
 {
-	uint32 total_entries = 0;
-	struct winbindd_domain *domain;
-	const char *which_domain;
-	char *extra_data = NULL;
-	unsigned int extra_data_len = 0, i;
-
-	DEBUG(3, ("[%5lu]: list groups\n", (unsigned long)state->pid));
-
-	/* Ensure null termination */
-	state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';	
-	which_domain = state->request.domain_name;
-	
-	/* Enumerate over trusted domains */
-
-	for (domain = domain_list(); domain; domain = domain->next) {
-		struct getent_state groups;
-
-		/* if we have a domain name restricting the request and this
-		   one in the list doesn't match, then just bypass the remainder
-		   of the loop */
-		   
-		if ( *which_domain && !strequal(which_domain, domain->name) )
-			continue;
-			
-		ZERO_STRUCT(groups);
-
-		/* Get list of sam groups */
-		
-		fstrcpy(groups.domain_name, domain->name);
-
-		get_sam_group_entries(&groups);
-			
-		if (groups.num_sam_entries == 0) {
-			/* this domain is empty or in an error state */
-			continue;
-		}
-
-		/* keep track the of the total number of groups seen so 
-		   far over all domains */
-		total_entries += groups.num_sam_entries;
-		
-		/* Allocate some memory for extra data.  Note that we limit
-		   account names to sizeof(fstring) = 128 characters.  */		
-		extra_data = (char *)SMB_REALLOC(
-			extra_data, sizeof(fstring) * total_entries);
- 
-		if (!extra_data) {
-			DEBUG(0,("failed to enlarge buffer!\n"));
-			request_error(state);
-			return;
-		}
-
-		/* Pack group list into extra data fields */
-		for (i = 0; i < groups.num_sam_entries; i++) {
-			char *group_name = ((struct acct_info *)
-					    groups.sam_entries)[i].acct_name; 
-			fstring name;
-
-			fill_domain_username(name, domain->name, group_name, True);
-			/* Append to extra data */			
-			memcpy(&extra_data[extra_data_len], name, 
-                               strlen(name));
-			extra_data_len += strlen(name);
-			extra_data[extra_data_len++] = ',';
-		}
-
-		SAFE_FREE(groups.sam_entries);
-	}
-
-	/* Assign extra_data fields in response structure */
-	if (extra_data) {
-		extra_data[extra_data_len - 1] = '\0';
-		state->response.extra_data.data = extra_data;
-		state->response.length += extra_data_len;
-	}
-
-	/* No domains may have responded but that's still OK so don't
-	   return an error. */
-
-	request_ok(state);
+	winbindd_list_ent(state, LIST_GROUPS);
 }
 
 /* Get user supplementary groups.  This is much quicker than trying to
diff --git a/source/winbindd/winbindd_misc.c b/source/winbindd/winbindd_misc.c
index f63aa16..ddfaa7d 100644
--- a/source/winbindd/winbindd_misc.c
+++ b/source/winbindd/winbindd_misc.c
@@ -97,6 +97,129 @@ enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *do
 	return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
 }
 
+/* Helpers for listing user and group names */
+
+const char *ent_type_strings[] = {"users", 
+				  "groups"};
+
+static const char *get_ent_type_string(enum ent_type type)
+{
+	return ent_type_strings[type];
+}
+
+struct listent_state {
+	TALLOC_CTX *mem_ctx;
+	struct winbindd_cli_state *cli_state;
+	enum ent_type type;
+	int domain_count;
+	char *extra_data;
+	uint32_t extra_data_len;
+};
+
+static void listent_recv(void *private_data, bool success, fstring dom_name,
+	                 char *extra_data);
+
+/* List domain users/groups without mapping to unix ids */
+void winbindd_list_ent(struct winbindd_cli_state *state, enum ent_type type)
+{
+	struct winbindd_domain *domain;
+	const char *which_domain;
+	struct listent_state *ent_state;
+
+	DEBUG(3, ("[%5lu]: list %s\n", (unsigned long)state->pid, 
+	      get_ent_type_string(type)));
+
+	/* Ensure null termination */
+	state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';	
+	which_domain = state->request.domain_name;
+	
+	/* Initialize listent_state */
+	ent_state = TALLOC_P(state->mem_ctx, struct listent_state);
+	if (ent_state == NULL) {
+		DEBUG(0, ("talloc failed\n"));
+		request_error(state);
+		return;
+	}
+
+	ent_state->mem_ctx = state->mem_ctx;
+	ent_state->cli_state = state;
+	ent_state->type = type;
+	ent_state->domain_count = 0;
+	ent_state->extra_data = NULL;
+	ent_state->extra_data_len = 0;
+
+	/* Must count the full list of expected domains before we request data
+	 * from any of them.  Otherwise it's possible for a connection to the
+	 * first domain to fail, call listent_recv(), and return to the
+	 * client without checking any other domains. */
+	for (domain = domain_list(); domain; domain = domain->next) {
+		/* if we have a domain name restricting the request and this
+		   one in the list doesn't match, then just bypass the remainder
+		   of the loop */
+		if ( *which_domain && !strequal(which_domain, domain->name) )
+			continue;
+
+		ent_state->domain_count++;
+	}
+
+	/* Make sure we're enumerating at least one domain */
+	if (!ent_state->domain_count) {
+		request_ok(state);
+		return;
+	}
+
+	/* Enumerate list of trusted domains and request user/group list from
+	 * each */
+	for (domain = domain_list(); domain; domain = domain->next) {
+		if ( *which_domain && !strequal(which_domain, domain->name) )
+			continue;
+
+		winbindd_listent_async(state->mem_ctx, domain, 
+			                  listent_recv, ent_state, type);
+	}
+}
+
+static void listent_recv(void *private_data, bool success, fstring dom_name,
+	                 char *extra_data)
+{
+	/* extra_data comes to us as a '\0' terminated string of comma
+	   separated users or groups */
+	struct listent_state *state = talloc_get_type_abort(
+		private_data, struct listent_state);
+
+	/* Append users/groups from one domain onto the whole list */
+	if (extra_data) {
+		DEBUG(5, ("listent_recv: %s returned %s.\n", 
+		      dom_name, get_ent_type_string(state->type)));
+                if (!state->extra_data)
+                        state->extra_data = talloc_asprintf(state->mem_ctx,
+                                                            "%s", extra_data);
+                else
+                        state->extra_data = talloc_asprintf_append(
+                                                            state->extra_data,
+                                                            ",%s", extra_data);
+                /* Add one for the '\0' and each additional ',' */
+                state->extra_data_len += strlen(extra_data) + 1;
+	}
+	else {
+		DEBUG(5, ("listent_recv: %s returned no %s.\n", 
+		      dom_name, get_ent_type_string(state->type)));
+	}
+
+	if (--state->domain_count)
+		/* Still waiting for some child domains to return */
+		return;
+
+	/* Return list of all users/groups to the client */
+	if (state->extra_data) {
+		state->cli_state->response.extra_data.data = 
+			SMB_STRDUP(state->extra_data);
+		state->cli_state->response.length += state->extra_data_len;
+	}
+
+	request_ok(state->cli_state);
+}	
+
 /* Constants and helper functions for determining domain trust types */
 
 enum trust_type {
diff --git a/source/winbindd/winbindd_user.c b/source/winbindd/winbindd_user.c
index 6241d84..4591838 100644
--- a/source/winbindd/winbindd_user.c
+++ b/source/winbindd/winbindd_user.c
@@ -778,99 +778,7 @@ void winbindd_getpwent(struct winbindd_cli_state *state)
 }
 
 /* List domain users without mapping to unix ids */
-
 void winbindd_list_users(struct winbindd_cli_state *state)
 {
-	struct winbindd_domain *domain;
-	WINBIND_USERINFO *info;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list