1/* 2 Unix SMB/CIFS implementation. 3 async next_pwent 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#include "librpc/gen_ndr/cli_wbint.h" 23 24struct wb_next_pwent_state { 25 struct tevent_context *ev; 26 struct getpwent_state *gstate; 27 struct winbindd_pw *pw; 28}; 29 30static void wb_next_pwent_fetch_done(struct tevent_req *subreq); 31static void wb_next_pwent_fill_done(struct tevent_req *subreq); 32 33struct tevent_req *wb_next_pwent_send(TALLOC_CTX *mem_ctx, 34 struct tevent_context *ev, 35 struct getpwent_state *gstate, 36 struct winbindd_pw *pw) 37{ 38 struct tevent_req *req, *subreq; 39 struct wb_next_pwent_state *state; 40 41 req = tevent_req_create(mem_ctx, &state, struct wb_next_pwent_state); 42 if (req == NULL) { 43 return NULL; 44 } 45 state->ev = ev; 46 state->gstate = gstate; 47 state->pw = pw; 48 49 if (state->gstate->next_user >= state->gstate->num_users) { 50 TALLOC_FREE(state->gstate->users); 51 52 if (state->gstate->domain == NULL) { 53 state->gstate->domain = domain_list(); 54 } else { 55 state->gstate->domain = state->gstate->domain->next; 56 } 57 58 if ((state->gstate->domain != NULL) 59 && sid_check_is_domain(&state->gstate->domain->sid)) { 60 state->gstate->domain = state->gstate->domain->next; 61 } 62 63 if (state->gstate->domain == NULL) { 64 tevent_req_nterror(req, NT_STATUS_NO_MORE_ENTRIES); 65 return tevent_req_post(req, ev); 66 } 67 subreq = wb_query_user_list_send(state, state->ev, 68 state->gstate->domain); 69 if (tevent_req_nomem(subreq, req)) { 70 return tevent_req_post(req, ev); 71 } 72 tevent_req_set_callback(subreq, wb_next_pwent_fetch_done, req); 73 return req; 74 } 75 76 subreq = wb_fill_pwent_send( 77 state, state->ev, 78 &state->gstate->users[state->gstate->next_user], 79 state->pw); 80 if (tevent_req_nomem(subreq, req)) { 81 return tevent_req_post(req, ev); 82 } 83 tevent_req_set_callback(subreq, wb_next_pwent_fill_done, req); 84 return req; 85} 86 87static void wb_next_pwent_fetch_done(struct tevent_req *subreq) 88{ 89 struct tevent_req *req = tevent_req_callback_data( 90 subreq, struct tevent_req); 91 struct wb_next_pwent_state *state = tevent_req_data( 92 req, struct wb_next_pwent_state); 93 NTSTATUS status; 94 95 status = wb_query_user_list_recv(subreq, state->gstate, 96 &state->gstate->num_users, 97 &state->gstate->users); 98 TALLOC_FREE(subreq); 99 if (!NT_STATUS_IS_OK(status)) { 100 /* Ignore errors here, just log it */ 101 DEBUG(10, ("query_user_list for domain %s returned %s\n", 102 state->gstate->domain->name, 103 nt_errstr(status))); 104 state->gstate->num_users = 0; 105 } 106 107 if (state->gstate->num_users == 0) { 108 state->gstate->domain = state->gstate->domain->next; 109 110 if ((state->gstate->domain != NULL) 111 && sid_check_is_domain(&state->gstate->domain->sid)) { 112 state->gstate->domain = state->gstate->domain->next; 113 } 114 115 if (state->gstate->domain == NULL) { 116 tevent_req_nterror(req, NT_STATUS_NO_MORE_ENTRIES); 117 return; 118 } 119 subreq = wb_query_user_list_send(state, state->ev, 120 state->gstate->domain); 121 if (tevent_req_nomem(subreq, req)) { 122 return; 123 } 124 tevent_req_set_callback(subreq, wb_next_pwent_fetch_done, req); 125 return; 126 } 127 128 state->gstate->next_user = 0; 129 130 subreq = wb_fill_pwent_send( 131 state, state->ev, 132 &state->gstate->users[state->gstate->next_user], 133 state->pw); 134 if (tevent_req_nomem(subreq, req)) { 135 return; 136 } 137 tevent_req_set_callback(subreq, wb_next_pwent_fill_done, req); 138} 139 140static void wb_next_pwent_fill_done(struct tevent_req *subreq) 141{ 142 struct tevent_req *req = tevent_req_callback_data( 143 subreq, struct tevent_req); 144 struct wb_next_pwent_state *state = tevent_req_data( 145 req, struct wb_next_pwent_state); 146 NTSTATUS status; 147 148 status = wb_fill_pwent_recv(subreq); 149 TALLOC_FREE(subreq); 150 if (!NT_STATUS_IS_OK(status)) { 151 tevent_req_nterror(req, status); 152 return; 153 } 154 state->gstate->next_user += 1; 155 tevent_req_done(req); 156} 157 158NTSTATUS wb_next_pwent_recv(struct tevent_req *req) 159{ 160 return tevent_req_simple_recv_ntstatus(req); 161} 162