2 Unix SMB/CIFS implementation.
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 */
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
43 static void wbcPasswdDestructor(void *ptr)
45 struct passwd *pw = (struct passwd *)ptr;
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),
62 pw->pw_name = strdup(p->pw_name);
63 if (pw->pw_name == NULL) {
66 pw->pw_passwd = strdup(p->pw_passwd);
67 if (pw->pw_passwd == NULL) {
70 pw->pw_gecos = strdup(p->pw_gecos);
71 if (pw->pw_gecos == NULL) {
74 pw->pw_shell = strdup(p->pw_shell);
75 if (pw->pw_shell == NULL) {
78 pw->pw_dir = strdup(p->pw_dir);
79 if (pw->pw_dir == NULL) {
82 pw->pw_uid = p->pw_uid;
83 pw->pw_gid = p->pw_gid;
95 static void wbcGroupDestructor(void *ptr)
97 struct group *gr = (struct group *)ptr;
103 for (i=0; gr->gr_mem[i] != NULL; i++) {
109 static struct group *copy_group_entry(struct winbindd_gr *g,
112 struct group *gr = NULL;
116 gr = (struct group *)wbcAllocateMemory(
117 1, sizeof(struct group), wbcGroupDestructor);
122 gr->gr_name = strdup(g->gr_name);
123 if (gr->gr_name == NULL) {
126 gr->gr_passwd = strdup(g->gr_passwd);
127 if (gr->gr_passwd == NULL) {
130 gr->gr_gid = g->gr_gid;
132 gr->gr_mem = (char **)calloc(g->num_gr_mem+1, sizeof(char *));
133 if (gr->gr_mem == NULL) {
137 mem_p = mem_q = mem_buf;
138 for (i=0; i<g->num_gr_mem && mem_p; i++) {
139 mem_q = strchr(mem_p, ',');
144 gr->gr_mem[i] = strdup(mem_p);
145 if (gr->gr_mem[i] == NULL) {
155 gr->gr_mem[i] = NULL;
164 /* Fill in a struct passwd* for a domain user based on username */
165 wbcErr wbcGetpwnam(const char *name, struct passwd **pwd)
167 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
168 struct winbindd_request request;
169 struct winbindd_response response;
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 /* dst is already null terminated from the memset above */
183 strncpy(request.data.username, name, sizeof(request.data.username)-1);
185 wbc_status = wbcRequestResponse(WINBINDD_GETPWNAM,
188 BAIL_ON_WBC_ERROR(wbc_status);
190 *pwd = copy_passwd_entry(&response.data.pw);
191 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
197 /* Fill in a struct passwd* for a domain user based on uid */
198 wbcErr wbcGetpwuid(uid_t uid, struct passwd **pwd)
200 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
201 struct winbindd_request request;
202 struct winbindd_response response;
205 wbc_status = WBC_ERR_INVALID_PARAM;
206 BAIL_ON_WBC_ERROR(wbc_status);
209 /* Initialize request */
211 ZERO_STRUCT(request);
212 ZERO_STRUCT(response);
214 request.data.uid = uid;
216 wbc_status = wbcRequestResponse(WINBINDD_GETPWUID,
219 BAIL_ON_WBC_ERROR(wbc_status);
221 *pwd = copy_passwd_entry(&response.data.pw);
222 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
228 /* Fill in a struct passwd* for a domain user based on sid */
229 wbcErr wbcGetpwsid(struct wbcDomainSid *sid, struct passwd **pwd)
231 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
232 struct winbindd_request request;
233 struct winbindd_response response;
234 char * sid_string = NULL;
237 wbc_status = WBC_ERR_INVALID_PARAM;
238 BAIL_ON_WBC_ERROR(wbc_status);
241 wbc_status = wbcSidToString(sid, &sid_string);
242 BAIL_ON_WBC_ERROR(wbc_status);
244 /* Initialize request */
246 ZERO_STRUCT(request);
247 ZERO_STRUCT(response);
249 strncpy(request.data.sid, sid_string, sizeof(request.data.sid));
251 wbc_status = wbcRequestResponse(WINBINDD_GETPWSID,
254 BAIL_ON_WBC_ERROR(wbc_status);
256 *pwd = copy_passwd_entry(&response.data.pw);
257 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
260 wbcFreeMemory(sid_string);
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);
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,
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);
295 winbindd_free_response(&response);
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);
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,
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);
329 winbindd_free_response(&response);
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,
363 BAIL_ON_WBC_ERROR(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,
381 BAIL_ON_WBC_ERROR(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) {
399 /* Otherwise, query winbindd for some entries. */
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,
411 BAIL_ON_WBC_ERROR(wbc_status);
413 pw_cache_size = pw_response.data.num_entries;
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);
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,
458 BAIL_ON_WBC_ERROR(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,
476 BAIL_ON_WBC_ERROR(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;
490 /* If there's a cached result, return that. */
491 if (gr_cache_idx < gr_cache_size) {
495 /* Otherwise, query winbindd for some entries. */
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,
507 BAIL_ON_WBC_ERROR(wbc_status);
509 gr_cache_size = gr_response.data.num_entries;
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);
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) {
541 /* Otherwise, query winbindd for some entries. */
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,
554 BAIL_ON_WBC_ERROR(wbc_status);
556 gr_cache_size = gr_response.data.num_entries;
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);
572 /* Return the unix group array belonging to the given user */
573 wbcErr wbcGetGroups(const char *account,
574 uint32_t *num_groups,
577 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
578 struct winbindd_request request;
579 struct winbindd_response response;
581 gid_t *groups = NULL;
583 /* Initialize request */
585 ZERO_STRUCT(request);
586 ZERO_STRUCT(response);
589 wbc_status = WBC_ERR_INVALID_PARAM;
590 BAIL_ON_WBC_ERROR(wbc_status);
595 strncpy(request.data.username, account, sizeof(request.data.username)-1);
597 wbc_status = wbcRequestResponse(WINBINDD_GETGROUPS,
600 BAIL_ON_WBC_ERROR(wbc_status);
602 groups = talloc_array(NULL, gid_t, response.data.num_entries);
603 BAIL_ON_PTR_ERROR(groups, wbc_status);
605 for (i = 0; i < response.data.num_entries; i++) {
606 groups[i] = ((gid_t *)response.extra_data.data)[i];
609 *num_groups = response.data.num_entries;
613 wbc_status = WBC_ERR_SUCCESS;
616 winbindd_free_response(&response);