nsswitch: Move source3 files to top level dir.
[Samba/ekacnet.git] / nsswitch / libwbclient / wbc_pwd.c
blobcd945996c89968414c576ef4a0f0b354ef2d2917
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 "libwbclient.h"
27 /** @brief The maximum number of pwent structs to get from winbindd
30 #define MAX_GETPWENT_USERS 500
32 /** @brief The maximum number of grent structs to get from winbindd
35 #define MAX_GETGRENT_GROUPS 500
37 /**
39 **/
41 static struct passwd *copy_passwd_entry(struct winbindd_pw *p)
43 struct passwd *pwd = NULL;
44 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
46 pwd = talloc(NULL, struct passwd);
47 BAIL_ON_PTR_ERROR(pwd, wbc_status);
49 pwd->pw_name = talloc_strdup(pwd,p->pw_name);
50 BAIL_ON_PTR_ERROR(pwd->pw_name, wbc_status);
52 pwd->pw_passwd = talloc_strdup(pwd, p->pw_passwd);
53 BAIL_ON_PTR_ERROR(pwd->pw_passwd, wbc_status);
55 pwd->pw_gecos = talloc_strdup(pwd, p->pw_gecos);
56 BAIL_ON_PTR_ERROR(pwd->pw_gecos, wbc_status);
58 pwd->pw_shell = talloc_strdup(pwd, p->pw_shell);
59 BAIL_ON_PTR_ERROR(pwd->pw_shell, wbc_status);
61 pwd->pw_dir = talloc_strdup(pwd, p->pw_dir);
62 BAIL_ON_PTR_ERROR(pwd->pw_dir, wbc_status);
64 pwd->pw_uid = p->pw_uid;
65 pwd->pw_gid = p->pw_gid;
67 done:
68 if (!WBC_ERROR_IS_OK(wbc_status)) {
69 talloc_free(pwd);
70 pwd = NULL;
73 return pwd;
76 /**
78 **/
80 static struct group *copy_group_entry(struct winbindd_gr *g,
81 char *mem_buf)
83 struct group *grp = NULL;
84 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
85 int i;
86 char *mem_p, *mem_q;
88 grp = talloc(NULL, struct group);
89 BAIL_ON_PTR_ERROR(grp, wbc_status);
91 grp->gr_name = talloc_strdup(grp, g->gr_name);
92 BAIL_ON_PTR_ERROR(grp->gr_name, wbc_status);
94 grp->gr_passwd = talloc_strdup(grp, g->gr_passwd);
95 BAIL_ON_PTR_ERROR(grp->gr_passwd, wbc_status);
97 grp->gr_gid = g->gr_gid;
99 grp->gr_mem = talloc_array(grp, char*, g->num_gr_mem+1);
101 mem_p = mem_q = mem_buf;
102 for (i=0; i<g->num_gr_mem && mem_p; i++) {
103 if ((mem_q = strchr(mem_p, ',')) != NULL) {
104 *mem_q = '\0';
107 grp->gr_mem[i] = talloc_strdup(grp, mem_p);
108 BAIL_ON_PTR_ERROR(grp->gr_mem[i], wbc_status);
110 if (mem_q == NULL) {
111 i += 1;
112 break;
114 mem_p = mem_q + 1;
116 grp->gr_mem[i] = NULL;
118 wbc_status = WBC_ERR_SUCCESS;
120 done:
121 if (!WBC_ERROR_IS_OK(wbc_status)) {
122 talloc_free(grp);
123 grp = NULL;
126 return grp;
129 /* Fill in a struct passwd* for a domain user based on username */
130 wbcErr wbcGetpwnam(const char *name, struct passwd **pwd)
132 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
133 struct winbindd_request request;
134 struct winbindd_response response;
136 if (!name || !pwd) {
137 wbc_status = WBC_ERR_INVALID_PARAM;
138 BAIL_ON_WBC_ERROR(wbc_status);
141 /* Initialize request */
143 ZERO_STRUCT(request);
144 ZERO_STRUCT(response);
146 /* dst is already null terminated from the memset above */
148 strncpy(request.data.username, name, sizeof(request.data.username)-1);
150 wbc_status = wbcRequestResponse(WINBINDD_GETPWNAM,
151 &request,
152 &response);
153 BAIL_ON_WBC_ERROR(wbc_status);
155 *pwd = copy_passwd_entry(&response.data.pw);
156 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
158 done:
159 return wbc_status;
162 /* Fill in a struct passwd* for a domain user based on uid */
163 wbcErr wbcGetpwuid(uid_t uid, struct passwd **pwd)
165 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
166 struct winbindd_request request;
167 struct winbindd_response response;
169 if (!pwd) {
170 wbc_status = WBC_ERR_INVALID_PARAM;
171 BAIL_ON_WBC_ERROR(wbc_status);
174 /* Initialize request */
176 ZERO_STRUCT(request);
177 ZERO_STRUCT(response);
179 request.data.uid = uid;
181 wbc_status = wbcRequestResponse(WINBINDD_GETPWUID,
182 &request,
183 &response);
184 BAIL_ON_WBC_ERROR(wbc_status);
186 *pwd = copy_passwd_entry(&response.data.pw);
187 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
189 done:
190 return wbc_status;
193 /* Fill in a struct passwd* for a domain user based on username */
194 wbcErr wbcGetgrnam(const char *name, struct group **grp)
196 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
197 struct winbindd_request request;
198 struct winbindd_response response;
200 /* Initialize request */
202 ZERO_STRUCT(request);
203 ZERO_STRUCT(response);
205 if (!name || !grp) {
206 wbc_status = WBC_ERR_INVALID_PARAM;
207 BAIL_ON_WBC_ERROR(wbc_status);
210 /* dst is already null terminated from the memset above */
212 strncpy(request.data.groupname, name, sizeof(request.data.groupname)-1);
214 wbc_status = wbcRequestResponse(WINBINDD_GETGRNAM,
215 &request,
216 &response);
217 BAIL_ON_WBC_ERROR(wbc_status);
219 *grp = copy_group_entry(&response.data.gr,
220 (char*)response.extra_data.data);
221 BAIL_ON_PTR_ERROR(*grp, wbc_status);
223 done:
224 if (response.extra_data.data)
225 free(response.extra_data.data);
227 return wbc_status;
230 /* Fill in a struct passwd* for a domain user based on uid */
231 wbcErr wbcGetgrgid(gid_t gid, struct group **grp)
233 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
234 struct winbindd_request request;
235 struct winbindd_response response;
237 /* Initialize request */
239 ZERO_STRUCT(request);
240 ZERO_STRUCT(response);
242 if (!grp) {
243 wbc_status = WBC_ERR_INVALID_PARAM;
244 BAIL_ON_WBC_ERROR(wbc_status);
247 request.data.gid = gid;
249 wbc_status = wbcRequestResponse(WINBINDD_GETGRGID,
250 &request,
251 &response);
252 BAIL_ON_WBC_ERROR(wbc_status);
254 *grp = copy_group_entry(&response.data.gr,
255 (char*)response.extra_data.data);
256 BAIL_ON_PTR_ERROR(*grp, wbc_status);
258 done:
259 if (response.extra_data.data)
260 free(response.extra_data.data);
262 return wbc_status;
265 /** @brief Number of cached passwd structs
268 static uint32_t pw_cache_size;
270 /** @brief Position of the pwent context
273 static uint32_t pw_cache_idx;
275 /** @brief Winbindd response containing the passwd structs
278 static struct winbindd_response pw_response;
280 /* Reset the passwd iterator */
281 wbcErr wbcSetpwent(void)
283 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
285 if (pw_cache_size > 0) {
286 pw_cache_idx = pw_cache_size = 0;
287 if (pw_response.extra_data.data) {
288 free(pw_response.extra_data.data);
292 ZERO_STRUCT(pw_response);
294 wbc_status = wbcRequestResponse(WINBINDD_SETPWENT,
295 NULL, NULL);
296 BAIL_ON_WBC_ERROR(wbc_status);
298 done:
299 return wbc_status;
302 /* Close the passwd iterator */
303 wbcErr wbcEndpwent(void)
305 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
307 if (pw_cache_size > 0) {
308 pw_cache_idx = pw_cache_size = 0;
309 if (pw_response.extra_data.data) {
310 free(pw_response.extra_data.data);
314 wbc_status = wbcRequestResponse(WINBINDD_ENDPWENT,
315 NULL, NULL);
316 BAIL_ON_WBC_ERROR(wbc_status);
318 done:
319 return wbc_status;
322 /* Return the next struct passwd* entry from the pwent iterator */
323 wbcErr wbcGetpwent(struct passwd **pwd)
325 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
326 struct winbindd_request request;
327 struct winbindd_pw *wb_pw;
329 /* If there's a cached result, return that. */
330 if (pw_cache_idx < pw_cache_size) {
331 goto return_result;
334 /* Otherwise, query winbindd for some entries. */
336 pw_cache_idx = 0;
338 if (pw_response.extra_data.data) {
339 free(pw_response.extra_data.data);
340 ZERO_STRUCT(pw_response);
343 ZERO_STRUCT(request);
344 request.data.num_entries = MAX_GETPWENT_USERS;
346 wbc_status = wbcRequestResponse(WINBINDD_GETPWENT, &request,
347 &pw_response);
349 BAIL_ON_WBC_ERROR(wbc_status);
351 pw_cache_size = pw_response.data.num_entries;
353 return_result:
355 wb_pw = (struct winbindd_pw *) pw_response.extra_data.data;
357 *pwd = copy_passwd_entry(&wb_pw[pw_cache_idx]);
359 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
361 pw_cache_idx++;
363 done:
364 return wbc_status;
367 /** @brief Number of cached group structs
370 static uint32_t gr_cache_size;
372 /** @brief Position of the grent context
375 static uint32_t gr_cache_idx;
377 /** @brief Winbindd response containing the group structs
380 static struct winbindd_response gr_response;
382 /* Reset the group iterator */
383 wbcErr wbcSetgrent(void)
385 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
387 if (gr_cache_size > 0) {
388 gr_cache_idx = gr_cache_size = 0;
389 if (gr_response.extra_data.data) {
390 free(gr_response.extra_data.data);
394 ZERO_STRUCT(gr_response);
396 wbc_status = wbcRequestResponse(WINBINDD_SETGRENT,
397 NULL, NULL);
398 BAIL_ON_WBC_ERROR(wbc_status);
400 done:
401 return wbc_status;
404 /* Close the group iterator */
405 wbcErr wbcEndgrent(void)
407 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
409 if (gr_cache_size > 0) {
410 gr_cache_idx = gr_cache_size = 0;
411 if (gr_response.extra_data.data) {
412 free(gr_response.extra_data.data);
416 wbc_status = wbcRequestResponse(WINBINDD_ENDGRENT,
417 NULL, NULL);
418 BAIL_ON_WBC_ERROR(wbc_status);
420 done:
421 return wbc_status;
424 /* Return the next struct group* entry from the pwent iterator */
425 wbcErr wbcGetgrent(struct group **grp)
427 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
428 struct winbindd_request request;
429 struct winbindd_gr *wb_gr;
430 uint32_t mem_ofs;
432 /* If there's a cached result, return that. */
433 if (gr_cache_idx < gr_cache_size) {
434 goto return_result;
437 /* Otherwise, query winbindd for some entries. */
439 gr_cache_idx = 0;
441 if (gr_response.extra_data.data) {
442 free(gr_response.extra_data.data);
443 ZERO_STRUCT(gr_response);
446 ZERO_STRUCT(request);
447 request.data.num_entries = MAX_GETGRENT_GROUPS;
449 wbc_status = wbcRequestResponse(WINBINDD_GETGRENT, &request,
450 &gr_response);
452 BAIL_ON_WBC_ERROR(wbc_status);
454 gr_cache_size = gr_response.data.num_entries;
456 return_result:
458 wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
460 mem_ofs = wb_gr[gr_cache_idx].gr_mem_ofs +
461 gr_cache_size * sizeof(struct winbindd_gr);
463 *grp = copy_group_entry(&wb_gr[gr_cache_idx],
464 ((char *)gr_response.extra_data.data)+mem_ofs);
466 BAIL_ON_PTR_ERROR(*grp, wbc_status);
468 gr_cache_idx++;
470 done:
471 return wbc_status;
474 /* Return the next struct group* entry from the pwent iterator */
475 wbcErr wbcGetgrlist(struct group **grp)
477 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
478 struct winbindd_request request;
479 struct winbindd_gr *wb_gr;
481 /* If there's a cached result, return that. */
482 if (gr_cache_idx < gr_cache_size) {
483 goto return_result;
486 /* Otherwise, query winbindd for some entries. */
488 gr_cache_idx = 0;
490 if (gr_response.extra_data.data) {
491 free(gr_response.extra_data.data);
492 ZERO_STRUCT(gr_response);
495 ZERO_STRUCT(request);
496 request.data.num_entries = MAX_GETGRENT_GROUPS;
498 wbc_status = wbcRequestResponse(WINBINDD_GETGRLST, &request,
499 &gr_response);
501 BAIL_ON_WBC_ERROR(wbc_status);
503 gr_cache_size = gr_response.data.num_entries;
505 return_result:
507 wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
509 *grp = copy_group_entry(&wb_gr[gr_cache_idx], NULL);
511 BAIL_ON_PTR_ERROR(*grp, wbc_status);
513 gr_cache_idx++;
515 done:
516 return wbc_status;
519 /* Return the unix group array belonging to the given user */
520 wbcErr wbcGetGroups(const char *account,
521 uint32_t *num_groups,
522 gid_t **_groups)
524 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
525 struct winbindd_request request;
526 struct winbindd_response response;
527 uint32_t i;
528 gid_t *groups = NULL;
530 /* Initialize request */
532 ZERO_STRUCT(request);
533 ZERO_STRUCT(response);
535 if (!account) {
536 wbc_status = WBC_ERR_INVALID_PARAM;
537 BAIL_ON_WBC_ERROR(wbc_status);
540 /* Send request */
542 strncpy(request.data.username, account, sizeof(request.data.username)-1);
544 wbc_status = wbcRequestResponse(WINBINDD_GETGROUPS,
545 &request,
546 &response);
547 BAIL_ON_WBC_ERROR(wbc_status);
549 groups = talloc_array(NULL, gid_t, response.data.num_entries);
550 BAIL_ON_PTR_ERROR(groups, wbc_status);
552 for (i = 0; i < response.data.num_entries; i++) {
553 groups[i] = ((gid_t *)response.extra_data.data)[i];
556 *num_groups = response.data.num_entries;
557 *_groups = groups;
558 groups = NULL;
560 wbc_status = WBC_ERR_SUCCESS;
562 done:
563 if (response.extra_data.data) {
564 free(response.extra_data.data);
566 if (groups) {
567 talloc_free(groups);
570 return wbc_status;