source: branches/samba-3.3.x/source/nsswitch/libwbclient/wbc_pwd.c

Last change on this file was 206, checked in by Herwig Bauernfeind, 16 years ago

Import Samba 3.3 branch at 3.0.0 level (psmedley's port)

File size: 13.3 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 Winbind client API
5
6 Copyright (C) Gerald (Jerry) Carter 2007
7
8
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.
13
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.
18
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/>.
21*/
22
23/* Required Headers */
24
25#include "libwbclient.h"
26
27/** @brief The maximum number of pwent structs to get from winbindd
28 *
29 */
30#define MAX_GETPWENT_USERS 500
31
32/** @brief The maximum number of grent structs to get from winbindd
33 *
34 */
35#define MAX_GETGRENT_GROUPS 500
36
37/**
38 *
39 **/
40
41static struct passwd *copy_passwd_entry(struct winbindd_pw *p)
42{
43 struct passwd *pwd = NULL;
44 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
45
46 pwd = talloc(NULL, struct passwd);
47 BAIL_ON_PTR_ERROR(pwd, wbc_status);
48
49 pwd->pw_name = talloc_strdup(pwd,p->pw_name);
50 BAIL_ON_PTR_ERROR(pwd->pw_name, wbc_status);
51
52 pwd->pw_passwd = talloc_strdup(pwd, p->pw_passwd);
53 BAIL_ON_PTR_ERROR(pwd->pw_passwd, wbc_status);
54
55 pwd->pw_gecos = talloc_strdup(pwd, p->pw_gecos);
56 BAIL_ON_PTR_ERROR(pwd->pw_gecos, wbc_status);
57
58 pwd->pw_shell = talloc_strdup(pwd, p->pw_shell);
59 BAIL_ON_PTR_ERROR(pwd->pw_shell, wbc_status);
60
61 pwd->pw_dir = talloc_strdup(pwd, p->pw_dir);
62 BAIL_ON_PTR_ERROR(pwd->pw_dir, wbc_status);
63
64 pwd->pw_uid = p->pw_uid;
65 pwd->pw_gid = p->pw_gid;
66
67done:
68 if (!WBC_ERROR_IS_OK(wbc_status)) {
69 talloc_free(pwd);
70 pwd = NULL;
71 }
72
73 return pwd;
74}
75
76/**
77 *
78 **/
79
80static struct group *copy_group_entry(struct winbindd_gr *g,
81 char *mem_buf)
82{
83 struct group *grp = NULL;
84 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
85 int i;
86 char *mem_p, *mem_q;
87
88 grp = talloc(NULL, struct group);
89 BAIL_ON_PTR_ERROR(grp, wbc_status);
90
91 grp->gr_name = talloc_strdup(grp, g->gr_name);
92 BAIL_ON_PTR_ERROR(grp->gr_name, wbc_status);
93
94 grp->gr_passwd = talloc_strdup(grp, g->gr_passwd);
95 BAIL_ON_PTR_ERROR(grp->gr_passwd, wbc_status);
96
97 grp->gr_gid = g->gr_gid;
98
99 grp->gr_mem = talloc_array(grp, char*, g->num_gr_mem+1);
100
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) {
104 *mem_q = '\0';
105 }
106
107 grp->gr_mem[i] = talloc_strdup(grp, mem_p);
108 BAIL_ON_PTR_ERROR(grp->gr_mem[i], wbc_status);
109
110 if (mem_q == NULL) {
111 i += 1;
112 break;
113 }
114 mem_p = mem_q + 1;
115 }
116 grp->gr_mem[i] = NULL;
117
118 wbc_status = WBC_ERR_SUCCESS;
119
120done:
121 if (!WBC_ERROR_IS_OK(wbc_status)) {
122 talloc_free(grp);
123 grp = NULL;
124 }
125
126 return grp;
127}
128
129/** @brief Fill in a struct passwd* for a domain user based
130 * on username
131 *
132 * @param *name Username to lookup
133 * @param **pwd Pointer to resulting struct passwd* from the query.
134 *
135 * @return #wbcErr
136 **/
137
138wbcErr wbcGetpwnam(const char *name, struct passwd **pwd)
139{
140 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
141 struct winbindd_request request;
142 struct winbindd_response response;
143
144 if (!name || !pwd) {
145 wbc_status = WBC_ERR_INVALID_PARAM;
146 BAIL_ON_WBC_ERROR(wbc_status);
147 }
148
149 /* Initialize request */
150
151 ZERO_STRUCT(request);
152 ZERO_STRUCT(response);
153
154 /* dst is already null terminated from the memset above */
155
156 strncpy(request.data.username, name, sizeof(request.data.username)-1);
157
158 wbc_status = wbcRequestResponse(WINBINDD_GETPWNAM,
159 &request,
160 &response);
161 BAIL_ON_WBC_ERROR(wbc_status);
162
163 *pwd = copy_passwd_entry(&response.data.pw);
164 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
165
166 done:
167 return wbc_status;
168}
169
170/** @brief Fill in a struct passwd* for a domain user based
171 * on uid
172 *
173 * @param uid Uid to lookup
174 * @param **pwd Pointer to resulting struct passwd* from the query.
175 *
176 * @return #wbcErr
177 **/
178
179wbcErr wbcGetpwuid(uid_t uid, struct passwd **pwd)
180{
181 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
182 struct winbindd_request request;
183 struct winbindd_response response;
184
185 if (!pwd) {
186 wbc_status = WBC_ERR_INVALID_PARAM;
187 BAIL_ON_WBC_ERROR(wbc_status);
188 }
189
190 /* Initialize request */
191
192 ZERO_STRUCT(request);
193 ZERO_STRUCT(response);
194
195 request.data.uid = uid;
196
197 wbc_status = wbcRequestResponse(WINBINDD_GETPWUID,
198 &request,
199 &response);
200 BAIL_ON_WBC_ERROR(wbc_status);
201
202 *pwd = copy_passwd_entry(&response.data.pw);
203 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
204
205 done:
206 return wbc_status;
207}
208
209/** @brief Fill in a struct passwd* for a domain user based
210 * on username
211 *
212 * @param *name Username to lookup
213 * @param **grp Pointer to resulting struct group* from the query.
214 *
215 * @return #wbcErr
216 **/
217
218wbcErr wbcGetgrnam(const char *name, struct group **grp)
219{
220 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
221 struct winbindd_request request;
222 struct winbindd_response response;
223
224 /* Initialize request */
225
226 ZERO_STRUCT(request);
227 ZERO_STRUCT(response);
228
229 if (!name || !grp) {
230 wbc_status = WBC_ERR_INVALID_PARAM;
231 BAIL_ON_WBC_ERROR(wbc_status);
232 }
233
234 /* dst is already null terminated from the memset above */
235
236 strncpy(request.data.groupname, name, sizeof(request.data.groupname)-1);
237
238 wbc_status = wbcRequestResponse(WINBINDD_GETGRNAM,
239 &request,
240 &response);
241 BAIL_ON_WBC_ERROR(wbc_status);
242
243 *grp = copy_group_entry(&response.data.gr,
244 (char*)response.extra_data.data);
245 BAIL_ON_PTR_ERROR(*grp, wbc_status);
246
247 done:
248 if (response.extra_data.data)
249 free(response.extra_data.data);
250
251 return wbc_status;
252}
253
254/** @brief Fill in a struct passwd* for a domain user based
255 * on uid
256 *
257 * @param gid Uid to lookup
258 * @param **grp Pointer to resulting struct group* from the query.
259 *
260 * @return #wbcErr
261 **/
262
263wbcErr wbcGetgrgid(gid_t gid, struct group **grp)
264{
265 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
266 struct winbindd_request request;
267 struct winbindd_response response;
268
269 /* Initialize request */
270
271 ZERO_STRUCT(request);
272 ZERO_STRUCT(response);
273
274 if (!grp) {
275 wbc_status = WBC_ERR_INVALID_PARAM;
276 BAIL_ON_WBC_ERROR(wbc_status);
277 }
278
279 request.data.gid = gid;
280
281 wbc_status = wbcRequestResponse(WINBINDD_GETGRGID,
282 &request,
283 &response);
284 BAIL_ON_WBC_ERROR(wbc_status);
285
286 *grp = copy_group_entry(&response.data.gr,
287 (char*)response.extra_data.data);
288 BAIL_ON_PTR_ERROR(*grp, wbc_status);
289
290 done:
291 if (response.extra_data.data)
292 free(response.extra_data.data);
293
294 return wbc_status;
295}
296
297/** @brief Number of cached passwd structs
298 *
299 */
300static uint32_t pw_cache_size;
301
302/** @brief Position of the pwent context
303 *
304 */
305static uint32_t pw_cache_idx;
306
307/** @brief Winbindd response containing the passwd structs
308 *
309 */
310static struct winbindd_response pw_response;
311
312/** @brief Reset the passwd iterator
313 *
314 * @return #wbcErr
315 **/
316
317wbcErr wbcSetpwent(void)
318{
319 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
320
321 if (pw_cache_size > 0) {
322 pw_cache_idx = pw_cache_size = 0;
323 if (pw_response.extra_data.data) {
324 free(pw_response.extra_data.data);
325 }
326 }
327
328 ZERO_STRUCT(pw_response);
329
330 wbc_status = wbcRequestResponse(WINBINDD_SETPWENT,
331 NULL, NULL);
332 BAIL_ON_WBC_ERROR(wbc_status);
333
334 done:
335 return wbc_status;
336}
337
338/** @brief Close the passwd iterator
339 *
340 * @return #wbcErr
341 **/
342
343wbcErr wbcEndpwent(void)
344{
345 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
346
347 if (pw_cache_size > 0) {
348 pw_cache_idx = pw_cache_size = 0;
349 if (pw_response.extra_data.data) {
350 free(pw_response.extra_data.data);
351 }
352 }
353
354 wbc_status = wbcRequestResponse(WINBINDD_ENDPWENT,
355 NULL, NULL);
356 BAIL_ON_WBC_ERROR(wbc_status);
357
358 done:
359 return wbc_status;
360}
361
362/** @brief Return the next struct passwd* entry from the pwent iterator
363 *
364 * @param **pwd Pointer to resulting struct passwd* from the query.
365 *
366 * @return #wbcErr
367 **/
368
369wbcErr wbcGetpwent(struct passwd **pwd)
370{
371 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
372 struct winbindd_request request;
373 struct winbindd_pw *wb_pw;
374
375 /* If there's a cached result, return that. */
376 if (pw_cache_idx < pw_cache_size) {
377 goto return_result;
378 }
379
380 /* Otherwise, query winbindd for some entries. */
381
382 pw_cache_idx = 0;
383
384 if (pw_response.extra_data.data) {
385 free(pw_response.extra_data.data);
386 ZERO_STRUCT(pw_response);
387 }
388
389 ZERO_STRUCT(request);
390 request.data.num_entries = MAX_GETPWENT_USERS;
391
392 wbc_status = wbcRequestResponse(WINBINDD_GETPWENT, &request,
393 &pw_response);
394
395 BAIL_ON_WBC_ERROR(wbc_status);
396
397 pw_cache_size = pw_response.data.num_entries;
398
399return_result:
400
401 wb_pw = (struct winbindd_pw *) pw_response.extra_data.data;
402
403 *pwd = copy_passwd_entry(&wb_pw[pw_cache_idx]);
404
405 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
406
407 pw_cache_idx++;
408
409done:
410 return wbc_status;
411}
412
413/** @brief Number of cached group structs
414 *
415 */
416static uint32_t gr_cache_size;
417
418/** @brief Position of the grent context
419 *
420 */
421static uint32_t gr_cache_idx;
422
423/** @brief Winbindd response containing the group structs
424 *
425 */
426static struct winbindd_response gr_response;
427
428/** @brief Reset the group iterator
429 *
430 * @return #wbcErr
431 **/
432
433wbcErr wbcSetgrent(void)
434{
435 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
436
437 if (gr_cache_size > 0) {
438 gr_cache_idx = gr_cache_size = 0;
439 if (gr_response.extra_data.data) {
440 free(gr_response.extra_data.data);
441 }
442 }
443
444 ZERO_STRUCT(gr_response);
445
446 wbc_status = wbcRequestResponse(WINBINDD_SETGRENT,
447 NULL, NULL);
448 BAIL_ON_WBC_ERROR(wbc_status);
449
450 done:
451 return wbc_status;
452}
453
454/** @brief Close the group iterator
455 *
456 * @return #wbcErr
457 **/
458
459wbcErr wbcEndgrent(void)
460{
461 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
462
463 if (gr_cache_size > 0) {
464 gr_cache_idx = gr_cache_size = 0;
465 if (gr_response.extra_data.data) {
466 free(gr_response.extra_data.data);
467 }
468 }
469
470 wbc_status = wbcRequestResponse(WINBINDD_ENDGRENT,
471 NULL, NULL);
472 BAIL_ON_WBC_ERROR(wbc_status);
473
474 done:
475 return wbc_status;
476}
477
478/** @brief Return the next struct group* entry from the pwent iterator
479 *
480 * @param **grp Pointer to resulting struct group* from the query.
481 *
482 * @return #wbcErr
483 **/
484
485wbcErr wbcGetgrent(struct group **grp)
486{
487 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
488 struct winbindd_request request;
489 struct winbindd_gr *wb_gr;
490 uint32_t mem_ofs;
491
492 /* If there's a cached result, return that. */
493 if (gr_cache_idx < gr_cache_size) {
494 goto return_result;
495 }
496
497 /* Otherwise, query winbindd for some entries. */
498
499 gr_cache_idx = 0;
500
501 if (gr_response.extra_data.data) {
502 free(gr_response.extra_data.data);
503 ZERO_STRUCT(gr_response);
504 }
505
506 ZERO_STRUCT(request);
507 request.data.num_entries = MAX_GETGRENT_GROUPS;
508
509 wbc_status = wbcRequestResponse(WINBINDD_GETGRENT, &request,
510 &gr_response);
511
512 BAIL_ON_WBC_ERROR(wbc_status);
513
514 gr_cache_size = gr_response.data.num_entries;
515
516return_result:
517
518 wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
519
520 mem_ofs = wb_gr[gr_cache_idx].gr_mem_ofs +
521 gr_cache_size * sizeof(struct winbindd_gr);
522
523 *grp = copy_group_entry(&wb_gr[gr_cache_idx],
524 ((char *)gr_response.extra_data.data)+mem_ofs);
525
526 BAIL_ON_PTR_ERROR(*grp, wbc_status);
527
528 gr_cache_idx++;
529
530done:
531 return wbc_status;
532}
533
534/** @brief Return the next struct group* entry from the pwent iterator
535 *
536 * This is similar to #wbcGetgrent, just that the member list is empty
537 *
538 * @param **grp Pointer to resulting struct group* from the query.
539 *
540 * @return #wbcErr
541 **/
542
543wbcErr wbcGetgrlist(struct group **grp)
544{
545 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
546 struct winbindd_request request;
547 struct winbindd_gr *wb_gr;
548
549 /* If there's a cached result, return that. */
550 if (gr_cache_idx < gr_cache_size) {
551 goto return_result;
552 }
553
554 /* Otherwise, query winbindd for some entries. */
555
556 gr_cache_idx = 0;
557
558 if (gr_response.extra_data.data) {
559 free(gr_response.extra_data.data);
560 ZERO_STRUCT(gr_response);
561 }
562
563 ZERO_STRUCT(request);
564 request.data.num_entries = MAX_GETGRENT_GROUPS;
565
566 wbc_status = wbcRequestResponse(WINBINDD_GETGRLST, &request,
567 &gr_response);
568
569 BAIL_ON_WBC_ERROR(wbc_status);
570
571 gr_cache_size = gr_response.data.num_entries;
572
573return_result:
574
575 wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
576
577 *grp = copy_group_entry(&wb_gr[gr_cache_idx], NULL);
578
579 BAIL_ON_PTR_ERROR(*grp, wbc_status);
580
581 gr_cache_idx++;
582
583done:
584 return wbc_status;
585}
586
587/** @brief Return the unix group array belonging to the given user
588 *
589 * @param *account The given user name
590 * @param *num_groups Number of elements returned in the groups array
591 * @param **_groups Pointer to resulting gid_t array.
592 *
593 * @return #wbcErr
594 **/
595wbcErr wbcGetGroups(const char *account,
596 uint32_t *num_groups,
597 gid_t **_groups)
598{
599 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
600 struct winbindd_request request;
601 struct winbindd_response response;
602 uint32_t i;
603 gid_t *groups = NULL;
604
605 /* Initialize request */
606
607 ZERO_STRUCT(request);
608 ZERO_STRUCT(response);
609
610 if (!account) {
611 wbc_status = WBC_ERR_INVALID_PARAM;
612 BAIL_ON_WBC_ERROR(wbc_status);
613 }
614
615 /* Send request */
616
617 strncpy(request.data.username, account, sizeof(request.data.username)-1);
618
619 wbc_status = wbcRequestResponse(WINBINDD_GETGROUPS,
620 &request,
621 &response);
622 BAIL_ON_WBC_ERROR(wbc_status);
623
624 groups = talloc_array(NULL, gid_t, response.data.num_entries);
625 BAIL_ON_PTR_ERROR(groups, wbc_status);
626
627 for (i = 0; i < response.data.num_entries; i++) {
628 groups[i] = ((gid_t *)response.extra_data.data)[i];
629 }
630
631 *num_groups = response.data.num_entries;
632 *_groups = groups;
633 groups = NULL;
634
635 wbc_status = WBC_ERR_SUCCESS;
636
637 done:
638 if (response.extra_data.data) {
639 free(response.extra_data.data);
640 }
641 if (groups) {
642 talloc_free(groups);
643 }
644
645 return wbc_status;
646}
Note: See TracBrowser for help on using the repository browser.