root/nsswitch/winbind_nss_linux.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_static
  2. next_token_alloc
  3. fill_pwent
  4. fill_grent
  5. _nss_winbind_setpwent
  6. _nss_winbind_endpwent
  7. _nss_winbind_getpwent_r
  8. _nss_winbind_getpwuid_r
  9. _nss_winbind_getpwnam_r
  10. _nss_winbind_setgrent
  11. _nss_winbind_endgrent
  12. winbind_getgrent
  13. _nss_winbind_getgrent_r
  14. _nss_winbind_getgrlst_r
  15. _nss_winbind_getgrnam_r
  16. _nss_winbind_getgrgid_r
  17. _nss_winbind_initgroups_dyn
  18. _nss_winbind_getusersids
  19. _nss_winbind_nametosid
  20. _nss_winbind_sidtoname
  21. _nss_winbind_sidtouid
  22. _nss_winbind_sidtogid
  23. _nss_winbind_uidtosid
  24. _nss_winbind_gidtosid

   1 /*
   2    Unix SMB/CIFS implementation.
   3 
   4    Windows NT Domain nsswitch module
   5 
   6    Copyright (C) Tim Potter 2000
   7 
   8    This library is free software; you can redistribute it and/or
   9    modify it under the terms of the GNU Lesser General Public
  10    License as published by the Free Software Foundation; either
  11    version 3 of the License, or (at your option) any later version.
  12 
  13    This library is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16    Library General Public License for more details.
  17 
  18    You should have received a copy of the GNU Lesser General Public License
  19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 #include "winbind_client.h"
  23 
  24 #if HAVE_PTHREAD_H
  25 #include <pthread.h>
  26 #endif
  27 
  28 #if HAVE_PTHREAD
  29 static pthread_mutex_t winbind_nss_mutex = PTHREAD_MUTEX_INITIALIZER;
  30 #endif
  31 
  32 /* Maximum number of users to pass back over the unix domain socket
  33    per call. This is not a static limit on the total number of users
  34    or groups returned in total. */
  35 
  36 #define MAX_GETPWENT_USERS 250
  37 #define MAX_GETGRENT_USERS 250
  38 
  39 NSS_STATUS _nss_winbind_setpwent(void);
  40 NSS_STATUS _nss_winbind_endpwent(void);
  41 NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, char *buffer,
  42                                    size_t buflen, int *errnop);
  43 NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result,
  44                                    char *buffer, size_t buflen, int *errnop);
  45 NSS_STATUS _nss_winbind_getpwnam_r(const char *name, struct passwd *result,
  46                                    char *buffer, size_t buflen, int *errnop);
  47 NSS_STATUS _nss_winbind_setgrent(void);
  48 NSS_STATUS _nss_winbind_endgrent(void);
  49 NSS_STATUS _nss_winbind_getgrent_r(struct group *result, char *buffer,
  50                                    size_t buflen, int *errnop);
  51 NSS_STATUS _nss_winbind_getgrlst_r(struct group *result, char *buffer,
  52                                    size_t buflen, int *errnop);
  53 NSS_STATUS _nss_winbind_getgrnam_r(const char *name, struct group *result,
  54                                    char *buffer, size_t buflen, int *errnop);
  55 NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, struct group *result, char *buffer,
  56                                    size_t buflen, int *errnop);
  57 NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start,
  58                                        long int *size, gid_t **groups,
  59                                        long int limit, int *errnop);
  60 NSS_STATUS _nss_winbind_getusersids(const char *user_sid, char **group_sids,
  61                                     int *num_groups, char *buffer, size_t buf_size,
  62                                     int *errnop);
  63 NSS_STATUS _nss_winbind_nametosid(const char *name, char **sid, char *buffer,
  64                                   size_t buflen, int *errnop);
  65 NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, char *buffer,
  66                                   size_t buflen, int *errnop);
  67 NSS_STATUS _nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop);
  68 NSS_STATUS _nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop);
  69 NSS_STATUS _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer,
  70                                  size_t buflen, int *errnop);
  71 NSS_STATUS _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer,
  72                                  size_t buflen, int *errnop);
  73 
  74 /* Prototypes from wb_common.c */
  75 
  76 /* Allocate some space from the nss static buffer.  The buffer and buflen
  77    are the pointers passed in by the C library to the _nss_ntdom_*
  78    functions. */
  79 
  80 static char *get_static(char **buffer, size_t *buflen, size_t len)
     /* [<][>][^][v][top][bottom][index][help] */
  81 {
  82         char *result;
  83 
  84         /* Error check.  We return false if things aren't set up right, or
  85            there isn't enough buffer space left. */
  86 
  87         if ((buffer == NULL) || (buflen == NULL) || (*buflen < len)) {
  88                 return NULL;
  89         }
  90 
  91         /* Return an index into the static buffer */
  92 
  93         result = *buffer;
  94         *buffer += len;
  95         *buflen -= len;
  96 
  97         return result;
  98 }
  99 
 100 /* I've copied the strtok() replacement function next_token_Xalloc() from
 101    lib/util_str.c as I really don't want to have to link in any other
 102    objects if I can possibly avoid it. */
 103 
 104 static bool next_token_alloc(const char **ptr,
     /* [<][>][^][v][top][bottom][index][help] */
 105                                 char **pp_buff,
 106                                 const char *sep)
 107 {
 108         const char *s;
 109         const char *saved_s;
 110         char *pbuf;
 111         bool quoted;
 112         size_t len=1;
 113 
 114         *pp_buff = NULL;
 115         if (!ptr) {
 116                 return(false);
 117         }
 118 
 119         s = *ptr;
 120 
 121         /* default to simple separators */
 122         if (!sep) {
 123                 sep = " \t\n\r";
 124         }
 125 
 126         /* find the first non sep char */
 127         while (*s && strchr(sep,*s)) {
 128                 s++;
 129         }
 130 
 131         /* nothing left? */
 132         if (!*s) {
 133                 return false;
 134         }
 135 
 136         /* When restarting we need to go from here. */
 137         saved_s = s;
 138 
 139         /* Work out the length needed. */
 140         for (quoted = false; *s &&
 141                         (quoted || !strchr(sep,*s)); s++) {
 142                 if (*s == '\"') {
 143                         quoted = !quoted;
 144                 } else {
 145                         len++;
 146                 }
 147         }
 148 
 149         /* We started with len = 1 so we have space for the nul. */
 150         *pp_buff = (char *)malloc(len);
 151         if (!*pp_buff) {
 152                 return false;
 153         }
 154 
 155         /* copy over the token */
 156         pbuf = *pp_buff;
 157         s = saved_s;
 158         for (quoted = false; *s &&
 159                         (quoted || !strchr(sep,*s)); s++) {
 160                 if ( *s == '\"' ) {
 161                         quoted = !quoted;
 162                 } else {
 163                         *pbuf++ = *s;
 164                 }
 165         }
 166 
 167         *ptr = (*s) ? s+1 : s;
 168         *pbuf = 0;
 169 
 170         return true;
 171 }
 172 
 173 /* Fill a pwent structure from a winbindd_response structure.  We use
 174    the static data passed to us by libc to put strings and stuff in.
 175    Return NSS_STATUS_TRYAGAIN if we run out of memory. */
 176 
 177 static NSS_STATUS fill_pwent(struct passwd *result,
     /* [<][>][^][v][top][bottom][index][help] */
 178                                   struct winbindd_pw *pw,
 179                                   char **buffer, size_t *buflen)
 180 {
 181         /* User name */
 182 
 183         if ((result->pw_name =
 184              get_static(buffer, buflen, strlen(pw->pw_name) + 1)) == NULL) {
 185 
 186                 /* Out of memory */
 187 
 188                 return NSS_STATUS_TRYAGAIN;
 189         }
 190 
 191         strcpy(result->pw_name, pw->pw_name);
 192 
 193         /* Password */
 194 
 195         if ((result->pw_passwd =
 196              get_static(buffer, buflen, strlen(pw->pw_passwd) + 1)) == NULL) {
 197 
 198                 /* Out of memory */
 199 
 200                 return NSS_STATUS_TRYAGAIN;
 201         }
 202 
 203         strcpy(result->pw_passwd, pw->pw_passwd);
 204 
 205         /* [ug]id */
 206 
 207         result->pw_uid = pw->pw_uid;
 208         result->pw_gid = pw->pw_gid;
 209 
 210         /* GECOS */
 211 
 212         if ((result->pw_gecos =
 213              get_static(buffer, buflen, strlen(pw->pw_gecos) + 1)) == NULL) {
 214 
 215                 /* Out of memory */
 216 
 217                 return NSS_STATUS_TRYAGAIN;
 218         }
 219 
 220         strcpy(result->pw_gecos, pw->pw_gecos);
 221 
 222         /* Home directory */
 223 
 224         if ((result->pw_dir =
 225              get_static(buffer, buflen, strlen(pw->pw_dir) + 1)) == NULL) {
 226 
 227                 /* Out of memory */
 228 
 229                 return NSS_STATUS_TRYAGAIN;
 230         }
 231 
 232         strcpy(result->pw_dir, pw->pw_dir);
 233 
 234         /* Logon shell */
 235 
 236         if ((result->pw_shell =
 237              get_static(buffer, buflen, strlen(pw->pw_shell) + 1)) == NULL) {
 238 
 239                 /* Out of memory */
 240 
 241                 return NSS_STATUS_TRYAGAIN;
 242         }
 243 
 244         strcpy(result->pw_shell, pw->pw_shell);
 245 
 246         /* The struct passwd for Solaris has some extra fields which must
 247            be initialised or nscd crashes. */
 248 
 249 #if HAVE_PASSWD_PW_COMMENT
 250         result->pw_comment = "";
 251 #endif
 252 
 253 #if HAVE_PASSWD_PW_AGE
 254         result->pw_age = "";
 255 #endif
 256 
 257         return NSS_STATUS_SUCCESS;
 258 }
 259 
 260 /* Fill a grent structure from a winbindd_response structure.  We use
 261    the static data passed to us by libc to put strings and stuff in.
 262    Return NSS_STATUS_TRYAGAIN if we run out of memory. */
 263 
 264 static NSS_STATUS fill_grent(struct group *result, struct winbindd_gr *gr,
     /* [<][>][^][v][top][bottom][index][help] */
 265                       char *gr_mem, char **buffer, size_t *buflen)
 266 {
 267         char *name;
 268         int i;
 269         char *tst;
 270 
 271         /* Group name */
 272 
 273         if ((result->gr_name =
 274              get_static(buffer, buflen, strlen(gr->gr_name) + 1)) == NULL) {
 275 
 276                 /* Out of memory */
 277 
 278                 return NSS_STATUS_TRYAGAIN;
 279         }
 280 
 281         strcpy(result->gr_name, gr->gr_name);
 282 
 283         /* Password */
 284 
 285         if ((result->gr_passwd =
 286              get_static(buffer, buflen, strlen(gr->gr_passwd) + 1)) == NULL) {
 287 
 288                 /* Out of memory */
 289                 return NSS_STATUS_TRYAGAIN;
 290         }
 291 
 292         strcpy(result->gr_passwd, gr->gr_passwd);
 293 
 294         /* gid */
 295 
 296         result->gr_gid = gr->gr_gid;
 297 
 298         /* Group membership */
 299 
 300         if ((gr->num_gr_mem < 0) || !gr_mem) {
 301                 gr->num_gr_mem = 0;
 302         }
 303 
 304         /* this next value is a pointer to a pointer so let's align it */
 305 
 306         /* Calculate number of extra bytes needed to align on pointer size boundry */
 307         if ((i = (unsigned long)(*buffer) % sizeof(char*)) != 0)
 308                 i = sizeof(char*) - i;
 309 
 310         if ((tst = get_static(buffer, buflen, ((gr->num_gr_mem + 1) *
 311                                  sizeof(char *)+i))) == NULL) {
 312 
 313                 /* Out of memory */
 314 
 315                 return NSS_STATUS_TRYAGAIN;
 316         }
 317         result->gr_mem = (char **)(tst + i);
 318 
 319         if (gr->num_gr_mem == 0) {
 320 
 321                 /* Group is empty */
 322 
 323                 *(result->gr_mem) = NULL;
 324                 return NSS_STATUS_SUCCESS;
 325         }
 326 
 327         /* Start looking at extra data */
 328 
 329         i = 0;
 330 
 331         while(next_token_alloc((const char **)&gr_mem, &name, ",")) {
 332                 /* Allocate space for member */
 333                 if (((result->gr_mem)[i] =
 334                      get_static(buffer, buflen, strlen(name) + 1)) == NULL) {
 335                         free(name);
 336                         /* Out of memory */
 337                         return NSS_STATUS_TRYAGAIN;
 338                 }
 339                 strcpy((result->gr_mem)[i], name);
 340                 free(name);
 341                 i++;
 342         }
 343 
 344         /* Terminate list */
 345 
 346         (result->gr_mem)[i] = NULL;
 347 
 348         return NSS_STATUS_SUCCESS;
 349 }
 350 
 351 /*
 352  * NSS user functions
 353  */
 354 
 355 static struct winbindd_response getpwent_response;
 356 
 357 static int ndx_pw_cache;                 /* Current index into pwd cache */
 358 static int num_pw_cache;                 /* Current size of pwd cache */
 359 
 360 /* Rewind "file pointer" to start of ntdom password database */
 361 
 362 NSS_STATUS
 363 _nss_winbind_setpwent(void)
     /* [<][>][^][v][top][bottom][index][help] */
 364 {
 365         NSS_STATUS ret;
 366 #ifdef DEBUG_NSS
 367         fprintf(stderr, "[%5d]: setpwent\n", getpid());
 368 #endif
 369 
 370 #if HAVE_PTHREAD
 371         pthread_mutex_lock(&winbind_nss_mutex);
 372 #endif
 373 
 374         if (num_pw_cache > 0) {
 375                 ndx_pw_cache = num_pw_cache = 0;
 376                 winbindd_free_response(&getpwent_response);
 377         }
 378 
 379         ret = winbindd_request_response(WINBINDD_SETPWENT, NULL, NULL);
 380 #ifdef DEBUG_NSS
 381         fprintf(stderr, "[%5d]: setpwent returns %s (%d)\n", getpid(),
 382                 nss_err_str(ret), ret);
 383 #endif
 384 
 385 #if HAVE_PTHREAD
 386         pthread_mutex_unlock(&winbind_nss_mutex);
 387 #endif
 388         return ret;
 389 }
 390 
 391 /* Close ntdom password database "file pointer" */
 392 
 393 NSS_STATUS
 394 _nss_winbind_endpwent(void)
     /* [<][>][^][v][top][bottom][index][help] */
 395 {
 396         NSS_STATUS ret;
 397 #ifdef DEBUG_NSS
 398         fprintf(stderr, "[%5d]: endpwent\n", getpid());
 399 #endif
 400 
 401 #if HAVE_PTHREAD
 402         pthread_mutex_lock(&winbind_nss_mutex);
 403 #endif
 404 
 405         if (num_pw_cache > 0) {
 406                 ndx_pw_cache = num_pw_cache = 0;
 407                 winbindd_free_response(&getpwent_response);
 408         }
 409 
 410         ret = winbindd_request_response(WINBINDD_ENDPWENT, NULL, NULL);
 411 #ifdef DEBUG_NSS
 412         fprintf(stderr, "[%5d]: endpwent returns %s (%d)\n", getpid(),
 413                 nss_err_str(ret), ret);
 414 #endif
 415 
 416 #if HAVE_PTHREAD
 417         pthread_mutex_unlock(&winbind_nss_mutex);
 418 #endif
 419 
 420         return ret;
 421 }
 422 
 423 /* Fetch the next password entry from ntdom password database */
 424 
 425 NSS_STATUS
 426 _nss_winbind_getpwent_r(struct passwd *result, char *buffer,
     /* [<][>][^][v][top][bottom][index][help] */
 427                         size_t buflen, int *errnop)
 428 {
 429         NSS_STATUS ret;
 430         struct winbindd_request request;
 431         static int called_again;
 432 
 433 #ifdef DEBUG_NSS
 434         fprintf(stderr, "[%5d]: getpwent\n", getpid());
 435 #endif
 436 
 437 #if HAVE_PTHREAD
 438         pthread_mutex_lock(&winbind_nss_mutex);
 439 #endif
 440 
 441         /* Return an entry from the cache if we have one, or if we are
 442            called again because we exceeded our static buffer.  */
 443 
 444         if ((ndx_pw_cache < num_pw_cache) || called_again) {
 445                 goto return_result;
 446         }
 447 
 448         /* Else call winbindd to get a bunch of entries */
 449 
 450         if (num_pw_cache > 0) {
 451                 winbindd_free_response(&getpwent_response);
 452         }
 453 
 454         ZERO_STRUCT(request);
 455         ZERO_STRUCT(getpwent_response);
 456 
 457         request.data.num_entries = MAX_GETPWENT_USERS;
 458 
 459         ret = winbindd_request_response(WINBINDD_GETPWENT, &request,
 460                                &getpwent_response);
 461 
 462         if (ret == NSS_STATUS_SUCCESS) {
 463                 struct winbindd_pw *pw_cache;
 464 
 465                 /* Fill cache */
 466 
 467                 ndx_pw_cache = 0;
 468                 num_pw_cache = getpwent_response.data.num_entries;
 469 
 470                 /* Return a result */
 471 
 472         return_result:
 473 
 474                 pw_cache = (struct winbindd_pw *)
 475                         getpwent_response.extra_data.data;
 476 
 477                 /* Check data is valid */
 478 
 479                 if (pw_cache == NULL) {
 480                         ret = NSS_STATUS_NOTFOUND;
 481                         goto done;
 482                 }
 483 
 484                 ret = fill_pwent(result, &pw_cache[ndx_pw_cache],
 485                                  &buffer, &buflen);
 486 
 487                 /* Out of memory - try again */
 488 
 489                 if (ret == NSS_STATUS_TRYAGAIN) {
 490                         called_again = true;
 491                         *errnop = errno = ERANGE;
 492                         goto done;
 493                 }
 494 
 495                 *errnop = errno = 0;
 496                 called_again = false;
 497                 ndx_pw_cache++;
 498 
 499                 /* If we've finished with this lot of results free cache */
 500 
 501                 if (ndx_pw_cache == num_pw_cache) {
 502                         ndx_pw_cache = num_pw_cache = 0;
 503                         winbindd_free_response(&getpwent_response);
 504                 }
 505         }
 506         done:
 507 #ifdef DEBUG_NSS
 508         fprintf(stderr, "[%5d]: getpwent returns %s (%d)\n", getpid(),
 509                 nss_err_str(ret), ret);
 510 #endif
 511 
 512 #if HAVE_PTHREAD
 513         pthread_mutex_unlock(&winbind_nss_mutex);
 514 #endif
 515         return ret;
 516 }
 517 
 518 /* Return passwd struct from uid */
 519 
 520 NSS_STATUS
 521 _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer,
     /* [<][>][^][v][top][bottom][index][help] */
 522                         size_t buflen, int *errnop)
 523 {
 524         NSS_STATUS ret;
 525         static struct winbindd_response response;
 526         struct winbindd_request request;
 527         static int keep_response;
 528 
 529 #ifdef DEBUG_NSS
 530         fprintf(stderr, "[%5d]: getpwuid_r %d\n", getpid(), (unsigned int)uid);
 531 #endif
 532 
 533 #if HAVE_PTHREAD
 534         pthread_mutex_lock(&winbind_nss_mutex);
 535 #endif
 536 
 537         /* If our static buffer needs to be expanded we are called again */
 538         if (!keep_response || uid != response.data.pw.pw_uid) {
 539 
 540                 /* Call for the first time */
 541 
 542                 ZERO_STRUCT(response);
 543                 ZERO_STRUCT(request);
 544 
 545                 request.data.uid = uid;
 546 
 547                 ret = winbindd_request_response(WINBINDD_GETPWUID, &request, &response);
 548 
 549                 if (ret == NSS_STATUS_SUCCESS) {
 550                         ret = fill_pwent(result, &response.data.pw,
 551                                          &buffer, &buflen);
 552 
 553                         if (ret == NSS_STATUS_TRYAGAIN) {
 554                                 keep_response = true;
 555                                 *errnop = errno = ERANGE;
 556                                 goto done;
 557                         }
 558                 }
 559 
 560         } else {
 561 
 562                 /* We've been called again */
 563 
 564                 ret = fill_pwent(result, &response.data.pw, &buffer, &buflen);
 565 
 566                 if (ret == NSS_STATUS_TRYAGAIN) {
 567                         *errnop = errno = ERANGE;
 568                         goto done;
 569                 }
 570 
 571                 keep_response = false;
 572                 *errnop = errno = 0;
 573         }
 574 
 575         winbindd_free_response(&response);
 576 
 577         done:
 578 
 579 #ifdef DEBUG_NSS
 580         fprintf(stderr, "[%5d]: getpwuid %d returns %s (%d)\n", getpid(),
 581                 (unsigned int)uid, nss_err_str(ret), ret);
 582 #endif
 583 
 584 #if HAVE_PTHREAD
 585         pthread_mutex_unlock(&winbind_nss_mutex);
 586 #endif
 587 
 588         return ret;
 589 }
 590 
 591 /* Return passwd struct from username */
 592 NSS_STATUS
 593 _nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer,
     /* [<][>][^][v][top][bottom][index][help] */
 594                         size_t buflen, int *errnop)
 595 {
 596         NSS_STATUS ret;
 597         static struct winbindd_response response;
 598         struct winbindd_request request;
 599         static int keep_response;
 600 
 601 #ifdef DEBUG_NSS
 602         fprintf(stderr, "[%5d]: getpwnam_r %s\n", getpid(), name);
 603 #endif
 604 
 605 #if HAVE_PTHREAD
 606         pthread_mutex_lock(&winbind_nss_mutex);
 607 #endif
 608 
 609         /* If our static buffer needs to be expanded we are called again */
 610 
 611         if (!keep_response || strcmp(name,response.data.pw.pw_name) != 0) {
 612 
 613                 /* Call for the first time */
 614 
 615                 ZERO_STRUCT(response);
 616                 ZERO_STRUCT(request);
 617 
 618                 strncpy(request.data.username, name,
 619                         sizeof(request.data.username) - 1);
 620                 request.data.username
 621                         [sizeof(request.data.username) - 1] = '\0';
 622 
 623                 ret = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response);
 624 
 625                 if (ret == NSS_STATUS_SUCCESS) {
 626                         ret = fill_pwent(result, &response.data.pw, &buffer,
 627                                          &buflen);
 628 
 629                         if (ret == NSS_STATUS_TRYAGAIN) {
 630                                 keep_response = true;
 631                                 *errnop = errno = ERANGE;
 632                                 goto done;
 633                         }
 634                 }
 635 
 636         } else {
 637 
 638                 /* We've been called again */
 639 
 640                 ret = fill_pwent(result, &response.data.pw, &buffer, &buflen);
 641 
 642                 if (ret == NSS_STATUS_TRYAGAIN) {
 643                         keep_response = true;
 644                         *errnop = errno = ERANGE;
 645                         goto done;
 646                 }
 647 
 648                 keep_response = false;
 649                 *errnop = errno = 0;
 650         }
 651 
 652         winbindd_free_response(&response);
 653         done:
 654 #ifdef DEBUG_NSS
 655         fprintf(stderr, "[%5d]: getpwnam %s returns %s (%d)\n", getpid(),
 656                 name, nss_err_str(ret), ret);
 657 #endif
 658 
 659 #if HAVE_PTHREAD
 660         pthread_mutex_unlock(&winbind_nss_mutex);
 661 #endif
 662 
 663         return ret;
 664 }
 665 
 666 /*
 667  * NSS group functions
 668  */
 669 
 670 static struct winbindd_response getgrent_response;
 671 
 672 static int ndx_gr_cache;                 /* Current index into grp cache */
 673 static int num_gr_cache;                 /* Current size of grp cache */
 674 
 675 /* Rewind "file pointer" to start of ntdom group database */
 676 
 677 NSS_STATUS
 678 _nss_winbind_setgrent(void)
     /* [<][>][^][v][top][bottom][index][help] */
 679 {
 680         NSS_STATUS ret;
 681 #ifdef DEBUG_NSS
 682         fprintf(stderr, "[%5d]: setgrent\n", getpid());
 683 #endif
 684 
 685 #if HAVE_PTHREAD
 686         pthread_mutex_lock(&winbind_nss_mutex);
 687 #endif
 688 
 689         if (num_gr_cache > 0) {
 690                 ndx_gr_cache = num_gr_cache = 0;
 691                 winbindd_free_response(&getgrent_response);
 692         }
 693 
 694         ret = winbindd_request_response(WINBINDD_SETGRENT, NULL, NULL);
 695 #ifdef DEBUG_NSS
 696         fprintf(stderr, "[%5d]: setgrent returns %s (%d)\n", getpid(),
 697                 nss_err_str(ret), ret);
 698 #endif
 699 
 700 #if HAVE_PTHREAD
 701         pthread_mutex_unlock(&winbind_nss_mutex);
 702 #endif
 703 
 704         return ret;
 705 }
 706 
 707 /* Close "file pointer" for ntdom group database */
 708 
 709 NSS_STATUS
 710 _nss_winbind_endgrent(void)
     /* [<][>][^][v][top][bottom][index][help] */
 711 {
 712         NSS_STATUS ret;
 713 #ifdef DEBUG_NSS
 714         fprintf(stderr, "[%5d]: endgrent\n", getpid());
 715 #endif
 716 
 717 #if HAVE_PTHREAD
 718         pthread_mutex_lock(&winbind_nss_mutex);
 719 #endif
 720 
 721         if (num_gr_cache > 0) {
 722                 ndx_gr_cache = num_gr_cache = 0;
 723                 winbindd_free_response(&getgrent_response);
 724         }
 725 
 726         ret = winbindd_request_response(WINBINDD_ENDGRENT, NULL, NULL);
 727 #ifdef DEBUG_NSS
 728         fprintf(stderr, "[%5d]: endgrent returns %s (%d)\n", getpid(),
 729                 nss_err_str(ret), ret);
 730 #endif
 731 
 732 #if HAVE_PTHREAD
 733         pthread_mutex_unlock(&winbind_nss_mutex);
 734 #endif
 735 
 736         return ret;
 737 }
 738 
 739 /* Get next entry from ntdom group database */
 740 
 741 static NSS_STATUS
 742 winbind_getgrent(enum winbindd_cmd cmd,
     /* [<][>][^][v][top][bottom][index][help] */
 743                  struct group *result,
 744                  char *buffer, size_t buflen, int *errnop)
 745 {
 746         NSS_STATUS ret;
 747         static struct winbindd_request request;
 748         static int called_again;
 749 
 750 
 751 #ifdef DEBUG_NSS
 752         fprintf(stderr, "[%5d]: getgrent\n", getpid());
 753 #endif
 754 
 755 #if HAVE_PTHREAD
 756         pthread_mutex_lock(&winbind_nss_mutex);
 757 #endif
 758 
 759         /* Return an entry from the cache if we have one, or if we are
 760            called again because we exceeded our static buffer.  */
 761 
 762         if ((ndx_gr_cache < num_gr_cache) || called_again) {
 763                 goto return_result;
 764         }
 765 
 766         /* Else call winbindd to get a bunch of entries */
 767 
 768         if (num_gr_cache > 0) {
 769                 winbindd_free_response(&getgrent_response);
 770         }
 771 
 772         ZERO_STRUCT(request);
 773         ZERO_STRUCT(getgrent_response);
 774 
 775         request.data.num_entries = MAX_GETGRENT_USERS;
 776 
 777         ret = winbindd_request_response(cmd, &request,
 778                                &getgrent_response);
 779 
 780         if (ret == NSS_STATUS_SUCCESS) {
 781                 struct winbindd_gr *gr_cache;
 782                 int mem_ofs;
 783 
 784                 /* Fill cache */
 785 
 786                 ndx_gr_cache = 0;
 787                 num_gr_cache = getgrent_response.data.num_entries;
 788 
 789                 /* Return a result */
 790 
 791         return_result:
 792 
 793                 gr_cache = (struct winbindd_gr *)
 794                         getgrent_response.extra_data.data;
 795 
 796                 /* Check data is valid */
 797 
 798                 if (gr_cache == NULL) {
 799                         ret = NSS_STATUS_NOTFOUND;
 800                         goto done;
 801                 }
 802 
 803                 /* Fill group membership.  The offset into the extra data
 804                    for the group membership is the reported offset plus the
 805                    size of all the winbindd_gr records returned. */
 806 
 807                 mem_ofs = gr_cache[ndx_gr_cache].gr_mem_ofs +
 808                         num_gr_cache * sizeof(struct winbindd_gr);
 809 
 810                 ret = fill_grent(result, &gr_cache[ndx_gr_cache],
 811                                  ((char *)getgrent_response.extra_data.data)+mem_ofs,
 812                                  &buffer, &buflen);
 813 
 814                 /* Out of memory - try again */
 815 
 816                 if (ret == NSS_STATUS_TRYAGAIN) {
 817                         called_again = true;
 818                         *errnop = errno = ERANGE;
 819                         goto done;
 820                 }
 821 
 822                 *errnop = 0;
 823                 called_again = false;
 824                 ndx_gr_cache++;
 825 
 826                 /* If we've finished with this lot of results free cache */
 827 
 828                 if (ndx_gr_cache == num_gr_cache) {
 829                         ndx_gr_cache = num_gr_cache = 0;
 830                         winbindd_free_response(&getgrent_response);
 831                 }
 832         }
 833         done:
 834 #ifdef DEBUG_NSS
 835         fprintf(stderr, "[%5d]: getgrent returns %s (%d)\n", getpid(),
 836                 nss_err_str(ret), ret);
 837 #endif
 838 
 839 #if HAVE_PTHREAD
 840         pthread_mutex_unlock(&winbind_nss_mutex);
 841 #endif
 842 
 843         return ret;
 844 }
 845 
 846 
 847 NSS_STATUS
 848 _nss_winbind_getgrent_r(struct group *result,
     /* [<][>][^][v][top][bottom][index][help] */
 849                         char *buffer, size_t buflen, int *errnop)
 850 {
 851         return winbind_getgrent(WINBINDD_GETGRENT, result, buffer, buflen, errnop);
 852 }
 853 
 854 NSS_STATUS
 855 _nss_winbind_getgrlst_r(struct group *result,
     /* [<][>][^][v][top][bottom][index][help] */
 856                         char *buffer, size_t buflen, int *errnop)
 857 {
 858         return winbind_getgrent(WINBINDD_GETGRLST, result, buffer, buflen, errnop);
 859 }
 860 
 861 /* Return group struct from group name */
 862 
 863 NSS_STATUS
 864 _nss_winbind_getgrnam_r(const char *name,
     /* [<][>][^][v][top][bottom][index][help] */
 865                         struct group *result, char *buffer,
 866                         size_t buflen, int *errnop)
 867 {
 868         NSS_STATUS ret;
 869         static struct winbindd_response response;
 870         struct winbindd_request request;
 871         static int keep_response;
 872 
 873 #ifdef DEBUG_NSS
 874         fprintf(stderr, "[%5d]: getgrnam %s\n", getpid(), name);
 875 #endif
 876 
 877 #if HAVE_PTHREAD
 878         pthread_mutex_lock(&winbind_nss_mutex);
 879 #endif
 880 
 881         /* If our static buffer needs to be expanded we are called again */
 882         /* Or if the stored response group name differs from the request. */
 883 
 884         if (!keep_response || strcmp(name,response.data.gr.gr_name) != 0) {
 885 
 886                 /* Call for the first time */
 887 
 888                 ZERO_STRUCT(request);
 889                 ZERO_STRUCT(response);
 890 
 891                 strncpy(request.data.groupname, name,
 892                         sizeof(request.data.groupname));
 893                 request.data.groupname
 894                         [sizeof(request.data.groupname) - 1] = '\0';
 895 
 896                 ret = winbindd_request_response(WINBINDD_GETGRNAM, &request, &response);
 897 
 898                 if (ret == NSS_STATUS_SUCCESS) {
 899                         ret = fill_grent(result, &response.data.gr,
 900                                          (char *)response.extra_data.data,
 901                                          &buffer, &buflen);
 902 
 903                         if (ret == NSS_STATUS_TRYAGAIN) {
 904                                 keep_response = true;
 905                                 *errnop = errno = ERANGE;
 906                                 goto done;
 907                         }
 908                 }
 909 
 910         } else {
 911 
 912                 /* We've been called again */
 913 
 914                 ret = fill_grent(result, &response.data.gr,
 915                                  (char *)response.extra_data.data, &buffer,
 916                                  &buflen);
 917 
 918                 if (ret == NSS_STATUS_TRYAGAIN) {
 919                         keep_response = true;
 920                         *errnop = errno = ERANGE;
 921                         goto done;
 922                 }
 923 
 924                 keep_response = false;
 925                 *errnop = 0;
 926         }
 927 
 928         winbindd_free_response(&response);
 929         done:
 930 #ifdef DEBUG_NSS
 931         fprintf(stderr, "[%5d]: getgrnam %s returns %s (%d)\n", getpid(),
 932                 name, nss_err_str(ret), ret);
 933 #endif
 934 
 935 #if HAVE_PTHREAD
 936         pthread_mutex_unlock(&winbind_nss_mutex);
 937 #endif
 938 
 939         return ret;
 940 }
 941 
 942 /* Return group struct from gid */
 943 
 944 NSS_STATUS
 945 _nss_winbind_getgrgid_r(gid_t gid,
     /* [<][>][^][v][top][bottom][index][help] */
 946                         struct group *result, char *buffer,
 947                         size_t buflen, int *errnop)
 948 {
 949         NSS_STATUS ret;
 950         static struct winbindd_response response;
 951         struct winbindd_request request;
 952         static int keep_response;
 953 
 954 #ifdef DEBUG_NSS
 955         fprintf(stderr, "[%5d]: getgrgid %d\n", getpid(), gid);
 956 #endif
 957 
 958 #if HAVE_PTHREAD
 959         pthread_mutex_lock(&winbind_nss_mutex);
 960 #endif
 961 
 962         /* If our static buffer needs to be expanded we are called again */
 963         /* Or if the stored response group name differs from the request. */
 964 
 965         if (!keep_response || gid != response.data.gr.gr_gid) {
 966 
 967                 /* Call for the first time */
 968 
 969                 ZERO_STRUCT(request);
 970                 ZERO_STRUCT(response);
 971 
 972                 request.data.gid = gid;
 973 
 974                 ret = winbindd_request_response(WINBINDD_GETGRGID, &request, &response);
 975 
 976                 if (ret == NSS_STATUS_SUCCESS) {
 977 
 978                         ret = fill_grent(result, &response.data.gr,
 979                                          (char *)response.extra_data.data,
 980                                          &buffer, &buflen);
 981 
 982                         if (ret == NSS_STATUS_TRYAGAIN) {
 983                                 keep_response = true;
 984                                 *errnop = errno = ERANGE;
 985                                 goto done;
 986                         }
 987                 }
 988 
 989         } else {
 990 
 991                 /* We've been called again */
 992 
 993                 ret = fill_grent(result, &response.data.gr,
 994                                  (char *)response.extra_data.data, &buffer,
 995                                  &buflen);
 996 
 997                 if (ret == NSS_STATUS_TRYAGAIN) {
 998                         keep_response = true;
 999                         *errnop = errno = ERANGE;
1000                         goto done;
1001                 }
1002 
1003                 keep_response = false;
1004                 *errnop = 0;
1005         }
1006 
1007         winbindd_free_response(&response);
1008         done:
1009 #ifdef DEBUG_NSS
1010         fprintf(stderr, "[%5d]: getgrgid %d returns %s (%d)\n", getpid(),
1011                 (unsigned int)gid, nss_err_str(ret), ret);
1012 #endif
1013 
1014 #if HAVE_PTHREAD
1015         pthread_mutex_unlock(&winbind_nss_mutex);
1016 #endif
1017         return ret;
1018 }
1019 
1020 /* Initialise supplementary groups */
1021 
1022 NSS_STATUS
1023 _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start,
     /* [<][>][^][v][top][bottom][index][help] */
1024                             long int *size, gid_t **groups, long int limit,
1025                             int *errnop)
1026 {
1027         NSS_STATUS ret;
1028         struct winbindd_request request;
1029         struct winbindd_response response;
1030         int i;
1031 
1032 #ifdef DEBUG_NSS
1033         fprintf(stderr, "[%5d]: initgroups %s (%d)\n", getpid(),
1034                 user, group);
1035 #endif
1036 
1037 #if HAVE_PTHREAD
1038         pthread_mutex_lock(&winbind_nss_mutex);
1039 #endif
1040 
1041         ZERO_STRUCT(request);
1042         ZERO_STRUCT(response);
1043 
1044         strncpy(request.data.username, user,
1045                 sizeof(request.data.username) - 1);
1046 
1047         ret = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
1048 
1049         if (ret == NSS_STATUS_SUCCESS) {
1050                 int num_gids = response.data.num_entries;
1051                 gid_t *gid_list = (gid_t *)response.extra_data.data;
1052 
1053 #ifdef DEBUG_NSS
1054                 fprintf(stderr, "[%5d]: initgroups %s: got NSS_STATUS_SUCCESS "
1055                                 "and %d gids\n", getpid(),
1056                                 user, num_gids);
1057 #endif
1058                 if (gid_list == NULL) {
1059                         ret = NSS_STATUS_NOTFOUND;
1060                         goto done;
1061                 }
1062 
1063                 /* Copy group list to client */
1064 
1065                 for (i = 0; i < num_gids; i++) {
1066 
1067 #ifdef DEBUG_NSS
1068                         fprintf(stderr, "[%5d]: initgroups %s (%d): "
1069                                         "processing gid %d \n", getpid(),
1070                                         user, group, gid_list[i]);
1071 #endif
1072 
1073                         /* Skip primary group */
1074 
1075                         if (gid_list[i] == group) {
1076                                 continue;
1077                         }
1078 
1079                         /* Filled buffer ? If so, resize. */
1080 
1081                         if (*start == *size) {
1082                                 long int newsize;
1083                                 gid_t *newgroups;
1084 
1085                                 newsize = 2 * (*size);
1086                                 if (limit > 0) {
1087                                         if (*size == limit) {
1088                                                 goto done;
1089                                         }
1090                                         if (newsize > limit) {
1091                                                 newsize = limit;
1092                                         }
1093                                 }
1094 
1095                                 newgroups = (gid_t *)
1096                                         realloc((*groups),
1097                                                 newsize * sizeof(**groups));
1098                                 if (!newgroups) {
1099                                         *errnop = ENOMEM;
1100                                         ret = NSS_STATUS_NOTFOUND;
1101                                         goto done;
1102                                 }
1103                                 *groups = newgroups;
1104                                 *size = newsize;
1105                         }
1106 
1107                         /* Add to buffer */
1108 
1109                         (*groups)[*start] = gid_list[i];
1110                         *start += 1;
1111                 }
1112         }
1113 
1114         /* Back to your regularly scheduled programming */
1115 
1116  done:
1117 #ifdef DEBUG_NSS
1118         fprintf(stderr, "[%5d]: initgroups %s returns %s (%d)\n", getpid(),
1119                 user, nss_err_str(ret), ret);
1120 #endif
1121 
1122 #if HAVE_PTHREAD
1123         pthread_mutex_unlock(&winbind_nss_mutex);
1124 #endif
1125 
1126         return ret;
1127 }
1128 
1129 
1130 /* return a list of group SIDs for a user SID */
1131 NSS_STATUS
1132 _nss_winbind_getusersids(const char *user_sid, char **group_sids,
     /* [<][>][^][v][top][bottom][index][help] */
1133                          int *num_groups,
1134                          char *buffer, size_t buf_size, int *errnop)
1135 {
1136         NSS_STATUS ret;
1137         struct winbindd_request request;
1138         struct winbindd_response response;
1139 
1140 #ifdef DEBUG_NSS
1141         fprintf(stderr, "[%5d]: getusersids %s\n", getpid(), user_sid);
1142 #endif
1143 
1144 #if HAVE_PTHREAD
1145         pthread_mutex_lock(&winbind_nss_mutex);
1146 #endif
1147 
1148         ZERO_STRUCT(request);
1149         ZERO_STRUCT(response);
1150 
1151         strncpy(request.data.sid, user_sid,sizeof(request.data.sid) - 1);
1152         request.data.sid[sizeof(request.data.sid) - 1] = '\0';
1153 
1154         ret = winbindd_request_response(WINBINDD_GETUSERSIDS, &request, &response);
1155 
1156         if (ret != NSS_STATUS_SUCCESS) {
1157                 goto done;
1158         }
1159 
1160         if (buf_size < response.length - sizeof(response)) {
1161                 ret = NSS_STATUS_TRYAGAIN;
1162                 errno = *errnop = ERANGE;
1163                 goto done;
1164         }
1165 
1166         *num_groups = response.data.num_entries;
1167         *group_sids = buffer;
1168         memcpy(buffer, response.extra_data.data, response.length - sizeof(response));
1169         errno = *errnop = 0;
1170 
1171  done:
1172         winbindd_free_response(&response);
1173 
1174 #if HAVE_PTHREAD
1175         pthread_mutex_unlock(&winbind_nss_mutex);
1176 #endif
1177 
1178         return ret;
1179 }
1180 
1181 
1182 /* map a user or group name to a SID string */
1183 NSS_STATUS
1184 _nss_winbind_nametosid(const char *name, char **sid, char *buffer,
     /* [<][>][^][v][top][bottom][index][help] */
1185                        size_t buflen, int *errnop)
1186 {
1187         NSS_STATUS ret;
1188         struct winbindd_response response;
1189         struct winbindd_request request;
1190 
1191 #ifdef DEBUG_NSS
1192         fprintf(stderr, "[%5d]: nametosid %s\n", getpid(), name);
1193 #endif
1194 
1195 #if HAVE_PTHREAD
1196         pthread_mutex_lock(&winbind_nss_mutex);
1197 #endif
1198 
1199         ZERO_STRUCT(response);
1200         ZERO_STRUCT(request);
1201 
1202         strncpy(request.data.name.name, name,
1203                 sizeof(request.data.name.name) - 1);
1204         request.data.name.name[sizeof(request.data.name.name) - 1] = '\0';
1205 
1206         ret = winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response);
1207         if (ret != NSS_STATUS_SUCCESS) {
1208                 *errnop = errno = EINVAL;
1209                 goto failed;
1210         }
1211 
1212         if (buflen < strlen(response.data.sid.sid)+1) {
1213                 ret = NSS_STATUS_TRYAGAIN;
1214                 *errnop = errno = ERANGE;
1215                 goto failed;
1216         }
1217 
1218         *errnop = errno = 0;
1219         *sid = buffer;
1220         strcpy(*sid, response.data.sid.sid);
1221 
1222 failed:
1223         winbindd_free_response(&response);
1224 
1225 #if HAVE_PTHREAD
1226         pthread_mutex_unlock(&winbind_nss_mutex);
1227 #endif
1228 
1229         return ret;
1230 }
1231 
1232 /* map a sid string to a user or group name */
1233 NSS_STATUS
1234 _nss_winbind_sidtoname(const char *sid, char **name, char *buffer,
     /* [<][>][^][v][top][bottom][index][help] */
1235                        size_t buflen, int *errnop)
1236 {
1237         NSS_STATUS ret;
1238         struct winbindd_response response;
1239         struct winbindd_request request;
1240         static char sep_char;
1241         unsigned needed;
1242 
1243 #ifdef DEBUG_NSS
1244         fprintf(stderr, "[%5d]: sidtoname %s\n", getpid(), sid);
1245 #endif
1246 
1247 #if HAVE_PTHREAD
1248         pthread_mutex_lock(&winbind_nss_mutex);
1249 #endif
1250 
1251         ZERO_STRUCT(response);
1252         ZERO_STRUCT(request);
1253 
1254         /* we need to fetch the separator first time through */
1255         if (!sep_char) {
1256                 ret = winbindd_request_response(WINBINDD_INFO, &request, &response);
1257                 if (ret != NSS_STATUS_SUCCESS) {
1258                         *errnop = errno = EINVAL;
1259                         goto failed;
1260                 }
1261 
1262                 sep_char = response.data.info.winbind_separator;
1263                 winbindd_free_response(&response);
1264         }
1265 
1266 
1267         strncpy(request.data.sid, sid,
1268                 sizeof(request.data.sid) - 1);
1269         request.data.sid[sizeof(request.data.sid) - 1] = '\0';
1270 
1271         ret = winbindd_request_response(WINBINDD_LOOKUPSID, &request, &response);
1272         if (ret != NSS_STATUS_SUCCESS) {
1273                 *errnop = errno = EINVAL;
1274                 goto failed;
1275         }
1276 
1277         needed =
1278                 strlen(response.data.name.dom_name) +
1279                 strlen(response.data.name.name) + 2;
1280 
1281         if (buflen < needed) {
1282                 ret = NSS_STATUS_TRYAGAIN;
1283                 *errnop = errno = ERANGE;
1284                 goto failed;
1285         }
1286 
1287         snprintf(buffer, needed, "%s%c%s",
1288                  response.data.name.dom_name,
1289                  sep_char,
1290                  response.data.name.name);
1291 
1292         *name = buffer;
1293         *errnop = errno = 0;
1294 
1295 failed:
1296         winbindd_free_response(&response);
1297 
1298 #if HAVE_PTHREAD
1299         pthread_mutex_unlock(&winbind_nss_mutex);
1300 #endif
1301 
1302         return ret;
1303 }
1304 
1305 /* map a sid to a uid */
1306 NSS_STATUS
1307 _nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop)
     /* [<][>][^][v][top][bottom][index][help] */
1308 {
1309         NSS_STATUS ret;
1310         struct winbindd_response response;
1311         struct winbindd_request request;
1312 
1313 #ifdef DEBUG_NSS
1314         fprintf(stderr, "[%5d]: sidtouid %s\n", getpid(), sid);
1315 #endif
1316 
1317 #if HAVE_PTHREAD
1318         pthread_mutex_lock(&winbind_nss_mutex);
1319 #endif
1320 
1321         ZERO_STRUCT(request);
1322         ZERO_STRUCT(response);
1323 
1324         strncpy(request.data.sid, sid, sizeof(request.data.sid) - 1);
1325         request.data.sid[sizeof(request.data.sid) - 1] = '\0';
1326 
1327         ret = winbindd_request_response(WINBINDD_SID_TO_UID, &request, &response);
1328         if (ret != NSS_STATUS_SUCCESS) {
1329                 *errnop = errno = EINVAL;
1330                 goto failed;
1331         }
1332 
1333         *uid = response.data.uid;
1334 
1335 failed:
1336 
1337 #if HAVE_PTHREAD
1338         pthread_mutex_unlock(&winbind_nss_mutex);
1339 #endif
1340 
1341         return ret;
1342 }
1343 
1344 /* map a sid to a gid */
1345 NSS_STATUS
1346 _nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop)
     /* [<][>][^][v][top][bottom][index][help] */
1347 {
1348         NSS_STATUS ret;
1349         struct winbindd_response response;
1350         struct winbindd_request request;
1351 
1352 #ifdef DEBUG_NSS
1353         fprintf(stderr, "[%5d]: sidtogid %s\n", getpid(), sid);
1354 #endif
1355 
1356 #if HAVE_PTHREAD
1357         pthread_mutex_lock(&winbind_nss_mutex);
1358 #endif
1359 
1360         ZERO_STRUCT(request);
1361         ZERO_STRUCT(response);
1362 
1363         strncpy(request.data.sid, sid, sizeof(request.data.sid) - 1);
1364         request.data.sid[sizeof(request.data.sid) - 1] = '\0';
1365 
1366         ret = winbindd_request_response(WINBINDD_SID_TO_GID, &request, &response);
1367         if (ret != NSS_STATUS_SUCCESS) {
1368                 *errnop = errno = EINVAL;
1369                 goto failed;
1370         }
1371 
1372         *gid = response.data.gid;
1373 
1374 failed:
1375 
1376 #if HAVE_PTHREAD
1377         pthread_mutex_unlock(&winbind_nss_mutex);
1378 #endif
1379 
1380         return ret;
1381 }
1382 
1383 /* map a uid to a SID string */
1384 NSS_STATUS
1385 _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer,
     /* [<][>][^][v][top][bottom][index][help] */
1386                       size_t buflen, int *errnop)
1387 {
1388         NSS_STATUS ret;
1389         struct winbindd_response response;
1390         struct winbindd_request request;
1391 
1392 #ifdef DEBUG_NSS
1393         fprintf(stderr, "[%5u]: uidtosid %u\n", (unsigned int)getpid(), (unsigned int)uid);
1394 #endif
1395 
1396 #if HAVE_PTHREAD
1397         pthread_mutex_lock(&winbind_nss_mutex);
1398 #endif
1399 
1400         ZERO_STRUCT(response);
1401         ZERO_STRUCT(request);
1402 
1403         request.data.uid = uid;
1404 
1405         ret = winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response);
1406         if (ret != NSS_STATUS_SUCCESS) {
1407                 *errnop = errno = EINVAL;
1408                 goto failed;
1409         }
1410 
1411         if (buflen < strlen(response.data.sid.sid)+1) {
1412                 ret = NSS_STATUS_TRYAGAIN;
1413                 *errnop = errno = ERANGE;
1414                 goto failed;
1415         }
1416 
1417         *errnop = errno = 0;
1418         *sid = buffer;
1419         strcpy(*sid, response.data.sid.sid);
1420 
1421 failed:
1422         winbindd_free_response(&response);
1423 
1424 #if HAVE_PTHREAD
1425         pthread_mutex_unlock(&winbind_nss_mutex);
1426 #endif
1427 
1428         return ret;
1429 }
1430 
1431 /* map a gid to a SID string */
1432 NSS_STATUS
1433 _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer,
     /* [<][>][^][v][top][bottom][index][help] */
1434                       size_t buflen, int *errnop)
1435 {
1436         NSS_STATUS ret;
1437         struct winbindd_response response;
1438         struct winbindd_request request;
1439 
1440 #ifdef DEBUG_NSS
1441         fprintf(stderr, "[%5u]: gidtosid %u\n", (unsigned int)getpid(), (unsigned int)gid);
1442 #endif
1443 
1444 #if HAVE_PTHREAD
1445         pthread_mutex_lock(&winbind_nss_mutex);
1446 #endif
1447 
1448         ZERO_STRUCT(response);
1449         ZERO_STRUCT(request);
1450 
1451         request.data.gid = gid;
1452 
1453         ret = winbindd_request_response(WINBINDD_GID_TO_SID, &request, &response);
1454         if (ret != NSS_STATUS_SUCCESS) {
1455                 *errnop = errno = EINVAL;
1456                 goto failed;
1457         }
1458 
1459         if (buflen < strlen(response.data.sid.sid)+1) {
1460                 ret = NSS_STATUS_TRYAGAIN;
1461                 *errnop = errno = ERANGE;
1462                 goto failed;
1463         }
1464 
1465         *errnop = errno = 0;
1466         *sid = buffer;
1467         strcpy(*sid, response.data.sid.sid);
1468 
1469 failed:
1470         winbindd_free_response(&response);
1471 
1472 #if HAVE_PTHREAD
1473         pthread_mutex_unlock(&winbind_nss_mutex);
1474 #endif
1475 
1476         return ret;
1477 }

/* [<][>][^][v][top][bottom][index][help] */