libwbclient: Fix memleaks in tests
[ira/wip.git] / nsswitch / libwbclient / wbc_idmap_async.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Winbind client API
5
6    Copyright (C) 2009,2010 Kai Blin  <kai@samba.org>
7
8    This library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public
10    License as published by the Free Software Foundation; either
11    version 3 of the License, or (at your option) any later version.
12
13    This library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Library General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /* Required Headers */
23
24 #include "replace.h"
25 #include "libwbclient.h"
26 #include "wbc_async.h"
27
28 struct wbc_sid_to_uid_state {
29         struct winbindd_request req;
30         uid_t uid;
31 };
32
33 static void wbcSidToUid_done(struct tevent_req *subreq);
34
35 /**
36  * @brief Convert a Windows SID to a Unix uid, allocating an uid if needed
37  *
38  * @param mem_ctx       talloc context to allocate the request from
39  * @param ev            tevent context to use for async operation
40  * @param wb_ctx        winbind context to use
41  * @param *sid          pointer to the domain SID to be resolved
42  *
43  * @return tevent_req on success, NULL on error
44  */
45
46 struct tevent_req *wbcSidToUid_send(TALLOC_CTX *mem_ctx,
47                                     struct tevent_context *ev,
48                                     struct wb_context *wb_ctx,
49                                     const struct wbcDomainSid *sid)
50 {
51         struct tevent_req *req, *subreq;
52         struct wbc_sid_to_uid_state *state;
53         char *sid_string;
54         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
55
56         req = tevent_req_create(mem_ctx, &state, struct wbc_sid_to_uid_state);
57         if (req == NULL) {
58                 return NULL;
59         }
60
61         ZERO_STRUCT(state->req);
62
63         state->req.cmd = WINBINDD_SID_TO_UID;
64         wbc_status = wbcSidToString(sid, &sid_string);
65         if (!WBC_ERROR_IS_OK(wbc_status)) {
66                 return tevent_req_post(req, ev);
67         }
68         strncpy(state->req.data.sid, sid_string, sizeof(state->req.data.sid)-1);
69         wbcFreeMemory(sid_string);
70
71         subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
72         if (tevent_req_nomem(subreq, req)) {
73                 return tevent_req_post(req, ev);
74         }
75
76         tevent_req_set_callback(subreq, wbcSidToUid_done, req);
77         return req;
78 }
79
80 static void wbcSidToUid_done(struct tevent_req *subreq)
81 {
82         struct tevent_req *req = tevent_req_callback_data(
83                         subreq, struct tevent_req);
84         struct wbc_sid_to_uid_state *state = tevent_req_data(
85                         req, struct wbc_sid_to_uid_state);
86         struct winbindd_response *resp;
87         wbcErr wbc_status;
88
89         wbc_status = wb_trans_recv(subreq, state, &resp);
90         TALLOC_FREE(subreq);
91         if (!WBC_ERROR_IS_OK(wbc_status)) {
92                 tevent_req_error(req, wbc_status);
93                 return;
94         }
95         state->uid = resp->data.uid;
96         TALLOC_FREE(resp);
97
98         tevent_req_done(req);
99 }
100
101 /**
102  * @brief Receive a Unix uid mapped to a Windows SID
103  *
104  * @param req           tevent_req containing the request
105  * @param *puid         pointer to hold the resolved uid_t value
106  *
107  * @return #wbcErr
108  */
109
110 wbcErr wbcSidToUid_recv(struct tevent_req *req, uid_t *puid)
111 {
112         struct wbc_sid_to_uid_state *state = tevent_req_data(
113                         req, struct wbc_sid_to_uid_state);
114         wbcErr wbc_status;
115
116         if (tevent_req_is_wbcerr(req, &wbc_status)) {
117                 tevent_req_received(req);
118                 return wbc_status;
119         }
120
121         *puid = state->uid;
122
123         tevent_req_received(req);
124         return WBC_ERR_SUCCESS;
125 }
126
127
128 struct wbc_uid_to_sid_state {
129         struct winbindd_request req;
130         struct wbcDomainSid *sid;
131 };
132
133 static void wbcUidToSid_done(struct tevent_req *subreq);
134
135 /**
136  * @brief Request a Windows SID for an Unix uid, allocating an SID if needed
137  *
138  * @param mem_ctx       talloc context to allocate the request from
139  * @param ev            tevent context to use for async operation
140  * @param wb_ctx        winbind context to use
141  * @param uid           uid to be resolved to a SID
142  *
143  * @return tevent_req on success, NULL on error
144  */
145
146 struct tevent_req *wbcUidToSid_send(TALLOC_CTX *mem_ctx,
147                                     struct tevent_context *ev,
148                                     struct wb_context *wb_ctx,
149                                     uid_t uid)
150 {
151         struct tevent_req *req, *subreq;
152         struct wbc_uid_to_sid_state *state;
153
154         req = tevent_req_create(mem_ctx, &state, struct wbc_uid_to_sid_state);
155         if (req == NULL) {
156                 return NULL;
157         }
158
159         ZERO_STRUCT(state->req);
160
161         state->req.cmd = WINBINDD_UID_TO_SID;
162         state->req.data.uid = uid;
163
164         subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
165         if (tevent_req_nomem(subreq, req)) {
166                 return tevent_req_post(req, ev);
167         }
168
169         tevent_req_set_callback(subreq, wbcUidToSid_done, req);
170         return req;
171 }
172
173 static void wbcUidToSid_done(struct tevent_req *subreq)
174 {
175         struct tevent_req *req = tevent_req_callback_data(
176                         subreq, struct tevent_req);
177         struct wbc_uid_to_sid_state *state = tevent_req_data(
178                         req, struct wbc_uid_to_sid_state);
179         struct winbindd_response *resp;
180         wbcErr wbc_status;
181
182         wbc_status = wb_trans_recv(subreq, state, &resp);
183         TALLOC_FREE(subreq);
184         if (!WBC_ERROR_IS_OK(wbc_status)) {
185                 tevent_req_error(req, wbc_status);
186                 return;
187         }
188
189         state->sid = talloc(state, struct wbcDomainSid);
190         if (state->sid == NULL) {
191                 TALLOC_FREE(resp);
192                 tevent_req_error(req, WBC_ERR_NO_MEMORY);
193                 return;
194         }
195
196         wbc_status = wbcStringToSid(resp->data.sid.sid, state->sid);
197         TALLOC_FREE(resp);
198
199         if (!WBC_ERROR_IS_OK(wbc_status)) {
200                 tevent_req_error(req, wbc_status);
201                 return;
202         }
203
204         tevent_req_done(req);
205 }
206
207 /**
208  * @brief Receive a Unix uid mapped to a Windows SID
209  *
210  * @param req           tevent_req containing the request
211  * @param *psid         pointer to hold the resolved SID
212  *
213  * @return #wbcErr
214  */
215
216 wbcErr wbcUidToSid_recv(struct tevent_req *req, struct wbcDomainSid *psid)
217 {
218         struct wbc_uid_to_sid_state *state = tevent_req_data(
219                         req, struct wbc_uid_to_sid_state);
220         wbcErr wbc_status;
221
222         if (psid == NULL) {
223                 tevent_req_received(req);
224                 return WBC_ERR_INVALID_PARAM;
225         }
226
227         if (tevent_req_is_wbcerr(req, &wbc_status)) {
228                 tevent_req_received(req);
229                 return wbc_status;
230         }
231
232         memcpy(psid, state->sid, sizeof(struct wbcDomainSid));
233
234         tevent_req_received(req);
235         return WBC_ERR_SUCCESS;
236 }
237
238
239 struct wbc_sid_to_gid_state {
240         struct winbindd_request req;
241         gid_t gid;
242 };
243
244 static void wbcSidToGid_done(struct tevent_req *subreq);
245
246 /**
247  * @brief Request to convert a Windows SID to a Unix gid,
248  * allocating a gid if needed
249  *
250  * @param mem_ctx       talloc context to allocate the request from
251  * @param ev            tevent context to use for async operation
252  * @param wb_ctx        winbind context to use
253  * @param *sid          pointer to the domain SID to be resolved
254  *
255  * @return tevent_req on success, NULL on error
256  */
257
258 struct tevent_req *wbcSidToGid_send(TALLOC_CTX *mem_ctx,
259                                     struct tevent_context *ev,
260                                     struct wb_context *wb_ctx,
261                                     const struct wbcDomainSid *sid)
262 {
263         struct tevent_req *req, *subreq;
264         struct wbc_sid_to_gid_state *state;
265         char *sid_string;
266         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
267
268         req = tevent_req_create(mem_ctx, &state, struct wbc_sid_to_gid_state);
269         if (req == NULL) {
270                 return NULL;
271         }
272
273         ZERO_STRUCT(state->req);
274
275         state->req.cmd = WINBINDD_SID_TO_GID;
276         wbc_status = wbcSidToString(sid, &sid_string);
277         if (!WBC_ERROR_IS_OK(wbc_status)) {
278                 return tevent_req_post(req, ev);
279         }
280         strncpy(state->req.data.sid, sid_string, sizeof(state->req.data.sid)-1);
281         wbcFreeMemory(sid_string);
282
283         subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
284         if (tevent_req_nomem(subreq, req)) {
285                 return tevent_req_post(req, ev);
286         }
287
288         tevent_req_set_callback(subreq, wbcSidToGid_done, req);
289         return req;
290 }
291
292 static void wbcSidToGid_done(struct tevent_req *subreq)
293 {
294         struct tevent_req *req = tevent_req_callback_data(
295                         subreq, struct tevent_req);
296         struct wbc_sid_to_gid_state *state = tevent_req_data(
297                         req, struct wbc_sid_to_gid_state);
298         struct winbindd_response *resp;
299         wbcErr wbc_status;
300
301         wbc_status = wb_trans_recv(subreq, state, &resp);
302         TALLOC_FREE(subreq);
303         if (!WBC_ERROR_IS_OK(wbc_status)) {
304                 tevent_req_error(req, wbc_status);
305                 return;
306         }
307         state->gid = resp->data.gid;
308         TALLOC_FREE(resp);
309
310         tevent_req_done(req);
311 }
312
313 /**
314  * @brief Receive a Unix gid mapped to a Windows SID
315  *
316  * @param req           tevent_req containing the request
317  * @param *pgid         pointer to hold the resolved gid_t value
318  *
319  * @return #wbcErr
320  */
321
322 wbcErr wbcSidToGid_recv(struct tevent_req *req, gid_t *pgid)
323 {
324         struct wbc_sid_to_gid_state *state = tevent_req_data(
325                         req, struct wbc_sid_to_gid_state);
326         wbcErr wbc_status;
327
328         if (tevent_req_is_wbcerr(req, &wbc_status)) {
329                 tevent_req_received(req);
330                 return wbc_status;
331         }
332
333         *pgid = state->gid;
334
335         tevent_req_received(req);
336         return WBC_ERR_SUCCESS;
337 }
338
339
340 struct wbc_gid_to_sid_state {
341         struct winbindd_request req;
342         struct wbcDomainSid *sid;
343 };
344
345 static void wbcGidToSid_done(struct tevent_req *subreq);
346
347 /**
348  * @brief Request a Windows SID for an Unix Gid, allocating an SID if needed
349  *
350  * @param mem_ctx       talloc context to allocate the request from
351  * @param ev            tevent context to use for async operation
352  * @param wb_ctx        winbind context to use
353  * @param gid           gid to be resolved to a SID
354  *
355  * @return tevent_req on success, NULL on error
356  */
357
358 struct tevent_req *wbcGidToSid_send(TALLOC_CTX *mem_ctx,
359                                     struct tevent_context *ev,
360                                     struct wb_context *wb_ctx,
361                                     gid_t gid)
362 {
363         struct tevent_req *req, *subreq;
364         struct wbc_gid_to_sid_state *state;
365
366         req = tevent_req_create(mem_ctx, &state, struct wbc_gid_to_sid_state);
367         if (req == NULL) {
368                 return NULL;
369         }
370
371         ZERO_STRUCT(state->req);
372
373         state->req.cmd = WINBINDD_GID_TO_SID;
374         state->req.data.gid = gid;
375
376         subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
377         if (tevent_req_nomem(subreq, req)) {
378                 return tevent_req_post(req, ev);
379         }
380
381         tevent_req_set_callback(subreq, wbcGidToSid_done, req);
382         return req;
383 }
384
385 static void wbcGidToSid_done(struct tevent_req *subreq)
386 {
387         struct tevent_req *req = tevent_req_callback_data(
388                         subreq, struct tevent_req);
389         struct wbc_gid_to_sid_state *state = tevent_req_data(
390                         req, struct wbc_gid_to_sid_state);
391         struct winbindd_response *resp;
392         wbcErr wbc_status;
393
394         wbc_status = wb_trans_recv(subreq, state, &resp);
395         TALLOC_FREE(subreq);
396         if (!WBC_ERROR_IS_OK(wbc_status)) {
397                 tevent_req_error(req, wbc_status);
398                 return;
399         }
400
401         state->sid = talloc(state, struct wbcDomainSid);
402         if (state->sid == NULL) {
403                 TALLOC_FREE(resp);
404                 tevent_req_error(req, WBC_ERR_NO_MEMORY);
405                 return;
406         }
407
408         wbc_status = wbcStringToSid(resp->data.sid.sid, state->sid);
409         TALLOC_FREE(resp);
410
411         if (!WBC_ERROR_IS_OK(wbc_status)) {
412                 tevent_req_error(req, wbc_status);
413                 return;
414         }
415
416         tevent_req_done(req);
417 }
418
419 /**
420  * @brief Receive a Unix gid mapped to a Windows SID
421  *
422  * @param req           tevent_req containing the request
423  * @param *psid         pointer to hold the resolved SID
424  *
425  * @return #wbcErr
426  */
427
428 wbcErr wbcGidToSid_recv(struct tevent_req *req, struct wbcDomainSid *psid)
429 {
430         struct wbc_gid_to_sid_state *state = tevent_req_data(
431                         req, struct wbc_gid_to_sid_state);
432         wbcErr wbc_status;
433
434         if (psid == NULL) {
435                 tevent_req_received(req);
436                 return WBC_ERR_INVALID_PARAM;
437         }
438
439         if (tevent_req_is_wbcerr(req, &wbc_status)) {
440                 tevent_req_received(req);
441                 return wbc_status;
442         }
443
444         memcpy(psid, state->sid, sizeof(struct wbcDomainSid));
445
446         tevent_req_received(req);
447         return WBC_ERR_SUCCESS;
448 }