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 2009 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 513 /* avoid memmove if last entry */ 514 if (acl->acl_cnt == (j + 1)) { 515 acl->acl_cnt--; 516 break; 517 } 518 519 start = (char *)acl_entry + 520 acl->acl_entry_size; 521 (void) memmove(acl_entry, start, 522 acl->acl_entry_size * 523 (acl->acl_cnt-- - (j + 1))); 524 525 if (flag == ACL_REMOVE_FIRST) 526 break; 527 /* 528 * List has changed, just continue so this 529 * slot gets checked with it's new contents. 530 */ 531 continue; 532 } 533 acl_entry = ((char *)acl_entry + acl->acl_entry_size); 534 if (++j >= acl->acl_cnt) { 535 break; 536 } 537 } 538 remove_entry = (char *)remove_entry + removeacl->acl_entry_size; 539 } 540 541 return ((found == 0) ? EACL_NO_ACL_ENTRY : 0); 542 } 543 544 /* 545 * Replace entires entries in acl1 with the corresponding entries 546 * in newentries. The where argument specifies where to begin 547 * the replacement. If the where argument is 1 greater than the 548 * number of acl entries in acl1 then they are appended. If the 549 * where argument is 2+ greater than the number of acl entries then 550 * EACL_INVALID_SLOT is returned. 551 */ 552 int 553 acl_modifyentries(acl_t *acl1, acl_t *newentries, int where) 554 { 555 556 int slot; 557 int slots_needed; 558 int slots_left; 559 int newsize; 560 561 if (acl1 == NULL || newentries == NULL) 562 return (EACL_NO_ACL_ENTRY); 563 564 if (where < 0 || where >= acl1->acl_cnt) 565 return (EACL_INVALID_SLOT); 566 567 if (acl1->acl_type != newentries->acl_type) 568 return (EACL_DIFF_TYPE); 569 570 slot = where; 571 572 slots_left = acl1->acl_cnt - slot + 1; 573 if (slots_left < newentries->acl_cnt) { 574 slots_needed = newentries->acl_cnt - slots_left; 575 newsize = (acl1->acl_entry_size * acl1->acl_cnt) + 576 (acl1->acl_entry_size * slots_needed); 577 acl1->acl_aclp = realloc(acl1->acl_aclp, newsize); 578 if (acl1->acl_aclp == NULL) 579 return (-1); 580 } 581 (void) memcpy((char *)acl1->acl_aclp + (acl1->acl_entry_size * slot), 582 newentries->acl_aclp, 583 newentries->acl_entry_size * newentries->acl_cnt); 584 585 /* 586 * Did ACL grow? 587 */ 588 589 if ((slot + newentries->acl_cnt) > acl1->acl_cnt) { 590 acl1->acl_cnt = slot + newentries->acl_cnt; 591 } 592 593 return (0); 594 } 595 596 /* 597 * Add acl2 entries into acl1. The where argument specifies where 598 * to add the entries. 599 */ 600 int 601 acl_addentries(acl_t *acl1, acl_t *acl2, int where) 602 { 603 604 int newsize; 605 int len; 606 void *start; 607 void *to; 608 609 if (acl1 == NULL || acl2 == NULL) 610 return (EACL_NO_ACL_ENTRY); 611 612 if (acl1->acl_type != acl2->acl_type) 613 return (EACL_DIFF_TYPE); 614 615 /* 616 * allow where to specify 1 past last slot for an append operation 617 * but anything greater is an error. 618 */ 619 if (where < 0 || where > acl1->acl_cnt) 620 return (EACL_INVALID_SLOT); 621 622 newsize = (acl2->acl_entry_size * acl2->acl_cnt) + 623 (acl1->acl_entry_size * acl1->acl_cnt); 624 acl1->acl_aclp = realloc(acl1->acl_aclp, newsize); 625 if (acl1->acl_aclp == NULL) 626 return (-1); 627 628 /* 629 * first push down entries where new ones will be inserted 630 */ 631 632 to = (void *)((char *)acl1->acl_aclp + 633 ((where + acl2->acl_cnt) * acl1->acl_entry_size)); 634 635 start = (void *)((char *)acl1->acl_aclp + 636 where * acl1->acl_entry_size); 637 638 if (where < acl1->acl_cnt) { 639 len = (acl1->acl_cnt - where) * acl1->acl_entry_size; 640 (void) memmove(to, start, len); 641 } 642 643 /* 644 * now stick in new entries. 645 */ 646 647 (void) memmove(start, acl2->acl_aclp, 648 acl2->acl_cnt * acl2->acl_entry_size); 649 650 acl1->acl_cnt += acl2->acl_cnt; 651 return (0); 652 } 653 654 /* 655 * return text for an ACL error. 656 */ 657 char * 658 acl_strerror(int errnum) 659 { 660 switch (errnum) { 661 case EACL_GRP_ERROR: 662 return (dgettext(TEXT_DOMAIN, 663 "There is more than one group or default group entry")); 664 case EACL_USER_ERROR: 665 return (dgettext(TEXT_DOMAIN, 666 "There is more than one user or default user entry")); 667 case EACL_OTHER_ERROR: 668 return (dgettext(TEXT_DOMAIN, 669 "There is more than one other entry")); 670 case EACL_CLASS_ERROR: 671 return (dgettext(TEXT_DOMAIN, 672 "There is more than one mask entry")); 673 case EACL_DUPLICATE_ERROR: 674 return (dgettext(TEXT_DOMAIN, 675 "Duplicate user or group entries")); 676 case EACL_MISS_ERROR: 677 return (dgettext(TEXT_DOMAIN, 678 "Missing user/group owner, other, mask entry")); 679 case EACL_MEM_ERROR: 680 return (dgettext(TEXT_DOMAIN, 681 "Memory error")); 682 case EACL_ENTRY_ERROR: 683 return (dgettext(TEXT_DOMAIN, 684 "Unrecognized entry type")); 685 case EACL_INHERIT_ERROR: 686 return (dgettext(TEXT_DOMAIN, 687 "Invalid inheritance flags")); 688 case EACL_FLAGS_ERROR: 689 return (dgettext(TEXT_DOMAIN, 690 "Unrecognized entry flags")); 691 case EACL_PERM_MASK_ERROR: 692 return (dgettext(TEXT_DOMAIN, 693 "Invalid ACL permissions")); 694 case EACL_COUNT_ERROR: 695 return (dgettext(TEXT_DOMAIN, 696 "Invalid ACL count")); 697 case EACL_INVALID_SLOT: 698 return (dgettext(TEXT_DOMAIN, 699 "Invalid ACL entry number specified")); 700 case EACL_NO_ACL_ENTRY: 701 return (dgettext(TEXT_DOMAIN, 702 "ACL entry doesn't exist")); 703 case EACL_DIFF_TYPE: 704 return (dgettext(TEXT_DOMAIN, 705 "ACL type's are different")); 706 case EACL_INVALID_USER_GROUP: 707 return (dgettext(TEXT_DOMAIN, "Invalid user or group")); 708 case EACL_INVALID_STR: 709 return (dgettext(TEXT_DOMAIN, "ACL string is invalid")); 710 case EACL_FIELD_NOT_BLANK: 711 return (dgettext(TEXT_DOMAIN, "Field expected to be blank")); 712 case EACL_INVALID_ACCESS_TYPE: 713 return (dgettext(TEXT_DOMAIN, "Invalid access type")); 714 case EACL_UNKNOWN_DATA: 715 return (dgettext(TEXT_DOMAIN, "Unrecognized entry")); 716 case EACL_MISSING_FIELDS: 717 return (dgettext(TEXT_DOMAIN, 718 "ACL specification missing required fields")); 719 case EACL_INHERIT_NOTDIR: 720 return (dgettext(TEXT_DOMAIN, 721 "Inheritance flags are only allowed on directories")); 722 case -1: 723 return (strerror(errno)); 724 default: 725 errno = EINVAL; 726 return (dgettext(TEXT_DOMAIN, "Unknown error")); 727 } 728 } 729 730 extern int yyinteractive; 731 732 /* PRINTFLIKE1 */ 733 void 734 acl_error(const char *fmt, ...) 735 { 736 va_list va; 737 738 if (yyinteractive == 0) 739 return; 740 741 va_start(va, fmt); 742 (void) vfprintf(stderr, fmt, va); 743 va_end(va); 744 } 745 746 int 747 sid_to_id(char *sid, boolean_t user, uid_t *id) 748 { 749 idmap_handle_t *idmap_hdl = NULL; 750 idmap_get_handle_t *get_hdl = NULL; 751 char *rid_start = NULL; 752 idmap_stat status; 753 char *end; 754 int error = 1; 755 char *domain_start; 756 757 if ((domain_start = strchr(sid, '@')) == NULL) { 758 idmap_rid_t rid; 759 760 if ((rid_start = strrchr(sid, '-')) == NULL) 761 return (1); 762 *rid_start++ = '\0'; 763 errno = 0; 764 rid = strtoul(rid_start--, &end, 10); 765 if (errno == 0 && *end == '\0') { 766 if (idmap_init(&idmap_hdl) == IDMAP_SUCCESS && 767 idmap_get_create(idmap_hdl, &get_hdl) == 768 IDMAP_SUCCESS) { 769 if (user) 770 error = idmap_get_uidbysid(get_hdl, 771 sid, rid, IDMAP_REQ_FLG_USE_CACHE, 772 id, &status); 773 else 774 error = idmap_get_gidbysid(get_hdl, 775 sid, rid, IDMAP_REQ_FLG_USE_CACHE, 776 id, &status); 777 if (error == IDMAP_SUCCESS) { 778 error = idmap_get_mappings(get_hdl); 779 if (error == IDMAP_SUCCESS && 780 status != IDMAP_SUCCESS) 781 error = 1; 782 else 783 error = 0; 784 } 785 } else { 786 error = 1; 787 } 788 if (get_hdl) 789 idmap_get_destroy(get_hdl); 790 if (idmap_hdl) 791 (void) idmap_fini(idmap_hdl); 792 } else { 793 error = 1; 794 } 795 *rid_start = '-'; /* putback character removed earlier */ 796 } else { 797 char *name = sid; 798 *domain_start++ = '\0'; 799 800 if (user) 801 error = idmap_getuidbywinname(name, domain_start, 802 IDMAP_REQ_FLG_USE_CACHE, id); 803 else 804 error = idmap_getgidbywinname(name, domain_start, 805 IDMAP_REQ_FLG_USE_CACHE, id); 806 *--domain_start = '@'; 807 error = (error == IDMAP_SUCCESS) ? 0 : 1; 808 } 809 810 return (error); 811 } 812