• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source3/winbindd/
1/*
2   Unix SMB/CIFS implementation.
3   async implementation of WINBINDD_GETPWENT
4   Copyright (C) Volker Lendecke 2009
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 3 of the License, or
9   (at your option) any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#include "includes.h"
21#include "winbindd.h"
22
23struct winbindd_getpwent_state {
24	struct tevent_context *ev;
25	struct winbindd_cli_state *cli;
26	int max_users;
27	int num_users;
28	struct winbindd_pw *users;
29};
30
31static void winbindd_getpwent_done(struct tevent_req *subreq);
32
33struct tevent_req *winbindd_getpwent_send(TALLOC_CTX *mem_ctx,
34					  struct tevent_context *ev,
35					  struct winbindd_cli_state *cli,
36					  struct winbindd_request *request)
37{
38	struct tevent_req *req, *subreq;
39	struct winbindd_getpwent_state *state;
40
41	req = tevent_req_create(mem_ctx, &state,
42				struct winbindd_getpwent_state);
43	if (req == NULL) {
44		return NULL;
45	}
46	state->ev = ev;
47	state->num_users = 0;
48	state->cli = cli;
49
50	DEBUG(3, ("[%5lu]: getpwent\n", (unsigned long)cli->pid));
51
52	if (!lp_winbind_enum_users()) {
53		tevent_req_nterror(req, NT_STATUS_NO_MORE_ENTRIES);
54		return tevent_req_post(req, ev);
55	}
56
57	if (cli->pwent_state == NULL) {
58		tevent_req_nterror(req, NT_STATUS_NO_MORE_ENTRIES);
59		return tevent_req_post(req, ev);
60	}
61
62	state->max_users = MIN(500, request->data.num_entries);
63	if (state->max_users == 0) {
64		tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
65		return tevent_req_post(req, ev);
66	}
67
68	state->users = talloc_zero_array(state, struct winbindd_pw,
69					 state->max_users);
70	if (tevent_req_nomem(state->users, req)) {
71		return tevent_req_post(req, ev);
72	}
73
74	subreq = wb_next_pwent_send(state, ev, cli->pwent_state,
75				    &state->users[state->num_users]);
76	if (tevent_req_nomem(subreq, req)) {
77		return tevent_req_post(req, ev);
78	}
79	tevent_req_set_callback(subreq, winbindd_getpwent_done, req);
80	return req;
81}
82
83static void winbindd_getpwent_done(struct tevent_req *subreq)
84{
85	struct tevent_req *req = tevent_req_callback_data(
86		subreq, struct tevent_req);
87	struct winbindd_getpwent_state *state = tevent_req_data(
88		req, struct winbindd_getpwent_state);
89	NTSTATUS status;
90
91	status = wb_next_pwent_recv(subreq);
92	TALLOC_FREE(subreq);
93	if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)) {
94		DEBUG(10, ("winbindd_getpwent_done: done with %d users\n",
95			   (int)state->num_users));
96		TALLOC_FREE(state->cli->pwent_state);
97		tevent_req_done(req);
98		return;
99	}
100	if (!NT_STATUS_IS_OK(status)) {
101		tevent_req_nterror(req, status);
102		return;
103	}
104	state->num_users += 1;
105	if (state->num_users >= state->max_users) {
106		DEBUG(10, ("winbindd_getpwent_done: Got enough users: %d\n",
107			   (int)state->num_users));
108		tevent_req_done(req);
109		return;
110	}
111	if (state->cli->pwent_state == NULL) {
112		DEBUG(10, ("winbindd_getpwent_done: endpwent called in "
113			   "between\n"));
114		tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
115		return;
116	}
117	subreq = wb_next_pwent_send(state, state->ev, state->cli->pwent_state,
118				    &state->users[state->num_users]);
119	if (tevent_req_nomem(subreq, req)) {
120		return;
121	}
122	tevent_req_set_callback(subreq, winbindd_getpwent_done, req);
123}
124
125NTSTATUS winbindd_getpwent_recv(struct tevent_req *req,
126				struct winbindd_response *response)
127{
128	struct winbindd_getpwent_state *state = tevent_req_data(
129		req, struct winbindd_getpwent_state);
130	NTSTATUS status;
131
132	if (tevent_req_is_nterror(req, &status)) {
133		DEBUG(5, ("getpwent failed: %s\n", nt_errstr(status)));
134		return status;
135	}
136
137	if (state->num_users == 0) {
138		return NT_STATUS_NO_MORE_ENTRIES;
139	}
140
141	response->data.num_entries = state->num_users;
142	response->extra_data.data = talloc_move(response, &state->users);
143	response->length += state->num_users * sizeof(struct winbindd_pw);
144	return NT_STATUS_OK;
145}
146