source: vendor/current/nsswitch/libwbclient/wbc_pwd.c@ 740

Last change on this file since 740 was 740, checked in by Silvan Scherrer, 12 years ago

Samba Server: update vendor to 3.6.0

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