summaryrefslogtreecommitdiff
path: root/source3/winbindd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/winbindd')
-rw-r--r--source3/winbindd/winbindd.c3
-rw-r--r--source3/winbindd/winbindd_async.c180
-rw-r--r--source3/winbindd/winbindd_domain.c8
-rw-r--r--source3/winbindd/winbindd_group.c6
-rw-r--r--source3/winbindd/winbindd_list_groups.c204
-rw-r--r--source3/winbindd/winbindd_misc.c122
-rw-r--r--source3/winbindd/winbindd_proto.h8
7 files changed, 214 insertions, 317 deletions
diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c
index 1d3762f5b9..e583dae4a9 100644
--- a/source3/winbindd/winbindd.c
+++ b/source3/winbindd/winbindd.c
@@ -435,7 +435,6 @@ static struct winbindd_dispatch_table {
/* Enumeration functions */
- { WINBINDD_LIST_GROUPS, winbindd_list_groups, "LIST_GROUPS" },
{ WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
"LIST_TRUSTDOM" },
@@ -538,6 +537,8 @@ static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
winbindd_endgrent_send, winbindd_endgrent_recv },
{ WINBINDD_LIST_USERS, "LIST_USERS",
winbindd_list_users_send, winbindd_list_users_recv },
+ { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
+ winbindd_list_groups_send, winbindd_list_groups_recv },
{ 0, NULL, NULL, NULL }
};
diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c
index 1e63ed1fec..6c5d92e71b 100644
--- a/source3/winbindd/winbindd_async.c
+++ b/source3/winbindd/winbindd_async.c
@@ -454,163 +454,6 @@ 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,
- (char *)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)
-{
- struct wbint_userinfo *info;
- NTSTATUS status;
- struct winbindd_methods *methods;
- uint32 num_entries = 0;
- char *extra_data;
- 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 = talloc_array(state->mem_ctx, char,
- (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;
- uint32_t extra_data_len = 0, i;
-
- ZERO_STRUCT(groups);
-
- /* 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 = talloc_array(
- state->mem_ctx, char,
- (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)
{
@@ -671,29 +514,6 @@ bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
return True;
}
-static bool parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
- uint32 **rids, size_t *num_rids)
-{
- char *p;
-
- p = ridstr;
- if (p == NULL)
- return False;
-
- while (p[0] != '\0') {
- uint32 rid;
- char *q;
- rid = strtoul(p, &q, 10);
- if (*q != '\n') {
- DEBUG(0, ("Got invalid ridstr: %s\n", p));
- return False;
- }
- p = q+1;
- ADD_TO_ARRAY(mem_ctx, uint32, rid, rids, num_rids);
- }
- return True;
-}
-
static void getsidaliases_recv(TALLOC_CTX *mem_ctx, bool success,
struct winbindd_response *response,
void *c, void *private_data)
diff --git a/source3/winbindd/winbindd_domain.c b/source3/winbindd/winbindd_domain.c
index 14376c62bf..107c83ac80 100644
--- a/source3/winbindd/winbindd_domain.c
+++ b/source3/winbindd/winbindd_domain.c
@@ -50,14 +50,6 @@ static const struct winbindd_child_dispatch_table domain_dispatch_table[] = {
.struct_cmd = WINBINDD_LOOKUPNAME,
.struct_fn = winbindd_dual_lookupname,
},{
- .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/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c
index 8a76071265..eab5c26df4 100644
--- a/source3/winbindd/winbindd_group.c
+++ b/source3/winbindd/winbindd_group.c
@@ -201,12 +201,6 @@ bool get_sam_group_entries(struct getent_state *ent)
return result;
}
-/* List domain groups without mapping to unix ids */
-void winbindd_list_groups(struct winbindd_cli_state *state)
-{
- winbindd_list_ent(state, LIST_GROUPS);
-}
-
/* Get user supplementary groups. This is much quicker than trying to
invert the groups database. We merge the groups from the gids and
other_sids info3 fields as trusted domain, universal group
diff --git a/source3/winbindd/winbindd_list_groups.c b/source3/winbindd/winbindd_list_groups.c
new file mode 100644
index 0000000000..3795045787
--- /dev/null
+++ b/source3/winbindd/winbindd_list_groups.c
@@ -0,0 +1,204 @@
+/*
+ Unix SMB/CIFS implementation.
+ async implementation of WINBINDD_LIST_GROUPS
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+#include "librpc/gen_ndr/cli_wbint.h"
+
+struct winbindd_list_groups_domstate {
+ struct tevent_req *subreq;
+ struct winbindd_domain *domain;
+ struct wbint_Principals groups;
+};
+
+struct winbindd_list_groups_state {
+ int num_received;
+ /* All domains */
+ int num_domains;
+ struct winbindd_list_groups_domstate *domains;
+};
+
+static void winbindd_list_groups_done(struct tevent_req *subreq);
+
+struct tevent_req *winbindd_list_groups_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_cli_state *cli,
+ struct winbindd_request *request)
+{
+ struct tevent_req *req;
+ struct winbindd_list_groups_state *state;
+ struct winbindd_domain *domain;
+ int i;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct winbindd_list_groups_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ /* Ensure null termination */
+ request->domain_name[sizeof(request->domain_name)-1]='\0';
+
+ DEBUG(3, ("list_groups %s\n", request->domain_name));
+
+ if (request->domain_name[0] != '\0') {
+ state->num_domains = 1;
+ } else {
+ state->num_domains = 0;
+ for (domain = domain_list(); domain; domain = domain->next) {
+ state->num_domains += 1;
+ }
+ }
+
+ state->domains = talloc_array(state,
+ struct winbindd_list_groups_domstate,
+ state->num_domains);
+ if (tevent_req_nomem(state->domains, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ if (request->domain_name[0] != '\0') {
+ state->domains[0].domain = find_domain_from_name_noinit(
+ request->domain_name);
+ if (state->domains[0].domain == NULL) {
+ tevent_req_nterror(req, NT_STATUS_NO_SUCH_DOMAIN);
+ return tevent_req_post(req, ev);
+ }
+ } else {
+ i = 0;
+ for (domain = domain_list(); domain; domain = domain->next) {
+ state->domains[i++].domain = domain;
+ }
+ }
+
+ for (i=0; i<state->num_domains; i++) {
+ struct winbindd_list_groups_domstate *d = &state->domains[i];
+
+ d->subreq = rpccli_wbint_QueryGroupList_send(
+ state->domains, ev, d->domain->child.rpccli,
+ &d->groups);
+ if (tevent_req_nomem(d->subreq, req)) {
+ TALLOC_FREE(state->domains);
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(d->subreq, winbindd_list_groups_done,
+ req);
+ }
+ state->num_received = 0;
+ return req;
+}
+
+static void winbindd_list_groups_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct winbindd_list_groups_state *state = tevent_req_data(
+ req, struct winbindd_list_groups_state);
+ NTSTATUS status, result;
+ int i;
+
+ status = rpccli_wbint_QueryGroupList_recv(subreq, state->domains,
+ &result);
+
+ for (i=0; i<state->num_domains; i++) {
+ if (subreq == state->domains[i].subreq) {
+ break;
+ }
+ }
+ if (i < state->num_domains) {
+ struct winbindd_list_groups_domstate *d = &state->domains[i];
+
+ DEBUG(10, ("Domain %s returned %d users\n", d->domain->name,
+ d->groups.num_principals));
+
+ d->subreq = NULL;
+
+ if (!NT_STATUS_IS_OK(status) || !NT_STATUS_IS_OK(result)) {
+ DEBUG(10, ("list_groups for domain %s failed\n",
+ d->domain->name));
+ d->groups.num_principals = 0;
+ }
+ }
+
+ TALLOC_FREE(subreq);
+
+ state->num_received += 1;
+
+ if (state->num_received >= state->num_domains) {
+ tevent_req_done(req);
+ }
+}
+
+NTSTATUS winbindd_list_groups_recv(struct tevent_req *req,
+ struct winbindd_response *response)
+{
+ struct winbindd_list_groups_state *state = tevent_req_data(
+ req, struct winbindd_list_groups_state);
+ NTSTATUS status;
+ char *result;
+ int i;
+ uint32_t j;
+ size_t len;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+
+ len = 0;
+ for (i=0; i<state->num_domains; i++) {
+ struct winbindd_list_groups_domstate *d = &state->domains[i];
+
+ for (j=0; j<d->groups.num_principals; j++) {
+ fstring name;
+ fill_domain_username(name, d->domain->name,
+ d->groups.principals[j].name,
+ True);
+ len += strlen(name)+1;
+ }
+ }
+
+ result = talloc_array(response, char, len+1);
+ if (result == 0) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ len = 0;
+ for (i=0; i<state->num_domains; i++) {
+ struct winbindd_list_groups_domstate *d = &state->domains[i];
+
+ for (j=0; j<d->groups.num_principals; j++) {
+ fstring name;
+ size_t this_len;
+ fill_domain_username(name, d->domain->name,
+ d->groups.principals[j].name,
+ True);
+ this_len = strlen(name);
+ memcpy(result+len, name, this_len);
+ len += this_len;
+ result[len] = ',';
+ len += 1;
+ }
+ }
+ result[len-1] = '\0';
+
+ response->extra_data.data = result;
+ response->length += len;
+
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c
index beaf450743..b967390966 100644
--- a/source3/winbindd/winbindd_misc.c
+++ b/source3/winbindd/winbindd_misc.c
@@ -94,128 +94,6 @@ 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 = 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/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 9894602523..b59d11b78f 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -950,4 +950,12 @@ struct tevent_req *winbindd_list_users_send(TALLOC_CTX *mem_ctx,
NTSTATUS winbindd_list_users_recv(struct tevent_req *req,
struct winbindd_response *response);
+struct tevent_req *winbindd_list_groups_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_cli_state *cli,
+ struct winbindd_request *request);
+NTSTATUS winbindd_list_groups_recv(struct tevent_req *req,
+ struct winbindd_response *response);
+
+
#endif /* _WINBINDD_PROTO_H_ */