1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 #include <stdlib.h> 28 #include <string.h> 29 #include <unistd.h> 30 #include <limits.h> 31 #include <grp.h> 32 #include <pwd.h> 33 #include <strings.h> 34 #include <sys/types.h> 35 #include <errno.h> 36 #include <sys/stat.h> 37 #include <sys/varargs.h> 38 #include <locale.h> 39 #include <aclutils.h> 40 #include <sys/avl.h> 41 #include <acl_common.h> 42 #include <idmap.h> 43 44 #define ACL_PATH 0 45 #define ACL_FD 1 46 47 48 typedef union { 49 const char *file; 50 int fd; 51 } acl_inp; 52 53 54 /* 55 * Determine whether a file has a trivial ACL 56 * returns: 0 = trivial 57 * 1 = nontrivial 58 * <0 some other system failure, such as ENOENT or EPERM 59 */ 60 int 61 acl_trivial(const char *filename) 62 { 63 int acl_flavor; 64 int aclcnt; 65 int cntcmd; 66 int val = 0; 67 ace_t *acep; 68 69 acl_flavor = pathconf(filename, _PC_ACL_ENABLED); 70 71 if (acl_flavor == _ACL_ACE_ENABLED) 72 cntcmd = ACE_GETACLCNT; 73 else 74 cntcmd = GETACLCNT; 75 76 aclcnt = acl(filename, cntcmd, 0, NULL); 77 if (aclcnt > 0) { 78 if (acl_flavor == _ACL_ACE_ENABLED) { 79 acep = malloc(sizeof (ace_t) * aclcnt); 80 if (acep == NULL) 81 return (-1); 82 if (acl(filename, ACE_GETACL, 83 aclcnt, acep) < 0) { 84 free(acep); 85 return (-1); 86 } 87 88 val = ace_trivial(acep, aclcnt); 89 free(acep); 90 91 } else if (aclcnt > MIN_ACL_ENTRIES) 92 val = 1; 93 } 94 return (val); 95 } 96 97 98 static int 99 cacl_get(acl_inp inp, int get_flag, int type, acl_t **aclp) 100 { 101 const char *fname; 102 int fd; 103 int ace_acl = 0; 104 int error; 105 int getcmd, cntcmd; 106 acl_t *acl_info; 107 int save_errno; 108 int stat_error; 109 struct stat64 statbuf; 110 111 *aclp = NULL; 112 if (type == ACL_PATH) { 113 fname = inp.file; 114 ace_acl = pathconf(fname, _PC_ACL_ENABLED); 115 } else { 116 fd = inp.fd; 117 ace_acl = fpathconf(fd, _PC_ACL_ENABLED); 118 } 119 120 /* 121 * if acl's aren't supported then 122 * send it through the old GETACL interface 123 */ 124 if (ace_acl == 0 || ace_acl == -1) { 125 ace_acl = _ACL_ACLENT_ENABLED; 126 } 127 128 if (ace_acl & _ACL_ACE_ENABLED) { 129 cntcmd = ACE_GETACLCNT; 130 getcmd = ACE_GETACL; 131 acl_info = acl_alloc(ACE_T); 132 } else { 133 cntcmd = GETACLCNT; 134 getcmd = GETACL; 135 acl_info = acl_alloc(ACLENT_T); 136 } 137 138 if (acl_info == NULL) 139 return (-1); 140 141 if (type == ACL_PATH) { 142 acl_info->acl_cnt = acl(fname, cntcmd, 0, NULL); 143 } else { 144 acl_info->acl_cnt = facl(fd, cntcmd, 0, NULL); 145 } 146 147 save_errno = errno; 148 if (acl_info->acl_cnt < 0) { 149 acl_free(acl_info); 150 errno = save_errno; 151 return (-1); 152 } 153 154 if (acl_info->acl_cnt == 0) { 155 acl_free(acl_info); 156 errno = save_errno; 157 return (0); 158 } 159 160 acl_info->acl_aclp = 161 malloc(acl_info->acl_cnt * acl_info->acl_entry_size); 162 save_errno = errno; 163 164 if (acl_info->acl_aclp == NULL) { 165 acl_free(acl_info); 166 errno = save_errno; 167 return (-1); 168 } 169 170 if (type == ACL_PATH) { 171 stat_error = stat64(fname, &statbuf); 172 error = acl(fname, getcmd, acl_info->acl_cnt, 173 acl_info->acl_aclp); 174 } else { 175 stat_error = fstat64(fd, &statbuf); 176 error = facl(fd, getcmd, acl_info->acl_cnt, 177 acl_info->acl_aclp); 178 } 179 180 save_errno = errno; 181 if (error == -1) { 182 acl_free(acl_info); 183 errno = save_errno; 184 return (-1); 185 } 186 187 188 if (stat_error == 0) { 189 acl_info->acl_flags = 190 (S_ISDIR(statbuf.st_mode) ? ACL_IS_DIR : 0); 191 } else 192 acl_info->acl_flags = 0; 193 194 switch (acl_info->acl_type) { 195 case ACLENT_T: 196 if (acl_info->acl_cnt <= MIN_ACL_ENTRIES) 197 acl_info->acl_flags |= ACL_IS_TRIVIAL; 198 break; 199 case ACE_T: 200 if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0) 201 acl_info->acl_flags |= ACL_IS_TRIVIAL; 202 break; 203 default: 204 errno = EINVAL; 205 acl_free(acl_info); 206 return (-1); 207 } 208 209 if ((acl_info->acl_flags & ACL_IS_TRIVIAL) && 210 (get_flag & ACL_NO_TRIVIAL)) { 211 acl_free(acl_info); 212 errno = 0; 213 return (0); 214 } 215 216 *aclp = acl_info; 217 return (0); 218 } 219 220 /* 221 * return -1 on failure, otherwise the number of acl 222 * entries is returned 223 */ 224 int 225 acl_get(const char *path, int get_flag, acl_t **aclp) 226 { 227 acl_inp acl_inp; 228 acl_inp.file = path; 229 230 return (cacl_get(acl_inp, get_flag, ACL_PATH, aclp)); 231 } 232 233 int 234 facl_get(int fd, int get_flag, acl_t **aclp) 235 { 236 237 acl_inp acl_inp; 238 acl_inp.fd = fd; 239 240 return (cacl_get(acl_inp, get_flag, ACL_FD, aclp)); 241 } 242 243 /* 244 * Set an ACL, translates acl to ace_t when appropriate. 245 */ 246 static int 247 cacl_set(acl_inp *acl_inp, acl_t *aclp, int type) 248 { 249 int error = 0; 250 int acl_flavor_target; 251 struct stat64 statbuf; 252 int stat_error; 253 int isdir; 254 255 256 if (type == ACL_PATH) { 257 stat_error = stat64(acl_inp->file, &statbuf); 258 if (stat_error) 259 return (-1); 260 acl_flavor_target = pathconf(acl_inp->file, _PC_ACL_ENABLED); 261 } else { 262 stat_error = fstat64(acl_inp->fd, &statbuf); 263 if (stat_error) 264 return (-1); 265 acl_flavor_target = fpathconf(acl_inp->fd, _PC_ACL_ENABLED); 266 } 267 268 /* 269 * If target returns an error or 0 from pathconf call then 270 * fall back to UFS/POSIX Draft interface. 271 * In the case of 0 we will then fail in either acl(2) or 272 * acl_translate(). We could erroneously get 0 back from 273 * a file system that is using fs_pathconf() and not answering 274 * the _PC_ACL_ENABLED question itself. 275 */ 276 if (acl_flavor_target == 0 || acl_flavor_target == -1) 277 acl_flavor_target = _ACL_ACLENT_ENABLED; 278 279 isdir = S_ISDIR(statbuf.st_mode); 280 281 if ((error = acl_translate(aclp, acl_flavor_target, isdir, 282 statbuf.st_uid, statbuf.st_gid)) != 0) { 283 return (error); 284 } 285 286 if (type == ACL_PATH) { 287 error = acl(acl_inp->file, 288 (aclp->acl_type == ACE_T) ? ACE_SETACL : SETACL, 289 aclp->acl_cnt, aclp->acl_aclp); 290 } else { 291 error = facl(acl_inp->fd, 292 (aclp->acl_type == ACE_T) ? ACE_SETACL : SETACL, 293 aclp->acl_cnt, aclp->acl_aclp); 294 } 295 296 return (error); 297 } 298 299 int 300 acl_set(const char *path, acl_t *aclp) 301 { 302 acl_inp acl_inp; 303 304 acl_inp.file = path; 305 306 return (cacl_set(&acl_inp, aclp, ACL_PATH)); 307 } 308 309 int 310 facl_set(int fd, acl_t *aclp) 311 { 312 acl_inp acl_inp; 313 314 acl_inp.fd = fd; 315 316 return (cacl_set(&acl_inp, aclp, ACL_FD)); 317 } 318 319 int 320 acl_cnt(acl_t *aclp) 321 { 322 return (aclp->acl_cnt); 323 } 324 325 int 326 acl_type(acl_t *aclp) 327 { 328 return (aclp->acl_type); 329 } 330 331 acl_t * 332 acl_dup(acl_t *aclp) 333 { 334 acl_t *newaclp; 335 336 newaclp = acl_alloc(aclp->acl_type); 337 if (newaclp == NULL) 338 return (NULL); 339 340 newaclp->acl_aclp = malloc(aclp->acl_entry_size * aclp->acl_cnt); 341 if (newaclp->acl_aclp == NULL) { 342 acl_free(newaclp); 343 return (NULL); 344 } 345 346 (void) memcpy(newaclp->acl_aclp, 347 aclp->acl_aclp, aclp->acl_entry_size * aclp->acl_cnt); 348 newaclp->acl_cnt = aclp->acl_cnt; 349 350 return (newaclp); 351 } 352 353 int 354 acl_flags(acl_t *aclp) 355 { 356 return (aclp->acl_flags); 357 } 358 359 void * 360 acl_data(acl_t *aclp) 361 { 362 return (aclp->acl_aclp); 363 } 364 365 /* 366 * Take an acl array and build an acl_t. 367 */ 368 acl_t * 369 acl_to_aclp(enum acl_type type, void *acl, int count) 370 { 371 acl_t *aclp; 372 373 374 aclp = acl_alloc(type); 375 if (aclp == NULL) 376 return (aclp); 377 378 aclp->acl_aclp = acl; 379 aclp->acl_cnt = count; 380 381 return (aclp); 382 } 383 384 /* 385 * Remove an ACL from a file and create a trivial ACL based 386 * off of the mode argument. After acl has been set owner/group 387 * are updated to match owner,group arguments 388 */ 389 int 390 acl_strip(const char *file, uid_t owner, gid_t group, mode_t mode) 391 { 392 int error = 0; 393 aclent_t min_acl[MIN_ACL_ENTRIES]; 394 ace_t min_ace_acl[6]; /* owner, group, everyone + complement denies */ 395 int acl_flavor; 396 int aclcnt; 397 398 acl_flavor = pathconf(file, _PC_ACL_ENABLED); 399 400 /* 401 * force it through aclent flavor when file system doesn't 402 * understand question 403 */ 404 if (acl_flavor == 0 || acl_flavor == -1) 405 acl_flavor = _ACL_ACLENT_ENABLED; 406 407 if (acl_flavor & _ACL_ACLENT_ENABLED) { 408 min_acl[0].a_type = USER_OBJ; 409 min_acl[0].a_id = owner; 410 min_acl[0].a_perm = ((mode & 0700) >> 6); 411 min_acl[1].a_type = GROUP_OBJ; 412 min_acl[1].a_id = group; 413 min_acl[1].a_perm = ((mode & 0070) >> 3); 414 min_acl[2].a_type = CLASS_OBJ; 415 min_acl[2].a_id = (uid_t)-1; 416 min_acl[2].a_perm = ((mode & 0070) >> 3); 417 min_acl[3].a_type = OTHER_OBJ; 418 min_acl[3].a_id = (uid_t)-1; 419 min_acl[3].a_perm = (mode & 0007); 420 aclcnt = 4; 421 error = acl(file, SETACL, aclcnt, min_acl); 422 } else if (acl_flavor & _ACL_ACE_ENABLED) { 423 (void) memcpy(min_ace_acl, trivial_acl, sizeof (ace_t) * 6); 424 425 /* 426 * Make aces match request mode 427 */ 428 adjust_ace_pair(&min_ace_acl[0], (mode & 0700) >> 6); 429 adjust_ace_pair(&min_ace_acl[2], (mode & 0070) >> 3); 430 adjust_ace_pair(&min_ace_acl[4], mode & 0007); 431 432 error = acl(file, ACE_SETACL, 6, min_ace_acl); 433 } else { 434 errno = EINVAL; 435 error = 1; 436 } 437 438 if (error == 0) 439 error = chown(file, owner, group); 440 return (error); 441 } 442 443 static int 444 ace_match(void *entry1, void *entry2) 445 { 446 ace_t *p1 = (ace_t *)entry1; 447 ace_t *p2 = (ace_t *)entry2; 448 ace_t ace1, ace2; 449 450 ace1 = *p1; 451 ace2 = *p2; 452 453 /* 454 * Need to fixup who field for abstrations for 455 * accurate comparison, since field is undefined. 456 */ 457 if (ace1.a_flags & (ACE_OWNER|ACE_GROUP|ACE_EVERYONE)) 458 ace1.a_who = (uid_t)-1; 459 if (ace2.a_flags & (ACE_OWNER|ACE_GROUP|ACE_EVERYONE)) 460 ace2.a_who = (uid_t)-1; 461 return (memcmp(&ace1, &ace2, sizeof (ace_t))); 462 } 463 464 static int 465 aclent_match(void *entry1, void *entry2) 466 { 467 aclent_t *aclent1 = (aclent_t *)entry1; 468 aclent_t *aclent2 = (aclent_t *)entry2; 469 470 return (memcmp(aclent1, aclent2, sizeof (aclent_t))); 471 } 472 473 /* 474 * Find acl entries in acl that correspond to removeacl. Search 475 * is started from slot. The flag argument indicates whether to 476 * remove all matches or just the first match. 477 */ 478 int 479 acl_removeentries(acl_t *acl, acl_t *removeacl, int start_slot, int flag) 480 { 481 int i, j; 482 int match; 483 int (*acl_match)(void *acl1, void *acl2); 484 void *acl_entry, *remove_entry; 485 void *start; 486 int found = 0; 487 488 if (flag != ACL_REMOVE_ALL && flag != ACL_REMOVE_FIRST) 489 flag = ACL_REMOVE_FIRST; 490 491 if (acl == NULL || removeacl == NULL) 492 return (EACL_NO_ACL_ENTRY); 493 494 if (acl->acl_type != removeacl->acl_type) 495 return (EACL_DIFF_TYPE); 496 497 if (acl->acl_type == ACLENT_T) 498 acl_match = aclent_match; 499 else 500 acl_match = ace_match; 501 502 for (i = 0, remove_entry = removeacl->acl_aclp; 503 i != removeacl->acl_cnt; i++) { 504 505 j = 0; 506 acl_entry = (char *)acl->acl_aclp + 507 (acl->acl_entry_size * start_slot); 508 for (;;) { 509 match = acl_match(acl_entry, remove_entry); 510 if (match == 0) { 511 found++; 512 start = (char *)acl_entry + 513 acl->acl_entry_size; 514 (void) memmove(acl_entry, start, 515 acl->acl_entry_size * 516 acl->acl_cnt-- - (j + 1)); 517 518 if (flag == ACL_REMOVE_FIRST) 519 break; 520 /* 521 * List has changed, just continue so this 522 * slot gets checked with it's new contents. 523 */ 524 continue; 525 } 526 acl_entry = ((char *)acl_entry + acl->acl_entry_size); 527 if (++j >= acl->acl_cnt) { 528 break; 529 } 530 } 531 remove_entry = (char *)remove_entry + removeacl->acl_entry_size; 532 } 533 534 return ((found == 0) ? EACL_NO_ACL_ENTRY : 0); 535 } 536 537 /* 538 * Replace entires entries in acl1 with the corresponding entries 539 * in newentries. The where argument specifies where to begin 540 * the replacement. If the where argument is 1 greater than the 541 * number of acl entries in acl1 then they are appended. If the 542 * where argument is 2+ greater than the number of acl entries then 543 * EACL_INVALID_SLOT is returned. 544 */ 545 int 546 acl_modifyentries(acl_t *acl1, acl_t *newentries, int where) 547 { 548 549 int slot; 550 int slots_needed; 551 int slots_left; 552 int newsize; 553 554 if (acl1 == NULL || newentries == NULL) 555 return (EACL_NO_ACL_ENTRY); 556 557 if (where < 0 || where >= acl1->acl_cnt) 558 return (EACL_INVALID_SLOT); 559 560 if (acl1->acl_type != newentries->acl_type) 561 return (EACL_DIFF_TYPE); 562 563 slot = where; 564 565 slots_left = acl1->acl_cnt - slot + 1; 566 if (slots_left < newentries->acl_cnt) { 567 slots_needed = newentries->acl_cnt - slots_left; 568 newsize = (acl1->acl_entry_size * acl1->acl_cnt) + 569 (acl1->acl_entry_size * slots_needed); 570 acl1->acl_aclp = realloc(acl1->acl_aclp, newsize); 571 if (acl1->acl_aclp == NULL) 572 return (-1); 573 } 574 (void) memcpy((char *)acl1->acl_aclp + (acl1->acl_entry_size * slot), 575 newentries->acl_aclp, 576 newentries->acl_entry_size * newentries->acl_cnt); 577 578 /* 579 * Did ACL grow? 580 */ 581 582 if ((slot + newentries->acl_cnt) > acl1->acl_cnt) { 583 acl1->acl_cnt = slot + newentries->acl_cnt; 584 } 585 586 return (0); 587 } 588 589 /* 590 * Add acl2 entries into acl1. The where argument specifies where 591 * to add the entries. 592 */ 593 int 594 acl_addentries(acl_t *acl1, acl_t *acl2, int where) 595 { 596 597 int newsize; 598 int len; 599 void *start; 600 void *to; 601 602 if (acl1 == NULL || acl2 == NULL) 603 return (EACL_NO_ACL_ENTRY); 604 605 if (acl1->acl_type != acl2->acl_type) 606 return (EACL_DIFF_TYPE); 607 608 /* 609 * allow where to specify 1 past last slot for an append operation 610 * but anything greater is an error. 611 */ 612 if (where < 0 || where > acl1->acl_cnt) 613 return (EACL_INVALID_SLOT); 614 615 newsize = (acl2->acl_entry_size * acl2->acl_cnt) + 616 (acl1->acl_entry_size * acl1->acl_cnt); 617 acl1->acl_aclp = realloc(acl1->acl_aclp, newsize); 618 if (acl1->acl_aclp == NULL) 619 return (-1); 620 621 /* 622 * first push down entries where new ones will be inserted 623 */ 624 625 to = (void *)((char *)acl1->acl_aclp + 626 ((where + acl2->acl_cnt) * acl1->acl_entry_size)); 627 628 start = (void *)((char *)acl1->acl_aclp + 629 where * acl1->acl_entry_size); 630 631 if (where < acl1->acl_cnt) { 632 len = (acl1->acl_cnt - where) * acl1->acl_entry_size; 633 (void) memmove(to, start, len); 634 } 635 636 /* 637 * now stick in new entries. 638 */ 639 640 (void) memmove(start, acl2->acl_aclp, 641 acl2->acl_cnt * acl2->acl_entry_size); 642 643 acl1->acl_cnt += acl2->acl_cnt; 644 return (0); 645 } 646 647 /* 648 * return text for an ACL error. 649 */ 650 char * 651 acl_strerror(int errnum) 652 { 653 switch (errnum) { 654 case EACL_GRP_ERROR: 655 return (dgettext(TEXT_DOMAIN, 656 "There is more than one group or default group entry")); 657 case EACL_USER_ERROR: 658 return (dgettext(TEXT_DOMAIN, 659 "There is more than one user or default user entry")); 660 case EACL_OTHER_ERROR: 661 return (dgettext(TEXT_DOMAIN, 662 "There is more than one other entry")); 663 case EACL_CLASS_ERROR: 664 return (dgettext(TEXT_DOMAIN, 665 "There is more than one mask entry")); 666 case EACL_DUPLICATE_ERROR: 667 return (dgettext(TEXT_DOMAIN, 668 "Duplicate user or group entries")); 669 case EACL_MISS_ERROR: 670 return (dgettext(TEXT_DOMAIN, 671 "Missing user/group owner, other, mask entry")); 672 case EACL_MEM_ERROR: 673 return (dgettext(TEXT_DOMAIN, 674 "Memory error")); 675 case EACL_ENTRY_ERROR: 676 return (dgettext(TEXT_DOMAIN, 677 "Unrecognized entry type")); 678 case EACL_INHERIT_ERROR: 679 return (dgettext(TEXT_DOMAIN, 680 "Invalid inheritance flags")); 681 case EACL_FLAGS_ERROR: 682 return (dgettext(TEXT_DOMAIN, 683 "Unrecognized entry flags")); 684 case EACL_PERM_MASK_ERROR: 685 return (dgettext(TEXT_DOMAIN, 686 "Invalid ACL permissions")); 687 case EACL_COUNT_ERROR: 688 return (dgettext(TEXT_DOMAIN, 689 "Invalid ACL count")); 690 case EACL_INVALID_SLOT: 691 return (dgettext(TEXT_DOMAIN, 692 "Invalid ACL entry number specified")); 693 case EACL_NO_ACL_ENTRY: 694 return (dgettext(TEXT_DOMAIN, 695 "ACL entry doesn't exist")); 696 case EACL_DIFF_TYPE: 697 return (dgettext(TEXT_DOMAIN, 698 "ACL type's are different")); 699 case EACL_INVALID_USER_GROUP: 700 return (dgettext(TEXT_DOMAIN, "Invalid user or group")); 701 case EACL_INVALID_STR: 702 return (dgettext(TEXT_DOMAIN, "ACL string is invalid")); 703 case EACL_FIELD_NOT_BLANK: 704 return (dgettext(TEXT_DOMAIN, "Field expected to be blank")); 705 case EACL_INVALID_ACCESS_TYPE: 706 return (dgettext(TEXT_DOMAIN, "Invalid access type")); 707 case EACL_UNKNOWN_DATA: 708 return (dgettext(TEXT_DOMAIN, "Unrecognized entry")); 709 case EACL_MISSING_FIELDS: 710 return (dgettext(TEXT_DOMAIN, 711 "ACL specification missing required fields")); 712 case EACL_INHERIT_NOTDIR: 713 return (dgettext(TEXT_DOMAIN, 714 "Inheritance flags are only allowed on directories")); 715 case -1: 716 return (strerror(errno)); 717 default: 718 errno = EINVAL; 719 return (dgettext(TEXT_DOMAIN, "Unknown error")); 720 } 721 } 722 723 extern int yyinteractive; 724 725 /* PRINTFLIKE1 */ 726 void 727 acl_error(const char *fmt, ...) 728 { 729 va_list va; 730 731 if (yyinteractive == 0) 732 return; 733 734 va_start(va, fmt); 735 (void) vfprintf(stderr, fmt, va); 736 va_end(va); 737 } 738 739 int 740 sid_to_id(char *sid, boolean_t user, uid_t *id) 741 { 742 idmap_handle_t *idmap_hdl = NULL; 743 idmap_get_handle_t *get_hdl = NULL; 744 char *rid_start = NULL; 745 idmap_stat status; 746 char *end; 747 int error = 1; 748 char *domain_start; 749 750 if ((domain_start = strchr(sid, '@')) == NULL) { 751 idmap_rid_t rid; 752 753 if ((rid_start = strrchr(sid, '-')) == NULL) 754 return (1); 755 *rid_start++ = '\0'; 756 errno = 0; 757 rid = strtoul(rid_start--, &end, 10); 758 if (errno == 0 && *end == '\0') { 759 if (idmap_init(&idmap_hdl) == IDMAP_SUCCESS && 760 idmap_get_create(idmap_hdl, &get_hdl) == 761 IDMAP_SUCCESS) { 762 if (user) 763 error = idmap_get_uidbysid(get_hdl, 764 sid, rid, IDMAP_REQ_FLG_USE_CACHE, 765 id, &status); 766 else 767 error = idmap_get_gidbysid(get_hdl, 768 sid, rid, IDMAP_REQ_FLG_USE_CACHE, 769 id, &status); 770 if (error == IDMAP_SUCCESS) { 771 error = idmap_get_mappings(get_hdl); 772 if (error == IDMAP_SUCCESS && 773 status != IDMAP_SUCCESS) 774 error = 1; 775 else 776 error = 0; 777 } 778 } else { 779 error = 1; 780 } 781 if (get_hdl) 782 idmap_get_destroy(get_hdl); 783 if (idmap_hdl) 784 (void) idmap_fini(idmap_hdl); 785 } else { 786 error = 1; 787 } 788 *rid_start = '-'; /* putback character removed earlier */ 789 } else { 790 char *name = sid; 791 *domain_start++ = '\0'; 792 793 if (user) 794 error = idmap_getuidbywinname(name, domain_start, 795 IDMAP_REQ_FLG_USE_CACHE, id); 796 else 797 error = idmap_getgidbywinname(name, domain_start, 798 IDMAP_REQ_FLG_USE_CACHE, id); 799 *--domain_start = '@'; 800 error = (error == IDMAP_SUCCESS) ? 0 : 1; 801 } 802 803 return (error); 804 } 805