s3:idmap_tdb2: remove unused idmap_tdb2_alloc_close().
[amitay/samba.git] / source3 / winbindd / wb_gettoken.c
1 /*
2    Unix SMB/CIFS implementation.
3    async gettoken
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
24 struct wb_gettoken_state {
25         struct tevent_context *ev;
26         struct dom_sid usersid;
27         int num_sids;
28         struct dom_sid *sids;
29 };
30
31 static bool wb_add_rids_to_sids(TALLOC_CTX *mem_ctx,
32                                 int *pnum_sids, struct dom_sid **psids,
33                                 const struct dom_sid *domain_sid,
34                                 int num_rids, uint32_t *rids);
35
36 static void wb_gettoken_gotgroups(struct tevent_req *subreq);
37 static void wb_gettoken_gotlocalgroups(struct tevent_req *subreq);
38 static void wb_gettoken_gotbuiltins(struct tevent_req *subreq);
39
40 struct tevent_req *wb_gettoken_send(TALLOC_CTX *mem_ctx,
41                                     struct tevent_context *ev,
42                                     const struct dom_sid *sid)
43 {
44         struct tevent_req *req, *subreq;
45         struct wb_gettoken_state *state;
46         struct winbindd_domain *domain;
47
48         req = tevent_req_create(mem_ctx, &state, struct wb_gettoken_state);
49         if (req == NULL) {
50                 return NULL;
51         }
52         sid_copy(&state->usersid, sid);
53         state->ev = ev;
54
55         domain = find_domain_from_sid_noinit(sid);
56         if (domain == NULL) {
57                 DEBUG(5, ("Could not find domain from SID %s\n",
58                           sid_string_dbg(sid)));
59                 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
60                 return tevent_req_post(req, ev);
61         }
62
63         if (lp_winbind_trusted_domains_only() && domain->primary) {
64                 DEBUG(7, ("wb_gettoken: My domain -- rejecting getgroups() "
65                           "for %s.\n", sid_string_tos(sid)));
66                 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
67                 return tevent_req_post(req, ev);
68         }
69
70         subreq = wb_lookupusergroups_send(state, ev, domain, &state->usersid);
71         if (tevent_req_nomem(subreq, req)) {
72                 return tevent_req_post(req, ev);
73         }
74         tevent_req_set_callback(subreq, wb_gettoken_gotgroups, req);
75         return req;
76 }
77
78 static void wb_gettoken_gotgroups(struct tevent_req *subreq)
79 {
80         struct tevent_req *req = tevent_req_callback_data(
81                 subreq, struct tevent_req);
82         struct wb_gettoken_state *state = tevent_req_data(
83                 req, struct wb_gettoken_state);
84         struct dom_sid *sids;
85         struct winbindd_domain *domain;
86         NTSTATUS status;
87
88         status = wb_lookupusergroups_recv(subreq, state, &state->num_sids,
89                                           &state->sids);
90         TALLOC_FREE(subreq);
91         if (!NT_STATUS_IS_OK(status)) {
92                 tevent_req_nterror(req, status);
93                 return;
94         }
95
96         sids = talloc_realloc(state, state->sids, struct dom_sid,
97                               state->num_sids + 1);
98         if (tevent_req_nomem(sids, req)) {
99                 return;
100         }
101         memmove(&sids[1], &sids[0], state->num_sids * sizeof(sids[0]));
102         sid_copy(&sids[0], &state->usersid);
103         state->num_sids += 1;
104         state->sids = sids;
105
106         /*
107          * Expand our domain's aliases
108          */
109         domain = find_our_domain();
110         if (domain == NULL) {
111                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
112                 return;
113         }
114
115         subreq = wb_lookupuseraliases_send(state, state->ev, domain,
116                                            state->num_sids, state->sids);
117         if (tevent_req_nomem(subreq, req)) {
118                 return;
119         }
120         tevent_req_set_callback(subreq, wb_gettoken_gotlocalgroups, req);
121 }
122
123 static void wb_gettoken_gotlocalgroups(struct tevent_req *subreq)
124 {
125         struct tevent_req *req = tevent_req_callback_data(
126                 subreq, struct tevent_req);
127         struct wb_gettoken_state *state = tevent_req_data(
128                 req, struct wb_gettoken_state);
129         uint32_t num_rids;
130         uint32_t *rids;
131         struct winbindd_domain *domain;
132         NTSTATUS status;
133
134         status = wb_lookupuseraliases_recv(subreq, state, &num_rids, &rids);
135         TALLOC_FREE(subreq);
136         if (!NT_STATUS_IS_OK(status)) {
137                 tevent_req_nterror(req, status);
138                 return;
139         }
140         domain = find_our_domain();
141         if (!wb_add_rids_to_sids(state, &state->num_sids, &state->sids,
142                                  &domain->sid, num_rids, rids)) {
143                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
144                 return;
145         }
146         TALLOC_FREE(rids);
147
148         /*
149          * Now expand the builtin groups
150          */
151
152         domain = find_builtin_domain();
153         if (domain == NULL) {
154                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
155                 return;
156         }
157
158         subreq = wb_lookupuseraliases_send(state, state->ev, domain,
159                                            state->num_sids, state->sids);
160         if (tevent_req_nomem(subreq, req)) {
161                 return;
162         }
163         tevent_req_set_callback(subreq, wb_gettoken_gotbuiltins, req);
164 }
165
166 static void wb_gettoken_gotbuiltins(struct tevent_req *subreq)
167 {
168         struct tevent_req *req = tevent_req_callback_data(
169                 subreq, struct tevent_req);
170         struct wb_gettoken_state *state = tevent_req_data(
171                 req, struct wb_gettoken_state);
172         uint32_t num_rids;
173         uint32_t *rids;
174         NTSTATUS status;
175
176         status = wb_lookupuseraliases_recv(subreq, state, &num_rids, &rids);
177         TALLOC_FREE(subreq);
178         if (!NT_STATUS_IS_OK(status)) {
179                 tevent_req_nterror(req, status);
180                 return;
181         }
182         if (!wb_add_rids_to_sids(state, &state->num_sids, &state->sids,
183                                  &global_sid_Builtin, num_rids, rids)) {
184                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
185                 return;
186         }
187         tevent_req_done(req);
188 }
189
190 NTSTATUS wb_gettoken_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
191                           int *num_sids, struct dom_sid **sids)
192 {
193         struct wb_gettoken_state *state = tevent_req_data(
194                 req, struct wb_gettoken_state);
195         NTSTATUS status;
196
197         if (tevent_req_is_nterror(req, &status)) {
198                 return status;
199         }
200         *num_sids = state->num_sids;
201         *sids = talloc_move(mem_ctx, &state->sids);
202         return NT_STATUS_OK;
203 }
204
205 static bool wb_add_rids_to_sids(TALLOC_CTX *mem_ctx,
206                                 int *pnum_sids, struct dom_sid **psids,
207                                 const struct dom_sid *domain_sid,
208                                 int num_rids, uint32_t *rids)
209 {
210         struct dom_sid *sids;
211         int i;
212
213         sids = talloc_realloc(mem_ctx, *psids, struct dom_sid,
214                               *pnum_sids + num_rids);
215         if (sids == NULL) {
216                 return false;
217         }
218         for (i=0; i<num_rids; i++) {
219                 sid_compose(&sids[i+*pnum_sids], domain_sid, rids[i]);
220         }
221
222         *pnum_sids += num_rids;
223         *psids = sids;
224         return true;
225 }