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