s4:torture:smb2: Add test that shows the client can respond to a lease break over...
[Samba.git] / nsswitch / libwbclient / wbc_pwd.c
blob6df694dcacd464ce5a2f9b25f28139e93d0a7518
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;
240 if (!pwd) {
241 wbc_status = WBC_ERR_INVALID_PARAM;
242 BAIL_ON_WBC_ERROR(wbc_status);
245 /* Initialize request */
247 ZERO_STRUCT(request);
248 ZERO_STRUCT(response);
250 wbcSidToStringBuf(sid, request.data.sid, sizeof(request.data.sid));
252 wbc_status = wbcRequestResponse(WINBINDD_GETPWSID,
253 &request,
254 &response);
255 BAIL_ON_WBC_ERROR(wbc_status);
257 *pwd = copy_passwd_entry(&response.data.pw);
258 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
260 done:
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 response.data.num_entries, sizeof(gid_t), 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;