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 */
25 #include "libwbclient.h"
27 /** @brief The maximum number of pwent structs to get from winbindd
30 #define MAX_GETPWENT_USERS 500
36 static struct passwd *copy_passwd_entry(struct winbindd_pw *p)
38 struct passwd *pwd = NULL;
39 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
41 pwd = talloc(NULL, struct passwd);
42 BAIL_ON_PTR_ERROR(pwd, wbc_status);
44 pwd->pw_name = talloc_strdup(pwd,p->pw_name);
45 BAIL_ON_PTR_ERROR(pwd->pw_name, wbc_status);
47 pwd->pw_passwd = talloc_strdup(pwd, p->pw_passwd);
48 BAIL_ON_PTR_ERROR(pwd->pw_passwd, wbc_status);
50 pwd->pw_gecos = talloc_strdup(pwd, p->pw_gecos);
51 BAIL_ON_PTR_ERROR(pwd->pw_gecos, wbc_status);
53 pwd->pw_shell = talloc_strdup(pwd, p->pw_shell);
54 BAIL_ON_PTR_ERROR(pwd->pw_shell, wbc_status);
56 pwd->pw_dir = talloc_strdup(pwd, p->pw_dir);
57 BAIL_ON_PTR_ERROR(pwd->pw_dir, wbc_status);
59 pwd->pw_uid = p->pw_uid;
60 pwd->pw_gid = p->pw_gid;
63 if (!WBC_ERROR_IS_OK(wbc_status)) {
75 static struct group *copy_group_entry(struct winbindd_gr *g,
78 struct group *grp = NULL;
79 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
83 grp = talloc(NULL, struct group);
84 BAIL_ON_PTR_ERROR(grp, wbc_status);
86 grp->gr_name = talloc_strdup(grp, g->gr_name);
87 BAIL_ON_PTR_ERROR(grp->gr_name, wbc_status);
89 grp->gr_passwd = talloc_strdup(grp, g->gr_passwd);
90 BAIL_ON_PTR_ERROR(grp->gr_passwd, wbc_status);
92 grp->gr_gid = g->gr_gid;
94 grp->gr_mem = talloc_array(grp, char*, g->num_gr_mem+1);
96 mem_p = mem_q = mem_buf;
97 for (i=0; i<g->num_gr_mem && mem_p; i++) {
98 if ((mem_q = strchr(mem_p, ',')) != NULL) {
102 grp->gr_mem[i] = talloc_strdup(grp, mem_p);
103 BAIL_ON_PTR_ERROR(grp->gr_mem[i], wbc_status);
111 grp->gr_mem[i] = NULL;
113 wbc_status = WBC_ERR_SUCCESS;
116 if (!WBC_ERROR_IS_OK(wbc_status)) {
124 /** @brief Fill in a struct passwd* for a domain user based
127 * @param *name Username to lookup
128 * @param **pwd Pointer to resulting struct passwd* from the query.
133 wbcErr wbcGetpwnam(const char *name, struct passwd **pwd)
135 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
136 struct winbindd_request request;
137 struct winbindd_response response;
140 wbc_status = WBC_ERR_INVALID_PARAM;
141 BAIL_ON_WBC_ERROR(wbc_status);
144 /* Initialize request */
146 ZERO_STRUCT(request);
147 ZERO_STRUCT(response);
149 /* dst is already null terminated from the memset above */
151 strncpy(request.data.username, name, sizeof(request.data.username)-1);
153 wbc_status = wbcRequestResponse(WINBINDD_GETPWNAM,
156 BAIL_ON_WBC_ERROR(wbc_status);
158 *pwd = copy_passwd_entry(&response.data.pw);
159 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
165 /** @brief Fill in a struct passwd* for a domain user based
168 * @param uid Uid to lookup
169 * @param **pwd Pointer to resulting struct passwd* from the query.
174 wbcErr wbcGetpwuid(uid_t uid, struct passwd **pwd)
176 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
177 struct winbindd_request request;
178 struct winbindd_response response;
181 wbc_status = WBC_ERR_INVALID_PARAM;
182 BAIL_ON_WBC_ERROR(wbc_status);
185 /* Initialize request */
187 ZERO_STRUCT(request);
188 ZERO_STRUCT(response);
190 request.data.uid = uid;
192 wbc_status = wbcRequestResponse(WINBINDD_GETPWUID,
195 BAIL_ON_WBC_ERROR(wbc_status);
197 *pwd = copy_passwd_entry(&response.data.pw);
198 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
204 /** @brief Fill in a struct passwd* for a domain user based
207 * @param *name Username to lookup
208 * @param **grp Pointer to resulting struct group* from the query.
213 wbcErr wbcGetgrnam(const char *name, struct group **grp)
215 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
216 struct winbindd_request request;
217 struct winbindd_response response;
219 /* Initialize request */
221 ZERO_STRUCT(request);
222 ZERO_STRUCT(response);
225 wbc_status = WBC_ERR_INVALID_PARAM;
226 BAIL_ON_WBC_ERROR(wbc_status);
229 /* dst is already null terminated from the memset above */
231 strncpy(request.data.groupname, name, sizeof(request.data.groupname)-1);
233 wbc_status = wbcRequestResponse(WINBINDD_GETGRNAM,
236 BAIL_ON_WBC_ERROR(wbc_status);
238 *grp = copy_group_entry(&response.data.gr,
239 (char*)response.extra_data.data);
240 BAIL_ON_PTR_ERROR(*grp, wbc_status);
243 if (response.extra_data.data)
244 free(response.extra_data.data);
249 /** @brief Fill in a struct passwd* for a domain user based
252 * @param gid Uid to lookup
253 * @param **grp Pointer to resulting struct group* from the query.
258 wbcErr wbcGetgrgid(gid_t gid, struct group **grp)
260 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
261 struct winbindd_request request;
262 struct winbindd_response response;
264 /* Initialize request */
266 ZERO_STRUCT(request);
267 ZERO_STRUCT(response);
270 wbc_status = WBC_ERR_INVALID_PARAM;
271 BAIL_ON_WBC_ERROR(wbc_status);
274 request.data.gid = gid;
276 wbc_status = wbcRequestResponse(WINBINDD_GETGRGID,
279 BAIL_ON_WBC_ERROR(wbc_status);
281 *grp = copy_group_entry(&response.data.gr,
282 (char*)response.extra_data.data);
283 BAIL_ON_PTR_ERROR(*grp, wbc_status);
286 if (response.extra_data.data)
287 free(response.extra_data.data);
292 /** @brief Number of cached passwd structs
295 static uint32_t pw_cache_size;
297 /** @brief Position of the pwent context
300 static uint32_t pw_cache_idx;
302 /** @brief Winbindd response containing the passwd structs
305 static struct winbindd_response pw_response;
307 /** @brief Reset the passwd iterator
312 wbcErr wbcSetpwent(void)
314 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
316 if (pw_cache_size > 0) {
317 pw_cache_idx = pw_cache_size = 0;
318 if (pw_response.extra_data.data) {
319 free(pw_response.extra_data.data);
323 ZERO_STRUCT(pw_response);
325 wbc_status = wbcRequestResponse(WINBINDD_SETPWENT,
327 BAIL_ON_WBC_ERROR(wbc_status);
333 /** @brief Close the passwd iterator
338 wbcErr wbcEndpwent(void)
340 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
342 if (pw_cache_size > 0) {
343 pw_cache_idx = pw_cache_size = 0;
344 if (pw_response.extra_data.data) {
345 free(pw_response.extra_data.data);
349 wbc_status = wbcRequestResponse(WINBINDD_ENDPWENT,
351 BAIL_ON_WBC_ERROR(wbc_status);
357 /** @brief Return the next struct passwd* entry from the pwent iterator
359 * @param **pwd Pointer to resulting struct passwd* from the query.
364 wbcErr wbcGetpwent(struct passwd **pwd)
366 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
367 struct winbindd_request request;
368 struct winbindd_pw *wb_pw;
370 /* If there's a cached result, return that. */
371 if (pw_cache_idx < pw_cache_size) {
375 /* Otherwise, query winbindd for some entries. */
379 if (pw_response.extra_data.data) {
380 free(pw_response.extra_data.data);
381 ZERO_STRUCT(pw_response);
384 ZERO_STRUCT(request);
385 request.data.num_entries = MAX_GETPWENT_USERS;
387 wbc_status = wbcRequestResponse(WINBINDD_GETPWENT, &request,
390 BAIL_ON_WBC_ERROR(wbc_status);
392 pw_cache_size = pw_response.data.num_entries;
396 wb_pw = (struct winbindd_pw *) pw_response.extra_data.data;
398 *pwd = copy_passwd_entry(&wb_pw[pw_cache_idx]);
400 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
408 /** @brief Reset the group iterator
413 wbcErr wbcSetgrent(void)
415 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
417 wbc_status = wbcRequestResponse(WINBINDD_SETGRENT,
419 BAIL_ON_WBC_ERROR(wbc_status);
425 /** @brief Close the group iterator
430 wbcErr wbcEndgrent(void)
432 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
434 wbc_status = wbcRequestResponse(WINBINDD_ENDGRENT,
436 BAIL_ON_WBC_ERROR(wbc_status);
442 /** @brief Return the next struct group* entry from the pwent iterator
444 * @param **grp Pointer to resulting struct group* from the query.
449 wbcErr wbcGetgrent(struct group **grp)
451 return WBC_ERR_NOT_IMPLEMENTED;
454 /** @brief Return the next struct group* entry from the pwent iterator
456 * This is similar to #wbcGetgrent, just that the member list is empty
458 * @param **grp Pointer to resulting struct group* from the query.
463 wbcErr wbcGetgrlist(struct group **grp)
465 return WBC_ERR_NOT_IMPLEMENTED;
468 /** @brief Return the unix group array belonging to the given user
470 * @param *account The given user name
471 * @param *num_groups Number of elements returned in the groups array
472 * @param **_groups Pointer to resulting gid_t array.
476 wbcErr wbcGetGroups(const char *account,
477 uint32_t *num_groups,
480 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
481 struct winbindd_request request;
482 struct winbindd_response response;
484 gid_t *groups = NULL;
486 /* Initialize request */
488 ZERO_STRUCT(request);
489 ZERO_STRUCT(response);
492 wbc_status = WBC_ERR_INVALID_PARAM;
493 BAIL_ON_WBC_ERROR(wbc_status);
498 strncpy(request.data.username, account, sizeof(request.data.username)-1);
500 wbc_status = wbcRequestResponse(WINBINDD_GETGROUPS,
503 BAIL_ON_WBC_ERROR(wbc_status);
505 groups = talloc_array(NULL, gid_t, response.data.num_entries);
506 BAIL_ON_PTR_ERROR(groups, wbc_status);
508 for (i = 0; i < response.data.num_entries; i++) {
509 groups[i] = ((gid_t *)response.extra_data.data)[i];
512 *num_groups = response.data.num_entries;
516 wbc_status = WBC_ERR_SUCCESS;
519 if (response.extra_data.data) {
520 free(response.extra_data.data);