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
acl_trivial(const char * filename)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
cacl_get(acl_inp inp,int get_flag,int type,acl_t ** aclp)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
acl_get(const char * path,int get_flag,acl_t ** aclp)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
facl_get(int fd,int get_flag,acl_t ** aclp)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
cacl_set(acl_inp * acl_inp,acl_t * aclp,int type)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
acl_set(const char * path,acl_t * aclp)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
facl_set(int fd,acl_t * aclp)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
acl_cnt(acl_t * aclp)319 acl_cnt(acl_t *aclp)
320 {
321 return (aclp->acl_cnt);
322 }
323
324 int
acl_type(acl_t * aclp)325 acl_type(acl_t *aclp)
326 {
327 return (aclp->acl_type);
328 }
329
330 acl_t *
acl_dup(acl_t * aclp)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
acl_flags(acl_t * aclp)353 acl_flags(acl_t *aclp)
354 {
355 return (aclp->acl_flags);
356 }
357
358 void *
acl_data(acl_t * aclp)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 *
acl_to_aclp(enum acl_type type,void * acl,int count)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
acl_strip(const char * file,uid_t owner,gid_t group,mode_t mode)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
ace_match(void * entry1,void * entry2)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
aclent_match(void * entry1,void * entry2)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
acl_removeentries(acl_t * acl,acl_t * removeacl,int start_slot,int flag)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
acl_modifyentries(acl_t * acl1,acl_t * newentries,int where)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
acl_addentries(acl_t * acl1,acl_t * acl2,int where)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 *
acl_strerror(int errnum)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
acl_error(const char * fmt,...)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
sid_to_id(char * sid,boolean_t user,uid_t * id)741 sid_to_id(char *sid, boolean_t user, uid_t *id)
742 {
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_get_create(&get_hdl) ==
760 IDMAP_SUCCESS) {
761 if (user)
762 error = idmap_get_uidbysid(get_hdl,
763 sid, rid, IDMAP_REQ_FLG_USE_CACHE,
764 id, &status);
765 else
766 error = idmap_get_gidbysid(get_hdl,
767 sid, rid, IDMAP_REQ_FLG_USE_CACHE,
768 id, &status);
769 if (error == IDMAP_SUCCESS) {
770 error = idmap_get_mappings(get_hdl);
771 if (error == IDMAP_SUCCESS &&
772 status != IDMAP_SUCCESS)
773 error = 1;
774 else
775 error = 0;
776 }
777 } else {
778 error = 1;
779 }
780 if (get_hdl)
781 idmap_get_destroy(get_hdl);
782 } else {
783 error = 1;
784 }
785 *rid_start = '-'; /* putback character removed earlier */
786 } else {
787 char *name = sid;
788 *domain_start++ = '\0';
789
790 if (user)
791 error = idmap_getuidbywinname(name, domain_start,
792 IDMAP_REQ_FLG_USE_CACHE, id);
793 else
794 error = idmap_getgidbywinname(name, domain_start,
795 IDMAP_REQ_FLG_USE_CACHE, id);
796 *--domain_start = '@';
797 error = (error == IDMAP_SUCCESS) ? 0 : 1;
798 }
799
800 return (error);
801 }
802