libwbclient: Implement wbcSidToUid_send/recv
[samba.git] / nsswitch / libwbclient / wbc_idmap.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Winbind client API
5
6    Copyright (C) Gerald (Jerry) Carter 2007
7    Copyright (C) Kai Blin 2009
8
9
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 3 of the License, or (at your option) any later version.
14
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Library General Public License for more details.
19
20    You should have received a copy of the GNU Lesser General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 /* Required Headers */
25
26 #include "replace.h"
27 #include "libwbclient.h"
28
29 struct wbc_sid_to_uid_state {
30         struct winbindd_request req;
31         uid_t uid;
32 };
33
34 static void wbcSidToUid_done(struct tevent_req *subreq);
35
36 /**
37  * @brief Convert a Windows SID to a Unix uid, allocating an uid if needed
38  *
39  * @param mem_ctx       talloc context to allocate the request from
40  * @param ev            tevent context to use for async operation
41  * @param wb_ctx        winbind context to use
42  * @param *sid          pointer to the domain SID to be resolved
43  *
44  * @return tevent_req on success, NULL on error
45  */
46
47 struct tevent_req *wbcSidToUid_send(TALLOC_CTX *mem_ctx,
48                                     struct tevent_context *ev,
49                                     struct wb_context *wb_ctx,
50                                     const struct wbcDomainSid *sid)
51 {
52         struct tevent_req *req, *subreq;
53         struct wbc_sid_to_uid_state *state;
54         char *sid_string;
55         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
56
57         req = tevent_req_create(mem_ctx, &state, struct wbc_sid_to_uid_state);
58         if (req == NULL) {
59                 return NULL;
60         }
61
62         ZERO_STRUCT(state->req);
63
64         state->req.cmd = WINBINDD_SID_TO_UID;
65         wbc_status = wbcSidToString(sid, &sid_string);
66         if (!WBC_ERROR_IS_OK(wbc_status)) {
67                 return tevent_req_post(req, ev);
68         }
69         strncpy(state->req.data.sid, sid_string, sizeof(state->req.data.sid)-1);
70         wbcFreeMemory(sid_string);
71
72         subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
73         if (tevent_req_nomem(subreq, req)) {
74                 return tevent_req_post(req, ev);
75         }
76
77         tevent_req_set_callback(subreq, wbcSidToUid_done, req);
78         return req;
79 }
80
81 static void wbcSidToUid_done(struct tevent_req *subreq)
82 {
83         struct tevent_req *req = tevent_req_callback_data(
84                         subreq, struct tevent_req);
85         struct wbc_sid_to_uid_state *state = tevent_req_data(
86                         req, struct wbc_sid_to_uid_state);
87         struct winbindd_response *resp;
88         wbcErr wbc_status;
89
90         wbc_status = wb_trans_recv(subreq, state, &resp);
91         TALLOC_FREE(subreq);
92         if (!WBC_ERROR_IS_OK(wbc_status)) {
93                 tevent_req_error(req, wbc_status);
94                 return;
95         }
96         state->uid = resp->data.uid;
97         TALLOC_FREE(resp);
98
99         tevent_req_done(req);
100 }
101
102 /**
103  * @brief Receive a Unix uid mapped to a Windows SID
104  *
105  * @param req           tevent_req containing the request
106  * @param *puid         pointer to hold the resolved uid_t value
107  *
108  * @return #wbcErr
109  */
110
111 wbcErr wbcSidToUid_recv(struct tevent_req *req, uid_t *puid)
112 {
113         struct wbc_sid_to_uid_state *state = tevent_req_data(
114                         req, struct wbc_sid_to_uid_state);
115         wbcErr wbc_status;
116
117         if (tevent_req_is_wbcerr(req, &wbc_status)) {
118                 tevent_req_received(req);
119                 return wbc_status;
120         }
121
122         *puid = state->uid;
123
124         tevent_req_received(req);
125         return WBC_ERR_SUCCESS;
126 }
127
128 /* Convert a Windows SID to a Unix uid, allocating an uid if needed */
129 wbcErr wbcSidToUid(const struct wbcDomainSid *sid, uid_t *puid)
130 {
131         struct winbindd_request request;
132         struct winbindd_response response;
133         char *sid_string = NULL;
134         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
135
136         if (!sid || !puid) {
137                 wbc_status = WBC_ERR_INVALID_PARAM;
138                 BAIL_ON_WBC_ERROR(wbc_status);
139         }
140
141         /* Initialize request */
142
143         ZERO_STRUCT(request);
144         ZERO_STRUCT(response);
145
146         wbc_status = wbcSidToString(sid, &sid_string);
147         BAIL_ON_WBC_ERROR(wbc_status);
148
149         strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
150         wbcFreeMemory(sid_string);
151
152         /* Make request */
153
154         wbc_status = wbcRequestResponse(WINBINDD_SID_TO_UID,
155                                         &request,
156                                         &response);
157         BAIL_ON_WBC_ERROR(wbc_status);
158
159         *puid = response.data.uid;
160
161         wbc_status = WBC_ERR_SUCCESS;
162
163  done:
164         return wbc_status;
165 }
166
167 /* Convert a Windows SID to a Unix uid if there already is a mapping */
168 wbcErr wbcQuerySidToUid(const struct wbcDomainSid *sid,
169                         uid_t *puid)
170 {
171         return WBC_ERR_NOT_IMPLEMENTED;
172 }
173
174 /* Convert a Unix uid to a Windows SID, allocating a SID if needed */
175 wbcErr wbcUidToSid(uid_t uid, struct wbcDomainSid *sid)
176 {
177         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
178         struct winbindd_request request;
179         struct winbindd_response response;
180
181         if (!sid) {
182                 wbc_status = WBC_ERR_INVALID_PARAM;
183                 BAIL_ON_WBC_ERROR(wbc_status);
184         }
185
186         /* Initialize request */
187
188         ZERO_STRUCT(request);
189         ZERO_STRUCT(response);
190
191         request.data.uid = uid;
192
193         /* Make request */
194
195         wbc_status = wbcRequestResponse(WINBINDD_UID_TO_SID,
196                                         &request,
197                                         &response);
198         BAIL_ON_WBC_ERROR(wbc_status);
199
200         wbc_status = wbcStringToSid(response.data.sid.sid, sid);
201         BAIL_ON_WBC_ERROR(wbc_status);
202
203 done:
204         return wbc_status;
205 }
206
207 /* Convert a Unix uid to a Windows SID if there already is a mapping */
208 wbcErr wbcQueryUidToSid(uid_t uid,
209                         struct wbcDomainSid *sid)
210 {
211         return WBC_ERR_NOT_IMPLEMENTED;
212 }
213
214 /** @brief Convert a Windows SID to a Unix gid, allocating a gid if needed
215  *
216  * @param *sid        Pointer to the domain SID to be resolved
217  * @param *pgid       Pointer to the resolved gid_t value
218  *
219  * @return #wbcErr
220  *
221  **/
222
223 wbcErr wbcSidToGid(const struct wbcDomainSid *sid, gid_t *pgid)
224 {
225         struct winbindd_request request;
226         struct winbindd_response response;
227         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
228         char *sid_string = NULL;
229
230         if (!sid || !pgid) {
231                 wbc_status = WBC_ERR_INVALID_PARAM;
232                 BAIL_ON_WBC_ERROR(wbc_status);
233         }
234
235         /* Initialize request */
236
237         ZERO_STRUCT(request);
238         ZERO_STRUCT(response);
239
240         wbc_status = wbcSidToString(sid, &sid_string);
241         BAIL_ON_WBC_ERROR(wbc_status);
242
243         strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
244         wbcFreeMemory(sid_string);
245
246         /* Make request */
247
248         wbc_status = wbcRequestResponse(WINBINDD_SID_TO_GID,
249                                         &request,
250                                         &response);
251         BAIL_ON_WBC_ERROR(wbc_status);
252
253         *pgid = response.data.gid;
254
255         wbc_status = WBC_ERR_SUCCESS;
256
257  done:
258         return wbc_status;
259 }
260
261 /* Convert a Windows SID to a Unix gid if there already is a mapping */
262
263 wbcErr wbcQuerySidToGid(const struct wbcDomainSid *sid,
264                         gid_t *pgid)
265 {
266         return WBC_ERR_NOT_IMPLEMENTED;
267 }
268
269 /* Convert a Unix gid to a Windows SID, allocating a SID if needed */
270 wbcErr wbcGidToSid(gid_t gid, struct wbcDomainSid *sid)
271 {
272         struct winbindd_request request;
273         struct winbindd_response response;
274         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
275
276         if (!sid) {
277                 wbc_status = WBC_ERR_INVALID_PARAM;
278                 BAIL_ON_WBC_ERROR(wbc_status);
279         }
280
281         /* Initialize request */
282
283         ZERO_STRUCT(request);
284         ZERO_STRUCT(response);
285
286         request.data.gid = gid;
287
288         /* Make request */
289
290         wbc_status = wbcRequestResponse(WINBINDD_GID_TO_SID,
291                                         &request,
292                                         &response);
293         BAIL_ON_WBC_ERROR(wbc_status);
294
295         wbc_status = wbcStringToSid(response.data.sid.sid, sid);
296         BAIL_ON_WBC_ERROR(wbc_status);
297
298 done:
299         return wbc_status;
300 }
301
302 /* Convert a Unix gid to a Windows SID if there already is a mapping */
303 wbcErr wbcQueryGidToSid(gid_t gid,
304                         struct wbcDomainSid *sid)
305 {
306         return WBC_ERR_NOT_IMPLEMENTED;
307 }
308
309 /* Obtain a new uid from Winbind */
310 wbcErr wbcAllocateUid(uid_t *puid)
311 {
312         struct winbindd_request request;
313         struct winbindd_response response;
314         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
315
316         if (!puid)
317                 return WBC_ERR_INVALID_PARAM;
318
319         /* Initialise request */
320
321         ZERO_STRUCT(request);
322         ZERO_STRUCT(response);
323
324         /* Make request */
325
326         wbc_status = wbcRequestResponse(WINBINDD_ALLOCATE_UID,
327                                            &request, &response);
328         BAIL_ON_WBC_ERROR(wbc_status);
329
330         /* Copy out result */
331         *puid = response.data.uid;
332
333         wbc_status = WBC_ERR_SUCCESS;
334
335  done:
336         return wbc_status;
337 }
338
339 /* Obtain a new gid from Winbind */
340 wbcErr wbcAllocateGid(gid_t *pgid)
341 {
342         struct winbindd_request request;
343         struct winbindd_response response;
344         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
345
346         if (!pgid)
347                 return WBC_ERR_INVALID_PARAM;
348
349         /* Initialise request */
350
351         ZERO_STRUCT(request);
352         ZERO_STRUCT(response);
353
354         /* Make request */
355
356         wbc_status = wbcRequestResponse(WINBINDD_ALLOCATE_GID,
357                                            &request, &response);
358         BAIL_ON_WBC_ERROR(wbc_status);
359
360         /* Copy out result */
361         *pgid = response.data.gid;
362
363         wbc_status = WBC_ERR_SUCCESS;
364
365  done:
366         return wbc_status;
367 }
368
369 /* we can't include smb.h here... */
370 #define _ID_TYPE_UID 1
371 #define _ID_TYPE_GID 2
372
373 /* Set an user id mapping */
374 wbcErr wbcSetUidMapping(uid_t uid, const struct wbcDomainSid *sid)
375 {
376         struct winbindd_request request;
377         struct winbindd_response response;
378         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
379         char *sid_string = NULL;
380
381         if (!sid) {
382                 return WBC_ERR_INVALID_PARAM;
383         }
384
385         /* Initialise request */
386
387         ZERO_STRUCT(request);
388         ZERO_STRUCT(response);
389
390         /* Make request */
391
392         request.data.dual_idmapset.id = uid;
393         request.data.dual_idmapset.type = _ID_TYPE_UID;
394
395         wbc_status = wbcSidToString(sid, &sid_string);
396         BAIL_ON_WBC_ERROR(wbc_status);
397
398         strncpy(request.data.dual_idmapset.sid, sid_string,
399                 sizeof(request.data.dual_idmapset.sid)-1);
400         wbcFreeMemory(sid_string);
401
402         wbc_status = wbcRequestResponse(WINBINDD_SET_MAPPING,
403                                         &request, &response);
404         BAIL_ON_WBC_ERROR(wbc_status);
405
406  done:
407         return wbc_status;
408 }
409
410 /* Set a group id mapping */
411 wbcErr wbcSetGidMapping(gid_t gid, const struct wbcDomainSid *sid)
412 {
413         struct winbindd_request request;
414         struct winbindd_response response;
415         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
416         char *sid_string = NULL;
417
418         if (!sid) {
419                 return WBC_ERR_INVALID_PARAM;
420         }
421
422         /* Initialise request */
423
424         ZERO_STRUCT(request);
425         ZERO_STRUCT(response);
426
427         /* Make request */
428
429         request.data.dual_idmapset.id = gid;
430         request.data.dual_idmapset.type = _ID_TYPE_GID;
431
432         wbc_status = wbcSidToString(sid, &sid_string);
433         BAIL_ON_WBC_ERROR(wbc_status);
434
435         strncpy(request.data.dual_idmapset.sid, sid_string,
436                 sizeof(request.data.dual_idmapset.sid)-1);
437         wbcFreeMemory(sid_string);
438
439         wbc_status = wbcRequestResponse(WINBINDD_SET_MAPPING,
440                                         &request, &response);
441         BAIL_ON_WBC_ERROR(wbc_status);
442
443  done:
444         return wbc_status;
445 }
446
447 /* Remove a user id mapping */
448 wbcErr wbcRemoveUidMapping(uid_t uid, const struct wbcDomainSid *sid)
449 {
450         struct winbindd_request request;
451         struct winbindd_response response;
452         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
453         char *sid_string = NULL;
454
455         if (!sid) {
456                 return WBC_ERR_INVALID_PARAM;
457         }
458
459         /* Initialise request */
460
461         ZERO_STRUCT(request);
462         ZERO_STRUCT(response);
463
464         /* Make request */
465
466         request.data.dual_idmapset.id = uid;
467         request.data.dual_idmapset.type = _ID_TYPE_UID;
468
469         wbc_status = wbcSidToString(sid, &sid_string);
470         BAIL_ON_WBC_ERROR(wbc_status);
471
472         strncpy(request.data.dual_idmapset.sid, sid_string,
473                 sizeof(request.data.dual_idmapset.sid)-1);
474         wbcFreeMemory(sid_string);
475
476         wbc_status = wbcRequestResponse(WINBINDD_REMOVE_MAPPING,
477                                         &request, &response);
478         BAIL_ON_WBC_ERROR(wbc_status);
479
480  done:
481         return wbc_status;
482 }
483
484 /* Remove a group id mapping */
485 wbcErr wbcRemoveGidMapping(gid_t gid, const struct wbcDomainSid *sid)
486 {
487         struct winbindd_request request;
488         struct winbindd_response response;
489         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
490         char *sid_string = NULL;
491
492         if (!sid) {
493                 return WBC_ERR_INVALID_PARAM;
494         }
495
496         /* Initialise request */
497
498         ZERO_STRUCT(request);
499         ZERO_STRUCT(response);
500
501         /* Make request */
502
503         request.data.dual_idmapset.id = gid;
504         request.data.dual_idmapset.type = _ID_TYPE_GID;
505
506         wbc_status = wbcSidToString(sid, &sid_string);
507         BAIL_ON_WBC_ERROR(wbc_status);
508
509         strncpy(request.data.dual_idmapset.sid, sid_string,
510                 sizeof(request.data.dual_idmapset.sid)-1);
511         wbcFreeMemory(sid_string);
512
513         wbc_status = wbcRequestResponse(WINBINDD_REMOVE_MAPPING,
514                                         &request, &response);
515         BAIL_ON_WBC_ERROR(wbc_status);
516
517  done:
518         return wbc_status;
519 }
520
521 /* Set the highwater mark for allocated uids. */
522 wbcErr wbcSetUidHwm(uid_t uid_hwm)
523 {
524         struct winbindd_request request;
525         struct winbindd_response response;
526         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
527
528         /* Initialise request */
529
530         ZERO_STRUCT(request);
531         ZERO_STRUCT(response);
532
533         /* Make request */
534
535         request.data.dual_idmapset.id = uid_hwm;
536         request.data.dual_idmapset.type = _ID_TYPE_UID;
537
538         wbc_status = wbcRequestResponse(WINBINDD_SET_HWM,
539                                         &request, &response);
540         BAIL_ON_WBC_ERROR(wbc_status);
541
542  done:
543         return wbc_status;
544 }
545
546 /* Set the highwater mark for allocated gids. */
547 wbcErr wbcSetGidHwm(gid_t gid_hwm)
548 {
549         struct winbindd_request request;
550         struct winbindd_response response;
551         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
552
553         /* Initialise request */
554
555         ZERO_STRUCT(request);
556         ZERO_STRUCT(response);
557
558         /* Make request */
559
560         request.data.dual_idmapset.id = gid_hwm;
561         request.data.dual_idmapset.type = _ID_TYPE_GID;
562
563         wbc_status = wbcRequestResponse(WINBINDD_SET_HWM,
564                                         &request, &response);
565         BAIL_ON_WBC_ERROR(wbc_status);
566
567  done:
568         return wbc_status;
569 }