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 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 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; 395 int acl_flavor; 396 int aclcnt; 397 struct stat64 statbuf; 398 399 acl_flavor = pathconf(file, _PC_ACL_ENABLED); 400 401 if (stat64(file, &statbuf) != 0) { 402 error = 1; 403 return (error); 404 } 405 406 /* 407 * force it through aclent flavor when file system doesn't 408 * understand question 409 */ 410 if (acl_flavor == 0 || acl_flavor == -1) 411 acl_flavor = _ACL_ACLENT_ENABLED; 412 413 if (acl_flavor & _ACL_ACLENT_ENABLED) { 414 min_acl[0].a_type = USER_OBJ; 415 min_acl[0].a_id = owner; 416 min_acl[0].a_perm = ((mode & 0700) >> 6); 417 min_acl[1].a_type = GROUP_OBJ; 418 min_acl[1].a_id = group; 419 min_acl[1].a_perm = ((mode & 0070) >> 3); 420 min_acl[2].a_type = CLASS_OBJ; 421 min_acl[2].a_id = (uid_t)-1; 422 min_acl[2].a_perm = ((mode & 0070) >> 3); 423 min_acl[3].a_type = OTHER_OBJ; 424 min_acl[3].a_id = (uid_t)-1; 425 min_acl[3].a_perm = (mode & 0007); 426 aclcnt = 4; 427 error = acl(file, SETACL, aclcnt, min_acl); 428 } else if (acl_flavor & _ACL_ACE_ENABLED) { 429 if ((error = acl_trivial_create(mode, S_ISDIR(statbuf.st_mode), 430 &min_ace_acl, &aclcnt)) != 0) 431 return (error); 432 error = acl(file, ACE_SETACL, aclcnt, min_ace_acl); 433 free(min_ace_acl); 434 } else { 435 errno = EINVAL; 436 error = 1; 437 } 438 439 if (error == 0) 440 error = chown(file, owner, group); 441 return (error); 442 } 443 444 static int 445 ace_match(void *entry1, void *entry2) 446 { 447 ace_t *p1 = (ace_t *)entry1; 448 ace_t *p2 = (ace_t *)entry2; 449 ace_t ace1, ace2; 450 451 ace1 = *p1; 452 ace2 = *p2; 453 454 /* 455 * Need to fixup who field for abstrations for 456 * accurate comparison, since field is undefined. 457 */ 458 if (ace1.a_flags & (ACE_OWNER|ACE_GROUP|ACE_EVERYONE)) 459 ace1.a_who = (uid_t)-1; 460 if (ace2.a_flags & (ACE_OWNER|ACE_GROUP|ACE_EVERYONE)) 461 ace2.a_who = (uid_t)-1; 462 return (memcmp(&ace1, &ace2, sizeof (ace_t))); 463 } 464 465 static int 466 aclent_match(void *entry1, void *entry2) 467 { 468 aclent_t *aclent1 = (aclent_t *)entry1; 469 aclent_t *aclent2 = (aclent_t *)entry2; 470 471 return (memcmp(aclent1, aclent2, sizeof (aclent_t))); 472 } 473 474 /* 475 * Find acl entries in acl that correspond to removeacl. Search 476 * is started from slot. The flag argument indicates whether to 477 * remove all matches or just the first match. 478 */ 479 int 480 acl_removeentries(acl_t *acl, acl_t *removeacl, int start_slot, int flag) 481 { 482 int i, j; 483 int match; 484 int (*acl_match)(void *acl1, void *acl2); 485 void *acl_entry, *remove_entry; 486 void *start; 487 int found = 0; 488 489 if (flag != ACL_REMOVE_ALL && flag != ACL_REMOVE_FIRST) 490 flag = ACL_REMOVE_FIRST; 491 492 if (acl == NULL || removeacl == NULL) 493 return (EACL_NO_ACL_ENTRY); 494 495 if (acl->acl_type != removeacl->acl_type) 496 return (EACL_DIFF_TYPE); 497 498 if (acl->acl_type == ACLENT_T) 499 acl_match = aclent_match; 500 else 501 acl_match = ace_match; 502 503 for (i = 0, remove_entry = removeacl->acl_aclp; 504 i != removeacl->acl_cnt; i++) { 505 506 j = 0; 507 acl_entry = (char *)acl->acl_aclp + 508 (acl->acl_entry_size * start_slot); 509 for (;;) { 510 match = acl_match(acl_entry, remove_entry); 511 if (match == 0) { 512 found++; 513 514 /* avoid memmove if last entry */ 515 if (acl->acl_cnt == (j + 1)) { 516 acl->acl_cnt--; 517 break; 518 } 519 520 start = (char *)acl_entry + 521 acl->acl_entry_size; 522 (void) memmove(acl_entry, start, 523 acl->acl_entry_size * 524 (acl->acl_cnt-- - (j + 1))); 525 526 if (flag == ACL_REMOVE_FIRST) 527 break; 528 /* 529 * List has changed, just continue so this 530 * slot gets checked with it's new contents. 531 */ 532 continue; 533 } 534 acl_entry = ((char *)acl_entry + acl->acl_entry_size); 535 if (++j >= acl->acl_cnt) { 536 break; 537 } 538 } 539 remove_entry = (char *)remove_entry + removeacl->acl_entry_size; 540 } 541 542 return ((found == 0) ? EACL_NO_ACL_ENTRY : 0); 543 } 544 545 /* 546 * Replace entires entries in acl1 with the corresponding entries 547 * in newentries. The where argument specifies where to begin 548 * the replacement. If the where argument is 1 greater than the 549 * number of acl entries in acl1 then they are appended. If the 550 * where argument is 2+ greater than the number of acl entries then 551 * EACL_INVALID_SLOT is returned. 552 */ 553 int 554 acl_modifyentries(acl_t *acl1, acl_t *newentries, int where) 555 { 556 557 int slot; 558 int slots_needed; 559 int slots_left; 560 int newsize; 561 562 if (acl1 == NULL || newentries == NULL) 563 return (EACL_NO_ACL_ENTRY); 564 565 if (where < 0 || where >= acl1->acl_cnt) 566 return (EACL_INVALID_SLOT); 567 568 if (acl1->acl_type != newentries->acl_type) 569 return (EACL_DIFF_TYPE); 570 571 slot = where; 572 573 slots_left = acl1->acl_cnt - slot + 1; 574 if (slots_left < newentries->acl_cnt) { 575 slots_needed = newentries->acl_cnt - slots_left; 576 newsize = (acl1->acl_entry_size * acl1->acl_cnt) + 577 (acl1->acl_entry_size * slots_needed); 578 acl1->acl_aclp = realloc(acl1->acl_aclp, newsize); 579 if (acl1->acl_aclp == NULL) 580 return (-1); 581 } 582 (void) memcpy((char *)acl1->acl_aclp + (acl1->acl_entry_size * slot), 583 newentries->acl_aclp, 584 newentries->acl_entry_size * newentries->acl_cnt); 585 586 /* 587 * Did ACL grow? 588 */ 589 590 if ((slot + newentries->acl_cnt) > acl1->acl_cnt) { 591 acl1->acl_cnt = slot + newentries->acl_cnt; 592 } 593 594 return (0); 595 } 596 597 /* 598 * Add acl2 entries into acl1. The where argument specifies where 599 * to add the entries. 600 */ 601 int 602 acl_addentries(acl_t *acl1, acl_t *acl2, int where) 603 { 604 605 int newsize; 606 int len; 607 void *start; 608 void *to; 609 610 if (acl1 == NULL || acl2 == NULL) 611 return (EACL_NO_ACL_ENTRY); 612 613 if (acl1->acl_type != acl2->acl_type) 614 return (EACL_DIFF_TYPE); 615 616 /* 617 * allow where to specify 1 past last slot for an append operation 618 * but anything greater is an error. 619 */ 620 if (where < 0 || where > acl1->acl_cnt) 621 return (EACL_INVALID_SLOT); 622 623 newsize = (acl2->acl_entry_size * acl2->acl_cnt) + 624 (acl1->acl_entry_size * acl1->acl_cnt); 625 acl1->acl_aclp = realloc(acl1->acl_aclp, newsize); 626 if (acl1->acl_aclp == NULL) 627 return (-1); 628 629 /* 630 * first push down entries where new ones will be inserted 631 */ 632 633 to = (void *)((char *)acl1->acl_aclp + 634 ((where + acl2->acl_cnt) * acl1->acl_entry_size)); 635 636 start = (void *)((char *)acl1->acl_aclp + 637 where * acl1->acl_entry_size); 638 639 if (where < acl1->acl_cnt) { 640 len = (acl1->acl_cnt - where) * acl1->acl_entry_size; 641 (void) memmove(to, start, len); 642 } 643 644 /* 645 * now stick in new entries. 646 */ 647 648 (void) memmove(start, acl2->acl_aclp, 649 acl2->acl_cnt * acl2->acl_entry_size); 650 651 acl1->acl_cnt += acl2->acl_cnt; 652 return (0); 653 } 654 655 /* 656 * return text for an ACL error. 657 */ 658 char * 659 acl_strerror(int errnum) 660 { 661 switch (errnum) { 662 case EACL_GRP_ERROR: 663 return (dgettext(TEXT_DOMAIN, 664 "There is more than one group or default group entry")); 665 case EACL_USER_ERROR: 666 return (dgettext(TEXT_DOMAIN, 667 "There is more than one user or default user entry")); 668 case EACL_OTHER_ERROR: 669 return (dgettext(TEXT_DOMAIN, 670 "There is more than one other entry")); 671 case EACL_CLASS_ERROR: 672 return (dgettext(TEXT_DOMAIN, 673 "There is more than one mask entry")); 674 case EACL_DUPLICATE_ERROR: 675 return (dgettext(TEXT_DOMAIN, 676 "Duplicate user or group entries")); 677 case EACL_MISS_ERROR: 678 return (dgettext(TEXT_DOMAIN, 679 "Missing user/group owner, other, mask entry")); 680 case EACL_MEM_ERROR: 681 return (dgettext(TEXT_DOMAIN, 682 "Memory error")); 683 case EACL_ENTRY_ERROR: 684 return (dgettext(TEXT_DOMAIN, 685 "Unrecognized entry type")); 686 case EACL_INHERIT_ERROR: 687 return (dgettext(TEXT_DOMAIN, 688 "Invalid inheritance flags")); 689 case EACL_FLAGS_ERROR: 690 return (dgettext(TEXT_DOMAIN, 691 "Unrecognized entry flags")); 692 case EACL_PERM_MASK_ERROR: 693 return (dgettext(TEXT_DOMAIN, 694 "Invalid ACL permissions")); 695 case EACL_COUNT_ERROR: 696 return (dgettext(TEXT_DOMAIN, 697 "Invalid ACL count")); 698 case EACL_INVALID_SLOT: 699 return (dgettext(TEXT_DOMAIN, 700 "Invalid ACL entry number specified")); 701 case EACL_NO_ACL_ENTRY: 702 return (dgettext(TEXT_DOMAIN, 703 "ACL entry doesn't exist")); 704 case EACL_DIFF_TYPE: 705 return (dgettext(TEXT_DOMAIN, 706 "Different file system ACL types cannot be merged")); 707 case EACL_INVALID_USER_GROUP: 708 return (dgettext(TEXT_DOMAIN, "Invalid user or group")); 709 case EACL_INVALID_STR: 710 return (dgettext(TEXT_DOMAIN, "ACL string is invalid")); 711 case EACL_FIELD_NOT_BLANK: 712 return (dgettext(TEXT_DOMAIN, "Field expected to be blank")); 713 case EACL_INVALID_ACCESS_TYPE: 714 return (dgettext(TEXT_DOMAIN, "Invalid access type")); 715 case EACL_UNKNOWN_DATA: 716 return (dgettext(TEXT_DOMAIN, "Unrecognized entry")); 717 case EACL_MISSING_FIELDS: 718 return (dgettext(TEXT_DOMAIN, 719 "ACL specification missing required fields")); 720 case EACL_INHERIT_NOTDIR: 721 return (dgettext(TEXT_DOMAIN, 722 "Inheritance flags are only allowed on directories")); 723 case -1: 724 return (strerror(errno)); 725 default: 726 errno = EINVAL; 727 return (dgettext(TEXT_DOMAIN, "Unknown error")); 728 } 729 } 730 731 extern int yyinteractive; 732 733 /* PRINTFLIKE1 */ 734 void 735 acl_error(const char *fmt, ...) 736 { 737 va_list va; 738 739 if (yyinteractive == 0) 740 return; 741 742 va_start(va, fmt); 743 (void) vfprintf(stderr, fmt, va); 744 va_end(va); 745 } 746 747 int 748 sid_to_id(char *sid, boolean_t user, uid_t *id) 749 { 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_get_create(&get_hdl) == 767 IDMAP_SUCCESS) { 768 if (user) 769 error = idmap_get_uidbysid(get_hdl, 770 sid, rid, IDMAP_REQ_FLG_USE_CACHE, 771 id, &status); 772 else 773 error = idmap_get_gidbysid(get_hdl, 774 sid, rid, IDMAP_REQ_FLG_USE_CACHE, 775 id, &status); 776 if (error == IDMAP_SUCCESS) { 777 error = idmap_get_mappings(get_hdl); 778 if (error == IDMAP_SUCCESS && 779 status != IDMAP_SUCCESS) 780 error = 1; 781 else 782 error = 0; 783 } 784 } else { 785 error = 1; 786 } 787 if (get_hdl) 788 idmap_get_destroy(get_hdl); 789 } else { 790 error = 1; 791 } 792 *rid_start = '-'; /* putback character removed earlier */ 793 } else { 794 char *name = sid; 795 *domain_start++ = '\0'; 796 797 if (user) 798 error = idmap_getuidbywinname(name, domain_start, 799 IDMAP_REQ_FLG_USE_CACHE, id); 800 else 801 error = idmap_getgidbywinname(name, domain_start, 802 IDMAP_REQ_FLG_USE_CACHE, id); 803 *--domain_start = '@'; 804 error = (error == IDMAP_SUCCESS) ? 0 : 1; 805 } 806 807 return (error); 808 } 809