Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Winbind client API
5 :
6 : Copyright (C) Gerald (Jerry) Carter 2007
7 : Copyright (C) Matthew Newton 2015
8 :
9 :
10 : This library is free software; you can redistribute it and/or
11 : modify it under the terms of the GNU Lesser General Public
12 : License as published by the Free Software Foundation; either
13 : version 3 of the License, or (at your option) any later version.
14 :
15 : This library is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 : Library General Public License for more details.
19 :
20 : You should have received a copy of the GNU Lesser General Public License
21 : along with this program. If not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : /* Required Headers */
25 :
26 : #include "replace.h"
27 : #include "libwbclient.h"
28 : #include "../winbind_client.h"
29 :
30 : /** @brief The maximum number of pwent structs to get from winbindd
31 : *
32 : */
33 : #define MAX_GETPWENT_USERS 500
34 :
35 : /** @brief The maximum number of grent structs to get from winbindd
36 : *
37 : */
38 : #define MAX_GETGRENT_GROUPS 500
39 :
40 : /**
41 : *
42 : **/
43 :
44 141833 : static void wbcPasswdDestructor(void *ptr)
45 : {
46 141833 : struct passwd *pw = (struct passwd *)ptr;
47 141833 : free(pw->pw_name);
48 141833 : free(pw->pw_passwd);
49 141833 : free(pw->pw_gecos);
50 141833 : free(pw->pw_shell);
51 141833 : free(pw->pw_dir);
52 141833 : }
53 :
54 141833 : static struct passwd *copy_passwd_entry(struct winbindd_pw *p)
55 : {
56 141833 : struct passwd *pw = NULL;
57 :
58 141833 : pw = (struct passwd *)wbcAllocateMemory(1, sizeof(struct passwd),
59 : wbcPasswdDestructor);
60 141833 : if (pw == NULL) {
61 0 : return NULL;
62 : }
63 141833 : pw->pw_name = strdup(p->pw_name);
64 141833 : if (pw->pw_name == NULL) {
65 0 : goto fail;
66 : }
67 141833 : pw->pw_passwd = strdup(p->pw_passwd);
68 141833 : if (pw->pw_passwd == NULL) {
69 0 : goto fail;
70 : }
71 141833 : pw->pw_gecos = strdup(p->pw_gecos);
72 141833 : if (pw->pw_gecos == NULL) {
73 0 : goto fail;
74 : }
75 141833 : pw->pw_shell = strdup(p->pw_shell);
76 141833 : if (pw->pw_shell == NULL) {
77 0 : goto fail;
78 : }
79 141833 : pw->pw_dir = strdup(p->pw_dir);
80 141833 : if (pw->pw_dir == NULL) {
81 0 : goto fail;
82 : }
83 141833 : pw->pw_uid = p->pw_uid;
84 141833 : pw->pw_gid = p->pw_gid;
85 141833 : return pw;
86 :
87 0 : fail:
88 0 : wbcFreeMemory(pw);
89 0 : return NULL;
90 : }
91 :
92 : /**
93 : *
94 : **/
95 :
96 28 : static void wbcGroupDestructor(void *ptr)
97 : {
98 28 : struct group *gr = (struct group *)ptr;
99 0 : int i;
100 :
101 28 : free(gr->gr_name);
102 28 : free(gr->gr_passwd);
103 :
104 : /* if the array was partly created this can be NULL */
105 28 : if (gr->gr_mem == NULL) {
106 0 : return;
107 : }
108 :
109 52 : for (i=0; gr->gr_mem[i] != NULL; i++) {
110 24 : free(gr->gr_mem[i]);
111 : }
112 28 : free(gr->gr_mem);
113 : }
114 :
115 28 : static struct group *copy_group_entry(struct winbindd_gr *g,
116 : char *mem_buf)
117 : {
118 28 : struct group *gr = NULL;
119 0 : int i;
120 0 : char *mem_p, *mem_q;
121 :
122 28 : gr = (struct group *)wbcAllocateMemory(
123 : 1, sizeof(struct group), wbcGroupDestructor);
124 28 : if (gr == NULL) {
125 0 : return NULL;
126 : }
127 :
128 28 : gr->gr_name = strdup(g->gr_name);
129 28 : if (gr->gr_name == NULL) {
130 0 : goto fail;
131 : }
132 28 : gr->gr_passwd = strdup(g->gr_passwd);
133 28 : if (gr->gr_passwd == NULL) {
134 0 : goto fail;
135 : }
136 28 : gr->gr_gid = g->gr_gid;
137 :
138 28 : gr->gr_mem = (char **)calloc(g->num_gr_mem+1, sizeof(char *));
139 28 : if (gr->gr_mem == NULL) {
140 0 : goto fail;
141 : }
142 :
143 28 : mem_p = mem_q = mem_buf;
144 48 : for (i=0; i<g->num_gr_mem && mem_p; i++) {
145 24 : mem_q = strchr(mem_p, ',');
146 24 : if (mem_q != NULL) {
147 20 : *mem_q = '\0';
148 : }
149 :
150 24 : gr->gr_mem[i] = strdup(mem_p);
151 24 : if (gr->gr_mem[i] == NULL) {
152 0 : goto fail;
153 : }
154 :
155 24 : if (mem_q == NULL) {
156 4 : i += 1;
157 4 : break;
158 : }
159 20 : mem_p = mem_q + 1;
160 : }
161 28 : gr->gr_mem[i] = NULL;
162 :
163 28 : return gr;
164 :
165 0 : fail:
166 0 : wbcFreeMemory(gr);
167 0 : return NULL;
168 : }
169 :
170 : /* Fill in a struct passwd* for a domain user based on username */
171 : _PUBLIC_
172 141608 : wbcErr wbcCtxGetpwnam(struct wbcContext *ctx,
173 : const char *name, struct passwd **pwd)
174 : {
175 141608 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
176 0 : struct winbindd_request request;
177 0 : struct winbindd_response response;
178 :
179 141608 : if (!name || !pwd) {
180 0 : wbc_status = WBC_ERR_INVALID_PARAM;
181 0 : BAIL_ON_WBC_ERROR(wbc_status);
182 : }
183 :
184 : /* Initialize request */
185 :
186 141608 : ZERO_STRUCT(request);
187 141608 : ZERO_STRUCT(response);
188 :
189 : /* dst is already null terminated from the memset above */
190 :
191 141608 : strncpy(request.data.username, name, sizeof(request.data.username)-1);
192 :
193 141608 : wbc_status = wbcRequestResponse(ctx, WINBINDD_GETPWNAM,
194 : &request,
195 : &response);
196 141607 : BAIL_ON_WBC_ERROR(wbc_status);
197 :
198 141603 : *pwd = copy_passwd_entry(&response.data.pw);
199 141603 : BAIL_ON_PTR_ERROR(*pwd, wbc_status);
200 :
201 141607 : done:
202 141607 : return wbc_status;
203 : }
204 :
205 : _PUBLIC_
206 141584 : wbcErr wbcGetpwnam(const char *name, struct passwd **pwd)
207 : {
208 141584 : return wbcCtxGetpwnam(NULL, name, pwd);
209 : }
210 :
211 : /* Fill in a struct passwd* for a domain user based on uid */
212 : _PUBLIC_
213 230 : wbcErr wbcCtxGetpwuid(struct wbcContext *ctx, uid_t uid, struct passwd **pwd)
214 : {
215 230 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
216 0 : struct winbindd_request request;
217 0 : struct winbindd_response response;
218 :
219 230 : if (!pwd) {
220 0 : wbc_status = WBC_ERR_INVALID_PARAM;
221 0 : BAIL_ON_WBC_ERROR(wbc_status);
222 : }
223 :
224 : /* Initialize request */
225 :
226 230 : ZERO_STRUCT(request);
227 230 : ZERO_STRUCT(response);
228 :
229 230 : request.data.uid = uid;
230 :
231 230 : wbc_status = wbcRequestResponse(ctx, WINBINDD_GETPWUID,
232 : &request,
233 : &response);
234 230 : BAIL_ON_WBC_ERROR(wbc_status);
235 :
236 230 : *pwd = copy_passwd_entry(&response.data.pw);
237 230 : BAIL_ON_PTR_ERROR(*pwd, wbc_status);
238 :
239 230 : done:
240 230 : return wbc_status;
241 : }
242 :
243 : _PUBLIC_
244 8 : wbcErr wbcGetpwuid(uid_t uid, struct passwd **pwd)
245 : {
246 8 : return wbcCtxGetpwuid(NULL, uid, pwd);
247 : }
248 :
249 : /* Fill in a struct passwd* for a domain user based on sid */
250 : _PUBLIC_
251 0 : wbcErr wbcCtxGetpwsid(struct wbcContext *ctx,
252 : struct wbcDomainSid *sid, struct passwd **pwd)
253 : {
254 0 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
255 0 : struct winbindd_request request;
256 0 : struct winbindd_response response;
257 :
258 0 : if (!pwd) {
259 0 : wbc_status = WBC_ERR_INVALID_PARAM;
260 0 : BAIL_ON_WBC_ERROR(wbc_status);
261 : }
262 :
263 : /* Initialize request */
264 :
265 0 : ZERO_STRUCT(request);
266 0 : ZERO_STRUCT(response);
267 :
268 0 : wbcSidToStringBuf(sid, request.data.sid, sizeof(request.data.sid));
269 :
270 0 : wbc_status = wbcRequestResponse(ctx, WINBINDD_GETPWSID,
271 : &request,
272 : &response);
273 0 : BAIL_ON_WBC_ERROR(wbc_status);
274 :
275 0 : *pwd = copy_passwd_entry(&response.data.pw);
276 0 : BAIL_ON_PTR_ERROR(*pwd, wbc_status);
277 :
278 0 : done:
279 0 : return wbc_status;
280 : }
281 :
282 : _PUBLIC_
283 0 : wbcErr wbcGetpwsid(struct wbcDomainSid *sid, struct passwd **pwd)
284 : {
285 0 : return wbcCtxGetpwsid(NULL, sid, pwd);
286 : }
287 :
288 : /* Fill in a struct passwd* for a domain user based on username */
289 : _PUBLIC_
290 28 : wbcErr wbcCtxGetgrnam(struct wbcContext *ctx,
291 : const char *name, struct group **grp)
292 : {
293 28 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
294 0 : struct winbindd_request request;
295 0 : struct winbindd_response response;
296 :
297 : /* Initialize request */
298 :
299 28 : ZERO_STRUCT(request);
300 28 : ZERO_STRUCT(response);
301 :
302 28 : if (!name || !grp) {
303 0 : wbc_status = WBC_ERR_INVALID_PARAM;
304 0 : BAIL_ON_WBC_ERROR(wbc_status);
305 : }
306 :
307 : /* dst is already null terminated from the memset above */
308 :
309 28 : strncpy(request.data.groupname, name, sizeof(request.data.groupname)-1);
310 :
311 28 : wbc_status = wbcRequestResponse(ctx, WINBINDD_GETGRNAM,
312 : &request,
313 : &response);
314 28 : BAIL_ON_WBC_ERROR(wbc_status);
315 :
316 40 : *grp = copy_group_entry(&response.data.gr,
317 20 : (char*)response.extra_data.data);
318 20 : BAIL_ON_PTR_ERROR(*grp, wbc_status);
319 :
320 28 : done:
321 28 : winbindd_free_response(&response);
322 :
323 28 : return wbc_status;
324 : }
325 :
326 : _PUBLIC_
327 28 : wbcErr wbcGetgrnam(const char *name, struct group **grp)
328 : {
329 28 : return wbcCtxGetgrnam(NULL, name, grp);
330 : }
331 :
332 : /* Fill in a struct passwd* for a domain user based on uid */
333 : _PUBLIC_
334 8 : wbcErr wbcCtxGetgrgid(struct wbcContext *ctx, gid_t gid, struct group **grp)
335 : {
336 8 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
337 0 : struct winbindd_request request;
338 0 : struct winbindd_response response;
339 :
340 : /* Initialize request */
341 :
342 8 : ZERO_STRUCT(request);
343 8 : ZERO_STRUCT(response);
344 :
345 8 : if (!grp) {
346 0 : wbc_status = WBC_ERR_INVALID_PARAM;
347 0 : BAIL_ON_WBC_ERROR(wbc_status);
348 : }
349 :
350 8 : request.data.gid = gid;
351 :
352 8 : wbc_status = wbcRequestResponse(ctx, WINBINDD_GETGRGID,
353 : &request,
354 : &response);
355 8 : BAIL_ON_WBC_ERROR(wbc_status);
356 :
357 16 : *grp = copy_group_entry(&response.data.gr,
358 8 : (char*)response.extra_data.data);
359 8 : BAIL_ON_PTR_ERROR(*grp, wbc_status);
360 :
361 8 : done:
362 8 : winbindd_free_response(&response);
363 :
364 8 : return wbc_status;
365 : }
366 :
367 : _PUBLIC_
368 8 : wbcErr wbcGetgrgid(gid_t gid, struct group **grp)
369 : {
370 8 : return wbcCtxGetgrgid(NULL, gid, grp);
371 : }
372 :
373 : /** @brief Winbindd response containing the passwd structs
374 : *
375 : */
376 : static struct winbindd_response pw_response;
377 :
378 : /* Reset the passwd iterator */
379 : _PUBLIC_
380 0 : wbcErr wbcCtxSetpwent(struct wbcContext *ctx)
381 : {
382 0 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
383 :
384 0 : if (!ctx) {
385 0 : ctx = wbcGetGlobalCtx();
386 : }
387 :
388 0 : if (ctx->pw_cache_size > 0) {
389 0 : ctx->pw_cache_idx = ctx->pw_cache_size = 0;
390 0 : winbindd_free_response(&pw_response);
391 : }
392 :
393 0 : ZERO_STRUCT(pw_response);
394 :
395 0 : wbc_status = wbcRequestResponse(ctx, WINBINDD_SETPWENT,
396 : NULL, NULL);
397 0 : BAIL_ON_WBC_ERROR(wbc_status);
398 :
399 0 : done:
400 0 : return wbc_status;
401 : }
402 :
403 : _PUBLIC_
404 0 : wbcErr wbcSetpwent(void)
405 : {
406 0 : return wbcCtxSetpwent(NULL);
407 : }
408 :
409 : /* Close the passwd iterator */
410 : _PUBLIC_
411 0 : wbcErr wbcCtxEndpwent(struct wbcContext *ctx)
412 : {
413 0 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
414 :
415 0 : if (!ctx) {
416 0 : ctx = wbcGetGlobalCtx();
417 : }
418 :
419 0 : if (ctx->pw_cache_size > 0) {
420 0 : ctx->pw_cache_idx = ctx->pw_cache_size = 0;
421 0 : winbindd_free_response(&pw_response);
422 : }
423 :
424 0 : wbc_status = wbcRequestResponse(ctx, WINBINDD_ENDPWENT,
425 : NULL, NULL);
426 0 : BAIL_ON_WBC_ERROR(wbc_status);
427 :
428 0 : done:
429 0 : return wbc_status;
430 : }
431 :
432 : _PUBLIC_
433 0 : wbcErr wbcEndpwent(void)
434 : {
435 0 : return wbcCtxEndpwent(NULL);
436 : }
437 :
438 : /* Return the next struct passwd* entry from the pwent iterator */
439 : _PUBLIC_
440 0 : wbcErr wbcCtxGetpwent(struct wbcContext *ctx, struct passwd **pwd)
441 : {
442 0 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
443 0 : struct winbindd_request request;
444 0 : struct winbindd_pw *wb_pw;
445 :
446 0 : if (!ctx) {
447 0 : ctx = wbcGetGlobalCtx();
448 : }
449 :
450 : /* If there's a cached result, return that. */
451 0 : if (ctx->pw_cache_idx < ctx->pw_cache_size) {
452 0 : goto return_result;
453 : }
454 :
455 : /* Otherwise, query winbindd for some entries. */
456 :
457 0 : ctx->pw_cache_idx = 0;
458 :
459 0 : winbindd_free_response(&pw_response);
460 :
461 0 : ZERO_STRUCT(request);
462 0 : request.data.num_entries = MAX_GETPWENT_USERS;
463 :
464 0 : wbc_status = wbcRequestResponse(ctx, WINBINDD_GETPWENT, &request,
465 : &pw_response);
466 :
467 0 : BAIL_ON_WBC_ERROR(wbc_status);
468 :
469 0 : ctx->pw_cache_size = pw_response.data.num_entries;
470 :
471 0 : return_result:
472 :
473 0 : wb_pw = (struct winbindd_pw *) pw_response.extra_data.data;
474 :
475 0 : *pwd = copy_passwd_entry(&wb_pw[ctx->pw_cache_idx]);
476 :
477 0 : BAIL_ON_PTR_ERROR(*pwd, wbc_status);
478 :
479 0 : ctx->pw_cache_idx++;
480 :
481 0 : done:
482 0 : return wbc_status;
483 : }
484 :
485 : _PUBLIC_
486 0 : wbcErr wbcGetpwent(struct passwd **pwd)
487 : {
488 0 : return wbcCtxGetpwent(NULL, pwd);
489 : }
490 :
491 : /** @brief Winbindd response containing the group structs
492 : *
493 : */
494 : static struct winbindd_response gr_response;
495 :
496 : /* Reset the group iterator */
497 : _PUBLIC_
498 0 : wbcErr wbcCtxSetgrent(struct wbcContext *ctx)
499 : {
500 0 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
501 :
502 0 : if (!ctx) {
503 0 : ctx = wbcGetGlobalCtx();
504 : }
505 :
506 0 : if (ctx->gr_cache_size > 0) {
507 0 : ctx->gr_cache_idx = ctx->gr_cache_size = 0;
508 0 : winbindd_free_response(&gr_response);
509 : }
510 :
511 0 : ZERO_STRUCT(gr_response);
512 :
513 0 : wbc_status = wbcRequestResponse(ctx, WINBINDD_SETGRENT,
514 : NULL, NULL);
515 0 : BAIL_ON_WBC_ERROR(wbc_status);
516 :
517 0 : done:
518 0 : return wbc_status;
519 : }
520 :
521 : _PUBLIC_
522 0 : wbcErr wbcSetgrent(void)
523 : {
524 0 : return wbcCtxSetgrent(NULL);
525 : }
526 :
527 : /* Close the group iterator */
528 : _PUBLIC_
529 0 : wbcErr wbcCtxEndgrent(struct wbcContext *ctx)
530 : {
531 0 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
532 :
533 0 : if (!ctx) {
534 0 : ctx = wbcGetGlobalCtx();
535 : }
536 :
537 0 : if (ctx->gr_cache_size > 0) {
538 0 : ctx->gr_cache_idx = ctx->gr_cache_size = 0;
539 0 : winbindd_free_response(&gr_response);
540 : }
541 :
542 0 : wbc_status = wbcRequestResponse(ctx, WINBINDD_ENDGRENT,
543 : NULL, NULL);
544 0 : BAIL_ON_WBC_ERROR(wbc_status);
545 :
546 0 : done:
547 0 : return wbc_status;
548 : }
549 :
550 : _PUBLIC_
551 0 : wbcErr wbcEndgrent(void)
552 : {
553 0 : return wbcCtxEndgrent(NULL);
554 : }
555 :
556 : /* Return the next struct group* entry from the pwent iterator */
557 : _PUBLIC_
558 0 : wbcErr wbcCtxGetgrent(struct wbcContext *ctx, struct group **grp)
559 : {
560 0 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
561 0 : struct winbindd_request request;
562 0 : struct winbindd_gr *wb_gr;
563 0 : uint32_t mem_ofs;
564 :
565 0 : if (!ctx) {
566 0 : ctx = wbcGetGlobalCtx();
567 : }
568 :
569 : /* If there's a cached result, return that. */
570 0 : if (ctx->gr_cache_idx < ctx->gr_cache_size) {
571 0 : goto return_result;
572 : }
573 :
574 : /* Otherwise, query winbindd for some entries. */
575 :
576 0 : ctx->gr_cache_idx = 0;
577 :
578 0 : winbindd_free_response(&gr_response);
579 :
580 0 : ZERO_STRUCT(request);
581 0 : request.data.num_entries = MAX_GETGRENT_GROUPS;
582 :
583 0 : wbc_status = wbcRequestResponse(ctx, WINBINDD_GETGRENT,
584 : &request, &gr_response);
585 :
586 0 : BAIL_ON_WBC_ERROR(wbc_status);
587 :
588 0 : ctx->gr_cache_size = gr_response.data.num_entries;
589 :
590 0 : return_result:
591 :
592 0 : wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
593 :
594 0 : mem_ofs = wb_gr[ctx->gr_cache_idx].gr_mem_ofs +
595 0 : ctx->gr_cache_size * sizeof(struct winbindd_gr);
596 :
597 0 : *grp = copy_group_entry(&wb_gr[ctx->gr_cache_idx],
598 0 : ((char *)gr_response.extra_data.data)+mem_ofs);
599 :
600 0 : BAIL_ON_PTR_ERROR(*grp, wbc_status);
601 :
602 0 : ctx->gr_cache_idx++;
603 :
604 0 : done:
605 0 : return wbc_status;
606 : }
607 :
608 : _PUBLIC_
609 0 : wbcErr wbcGetgrent(struct group **grp)
610 : {
611 0 : return wbcCtxGetgrent(NULL, grp);
612 : }
613 :
614 : /* Return the next struct group* entry from the pwent iterator */
615 : _PUBLIC_
616 0 : wbcErr wbcCtxGetgrlist(struct wbcContext *ctx, struct group **grp)
617 : {
618 0 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
619 0 : struct winbindd_request request;
620 0 : struct winbindd_gr *wb_gr;
621 :
622 0 : if (!ctx) {
623 0 : ctx = wbcGetGlobalCtx();
624 : }
625 :
626 : /* If there's a cached result, return that. */
627 0 : if (ctx->gr_cache_idx < ctx->gr_cache_size) {
628 0 : goto return_result;
629 : }
630 :
631 : /* Otherwise, query winbindd for some entries. */
632 :
633 0 : ctx->gr_cache_idx = 0;
634 :
635 0 : winbindd_free_response(&gr_response);
636 0 : ZERO_STRUCT(gr_response);
637 :
638 0 : ZERO_STRUCT(request);
639 0 : request.data.num_entries = MAX_GETGRENT_GROUPS;
640 :
641 0 : wbc_status = wbcRequestResponse(ctx, WINBINDD_GETGRLST,
642 : &request, &gr_response);
643 :
644 0 : BAIL_ON_WBC_ERROR(wbc_status);
645 :
646 0 : ctx->gr_cache_size = gr_response.data.num_entries;
647 :
648 0 : return_result:
649 :
650 0 : wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
651 :
652 0 : *grp = copy_group_entry(&wb_gr[ctx->gr_cache_idx], NULL);
653 :
654 0 : BAIL_ON_PTR_ERROR(*grp, wbc_status);
655 :
656 0 : ctx->gr_cache_idx++;
657 :
658 0 : done:
659 0 : return wbc_status;
660 : }
661 :
662 : _PUBLIC_
663 0 : wbcErr wbcGetgrlist(struct group **grp)
664 : {
665 0 : return wbcCtxGetgrlist(NULL, grp);
666 : }
667 :
668 : /* Return the unix group array belonging to the given user */
669 : _PUBLIC_
670 1634 : wbcErr wbcCtxGetGroups(struct wbcContext *ctx, const char *account,
671 : uint32_t *num_groups, gid_t **_groups)
672 : {
673 1634 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
674 0 : struct winbindd_request request;
675 0 : struct winbindd_response response;
676 0 : uint32_t i;
677 1634 : gid_t *groups = NULL;
678 :
679 : /* Initialize request */
680 :
681 1634 : ZERO_STRUCT(request);
682 1634 : ZERO_STRUCT(response);
683 :
684 1634 : if (!account) {
685 0 : wbc_status = WBC_ERR_INVALID_PARAM;
686 0 : BAIL_ON_WBC_ERROR(wbc_status);
687 : }
688 :
689 : /* Send request */
690 :
691 1634 : strncpy(request.data.username, account, sizeof(request.data.username)-1);
692 :
693 1634 : wbc_status = wbcRequestResponse(ctx, WINBINDD_GETGROUPS,
694 : &request,
695 : &response);
696 1634 : BAIL_ON_WBC_ERROR(wbc_status);
697 :
698 1634 : groups = (gid_t *)wbcAllocateMemory(
699 1634 : response.data.num_entries, sizeof(gid_t), NULL);
700 1634 : BAIL_ON_PTR_ERROR(groups, wbc_status);
701 :
702 4264 : for (i = 0; i < response.data.num_entries; i++) {
703 2630 : groups[i] = ((gid_t *)response.extra_data.data)[i];
704 : }
705 :
706 1634 : *num_groups = response.data.num_entries;
707 1634 : *_groups = groups;
708 1634 : groups = NULL;
709 :
710 1634 : wbc_status = WBC_ERR_SUCCESS;
711 :
712 1634 : done:
713 1634 : winbindd_free_response(&response);
714 1634 : wbcFreeMemory(groups);
715 1634 : return wbc_status;
716 : }
717 :
718 : _PUBLIC_
719 1634 : wbcErr wbcGetGroups(const char *account, uint32_t *num_groups, gid_t **_groups)
720 : {
721 1634 : return wbcCtxGetGroups(NULL, account, num_groups, _groups);
722 : }
|