tsocket: fill in sa.sa_len if the system supports it
[Samba/gebeck_regimport.git] / nsswitch / libwbclient / wbc_pwd.c
blob1527808d888d98eb581ccdee5a8eafccb9455e75
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 /* if the array was partly created this can be NULL */
104 if (gr->gr_mem == NULL) {
105 return;
108 for (i=0; gr->gr_mem[i] != NULL; i++) {
109 free(gr->gr_mem[i]);
111 free(gr->gr_mem);
114 static struct group *copy_group_entry(struct winbindd_gr *g,
115 char *mem_buf)
117 struct group *gr = NULL;
118 int i;
119 char *mem_p, *mem_q;
121 gr = (struct group *)wbcAllocateMemory(
122 1, sizeof(struct group), wbcGroupDestructor);
123 if (gr == NULL) {
124 return NULL;
127 gr->gr_name = strdup(g->gr_name);
128 if (gr->gr_name == NULL) {
129 goto fail;
131 gr->gr_passwd = strdup(g->gr_passwd);
132 if (gr->gr_passwd == NULL) {
133 goto fail;
135 gr->gr_gid = g->gr_gid;
137 gr->gr_mem = (char **)calloc(g->num_gr_mem+1, sizeof(char *));
138 if (gr->gr_mem == NULL) {
139 goto fail;
142 mem_p = mem_q = mem_buf;
143 for (i=0; i<g->num_gr_mem && mem_p; i++) {
144 mem_q = strchr(mem_p, ',');
145 if (mem_q != NULL) {
146 *mem_q = '\0';
149 gr->gr_mem[i] = strdup(mem_p);
150 if (gr->gr_mem[i] == NULL) {
151 goto fail;
154 if (mem_q == NULL) {
155 i += 1;
156 break;
158 mem_p = mem_q + 1;
160 gr->gr_mem[i] = NULL;
162 return gr;
164 fail:
165 wbcFreeMemory(gr);
166 return NULL;
169 /* Fill in a struct passwd* for a domain user based on username */
170 wbcErr wbcGetpwnam(const char *name, struct passwd **pwd)
172 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
173 struct winbindd_request request;
174 struct winbindd_response response;
176 if (!name || !pwd) {
177 wbc_status = WBC_ERR_INVALID_PARAM;
178 BAIL_ON_WBC_ERROR(wbc_status);
181 /* Initialize request */
183 ZERO_STRUCT(request);
184 ZERO_STRUCT(response);
186 /* dst is already null terminated from the memset above */
188 strncpy(request.data.username, name, sizeof(request.data.username)-1);
190 wbc_status = wbcRequestResponse(WINBINDD_GETPWNAM,
191 &request,
192 &response);
193 BAIL_ON_WBC_ERROR(wbc_status);
195 *pwd = copy_passwd_entry(&response.data.pw);
196 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
198 done:
199 return wbc_status;
202 /* Fill in a struct passwd* for a domain user based on uid */
203 wbcErr wbcGetpwuid(uid_t uid, struct passwd **pwd)
205 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
206 struct winbindd_request request;
207 struct winbindd_response response;
209 if (!pwd) {
210 wbc_status = WBC_ERR_INVALID_PARAM;
211 BAIL_ON_WBC_ERROR(wbc_status);
214 /* Initialize request */
216 ZERO_STRUCT(request);
217 ZERO_STRUCT(response);
219 request.data.uid = uid;
221 wbc_status = wbcRequestResponse(WINBINDD_GETPWUID,
222 &request,
223 &response);
224 BAIL_ON_WBC_ERROR(wbc_status);
226 *pwd = copy_passwd_entry(&response.data.pw);
227 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
229 done:
230 return wbc_status;
233 /* Fill in a struct passwd* for a domain user based on sid */
234 wbcErr wbcGetpwsid(struct wbcDomainSid *sid, struct passwd **pwd)
236 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
237 struct winbindd_request request;
238 struct winbindd_response response;
239 char * sid_string = NULL;
241 if (!pwd) {
242 wbc_status = WBC_ERR_INVALID_PARAM;
243 BAIL_ON_WBC_ERROR(wbc_status);
246 wbc_status = wbcSidToString(sid, &sid_string);
247 BAIL_ON_WBC_ERROR(wbc_status);
249 /* Initialize request */
251 ZERO_STRUCT(request);
252 ZERO_STRUCT(response);
254 strncpy(request.data.sid, sid_string, sizeof(request.data.sid));
256 wbc_status = wbcRequestResponse(WINBINDD_GETPWSID,
257 &request,
258 &response);
259 BAIL_ON_WBC_ERROR(wbc_status);
261 *pwd = copy_passwd_entry(&response.data.pw);
262 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
264 done:
265 wbcFreeMemory(sid_string);
266 return wbc_status;
269 /* Fill in a struct passwd* for a domain user based on username */
270 wbcErr wbcGetgrnam(const char *name, struct group **grp)
272 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
273 struct winbindd_request request;
274 struct winbindd_response response;
276 /* Initialize request */
278 ZERO_STRUCT(request);
279 ZERO_STRUCT(response);
281 if (!name || !grp) {
282 wbc_status = WBC_ERR_INVALID_PARAM;
283 BAIL_ON_WBC_ERROR(wbc_status);
286 /* dst is already null terminated from the memset above */
288 strncpy(request.data.groupname, name, sizeof(request.data.groupname)-1);
290 wbc_status = wbcRequestResponse(WINBINDD_GETGRNAM,
291 &request,
292 &response);
293 BAIL_ON_WBC_ERROR(wbc_status);
295 *grp = copy_group_entry(&response.data.gr,
296 (char*)response.extra_data.data);
297 BAIL_ON_PTR_ERROR(*grp, wbc_status);
299 done:
300 winbindd_free_response(&response);
302 return wbc_status;
305 /* Fill in a struct passwd* for a domain user based on uid */
306 wbcErr wbcGetgrgid(gid_t gid, struct group **grp)
308 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
309 struct winbindd_request request;
310 struct winbindd_response response;
312 /* Initialize request */
314 ZERO_STRUCT(request);
315 ZERO_STRUCT(response);
317 if (!grp) {
318 wbc_status = WBC_ERR_INVALID_PARAM;
319 BAIL_ON_WBC_ERROR(wbc_status);
322 request.data.gid = gid;
324 wbc_status = wbcRequestResponse(WINBINDD_GETGRGID,
325 &request,
326 &response);
327 BAIL_ON_WBC_ERROR(wbc_status);
329 *grp = copy_group_entry(&response.data.gr,
330 (char*)response.extra_data.data);
331 BAIL_ON_PTR_ERROR(*grp, wbc_status);
333 done:
334 winbindd_free_response(&response);
336 return wbc_status;
339 /** @brief Number of cached passwd structs
342 static uint32_t pw_cache_size;
344 /** @brief Position of the pwent context
347 static uint32_t pw_cache_idx;
349 /** @brief Winbindd response containing the passwd structs
352 static struct winbindd_response pw_response;
354 /* Reset the passwd iterator */
355 wbcErr wbcSetpwent(void)
357 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
359 if (pw_cache_size > 0) {
360 pw_cache_idx = pw_cache_size = 0;
361 winbindd_free_response(&pw_response);
364 ZERO_STRUCT(pw_response);
366 wbc_status = wbcRequestResponse(WINBINDD_SETPWENT,
367 NULL, NULL);
368 BAIL_ON_WBC_ERROR(wbc_status);
370 done:
371 return wbc_status;
374 /* Close the passwd iterator */
375 wbcErr wbcEndpwent(void)
377 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
379 if (pw_cache_size > 0) {
380 pw_cache_idx = pw_cache_size = 0;
381 winbindd_free_response(&pw_response);
384 wbc_status = wbcRequestResponse(WINBINDD_ENDPWENT,
385 NULL, NULL);
386 BAIL_ON_WBC_ERROR(wbc_status);
388 done:
389 return wbc_status;
392 /* Return the next struct passwd* entry from the pwent iterator */
393 wbcErr wbcGetpwent(struct passwd **pwd)
395 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
396 struct winbindd_request request;
397 struct winbindd_pw *wb_pw;
399 /* If there's a cached result, return that. */
400 if (pw_cache_idx < pw_cache_size) {
401 goto return_result;
404 /* Otherwise, query winbindd for some entries. */
406 pw_cache_idx = 0;
408 winbindd_free_response(&pw_response);
410 ZERO_STRUCT(request);
411 request.data.num_entries = MAX_GETPWENT_USERS;
413 wbc_status = wbcRequestResponse(WINBINDD_GETPWENT, &request,
414 &pw_response);
416 BAIL_ON_WBC_ERROR(wbc_status);
418 pw_cache_size = pw_response.data.num_entries;
420 return_result:
422 wb_pw = (struct winbindd_pw *) pw_response.extra_data.data;
424 *pwd = copy_passwd_entry(&wb_pw[pw_cache_idx]);
426 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
428 pw_cache_idx++;
430 done:
431 return wbc_status;
434 /** @brief Number of cached group structs
437 static uint32_t gr_cache_size;
439 /** @brief Position of the grent context
442 static uint32_t gr_cache_idx;
444 /** @brief Winbindd response containing the group structs
447 static struct winbindd_response gr_response;
449 /* Reset the group iterator */
450 wbcErr wbcSetgrent(void)
452 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
454 if (gr_cache_size > 0) {
455 gr_cache_idx = gr_cache_size = 0;
456 winbindd_free_response(&gr_response);
459 ZERO_STRUCT(gr_response);
461 wbc_status = wbcRequestResponse(WINBINDD_SETGRENT,
462 NULL, NULL);
463 BAIL_ON_WBC_ERROR(wbc_status);
465 done:
466 return wbc_status;
469 /* Close the group iterator */
470 wbcErr wbcEndgrent(void)
472 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
474 if (gr_cache_size > 0) {
475 gr_cache_idx = gr_cache_size = 0;
476 winbindd_free_response(&gr_response);
479 wbc_status = wbcRequestResponse(WINBINDD_ENDGRENT,
480 NULL, NULL);
481 BAIL_ON_WBC_ERROR(wbc_status);
483 done:
484 return wbc_status;
487 /* Return the next struct group* entry from the pwent iterator */
488 wbcErr wbcGetgrent(struct group **grp)
490 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
491 struct winbindd_request request;
492 struct winbindd_gr *wb_gr;
493 uint32_t mem_ofs;
495 /* If there's a cached result, return that. */
496 if (gr_cache_idx < gr_cache_size) {
497 goto return_result;
500 /* Otherwise, query winbindd for some entries. */
502 gr_cache_idx = 0;
504 winbindd_free_response(&gr_response);
506 ZERO_STRUCT(request);
507 request.data.num_entries = MAX_GETGRENT_GROUPS;
509 wbc_status = wbcRequestResponse(WINBINDD_GETGRENT, &request,
510 &gr_response);
512 BAIL_ON_WBC_ERROR(wbc_status);
514 gr_cache_size = gr_response.data.num_entries;
516 return_result:
518 wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
520 mem_ofs = wb_gr[gr_cache_idx].gr_mem_ofs +
521 gr_cache_size * sizeof(struct winbindd_gr);
523 *grp = copy_group_entry(&wb_gr[gr_cache_idx],
524 ((char *)gr_response.extra_data.data)+mem_ofs);
526 BAIL_ON_PTR_ERROR(*grp, wbc_status);
528 gr_cache_idx++;
530 done:
531 return wbc_status;
534 /* Return the next struct group* entry from the pwent iterator */
535 wbcErr wbcGetgrlist(struct group **grp)
537 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
538 struct winbindd_request request;
539 struct winbindd_gr *wb_gr;
541 /* If there's a cached result, return that. */
542 if (gr_cache_idx < gr_cache_size) {
543 goto return_result;
546 /* Otherwise, query winbindd for some entries. */
548 gr_cache_idx = 0;
550 winbindd_free_response(&gr_response);
551 ZERO_STRUCT(gr_response);
553 ZERO_STRUCT(request);
554 request.data.num_entries = MAX_GETGRENT_GROUPS;
556 wbc_status = wbcRequestResponse(WINBINDD_GETGRLST, &request,
557 &gr_response);
559 BAIL_ON_WBC_ERROR(wbc_status);
561 gr_cache_size = gr_response.data.num_entries;
563 return_result:
565 wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
567 *grp = copy_group_entry(&wb_gr[gr_cache_idx], NULL);
569 BAIL_ON_PTR_ERROR(*grp, wbc_status);
571 gr_cache_idx++;
573 done:
574 return wbc_status;
577 /* Return the unix group array belonging to the given user */
578 wbcErr wbcGetGroups(const char *account,
579 uint32_t *num_groups,
580 gid_t **_groups)
582 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
583 struct winbindd_request request;
584 struct winbindd_response response;
585 uint32_t i;
586 gid_t *groups = NULL;
588 /* Initialize request */
590 ZERO_STRUCT(request);
591 ZERO_STRUCT(response);
593 if (!account) {
594 wbc_status = WBC_ERR_INVALID_PARAM;
595 BAIL_ON_WBC_ERROR(wbc_status);
598 /* Send request */
600 strncpy(request.data.username, account, sizeof(request.data.username)-1);
602 wbc_status = wbcRequestResponse(WINBINDD_GETGROUPS,
603 &request,
604 &response);
605 BAIL_ON_WBC_ERROR(wbc_status);
607 groups = (gid_t *)wbcAllocateMemory(
608 sizeof(gid_t), response.data.num_entries, NULL);
609 BAIL_ON_PTR_ERROR(groups, wbc_status);
611 for (i = 0; i < response.data.num_entries; i++) {
612 groups[i] = ((gid_t *)response.extra_data.data)[i];
615 *num_groups = response.data.num_entries;
616 *_groups = groups;
617 groups = NULL;
619 wbc_status = WBC_ERR_SUCCESS;
621 done:
622 winbindd_free_response(&response);
623 wbcFreeMemory(groups);
624 return wbc_status;