s3-waf: fix linking of swat by adding cap as dependency
[Samba/gebeck_regimport.git] / nsswitch / libwbclient / wbc_pwd.c
blobc7bfdb8fd88305e8a76f967b1838f85461d78591
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind client API
6 Copyright (C) Gerald (Jerry) Carter 2007
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 3 of the License, or (at your option) any later version.
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 /* Required Headers */
25 #include "replace.h"
26 #include "libwbclient.h"
27 #include "../winbind_client.h"
29 /** @brief The maximum number of pwent structs to get from winbindd
32 #define MAX_GETPWENT_USERS 500
34 /** @brief The maximum number of grent structs to get from winbindd
37 #define MAX_GETGRENT_GROUPS 500
39 /**
41 **/
43 static void wbcPasswdDestructor(void *ptr)
45 struct passwd *pw = (struct passwd *)ptr;
46 free(pw->pw_name);
47 free(pw->pw_passwd);
48 free(pw->pw_gecos);
49 free(pw->pw_shell);
50 free(pw->pw_dir);
53 static struct passwd *copy_passwd_entry(struct winbindd_pw *p)
55 struct passwd *pw = NULL;
57 pw = (struct passwd *)wbcAllocateMemory(1, sizeof(struct passwd),
58 wbcPasswdDestructor);
59 if (pw == NULL) {
60 return NULL;
62 pw->pw_name = strdup(p->pw_name);
63 if (pw->pw_name == NULL) {
64 goto fail;
66 pw->pw_passwd = strdup(p->pw_passwd);
67 if (pw->pw_passwd == NULL) {
68 goto fail;
70 pw->pw_gecos = strdup(p->pw_gecos);
71 if (pw->pw_gecos == NULL) {
72 goto fail;
74 pw->pw_shell = strdup(p->pw_shell);
75 if (pw->pw_shell == NULL) {
76 goto fail;
78 pw->pw_dir = strdup(p->pw_dir);
79 if (pw->pw_dir == NULL) {
80 goto fail;
82 pw->pw_uid = p->pw_uid;
83 pw->pw_gid = p->pw_gid;
84 return pw;
86 fail:
87 wbcFreeMemory(pw);
88 return NULL;
91 /**
93 **/
95 static void wbcGroupDestructor(void *ptr)
97 struct group *gr = (struct group *)ptr;
98 int i;
100 free(gr->gr_name);
101 free(gr->gr_passwd);
103 for (i=0; gr->gr_mem[i] != NULL; i++) {
104 free(gr->gr_mem[i]);
106 free(gr->gr_mem);
109 static struct group *copy_group_entry(struct winbindd_gr *g,
110 char *mem_buf)
112 struct group *gr = NULL;
113 int i;
114 char *mem_p, *mem_q;
116 gr = (struct group *)wbcAllocateMemory(
117 1, sizeof(struct group), wbcGroupDestructor);
118 if (gr == NULL) {
119 return NULL;
122 gr->gr_name = strdup(g->gr_name);
123 if (gr->gr_name == NULL) {
124 goto fail;
126 gr->gr_passwd = strdup(g->gr_passwd);
127 if (gr->gr_passwd == NULL) {
128 goto fail;
130 gr->gr_gid = g->gr_gid;
132 gr->gr_mem = (char **)calloc(g->num_gr_mem+1, sizeof(char *));
133 if (gr->gr_mem == NULL) {
134 goto fail;
137 mem_p = mem_q = mem_buf;
138 for (i=0; i<g->num_gr_mem && mem_p; i++) {
139 mem_q = strchr(mem_p, ',');
140 if (mem_q != NULL) {
141 *mem_q = '\0';
144 gr->gr_mem[i] = strdup(mem_p);
145 if (gr->gr_mem[i] == NULL) {
146 goto fail;
149 if (mem_q == NULL) {
150 i += 1;
151 break;
153 mem_p = mem_q + 1;
155 gr->gr_mem[i] = NULL;
157 return gr;
159 fail:
160 wbcFreeMemory(gr);
161 return NULL;
164 /* Fill in a struct passwd* for a domain user based on username */
165 wbcErr wbcGetpwnam(const char *name, struct passwd **pwd)
167 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
168 struct winbindd_request request;
169 struct winbindd_response response;
171 if (!name || !pwd) {
172 wbc_status = WBC_ERR_INVALID_PARAM;
173 BAIL_ON_WBC_ERROR(wbc_status);
176 /* Initialize request */
178 ZERO_STRUCT(request);
179 ZERO_STRUCT(response);
181 /* dst is already null terminated from the memset above */
183 strncpy(request.data.username, name, sizeof(request.data.username)-1);
185 wbc_status = wbcRequestResponse(WINBINDD_GETPWNAM,
186 &request,
187 &response);
188 BAIL_ON_WBC_ERROR(wbc_status);
190 *pwd = copy_passwd_entry(&response.data.pw);
191 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
193 done:
194 return wbc_status;
197 /* Fill in a struct passwd* for a domain user based on uid */
198 wbcErr wbcGetpwuid(uid_t uid, struct passwd **pwd)
200 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
201 struct winbindd_request request;
202 struct winbindd_response response;
204 if (!pwd) {
205 wbc_status = WBC_ERR_INVALID_PARAM;
206 BAIL_ON_WBC_ERROR(wbc_status);
209 /* Initialize request */
211 ZERO_STRUCT(request);
212 ZERO_STRUCT(response);
214 request.data.uid = uid;
216 wbc_status = wbcRequestResponse(WINBINDD_GETPWUID,
217 &request,
218 &response);
219 BAIL_ON_WBC_ERROR(wbc_status);
221 *pwd = copy_passwd_entry(&response.data.pw);
222 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
224 done:
225 return wbc_status;
228 /* Fill in a struct passwd* for a domain user based on sid */
229 wbcErr wbcGetpwsid(struct wbcDomainSid *sid, struct passwd **pwd)
231 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
232 struct winbindd_request request;
233 struct winbindd_response response;
234 char * sid_string = NULL;
236 if (!pwd) {
237 wbc_status = WBC_ERR_INVALID_PARAM;
238 BAIL_ON_WBC_ERROR(wbc_status);
241 wbc_status = wbcSidToString(sid, &sid_string);
242 BAIL_ON_WBC_ERROR(wbc_status);
244 /* Initialize request */
246 ZERO_STRUCT(request);
247 ZERO_STRUCT(response);
249 strncpy(request.data.sid, sid_string, sizeof(request.data.sid));
251 wbc_status = wbcRequestResponse(WINBINDD_GETPWSID,
252 &request,
253 &response);
254 BAIL_ON_WBC_ERROR(wbc_status);
256 *pwd = copy_passwd_entry(&response.data.pw);
257 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
259 done:
260 wbcFreeMemory(sid_string);
261 return wbc_status;
264 /* Fill in a struct passwd* for a domain user based on username */
265 wbcErr wbcGetgrnam(const char *name, struct group **grp)
267 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
268 struct winbindd_request request;
269 struct winbindd_response response;
271 /* Initialize request */
273 ZERO_STRUCT(request);
274 ZERO_STRUCT(response);
276 if (!name || !grp) {
277 wbc_status = WBC_ERR_INVALID_PARAM;
278 BAIL_ON_WBC_ERROR(wbc_status);
281 /* dst is already null terminated from the memset above */
283 strncpy(request.data.groupname, name, sizeof(request.data.groupname)-1);
285 wbc_status = wbcRequestResponse(WINBINDD_GETGRNAM,
286 &request,
287 &response);
288 BAIL_ON_WBC_ERROR(wbc_status);
290 *grp = copy_group_entry(&response.data.gr,
291 (char*)response.extra_data.data);
292 BAIL_ON_PTR_ERROR(*grp, wbc_status);
294 done:
295 winbindd_free_response(&response);
297 return wbc_status;
300 /* Fill in a struct passwd* for a domain user based on uid */
301 wbcErr wbcGetgrgid(gid_t gid, struct group **grp)
303 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
304 struct winbindd_request request;
305 struct winbindd_response response;
307 /* Initialize request */
309 ZERO_STRUCT(request);
310 ZERO_STRUCT(response);
312 if (!grp) {
313 wbc_status = WBC_ERR_INVALID_PARAM;
314 BAIL_ON_WBC_ERROR(wbc_status);
317 request.data.gid = gid;
319 wbc_status = wbcRequestResponse(WINBINDD_GETGRGID,
320 &request,
321 &response);
322 BAIL_ON_WBC_ERROR(wbc_status);
324 *grp = copy_group_entry(&response.data.gr,
325 (char*)response.extra_data.data);
326 BAIL_ON_PTR_ERROR(*grp, wbc_status);
328 done:
329 winbindd_free_response(&response);
331 return wbc_status;
334 /** @brief Number of cached passwd structs
337 static uint32_t pw_cache_size;
339 /** @brief Position of the pwent context
342 static uint32_t pw_cache_idx;
344 /** @brief Winbindd response containing the passwd structs
347 static struct winbindd_response pw_response;
349 /* Reset the passwd iterator */
350 wbcErr wbcSetpwent(void)
352 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
354 if (pw_cache_size > 0) {
355 pw_cache_idx = pw_cache_size = 0;
356 winbindd_free_response(&pw_response);
359 ZERO_STRUCT(pw_response);
361 wbc_status = wbcRequestResponse(WINBINDD_SETPWENT,
362 NULL, NULL);
363 BAIL_ON_WBC_ERROR(wbc_status);
365 done:
366 return wbc_status;
369 /* Close the passwd iterator */
370 wbcErr wbcEndpwent(void)
372 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
374 if (pw_cache_size > 0) {
375 pw_cache_idx = pw_cache_size = 0;
376 winbindd_free_response(&pw_response);
379 wbc_status = wbcRequestResponse(WINBINDD_ENDPWENT,
380 NULL, NULL);
381 BAIL_ON_WBC_ERROR(wbc_status);
383 done:
384 return wbc_status;
387 /* Return the next struct passwd* entry from the pwent iterator */
388 wbcErr wbcGetpwent(struct passwd **pwd)
390 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
391 struct winbindd_request request;
392 struct winbindd_pw *wb_pw;
394 /* If there's a cached result, return that. */
395 if (pw_cache_idx < pw_cache_size) {
396 goto return_result;
399 /* Otherwise, query winbindd for some entries. */
401 pw_cache_idx = 0;
403 winbindd_free_response(&pw_response);
405 ZERO_STRUCT(request);
406 request.data.num_entries = MAX_GETPWENT_USERS;
408 wbc_status = wbcRequestResponse(WINBINDD_GETPWENT, &request,
409 &pw_response);
411 BAIL_ON_WBC_ERROR(wbc_status);
413 pw_cache_size = pw_response.data.num_entries;
415 return_result:
417 wb_pw = (struct winbindd_pw *) pw_response.extra_data.data;
419 *pwd = copy_passwd_entry(&wb_pw[pw_cache_idx]);
421 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
423 pw_cache_idx++;
425 done:
426 return wbc_status;
429 /** @brief Number of cached group structs
432 static uint32_t gr_cache_size;
434 /** @brief Position of the grent context
437 static uint32_t gr_cache_idx;
439 /** @brief Winbindd response containing the group structs
442 static struct winbindd_response gr_response;
444 /* Reset the group iterator */
445 wbcErr wbcSetgrent(void)
447 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
449 if (gr_cache_size > 0) {
450 gr_cache_idx = gr_cache_size = 0;
451 winbindd_free_response(&gr_response);
454 ZERO_STRUCT(gr_response);
456 wbc_status = wbcRequestResponse(WINBINDD_SETGRENT,
457 NULL, NULL);
458 BAIL_ON_WBC_ERROR(wbc_status);
460 done:
461 return wbc_status;
464 /* Close the group iterator */
465 wbcErr wbcEndgrent(void)
467 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
469 if (gr_cache_size > 0) {
470 gr_cache_idx = gr_cache_size = 0;
471 winbindd_free_response(&gr_response);
474 wbc_status = wbcRequestResponse(WINBINDD_ENDGRENT,
475 NULL, NULL);
476 BAIL_ON_WBC_ERROR(wbc_status);
478 done:
479 return wbc_status;
482 /* Return the next struct group* entry from the pwent iterator */
483 wbcErr wbcGetgrent(struct group **grp)
485 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
486 struct winbindd_request request;
487 struct winbindd_gr *wb_gr;
488 uint32_t mem_ofs;
490 /* If there's a cached result, return that. */
491 if (gr_cache_idx < gr_cache_size) {
492 goto return_result;
495 /* Otherwise, query winbindd for some entries. */
497 gr_cache_idx = 0;
499 winbindd_free_response(&gr_response);
501 ZERO_STRUCT(request);
502 request.data.num_entries = MAX_GETGRENT_GROUPS;
504 wbc_status = wbcRequestResponse(WINBINDD_GETGRENT, &request,
505 &gr_response);
507 BAIL_ON_WBC_ERROR(wbc_status);
509 gr_cache_size = gr_response.data.num_entries;
511 return_result:
513 wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
515 mem_ofs = wb_gr[gr_cache_idx].gr_mem_ofs +
516 gr_cache_size * sizeof(struct winbindd_gr);
518 *grp = copy_group_entry(&wb_gr[gr_cache_idx],
519 ((char *)gr_response.extra_data.data)+mem_ofs);
521 BAIL_ON_PTR_ERROR(*grp, wbc_status);
523 gr_cache_idx++;
525 done:
526 return wbc_status;
529 /* Return the next struct group* entry from the pwent iterator */
530 wbcErr wbcGetgrlist(struct group **grp)
532 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
533 struct winbindd_request request;
534 struct winbindd_gr *wb_gr;
536 /* If there's a cached result, return that. */
537 if (gr_cache_idx < gr_cache_size) {
538 goto return_result;
541 /* Otherwise, query winbindd for some entries. */
543 gr_cache_idx = 0;
545 winbindd_free_response(&gr_response);
546 ZERO_STRUCT(gr_response);
548 ZERO_STRUCT(request);
549 request.data.num_entries = MAX_GETGRENT_GROUPS;
551 wbc_status = wbcRequestResponse(WINBINDD_GETGRLST, &request,
552 &gr_response);
554 BAIL_ON_WBC_ERROR(wbc_status);
556 gr_cache_size = gr_response.data.num_entries;
558 return_result:
560 wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
562 *grp = copy_group_entry(&wb_gr[gr_cache_idx], NULL);
564 BAIL_ON_PTR_ERROR(*grp, wbc_status);
566 gr_cache_idx++;
568 done:
569 return wbc_status;
572 /* Return the unix group array belonging to the given user */
573 wbcErr wbcGetGroups(const char *account,
574 uint32_t *num_groups,
575 gid_t **_groups)
577 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
578 struct winbindd_request request;
579 struct winbindd_response response;
580 uint32_t i;
581 gid_t *groups = NULL;
583 /* Initialize request */
585 ZERO_STRUCT(request);
586 ZERO_STRUCT(response);
588 if (!account) {
589 wbc_status = WBC_ERR_INVALID_PARAM;
590 BAIL_ON_WBC_ERROR(wbc_status);
593 /* Send request */
595 strncpy(request.data.username, account, sizeof(request.data.username)-1);
597 wbc_status = wbcRequestResponse(WINBINDD_GETGROUPS,
598 &request,
599 &response);
600 BAIL_ON_WBC_ERROR(wbc_status);
602 groups = (gid_t *)wbcAllocateMemory(
603 sizeof(gid_t), response.data.num_entries, NULL);
604 BAIL_ON_PTR_ERROR(groups, wbc_status);
606 for (i = 0; i < response.data.num_entries; i++) {
607 groups[i] = ((gid_t *)response.extra_data.data)[i];
610 *num_groups = response.data.num_entries;
611 *_groups = groups;
612 groups = NULL;
614 wbc_status = WBC_ERR_SUCCESS;
616 done:
617 winbindd_free_response(&response);
618 wbcFreeMemory(groups);
619 return wbc_status;