1/* 2 Unix SMB/CIFS implementation. 3 async getpwsid 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_getpwsid_state { 25 struct winbindd_domain *user_domain; 26 struct tevent_context *ev; 27 struct dom_sid sid; 28 struct wbint_userinfo *userinfo; 29 struct winbindd_pw *pw; 30}; 31 32static void wb_getpwsid_queryuser_done(struct tevent_req *subreq); 33static void wb_getpwsid_lookupsid_done(struct tevent_req *subreq); 34static void wb_getpwsid_done(struct tevent_req *subreq); 35 36struct tevent_req *wb_getpwsid_send(TALLOC_CTX *mem_ctx, 37 struct tevent_context *ev, 38 const struct dom_sid *user_sid, 39 struct winbindd_pw *pw) 40{ 41 struct tevent_req *req, *subreq; 42 struct wb_getpwsid_state *state; 43 44 req = tevent_req_create(mem_ctx, &state, struct wb_getpwsid_state); 45 if (req == NULL) { 46 return NULL; 47 } 48 sid_copy(&state->sid, user_sid); 49 state->ev = ev; 50 state->pw = pw; 51 52 state->user_domain = find_domain_from_sid_noinit(user_sid); 53 if (state->user_domain == NULL) { 54 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); 55 return tevent_req_post(req, ev); 56 } 57 58 subreq = wb_queryuser_send(state, ev, &state->sid); 59 if (tevent_req_nomem(subreq, req)) { 60 return tevent_req_post(req, ev); 61 } 62 tevent_req_set_callback(subreq, wb_getpwsid_queryuser_done, req); 63 return req; 64} 65 66static void wb_getpwsid_queryuser_done(struct tevent_req *subreq) 67{ 68 struct tevent_req *req = tevent_req_callback_data( 69 subreq, struct tevent_req); 70 struct wb_getpwsid_state *state = tevent_req_data( 71 req, struct wb_getpwsid_state); 72 NTSTATUS status; 73 74 status = wb_queryuser_recv(subreq, state, &state->userinfo); 75 TALLOC_FREE(subreq); 76 if (!NT_STATUS_IS_OK(status)) { 77 tevent_req_nterror(req, status); 78 return; 79 } 80 81 if ((state->userinfo->acct_name != NULL) 82 && (state->userinfo->acct_name[0] != '\0')) { 83 /* 84 * QueryUser got us a name, let's got directly to the 85 * fill_pwent step 86 */ 87 subreq = wb_fill_pwent_send(state, state->ev, state->userinfo, 88 state->pw); 89 if (tevent_req_nomem(subreq, req)) { 90 return; 91 } 92 tevent_req_set_callback(subreq, wb_getpwsid_done, req); 93 return; 94 } 95 96 /* 97 * QueryUser didn't get us a name, do it via LSA. 98 */ 99 subreq = wb_lookupsid_send(state, state->ev, 100 &state->userinfo->user_sid); 101 if (tevent_req_nomem(subreq, req)) { 102 return; 103 } 104 tevent_req_set_callback(subreq, wb_getpwsid_lookupsid_done, req); 105} 106 107static void wb_getpwsid_lookupsid_done(struct tevent_req *subreq) 108{ 109 struct tevent_req *req = tevent_req_callback_data( 110 subreq, struct tevent_req); 111 struct wb_getpwsid_state *state = tevent_req_data( 112 req, struct wb_getpwsid_state); 113 NTSTATUS status; 114 enum lsa_SidType type; 115 const char *domain; 116 117 status = wb_lookupsid_recv(subreq, state->userinfo, &type, &domain, 118 &state->userinfo->acct_name); 119 TALLOC_FREE(subreq); 120 if (!NT_STATUS_IS_OK(status)) { 121 tevent_req_nterror(req, status); 122 return; 123 } 124 subreq = wb_fill_pwent_send(state, state->ev, state->userinfo, 125 state->pw); 126 if (tevent_req_nomem(subreq, req)) { 127 return; 128 } 129 tevent_req_set_callback(subreq, wb_getpwsid_done, req); 130} 131 132static void wb_getpwsid_done(struct tevent_req *subreq) 133{ 134 struct tevent_req *req = tevent_req_callback_data( 135 subreq, struct tevent_req); 136 NTSTATUS status; 137 138 status = wb_fill_pwent_recv(subreq); 139 if (!NT_STATUS_IS_OK(status)) { 140 tevent_req_nterror(req, status); 141 return; 142 } 143 tevent_req_done(req); 144} 145 146NTSTATUS wb_getpwsid_recv(struct tevent_req *req) 147{ 148 NTSTATUS status; 149 150 if (tevent_req_is_nterror(req, &status)) { 151 return status; 152 } 153 return NT_STATUS_OK; 154} 155