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

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

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