LCOV - code coverage report
Current view: top level - nsswitch/libwbclient - wbc_sid.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 359 543 66.1 %
Date: 2024-06-13 04:01:37 Functions: 21 25 84.0 %

          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) 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             : #include "lib/util/smb_strtox.h"
      30             : 
      31             : /* Convert a sid to a string into a buffer. Return the string
      32             :  * length. If buflen is too small, return the string length that would
      33             :  * result if it was long enough. */
      34             : _PUBLIC_
      35       99839 : int wbcSidToStringBuf(const struct wbcDomainSid *sid, char *buf, int buflen)
      36             : {
      37             :         uint64_t id_auth;
      38             :         int i, ofs;
      39             : 
      40       99839 :         if (!sid) {
      41           0 :                 strlcpy(buf, "(NULL SID)", buflen);
      42           0 :                 return 10;      /* strlen("(NULL SID)") */
      43             :         }
      44             : 
      45      252227 :         id_auth = (uint64_t)sid->id_auth[5] +
      46      176033 :                 ((uint64_t)sid->id_auth[4] << 8) +
      47      176033 :                 ((uint64_t)sid->id_auth[3] << 16) +
      48      176033 :                 ((uint64_t)sid->id_auth[2] << 24) +
      49       99839 :                 ((uint64_t)sid->id_auth[1] << 32) +
      50       99839 :                 ((uint64_t)sid->id_auth[0] << 40);
      51             : 
      52       99839 :         ofs = snprintf(buf, buflen, "S-%hhu-", (unsigned char)sid->sid_rev_num);
      53       99839 :         if (id_auth >= UINT32_MAX) {
      54           0 :                 ofs += snprintf(buf + ofs, MAX(buflen - ofs, 0), "0x%llx",
      55             :                                 (unsigned long long)id_auth);
      56             :         } else {
      57       99839 :                 ofs += snprintf(buf + ofs, MAX(buflen - ofs, 0), "%llu",
      58             :                                 (unsigned long long)id_auth);
      59             :         }
      60             : 
      61      387409 :         for (i = 0; i < sid->num_auths; i++) {
      62      287570 :                 ofs += snprintf(buf + ofs, MAX(buflen - ofs, 0), "-%u",
      63      287570 :                                 (unsigned int)sid->sub_auths[i]);
      64             :         }
      65       99839 :         return ofs;
      66             : }
      67             : 
      68             : /* Convert a binary SID to a character string */
      69             : _PUBLIC_
      70          64 : wbcErr wbcSidToString(const struct wbcDomainSid *sid,
      71             :                       char **sid_string)
      72             : {
      73             :         char buf[WBC_SID_STRING_BUFLEN];
      74             :         char *result;
      75             :         int len;
      76             : 
      77          64 :         if (!sid) {
      78           0 :                 return WBC_ERR_INVALID_SID;
      79             :         }
      80             : 
      81          64 :         len = wbcSidToStringBuf(sid, buf, sizeof(buf));
      82             : 
      83          64 :         if (len >= WBC_SID_STRING_BUFLEN) {
      84           0 :                 return WBC_ERR_INVALID_SID;
      85             :         }
      86             : 
      87          64 :         result = (char *)wbcAllocateMemory(len+1, 1, NULL);
      88          64 :         if (result == NULL) {
      89           0 :                 return WBC_ERR_NO_MEMORY;
      90             :         }
      91          64 :         memcpy(result, buf, len+1);
      92             : 
      93          64 :         *sid_string = result;
      94          64 :         return WBC_ERR_SUCCESS;
      95             : }
      96             : 
      97             : #define AUTHORITY_MASK  (~(0xffffffffffffULL))
      98             : 
      99             : /* Convert a character string to a binary SID */
     100             : _PUBLIC_
     101       11913 : wbcErr wbcStringToSid(const char *str,
     102             :                       struct wbcDomainSid *sid)
     103             : {
     104             :         const char *p;
     105             :         char *q;
     106       11913 :         int error = 0;
     107             :         uint64_t x;
     108       11913 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     109             : 
     110       11913 :         if (!sid) {
     111           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     112           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     113             :         }
     114             : 
     115             :         /* Sanity check for either "S-" or "s-" */
     116             : 
     117       11913 :         if (!str
     118       11913 :             || (str[0]!='S' && str[0]!='s')
     119        9858 :             || (str[1]!='-'))
     120             :         {
     121        2055 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     122        2055 :                 BAIL_ON_WBC_ERROR(wbc_status);
     123             :         }
     124             : 
     125             :         /* Get the SID revision number */
     126             : 
     127        9858 :         p = str+2;
     128        9858 :         x = (uint64_t)smb_strtoul(p, &q, 10, &error, SMB_STR_STANDARD);
     129        9858 :         if (x == 0 || x > UINT8_MAX || !q || *q != '-' || error != 0) {
     130           0 :                 wbc_status = WBC_ERR_INVALID_SID;
     131           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     132             :         }
     133        9858 :         sid->sid_rev_num = (uint8_t)x;
     134             : 
     135             :         /*
     136             :          * Next the Identifier Authority.  This is stored big-endian in a
     137             :          * 6 byte array. If the authority value is >= UINT_MAX, then it should
     138             :          * be expressed as a hex value, according to MS-DTYP.
     139             :          */
     140        9858 :         p = q+1;
     141        9858 :         x = smb_strtoull(p, &q, 0, &error, SMB_STR_STANDARD);
     142        9858 :         if (!q || *q != '-' || (x & AUTHORITY_MASK) || error != 0) {
     143           0 :                 wbc_status = WBC_ERR_INVALID_SID;
     144           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     145             :         }
     146        9858 :         sid->id_auth[5] = (x & 0x0000000000ffULL);
     147        9858 :         sid->id_auth[4] = (x & 0x00000000ff00ULL) >> 8;
     148        9858 :         sid->id_auth[3] = (x & 0x000000ff0000ULL) >> 16;
     149        9858 :         sid->id_auth[2] = (x & 0x0000ff000000ULL) >> 24;
     150        9858 :         sid->id_auth[1] = (x & 0x00ff00000000ULL) >> 32;
     151        9858 :         sid->id_auth[0] = (x & 0xff0000000000ULL) >> 40;
     152             : 
     153             :         /* now read the the subauthorities */
     154        9858 :         p = q +1;
     155        9858 :         sid->num_auths = 0;
     156       42818 :         while (sid->num_auths < WBC_MAXSUBAUTHS) {
     157       34701 :                 x = smb_strtoull(p, &q, 10, &error, SMB_STR_ALLOW_NO_CONVERSION);
     158       34701 :                 if (p == q)
     159           0 :                         break;
     160       34701 :                 if (x > UINT32_MAX || error != 0) {
     161           0 :                         wbc_status = WBC_ERR_INVALID_SID;
     162           0 :                         BAIL_ON_WBC_ERROR(wbc_status);
     163             :                 }
     164       34701 :                 sid->sub_auths[sid->num_auths++] = x;
     165             : 
     166       34701 :                 if (*q != '-') {
     167        9858 :                         break;
     168             :                 }
     169       24843 :                 p = q + 1;
     170             :         }
     171             : 
     172             :         /* IF we ended early, then the SID could not be converted */
     173             : 
     174        9858 :         if (q && *q!='\0') {
     175           0 :                 wbc_status = WBC_ERR_INVALID_SID;
     176           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     177             :         }
     178             : 
     179        9858 :         wbc_status = WBC_ERR_SUCCESS;
     180             : 
     181       11913 : done:
     182       11913 :         return wbc_status;
     183             : 
     184             : }
     185             : 
     186             : 
     187             : /* Convert a domain and name to SID */
     188             : _PUBLIC_
     189         758 : wbcErr wbcCtxLookupName(struct wbcContext *ctx,
     190             :                         const char *domain,
     191             :                         const char *name,
     192             :                         struct wbcDomainSid *sid,
     193             :                         enum wbcSidType *name_type)
     194             : {
     195             :         struct winbindd_request request;
     196             :         struct winbindd_response response;
     197         758 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     198             : 
     199         758 :         if (!sid || !name_type) {
     200           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     201           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     202             :         }
     203             : 
     204             :         /* Initialize request */
     205             : 
     206         758 :         ZERO_STRUCT(request);
     207         758 :         ZERO_STRUCT(response);
     208             : 
     209             :         /* dst is already null terminated from the memset above */
     210             : 
     211         758 :         strncpy(request.data.name.dom_name, domain,
     212             :                 sizeof(request.data.name.dom_name)-1);
     213         758 :         strncpy(request.data.name.name, name,
     214             :                 sizeof(request.data.name.name)-1);
     215             : 
     216         758 :         wbc_status = wbcRequestResponse(ctx, WINBINDD_LOOKUPNAME,
     217             :                                         &request,
     218             :                                         &response);
     219         758 :         BAIL_ON_WBC_ERROR(wbc_status);
     220             : 
     221         580 :         wbc_status = wbcStringToSid(response.data.sid.sid, sid);
     222         580 :         BAIL_ON_WBC_ERROR(wbc_status);
     223             : 
     224         580 :         *name_type = (enum wbcSidType)response.data.sid.type;
     225             : 
     226         580 :         wbc_status = WBC_ERR_SUCCESS;
     227             : 
     228         758 :  done:
     229         758 :         return wbc_status;
     230             : }
     231             : 
     232             : _PUBLIC_
     233         614 : wbcErr wbcLookupName(const char *domain,
     234             :                      const char *name,
     235             :                      struct wbcDomainSid *sid,
     236             :                      enum wbcSidType *name_type)
     237             : {
     238         614 :         return wbcCtxLookupName(NULL, domain, name, sid, name_type);
     239             : }
     240             : 
     241             : 
     242             : /* Convert a SID to a domain and name */
     243             : _PUBLIC_
     244         220 : wbcErr wbcCtxLookupSid(struct wbcContext *ctx,
     245             :                        const struct wbcDomainSid *sid,
     246             :                        char **pdomain,
     247             :                        char **pname,
     248             :                        enum wbcSidType *pname_type)
     249             : {
     250             :         struct winbindd_request request;
     251             :         struct winbindd_response response;
     252         220 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     253             :         char *domain, *name;
     254             : 
     255         220 :         if (!sid) {
     256           0 :                 return WBC_ERR_INVALID_PARAM;
     257             :         }
     258             : 
     259             :         /* Initialize request */
     260             : 
     261         220 :         ZERO_STRUCT(request);
     262         220 :         ZERO_STRUCT(response);
     263             : 
     264         220 :         wbcSidToStringBuf(sid, request.data.sid, sizeof(request.data.sid));
     265             : 
     266             :         /* Make request */
     267             : 
     268         220 :         wbc_status = wbcRequestResponse(ctx, WINBINDD_LOOKUPSID,
     269             :                                         &request,
     270             :                                         &response);
     271         220 :         if (!WBC_ERROR_IS_OK(wbc_status)) {
     272           6 :                 return wbc_status;
     273             :         }
     274             : 
     275             :         /* Copy out result */
     276             : 
     277         214 :         wbc_status = WBC_ERR_NO_MEMORY;
     278         214 :         domain = NULL;
     279         214 :         name = NULL;
     280             : 
     281         214 :         domain = wbcStrDup(response.data.name.dom_name);
     282         214 :         if (domain == NULL) {
     283           0 :                 goto done;
     284             :         }
     285         214 :         name = wbcStrDup(response.data.name.name);
     286         214 :         if (name == NULL) {
     287           0 :                 goto done;
     288             :         }
     289         214 :         if (pdomain != NULL) {
     290         214 :                 *pdomain = domain;
     291         214 :                 domain = NULL;
     292             :         }
     293         214 :         if (pname != NULL) {
     294         214 :                 *pname = name;
     295         214 :                 name = NULL;
     296             :         }
     297         214 :         if (pname_type != NULL) {
     298         214 :                 *pname_type = (enum wbcSidType)response.data.name.type;
     299             :         }
     300         214 :         wbc_status = WBC_ERR_SUCCESS;
     301         214 : done:
     302         214 :         wbcFreeMemory(name);
     303         214 :         wbcFreeMemory(domain);
     304         214 :         return wbc_status;
     305             : }
     306             : 
     307             : _PUBLIC_
     308         126 : wbcErr wbcLookupSid(const struct wbcDomainSid *sid,
     309             :                     char **pdomain,
     310             :                     char **pname,
     311             :                     enum wbcSidType *pname_type)
     312             : {
     313         126 :         return wbcCtxLookupSid(NULL, sid, pdomain, pname, pname_type);
     314             : }
     315             : 
     316           0 : static void wbcDomainInfosDestructor(void *ptr)
     317             : {
     318           0 :         struct wbcDomainInfo *i = (struct wbcDomainInfo *)ptr;
     319             : 
     320           0 :         while (i->short_name != NULL) {
     321           0 :                 wbcFreeMemory(i->short_name);
     322           0 :                 wbcFreeMemory(i->dns_name);
     323           0 :                 i += 1;
     324             :         }
     325           0 : }
     326             : 
     327           0 : static void wbcTranslatedNamesDestructor(void *ptr)
     328             : {
     329           0 :         struct wbcTranslatedName *n = (struct wbcTranslatedName *)ptr;
     330             : 
     331           0 :         while (n->name != NULL) {
     332           0 :                 wbcFreeMemory(n->name);
     333           0 :                 n += 1;
     334             :         }
     335           0 : }
     336             : 
     337             : _PUBLIC_
     338           0 : wbcErr wbcCtxLookupSids(struct wbcContext *ctx,
     339             :                         const struct wbcDomainSid *sids, int num_sids,
     340             :                         struct wbcDomainInfo **pdomains, int *pnum_domains,
     341             :                         struct wbcTranslatedName **pnames)
     342             : {
     343             :         struct winbindd_request request;
     344             :         struct winbindd_response response;
     345           0 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     346             :         int buflen, i, extra_len, num_domains, num_names;
     347             :         char *sidlist, *p, *q, *extra_data;
     348           0 :         struct wbcDomainInfo *domains = NULL;
     349           0 :         struct wbcTranslatedName *names = NULL;
     350           0 :         int error = 0;
     351             : 
     352           0 :         buflen = num_sids * (WBC_SID_STRING_BUFLEN + 1) + 1;
     353             : 
     354           0 :         sidlist = (char *)malloc(buflen);
     355           0 :         if (sidlist == NULL) {
     356           0 :                 return WBC_ERR_NO_MEMORY;
     357             :         }
     358             : 
     359           0 :         p = sidlist;
     360             : 
     361           0 :         for (i=0; i<num_sids; i++) {
     362             :                 int remaining;
     363             :                 int len;
     364             : 
     365           0 :                 remaining = buflen - (p - sidlist);
     366             : 
     367           0 :                 len = wbcSidToStringBuf(&sids[i], p, remaining);
     368           0 :                 if (len > remaining) {
     369           0 :                         free(sidlist);
     370           0 :                         return WBC_ERR_UNKNOWN_FAILURE;
     371             :                 }
     372             : 
     373           0 :                 p += len;
     374           0 :                 *p++ = '\n';
     375             :         }
     376           0 :         *p++ = '\0';
     377             : 
     378           0 :         ZERO_STRUCT(request);
     379           0 :         ZERO_STRUCT(response);
     380             : 
     381           0 :         request.extra_data.data = sidlist;
     382           0 :         request.extra_len = p - sidlist;
     383             : 
     384           0 :         wbc_status = wbcRequestResponse(ctx, WINBINDD_LOOKUPSIDS,
     385             :                                         &request, &response);
     386           0 :         free(sidlist);
     387           0 :         if (!WBC_ERROR_IS_OK(wbc_status)) {
     388           0 :                 return wbc_status;
     389             :         }
     390             : 
     391           0 :         extra_len = response.length - sizeof(struct winbindd_response);
     392           0 :         extra_data = (char *)response.extra_data.data;
     393             : 
     394           0 :         if ((extra_len <= 0) || (extra_data[extra_len-1] != '\0')) {
     395           0 :                 goto wbc_err_invalid;
     396             :         }
     397             : 
     398           0 :         p = extra_data;
     399             : 
     400           0 :         num_domains = smb_strtoul(p, &q, 10, &error, SMB_STR_STANDARD);
     401           0 :         if (*q != '\n' || error != 0) {
     402           0 :                 goto wbc_err_invalid;
     403             :         }
     404           0 :         p = q+1;
     405             : 
     406           0 :         domains = (struct wbcDomainInfo *)wbcAllocateMemory(
     407           0 :                 num_domains+1, sizeof(struct wbcDomainInfo),
     408             :                 wbcDomainInfosDestructor);
     409           0 :         if (domains == NULL) {
     410           0 :                 wbc_status = WBC_ERR_NO_MEMORY;
     411           0 :                 goto fail;
     412             :         }
     413             : 
     414           0 :         for (i=0; i<num_domains; i++) {
     415             : 
     416           0 :                 q = strchr(p, ' ');
     417           0 :                 if (q == NULL) {
     418           0 :                         goto wbc_err_invalid;
     419             :                 }
     420           0 :                 *q = '\0';
     421           0 :                 wbc_status = wbcStringToSid(p, &domains[i].sid);
     422           0 :                 if (!WBC_ERROR_IS_OK(wbc_status)) {
     423           0 :                         goto fail;
     424             :                 }
     425           0 :                 p = q+1;
     426             : 
     427           0 :                 q = strchr(p, '\n');
     428           0 :                 if (q == NULL) {
     429           0 :                         goto wbc_err_invalid;
     430             :                 }
     431           0 :                 *q = '\0';
     432           0 :                 domains[i].short_name = wbcStrDup(p);
     433           0 :                 if (domains[i].short_name == NULL) {
     434           0 :                         wbc_status = WBC_ERR_NO_MEMORY;
     435           0 :                         goto fail;
     436             :                 }
     437           0 :                 p = q+1;
     438             :         }
     439             : 
     440           0 :         num_names = smb_strtoul(p, &q, 10, &error, SMB_STR_STANDARD);
     441           0 :         if (*q != '\n' || error != 0) {
     442           0 :                 goto wbc_err_invalid;
     443             :         }
     444           0 :         p = q+1;
     445             : 
     446           0 :         if (num_names != num_sids) {
     447           0 :                 goto wbc_err_invalid;
     448             :         }
     449             : 
     450           0 :         names = (struct wbcTranslatedName *)wbcAllocateMemory(
     451           0 :                 num_names+1, sizeof(struct wbcTranslatedName),
     452             :                 wbcTranslatedNamesDestructor);
     453           0 :         if (names == NULL) {
     454           0 :                 wbc_status = WBC_ERR_NO_MEMORY;
     455           0 :                 goto fail;
     456             :         }
     457             : 
     458           0 :         for (i=0; i<num_names; i++) {
     459             : 
     460           0 :                 names[i].domain_index = smb_strtoul(p,
     461             :                                                     &q,
     462             :                                                     10,
     463             :                                                     &error,
     464             :                                                     SMB_STR_STANDARD);
     465           0 :                 if (names[i].domain_index < 0 || error != 0) {
     466           0 :                         goto wbc_err_invalid;
     467             :                 }
     468           0 :                 if (names[i].domain_index >= num_domains) {
     469           0 :                         goto wbc_err_invalid;
     470             :                 }
     471             : 
     472           0 :                 if (*q != ' ') {
     473           0 :                         goto wbc_err_invalid;
     474             :                 }
     475           0 :                 p = q+1;
     476             : 
     477           0 :                 names[i].type = smb_strtoul(p, &q, 10, &error, SMB_STR_STANDARD);
     478           0 :                 if (*q != ' ' || error != 0) {
     479           0 :                         goto wbc_err_invalid;
     480             :                 }
     481           0 :                 p = q+1;
     482             : 
     483           0 :                 q = strchr(p, '\n');
     484           0 :                 if (q == NULL) {
     485           0 :                         goto wbc_err_invalid;
     486             :                 }
     487           0 :                 *q = '\0';
     488           0 :                 names[i].name = wbcStrDup(p);
     489           0 :                 if (names[i].name == NULL) {
     490           0 :                         wbc_status = WBC_ERR_NO_MEMORY;
     491           0 :                         goto fail;
     492             :                 }
     493           0 :                 p = q+1;
     494             :         }
     495           0 :         if (*p != '\0') {
     496           0 :                 goto wbc_err_invalid;
     497             :         }
     498             : 
     499           0 :         *pdomains = domains;
     500           0 :         *pnames = names;
     501           0 :         winbindd_free_response(&response);
     502           0 :         return WBC_ERR_SUCCESS;
     503             : 
     504           0 : wbc_err_invalid:
     505           0 :         wbc_status = WBC_ERR_INVALID_RESPONSE;
     506           0 : fail:
     507           0 :         winbindd_free_response(&response);
     508           0 :         wbcFreeMemory(domains);
     509           0 :         wbcFreeMemory(names);
     510           0 :         return wbc_status;
     511             : }
     512             : 
     513             : _PUBLIC_
     514           0 : wbcErr wbcLookupSids(const struct wbcDomainSid *sids, int num_sids,
     515             :                      struct wbcDomainInfo **pdomains, int *pnum_domains,
     516             :                      struct wbcTranslatedName **pnames)
     517             : {
     518           0 :         return wbcCtxLookupSids(NULL, sids, num_sids, pdomains,
     519             :                                 pnum_domains, pnames);
     520             : }
     521             : 
     522             : /* Translate a collection of RIDs within a domain to names */
     523             : 
     524             : _PUBLIC_
     525          22 : wbcErr wbcCtxLookupRids(struct wbcContext *ctx, struct wbcDomainSid *dom_sid,
     526             :                      int num_rids,
     527             :                      uint32_t *rids,
     528             :                      const char **pp_domain_name,
     529             :                      const char ***pnames,
     530             :                      enum wbcSidType **ptypes)
     531             : {
     532             :         size_t i, len, ridbuf_size;
     533             :         char *ridlist;
     534             :         char *p;
     535          22 :         int error = 0;
     536             :         struct winbindd_request request;
     537             :         struct winbindd_response response;
     538          22 :         char *domain_name = NULL;
     539          22 :         const char **names = NULL;
     540          22 :         enum wbcSidType *types = NULL;
     541          22 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     542             : 
     543             :         /* Initialise request */
     544             : 
     545          22 :         ZERO_STRUCT(request);
     546          22 :         ZERO_STRUCT(response);
     547             : 
     548          22 :         if (!dom_sid || (num_rids == 0)) {
     549           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     550           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     551             :         }
     552             : 
     553          22 :         wbcSidToStringBuf(dom_sid, request.data.sid, sizeof(request.data.sid));
     554             : 
     555             :         /* Even if all the Rids were of maximum 32bit values,
     556             :            we would only have 11 bytes per rid in the final array
     557             :            ("4294967296" + \n).  Add one more byte for the
     558             :            terminating '\0' */
     559             : 
     560          22 :         ridbuf_size = (sizeof(char)*11) * num_rids + 1;
     561             : 
     562          22 :         ridlist = (char *)malloc(ridbuf_size);
     563          22 :         BAIL_ON_PTR_ERROR(ridlist, wbc_status);
     564             : 
     565          22 :         len = 0;
     566          46 :         for (i=0; i<num_rids; i++) {
     567          24 :                 len += snprintf(ridlist + len, ridbuf_size - len, "%u\n",
     568          24 :                                 rids[i]);
     569             :         }
     570          22 :         ridlist[len] = '\0';
     571          22 :         len += 1;
     572             : 
     573          22 :         request.extra_data.data = ridlist;
     574          22 :         request.extra_len = len;
     575             : 
     576          22 :         wbc_status = wbcRequestResponse(ctx, WINBINDD_LOOKUPRIDS,
     577             :                                         &request,
     578             :                                         &response);
     579          22 :         free(ridlist);
     580          22 :         BAIL_ON_WBC_ERROR(wbc_status);
     581             : 
     582           2 :         domain_name = wbcStrDup(response.data.domain_name);
     583           2 :         BAIL_ON_PTR_ERROR(domain_name, wbc_status);
     584             : 
     585           2 :         names = wbcAllocateStringArray(num_rids);
     586           2 :         BAIL_ON_PTR_ERROR(names, wbc_status);
     587             : 
     588           2 :         types = (enum wbcSidType *)wbcAllocateMemory(
     589             :                 num_rids, sizeof(enum wbcSidType), NULL);
     590           2 :         BAIL_ON_PTR_ERROR(types, wbc_status);
     591             : 
     592           2 :         p = (char *)response.extra_data.data;
     593             : 
     594           9 :         for (i=0; i<num_rids; i++) {
     595             :                 char *q;
     596             : 
     597           4 :                 if (*p == '\0') {
     598           0 :                         wbc_status = WBC_ERR_INVALID_RESPONSE;
     599           0 :                         goto done;
     600             :                 }
     601             : 
     602           4 :                 types[i] = (enum wbcSidType)smb_strtoul(p,
     603             :                                                         &q,
     604             :                                                         10,
     605             :                                                         &error,
     606             :                                                         SMB_STR_STANDARD);
     607             : 
     608           4 :                 if (*q != ' ' || error != 0) {
     609           0 :                         wbc_status = WBC_ERR_INVALID_RESPONSE;
     610           0 :                         goto done;
     611             :                 }
     612             : 
     613           4 :                 p = q+1;
     614             : 
     615           4 :                 if ((q = strchr(p, '\n')) == NULL) {
     616           0 :                         wbc_status = WBC_ERR_INVALID_RESPONSE;
     617           0 :                         goto done;
     618             :                 }
     619             : 
     620           4 :                 *q = '\0';
     621             : 
     622           4 :                 names[i] = strdup(p);
     623           4 :                 BAIL_ON_PTR_ERROR(names[i], wbc_status);
     624             : 
     625           4 :                 p = q+1;
     626             :         }
     627             : 
     628           2 :         if (*p != '\0') {
     629           0 :                 wbc_status = WBC_ERR_INVALID_RESPONSE;
     630           0 :                 goto done;
     631             :         }
     632             : 
     633           2 :         wbc_status = WBC_ERR_SUCCESS;
     634             : 
     635          22 :  done:
     636          22 :         winbindd_free_response(&response);
     637             : 
     638          22 :         if (WBC_ERROR_IS_OK(wbc_status)) {
     639           2 :                 *pp_domain_name = domain_name;
     640           2 :                 *pnames = names;
     641           2 :                 *ptypes = types;
     642             :         }
     643             :         else {
     644          20 :                 wbcFreeMemory(domain_name);
     645          20 :                 wbcFreeMemory(names);
     646          20 :                 wbcFreeMemory(types);
     647             :         }
     648             : 
     649          22 :         return wbc_status;
     650             : }
     651             : 
     652             : _PUBLIC_
     653          22 : wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid,
     654             :                      int num_rids,
     655             :                      uint32_t *rids,
     656             :                      const char **pp_domain_name,
     657             :                      const char ***pnames,
     658             :                      enum wbcSidType **ptypes)
     659             : {
     660          22 :         return wbcCtxLookupRids(NULL, dom_sid, num_rids, rids,
     661             :                                 pp_domain_name, pnames, ptypes);
     662             : }
     663             : 
     664             : /* Get the groups a user belongs to */
     665             : _PUBLIC_
     666         108 : wbcErr wbcCtxLookupUserSids(struct wbcContext *ctx,
     667             :                             const struct wbcDomainSid *user_sid,
     668             :                             bool domain_groups_only,
     669             :                             uint32_t *num_sids,
     670             :                             struct wbcDomainSid **_sids)
     671             : {
     672             :         uint32_t i;
     673             :         const char *s;
     674             :         struct winbindd_request request;
     675             :         struct winbindd_response response;
     676         108 :         struct wbcDomainSid *sids = NULL;
     677         108 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     678             :         int cmd;
     679             : 
     680             :         /* Initialise request */
     681             : 
     682         108 :         ZERO_STRUCT(request);
     683         108 :         ZERO_STRUCT(response);
     684             : 
     685         108 :         if (!user_sid) {
     686           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     687           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     688             :         }
     689             : 
     690         108 :         wbcSidToStringBuf(user_sid, request.data.sid, sizeof(request.data.sid));
     691             : 
     692         108 :         if (domain_groups_only) {
     693          28 :                 cmd = WINBINDD_GETUSERDOMGROUPS;
     694             :         } else {
     695          80 :                 cmd = WINBINDD_GETUSERSIDS;
     696             :         }
     697             : 
     698         108 :         wbc_status = wbcRequestResponse(ctx, cmd,
     699             :                                         &request,
     700             :                                         &response);
     701         108 :         BAIL_ON_WBC_ERROR(wbc_status);
     702             : 
     703         114 :         if (response.data.num_entries &&
     704          74 :             !response.extra_data.data) {
     705           0 :                 wbc_status = WBC_ERR_INVALID_RESPONSE;
     706           0 :                 BAIL_ON_WBC_ERROR(wbc_status);
     707             :         }
     708             : 
     709          74 :         sids = (struct wbcDomainSid *)wbcAllocateMemory(
     710          74 :                 response.data.num_entries, sizeof(struct wbcDomainSid),
     711             :                 NULL);
     712          74 :         BAIL_ON_PTR_ERROR(sids, wbc_status);
     713             : 
     714          74 :         s = (const char *)response.extra_data.data;
     715         304 :         for (i = 0; i < response.data.num_entries; i++) {
     716         230 :                 char *n = strchr(s, '\n');
     717         230 :                 if (n) {
     718         230 :                         *n = '\0';
     719             :                 }
     720         230 :                 wbc_status = wbcStringToSid(s, &sids[i]);
     721         230 :                 BAIL_ON_WBC_ERROR(wbc_status);
     722         230 :                 s += strlen(s) + 1;
     723             :         }
     724             : 
     725          74 :         *num_sids = response.data.num_entries;
     726          74 :         *_sids = sids;
     727          74 :         sids = NULL;
     728          74 :         wbc_status = WBC_ERR_SUCCESS;
     729             : 
     730         108 :  done:
     731         108 :         winbindd_free_response(&response);
     732         108 :         if (sids) {
     733           0 :                 wbcFreeMemory(sids);
     734             :         }
     735             : 
     736         108 :         return wbc_status;
     737             : }
     738             : 
     739             : _PUBLIC_
     740         108 : wbcErr wbcLookupUserSids(const struct wbcDomainSid *user_sid,
     741             :                          bool domain_groups_only,
     742             :                          uint32_t *num_sids,
     743             :                          struct wbcDomainSid **_sids)
     744             : {
     745         108 :         return wbcCtxLookupUserSids(NULL, user_sid, domain_groups_only,
     746             :                                     num_sids, _sids);
     747             : }
     748             : 
     749             : static inline
     750           2 : wbcErr _sid_to_rid(struct wbcDomainSid *sid, uint32_t *rid)
     751             : {
     752           2 :         if (sid->num_auths < 1) {
     753           0 :                 return WBC_ERR_INVALID_RESPONSE;
     754             :         }
     755           2 :         *rid = sid->sub_auths[sid->num_auths - 1];
     756             : 
     757           2 :         return WBC_ERR_SUCCESS;
     758             : }
     759             : 
     760             : /* Get alias membership for sids */
     761             : _PUBLIC_
     762           2 : wbcErr wbcCtxGetSidAliases(struct wbcContext *ctx,
     763             :                            const struct wbcDomainSid *dom_sid,
     764             :                            struct wbcDomainSid *sids,
     765             :                            uint32_t num_sids,
     766             :                            uint32_t **alias_rids,
     767             :                            uint32_t *num_alias_rids)
     768             : {
     769             :         uint32_t i;
     770             :         const char *s;
     771             :         struct winbindd_request request;
     772             :         struct winbindd_response response;
     773           2 :         ssize_t extra_data_len = 0;
     774           2 :         char * extra_data = NULL;
     775           2 :         ssize_t buflen = 0;
     776             :         struct wbcDomainSid sid;
     777           2 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     778           2 :         uint32_t * rids = NULL;
     779             : 
     780             :         /* Initialise request */
     781             : 
     782           2 :         ZERO_STRUCT(request);
     783           2 :         ZERO_STRUCT(response);
     784             : 
     785           2 :         if (!dom_sid) {
     786           0 :                 wbc_status = WBC_ERR_INVALID_PARAM;
     787           0 :                 goto done;
     788             :         }
     789             : 
     790           2 :         wbcSidToStringBuf(dom_sid, request.data.sid, sizeof(request.data.sid));
     791             : 
     792             :         /* Lets assume each sid is around 57 characters
     793             :          * S-1-5-21-AAAAAAAAAAA-BBBBBBBBBBB-CCCCCCCCCCC-DDDDDDDDDDD\n */
     794           2 :         buflen = 57 * num_sids;
     795           2 :         extra_data = (char *)malloc(buflen);
     796           2 :         if (!extra_data) {
     797           0 :                 wbc_status = WBC_ERR_NO_MEMORY;
     798           0 :                 goto done;
     799             :         }
     800             : 
     801             :         /* Build the sid list */
     802           9 :         for (i=0; i<num_sids; i++) {
     803             :                 char sid_str[WBC_SID_STRING_BUFLEN];
     804             :                 size_t sid_len;
     805             : 
     806           4 :                 sid_len = wbcSidToStringBuf(&sids[i], sid_str, sizeof(sid_str));
     807             : 
     808           4 :                 if (buflen < extra_data_len + sid_len + 2) {
     809           0 :                         char * tmp_data = NULL;
     810           0 :                         buflen *= 2;
     811           0 :                         tmp_data = (char *)realloc(extra_data, buflen);
     812           0 :                         if (!tmp_data) {
     813           0 :                                 wbc_status = WBC_ERR_NO_MEMORY;
     814           0 :                                 BAIL_ON_WBC_ERROR(wbc_status);
     815             :                         }
     816           0 :                         extra_data = tmp_data;
     817             :                 }
     818             : 
     819           4 :                 strncpy(&extra_data[extra_data_len], sid_str,
     820           4 :                         buflen - extra_data_len);
     821           4 :                 extra_data_len += sid_len;
     822           4 :                 extra_data[extra_data_len++] = '\n';
     823           4 :                 extra_data[extra_data_len] = '\0';
     824             :         }
     825           2 :         extra_data_len += 1;
     826             : 
     827           2 :         request.extra_data.data = extra_data;
     828           2 :         request.extra_len = extra_data_len;
     829             : 
     830           2 :         wbc_status = wbcRequestResponse(ctx, WINBINDD_GETSIDALIASES,
     831             :                                         &request,
     832             :                                         &response);
     833           2 :         BAIL_ON_WBC_ERROR(wbc_status);
     834             : 
     835           3 :         if (response.data.num_entries &&
     836           2 :             !response.extra_data.data) {
     837           0 :                 wbc_status = WBC_ERR_INVALID_RESPONSE;
     838           0 :                 goto done;
     839             :         }
     840             : 
     841           2 :         rids = (uint32_t *)wbcAllocateMemory(response.data.num_entries,
     842             :                                              sizeof(uint32_t), NULL);
     843           2 :         BAIL_ON_PTR_ERROR(rids, wbc_status);
     844             : 
     845           2 :         s = (const char *)response.extra_data.data;
     846           4 :         for (i = 0; i < response.data.num_entries; i++) {
     847           2 :                 char *n = strchr(s, '\n');
     848           2 :                 if (n) {
     849           2 :                         *n = '\0';
     850             :                 }
     851           2 :                 wbc_status = wbcStringToSid(s, &sid);
     852           2 :                 BAIL_ON_WBC_ERROR(wbc_status);
     853           2 :                 wbc_status = _sid_to_rid(&sid, &rids[i]);
     854           2 :                 BAIL_ON_WBC_ERROR(wbc_status);
     855           2 :                 s += strlen(s) + 1;
     856             :         }
     857             : 
     858           2 :         *num_alias_rids = response.data.num_entries;
     859           2 :         *alias_rids = rids;
     860           2 :         rids = NULL;
     861           2 :         wbc_status = WBC_ERR_SUCCESS;
     862             : 
     863           2 :  done:
     864           2 :         free(extra_data);
     865           2 :         winbindd_free_response(&response);
     866           2 :         wbcFreeMemory(rids);
     867           2 :         return wbc_status;
     868             : }
     869             : 
     870             : _PUBLIC_
     871           2 : wbcErr wbcGetSidAliases(const struct wbcDomainSid *dom_sid,
     872             :                         struct wbcDomainSid *sids,
     873             :                         uint32_t num_sids,
     874             :                         uint32_t **alias_rids,
     875             :                         uint32_t *num_alias_rids)
     876             : {
     877           2 :         return wbcCtxGetSidAliases(NULL, dom_sid, sids, num_sids,
     878             :                                    alias_rids, num_alias_rids);
     879             : }
     880             : 
     881             : 
     882             : /* Lists Users */
     883             : _PUBLIC_
     884          12 : wbcErr wbcCtxListUsers(struct wbcContext *ctx,
     885             :                        const char *domain_name,
     886             :                        uint32_t *_num_users,
     887             :                        const char ***_users)
     888             : {
     889          12 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     890             :         struct winbindd_request request;
     891             :         struct winbindd_response response;
     892          12 :         uint32_t num_users = 0;
     893          12 :         const char **users = NULL;
     894             :         const char *next;
     895             : 
     896             :         /* Initialise request */
     897             : 
     898          12 :         ZERO_STRUCT(request);
     899          12 :         ZERO_STRUCT(response);
     900             : 
     901          12 :         if (domain_name) {
     902          12 :                 strncpy(request.domain_name, domain_name,
     903             :                         sizeof(request.domain_name)-1);
     904             :         }
     905             : 
     906          12 :         wbc_status = wbcRequestResponse(ctx, WINBINDD_LIST_USERS,
     907             :                                         &request,
     908             :                                         &response);
     909          12 :         BAIL_ON_WBC_ERROR(wbc_status);
     910             : 
     911          12 :         users = wbcAllocateStringArray(response.data.num_entries);
     912          12 :         if (users == NULL) {
     913           0 :                 return WBC_ERR_NO_MEMORY;
     914             :         }
     915             : 
     916             :         /* Look through extra data */
     917             : 
     918          12 :         next = (const char *)response.extra_data.data;
     919         173 :         while (next) {
     920             :                 const char *current;
     921             :                 char *k;
     922             : 
     923         153 :                 if (num_users >= response.data.num_entries) {
     924           0 :                         wbc_status = WBC_ERR_INVALID_RESPONSE;
     925           0 :                         goto done;
     926             :                 }
     927             : 
     928         153 :                 current = next;
     929         153 :                 k = strchr(next, ',');
     930             : 
     931         153 :                 if (k) {
     932         141 :                         k[0] = '\0';
     933         141 :                         next = k+1;
     934             :                 } else {
     935          12 :                         next = NULL;
     936             :                 }
     937             : 
     938         153 :                 users[num_users] = strdup(current);
     939         153 :                 BAIL_ON_PTR_ERROR(users[num_users], wbc_status);
     940         153 :                 num_users += 1;
     941             :         }
     942          12 :         if (num_users != response.data.num_entries) {
     943           0 :                 wbc_status = WBC_ERR_INVALID_RESPONSE;
     944           0 :                 goto done;
     945             :         }
     946             : 
     947          12 :         *_num_users = response.data.num_entries;
     948          12 :         *_users = users;
     949          12 :         users = NULL;
     950          12 :         wbc_status = WBC_ERR_SUCCESS;
     951             : 
     952          12 :  done:
     953          12 :         winbindd_free_response(&response);
     954          12 :         wbcFreeMemory(users);
     955          12 :         return wbc_status;
     956             : }
     957             : 
     958             : _PUBLIC_
     959          12 : wbcErr wbcListUsers(const char *domain_name,
     960             :                     uint32_t *_num_users,
     961             :                     const char ***_users)
     962             : {
     963          12 :         return wbcCtxListUsers(NULL, domain_name, _num_users, _users);
     964             : }
     965             : 
     966             : /* Lists Groups */
     967             : _PUBLIC_
     968          12 : wbcErr wbcCtxListGroups(struct wbcContext *ctx,
     969             :                         const char *domain_name,
     970             :                         uint32_t *_num_groups,
     971             :                         const char ***_groups)
     972             : {
     973          12 :         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
     974             :         struct winbindd_request request;
     975             :         struct winbindd_response response;
     976          12 :         uint32_t num_groups = 0;
     977          12 :         const char **groups = NULL;
     978             :         const char *next;
     979             : 
     980             :         /* Initialise request */
     981             : 
     982          12 :         ZERO_STRUCT(request);
     983          12 :         ZERO_STRUCT(response);
     984             : 
     985          12 :         if (domain_name) {
     986          12 :                 strncpy(request.domain_name, domain_name,
     987             :                         sizeof(request.domain_name)-1);
     988             :         }
     989             : 
     990          12 :         wbc_status = wbcRequestResponse(ctx, WINBINDD_LIST_GROUPS,
     991             :                                         &request,
     992             :                                         &response);
     993          12 :         BAIL_ON_WBC_ERROR(wbc_status);
     994             : 
     995          12 :         groups = wbcAllocateStringArray(response.data.num_entries);
     996          12 :         if (groups == NULL) {
     997           0 :                 return WBC_ERR_NO_MEMORY;
     998             :         }
     999             : 
    1000             :         /* Look through extra data */
    1001             : 
    1002          12 :         next = (const char *)response.extra_data.data;
    1003         238 :         while (next) {
    1004             :                 const char *current;
    1005             :                 char *k;
    1006             : 
    1007         218 :                 if (num_groups >= response.data.num_entries) {
    1008           0 :                         wbc_status = WBC_ERR_INVALID_RESPONSE;
    1009           0 :                         goto done;
    1010             :                 }
    1011             : 
    1012         218 :                 current = next;
    1013         218 :                 k = strchr(next, ',');
    1014             : 
    1015         218 :                 if (k) {
    1016         206 :                         k[0] = '\0';
    1017         206 :                         next = k+1;
    1018             :                 } else {
    1019          12 :                         next = NULL;
    1020             :                 }
    1021             : 
    1022         218 :                 groups[num_groups] = strdup(current);
    1023         218 :                 BAIL_ON_PTR_ERROR(groups[num_groups], wbc_status);
    1024         218 :                 num_groups += 1;
    1025             :         }
    1026          12 :         if (num_groups != response.data.num_entries) {
    1027           0 :                 wbc_status = WBC_ERR_INVALID_RESPONSE;
    1028           0 :                 goto done;
    1029             :         }
    1030             : 
    1031          12 :         *_num_groups = response.data.num_entries;
    1032          12 :         *_groups = groups;
    1033          12 :         groups = NULL;
    1034          12 :         wbc_status = WBC_ERR_SUCCESS;
    1035             : 
    1036          12 :  done:
    1037          12 :         winbindd_free_response(&response);
    1038          12 :         wbcFreeMemory(groups);
    1039          12 :         return wbc_status;
    1040             : }
    1041             : 
    1042             : _PUBLIC_
    1043          12 : wbcErr wbcListGroups(const char *domain_name,
    1044             :                      uint32_t *_num_groups,
    1045             :                      const char ***_groups)
    1046             : {
    1047          12 :         return wbcCtxListGroups(NULL, domain_name, _num_groups, _groups);
    1048             : }
    1049             : 
    1050             : _PUBLIC_
    1051          22 : wbcErr wbcCtxGetDisplayName(struct wbcContext *ctx,
    1052             :                             const struct wbcDomainSid *sid,
    1053             :                             char **pdomain,
    1054             :                             char **pfullname,
    1055             :                             enum wbcSidType *pname_type)
    1056             : {
    1057             :         wbcErr wbc_status;
    1058          22 :         char *domain = NULL;
    1059          22 :         char *name = NULL;
    1060             :         enum wbcSidType name_type;
    1061             : 
    1062          22 :         wbc_status = wbcCtxLookupSid(ctx, sid, &domain, &name, &name_type);
    1063          22 :         BAIL_ON_WBC_ERROR(wbc_status);
    1064             : 
    1065          22 :         if (name_type == WBC_SID_NAME_USER) {
    1066             :                 uid_t uid;
    1067             :                 struct passwd *pwd;
    1068             : 
    1069          22 :                 wbc_status = wbcCtxSidToUid(ctx, sid, &uid);
    1070          22 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1071             : 
    1072          22 :                 wbc_status = wbcCtxGetpwuid(ctx, uid, &pwd);
    1073          22 :                 BAIL_ON_WBC_ERROR(wbc_status);
    1074             : 
    1075          22 :                 wbcFreeMemory(name);
    1076             : 
    1077          22 :                 name = wbcStrDup(pwd->pw_gecos);
    1078          22 :                 wbcFreeMemory(pwd);
    1079          22 :                 BAIL_ON_PTR_ERROR(name, wbc_status);
    1080             :         }
    1081             : 
    1082          22 :         wbc_status = WBC_ERR_SUCCESS;
    1083             : 
    1084          22 :  done:
    1085          22 :         if (WBC_ERROR_IS_OK(wbc_status)) {
    1086          22 :                 *pdomain = domain;
    1087          22 :                 *pfullname = name;
    1088          22 :                 *pname_type = name_type;
    1089             :         } else {
    1090           0 :                 wbcFreeMemory(domain);
    1091           0 :                 wbcFreeMemory(name);
    1092             :         }
    1093             : 
    1094          22 :         return wbc_status;
    1095             : }
    1096             : 
    1097             : _PUBLIC_
    1098          22 : wbcErr wbcGetDisplayName(const struct wbcDomainSid *sid,
    1099             :                          char **pdomain,
    1100             :                          char **pfullname,
    1101             :                          enum wbcSidType *pname_type)
    1102             : {
    1103          22 :         return wbcCtxGetDisplayName(NULL, sid, pdomain, pfullname, pname_type);
    1104             : }
    1105             : 
    1106             : _PUBLIC_
    1107         216 : const char* wbcSidTypeString(enum wbcSidType type)
    1108             : {
    1109         216 :         switch (type) {
    1110           2 :         case WBC_SID_NAME_USE_NONE: return "SID_NONE";
    1111         162 :         case WBC_SID_NAME_USER:     return "SID_USER";
    1112           8 :         case WBC_SID_NAME_DOM_GRP:  return "SID_DOM_GROUP";
    1113          22 :         case WBC_SID_NAME_DOMAIN:   return "SID_DOMAIN";
    1114           4 :         case WBC_SID_NAME_ALIAS:    return "SID_ALIAS";
    1115           8 :         case WBC_SID_NAME_WKN_GRP:  return "SID_WKN_GROUP";
    1116           2 :         case WBC_SID_NAME_DELETED:  return "SID_DELETED";
    1117           2 :         case WBC_SID_NAME_INVALID:  return "SID_INVALID";
    1118           2 :         case WBC_SID_NAME_UNKNOWN:  return "SID_UNKNOWN";
    1119           2 :         case WBC_SID_NAME_COMPUTER: return "SID_COMPUTER";
    1120           2 :         case WBC_SID_NAME_LABEL:    return "SID_LABEL";
    1121           0 :         default:                    return "Unknown type";
    1122             :         }
    1123             : }

Generated by: LCOV version 1.13