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
32 /** @brief The maximum number of grent structs to get from winbindd
35 #define MAX_GETGRENT_GROUPS 500
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
;
68 if (!WBC_ERROR_IS_OK(wbc_status
)) {
80 static struct group
*copy_group_entry(struct winbindd_gr
*g
,
83 struct group
*grp
= NULL
;
84 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
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
) {
107 grp
->gr_mem
[i
] = talloc_strdup(grp
, mem_p
);
108 BAIL_ON_PTR_ERROR(grp
->gr_mem
[i
], wbc_status
);
116 grp
->gr_mem
[i
] = NULL
;
118 wbc_status
= WBC_ERR_SUCCESS
;
121 if (!WBC_ERROR_IS_OK(wbc_status
)) {
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
;
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
,
153 BAIL_ON_WBC_ERROR(wbc_status
);
155 *pwd
= copy_passwd_entry(&response
.data
.pw
);
156 BAIL_ON_PTR_ERROR(*pwd
, 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
;
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
,
184 BAIL_ON_WBC_ERROR(wbc_status
);
186 *pwd
= copy_passwd_entry(&response
.data
.pw
);
187 BAIL_ON_PTR_ERROR(*pwd
, wbc_status
);
193 /* Fill in a struct passwd* for a domain user based on sid */
194 wbcErr
wbcGetpwsid(struct wbcDomainSid
*sid
, struct passwd
**pwd
)
196 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
197 struct winbindd_request request
;
198 struct winbindd_response response
;
199 char * sid_string
= NULL
;
202 wbc_status
= WBC_ERR_INVALID_PARAM
;
203 BAIL_ON_WBC_ERROR(wbc_status
);
206 wbc_status
= wbcSidToString(sid
, &sid_string
);
207 BAIL_ON_WBC_ERROR(wbc_status
);
209 /* Initialize request */
211 ZERO_STRUCT(request
);
212 ZERO_STRUCT(response
);
214 strncpy(request
.data
.sid
, sid_string
, sizeof(request
.data
.sid
));
216 wbc_status
= wbcRequestResponse(WINBINDD_GETPWSID
,
219 BAIL_ON_WBC_ERROR(wbc_status
);
221 *pwd
= copy_passwd_entry(&response
.data
.pw
);
222 BAIL_ON_PTR_ERROR(*pwd
, wbc_status
);
226 wbcFreeMemory(sid_string
);
232 /* Fill in a struct passwd* for a domain user based on username */
233 wbcErr
wbcGetgrnam(const char *name
, struct group
**grp
)
235 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
236 struct winbindd_request request
;
237 struct winbindd_response response
;
239 /* Initialize request */
241 ZERO_STRUCT(request
);
242 ZERO_STRUCT(response
);
245 wbc_status
= WBC_ERR_INVALID_PARAM
;
246 BAIL_ON_WBC_ERROR(wbc_status
);
249 /* dst is already null terminated from the memset above */
251 strncpy(request
.data
.groupname
, name
, sizeof(request
.data
.groupname
)-1);
253 wbc_status
= wbcRequestResponse(WINBINDD_GETGRNAM
,
256 BAIL_ON_WBC_ERROR(wbc_status
);
258 *grp
= copy_group_entry(&response
.data
.gr
,
259 (char*)response
.extra_data
.data
);
260 BAIL_ON_PTR_ERROR(*grp
, wbc_status
);
263 if (response
.extra_data
.data
)
264 free(response
.extra_data
.data
);
269 /* Fill in a struct passwd* for a domain user based on uid */
270 wbcErr
wbcGetgrgid(gid_t gid
, struct group
**grp
)
272 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
273 struct winbindd_request request
;
274 struct winbindd_response response
;
276 /* Initialize request */
278 ZERO_STRUCT(request
);
279 ZERO_STRUCT(response
);
282 wbc_status
= WBC_ERR_INVALID_PARAM
;
283 BAIL_ON_WBC_ERROR(wbc_status
);
286 request
.data
.gid
= gid
;
288 wbc_status
= wbcRequestResponse(WINBINDD_GETGRGID
,
291 BAIL_ON_WBC_ERROR(wbc_status
);
293 *grp
= copy_group_entry(&response
.data
.gr
,
294 (char*)response
.extra_data
.data
);
295 BAIL_ON_PTR_ERROR(*grp
, wbc_status
);
298 if (response
.extra_data
.data
)
299 free(response
.extra_data
.data
);
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 if (pw_response
.extra_data
.data
) {
327 free(pw_response
.extra_data
.data
);
331 ZERO_STRUCT(pw_response
);
333 wbc_status
= wbcRequestResponse(WINBINDD_SETPWENT
,
335 BAIL_ON_WBC_ERROR(wbc_status
);
341 /* Close the passwd iterator */
342 wbcErr
wbcEndpwent(void)
344 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
346 if (pw_cache_size
> 0) {
347 pw_cache_idx
= pw_cache_size
= 0;
348 if (pw_response
.extra_data
.data
) {
349 free(pw_response
.extra_data
.data
);
353 wbc_status
= wbcRequestResponse(WINBINDD_ENDPWENT
,
355 BAIL_ON_WBC_ERROR(wbc_status
);
361 /* Return the next struct passwd* entry from the pwent iterator */
362 wbcErr
wbcGetpwent(struct passwd
**pwd
)
364 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
365 struct winbindd_request request
;
366 struct winbindd_pw
*wb_pw
;
368 /* If there's a cached result, return that. */
369 if (pw_cache_idx
< pw_cache_size
) {
373 /* Otherwise, query winbindd for some entries. */
377 if (pw_response
.extra_data
.data
) {
378 free(pw_response
.extra_data
.data
);
379 ZERO_STRUCT(pw_response
);
382 ZERO_STRUCT(request
);
383 request
.data
.num_entries
= MAX_GETPWENT_USERS
;
385 wbc_status
= wbcRequestResponse(WINBINDD_GETPWENT
, &request
,
388 BAIL_ON_WBC_ERROR(wbc_status
);
390 pw_cache_size
= pw_response
.data
.num_entries
;
394 wb_pw
= (struct winbindd_pw
*) pw_response
.extra_data
.data
;
396 *pwd
= copy_passwd_entry(&wb_pw
[pw_cache_idx
]);
398 BAIL_ON_PTR_ERROR(*pwd
, wbc_status
);
406 /** @brief Number of cached group structs
409 static uint32_t gr_cache_size
;
411 /** @brief Position of the grent context
414 static uint32_t gr_cache_idx
;
416 /** @brief Winbindd response containing the group structs
419 static struct winbindd_response gr_response
;
421 /* Reset the group iterator */
422 wbcErr
wbcSetgrent(void)
424 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
426 if (gr_cache_size
> 0) {
427 gr_cache_idx
= gr_cache_size
= 0;
428 if (gr_response
.extra_data
.data
) {
429 free(gr_response
.extra_data
.data
);
433 ZERO_STRUCT(gr_response
);
435 wbc_status
= wbcRequestResponse(WINBINDD_SETGRENT
,
437 BAIL_ON_WBC_ERROR(wbc_status
);
443 /* Close the group iterator */
444 wbcErr
wbcEndgrent(void)
446 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
448 if (gr_cache_size
> 0) {
449 gr_cache_idx
= gr_cache_size
= 0;
450 if (gr_response
.extra_data
.data
) {
451 free(gr_response
.extra_data
.data
);
455 wbc_status
= wbcRequestResponse(WINBINDD_ENDGRENT
,
457 BAIL_ON_WBC_ERROR(wbc_status
);
463 /* Return the next struct group* entry from the pwent iterator */
464 wbcErr
wbcGetgrent(struct group
**grp
)
466 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
467 struct winbindd_request request
;
468 struct winbindd_gr
*wb_gr
;
471 /* If there's a cached result, return that. */
472 if (gr_cache_idx
< gr_cache_size
) {
476 /* Otherwise, query winbindd for some entries. */
480 if (gr_response
.extra_data
.data
) {
481 free(gr_response
.extra_data
.data
);
482 ZERO_STRUCT(gr_response
);
485 ZERO_STRUCT(request
);
486 request
.data
.num_entries
= MAX_GETGRENT_GROUPS
;
488 wbc_status
= wbcRequestResponse(WINBINDD_GETGRENT
, &request
,
491 BAIL_ON_WBC_ERROR(wbc_status
);
493 gr_cache_size
= gr_response
.data
.num_entries
;
497 wb_gr
= (struct winbindd_gr
*) gr_response
.extra_data
.data
;
499 mem_ofs
= wb_gr
[gr_cache_idx
].gr_mem_ofs
+
500 gr_cache_size
* sizeof(struct winbindd_gr
);
502 *grp
= copy_group_entry(&wb_gr
[gr_cache_idx
],
503 ((char *)gr_response
.extra_data
.data
)+mem_ofs
);
505 BAIL_ON_PTR_ERROR(*grp
, wbc_status
);
513 /* Return the next struct group* entry from the pwent iterator */
514 wbcErr
wbcGetgrlist(struct group
**grp
)
516 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
517 struct winbindd_request request
;
518 struct winbindd_gr
*wb_gr
;
520 /* If there's a cached result, return that. */
521 if (gr_cache_idx
< gr_cache_size
) {
525 /* Otherwise, query winbindd for some entries. */
529 if (gr_response
.extra_data
.data
) {
530 free(gr_response
.extra_data
.data
);
531 ZERO_STRUCT(gr_response
);
534 ZERO_STRUCT(request
);
535 request
.data
.num_entries
= MAX_GETGRENT_GROUPS
;
537 wbc_status
= wbcRequestResponse(WINBINDD_GETGRLST
, &request
,
540 BAIL_ON_WBC_ERROR(wbc_status
);
542 gr_cache_size
= gr_response
.data
.num_entries
;
546 wb_gr
= (struct winbindd_gr
*) gr_response
.extra_data
.data
;
548 *grp
= copy_group_entry(&wb_gr
[gr_cache_idx
], NULL
);
550 BAIL_ON_PTR_ERROR(*grp
, wbc_status
);
558 /* Return the unix group array belonging to the given user */
559 wbcErr
wbcGetGroups(const char *account
,
560 uint32_t *num_groups
,
563 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
564 struct winbindd_request request
;
565 struct winbindd_response response
;
567 gid_t
*groups
= NULL
;
569 /* Initialize request */
571 ZERO_STRUCT(request
);
572 ZERO_STRUCT(response
);
575 wbc_status
= WBC_ERR_INVALID_PARAM
;
576 BAIL_ON_WBC_ERROR(wbc_status
);
581 strncpy(request
.data
.username
, account
, sizeof(request
.data
.username
)-1);
583 wbc_status
= wbcRequestResponse(WINBINDD_GETGROUPS
,
586 BAIL_ON_WBC_ERROR(wbc_status
);
588 groups
= talloc_array(NULL
, gid_t
, response
.data
.num_entries
);
589 BAIL_ON_PTR_ERROR(groups
, wbc_status
);
591 for (i
= 0; i
< response
.data
.num_entries
; i
++) {
592 groups
[i
] = ((gid_t
*)response
.extra_data
.data
)[i
];
595 *num_groups
= response
.data
.num_entries
;
599 wbc_status
= WBC_ERR_SUCCESS
;
602 if (response
.extra_data
.data
) {
603 free(response
.extra_data
.data
);