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