libwbclient: Fix some pointless macro calls
[ira/wip.git] / nsswitch / libwbclient / wbc_sid.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Winbind client API
5
6    Copyright (C) Gerald (Jerry) Carter 2007
7    Copyright (C) Volker Lendecke 2010
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 /* Convert a binary SID to a character string */
31 wbcErr wbcSidToString(const struct wbcDomainSid *sid,
32                       char **sid_string)
33 {
34         uint32_t id_auth;
35         int i, ofs, maxlen;
36         char *result;
37
38         if (!sid) {
39                 return WBC_ERR_INVALID_SID;
40         }
41
42         maxlen = sid->num_auths * 11 + 25;
43
44         result = (char *)wbcAllocateMemory(maxlen, 1, NULL);
45         if (result == NULL) {
46                 return WBC_ERR_NO_MEMORY;
47         }
48
49         /*
50          * BIG NOTE: this function only does SIDS where the identauth is not
51          * >= ^32 in a range of 2^48.
52          */
53
54         id_auth = sid->id_auth[5] +
55                 (sid->id_auth[4] << 8) +
56                 (sid->id_auth[3] << 16) +
57                 (sid->id_auth[2] << 24);
58
59         ofs = snprintf(result, maxlen, "S-%u-%lu",
60                        (unsigned int)sid->sid_rev_num, (unsigned long)id_auth);
61
62         for (i = 0; i < sid->num_auths; i++) {
63                 ofs += snprintf(result + ofs, maxlen - ofs, "-%lu",
64                                 (unsigned long)sid->sub_auths[i]);
65         }
66
67         *sid_string = result;
68         return WBC_ERR_SUCCESS;
69 }
70
71 /* Convert a character string to a binary SID */
72 wbcErr wbcStringToSid(const char *str,
73                       struct wbcDomainSid *sid)
74 {
75         const char *p;
76         char *q;
77         uint32_t x;
78         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
79
80         if (!sid) {
81                 wbc_status = WBC_ERR_INVALID_PARAM;
82                 BAIL_ON_WBC_ERROR(wbc_status);
83         }
84
85         /* Sanity check for either "S-" or "s-" */
86
87         if (!str
88             || (str[0]!='S' && str[0]!='s')
89             || (str[1]!='-'))
90         {
91                 wbc_status = WBC_ERR_INVALID_PARAM;
92                 BAIL_ON_WBC_ERROR(wbc_status);
93         }
94
95         /* Get the SID revision number */
96
97         p = str+2;
98         x = (uint32_t)strtol(p, &q, 10);
99         if (x==0 || !q || *q!='-') {
100                 wbc_status = WBC_ERR_INVALID_SID;
101                 BAIL_ON_WBC_ERROR(wbc_status);
102         }
103         sid->sid_rev_num = (uint8_t)x;
104
105         /* Next the Identifier Authority.  This is stored in big-endian
106            in a 6 byte array. */
107
108         p = q+1;
109         x = (uint32_t)strtol(p, &q, 10);
110         if (!q || *q!='-') {
111                 wbc_status = WBC_ERR_INVALID_SID;
112                 BAIL_ON_WBC_ERROR(wbc_status);
113         }
114         sid->id_auth[5] = (x & 0x000000ff);
115         sid->id_auth[4] = (x & 0x0000ff00) >> 8;
116         sid->id_auth[3] = (x & 0x00ff0000) >> 16;
117         sid->id_auth[2] = (x & 0xff000000) >> 24;
118         sid->id_auth[1] = 0;
119         sid->id_auth[0] = 0;
120
121         /* now read the the subauthorities */
122
123         p = q +1;
124         sid->num_auths = 0;
125         while (sid->num_auths < WBC_MAXSUBAUTHS) {
126                 x=(uint32_t)strtoul(p, &q, 10);
127                 if (p == q)
128                         break;
129                 if (q == NULL) {
130                         wbc_status = WBC_ERR_INVALID_SID;
131                         BAIL_ON_WBC_ERROR(wbc_status);
132                 }
133                 sid->sub_auths[sid->num_auths++] = x;
134
135                 if ((*q!='-') || (*q=='\0'))
136                         break;
137                 p = q + 1;
138         }
139
140         /* IF we ended early, then the SID could not be converted */
141
142         if (q && *q!='\0') {
143                 wbc_status = WBC_ERR_INVALID_SID;
144                 BAIL_ON_WBC_ERROR(wbc_status);
145         }
146
147         wbc_status = WBC_ERR_SUCCESS;
148
149 done:
150         return wbc_status;
151
152 }
153
154
155 /* Convert a domain and name to SID */
156 wbcErr wbcLookupName(const char *domain,
157                      const char *name,
158                      struct wbcDomainSid *sid,
159                      enum wbcSidType *name_type)
160 {
161         struct winbindd_request request;
162         struct winbindd_response response;
163         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
164
165         if (!sid || !name_type) {
166                 wbc_status = WBC_ERR_INVALID_PARAM;
167                 BAIL_ON_WBC_ERROR(wbc_status);
168         }
169
170         /* Initialize request */
171
172         ZERO_STRUCT(request);
173         ZERO_STRUCT(response);
174
175         /* dst is already null terminated from the memset above */
176
177         strncpy(request.data.name.dom_name, domain,
178                 sizeof(request.data.name.dom_name)-1);
179         strncpy(request.data.name.name, name,
180                 sizeof(request.data.name.name)-1);
181
182         wbc_status = wbcRequestResponse(WINBINDD_LOOKUPNAME,
183                                         &request,
184                                         &response);
185         BAIL_ON_WBC_ERROR(wbc_status);
186
187         wbc_status = wbcStringToSid(response.data.sid.sid, sid);
188         BAIL_ON_WBC_ERROR(wbc_status);
189
190         *name_type = (enum wbcSidType)response.data.sid.type;
191
192         wbc_status = WBC_ERR_SUCCESS;
193
194  done:
195         return wbc_status;
196 }
197
198
199 /* Convert a SID to a domain and name */
200 wbcErr wbcLookupSid(const struct wbcDomainSid *sid,
201                     char **pdomain,
202                     char **pname,
203                     enum wbcSidType *pname_type)
204 {
205         struct winbindd_request request;
206         struct winbindd_response response;
207         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
208         char *sid_string = NULL;
209         char *domain, *name;
210
211         if (!sid) {
212                 return WBC_ERR_INVALID_PARAM;
213         }
214
215         /* Initialize request */
216
217         ZERO_STRUCT(request);
218         ZERO_STRUCT(response);
219
220         /* dst is already null terminated from the memset above */
221
222         wbc_status = wbcSidToString(sid, &sid_string);
223         if (!WBC_ERROR_IS_OK(wbc_status)) {
224                 return wbc_status;
225         }
226
227         strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
228         wbcFreeMemory(sid_string);
229
230         /* Make request */
231
232         wbc_status = wbcRequestResponse(WINBINDD_LOOKUPSID, &request,
233                                         &response);
234         if (!WBC_ERROR_IS_OK(wbc_status)) {
235                 return wbc_status;
236         }
237
238         /* Copy out result */
239
240         wbc_status = WBC_ERR_NO_MEMORY;
241         domain = NULL;
242         name = NULL;
243
244         domain = wbcStrDup(response.data.name.dom_name);
245         if (domain == NULL) {
246                 goto done;
247         }
248         name = wbcStrDup(response.data.name.name);
249         if (name == NULL) {
250                 goto done;
251         }
252         if (pdomain != NULL) {
253                 *pdomain = domain;
254                 domain = NULL;
255         }
256         if (pname != NULL) {
257                 *pname = name;
258                 name = NULL;
259         }
260         if (pname_type != NULL) {
261                 *pname_type = (enum wbcSidType)response.data.name.type;
262         }
263         wbc_status = WBC_ERR_SUCCESS;
264 done:
265         wbcFreeMemory(name);
266         wbcFreeMemory(domain);
267         return wbc_status;
268 }
269
270 /* Translate a collection of RIDs within a domain to names */
271
272 wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid,
273                      int num_rids,
274                      uint32_t *rids,
275                      const char **pp_domain_name,
276                      const char ***pnames,
277                      enum wbcSidType **ptypes)
278 {
279         size_t i, len, ridbuf_size;
280         char *ridlist;
281         char *p;
282         struct winbindd_request request;
283         struct winbindd_response response;
284         char *sid_string = NULL;
285         char *domain_name = NULL;
286         const char **names = NULL;
287         enum wbcSidType *types = NULL;
288         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
289
290         /* Initialise request */
291
292         ZERO_STRUCT(request);
293         ZERO_STRUCT(response);
294
295         if (!dom_sid || (num_rids == 0)) {
296                 wbc_status = WBC_ERR_INVALID_PARAM;
297                 BAIL_ON_WBC_ERROR(wbc_status);
298         }
299
300         wbc_status = wbcSidToString(dom_sid, &sid_string);
301         BAIL_ON_WBC_ERROR(wbc_status);
302
303         strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
304         wbcFreeMemory(sid_string);
305
306         /* Even if all the Rids were of maximum 32bit values,
307            we would only have 11 bytes per rid in the final array
308            ("4294967296" + \n).  Add one more byte for the
309            terminating '\0' */
310
311         ridbuf_size = (sizeof(char)*11) * num_rids + 1;
312
313         ridlist = (char *)malloc(ridbuf_size);
314         BAIL_ON_PTR_ERROR(ridlist, wbc_status);
315
316         len = 0;
317         for (i=0; i<num_rids; i++) {
318                 len += snprintf(ridlist + len, ridbuf_size - len, "%u\n",
319                                 rids[i]);
320         }
321         ridlist[len] = '\0';
322         len += 1;
323
324         request.extra_data.data = ridlist;
325         request.extra_len = len;
326
327         wbc_status = wbcRequestResponse(WINBINDD_LOOKUPRIDS,
328                                         &request,
329                                         &response);
330         free(ridlist);
331         BAIL_ON_WBC_ERROR(wbc_status);
332
333         domain_name = wbcStrDup(response.data.domain_name);
334         BAIL_ON_PTR_ERROR(domain_name, wbc_status);
335
336         names = wbcAllocateStringArray(num_rids);
337         BAIL_ON_PTR_ERROR(names, wbc_status);
338
339         types = (enum wbcSidType *)wbcAllocateMemory(
340                 num_rids, sizeof(enum wbcSidType), NULL);
341         BAIL_ON_PTR_ERROR(types, wbc_status);
342
343         p = (char *)response.extra_data.data;
344
345         for (i=0; i<num_rids; i++) {
346                 char *q;
347
348                 if (*p == '\0') {
349                         wbc_status = WBC_ERR_INVALID_RESPONSE;
350                         goto done;
351                 }
352
353                 types[i] = (enum wbcSidType)strtoul(p, &q, 10);
354
355                 if (*q != ' ') {
356                         wbc_status = WBC_ERR_INVALID_RESPONSE;
357                         goto done;
358                 }
359
360                 p = q+1;
361
362                 if ((q = strchr(p, '\n')) == NULL) {
363                         wbc_status = WBC_ERR_INVALID_RESPONSE;
364                         goto done;
365                 }
366
367                 *q = '\0';
368
369                 names[i] = strdup(p);
370                 BAIL_ON_PTR_ERROR(names[i], wbc_status);
371
372                 p = q+1;
373         }
374
375         if (*p != '\0') {
376                 wbc_status = WBC_ERR_INVALID_RESPONSE;
377                 goto done;
378         }
379
380         wbc_status = WBC_ERR_SUCCESS;
381
382  done:
383         winbindd_free_response(&response);
384
385         if (WBC_ERROR_IS_OK(wbc_status)) {
386                 *pp_domain_name = domain_name;
387                 *pnames = names;
388                 *ptypes = types;
389         }
390         else {
391                 wbcFreeMemory(domain_name);
392                 wbcFreeMemory(names);
393                 wbcFreeMemory(types);
394         }
395
396         return wbc_status;
397 }
398
399 /* Get the groups a user belongs to */
400 wbcErr wbcLookupUserSids(const struct wbcDomainSid *user_sid,
401                          bool domain_groups_only,
402                          uint32_t *num_sids,
403                          struct wbcDomainSid **_sids)
404 {
405         uint32_t i;
406         const char *s;
407         struct winbindd_request request;
408         struct winbindd_response response;
409         char *sid_string = NULL;
410         struct wbcDomainSid *sids = NULL;
411         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
412         int cmd;
413
414         /* Initialise request */
415
416         ZERO_STRUCT(request);
417         ZERO_STRUCT(response);
418
419         if (!user_sid) {
420                 wbc_status = WBC_ERR_INVALID_PARAM;
421                 BAIL_ON_WBC_ERROR(wbc_status);
422         }
423
424         wbc_status = wbcSidToString(user_sid, &sid_string);
425         BAIL_ON_WBC_ERROR(wbc_status);
426
427         strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
428         wbcFreeMemory(sid_string);
429
430         if (domain_groups_only) {
431                 cmd = WINBINDD_GETUSERDOMGROUPS;
432         } else {
433                 cmd = WINBINDD_GETUSERSIDS;
434         }
435
436         wbc_status = wbcRequestResponse(cmd,
437                                         &request,
438                                         &response);
439         BAIL_ON_WBC_ERROR(wbc_status);
440
441         if (response.data.num_entries &&
442             !response.extra_data.data) {
443                 wbc_status = WBC_ERR_INVALID_RESPONSE;
444                 BAIL_ON_WBC_ERROR(wbc_status);
445         }
446
447         sids = talloc_array(NULL, struct wbcDomainSid,
448                             response.data.num_entries);
449         BAIL_ON_PTR_ERROR(sids, wbc_status);
450
451         s = (const char *)response.extra_data.data;
452         for (i = 0; i < response.data.num_entries; i++) {
453                 char *n = strchr(s, '\n');
454                 if (n) {
455                         *n = '\0';
456                 }
457                 wbc_status = wbcStringToSid(s, &sids[i]);
458                 BAIL_ON_WBC_ERROR(wbc_status);
459                 s += strlen(s) + 1;
460         }
461
462         *num_sids = response.data.num_entries;
463         *_sids = sids;
464         sids = NULL;
465         wbc_status = WBC_ERR_SUCCESS;
466
467  done:
468         winbindd_free_response(&response);
469         if (sids) {
470                 talloc_free(sids);
471         }
472
473         return wbc_status;
474 }
475
476 static inline
477 wbcErr _sid_to_rid(struct wbcDomainSid *sid, uint32_t *rid)
478 {
479         if (sid->num_auths < 1) {
480                 return WBC_ERR_INVALID_RESPONSE;
481         }
482         *rid = sid->sub_auths[sid->num_auths - 1];
483
484         return WBC_ERR_SUCCESS;
485 }
486
487 /* Get alias membership for sids */
488 wbcErr wbcGetSidAliases(const struct wbcDomainSid *dom_sid,
489                         struct wbcDomainSid *sids,
490                         uint32_t num_sids,
491                         uint32_t **alias_rids,
492                         uint32_t *num_alias_rids)
493 {
494         uint32_t i;
495         const char *s;
496         struct winbindd_request request;
497         struct winbindd_response response;
498         char *sid_string = NULL;
499         ssize_t sid_len;
500         ssize_t extra_data_len = 0;
501         char * extra_data = NULL;
502         ssize_t buflen = 0;
503         struct wbcDomainSid sid;
504         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
505         uint32_t * rids = NULL;
506
507         /* Initialise request */
508
509         ZERO_STRUCT(request);
510         ZERO_STRUCT(response);
511
512         if (!dom_sid) {
513                 wbc_status = WBC_ERR_INVALID_PARAM;
514                 BAIL_ON_WBC_ERROR(wbc_status);
515         }
516
517         wbc_status = wbcSidToString(dom_sid, &sid_string);
518         BAIL_ON_WBC_ERROR(wbc_status);
519
520         strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
521         wbcFreeMemory(sid_string);
522         sid_string = NULL;
523
524         /* Lets assume each sid is around 54 characters
525          * S-1-5-AAAAAAAAAAA-BBBBBBBBBBB-CCCCCCCCCCC-DDDDDDDDDDD\n */
526         buflen = 54 * num_sids;
527         extra_data = talloc_array(NULL, char, buflen);
528         if (!extra_data) {
529                 wbc_status = WBC_ERR_NO_MEMORY;
530                 BAIL_ON_WBC_ERROR(wbc_status);
531         }
532
533         /* Build the sid list */
534         for (i=0; i<num_sids; i++) {
535                 wbcFreeMemory(sid_string);
536                 sid_string = NULL;
537                 wbc_status = wbcSidToString(&sids[i], &sid_string);
538                 BAIL_ON_WBC_ERROR(wbc_status);
539
540                 sid_len = strlen(sid_string);
541
542                 if (buflen < extra_data_len + sid_len + 2) {
543                         buflen *= 2;
544                         extra_data = talloc_realloc(NULL, extra_data,
545                             char, buflen);
546                         if (!extra_data) {
547                                 wbc_status = WBC_ERR_NO_MEMORY;
548                                 BAIL_ON_WBC_ERROR(wbc_status);
549                         }
550                 }
551
552                 strncpy(&extra_data[extra_data_len], sid_string,
553                         buflen - extra_data_len);
554                 extra_data_len += sid_len;
555                 extra_data[extra_data_len++] = '\n';
556                 extra_data[extra_data_len] = '\0';
557         }
558         extra_data_len += 1;
559
560         request.extra_data.data = extra_data;
561         request.extra_len = extra_data_len;
562
563         wbc_status = wbcRequestResponse(WINBINDD_GETSIDALIASES,
564                                         &request,
565                                         &response);
566         BAIL_ON_WBC_ERROR(wbc_status);
567
568         if (response.data.num_entries &&
569             !response.extra_data.data) {
570                 wbc_status = WBC_ERR_INVALID_RESPONSE;
571                 BAIL_ON_WBC_ERROR(wbc_status);
572         }
573
574         rids = talloc_array(NULL, uint32_t,
575                             response.data.num_entries);
576         BAIL_ON_PTR_ERROR(sids, wbc_status);
577
578         s = (const char *)response.extra_data.data;
579         for (i = 0; i < response.data.num_entries; i++) {
580                 char *n = strchr(s, '\n');
581                 if (n) {
582                         *n = '\0';
583                 }
584                 wbc_status = wbcStringToSid(s, &sid);
585                 BAIL_ON_WBC_ERROR(wbc_status);
586                 wbc_status = _sid_to_rid(&sid, &rids[i]);
587                 BAIL_ON_WBC_ERROR(wbc_status);
588                 s += strlen(s) + 1;
589         }
590
591         *num_alias_rids = response.data.num_entries;
592         *alias_rids = rids;
593         rids = NULL;
594         wbc_status = WBC_ERR_SUCCESS;
595
596  done:
597         wbcFreeMemory(sid_string);
598         talloc_free(extra_data);
599         winbindd_free_response(&response);
600         talloc_free(rids);
601         return wbc_status;
602 }
603
604
605 /* Lists Users */
606 wbcErr wbcListUsers(const char *domain_name,
607                     uint32_t *_num_users,
608                     const char ***_users)
609 {
610         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
611         struct winbindd_request request;
612         struct winbindd_response response;
613         uint32_t num_users = 0;
614         const char **users = NULL;
615         const char *next;
616
617         /* Initialise request */
618
619         ZERO_STRUCT(request);
620         ZERO_STRUCT(response);
621
622         if (domain_name) {
623                 strncpy(request.domain_name, domain_name,
624                         sizeof(request.domain_name)-1);
625         }
626
627         wbc_status = wbcRequestResponse(WINBINDD_LIST_USERS,
628                                         &request,
629                                         &response);
630         BAIL_ON_WBC_ERROR(wbc_status);
631
632         /* Look through extra data */
633
634         next = (const char *)response.extra_data.data;
635         while (next) {
636                 const char **tmp;
637                 const char *current = next;
638                 char *k = strchr(next, ',');
639                 if (k) {
640                         k[0] = '\0';
641                         next = k+1;
642                 } else {
643                         next = NULL;
644                 }
645
646                 tmp = talloc_realloc(NULL, users,
647                                      const char *,
648                                      num_users+1);
649                 BAIL_ON_PTR_ERROR(tmp, wbc_status);
650                 users = tmp;
651
652                 users[num_users] = talloc_strdup(users, current);
653                 BAIL_ON_PTR_ERROR(users[num_users], wbc_status);
654
655                 num_users++;
656         }
657
658         *_num_users = num_users;
659         *_users = users;
660         users = NULL;
661         wbc_status = WBC_ERR_SUCCESS;
662
663  done:
664         winbindd_free_response(&response);
665         if (users) {
666                 talloc_free(users);
667         }
668         return wbc_status;
669 }
670
671 /* Lists Groups */
672 wbcErr wbcListGroups(const char *domain_name,
673                      uint32_t *_num_groups,
674                      const char ***_groups)
675 {
676         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
677         struct winbindd_request request;
678         struct winbindd_response response;
679         uint32_t num_groups = 0;
680         const char **groups = NULL;
681         const char *next;
682
683         /* Initialise request */
684
685         ZERO_STRUCT(request);
686         ZERO_STRUCT(response);
687
688         if (domain_name) {
689                 strncpy(request.domain_name, domain_name,
690                         sizeof(request.domain_name)-1);
691         }
692
693         wbc_status = wbcRequestResponse(WINBINDD_LIST_GROUPS,
694                                         &request,
695                                         &response);
696         BAIL_ON_WBC_ERROR(wbc_status);
697
698         /* Look through extra data */
699
700         next = (const char *)response.extra_data.data;
701         while (next) {
702                 const char **tmp;
703                 const char *current = next;
704                 char *k = strchr(next, ',');
705                 if (k) {
706                         k[0] = '\0';
707                         next = k+1;
708                 } else {
709                         next = NULL;
710                 }
711
712                 tmp = talloc_realloc(NULL, groups,
713                                      const char *,
714                                      num_groups+1);
715                 BAIL_ON_PTR_ERROR(tmp, wbc_status);
716                 groups = tmp;
717
718                 groups[num_groups] = talloc_strdup(groups, current);
719                 BAIL_ON_PTR_ERROR(groups[num_groups], wbc_status);
720
721                 num_groups++;
722         }
723
724         *_num_groups = num_groups;
725         *_groups = groups;
726         groups = NULL;
727         wbc_status = WBC_ERR_SUCCESS;
728
729  done:
730         winbindd_free_response(&response);
731         if (groups) {
732                 talloc_free(groups);
733         }
734         return wbc_status;
735 }
736
737 wbcErr wbcGetDisplayName(const struct wbcDomainSid *sid,
738                          char **pdomain,
739                          char **pfullname,
740                          enum wbcSidType *pname_type)
741 {
742         wbcErr wbc_status;
743         char *domain = NULL;
744         char *name = NULL;
745         enum wbcSidType name_type;
746
747         wbc_status = wbcLookupSid(sid, &domain, &name, &name_type);
748         BAIL_ON_WBC_ERROR(wbc_status);
749
750         if (name_type == WBC_SID_NAME_USER) {
751                 uid_t uid;
752                 struct passwd *pwd;
753
754                 wbc_status = wbcSidToUid(sid, &uid);
755                 BAIL_ON_WBC_ERROR(wbc_status);
756
757                 wbc_status = wbcGetpwuid(uid, &pwd);
758                 BAIL_ON_WBC_ERROR(wbc_status);
759
760                 wbcFreeMemory(name);
761
762                 name = talloc_strdup(NULL, pwd->pw_gecos);
763                 BAIL_ON_PTR_ERROR(name, wbc_status);
764                 wbcFreeMemory(pwd);
765         }
766
767         wbc_status = WBC_ERR_SUCCESS;
768
769  done:
770         if (WBC_ERROR_IS_OK(wbc_status)) {
771                 *pdomain = domain;
772                 *pfullname = name;
773                 *pname_type = name_type;
774         } else {
775                 wbcFreeMemory(domain);
776                 wbcFreeMemory(name);
777         }
778
779         return wbc_status;
780 }
781
782 const char* wbcSidTypeString(enum wbcSidType type)
783 {
784         switch (type) {
785         case WBC_SID_NAME_USE_NONE: return "SID_NONE";
786         case WBC_SID_NAME_USER:     return "SID_USER";
787         case WBC_SID_NAME_DOM_GRP:  return "SID_DOM_GROUP";
788         case WBC_SID_NAME_DOMAIN:   return "SID_DOMAIN";
789         case WBC_SID_NAME_ALIAS:    return "SID_ALIAS";
790         case WBC_SID_NAME_WKN_GRP:  return "SID_WKN_GROUP";
791         case WBC_SID_NAME_DELETED:  return "SID_DELETED";
792         case WBC_SID_NAME_INVALID:  return "SID_INVALID";
793         case WBC_SID_NAME_UNKNOWN:  return "SID_UNKNOWN";
794         case WBC_SID_NAME_COMPUTER: return "SID_COMPUTER";
795         default:                    return "Unknown type";
796         }
797 }