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 struct passwd
*copy_passwd_entry(struct winbindd_pw
*p
)
45 struct passwd
*pwd
= NULL
;
46 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
48 pwd
= talloc(NULL
, struct passwd
);
49 BAIL_ON_PTR_ERROR(pwd
, wbc_status
);
51 pwd
->pw_name
= talloc_strdup(pwd
,p
->pw_name
);
52 BAIL_ON_PTR_ERROR(pwd
->pw_name
, wbc_status
);
54 pwd
->pw_passwd
= talloc_strdup(pwd
, p
->pw_passwd
);
55 BAIL_ON_PTR_ERROR(pwd
->pw_passwd
, wbc_status
);
57 pwd
->pw_gecos
= talloc_strdup(pwd
, p
->pw_gecos
);
58 BAIL_ON_PTR_ERROR(pwd
->pw_gecos
, wbc_status
);
60 pwd
->pw_shell
= talloc_strdup(pwd
, p
->pw_shell
);
61 BAIL_ON_PTR_ERROR(pwd
->pw_shell
, wbc_status
);
63 pwd
->pw_dir
= talloc_strdup(pwd
, p
->pw_dir
);
64 BAIL_ON_PTR_ERROR(pwd
->pw_dir
, wbc_status
);
66 pwd
->pw_uid
= p
->pw_uid
;
67 pwd
->pw_gid
= p
->pw_gid
;
70 if (!WBC_ERROR_IS_OK(wbc_status
)) {
82 static struct group
*copy_group_entry(struct winbindd_gr
*g
,
85 struct group
*grp
= NULL
;
86 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
90 grp
= talloc(NULL
, struct group
);
91 BAIL_ON_PTR_ERROR(grp
, wbc_status
);
93 grp
->gr_name
= talloc_strdup(grp
, g
->gr_name
);
94 BAIL_ON_PTR_ERROR(grp
->gr_name
, wbc_status
);
96 grp
->gr_passwd
= talloc_strdup(grp
, g
->gr_passwd
);
97 BAIL_ON_PTR_ERROR(grp
->gr_passwd
, wbc_status
);
99 grp
->gr_gid
= g
->gr_gid
;
101 grp
->gr_mem
= talloc_array(grp
, char*, g
->num_gr_mem
+1);
103 mem_p
= mem_q
= mem_buf
;
104 for (i
=0; i
<g
->num_gr_mem
&& mem_p
; i
++) {
105 if ((mem_q
= strchr(mem_p
, ',')) != NULL
) {
109 grp
->gr_mem
[i
] = talloc_strdup(grp
, mem_p
);
110 BAIL_ON_PTR_ERROR(grp
->gr_mem
[i
], wbc_status
);
118 grp
->gr_mem
[i
] = NULL
;
120 wbc_status
= WBC_ERR_SUCCESS
;
123 if (!WBC_ERROR_IS_OK(wbc_status
)) {
131 /* Fill in a struct passwd* for a domain user based on username */
132 wbcErr
wbcGetpwnam(const char *name
, struct passwd
**pwd
)
134 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
135 struct winbindd_request request
;
136 struct winbindd_response response
;
139 wbc_status
= WBC_ERR_INVALID_PARAM
;
140 BAIL_ON_WBC_ERROR(wbc_status
);
143 /* Initialize request */
145 ZERO_STRUCT(request
);
146 ZERO_STRUCT(response
);
148 /* dst is already null terminated from the memset above */
150 strncpy(request
.data
.username
, name
, sizeof(request
.data
.username
)-1);
152 wbc_status
= wbcRequestResponse(WINBINDD_GETPWNAM
,
155 BAIL_ON_WBC_ERROR(wbc_status
);
157 *pwd
= copy_passwd_entry(&response
.data
.pw
);
158 BAIL_ON_PTR_ERROR(*pwd
, wbc_status
);
164 /* Fill in a struct passwd* for a domain user based on uid */
165 wbcErr
wbcGetpwuid(uid_t uid
, 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 request
.data
.uid
= uid
;
183 wbc_status
= wbcRequestResponse(WINBINDD_GETPWUID
,
186 BAIL_ON_WBC_ERROR(wbc_status
);
188 *pwd
= copy_passwd_entry(&response
.data
.pw
);
189 BAIL_ON_PTR_ERROR(*pwd
, wbc_status
);
195 /* Fill in a struct passwd* for a domain user based on sid */
196 wbcErr
wbcGetpwsid(struct wbcDomainSid
*sid
, struct passwd
**pwd
)
198 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
199 struct winbindd_request request
;
200 struct winbindd_response response
;
201 char * sid_string
= NULL
;
204 wbc_status
= WBC_ERR_INVALID_PARAM
;
205 BAIL_ON_WBC_ERROR(wbc_status
);
208 wbc_status
= wbcSidToString(sid
, &sid_string
);
209 BAIL_ON_WBC_ERROR(wbc_status
);
211 /* Initialize request */
213 ZERO_STRUCT(request
);
214 ZERO_STRUCT(response
);
216 strncpy(request
.data
.sid
, sid_string
, sizeof(request
.data
.sid
));
218 wbc_status
= wbcRequestResponse(WINBINDD_GETPWSID
,
221 BAIL_ON_WBC_ERROR(wbc_status
);
223 *pwd
= copy_passwd_entry(&response
.data
.pw
);
224 BAIL_ON_PTR_ERROR(*pwd
, wbc_status
);
228 wbcFreeMemory(sid_string
);
234 /* Fill in a struct passwd* for a domain user based on username */
235 wbcErr
wbcGetgrnam(const char *name
, struct group
**grp
)
237 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
238 struct winbindd_request request
;
239 struct winbindd_response response
;
241 /* Initialize request */
243 ZERO_STRUCT(request
);
244 ZERO_STRUCT(response
);
247 wbc_status
= WBC_ERR_INVALID_PARAM
;
248 BAIL_ON_WBC_ERROR(wbc_status
);
251 /* dst is already null terminated from the memset above */
253 strncpy(request
.data
.groupname
, name
, sizeof(request
.data
.groupname
)-1);
255 wbc_status
= wbcRequestResponse(WINBINDD_GETGRNAM
,
258 BAIL_ON_WBC_ERROR(wbc_status
);
260 *grp
= copy_group_entry(&response
.data
.gr
,
261 (char*)response
.extra_data
.data
);
262 BAIL_ON_PTR_ERROR(*grp
, wbc_status
);
265 winbindd_free_response(&response
);
270 /* Fill in a struct passwd* for a domain user based on uid */
271 wbcErr
wbcGetgrgid(gid_t gid
, struct group
**grp
)
273 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
274 struct winbindd_request request
;
275 struct winbindd_response response
;
277 /* Initialize request */
279 ZERO_STRUCT(request
);
280 ZERO_STRUCT(response
);
283 wbc_status
= WBC_ERR_INVALID_PARAM
;
284 BAIL_ON_WBC_ERROR(wbc_status
);
287 request
.data
.gid
= gid
;
289 wbc_status
= wbcRequestResponse(WINBINDD_GETGRGID
,
292 BAIL_ON_WBC_ERROR(wbc_status
);
294 *grp
= copy_group_entry(&response
.data
.gr
,
295 (char*)response
.extra_data
.data
);
296 BAIL_ON_PTR_ERROR(*grp
, wbc_status
);
299 winbindd_free_response(&response
);
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 winbindd_free_response(&pw_response
);
329 ZERO_STRUCT(pw_response
);
331 wbc_status
= wbcRequestResponse(WINBINDD_SETPWENT
,
333 BAIL_ON_WBC_ERROR(wbc_status
);
339 /* Close the passwd iterator */
340 wbcErr
wbcEndpwent(void)
342 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
344 if (pw_cache_size
> 0) {
345 pw_cache_idx
= pw_cache_size
= 0;
346 winbindd_free_response(&pw_response
);
349 wbc_status
= wbcRequestResponse(WINBINDD_ENDPWENT
,
351 BAIL_ON_WBC_ERROR(wbc_status
);
357 /* Return the next struct passwd* entry from the pwent iterator */
358 wbcErr
wbcGetpwent(struct passwd
**pwd
)
360 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
361 struct winbindd_request request
;
362 struct winbindd_pw
*wb_pw
;
364 /* If there's a cached result, return that. */
365 if (pw_cache_idx
< pw_cache_size
) {
369 /* Otherwise, query winbindd for some entries. */
373 winbindd_free_response(&pw_response
);
375 ZERO_STRUCT(request
);
376 request
.data
.num_entries
= MAX_GETPWENT_USERS
;
378 wbc_status
= wbcRequestResponse(WINBINDD_GETPWENT
, &request
,
381 BAIL_ON_WBC_ERROR(wbc_status
);
383 pw_cache_size
= pw_response
.data
.num_entries
;
387 wb_pw
= (struct winbindd_pw
*) pw_response
.extra_data
.data
;
389 *pwd
= copy_passwd_entry(&wb_pw
[pw_cache_idx
]);
391 BAIL_ON_PTR_ERROR(*pwd
, wbc_status
);
399 /** @brief Number of cached group structs
402 static uint32_t gr_cache_size
;
404 /** @brief Position of the grent context
407 static uint32_t gr_cache_idx
;
409 /** @brief Winbindd response containing the group structs
412 static struct winbindd_response gr_response
;
414 /* Reset the group iterator */
415 wbcErr
wbcSetgrent(void)
417 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
419 if (gr_cache_size
> 0) {
420 gr_cache_idx
= gr_cache_size
= 0;
421 winbindd_free_response(&gr_response
);
424 ZERO_STRUCT(gr_response
);
426 wbc_status
= wbcRequestResponse(WINBINDD_SETGRENT
,
428 BAIL_ON_WBC_ERROR(wbc_status
);
434 /* Close the group iterator */
435 wbcErr
wbcEndgrent(void)
437 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
439 if (gr_cache_size
> 0) {
440 gr_cache_idx
= gr_cache_size
= 0;
441 winbindd_free_response(&gr_response
);
444 wbc_status
= wbcRequestResponse(WINBINDD_ENDGRENT
,
446 BAIL_ON_WBC_ERROR(wbc_status
);
452 /* Return the next struct group* entry from the pwent iterator */
453 wbcErr
wbcGetgrent(struct group
**grp
)
455 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
456 struct winbindd_request request
;
457 struct winbindd_gr
*wb_gr
;
460 /* If there's a cached result, return that. */
461 if (gr_cache_idx
< gr_cache_size
) {
465 /* Otherwise, query winbindd for some entries. */
469 winbindd_free_response(&gr_response
);
471 ZERO_STRUCT(request
);
472 request
.data
.num_entries
= MAX_GETGRENT_GROUPS
;
474 wbc_status
= wbcRequestResponse(WINBINDD_GETGRENT
, &request
,
477 BAIL_ON_WBC_ERROR(wbc_status
);
479 gr_cache_size
= gr_response
.data
.num_entries
;
483 wb_gr
= (struct winbindd_gr
*) gr_response
.extra_data
.data
;
485 mem_ofs
= wb_gr
[gr_cache_idx
].gr_mem_ofs
+
486 gr_cache_size
* sizeof(struct winbindd_gr
);
488 *grp
= copy_group_entry(&wb_gr
[gr_cache_idx
],
489 ((char *)gr_response
.extra_data
.data
)+mem_ofs
);
491 BAIL_ON_PTR_ERROR(*grp
, wbc_status
);
499 /* Return the next struct group* entry from the pwent iterator */
500 wbcErr
wbcGetgrlist(struct group
**grp
)
502 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
503 struct winbindd_request request
;
504 struct winbindd_gr
*wb_gr
;
506 /* If there's a cached result, return that. */
507 if (gr_cache_idx
< gr_cache_size
) {
511 /* Otherwise, query winbindd for some entries. */
515 winbindd_free_response(&gr_response
);
516 ZERO_STRUCT(gr_response
);
518 ZERO_STRUCT(request
);
519 request
.data
.num_entries
= MAX_GETGRENT_GROUPS
;
521 wbc_status
= wbcRequestResponse(WINBINDD_GETGRLST
, &request
,
524 BAIL_ON_WBC_ERROR(wbc_status
);
526 gr_cache_size
= gr_response
.data
.num_entries
;
530 wb_gr
= (struct winbindd_gr
*) gr_response
.extra_data
.data
;
532 *grp
= copy_group_entry(&wb_gr
[gr_cache_idx
], NULL
);
534 BAIL_ON_PTR_ERROR(*grp
, wbc_status
);
542 /* Return the unix group array belonging to the given user */
543 wbcErr
wbcGetGroups(const char *account
,
544 uint32_t *num_groups
,
547 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
548 struct winbindd_request request
;
549 struct winbindd_response response
;
551 gid_t
*groups
= NULL
;
553 /* Initialize request */
555 ZERO_STRUCT(request
);
556 ZERO_STRUCT(response
);
559 wbc_status
= WBC_ERR_INVALID_PARAM
;
560 BAIL_ON_WBC_ERROR(wbc_status
);
565 strncpy(request
.data
.username
, account
, sizeof(request
.data
.username
)-1);
567 wbc_status
= wbcRequestResponse(WINBINDD_GETGROUPS
,
570 BAIL_ON_WBC_ERROR(wbc_status
);
572 groups
= talloc_array(NULL
, gid_t
, response
.data
.num_entries
);
573 BAIL_ON_PTR_ERROR(groups
, wbc_status
);
575 for (i
= 0; i
< response
.data
.num_entries
; i
++) {
576 groups
[i
] = ((gid_t
*)response
.extra_data
.data
)[i
];
579 *num_groups
= response
.data
.num_entries
;
583 wbc_status
= WBC_ERR_SUCCESS
;
586 winbindd_free_response(&response
);