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.
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.
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]
22 * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
34 #include <sys/param.h>
35 #include <sys/types.h>
42 #define ID_STR_MAX 20 /* digits in LONG_MAX */
44 #define APPENDED_ID_MAX ID_STR_MAX + 1 /* id + colon */
46 * yyinteractive controls whether yyparse should print out
47 * error messages to stderr, and whether or not id's should be
48 * allowed from acl_fromtext().
55 extern acl_t
*acl_alloc(enum acl_type
);
58 * dynamic string that will increase in size on an
61 typedef struct dynaclstr
{
62 size_t d_bufsize
; /* current size of aclexport */
67 static int str_append(dynaclstr_t
*, char *);
68 static int aclent_perm_txt(dynaclstr_t
*, o_mode_t
);
71 aclent_perms(int perm
, char *txt_perms
)
89 pruname(uid_t uid
, char *uidp
, size_t buflen
, int noresolve
)
91 struct passwd
*passwdp
= NULL
;
94 passwdp
= getpwuid(uid
);
95 if (passwdp
== (struct passwd
*)NULL
) {
96 /* could not get passwd information: display uid instead */
97 (void) snprintf(uidp
, buflen
, "%u", uid
);
99 (void) strlcpy(uidp
, passwdp
->pw_name
, buflen
);
105 prgname(gid_t gid
, char *gidp
, size_t buflen
, int noresolve
)
107 struct group
*groupp
= NULL
;
110 groupp
= getgrgid(gid
);
111 if (groupp
== (struct group
*)NULL
) {
112 /* could not get group information: display gid instead */
113 (void) snprintf(gidp
, buflen
, "%u", gid
);
115 (void) strlcpy(gidp
, groupp
->gr_name
, buflen
);
121 getsidname(uid_t who
, boolean_t user
, char **sidp
, boolean_t noresolve
)
123 idmap_get_handle_t
*get_hdl
= NULL
;
126 int error
= IDMAP_ERR_NORESULT
;
133 * First try and get windows name
138 error
= idmap_getwinnamebyuid(who
,
139 IDMAP_REQ_FLG_USE_CACHE
, sidp
, NULL
);
141 error
= idmap_getwinnamebygid(who
,
142 IDMAP_REQ_FLG_USE_CACHE
, sidp
, NULL
);
144 if (error
!= IDMAP_SUCCESS
) {
145 if (idmap_get_create(&get_hdl
) == IDMAP_SUCCESS
) {
147 error
= idmap_get_sidbyuid(get_hdl
, who
,
148 IDMAP_REQ_FLG_USE_CACHE
, &domain
, &rid
,
151 error
= idmap_get_sidbygid(get_hdl
, who
,
152 IDMAP_REQ_FLG_USE_CACHE
, &domain
, &rid
,
154 if (error
== IDMAP_SUCCESS
&&
155 idmap_get_mappings(get_hdl
) == 0) {
156 if (status
== IDMAP_SUCCESS
) {
157 len
= snprintf(NULL
, 0,
158 "%s-%d", domain
, rid
);
159 if (*sidp
= malloc(len
+ 1)) {
160 (void) snprintf(*sidp
, len
+ 1,
161 "%s-%d", domain
, rid
);
167 idmap_get_destroy(get_hdl
);
172 return (*sidp
? 0 : 1);
176 aclent_printacl(acl_t
*aclp
)
183 char uidp
[ID_STR_MAX
];
184 char gidp
[ID_STR_MAX
];
186 /* display ACL: assume it is sorted. */
187 aclcnt
= aclp
->acl_cnt
;
188 for (tp
= aclp
->acl_aclp
; tp
&& aclcnt
--; tp
++) {
189 if (tp
->a_type
== CLASS_OBJ
)
192 aclcnt
= aclp
->acl_cnt
;
193 for (tp
= aclp
->acl_aclp
; aclcnt
--; tp
++) {
194 (void) printf(" %d:", slot
++);
195 switch (tp
->a_type
) {
197 aclent_perms(tp
->a_perm
, perm
);
198 (void) printf("user:%s:%s\t\t",
199 pruname(tp
->a_id
, uidp
, sizeof (uidp
), 0), perm
);
200 aclent_perms((tp
->a_perm
& mask
), perm
);
201 (void) printf("#effective:%s\n", perm
);
204 /* no need to display uid */
205 aclent_perms(tp
->a_perm
, perm
);
206 (void) printf("user::%s\n", perm
);
209 aclent_perms(tp
->a_perm
, perm
);
210 (void) printf("group:%s:%s\t\t",
211 prgname(tp
->a_id
, gidp
, sizeof (gidp
), 0), perm
);
212 aclent_perms(tp
->a_perm
& mask
, perm
);
213 (void) printf("#effective:%s\n", perm
);
216 aclent_perms(tp
->a_perm
, perm
);
217 (void) printf("group::%s\t\t", perm
);
218 aclent_perms(tp
->a_perm
& mask
, perm
);
219 (void) printf("#effective:%s\n", perm
);
222 aclent_perms(tp
->a_perm
, perm
);
223 (void) printf("mask:%s\n", perm
);
226 aclent_perms(tp
->a_perm
, perm
);
227 (void) printf("other:%s\n", perm
);
230 aclent_perms(tp
->a_perm
, perm
);
231 (void) printf("default:user:%s:%s\n",
232 pruname(tp
->a_id
, uidp
, sizeof (uidp
), 0), perm
);
235 aclent_perms(tp
->a_perm
, perm
);
236 (void) printf("default:user::%s\n", perm
);
239 aclent_perms(tp
->a_perm
, perm
);
240 (void) printf("default:group:%s:%s\n",
241 prgname(tp
->a_id
, gidp
, sizeof (gidp
), 0), perm
);
244 aclent_perms(tp
->a_perm
, perm
);
245 (void) printf("default:group::%s\n", perm
);
248 aclent_perms(tp
->a_perm
, perm
);
249 (void) printf("default:mask:%s\n", perm
);
252 aclent_perms(tp
->a_perm
, perm
);
253 (void) printf("default:other:%s\n", perm
);
256 (void) fprintf(stderr
,
257 dgettext(TEXT_DOMAIN
, "unrecognized entry\n"));
264 split_line(char *str
, int cols
)
279 for (i
= 0; i
!= len
; i
++) {
280 if ((i
+ pad_len
+ 4) >= cols
) {
281 (void) printf("%s%.*s\n", pad
, last_split
, ptr
);
282 ptr
= &ptr
[last_split
];
288 if (ptr
[i
] == '/' || ptr
[i
] == ':') {
294 (void) printf("%s%s\n", pad
, ptr
);
299 * compute entry type string, such as user:joe, group:staff,...
302 aclent_type_txt(dynaclstr_t
*dstr
, aclent_t
*aclp
, int flags
)
304 char idp
[ID_STR_MAX
];
307 switch (aclp
->a_type
) {
310 if (aclp
->a_type
== USER_OBJ
)
311 error
= str_append(dstr
, "user::");
313 error
= str_append(dstr
, "defaultuser::");
318 if (aclp
->a_type
== USER
)
319 error
= str_append(dstr
, "user:");
321 error
= str_append(dstr
, "defaultuser:");
324 error
= str_append(dstr
, pruname(aclp
->a_id
, idp
,
325 sizeof (idp
), flags
& ACL_NORESOLVE
));
327 error
= str_append(dstr
, ":");
332 if (aclp
->a_type
== GROUP_OBJ
)
333 error
= str_append(dstr
, "group::");
335 error
= str_append(dstr
, "defaultgroup::");
340 if (aclp
->a_type
== GROUP
)
341 error
= str_append(dstr
, "group:");
343 error
= str_append(dstr
, "defaultgroup:");
346 error
= str_append(dstr
, prgname(aclp
->a_id
, idp
,
347 sizeof (idp
), flags
& ACL_NORESOLVE
));
349 error
= str_append(dstr
, ":");
354 if (aclp
->a_type
== CLASS_OBJ
)
355 error
= str_append(dstr
, "mask:");
357 error
= str_append(dstr
, "defaultmask:");
362 if (aclp
->a_type
== OTHER_OBJ
)
363 error
= str_append(dstr
, "other:");
365 error
= str_append(dstr
, "defaultother:");
377 * compute entry type string such as, owner@:, user:joe, group:staff,...
380 ace_type_txt(dynaclstr_t
*dynstr
, ace_t
*acep
, int flags
)
382 char idp
[ID_STR_MAX
];
386 switch (acep
->a_flags
& ACE_TYPE_FLAGS
) {
388 error
= str_append(dynstr
, OWNERAT_TXT
);
391 case ACE_GROUP
|ACE_IDENTIFIER_GROUP
:
392 error
= str_append(dynstr
, GROUPAT_TXT
);
395 case ACE_IDENTIFIER_GROUP
:
396 if ((flags
& ACL_SID_FMT
) && acep
->a_who
> MAXUID
) {
397 if (error
= str_append(dynstr
,
400 if (error
= getsidname(acep
->a_who
, B_FALSE
,
401 &sidp
, flags
& ACL_NORESOLVE
))
403 error
= str_append(dynstr
, sidp
);
405 if (error
= str_append(dynstr
, GROUP_TXT
))
407 error
= str_append(dynstr
, prgname(acep
->a_who
, idp
,
408 sizeof (idp
), flags
& ACL_NORESOLVE
));
411 error
= str_append(dynstr
, ":");
415 error
= str_append(dynstr
, EVERYONEAT_TXT
);
419 if ((flags
& ACL_SID_FMT
) && acep
->a_who
> MAXUID
) {
420 if (error
= str_append(dynstr
, USERSID_TXT
))
422 if (error
= getsidname(acep
->a_who
, B_TRUE
,
423 &sidp
, flags
& ACL_NORESOLVE
))
425 error
= str_append(dynstr
, sidp
);
427 if (error
= str_append(dynstr
, USER_TXT
))
429 error
= str_append(dynstr
, pruname(acep
->a_who
, idp
,
430 sizeof (idp
), flags
& ACL_NORESOLVE
));
433 error
= str_append(dynstr
, ":");
446 * compute string of permissions, such as read_data/write_data or
448 * The format depends on the flags field which indicates whether the compact
449 * or verbose format should be used.
452 ace_perm_txt(dynaclstr_t
*dstr
, uint32_t mask
,
453 uint32_t iflags
, int isdir
, int flags
)
457 if (flags
& ACL_COMPACT_FMT
) {
460 if (mask
& ACE_READ_DATA
)
464 if (mask
& ACE_WRITE_DATA
)
468 if (mask
& ACE_EXECUTE
)
472 if (mask
& ACE_APPEND_DATA
)
476 if (mask
& ACE_DELETE
)
480 if (mask
& ACE_DELETE_CHILD
)
484 if (mask
& ACE_READ_ATTRIBUTES
)
488 if (mask
& ACE_WRITE_ATTRIBUTES
)
492 if (mask
& ACE_READ_NAMED_ATTRS
)
496 if (mask
& ACE_WRITE_NAMED_ATTRS
)
500 if (mask
& ACE_READ_ACL
)
504 if (mask
& ACE_WRITE_ACL
)
508 if (mask
& ACE_WRITE_OWNER
)
512 if (mask
& ACE_SYNCHRONIZE
)
518 error
= str_append(dstr
, buf
);
521 * If ACE is a directory, but inheritance indicates its
522 * for a file then print permissions for file rather than
526 if (mask
& ACE_LIST_DIRECTORY
) {
527 if (iflags
== ACE_FILE_INHERIT_ACE
) {
528 error
= str_append(dstr
,
532 str_append(dstr
, READ_DIR_TXT
);
535 if (error
== 0 && (mask
& ACE_ADD_FILE
)) {
536 if (iflags
== ACE_FILE_INHERIT_ACE
) {
538 str_append(dstr
, WRITE_DATA_TXT
);
541 str_append(dstr
, ADD_FILE_TXT
);
544 if (error
== 0 && (mask
& ACE_ADD_SUBDIRECTORY
)) {
545 if (iflags
== ACE_FILE_INHERIT_ACE
) {
546 error
= str_append(dstr
,
549 error
= str_append(dstr
,
554 if (mask
& ACE_READ_DATA
) {
555 error
= str_append(dstr
, READ_DATA_TXT
);
557 if (error
== 0 && (mask
& ACE_WRITE_DATA
)) {
558 error
= str_append(dstr
, WRITE_DATA_TXT
);
560 if (error
== 0 && (mask
& ACE_APPEND_DATA
)) {
561 error
= str_append(dstr
, APPEND_DATA_TXT
);
564 if (error
== 0 && (mask
& ACE_READ_NAMED_ATTRS
)) {
565 error
= str_append(dstr
, READ_XATTR_TXT
);
567 if (error
== 0 && (mask
& ACE_WRITE_NAMED_ATTRS
)) {
568 error
= str_append(dstr
, WRITE_XATTR_TXT
);
570 if (error
== 0 && (mask
& ACE_EXECUTE
)) {
571 error
= str_append(dstr
, EXECUTE_TXT
);
573 if (error
== 0 && (mask
& ACE_DELETE_CHILD
)) {
574 error
= str_append(dstr
, DELETE_CHILD_TXT
);
576 if (error
== 0 && (mask
& ACE_READ_ATTRIBUTES
)) {
577 error
= str_append(dstr
, READ_ATTRIBUTES_TXT
);
579 if (error
== 0 && (mask
& ACE_WRITE_ATTRIBUTES
)) {
580 error
= str_append(dstr
, WRITE_ATTRIBUTES_TXT
);
582 if (error
== 0 && (mask
& ACE_DELETE
)) {
583 error
= str_append(dstr
, DELETE_TXT
);
585 if (error
== 0 && (mask
& ACE_READ_ACL
)) {
586 error
= str_append(dstr
, READ_ACL_TXT
);
588 if (error
== 0 && (mask
& ACE_WRITE_ACL
)) {
589 error
= str_append(dstr
, WRITE_ACL_TXT
);
591 if (error
== 0 && (mask
& ACE_WRITE_OWNER
)) {
592 error
= str_append(dstr
, WRITE_OWNER_TXT
);
594 if (error
== 0 && (mask
& ACE_SYNCHRONIZE
)) {
595 error
= str_append(dstr
, SYNCHRONIZE_TXT
);
597 if (error
== 0 && dstr
->d_aclexport
[dstr
->d_pos
-1] == '/') {
598 dstr
->d_aclexport
[--dstr
->d_pos
] = '\0';
601 error
= str_append(dstr
, ":");
607 * compute string of access type, such as allow, deny, ...
610 ace_access_txt(dynaclstr_t
*dstr
, int type
)
614 if (type
== ACE_ACCESS_ALLOWED_ACE_TYPE
)
615 error
= str_append(dstr
, ALLOW_TXT
);
616 else if (type
== ACE_ACCESS_DENIED_ACE_TYPE
)
617 error
= str_append(dstr
, DENY_TXT
);
618 else if (type
== ACE_SYSTEM_AUDIT_ACE_TYPE
)
619 error
= str_append(dstr
, AUDIT_TXT
);
620 else if (type
== ACE_SYSTEM_ALARM_ACE_TYPE
)
621 error
= str_append(dstr
, ALARM_TXT
);
623 error
= str_append(dstr
, UNKNOWN_TXT
);
629 ace_inherit_txt(dynaclstr_t
*dstr
, uint32_t iflags
, int flags
)
633 if (flags
& ACL_COMPACT_FMT
) {
636 if (iflags
& ACE_FILE_INHERIT_ACE
)
640 if (iflags
& ACE_DIRECTORY_INHERIT_ACE
)
644 if (iflags
& ACE_INHERIT_ONLY_ACE
)
648 if (iflags
& ACE_NO_PROPAGATE_INHERIT_ACE
)
652 if (iflags
& ACE_SUCCESSFUL_ACCESS_ACE_FLAG
)
656 if (iflags
& ACE_FAILED_ACCESS_ACE_FLAG
)
660 if (iflags
& ACE_INHERITED_ACE
)
666 error
= str_append(dstr
, buf
);
668 if (iflags
& ACE_FILE_INHERIT_ACE
) {
669 error
= str_append(dstr
, FILE_INHERIT_TXT
);
671 if (error
== 0 && (iflags
& ACE_DIRECTORY_INHERIT_ACE
)) {
672 error
= str_append(dstr
, DIR_INHERIT_TXT
);
674 if (error
== 0 && (iflags
& ACE_NO_PROPAGATE_INHERIT_ACE
)) {
675 error
= str_append(dstr
, NO_PROPAGATE_TXT
);
677 if (error
== 0 && (iflags
& ACE_INHERIT_ONLY_ACE
)) {
678 error
= str_append(dstr
, INHERIT_ONLY_TXT
);
680 if (error
== 0 && (iflags
& ACE_SUCCESSFUL_ACCESS_ACE_FLAG
)) {
681 error
= str_append(dstr
, SUCCESSFUL_ACCESS_TXT
);
683 if (error
== 0 && (iflags
& ACE_FAILED_ACCESS_ACE_FLAG
)) {
684 error
= str_append(dstr
, FAILED_ACCESS_TXT
);
686 if (error
== 0 && (iflags
& ACE_INHERITED_ACE
)) {
687 error
= str_append(dstr
, INHERITED_ACE_TXT
);
689 if (error
== 0 && dstr
->d_aclexport
[dstr
->d_pos
-1] == '/') {
690 dstr
->d_aclexport
[--dstr
->d_pos
] = '\0';
691 error
= str_append(dstr
, ":");
699 * Convert internal acl representation to external representation.
701 * The length of a non-owning user name or non-owning group name ie entries
702 * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX. We
703 * thus check the length of these entries, and if greater than LOGNAME_MAX,
704 * we realloc() via increase_length().
706 * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always
711 * acltotext() converts each ACL entry to look like this:
713 * entry_type:uid^gid^name:perms[:id]
715 * The maximum length of entry_type is 14 ("defaultgroup::" and
716 * "defaultother::") hence ENTRYTYPELEN is set to 14.
718 * The max length of a uid^gid^name entry (in theory) is 8, hence we use,
719 * however the ID could be a number so we therefore use ID_STR_MAX
721 * The length of a perms entry is 4 to allow for the comma appended to each
722 * to each acl entry. Hence PERMS is set to 4.
725 #define ENTRYTYPELEN 14
727 #define ACL_ENTRY_SIZE (ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX)
730 aclent_acltotext(aclent_t
*aclp
, int aclcnt
, int flags
)
733 char *aclexport
= NULL
;
739 if ((dstr
= malloc(sizeof (dynaclstr_t
))) == NULL
)
741 dstr
->d_bufsize
= aclcnt
* ACL_ENTRY_SIZE
;
742 if ((dstr
->d_aclexport
= malloc(dstr
->d_bufsize
)) == NULL
) {
746 *dstr
->d_aclexport
= '\0';
749 for (i
= 0; i
< aclcnt
; i
++, aclp
++) {
750 if (error
= aclent_type_txt(dstr
, aclp
, flags
))
752 if (error
= aclent_perm_txt(dstr
, aclp
->a_perm
))
755 if ((flags
& ACL_APPEND_ID
) && ((aclp
->a_type
== USER
) ||
756 (aclp
->a_type
== DEF_USER
) || (aclp
->a_type
== GROUP
) ||
757 (aclp
->a_type
== DEF_GROUP
))) {
758 char id
[ID_STR_MAX
], *idstr
;
760 if (error
= str_append(dstr
, ":"))
762 id
[ID_STR_MAX
- 1] = '\0'; /* null terminate buffer */
763 idstr
= lltostr(aclp
->a_id
, &id
[ID_STR_MAX
- 1]);
764 if (error
= str_append(dstr
, idstr
))
768 if (error
= str_append(dstr
, ","))
772 if (dstr
->d_aclexport
)
773 free(dstr
->d_aclexport
);
775 aclexport
= dstr
->d_aclexport
;
782 acltotext(aclent_t
*aclp
, int aclcnt
)
784 return (aclent_acltotext(aclp
, aclcnt
, 0));
789 aclfromtext(char *aclstr
, int *aclcnt
)
795 error
= acl_fromtext(aclstr
, &aclp
);
799 aclentp
= aclp
->acl_aclp
;
800 aclp
->acl_aclp
= NULL
;
801 *aclcnt
= aclp
->acl_cnt
;
809 * Append string onto dynaclstr_t.
811 * Return 0 on success, 1 for failure.
814 str_append(dynaclstr_t
*dstr
, char *newstr
)
816 size_t len
= strlen(newstr
);
818 if ((len
+ dstr
->d_pos
) >= dstr
->d_bufsize
) {
819 dstr
->d_aclexport
= realloc(dstr
->d_aclexport
,
820 dstr
->d_bufsize
+ len
+ 1);
821 if (dstr
->d_aclexport
== NULL
)
823 dstr
->d_bufsize
+= len
;
825 (void) strcat(&dstr
->d_aclexport
[dstr
->d_pos
], newstr
);
831 aclent_perm_txt(dynaclstr_t
*dstr
, o_mode_t perm
)
848 return (str_append(dstr
, buf
));
852 * ace_acltotext() convert each ace formatted acl to look like this:
854 * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,]
856 * The maximum length of entry_type is 5 ("group")
858 * The max length of a uid^gid^name entry (in theory) is 8,
859 * however id could be a number so we therefore use ID_STR_MAX
861 * The length of a perms entry is 144 i.e read_data/write_data...
864 * iflags: file_inherit/dir_inherit/inherit_only/no_propagate/successful_access
869 #define ACE_ENTRYTYPLEN 6
870 #define IFLAGS_STR "file_inherit/dir_inherit/inherit_only/no_propagate/" \
871 "successful_access/failed_access/inherited"
872 #define IFLAGS_SIZE (sizeof (IFLAGS_STR) - 1)
873 #define ACCESS_TYPE_SIZE 7 /* if unknown */
875 #define PERMS_LEN 216
876 #define ACE_ENTRY_SIZE (ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN + \
877 ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX)
880 ace_acltotext(acl_t
*aceaclp
, int flags
)
882 ace_t
*aclp
= aceaclp
->acl_aclp
;
883 int aclcnt
= aceaclp
->acl_cnt
;
886 int isdir
= (aceaclp
->acl_flags
& ACL_IS_DIR
);
888 char *aclexport
= NULL
;
889 char *rawsidp
= NULL
;
894 if ((dstr
= malloc(sizeof (dynaclstr_t
))) == NULL
)
896 dstr
->d_bufsize
= aclcnt
* ACL_ENTRY_SIZE
;
897 if ((dstr
->d_aclexport
= malloc(dstr
->d_bufsize
)) == NULL
) {
901 *dstr
->d_aclexport
= '\0';
904 for (i
= 0; i
< aclcnt
; i
++, aclp
++) {
906 if (error
= ace_type_txt(dstr
, aclp
, flags
))
908 if (error
= ace_perm_txt(dstr
, aclp
->a_access_mask
,
909 aclp
->a_flags
, isdir
, flags
))
911 if (error
= ace_inherit_txt(dstr
, aclp
->a_flags
, flags
))
913 if (error
= ace_access_txt(dstr
, aclp
->a_type
))
916 if ((flags
& ACL_APPEND_ID
) &&
917 (((aclp
->a_flags
& ACE_TYPE_FLAGS
) == 0) ||
918 ((aclp
->a_flags
& ACE_TYPE_FLAGS
) ==
919 ACE_IDENTIFIER_GROUP
))) {
920 char id
[ID_STR_MAX
], *idstr
;
922 if (error
= str_append(dstr
, ":"))
926 id
[ID_STR_MAX
-1] = '\0'; /* null terminate */
927 if (aclp
->a_who
> MAXUID
&& (flags
& ACL_SID_FMT
)) {
929 error
= getsidname(aclp
->a_who
,
930 ((aclp
->a_flags
& ACE_TYPE_FLAGS
) == 0) ?
931 B_TRUE
: B_FALSE
, &idstr
, 1);
935 } else if (aclp
->a_who
> MAXUID
&&
936 !(flags
& ACL_NORESOLVE
)) {
937 idstr
= lltostr(UID_NOBODY
,
938 &id
[ID_STR_MAX
- 1]);
940 idstr
= lltostr(aclp
->a_who
,
941 &id
[ID_STR_MAX
- 1]);
943 if (error
= str_append(dstr
, idstr
))
950 if (i
< aclcnt
- 1) {
951 if (error
= str_append(dstr
, ","))
959 if (dstr
->d_aclexport
)
960 free(dstr
->d_aclexport
);
962 aclexport
= dstr
->d_aclexport
;
969 acl_totext(acl_t
*aclp
, int flags
)
976 switch (aclp
->acl_type
) {
978 txtp
= ace_acltotext(aclp
, flags
);
981 txtp
= aclent_acltotext(aclp
->acl_aclp
, aclp
->acl_cnt
, flags
);
989 acl_fromtext(const char *acltextp
, acl_t
**ret_aclp
)
994 buf
= malloc(strlen(acltextp
) + 2);
996 return (EACL_MEM_ERROR
);
997 strcpy(buf
, acltextp
);
1000 (void) mutex_lock(&yymutex
);
1014 (void) mutex_unlock(&yymutex
);
1020 acl_parse(const char *acltextp
, acl_t
**aclp
)
1025 error
= acl_fromtext(acltextp
, aclp
);
1031 ace_compact_printacl(acl_t
*aclp
)
1038 if ((dstr
= malloc(sizeof (dynaclstr_t
))) == NULL
)
1040 dstr
->d_bufsize
= ACE_ENTRY_SIZE
;
1041 if ((dstr
->d_aclexport
= malloc(dstr
->d_bufsize
)) == NULL
) {
1045 *dstr
->d_aclexport
= '\0';
1048 for (cnt
= 0, acep
= aclp
->acl_aclp
;
1049 cnt
!= aclp
->acl_cnt
; cnt
++, acep
++) {
1050 dstr
->d_aclexport
[0] = '\0';
1053 if (ace_type_txt(dstr
, acep
, 0))
1055 len
= strlen(&dstr
->d_aclexport
[0]);
1056 if (ace_perm_txt(dstr
, acep
->a_access_mask
, acep
->a_flags
,
1057 aclp
->acl_flags
& ACL_IS_DIR
, ACL_COMPACT_FMT
))
1059 if (ace_inherit_txt(dstr
, acep
->a_flags
, ACL_COMPACT_FMT
))
1061 if (ace_access_txt(dstr
, acep
->a_type
) == -1)
1063 (void) printf(" %20.*s%s\n", len
, dstr
->d_aclexport
,
1064 &dstr
->d_aclexport
[len
]);
1067 if (dstr
->d_aclexport
)
1068 free(dstr
->d_aclexport
);
1073 ace_printacl(acl_t
*aclp
, int cols
, int compact
)
1080 ace_compact_printacl(aclp
);
1084 acltext
= acl_totext(aclp
, 0);
1086 if (acltext
== NULL
)
1089 token
= strtok(acltext
, ",");
1090 if (token
== NULL
) {
1096 (void) printf(" %d:", slot
++);
1097 split_line(token
, cols
- 5);
1098 } while (token
= strtok(NULL
, ","));
1103 * pretty print an ACL.
1104 * For aclent_t ACL's the format is
1105 * similar to the old format used by getfacl,
1106 * with the addition of adding a "slot" number
1107 * before each entry.
1109 * for ace_t ACL's the cols variable will break up
1110 * the long lines into multiple lines and will also
1111 * print a "slot" number.
1114 acl_printacl(acl_t
*aclp
, int cols
, int compact
)
1117 switch (aclp
->acl_type
) {
1119 aclent_printacl(aclp
);
1122 ace_printacl(aclp
, cols
, compact
);
1127 typedef struct value_table
{
1128 char p_letter
; /* perm letter such as 'r' */
1129 uint32_t p_value
; /* value for perm when pletter found */
1133 * The permission tables are laid out in positional order
1134 * a '-' character will indicate a permission at a given
1135 * position is not specified. The '-' is not part of the
1136 * table, but will be checked for in the permission computation
1139 value_table_t ace_perm_table
[] = {
1140 { 'r', ACE_READ_DATA
},
1141 { 'w', ACE_WRITE_DATA
},
1142 { 'x', ACE_EXECUTE
},
1143 { 'p', ACE_APPEND_DATA
},
1145 { 'D', ACE_DELETE_CHILD
},
1146 { 'a', ACE_READ_ATTRIBUTES
},
1147 { 'A', ACE_WRITE_ATTRIBUTES
},
1148 { 'R', ACE_READ_NAMED_ATTRS
},
1149 { 'W', ACE_WRITE_NAMED_ATTRS
},
1150 { 'c', ACE_READ_ACL
},
1151 { 'C', ACE_WRITE_ACL
},
1152 { 'o', ACE_WRITE_OWNER
},
1153 { 's', ACE_SYNCHRONIZE
}
1156 #define ACE_PERM_COUNT (sizeof (ace_perm_table) / sizeof (value_table_t))
1158 value_table_t aclent_perm_table
[] = {
1164 #define ACLENT_PERM_COUNT (sizeof (aclent_perm_table) / sizeof (value_table_t))
1166 value_table_t inherit_table
[] = {
1167 {'f', ACE_FILE_INHERIT_ACE
},
1168 {'d', ACE_DIRECTORY_INHERIT_ACE
},
1169 {'i', ACE_INHERIT_ONLY_ACE
},
1170 {'n', ACE_NO_PROPAGATE_INHERIT_ACE
},
1171 {'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG
},
1172 {'F', ACE_FAILED_ACCESS_ACE_FLAG
},
1173 {'I', ACE_INHERITED_ACE
}
1176 #define IFLAG_COUNT (sizeof (inherit_table) / sizeof (value_table_t))
1177 #define IFLAG_COUNT_V1 6 /* Older version compatibility */
1180 * compute value from a permission table or inheritance table
1181 * based on string passed in. If positional is set then
1182 * string must match order in permtab, otherwise any order
1186 compute_values(value_table_t
*permtab
, int count
,
1187 char *permstr
, int positional
, uint32_t *mask
)
1189 uint32_t perm_val
= 0;
1197 for (i
= 0, pstr
= permstr
; i
!= count
&& pstr
&&
1198 *pstr
; i
++, pstr
++) {
1199 if (*pstr
== permtab
[i
].p_letter
) {
1200 perm_val
|= permtab
[i
].p_value
;
1201 } else if (*pstr
!= '-') {
1205 } else { /* random order single letters with no '-' */
1206 for (pstr
= permstr
; pstr
&& *pstr
; pstr
++) {
1207 for (found
= 0, i
= 0; i
!= count
; i
++) {
1208 if (*pstr
== permtab
[i
].p_letter
) {
1209 perm_val
|= permtab
[i
].p_value
;
1225 ace_inherit_helper(char *str
, uint32_t *imask
, int table_length
)
1229 if (strlen(str
) == table_length
) {
1231 * If the string == table_length then first check to see it's
1232 * in positional format. If that fails then see if it's in
1233 * non-positional format.
1235 if (compute_values(inherit_table
, table_length
, str
,
1236 1, imask
) && compute_values(inherit_table
,
1237 table_length
, str
, 0, imask
)) {
1241 rc
= compute_values(inherit_table
, table_length
, str
, 0, imask
);
1244 return (rc
? EACL_INHERIT_ERROR
: 0);
1248 * compute value for inheritance flags.
1251 compute_ace_inherit(char *str
, uint32_t *imask
)
1255 rc
= ace_inherit_helper(str
, imask
, IFLAG_COUNT
);
1257 if (rc
&& strlen(str
) != IFLAG_COUNT
) {
1259 /* is it an old formatted inherit string? */
1260 rc
= ace_inherit_helper(str
, imask
, IFLAG_COUNT_V1
);
1268 * compute value for ACE permissions.
1271 compute_ace_perms(char *str
, uint32_t *mask
)
1276 if (strlen(str
) == ACE_PERM_COUNT
)
1279 error
= compute_values(ace_perm_table
, ACE_PERM_COUNT
,
1280 str
, positional
, mask
);
1282 if (error
&& positional
) {
1284 * If positional was set, then make sure permissions
1285 * aren't actually valid in non positional case where
1286 * all permissions are specified, just in random order.
1288 error
= compute_values(ace_perm_table
,
1289 ACE_PERM_COUNT
, str
, 0, mask
);
1292 error
= EACL_PERM_MASK_ERROR
;
1300 * compute values for aclent permissions.
1303 compute_aclent_perms(char *str
, o_mode_t
*mask
)
1308 if (strlen(str
) != ACLENT_PERM_COUNT
)
1309 return (EACL_PERM_MASK_ERROR
);
1312 error
= compute_values(aclent_perm_table
, ACLENT_PERM_COUNT
,
1315 *mask
= (o_mode_t
)pmask
;
1317 error
= EACL_PERM_MASK_ERROR
;
1322 * determine ACE permissions.
1325 ace_perm_mask(struct acl_perm_type
*aclperm
, uint32_t *mask
)
1329 if (aclperm
->perm_style
== PERM_TYPE_EMPTY
) {
1334 if (aclperm
->perm_style
== PERM_TYPE_ACE
) {
1335 *mask
= aclperm
->perm_val
;
1339 error
= compute_ace_perms(aclperm
->perm_str
, mask
);
1341 acl_error(dgettext(TEXT_DOMAIN
,
1342 "Invalid permission(s) '%s' specified\n"),
1344 return (EACL_PERM_MASK_ERROR
);