s3-docs: Fix make manpages3.
[Samba/gebeck_regimport.git] / nsswitch / libwbclient / wbc_pwd.c
blobbae6bf91ead5b88d5f7399cd49a996ead4e22c27
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 struct passwd *copy_passwd_entry(struct winbindd_pw *p)
45 struct passwd *pwd = NULL;
46 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
48 pwd = talloc(NULL, struct passwd);
49 BAIL_ON_PTR_ERROR(pwd, wbc_status);
51 pwd->pw_name = talloc_strdup(pwd,p->pw_name);
52 BAIL_ON_PTR_ERROR(pwd->pw_name, wbc_status);
54 pwd->pw_passwd = talloc_strdup(pwd, p->pw_passwd);
55 BAIL_ON_PTR_ERROR(pwd->pw_passwd, wbc_status);
57 pwd->pw_gecos = talloc_strdup(pwd, p->pw_gecos);
58 BAIL_ON_PTR_ERROR(pwd->pw_gecos, wbc_status);
60 pwd->pw_shell = talloc_strdup(pwd, p->pw_shell);
61 BAIL_ON_PTR_ERROR(pwd->pw_shell, wbc_status);
63 pwd->pw_dir = talloc_strdup(pwd, p->pw_dir);
64 BAIL_ON_PTR_ERROR(pwd->pw_dir, wbc_status);
66 pwd->pw_uid = p->pw_uid;
67 pwd->pw_gid = p->pw_gid;
69 done:
70 if (!WBC_ERROR_IS_OK(wbc_status)) {
71 talloc_free(pwd);
72 pwd = NULL;
75 return pwd;
78 /**
80 **/
82 static struct group *copy_group_entry(struct winbindd_gr *g,
83 char *mem_buf)
85 struct group *grp = NULL;
86 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
87 int i;
88 char *mem_p, *mem_q;
90 grp = talloc(NULL, struct group);
91 BAIL_ON_PTR_ERROR(grp, wbc_status);
93 grp->gr_name = talloc_strdup(grp, g->gr_name);
94 BAIL_ON_PTR_ERROR(grp->gr_name, wbc_status);
96 grp->gr_passwd = talloc_strdup(grp, g->gr_passwd);
97 BAIL_ON_PTR_ERROR(grp->gr_passwd, wbc_status);
99 grp->gr_gid = g->gr_gid;
101 grp->gr_mem = talloc_array(grp, char*, g->num_gr_mem+1);
103 mem_p = mem_q = mem_buf;
104 for (i=0; i<g->num_gr_mem && mem_p; i++) {
105 if ((mem_q = strchr(mem_p, ',')) != NULL) {
106 *mem_q = '\0';
109 grp->gr_mem[i] = talloc_strdup(grp, mem_p);
110 BAIL_ON_PTR_ERROR(grp->gr_mem[i], wbc_status);
112 if (mem_q == NULL) {
113 i += 1;
114 break;
116 mem_p = mem_q + 1;
118 grp->gr_mem[i] = NULL;
120 wbc_status = WBC_ERR_SUCCESS;
122 done:
123 if (!WBC_ERROR_IS_OK(wbc_status)) {
124 talloc_free(grp);
125 grp = NULL;
128 return grp;
131 /* Fill in a struct passwd* for a domain user based on username */
132 wbcErr wbcGetpwnam(const char *name, struct passwd **pwd)
134 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
135 struct winbindd_request request;
136 struct winbindd_response response;
138 if (!name || !pwd) {
139 wbc_status = WBC_ERR_INVALID_PARAM;
140 BAIL_ON_WBC_ERROR(wbc_status);
143 /* Initialize request */
145 ZERO_STRUCT(request);
146 ZERO_STRUCT(response);
148 /* dst is already null terminated from the memset above */
150 strncpy(request.data.username, name, sizeof(request.data.username)-1);
152 wbc_status = wbcRequestResponse(WINBINDD_GETPWNAM,
153 &request,
154 &response);
155 BAIL_ON_WBC_ERROR(wbc_status);
157 *pwd = copy_passwd_entry(&response.data.pw);
158 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
160 done:
161 return wbc_status;
164 /* Fill in a struct passwd* for a domain user based on uid */
165 wbcErr wbcGetpwuid(uid_t uid, struct passwd **pwd)
167 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
168 struct winbindd_request request;
169 struct winbindd_response response;
171 if (!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 request.data.uid = uid;
183 wbc_status = wbcRequestResponse(WINBINDD_GETPWUID,
184 &request,
185 &response);
186 BAIL_ON_WBC_ERROR(wbc_status);
188 *pwd = copy_passwd_entry(&response.data.pw);
189 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
191 done:
192 return wbc_status;
195 /* Fill in a struct passwd* for a domain user based on sid */
196 wbcErr wbcGetpwsid(struct wbcDomainSid *sid, struct passwd **pwd)
198 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
199 struct winbindd_request request;
200 struct winbindd_response response;
201 char * sid_string = NULL;
203 if (!pwd) {
204 wbc_status = WBC_ERR_INVALID_PARAM;
205 BAIL_ON_WBC_ERROR(wbc_status);
208 wbc_status = wbcSidToString(sid, &sid_string);
209 BAIL_ON_WBC_ERROR(wbc_status);
211 /* Initialize request */
213 ZERO_STRUCT(request);
214 ZERO_STRUCT(response);
216 strncpy(request.data.sid, sid_string, sizeof(request.data.sid));
218 wbc_status = wbcRequestResponse(WINBINDD_GETPWSID,
219 &request,
220 &response);
221 BAIL_ON_WBC_ERROR(wbc_status);
223 *pwd = copy_passwd_entry(&response.data.pw);
224 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
226 done:
227 if (sid_string) {
228 wbcFreeMemory(sid_string);
231 return wbc_status;
234 /* Fill in a struct passwd* for a domain user based on username */
235 wbcErr wbcGetgrnam(const char *name, struct group **grp)
237 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
238 struct winbindd_request request;
239 struct winbindd_response response;
241 /* Initialize request */
243 ZERO_STRUCT(request);
244 ZERO_STRUCT(response);
246 if (!name || !grp) {
247 wbc_status = WBC_ERR_INVALID_PARAM;
248 BAIL_ON_WBC_ERROR(wbc_status);
251 /* dst is already null terminated from the memset above */
253 strncpy(request.data.groupname, name, sizeof(request.data.groupname)-1);
255 wbc_status = wbcRequestResponse(WINBINDD_GETGRNAM,
256 &request,
257 &response);
258 BAIL_ON_WBC_ERROR(wbc_status);
260 *grp = copy_group_entry(&response.data.gr,
261 (char*)response.extra_data.data);
262 BAIL_ON_PTR_ERROR(*grp, wbc_status);
264 done:
265 winbindd_free_response(&response);
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 winbindd_free_response(&response);
301 return wbc_status;
304 /** @brief Number of cached passwd structs
307 static uint32_t pw_cache_size;
309 /** @brief Position of the pwent context
312 static uint32_t pw_cache_idx;
314 /** @brief Winbindd response containing the passwd structs
317 static struct winbindd_response pw_response;
319 /* Reset the passwd iterator */
320 wbcErr wbcSetpwent(void)
322 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
324 if (pw_cache_size > 0) {
325 pw_cache_idx = pw_cache_size = 0;
326 winbindd_free_response(&pw_response);
329 ZERO_STRUCT(pw_response);
331 wbc_status = wbcRequestResponse(WINBINDD_SETPWENT,
332 NULL, NULL);
333 BAIL_ON_WBC_ERROR(wbc_status);
335 done:
336 return wbc_status;
339 /* Close the passwd iterator */
340 wbcErr wbcEndpwent(void)
342 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
344 if (pw_cache_size > 0) {
345 pw_cache_idx = pw_cache_size = 0;
346 winbindd_free_response(&pw_response);
349 wbc_status = wbcRequestResponse(WINBINDD_ENDPWENT,
350 NULL, NULL);
351 BAIL_ON_WBC_ERROR(wbc_status);
353 done:
354 return wbc_status;
357 /* Return the next struct passwd* entry from the pwent iterator */
358 wbcErr wbcGetpwent(struct passwd **pwd)
360 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
361 struct winbindd_request request;
362 struct winbindd_pw *wb_pw;
364 /* If there's a cached result, return that. */
365 if (pw_cache_idx < pw_cache_size) {
366 goto return_result;
369 /* Otherwise, query winbindd for some entries. */
371 pw_cache_idx = 0;
373 winbindd_free_response(&pw_response);
375 ZERO_STRUCT(request);
376 request.data.num_entries = MAX_GETPWENT_USERS;
378 wbc_status = wbcRequestResponse(WINBINDD_GETPWENT, &request,
379 &pw_response);
381 BAIL_ON_WBC_ERROR(wbc_status);
383 pw_cache_size = pw_response.data.num_entries;
385 return_result:
387 wb_pw = (struct winbindd_pw *) pw_response.extra_data.data;
389 *pwd = copy_passwd_entry(&wb_pw[pw_cache_idx]);
391 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
393 pw_cache_idx++;
395 done:
396 return wbc_status;
399 /** @brief Number of cached group structs
402 static uint32_t gr_cache_size;
404 /** @brief Position of the grent context
407 static uint32_t gr_cache_idx;
409 /** @brief Winbindd response containing the group structs
412 static struct winbindd_response gr_response;
414 /* Reset the group iterator */
415 wbcErr wbcSetgrent(void)
417 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
419 if (gr_cache_size > 0) {
420 gr_cache_idx = gr_cache_size = 0;
421 winbindd_free_response(&gr_response);
424 ZERO_STRUCT(gr_response);
426 wbc_status = wbcRequestResponse(WINBINDD_SETGRENT,
427 NULL, NULL);
428 BAIL_ON_WBC_ERROR(wbc_status);
430 done:
431 return wbc_status;
434 /* Close the group iterator */
435 wbcErr wbcEndgrent(void)
437 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
439 if (gr_cache_size > 0) {
440 gr_cache_idx = gr_cache_size = 0;
441 winbindd_free_response(&gr_response);
444 wbc_status = wbcRequestResponse(WINBINDD_ENDGRENT,
445 NULL, NULL);
446 BAIL_ON_WBC_ERROR(wbc_status);
448 done:
449 return wbc_status;
452 /* Return the next struct group* entry from the pwent iterator */
453 wbcErr wbcGetgrent(struct group **grp)
455 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
456 struct winbindd_request request;
457 struct winbindd_gr *wb_gr;
458 uint32_t mem_ofs;
460 /* If there's a cached result, return that. */
461 if (gr_cache_idx < gr_cache_size) {
462 goto return_result;
465 /* Otherwise, query winbindd for some entries. */
467 gr_cache_idx = 0;
469 winbindd_free_response(&gr_response);
471 ZERO_STRUCT(request);
472 request.data.num_entries = MAX_GETGRENT_GROUPS;
474 wbc_status = wbcRequestResponse(WINBINDD_GETGRENT, &request,
475 &gr_response);
477 BAIL_ON_WBC_ERROR(wbc_status);
479 gr_cache_size = gr_response.data.num_entries;
481 return_result:
483 wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
485 mem_ofs = wb_gr[gr_cache_idx].gr_mem_ofs +
486 gr_cache_size * sizeof(struct winbindd_gr);
488 *grp = copy_group_entry(&wb_gr[gr_cache_idx],
489 ((char *)gr_response.extra_data.data)+mem_ofs);
491 BAIL_ON_PTR_ERROR(*grp, wbc_status);
493 gr_cache_idx++;
495 done:
496 return wbc_status;
499 /* Return the next struct group* entry from the pwent iterator */
500 wbcErr wbcGetgrlist(struct group **grp)
502 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
503 struct winbindd_request request;
504 struct winbindd_gr *wb_gr;
506 /* If there's a cached result, return that. */
507 if (gr_cache_idx < gr_cache_size) {
508 goto return_result;
511 /* Otherwise, query winbindd for some entries. */
513 gr_cache_idx = 0;
515 winbindd_free_response(&gr_response);
516 ZERO_STRUCT(gr_response);
518 ZERO_STRUCT(request);
519 request.data.num_entries = MAX_GETGRENT_GROUPS;
521 wbc_status = wbcRequestResponse(WINBINDD_GETGRLST, &request,
522 &gr_response);
524 BAIL_ON_WBC_ERROR(wbc_status);
526 gr_cache_size = gr_response.data.num_entries;
528 return_result:
530 wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
532 *grp = copy_group_entry(&wb_gr[gr_cache_idx], NULL);
534 BAIL_ON_PTR_ERROR(*grp, wbc_status);
536 gr_cache_idx++;
538 done:
539 return wbc_status;
542 /* Return the unix group array belonging to the given user */
543 wbcErr wbcGetGroups(const char *account,
544 uint32_t *num_groups,
545 gid_t **_groups)
547 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
548 struct winbindd_request request;
549 struct winbindd_response response;
550 uint32_t i;
551 gid_t *groups = NULL;
553 /* Initialize request */
555 ZERO_STRUCT(request);
556 ZERO_STRUCT(response);
558 if (!account) {
559 wbc_status = WBC_ERR_INVALID_PARAM;
560 BAIL_ON_WBC_ERROR(wbc_status);
563 /* Send request */
565 strncpy(request.data.username, account, sizeof(request.data.username)-1);
567 wbc_status = wbcRequestResponse(WINBINDD_GETGROUPS,
568 &request,
569 &response);
570 BAIL_ON_WBC_ERROR(wbc_status);
572 groups = talloc_array(NULL, gid_t, response.data.num_entries);
573 BAIL_ON_PTR_ERROR(groups, wbc_status);
575 for (i = 0; i < response.data.num_entries; i++) {
576 groups[i] = ((gid_t *)response.extra_data.data)[i];
579 *num_groups = response.data.num_entries;
580 *_groups = groups;
581 groups = NULL;
583 wbc_status = WBC_ERR_SUCCESS;
585 done:
586 winbindd_free_response(&response);
587 if (groups) {
588 talloc_free(groups);
591 return wbc_status;