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 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
);
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
,
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
);
224 if (response
.extra_data
.data
)
225 free(response
.extra_data
.data
);
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
);
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
,
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
);
259 if (response
.extra_data
.data
)
260 free(response
.extra_data
.data
);
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
,
296 BAIL_ON_WBC_ERROR(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
,
316 BAIL_ON_WBC_ERROR(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
) {
334 /* Otherwise, query winbindd for some entries. */
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
,
349 BAIL_ON_WBC_ERROR(wbc_status
);
351 pw_cache_size
= pw_response
.data
.num_entries
;
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
);
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
,
398 BAIL_ON_WBC_ERROR(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
,
418 BAIL_ON_WBC_ERROR(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
;
432 /* If there's a cached result, return that. */
433 if (gr_cache_idx
< gr_cache_size
) {
437 /* Otherwise, query winbindd for some entries. */
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
,
452 BAIL_ON_WBC_ERROR(wbc_status
);
454 gr_cache_size
= gr_response
.data
.num_entries
;
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
);
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
) {
486 /* Otherwise, query winbindd for some entries. */
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
,
501 BAIL_ON_WBC_ERROR(wbc_status
);
503 gr_cache_size
= gr_response
.data
.num_entries
;
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
);
519 /* Return the unix group array belonging to the given user */
520 wbcErr
wbcGetGroups(const char *account
,
521 uint32_t *num_groups
,
524 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
525 struct winbindd_request request
;
526 struct winbindd_response response
;
528 gid_t
*groups
= NULL
;
530 /* Initialize request */
532 ZERO_STRUCT(request
);
533 ZERO_STRUCT(response
);
536 wbc_status
= WBC_ERR_INVALID_PARAM
;
537 BAIL_ON_WBC_ERROR(wbc_status
);
542 strncpy(request
.data
.username
, account
, sizeof(request
.data
.username
)-1);
544 wbc_status
= wbcRequestResponse(WINBINDD_GETGROUPS
,
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
;
560 wbc_status
= WBC_ERR_SUCCESS
;
563 if (response
.extra_data
.data
) {
564 free(response
.extra_data
.data
);