2 Unix SMB/CIFS implementation.
4 Copyright (C) Volker Lendecke 2009
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.
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.
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/>.
22 #include "librpc/gen_ndr/ndr_winbind_c.h"
23 #include "../libcli/security/security.h"
24 #include "passdb/machine_sid.h"
26 struct wb_gettoken_state {
27 struct tevent_context *ev;
28 struct dom_sid usersid;
29 bool expand_local_aliases;
34 static NTSTATUS wb_add_rids_to_sids(TALLOC_CTX *mem_ctx,
36 struct dom_sid **psids,
37 const struct dom_sid *domain_sid,
38 int num_rids, uint32_t *rids);
40 static void wb_gettoken_gotuser(struct tevent_req *subreq);
41 static void wb_gettoken_gotgroups(struct tevent_req *subreq);
42 static void wb_gettoken_gotlocalgroups(struct tevent_req *subreq);
43 static void wb_gettoken_gotbuiltins(struct tevent_req *subreq);
45 struct tevent_req *wb_gettoken_send(TALLOC_CTX *mem_ctx,
46 struct tevent_context *ev,
47 const struct dom_sid *sid,
48 bool expand_local_aliases)
50 struct tevent_req *req, *subreq;
51 struct wb_gettoken_state *state;
53 req = tevent_req_create(mem_ctx, &state, struct wb_gettoken_state);
57 sid_copy(&state->usersid, sid);
59 state->expand_local_aliases = expand_local_aliases;
61 subreq = wb_queryuser_send(state, ev, &state->usersid);
62 if (tevent_req_nomem(subreq, req)) {
63 return tevent_req_post(req, ev);
65 tevent_req_set_callback(subreq, wb_gettoken_gotuser, req);
69 static void wb_gettoken_gotuser(struct tevent_req *subreq)
71 struct tevent_req *req = tevent_req_callback_data(
72 subreq, struct tevent_req);
73 struct wb_gettoken_state *state = tevent_req_data(
74 req, struct wb_gettoken_state);
75 struct wbint_userinfo *info;
78 status = wb_queryuser_recv(subreq, state, &info);
80 if (tevent_req_nterror(req, status)) {
84 state->sids = talloc_array(state, struct dom_sid, 2);
85 if (tevent_req_nomem(state->sids, req)) {
90 sid_copy(&state->sids[0], &info->user_sid);
91 sid_copy(&state->sids[1], &info->group_sid);
93 subreq = wb_lookupusergroups_send(state, state->ev, &info->user_sid);
94 if (tevent_req_nomem(subreq, req)) {
97 tevent_req_set_callback(subreq, wb_gettoken_gotgroups, req);
100 static void wb_gettoken_gotgroups(struct tevent_req *subreq)
102 struct tevent_req *req = tevent_req_callback_data(
103 subreq, struct tevent_req);
104 struct wb_gettoken_state *state = tevent_req_data(
105 req, struct wb_gettoken_state);
107 struct dom_sid *groups;
108 struct winbindd_domain *domain;
111 status = wb_lookupusergroups_recv(subreq, state, &num_groups, &groups);
113 if (!NT_STATUS_IS_OK(status)) {
114 tevent_req_done(req);
118 for (i=0; i<num_groups; i++) {
119 status = add_sid_to_array_unique(
120 state, &groups[i], &state->sids, &state->num_sids);
122 if (tevent_req_nterror(req, status)) {
127 if (!state->expand_local_aliases) {
128 tevent_req_done(req);
133 * Expand our domain's aliases
135 domain = find_domain_from_sid_noinit(get_global_sam_sid());
136 if (domain == NULL) {
137 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
141 subreq = wb_lookupuseraliases_send(state, state->ev, domain,
142 state->num_sids, state->sids);
143 if (tevent_req_nomem(subreq, req)) {
146 tevent_req_set_callback(subreq, wb_gettoken_gotlocalgroups, req);
149 static void wb_gettoken_gotlocalgroups(struct tevent_req *subreq)
151 struct tevent_req *req = tevent_req_callback_data(
152 subreq, struct tevent_req);
153 struct wb_gettoken_state *state = tevent_req_data(
154 req, struct wb_gettoken_state);
157 struct winbindd_domain *domain;
160 status = wb_lookupuseraliases_recv(subreq, state, &num_rids, &rids);
162 if (tevent_req_nterror(req, status)) {
166 status = wb_add_rids_to_sids(state, &state->num_sids, &state->sids,
167 get_global_sam_sid(), num_rids, rids);
168 if (tevent_req_nterror(req, status)) {
174 * Now expand the builtin groups
177 domain = find_domain_from_sid(&global_sid_Builtin);
178 if (domain == NULL) {
179 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
183 subreq = wb_lookupuseraliases_send(state, state->ev, domain,
184 state->num_sids, state->sids);
185 if (tevent_req_nomem(subreq, req)) {
188 tevent_req_set_callback(subreq, wb_gettoken_gotbuiltins, req);
191 static void wb_gettoken_gotbuiltins(struct tevent_req *subreq)
193 struct tevent_req *req = tevent_req_callback_data(
194 subreq, struct tevent_req);
195 struct wb_gettoken_state *state = tevent_req_data(
196 req, struct wb_gettoken_state);
201 status = wb_lookupuseraliases_recv(subreq, state, &num_rids, &rids);
203 if (tevent_req_nterror(req, status)) {
206 status = wb_add_rids_to_sids(state, &state->num_sids, &state->sids,
207 &global_sid_Builtin, num_rids, rids);
208 if (tevent_req_nterror(req, status)) {
211 tevent_req_done(req);
214 NTSTATUS wb_gettoken_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
215 int *num_sids, struct dom_sid **sids)
217 struct wb_gettoken_state *state = tevent_req_data(
218 req, struct wb_gettoken_state);
221 if (tevent_req_is_nterror(req, &status)) {
224 *num_sids = state->num_sids;
225 *sids = talloc_move(mem_ctx, &state->sids);
229 static NTSTATUS wb_add_rids_to_sids(TALLOC_CTX *mem_ctx,
231 struct dom_sid **psids,
232 const struct dom_sid *domain_sid,
233 int num_rids, uint32_t *rids)
237 for (i=0; i<num_rids; i++) {
241 sid_compose(&sid, domain_sid, rids[i]);
243 status = add_sid_to_array_unique(
244 mem_ctx, &sid, psids, pnum_sids);
245 if (!NT_STATUS_IS_OK(status)) {