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 /* if the array was partly created this can be NULL */
104 if (gr
->gr_mem
== NULL
) {
108 for (i
=0; gr
->gr_mem
[i
] != NULL
; i
++) {
114 static struct group
*copy_group_entry(struct winbindd_gr
*g
,
117 struct group
*gr
= NULL
;
121 gr
= (struct group
*)wbcAllocateMemory(
122 1, sizeof(struct group
), wbcGroupDestructor
);
127 gr
->gr_name
= strdup(g
->gr_name
);
128 if (gr
->gr_name
== NULL
) {
131 gr
->gr_passwd
= strdup(g
->gr_passwd
);
132 if (gr
->gr_passwd
== NULL
) {
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
) {
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
, ',');
149 gr
->gr_mem
[i
] = strdup(mem_p
);
150 if (gr
->gr_mem
[i
] == NULL
) {
160 gr
->gr_mem
[i
] = 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
;
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
,
193 BAIL_ON_WBC_ERROR(wbc_status
);
195 *pwd
= copy_passwd_entry(&response
.data
.pw
);
196 BAIL_ON_PTR_ERROR(*pwd
, 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
;
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
,
224 BAIL_ON_WBC_ERROR(wbc_status
);
226 *pwd
= copy_passwd_entry(&response
.data
.pw
);
227 BAIL_ON_PTR_ERROR(*pwd
, 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
;
239 char * sid_string
= NULL
;
242 wbc_status
= WBC_ERR_INVALID_PARAM
;
243 BAIL_ON_WBC_ERROR(wbc_status
);
246 wbc_status
= wbcSidToString(sid
, &sid_string
);
247 BAIL_ON_WBC_ERROR(wbc_status
);
249 /* Initialize request */
251 ZERO_STRUCT(request
);
252 ZERO_STRUCT(response
);
254 strncpy(request
.data
.sid
, sid_string
, sizeof(request
.data
.sid
));
256 wbc_status
= wbcRequestResponse(WINBINDD_GETPWSID
,
259 BAIL_ON_WBC_ERROR(wbc_status
);
261 *pwd
= copy_passwd_entry(&response
.data
.pw
);
262 BAIL_ON_PTR_ERROR(*pwd
, wbc_status
);
265 wbcFreeMemory(sid_string
);
269 /* Fill in a struct passwd* for a domain user based on username */
270 wbcErr
wbcGetgrnam(const char *name
, 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 /* dst is already null terminated from the memset above */
288 strncpy(request
.data
.groupname
, name
, sizeof(request
.data
.groupname
)-1);
290 wbc_status
= wbcRequestResponse(WINBINDD_GETGRNAM
,
293 BAIL_ON_WBC_ERROR(wbc_status
);
295 *grp
= copy_group_entry(&response
.data
.gr
,
296 (char*)response
.extra_data
.data
);
297 BAIL_ON_PTR_ERROR(*grp
, wbc_status
);
300 winbindd_free_response(&response
);
305 /* Fill in a struct passwd* for a domain user based on uid */
306 wbcErr
wbcGetgrgid(gid_t gid
, struct group
**grp
)
308 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
309 struct winbindd_request request
;
310 struct winbindd_response response
;
312 /* Initialize request */
314 ZERO_STRUCT(request
);
315 ZERO_STRUCT(response
);
318 wbc_status
= WBC_ERR_INVALID_PARAM
;
319 BAIL_ON_WBC_ERROR(wbc_status
);
322 request
.data
.gid
= gid
;
324 wbc_status
= wbcRequestResponse(WINBINDD_GETGRGID
,
327 BAIL_ON_WBC_ERROR(wbc_status
);
329 *grp
= copy_group_entry(&response
.data
.gr
,
330 (char*)response
.extra_data
.data
);
331 BAIL_ON_PTR_ERROR(*grp
, wbc_status
);
334 winbindd_free_response(&response
);
339 /** @brief Number of cached passwd structs
342 static uint32_t pw_cache_size
;
344 /** @brief Position of the pwent context
347 static uint32_t pw_cache_idx
;
349 /** @brief Winbindd response containing the passwd structs
352 static struct winbindd_response pw_response
;
354 /* Reset the passwd iterator */
355 wbcErr
wbcSetpwent(void)
357 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
359 if (pw_cache_size
> 0) {
360 pw_cache_idx
= pw_cache_size
= 0;
361 winbindd_free_response(&pw_response
);
364 ZERO_STRUCT(pw_response
);
366 wbc_status
= wbcRequestResponse(WINBINDD_SETPWENT
,
368 BAIL_ON_WBC_ERROR(wbc_status
);
374 /* Close the passwd iterator */
375 wbcErr
wbcEndpwent(void)
377 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
379 if (pw_cache_size
> 0) {
380 pw_cache_idx
= pw_cache_size
= 0;
381 winbindd_free_response(&pw_response
);
384 wbc_status
= wbcRequestResponse(WINBINDD_ENDPWENT
,
386 BAIL_ON_WBC_ERROR(wbc_status
);
392 /* Return the next struct passwd* entry from the pwent iterator */
393 wbcErr
wbcGetpwent(struct passwd
**pwd
)
395 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
396 struct winbindd_request request
;
397 struct winbindd_pw
*wb_pw
;
399 /* If there's a cached result, return that. */
400 if (pw_cache_idx
< pw_cache_size
) {
404 /* Otherwise, query winbindd for some entries. */
408 winbindd_free_response(&pw_response
);
410 ZERO_STRUCT(request
);
411 request
.data
.num_entries
= MAX_GETPWENT_USERS
;
413 wbc_status
= wbcRequestResponse(WINBINDD_GETPWENT
, &request
,
416 BAIL_ON_WBC_ERROR(wbc_status
);
418 pw_cache_size
= pw_response
.data
.num_entries
;
422 wb_pw
= (struct winbindd_pw
*) pw_response
.extra_data
.data
;
424 *pwd
= copy_passwd_entry(&wb_pw
[pw_cache_idx
]);
426 BAIL_ON_PTR_ERROR(*pwd
, wbc_status
);
434 /** @brief Number of cached group structs
437 static uint32_t gr_cache_size
;
439 /** @brief Position of the grent context
442 static uint32_t gr_cache_idx
;
444 /** @brief Winbindd response containing the group structs
447 static struct winbindd_response gr_response
;
449 /* Reset the group iterator */
450 wbcErr
wbcSetgrent(void)
452 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
454 if (gr_cache_size
> 0) {
455 gr_cache_idx
= gr_cache_size
= 0;
456 winbindd_free_response(&gr_response
);
459 ZERO_STRUCT(gr_response
);
461 wbc_status
= wbcRequestResponse(WINBINDD_SETGRENT
,
463 BAIL_ON_WBC_ERROR(wbc_status
);
469 /* Close the group iterator */
470 wbcErr
wbcEndgrent(void)
472 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
474 if (gr_cache_size
> 0) {
475 gr_cache_idx
= gr_cache_size
= 0;
476 winbindd_free_response(&gr_response
);
479 wbc_status
= wbcRequestResponse(WINBINDD_ENDGRENT
,
481 BAIL_ON_WBC_ERROR(wbc_status
);
487 /* Return the next struct group* entry from the pwent iterator */
488 wbcErr
wbcGetgrent(struct group
**grp
)
490 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
491 struct winbindd_request request
;
492 struct winbindd_gr
*wb_gr
;
495 /* If there's a cached result, return that. */
496 if (gr_cache_idx
< gr_cache_size
) {
500 /* Otherwise, query winbindd for some entries. */
504 winbindd_free_response(&gr_response
);
506 ZERO_STRUCT(request
);
507 request
.data
.num_entries
= MAX_GETGRENT_GROUPS
;
509 wbc_status
= wbcRequestResponse(WINBINDD_GETGRENT
, &request
,
512 BAIL_ON_WBC_ERROR(wbc_status
);
514 gr_cache_size
= gr_response
.data
.num_entries
;
518 wb_gr
= (struct winbindd_gr
*) gr_response
.extra_data
.data
;
520 mem_ofs
= wb_gr
[gr_cache_idx
].gr_mem_ofs
+
521 gr_cache_size
* sizeof(struct winbindd_gr
);
523 *grp
= copy_group_entry(&wb_gr
[gr_cache_idx
],
524 ((char *)gr_response
.extra_data
.data
)+mem_ofs
);
526 BAIL_ON_PTR_ERROR(*grp
, wbc_status
);
534 /* Return the next struct group* entry from the pwent iterator */
535 wbcErr
wbcGetgrlist(struct group
**grp
)
537 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
538 struct winbindd_request request
;
539 struct winbindd_gr
*wb_gr
;
541 /* If there's a cached result, return that. */
542 if (gr_cache_idx
< gr_cache_size
) {
546 /* Otherwise, query winbindd for some entries. */
550 winbindd_free_response(&gr_response
);
551 ZERO_STRUCT(gr_response
);
553 ZERO_STRUCT(request
);
554 request
.data
.num_entries
= MAX_GETGRENT_GROUPS
;
556 wbc_status
= wbcRequestResponse(WINBINDD_GETGRLST
, &request
,
559 BAIL_ON_WBC_ERROR(wbc_status
);
561 gr_cache_size
= gr_response
.data
.num_entries
;
565 wb_gr
= (struct winbindd_gr
*) gr_response
.extra_data
.data
;
567 *grp
= copy_group_entry(&wb_gr
[gr_cache_idx
], NULL
);
569 BAIL_ON_PTR_ERROR(*grp
, wbc_status
);
577 /* Return the unix group array belonging to the given user */
578 wbcErr
wbcGetGroups(const char *account
,
579 uint32_t *num_groups
,
582 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
583 struct winbindd_request request
;
584 struct winbindd_response response
;
586 gid_t
*groups
= NULL
;
588 /* Initialize request */
590 ZERO_STRUCT(request
);
591 ZERO_STRUCT(response
);
594 wbc_status
= WBC_ERR_INVALID_PARAM
;
595 BAIL_ON_WBC_ERROR(wbc_status
);
600 strncpy(request
.data
.username
, account
, sizeof(request
.data
.username
)-1);
602 wbc_status
= wbcRequestResponse(WINBINDD_GETGROUPS
,
605 BAIL_ON_WBC_ERROR(wbc_status
);
607 groups
= (gid_t
*)wbcAllocateMemory(
608 response
.data
.num_entries
, sizeof(gid_t
), NULL
);
609 BAIL_ON_PTR_ERROR(groups
, wbc_status
);
611 for (i
= 0; i
< response
.data
.num_entries
; i
++) {
612 groups
[i
] = ((gid_t
*)response
.extra_data
.data
)[i
];
615 *num_groups
= response
.data
.num_entries
;
619 wbc_status
= WBC_ERR_SUCCESS
;
622 winbindd_free_response(&response
);
623 wbcFreeMemory(groups
);