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;
33 static bool wb_add_rids_to_sids(TALLOC_CTX *mem_ctx,
34 int *pnum_sids, struct dom_sid **psids,
35 const struct dom_sid *domain_sid,
36 int num_rids, uint32_t *rids);
38 static void wb_gettoken_gotuser(struct tevent_req *subreq);
39 static void wb_gettoken_gotlocalgroups(struct tevent_req *subreq);
40 static void wb_gettoken_gotbuiltins(struct tevent_req *subreq);
42 struct tevent_req *wb_gettoken_send(TALLOC_CTX *mem_ctx,
43 struct tevent_context *ev,
44 const struct dom_sid *sid)
46 struct tevent_req *req, *subreq;
47 struct wb_gettoken_state *state;
49 req = tevent_req_create(mem_ctx, &state, struct wb_gettoken_state);
53 sid_copy(&state->usersid, sid);
56 subreq = wb_queryuser_send(state, ev, &state->usersid);
57 if (tevent_req_nomem(subreq, req)) {
58 return tevent_req_post(req, ev);
60 tevent_req_set_callback(subreq, wb_gettoken_gotuser, req);
64 static void wb_gettoken_gotuser(struct tevent_req *subreq)
66 struct tevent_req *req = tevent_req_callback_data(
67 subreq, struct tevent_req);
68 struct wb_gettoken_state *state = tevent_req_data(
69 req, struct wb_gettoken_state);
71 struct winbindd_domain *domain;
72 struct wbint_userinfo *info;
74 struct dom_sid *groups;
77 status = wb_queryuser_recv(subreq, state, &info);
79 if (tevent_req_nterror(req, status)) {
83 sids = talloc_array(state, struct dom_sid, 2);
84 if (tevent_req_nomem(sids, req)) {
90 sid_copy(&state->sids[0], &info->user_sid);
91 sid_copy(&state->sids[1], &info->group_sid);
93 status = lookup_usergroups_cached(
94 state, &info->user_sid, &num_groups, &groups);
95 if (!NT_STATUS_IS_OK(status)) {
96 DBG_DEBUG("lookup_usergroups_cached failed (%s), not doing "
97 "supplementary group lookups\n", nt_errstr(status));
102 if (num_groups + state->num_sids < num_groups) {
103 tevent_req_nterror(req, NT_STATUS_INTEGER_OVERFLOW);
107 sids = talloc_realloc(state, state->sids, struct dom_sid,
108 state->num_sids+num_groups);
109 if (tevent_req_nomem(sids, req)) {
114 memcpy(&state->sids[state->num_sids], groups,
115 num_groups * sizeof(struct dom_sid));
116 state->num_sids += num_groups;
119 * Expand our domain's aliases
121 domain = find_domain_from_sid_noinit(get_global_sam_sid());
122 if (domain == NULL) {
123 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
127 subreq = wb_lookupuseraliases_send(state, state->ev, domain,
128 state->num_sids, state->sids);
129 if (tevent_req_nomem(subreq, req)) {
132 tevent_req_set_callback(subreq, wb_gettoken_gotlocalgroups, req);
135 static void wb_gettoken_gotlocalgroups(struct tevent_req *subreq)
137 struct tevent_req *req = tevent_req_callback_data(
138 subreq, struct tevent_req);
139 struct wb_gettoken_state *state = tevent_req_data(
140 req, struct wb_gettoken_state);
143 struct winbindd_domain *domain;
146 status = wb_lookupuseraliases_recv(subreq, state, &num_rids, &rids);
148 if (tevent_req_nterror(req, status)) {
151 if (!wb_add_rids_to_sids(state, &state->num_sids, &state->sids,
152 get_global_sam_sid(), num_rids, rids)) {
153 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
159 * Now expand the builtin groups
162 domain = find_builtin_domain();
163 if (domain == NULL) {
164 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
168 subreq = wb_lookupuseraliases_send(state, state->ev, domain,
169 state->num_sids, state->sids);
170 if (tevent_req_nomem(subreq, req)) {
173 tevent_req_set_callback(subreq, wb_gettoken_gotbuiltins, req);
176 static void wb_gettoken_gotbuiltins(struct tevent_req *subreq)
178 struct tevent_req *req = tevent_req_callback_data(
179 subreq, struct tevent_req);
180 struct wb_gettoken_state *state = tevent_req_data(
181 req, struct wb_gettoken_state);
186 status = wb_lookupuseraliases_recv(subreq, state, &num_rids, &rids);
188 if (tevent_req_nterror(req, status)) {
191 if (!wb_add_rids_to_sids(state, &state->num_sids, &state->sids,
192 &global_sid_Builtin, num_rids, rids)) {
193 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
196 tevent_req_done(req);
199 NTSTATUS wb_gettoken_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
200 int *num_sids, struct dom_sid **sids)
202 struct wb_gettoken_state *state = tevent_req_data(
203 req, struct wb_gettoken_state);
206 if (tevent_req_is_nterror(req, &status)) {
209 *num_sids = state->num_sids;
210 *sids = talloc_move(mem_ctx, &state->sids);
214 static bool wb_add_rids_to_sids(TALLOC_CTX *mem_ctx,
215 int *pnum_sids, struct dom_sid **psids,
216 const struct dom_sid *domain_sid,
217 int num_rids, uint32_t *rids)
219 struct dom_sid *sids;
222 sids = talloc_realloc(mem_ctx, *psids, struct dom_sid,
223 *pnum_sids + num_rids);
227 for (i=0; i<num_rids; i++) {
228 sid_compose(&sids[i+*pnum_sids], domain_sid, rids[i]);
231 *pnum_sids += num_rids;