s3-docs: Move -D option to the right paragraph in man winbindd.
[Samba.git] / nsswitch / libwbclient / wbc_pwd.c
blob897bf1f5c345b01102017ba157092fb892e9d8fe
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"
28 /** @brief The maximum number of pwent structs to get from winbindd
31 #define MAX_GETPWENT_USERS 500
33 /** @brief The maximum number of grent structs to get from winbindd
36 #define MAX_GETGRENT_GROUPS 500
38 /**
40 **/
42 static struct passwd *copy_passwd_entry(struct winbindd_pw *p)
44 struct passwd *pwd = NULL;
45 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
47 pwd = talloc(NULL, struct passwd);
48 BAIL_ON_PTR_ERROR(pwd, wbc_status);
50 pwd->pw_name = talloc_strdup(pwd,p->pw_name);
51 BAIL_ON_PTR_ERROR(pwd->pw_name, wbc_status);
53 pwd->pw_passwd = talloc_strdup(pwd, p->pw_passwd);
54 BAIL_ON_PTR_ERROR(pwd->pw_passwd, wbc_status);
56 pwd->pw_gecos = talloc_strdup(pwd, p->pw_gecos);
57 BAIL_ON_PTR_ERROR(pwd->pw_gecos, wbc_status);
59 pwd->pw_shell = talloc_strdup(pwd, p->pw_shell);
60 BAIL_ON_PTR_ERROR(pwd->pw_shell, wbc_status);
62 pwd->pw_dir = talloc_strdup(pwd, p->pw_dir);
63 BAIL_ON_PTR_ERROR(pwd->pw_dir, wbc_status);
65 pwd->pw_uid = p->pw_uid;
66 pwd->pw_gid = p->pw_gid;
68 done:
69 if (!WBC_ERROR_IS_OK(wbc_status)) {
70 talloc_free(pwd);
71 pwd = NULL;
74 return pwd;
77 /**
79 **/
81 static struct group *copy_group_entry(struct winbindd_gr *g,
82 char *mem_buf)
84 struct group *grp = NULL;
85 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
86 int i;
87 char *mem_p, *mem_q;
89 grp = talloc(NULL, struct group);
90 BAIL_ON_PTR_ERROR(grp, wbc_status);
92 grp->gr_name = talloc_strdup(grp, g->gr_name);
93 BAIL_ON_PTR_ERROR(grp->gr_name, wbc_status);
95 grp->gr_passwd = talloc_strdup(grp, g->gr_passwd);
96 BAIL_ON_PTR_ERROR(grp->gr_passwd, wbc_status);
98 grp->gr_gid = g->gr_gid;
100 grp->gr_mem = talloc_array(grp, char*, g->num_gr_mem+1);
102 mem_p = mem_q = mem_buf;
103 for (i=0; i<g->num_gr_mem && mem_p; i++) {
104 if ((mem_q = strchr(mem_p, ',')) != NULL) {
105 *mem_q = '\0';
108 grp->gr_mem[i] = talloc_strdup(grp, mem_p);
109 BAIL_ON_PTR_ERROR(grp->gr_mem[i], wbc_status);
111 if (mem_q == NULL) {
112 i += 1;
113 break;
115 mem_p = mem_q + 1;
117 grp->gr_mem[i] = NULL;
119 wbc_status = WBC_ERR_SUCCESS;
121 done:
122 if (!WBC_ERROR_IS_OK(wbc_status)) {
123 talloc_free(grp);
124 grp = NULL;
127 return grp;
130 /* Fill in a struct passwd* for a domain user based on username */
131 wbcErr wbcGetpwnam(const char *name, struct passwd **pwd)
133 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
134 struct winbindd_request request;
135 struct winbindd_response response;
137 if (!name || !pwd) {
138 wbc_status = WBC_ERR_INVALID_PARAM;
139 BAIL_ON_WBC_ERROR(wbc_status);
142 /* Initialize request */
144 ZERO_STRUCT(request);
145 ZERO_STRUCT(response);
147 /* dst is already null terminated from the memset above */
149 strncpy(request.data.username, name, sizeof(request.data.username)-1);
151 wbc_status = wbcRequestResponse(WINBINDD_GETPWNAM,
152 &request,
153 &response);
154 BAIL_ON_WBC_ERROR(wbc_status);
156 *pwd = copy_passwd_entry(&response.data.pw);
157 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
159 done:
160 return wbc_status;
163 /* Fill in a struct passwd* for a domain user based on uid */
164 wbcErr wbcGetpwuid(uid_t uid, struct passwd **pwd)
166 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
167 struct winbindd_request request;
168 struct winbindd_response response;
170 if (!pwd) {
171 wbc_status = WBC_ERR_INVALID_PARAM;
172 BAIL_ON_WBC_ERROR(wbc_status);
175 /* Initialize request */
177 ZERO_STRUCT(request);
178 ZERO_STRUCT(response);
180 request.data.uid = uid;
182 wbc_status = wbcRequestResponse(WINBINDD_GETPWUID,
183 &request,
184 &response);
185 BAIL_ON_WBC_ERROR(wbc_status);
187 *pwd = copy_passwd_entry(&response.data.pw);
188 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
190 done:
191 return wbc_status;
194 /* Fill in a struct passwd* for a domain user based on sid */
195 wbcErr wbcGetpwsid(struct wbcDomainSid *sid, struct passwd **pwd)
197 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
198 struct winbindd_request request;
199 struct winbindd_response response;
200 char * sid_string = NULL;
202 if (!pwd) {
203 wbc_status = WBC_ERR_INVALID_PARAM;
204 BAIL_ON_WBC_ERROR(wbc_status);
207 wbc_status = wbcSidToString(sid, &sid_string);
208 BAIL_ON_WBC_ERROR(wbc_status);
210 /* Initialize request */
212 ZERO_STRUCT(request);
213 ZERO_STRUCT(response);
215 strncpy(request.data.sid, sid_string, sizeof(request.data.sid));
217 wbc_status = wbcRequestResponse(WINBINDD_GETPWSID,
218 &request,
219 &response);
220 BAIL_ON_WBC_ERROR(wbc_status);
222 *pwd = copy_passwd_entry(&response.data.pw);
223 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
225 done:
226 if (sid_string) {
227 wbcFreeMemory(sid_string);
230 return wbc_status;
233 /* Fill in a struct passwd* for a domain user based on username */
234 wbcErr wbcGetgrnam(const char *name, struct group **grp)
236 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
237 struct winbindd_request request;
238 struct winbindd_response response;
240 /* Initialize request */
242 ZERO_STRUCT(request);
243 ZERO_STRUCT(response);
245 if (!name || !grp) {
246 wbc_status = WBC_ERR_INVALID_PARAM;
247 BAIL_ON_WBC_ERROR(wbc_status);
250 /* dst is already null terminated from the memset above */
252 strncpy(request.data.groupname, name, sizeof(request.data.groupname)-1);
254 wbc_status = wbcRequestResponse(WINBINDD_GETGRNAM,
255 &request,
256 &response);
257 BAIL_ON_WBC_ERROR(wbc_status);
259 *grp = copy_group_entry(&response.data.gr,
260 (char*)response.extra_data.data);
261 BAIL_ON_PTR_ERROR(*grp, wbc_status);
263 done:
264 if (response.extra_data.data)
265 free(response.extra_data.data);
267 return wbc_status;
270 /* Fill in a struct passwd* for a domain user based on uid */
271 wbcErr wbcGetgrgid(gid_t gid, struct group **grp)
273 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
274 struct winbindd_request request;
275 struct winbindd_response response;
277 /* Initialize request */
279 ZERO_STRUCT(request);
280 ZERO_STRUCT(response);
282 if (!grp) {
283 wbc_status = WBC_ERR_INVALID_PARAM;
284 BAIL_ON_WBC_ERROR(wbc_status);
287 request.data.gid = gid;
289 wbc_status = wbcRequestResponse(WINBINDD_GETGRGID,
290 &request,
291 &response);
292 BAIL_ON_WBC_ERROR(wbc_status);
294 *grp = copy_group_entry(&response.data.gr,
295 (char*)response.extra_data.data);
296 BAIL_ON_PTR_ERROR(*grp, wbc_status);
298 done:
299 if (response.extra_data.data)
300 free(response.extra_data.data);
302 return wbc_status;
305 /** @brief Number of cached passwd structs
308 static uint32_t pw_cache_size;
310 /** @brief Position of the pwent context
313 static uint32_t pw_cache_idx;
315 /** @brief Winbindd response containing the passwd structs
318 static struct winbindd_response pw_response;
320 /* Reset the passwd iterator */
321 wbcErr wbcSetpwent(void)
323 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
325 if (pw_cache_size > 0) {
326 pw_cache_idx = pw_cache_size = 0;
327 if (pw_response.extra_data.data) {
328 free(pw_response.extra_data.data);
332 ZERO_STRUCT(pw_response);
334 wbc_status = wbcRequestResponse(WINBINDD_SETPWENT,
335 NULL, NULL);
336 BAIL_ON_WBC_ERROR(wbc_status);
338 done:
339 return wbc_status;
342 /* Close the passwd iterator */
343 wbcErr wbcEndpwent(void)
345 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
347 if (pw_cache_size > 0) {
348 pw_cache_idx = pw_cache_size = 0;
349 if (pw_response.extra_data.data) {
350 free(pw_response.extra_data.data);
354 wbc_status = wbcRequestResponse(WINBINDD_ENDPWENT,
355 NULL, NULL);
356 BAIL_ON_WBC_ERROR(wbc_status);
358 done:
359 return wbc_status;
362 /* Return the next struct passwd* entry from the pwent iterator */
363 wbcErr wbcGetpwent(struct passwd **pwd)
365 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
366 struct winbindd_request request;
367 struct winbindd_pw *wb_pw;
369 /* If there's a cached result, return that. */
370 if (pw_cache_idx < pw_cache_size) {
371 goto return_result;
374 /* Otherwise, query winbindd for some entries. */
376 pw_cache_idx = 0;
378 if (pw_response.extra_data.data) {
379 free(pw_response.extra_data.data);
380 ZERO_STRUCT(pw_response);
383 ZERO_STRUCT(request);
384 request.data.num_entries = MAX_GETPWENT_USERS;
386 wbc_status = wbcRequestResponse(WINBINDD_GETPWENT, &request,
387 &pw_response);
389 BAIL_ON_WBC_ERROR(wbc_status);
391 pw_cache_size = pw_response.data.num_entries;
393 return_result:
395 wb_pw = (struct winbindd_pw *) pw_response.extra_data.data;
397 *pwd = copy_passwd_entry(&wb_pw[pw_cache_idx]);
399 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
401 pw_cache_idx++;
403 done:
404 return wbc_status;
407 /** @brief Number of cached group structs
410 static uint32_t gr_cache_size;
412 /** @brief Position of the grent context
415 static uint32_t gr_cache_idx;
417 /** @brief Winbindd response containing the group structs
420 static struct winbindd_response gr_response;
422 /* Reset the group iterator */
423 wbcErr wbcSetgrent(void)
425 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
427 if (gr_cache_size > 0) {
428 gr_cache_idx = gr_cache_size = 0;
429 if (gr_response.extra_data.data) {
430 free(gr_response.extra_data.data);
434 ZERO_STRUCT(gr_response);
436 wbc_status = wbcRequestResponse(WINBINDD_SETGRENT,
437 NULL, NULL);
438 BAIL_ON_WBC_ERROR(wbc_status);
440 done:
441 return wbc_status;
444 /* Close the group iterator */
445 wbcErr wbcEndgrent(void)
447 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
449 if (gr_cache_size > 0) {
450 gr_cache_idx = gr_cache_size = 0;
451 if (gr_response.extra_data.data) {
452 free(gr_response.extra_data.data);
456 wbc_status = wbcRequestResponse(WINBINDD_ENDGRENT,
457 NULL, NULL);
458 BAIL_ON_WBC_ERROR(wbc_status);
460 done:
461 return wbc_status;
464 /* Return the next struct group* entry from the pwent iterator */
465 wbcErr wbcGetgrent(struct group **grp)
467 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
468 struct winbindd_request request;
469 struct winbindd_gr *wb_gr;
470 uint32_t mem_ofs;
472 /* If there's a cached result, return that. */
473 if (gr_cache_idx < gr_cache_size) {
474 goto return_result;
477 /* Otherwise, query winbindd for some entries. */
479 gr_cache_idx = 0;
481 if (gr_response.extra_data.data) {
482 free(gr_response.extra_data.data);
483 ZERO_STRUCT(gr_response);
486 ZERO_STRUCT(request);
487 request.data.num_entries = MAX_GETGRENT_GROUPS;
489 wbc_status = wbcRequestResponse(WINBINDD_GETGRENT, &request,
490 &gr_response);
492 BAIL_ON_WBC_ERROR(wbc_status);
494 gr_cache_size = gr_response.data.num_entries;
496 return_result:
498 wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
500 mem_ofs = wb_gr[gr_cache_idx].gr_mem_ofs +
501 gr_cache_size * sizeof(struct winbindd_gr);
503 *grp = copy_group_entry(&wb_gr[gr_cache_idx],
504 ((char *)gr_response.extra_data.data)+mem_ofs);
506 BAIL_ON_PTR_ERROR(*grp, wbc_status);
508 gr_cache_idx++;
510 done:
511 return wbc_status;
514 /* Return the next struct group* entry from the pwent iterator */
515 wbcErr wbcGetgrlist(struct group **grp)
517 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
518 struct winbindd_request request;
519 struct winbindd_gr *wb_gr;
521 /* If there's a cached result, return that. */
522 if (gr_cache_idx < gr_cache_size) {
523 goto return_result;
526 /* Otherwise, query winbindd for some entries. */
528 gr_cache_idx = 0;
530 if (gr_response.extra_data.data) {
531 free(gr_response.extra_data.data);
532 ZERO_STRUCT(gr_response);
535 ZERO_STRUCT(request);
536 request.data.num_entries = MAX_GETGRENT_GROUPS;
538 wbc_status = wbcRequestResponse(WINBINDD_GETGRLST, &request,
539 &gr_response);
541 BAIL_ON_WBC_ERROR(wbc_status);
543 gr_cache_size = gr_response.data.num_entries;
545 return_result:
547 wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
549 *grp = copy_group_entry(&wb_gr[gr_cache_idx], NULL);
551 BAIL_ON_PTR_ERROR(*grp, wbc_status);
553 gr_cache_idx++;
555 done:
556 return wbc_status;
559 /* Return the unix group array belonging to the given user */
560 wbcErr wbcGetGroups(const char *account,
561 uint32_t *num_groups,
562 gid_t **_groups)
564 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
565 struct winbindd_request request;
566 struct winbindd_response response;
567 uint32_t i;
568 gid_t *groups = NULL;
570 /* Initialize request */
572 ZERO_STRUCT(request);
573 ZERO_STRUCT(response);
575 if (!account) {
576 wbc_status = WBC_ERR_INVALID_PARAM;
577 BAIL_ON_WBC_ERROR(wbc_status);
580 /* Send request */
582 strncpy(request.data.username, account, sizeof(request.data.username)-1);
584 wbc_status = wbcRequestResponse(WINBINDD_GETGROUPS,
585 &request,
586 &response);
587 BAIL_ON_WBC_ERROR(wbc_status);
589 groups = talloc_array(NULL, gid_t, response.data.num_entries);
590 BAIL_ON_PTR_ERROR(groups, wbc_status);
592 for (i = 0; i < response.data.num_entries; i++) {
593 groups[i] = ((gid_t *)response.extra_data.data)[i];
596 *num_groups = response.data.num_entries;
597 *_groups = groups;
598 groups = NULL;
600 wbc_status = WBC_ERR_SUCCESS;
602 done:
603 if (response.extra_data.data) {
604 free(response.extra_data.data);
606 if (groups) {
607 talloc_free(groups);
610 return wbc_status;