root/nsswitch/libwbclient/wbc_pwd.c

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

DEFINITIONS

This source file includes following definitions.
  1. copy_passwd_entry
  2. copy_group_entry
  3. wbcGetpwnam
  4. wbcGetpwuid
  5. wbcGetpwsid
  6. wbcGetgrnam
  7. wbcGetgrgid
  8. wbcSetpwent
  9. wbcEndpwent
  10. wbcGetpwent
  11. wbcSetgrent
  12. wbcEndgrent
  13. wbcGetgrent
  14. wbcGetgrlist
  15. wbcGetGroups

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

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