/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- copy_passwd_entry
- copy_group_entry
- wbcGetpwnam
- wbcGetpwuid
- wbcGetpwsid
- wbcGetgrnam
- wbcGetgrgid
- wbcSetpwent
- wbcEndpwent
- wbcGetpwent
- wbcSetgrent
- wbcEndgrent
- wbcGetgrent
- wbcGetgrlist
- wbcGetGroups
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
41 static struct passwd *copy_passwd_entry(struct winbindd_pw *p)
/* [<][>][^][v][top][bottom][index][help] */
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
67 done:
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
80 static struct group *copy_group_entry(struct winbindd_gr *g,
/* [<][>][^][v][top][bottom][index][help] */
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
120 done:
121 if (!WBC_ERROR_IS_OK(wbc_status)) {
122 talloc_free(grp);
123 grp = NULL;
124 }
125
126 return grp;
127 }
128
129 /* Fill in a struct passwd* for a domain user based on username */
130 wbcErr wbcGetpwnam(const char *name, struct passwd **pwd)
/* [<][>][^][v][top][bottom][index][help] */
131 {
132 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
133 struct winbindd_request request;
134 struct winbindd_response response;
135
136 if (!name || !pwd) {
137 wbc_status = WBC_ERR_INVALID_PARAM;
138 BAIL_ON_WBC_ERROR(wbc_status);
139 }
140
141 /* Initialize request */
142
143 ZERO_STRUCT(request);
144 ZERO_STRUCT(response);
145
146 /* dst is already null terminated from the memset above */
147
148 strncpy(request.data.username, name, sizeof(request.data.username)-1);
149
150 wbc_status = wbcRequestResponse(WINBINDD_GETPWNAM,
151 &request,
152 &response);
153 BAIL_ON_WBC_ERROR(wbc_status);
154
155 *pwd = copy_passwd_entry(&response.data.pw);
156 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
157
158 done:
159 return wbc_status;
160 }
161
162 /* Fill in a struct passwd* for a domain user based on uid */
163 wbcErr wbcGetpwuid(uid_t uid, struct passwd **pwd)
/* [<][>][^][v][top][bottom][index][help] */
164 {
165 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
166 struct winbindd_request request;
167 struct winbindd_response response;
168
169 if (!pwd) {
170 wbc_status = WBC_ERR_INVALID_PARAM;
171 BAIL_ON_WBC_ERROR(wbc_status);
172 }
173
174 /* Initialize request */
175
176 ZERO_STRUCT(request);
177 ZERO_STRUCT(response);
178
179 request.data.uid = uid;
180
181 wbc_status = wbcRequestResponse(WINBINDD_GETPWUID,
182 &request,
183 &response);
184 BAIL_ON_WBC_ERROR(wbc_status);
185
186 *pwd = copy_passwd_entry(&response.data.pw);
187 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
188
189 done:
190 return wbc_status;
191 }
192
193 /* Fill in a struct passwd* for a domain user based on sid */
194 wbcErr wbcGetpwsid(struct wbcDomainSid *sid, struct passwd **pwd)
/* [<][>][^][v][top][bottom][index][help] */
195 {
196 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
197 struct winbindd_request request;
198 struct winbindd_response response;
199 char * sid_string = NULL;
200
201 if (!pwd) {
202 wbc_status = WBC_ERR_INVALID_PARAM;
203 BAIL_ON_WBC_ERROR(wbc_status);
204 }
205
206 wbc_status = wbcSidToString(sid, &sid_string);
207 BAIL_ON_WBC_ERROR(wbc_status);
208
209 /* Initialize request */
210
211 ZERO_STRUCT(request);
212 ZERO_STRUCT(response);
213
214 strncpy(request.data.sid, sid_string, sizeof(request.data.sid));
215
216 wbc_status = wbcRequestResponse(WINBINDD_GETPWSID,
217 &request,
218 &response);
219 BAIL_ON_WBC_ERROR(wbc_status);
220
221 *pwd = copy_passwd_entry(&response.data.pw);
222 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
223
224 done:
225 if (sid_string) {
226 wbcFreeMemory(sid_string);
227 }
228
229 return wbc_status;
230 }
231
232 /* Fill in a struct passwd* for a domain user based on username */
233 wbcErr wbcGetgrnam(const char *name, struct group **grp)
/* [<][>][^][v][top][bottom][index][help] */
234 {
235 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
236 struct winbindd_request request;
237 struct winbindd_response response;
238
239 /* Initialize request */
240
241 ZERO_STRUCT(request);
242 ZERO_STRUCT(response);
243
244 if (!name || !grp) {
245 wbc_status = WBC_ERR_INVALID_PARAM;
246 BAIL_ON_WBC_ERROR(wbc_status);
247 }
248
249 /* dst is already null terminated from the memset above */
250
251 strncpy(request.data.groupname, name, sizeof(request.data.groupname)-1);
252
253 wbc_status = wbcRequestResponse(WINBINDD_GETGRNAM,
254 &request,
255 &response);
256 BAIL_ON_WBC_ERROR(wbc_status);
257
258 *grp = copy_group_entry(&response.data.gr,
259 (char*)response.extra_data.data);
260 BAIL_ON_PTR_ERROR(*grp, wbc_status);
261
262 done:
263 if (response.extra_data.data)
264 free(response.extra_data.data);
265
266 return wbc_status;
267 }
268
269 /* Fill in a struct passwd* for a domain user based on uid */
270 wbcErr wbcGetgrgid(gid_t gid, struct group **grp)
/* [<][>][^][v][top][bottom][index][help] */
271 {
272 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
273 struct winbindd_request request;
274 struct winbindd_response response;
275
276 /* Initialize request */
277
278 ZERO_STRUCT(request);
279 ZERO_STRUCT(response);
280
281 if (!grp) {
282 wbc_status = WBC_ERR_INVALID_PARAM;
283 BAIL_ON_WBC_ERROR(wbc_status);
284 }
285
286 request.data.gid = gid;
287
288 wbc_status = wbcRequestResponse(WINBINDD_GETGRGID,
289 &request,
290 &response);
291 BAIL_ON_WBC_ERROR(wbc_status);
292
293 *grp = copy_group_entry(&response.data.gr,
294 (char*)response.extra_data.data);
295 BAIL_ON_PTR_ERROR(*grp, wbc_status);
296
297 done:
298 if (response.extra_data.data)
299 free(response.extra_data.data);
300
301 return wbc_status;
302 }
303
304 /** @brief Number of cached passwd structs
305 *
306 */
307 static uint32_t pw_cache_size;
308
309 /** @brief Position of the pwent context
310 *
311 */
312 static uint32_t pw_cache_idx;
313
314 /** @brief Winbindd response containing the passwd structs
315 *
316 */
317 static struct winbindd_response pw_response;
318
319 /* Reset the passwd iterator */
320 wbcErr wbcSetpwent(void)
/* [<][>][^][v][top][bottom][index][help] */
321 {
322 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
323
324 if (pw_cache_size > 0) {
325 pw_cache_idx = pw_cache_size = 0;
326 if (pw_response.extra_data.data) {
327 free(pw_response.extra_data.data);
328 }
329 }
330
331 ZERO_STRUCT(pw_response);
332
333 wbc_status = wbcRequestResponse(WINBINDD_SETPWENT,
334 NULL, NULL);
335 BAIL_ON_WBC_ERROR(wbc_status);
336
337 done:
338 return wbc_status;
339 }
340
341 /* Close the passwd iterator */
342 wbcErr wbcEndpwent(void)
/* [<][>][^][v][top][bottom][index][help] */
343 {
344 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
345
346 if (pw_cache_size > 0) {
347 pw_cache_idx = pw_cache_size = 0;
348 if (pw_response.extra_data.data) {
349 free(pw_response.extra_data.data);
350 }
351 }
352
353 wbc_status = wbcRequestResponse(WINBINDD_ENDPWENT,
354 NULL, NULL);
355 BAIL_ON_WBC_ERROR(wbc_status);
356
357 done:
358 return wbc_status;
359 }
360
361 /* Return the next struct passwd* entry from the pwent iterator */
362 wbcErr wbcGetpwent(struct passwd **pwd)
/* [<][>][^][v][top][bottom][index][help] */
363 {
364 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
365 struct winbindd_request request;
366 struct winbindd_pw *wb_pw;
367
368 /* If there's a cached result, return that. */
369 if (pw_cache_idx < pw_cache_size) {
370 goto return_result;
371 }
372
373 /* Otherwise, query winbindd for some entries. */
374
375 pw_cache_idx = 0;
376
377 if (pw_response.extra_data.data) {
378 free(pw_response.extra_data.data);
379 ZERO_STRUCT(pw_response);
380 }
381
382 ZERO_STRUCT(request);
383 request.data.num_entries = MAX_GETPWENT_USERS;
384
385 wbc_status = wbcRequestResponse(WINBINDD_GETPWENT, &request,
386 &pw_response);
387
388 BAIL_ON_WBC_ERROR(wbc_status);
389
390 pw_cache_size = pw_response.data.num_entries;
391
392 return_result:
393
394 wb_pw = (struct winbindd_pw *) pw_response.extra_data.data;
395
396 *pwd = copy_passwd_entry(&wb_pw[pw_cache_idx]);
397
398 BAIL_ON_PTR_ERROR(*pwd, wbc_status);
399
400 pw_cache_idx++;
401
402 done:
403 return wbc_status;
404 }
405
406 /** @brief Number of cached group structs
407 *
408 */
409 static uint32_t gr_cache_size;
410
411 /** @brief Position of the grent context
412 *
413 */
414 static uint32_t gr_cache_idx;
415
416 /** @brief Winbindd response containing the group structs
417 *
418 */
419 static struct winbindd_response gr_response;
420
421 /* Reset the group iterator */
422 wbcErr wbcSetgrent(void)
/* [<][>][^][v][top][bottom][index][help] */
423 {
424 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
425
426 if (gr_cache_size > 0) {
427 gr_cache_idx = gr_cache_size = 0;
428 if (gr_response.extra_data.data) {
429 free(gr_response.extra_data.data);
430 }
431 }
432
433 ZERO_STRUCT(gr_response);
434
435 wbc_status = wbcRequestResponse(WINBINDD_SETGRENT,
436 NULL, NULL);
437 BAIL_ON_WBC_ERROR(wbc_status);
438
439 done:
440 return wbc_status;
441 }
442
443 /* Close the group iterator */
444 wbcErr wbcEndgrent(void)
/* [<][>][^][v][top][bottom][index][help] */
445 {
446 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
447
448 if (gr_cache_size > 0) {
449 gr_cache_idx = gr_cache_size = 0;
450 if (gr_response.extra_data.data) {
451 free(gr_response.extra_data.data);
452 }
453 }
454
455 wbc_status = wbcRequestResponse(WINBINDD_ENDGRENT,
456 NULL, NULL);
457 BAIL_ON_WBC_ERROR(wbc_status);
458
459 done:
460 return wbc_status;
461 }
462
463 /* Return the next struct group* entry from the pwent iterator */
464 wbcErr wbcGetgrent(struct group **grp)
/* [<][>][^][v][top][bottom][index][help] */
465 {
466 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
467 struct winbindd_request request;
468 struct winbindd_gr *wb_gr;
469 uint32_t mem_ofs;
470
471 /* If there's a cached result, return that. */
472 if (gr_cache_idx < gr_cache_size) {
473 goto return_result;
474 }
475
476 /* Otherwise, query winbindd for some entries. */
477
478 gr_cache_idx = 0;
479
480 if (gr_response.extra_data.data) {
481 free(gr_response.extra_data.data);
482 ZERO_STRUCT(gr_response);
483 }
484
485 ZERO_STRUCT(request);
486 request.data.num_entries = MAX_GETGRENT_GROUPS;
487
488 wbc_status = wbcRequestResponse(WINBINDD_GETGRENT, &request,
489 &gr_response);
490
491 BAIL_ON_WBC_ERROR(wbc_status);
492
493 gr_cache_size = gr_response.data.num_entries;
494
495 return_result:
496
497 wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
498
499 mem_ofs = wb_gr[gr_cache_idx].gr_mem_ofs +
500 gr_cache_size * sizeof(struct winbindd_gr);
501
502 *grp = copy_group_entry(&wb_gr[gr_cache_idx],
503 ((char *)gr_response.extra_data.data)+mem_ofs);
504
505 BAIL_ON_PTR_ERROR(*grp, wbc_status);
506
507 gr_cache_idx++;
508
509 done:
510 return wbc_status;
511 }
512
513 /* Return the next struct group* entry from the pwent iterator */
514 wbcErr wbcGetgrlist(struct group **grp)
/* [<][>][^][v][top][bottom][index][help] */
515 {
516 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
517 struct winbindd_request request;
518 struct winbindd_gr *wb_gr;
519
520 /* If there's a cached result, return that. */
521 if (gr_cache_idx < gr_cache_size) {
522 goto return_result;
523 }
524
525 /* Otherwise, query winbindd for some entries. */
526
527 gr_cache_idx = 0;
528
529 if (gr_response.extra_data.data) {
530 free(gr_response.extra_data.data);
531 ZERO_STRUCT(gr_response);
532 }
533
534 ZERO_STRUCT(request);
535 request.data.num_entries = MAX_GETGRENT_GROUPS;
536
537 wbc_status = wbcRequestResponse(WINBINDD_GETGRLST, &request,
538 &gr_response);
539
540 BAIL_ON_WBC_ERROR(wbc_status);
541
542 gr_cache_size = gr_response.data.num_entries;
543
544 return_result:
545
546 wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
547
548 *grp = copy_group_entry(&wb_gr[gr_cache_idx], NULL);
549
550 BAIL_ON_PTR_ERROR(*grp, wbc_status);
551
552 gr_cache_idx++;
553
554 done:
555 return wbc_status;
556 }
557
558 /* Return the unix group array belonging to the given user */
559 wbcErr wbcGetGroups(const char *account,
/* [<][>][^][v][top][bottom][index][help] */
560 uint32_t *num_groups,
561 gid_t **_groups)
562 {
563 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
564 struct winbindd_request request;
565 struct winbindd_response response;
566 uint32_t i;
567 gid_t *groups = NULL;
568
569 /* Initialize request */
570
571 ZERO_STRUCT(request);
572 ZERO_STRUCT(response);
573
574 if (!account) {
575 wbc_status = WBC_ERR_INVALID_PARAM;
576 BAIL_ON_WBC_ERROR(wbc_status);
577 }
578
579 /* Send request */
580
581 strncpy(request.data.username, account, sizeof(request.data.username)-1);
582
583 wbc_status = wbcRequestResponse(WINBINDD_GETGROUPS,
584 &request,
585 &response);
586 BAIL_ON_WBC_ERROR(wbc_status);
587
588 groups = talloc_array(NULL, gid_t, response.data.num_entries);
589 BAIL_ON_PTR_ERROR(groups, wbc_status);
590
591 for (i = 0; i < response.data.num_entries; i++) {
592 groups[i] = ((gid_t *)response.extra_data.data)[i];
593 }
594
595 *num_groups = response.data.num_entries;
596 *_groups = groups;
597 groups = NULL;
598
599 wbc_status = WBC_ERR_SUCCESS;
600
601 done:
602 if (response.extra_data.data) {
603 free(response.extra_data.data);
604 }
605 if (groups) {
606 talloc_free(groups);
607 }
608
609 return wbc_status;
610 }