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
== 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
== 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
, ":");
445 * compute string of permissions, such as read_data/write_data or
447 * The format depends on the flags field which indicates whether the compact
448 * or verbose format should be used.
451 ace_perm_txt(dynaclstr_t
*dstr
, uint32_t mask
,
452 uint32_t iflags
, int isdir
, int flags
)
456 if (flags
& ACL_COMPACT_FMT
) {
459 if (mask
& ACE_READ_DATA
)
463 if (mask
& ACE_WRITE_DATA
)
467 if (mask
& ACE_EXECUTE
)
471 if (mask
& ACE_APPEND_DATA
)
475 if (mask
& ACE_DELETE
)
479 if (mask
& ACE_DELETE_CHILD
)
483 if (mask
& ACE_READ_ATTRIBUTES
)
487 if (mask
& ACE_WRITE_ATTRIBUTES
)
491 if (mask
& ACE_READ_NAMED_ATTRS
)
495 if (mask
& ACE_WRITE_NAMED_ATTRS
)
499 if (mask
& ACE_READ_ACL
)
503 if (mask
& ACE_WRITE_ACL
)
507 if (mask
& ACE_WRITE_OWNER
)
511 if (mask
& ACE_SYNCHRONIZE
)
517 error
= str_append(dstr
, buf
);
520 * If ACE is a directory, but inheritance indicates its
521 * for a file then print permissions for file rather than
525 if (mask
& ACE_LIST_DIRECTORY
) {
526 if (iflags
== ACE_FILE_INHERIT_ACE
) {
527 error
= str_append(dstr
,
531 str_append(dstr
, READ_DIR_TXT
);
534 if (error
== 0 && (mask
& ACE_ADD_FILE
)) {
535 if (iflags
== ACE_FILE_INHERIT_ACE
) {
537 str_append(dstr
, WRITE_DATA_TXT
);
540 str_append(dstr
, ADD_FILE_TXT
);
543 if (error
== 0 && (mask
& ACE_ADD_SUBDIRECTORY
)) {
544 if (iflags
== ACE_FILE_INHERIT_ACE
) {
545 error
= str_append(dstr
,
548 error
= str_append(dstr
,
553 if (mask
& ACE_READ_DATA
) {
554 error
= str_append(dstr
, READ_DATA_TXT
);
556 if (error
== 0 && (mask
& ACE_WRITE_DATA
)) {
557 error
= str_append(dstr
, WRITE_DATA_TXT
);
559 if (error
== 0 && (mask
& ACE_APPEND_DATA
)) {
560 error
= str_append(dstr
, APPEND_DATA_TXT
);
563 if (error
== 0 && (mask
& ACE_READ_NAMED_ATTRS
)) {
564 error
= str_append(dstr
, READ_XATTR_TXT
);
566 if (error
== 0 && (mask
& ACE_WRITE_NAMED_ATTRS
)) {
567 error
= str_append(dstr
, WRITE_XATTR_TXT
);
569 if (error
== 0 && (mask
& ACE_EXECUTE
)) {
570 error
= str_append(dstr
, EXECUTE_TXT
);
572 if (error
== 0 && (mask
& ACE_DELETE_CHILD
)) {
573 error
= str_append(dstr
, DELETE_CHILD_TXT
);
575 if (error
== 0 && (mask
& ACE_READ_ATTRIBUTES
)) {
576 error
= str_append(dstr
, READ_ATTRIBUTES_TXT
);
578 if (error
== 0 && (mask
& ACE_WRITE_ATTRIBUTES
)) {
579 error
= str_append(dstr
, WRITE_ATTRIBUTES_TXT
);
581 if (error
== 0 && (mask
& ACE_DELETE
)) {
582 error
= str_append(dstr
, DELETE_TXT
);
584 if (error
== 0 && (mask
& ACE_READ_ACL
)) {
585 error
= str_append(dstr
, READ_ACL_TXT
);
587 if (error
== 0 && (mask
& ACE_WRITE_ACL
)) {
588 error
= str_append(dstr
, WRITE_ACL_TXT
);
590 if (error
== 0 && (mask
& ACE_WRITE_OWNER
)) {
591 error
= str_append(dstr
, WRITE_OWNER_TXT
);
593 if (error
== 0 && (mask
& ACE_SYNCHRONIZE
)) {
594 error
= str_append(dstr
, SYNCHRONIZE_TXT
);
596 if (error
== 0 && dstr
->d_aclexport
[dstr
->d_pos
-1] == '/') {
597 dstr
->d_aclexport
[--dstr
->d_pos
] = '\0';
600 error
= str_append(dstr
, ":");
606 * compute string of access type, such as allow, deny, ...
609 ace_access_txt(dynaclstr_t
*dstr
, int type
)
613 if (type
== ACE_ACCESS_ALLOWED_ACE_TYPE
)
614 error
= str_append(dstr
, ALLOW_TXT
);
615 else if (type
== ACE_ACCESS_DENIED_ACE_TYPE
)
616 error
= str_append(dstr
, DENY_TXT
);
617 else if (type
== ACE_SYSTEM_AUDIT_ACE_TYPE
)
618 error
= str_append(dstr
, AUDIT_TXT
);
619 else if (type
== ACE_SYSTEM_ALARM_ACE_TYPE
)
620 error
= str_append(dstr
, ALARM_TXT
);
622 error
= str_append(dstr
, UNKNOWN_TXT
);
628 ace_inherit_txt(dynaclstr_t
*dstr
, uint32_t iflags
, int flags
)
632 if (flags
& ACL_COMPACT_FMT
) {
635 if (iflags
& ACE_FILE_INHERIT_ACE
)
639 if (iflags
& ACE_DIRECTORY_INHERIT_ACE
)
643 if (iflags
& ACE_INHERIT_ONLY_ACE
)
647 if (iflags
& ACE_NO_PROPAGATE_INHERIT_ACE
)
651 if (iflags
& ACE_SUCCESSFUL_ACCESS_ACE_FLAG
)
655 if (iflags
& ACE_FAILED_ACCESS_ACE_FLAG
)
659 if (iflags
& ACE_INHERITED_ACE
)
665 error
= str_append(dstr
, buf
);
667 if (iflags
& ACE_FILE_INHERIT_ACE
) {
668 error
= str_append(dstr
, FILE_INHERIT_TXT
);
670 if (error
== 0 && (iflags
& ACE_DIRECTORY_INHERIT_ACE
)) {
671 error
= str_append(dstr
, DIR_INHERIT_TXT
);
673 if (error
== 0 && (iflags
& ACE_NO_PROPAGATE_INHERIT_ACE
)) {
674 error
= str_append(dstr
, NO_PROPAGATE_TXT
);
676 if (error
== 0 && (iflags
& ACE_INHERIT_ONLY_ACE
)) {
677 error
= str_append(dstr
, INHERIT_ONLY_TXT
);
679 if (error
== 0 && (iflags
& ACE_SUCCESSFUL_ACCESS_ACE_FLAG
)) {
680 error
= str_append(dstr
, SUCCESSFUL_ACCESS_TXT
);
682 if (error
== 0 && (iflags
& ACE_FAILED_ACCESS_ACE_FLAG
)) {
683 error
= str_append(dstr
, FAILED_ACCESS_TXT
);
685 if (error
== 0 && (iflags
& ACE_INHERITED_ACE
)) {
686 error
= str_append(dstr
, INHERITED_ACE_TXT
);
688 if (error
== 0 && dstr
->d_aclexport
[dstr
->d_pos
-1] == '/') {
689 dstr
->d_aclexport
[--dstr
->d_pos
] = '\0';
690 error
= str_append(dstr
, ":");
698 * Convert internal acl representation to external representation.
700 * The length of a non-owning user name or non-owning group name ie entries
701 * of type DEF_USER, USER, DEF_GROUP or GROUP, can exceed LOGNAME_MAX. We
702 * thus check the length of these entries, and if greater than LOGNAME_MAX,
703 * we realloc() via increase_length().
705 * The LOGNAME_MAX, ENTRYTYPELEN and PERMS limits are otherwise always
710 * acltotext() converts each ACL entry to look like this:
712 * entry_type:uid^gid^name:perms[:id]
714 * The maximum length of entry_type is 14 ("defaultgroup::" and
715 * "defaultother::") hence ENTRYTYPELEN is set to 14.
717 * The max length of a uid^gid^name entry (in theory) is 8, hence we use,
718 * however the ID could be a number so we therefore use ID_STR_MAX
720 * The length of a perms entry is 4 to allow for the comma appended to each
721 * to each acl entry. Hence PERMS is set to 4.
724 #define ENTRYTYPELEN 14
726 #define ACL_ENTRY_SIZE (ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX)
729 aclent_acltotext(aclent_t
*aclp
, int aclcnt
, int flags
)
732 char *aclexport
= NULL
;
738 if ((dstr
= malloc(sizeof (dynaclstr_t
))) == NULL
)
740 dstr
->d_bufsize
= aclcnt
* ACL_ENTRY_SIZE
;
741 if ((dstr
->d_aclexport
= malloc(dstr
->d_bufsize
)) == NULL
) {
745 *dstr
->d_aclexport
= '\0';
748 for (i
= 0; i
< aclcnt
; i
++, aclp
++) {
749 if (error
= aclent_type_txt(dstr
, aclp
, flags
))
751 if (error
= aclent_perm_txt(dstr
, aclp
->a_perm
))
754 if ((flags
& ACL_APPEND_ID
) && ((aclp
->a_type
== USER
) ||
755 (aclp
->a_type
== DEF_USER
) || (aclp
->a_type
== GROUP
) ||
756 (aclp
->a_type
== DEF_GROUP
))) {
757 char id
[ID_STR_MAX
], *idstr
;
759 if (error
= str_append(dstr
, ":"))
761 id
[ID_STR_MAX
- 1] = '\0'; /* null terminate buffer */
762 idstr
= lltostr(aclp
->a_id
, &id
[ID_STR_MAX
- 1]);
763 if (error
= str_append(dstr
, idstr
))
767 if (error
= str_append(dstr
, ","))
771 free(dstr
->d_aclexport
);
773 aclexport
= dstr
->d_aclexport
;
780 acltotext(aclent_t
*aclp
, int aclcnt
)
782 return (aclent_acltotext(aclp
, aclcnt
, 0));
787 aclfromtext(char *aclstr
, int *aclcnt
)
793 error
= acl_fromtext(aclstr
, &aclp
);
797 aclentp
= aclp
->acl_aclp
;
798 aclp
->acl_aclp
= NULL
;
799 *aclcnt
= aclp
->acl_cnt
;
807 * Append string onto dynaclstr_t.
809 * Return 0 on success, 1 for failure.
812 str_append(dynaclstr_t
*dstr
, char *newstr
)
814 size_t len
= strlen(newstr
);
816 if ((len
+ dstr
->d_pos
) >= dstr
->d_bufsize
) {
817 dstr
->d_aclexport
= realloc(dstr
->d_aclexport
,
818 dstr
->d_bufsize
+ len
+ 1);
819 if (dstr
->d_aclexport
== NULL
)
821 dstr
->d_bufsize
+= len
;
823 (void) strcat(&dstr
->d_aclexport
[dstr
->d_pos
], newstr
);
829 aclent_perm_txt(dynaclstr_t
*dstr
, o_mode_t perm
)
846 return (str_append(dstr
, buf
));
850 * ace_acltotext() convert each ace formatted acl to look like this:
852 * entry_type:uid^gid^name:perms[:flags]:<allow|deny>[:id][,]
854 * The maximum length of entry_type is 5 ("group")
856 * The max length of a uid^gid^name entry (in theory) is 8,
857 * however id could be a number so we therefore use ID_STR_MAX
859 * The length of a perms entry is 144 i.e read_data/write_data...
862 * iflags: file_inherit/dir_inherit/inherit_only/no_propagate/successful_access
867 #define ACE_ENTRYTYPLEN 6
868 #define IFLAGS_STR "file_inherit/dir_inherit/inherit_only/no_propagate/" \
869 "successful_access/failed_access/inherited"
870 #define IFLAGS_SIZE (sizeof (IFLAGS_STR) - 1)
871 #define ACCESS_TYPE_SIZE 7 /* if unknown */
873 #define PERMS_LEN 216
874 #define ACE_ENTRY_SIZE (ACE_ENTRYTYPLEN + ID_STR_MAX + PERMS_LEN + \
875 ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT + APPENDED_ID_MAX)
878 ace_acltotext(acl_t
*aceaclp
, int flags
)
880 ace_t
*aclp
= aceaclp
->acl_aclp
;
881 int aclcnt
= aceaclp
->acl_cnt
;
884 int isdir
= (aceaclp
->acl_flags
& ACL_IS_DIR
);
886 char *aclexport
= NULL
;
887 char *rawsidp
= NULL
;
892 if ((dstr
= malloc(sizeof (dynaclstr_t
))) == NULL
)
894 dstr
->d_bufsize
= aclcnt
* ACL_ENTRY_SIZE
;
895 if ((dstr
->d_aclexport
= malloc(dstr
->d_bufsize
)) == NULL
) {
899 *dstr
->d_aclexport
= '\0';
902 for (i
= 0; i
< aclcnt
; i
++, aclp
++) {
904 if (error
= ace_type_txt(dstr
, aclp
, flags
))
906 if (error
= ace_perm_txt(dstr
, aclp
->a_access_mask
,
907 aclp
->a_flags
, isdir
, flags
))
909 if (error
= ace_inherit_txt(dstr
, aclp
->a_flags
, flags
))
911 if (error
= ace_access_txt(dstr
, aclp
->a_type
))
914 if ((flags
& ACL_APPEND_ID
) &&
915 (((aclp
->a_flags
& ACE_TYPE_FLAGS
) == 0) ||
916 ((aclp
->a_flags
& ACE_TYPE_FLAGS
) ==
917 ACE_IDENTIFIER_GROUP
))) {
918 char id
[ID_STR_MAX
], *idstr
;
920 if (error
= str_append(dstr
, ":"))
924 id
[ID_STR_MAX
-1] = '\0'; /* null terminate */
925 if (aclp
->a_who
> MAXUID
&& (flags
& ACL_SID_FMT
)) {
927 error
= getsidname(aclp
->a_who
,
928 ((aclp
->a_flags
& ACE_TYPE_FLAGS
) == 0) ?
929 B_TRUE
: B_FALSE
, &idstr
, 1);
933 } else if (aclp
->a_who
> MAXUID
&&
934 !(flags
& ACL_NORESOLVE
)) {
935 idstr
= lltostr(UID_NOBODY
,
936 &id
[ID_STR_MAX
- 1]);
938 idstr
= lltostr(aclp
->a_who
,
939 &id
[ID_STR_MAX
- 1]);
941 if (error
= str_append(dstr
, idstr
))
948 if (i
< aclcnt
- 1) {
949 if (error
= str_append(dstr
, ","))
956 free(dstr
->d_aclexport
);
958 aclexport
= dstr
->d_aclexport
;
965 acl_totext(acl_t
*aclp
, int flags
)
972 switch (aclp
->acl_type
) {
974 txtp
= ace_acltotext(aclp
, flags
);
977 txtp
= aclent_acltotext(aclp
->acl_aclp
, aclp
->acl_cnt
, flags
);
985 acl_fromtext(const char *acltextp
, acl_t
**ret_aclp
)
990 buf
= malloc(strlen(acltextp
) + 2);
992 return (EACL_MEM_ERROR
);
993 strcpy(buf
, acltextp
);
996 (void) mutex_lock(&yymutex
);
1010 (void) mutex_unlock(&yymutex
);
1016 acl_parse(const char *acltextp
, acl_t
**aclp
)
1021 error
= acl_fromtext(acltextp
, aclp
);
1027 ace_compact_printacl(acl_t
*aclp
)
1034 if ((dstr
= malloc(sizeof (dynaclstr_t
))) == NULL
)
1036 dstr
->d_bufsize
= ACE_ENTRY_SIZE
;
1037 if ((dstr
->d_aclexport
= malloc(dstr
->d_bufsize
)) == NULL
) {
1041 *dstr
->d_aclexport
= '\0';
1044 for (cnt
= 0, acep
= aclp
->acl_aclp
;
1045 cnt
!= aclp
->acl_cnt
; cnt
++, acep
++) {
1046 dstr
->d_aclexport
[0] = '\0';
1049 if (ace_type_txt(dstr
, acep
, 0))
1051 len
= strlen(&dstr
->d_aclexport
[0]);
1052 if (ace_perm_txt(dstr
, acep
->a_access_mask
, acep
->a_flags
,
1053 aclp
->acl_flags
& ACL_IS_DIR
, ACL_COMPACT_FMT
))
1055 if (ace_inherit_txt(dstr
, acep
->a_flags
, ACL_COMPACT_FMT
))
1057 if (ace_access_txt(dstr
, acep
->a_type
) == -1)
1059 (void) printf(" %20.*s%s\n", len
, dstr
->d_aclexport
,
1060 &dstr
->d_aclexport
[len
]);
1063 free(dstr
->d_aclexport
);
1068 ace_printacl(acl_t
*aclp
, int cols
, int compact
)
1075 ace_compact_printacl(aclp
);
1079 acltext
= acl_totext(aclp
, 0);
1081 if (acltext
== NULL
)
1084 token
= strtok(acltext
, ",");
1085 if (token
== NULL
) {
1091 (void) printf(" %d:", slot
++);
1092 split_line(token
, cols
- 5);
1093 } while (token
= strtok(NULL
, ","));
1098 * pretty print an ACL.
1099 * For aclent_t ACL's the format is
1100 * similar to the old format used by getfacl,
1101 * with the addition of adding a "slot" number
1102 * before each entry.
1104 * for ace_t ACL's the cols variable will break up
1105 * the long lines into multiple lines and will also
1106 * print a "slot" number.
1109 acl_printacl(acl_t
*aclp
, int cols
, int compact
)
1112 switch (aclp
->acl_type
) {
1114 aclent_printacl(aclp
);
1117 ace_printacl(aclp
, cols
, compact
);
1122 typedef struct value_table
{
1123 char p_letter
; /* perm letter such as 'r' */
1124 uint32_t p_value
; /* value for perm when pletter found */
1128 * The permission tables are laid out in positional order
1129 * a '-' character will indicate a permission at a given
1130 * position is not specified. The '-' is not part of the
1131 * table, but will be checked for in the permission computation
1134 value_table_t ace_perm_table
[] = {
1135 { 'r', ACE_READ_DATA
},
1136 { 'w', ACE_WRITE_DATA
},
1137 { 'x', ACE_EXECUTE
},
1138 { 'p', ACE_APPEND_DATA
},
1140 { 'D', ACE_DELETE_CHILD
},
1141 { 'a', ACE_READ_ATTRIBUTES
},
1142 { 'A', ACE_WRITE_ATTRIBUTES
},
1143 { 'R', ACE_READ_NAMED_ATTRS
},
1144 { 'W', ACE_WRITE_NAMED_ATTRS
},
1145 { 'c', ACE_READ_ACL
},
1146 { 'C', ACE_WRITE_ACL
},
1147 { 'o', ACE_WRITE_OWNER
},
1148 { 's', ACE_SYNCHRONIZE
}
1151 #define ACE_PERM_COUNT (sizeof (ace_perm_table) / sizeof (value_table_t))
1153 value_table_t aclent_perm_table
[] = {
1159 #define ACLENT_PERM_COUNT (sizeof (aclent_perm_table) / sizeof (value_table_t))
1161 value_table_t inherit_table
[] = {
1162 {'f', ACE_FILE_INHERIT_ACE
},
1163 {'d', ACE_DIRECTORY_INHERIT_ACE
},
1164 {'i', ACE_INHERIT_ONLY_ACE
},
1165 {'n', ACE_NO_PROPAGATE_INHERIT_ACE
},
1166 {'S', ACE_SUCCESSFUL_ACCESS_ACE_FLAG
},
1167 {'F', ACE_FAILED_ACCESS_ACE_FLAG
},
1168 {'I', ACE_INHERITED_ACE
}
1171 #define IFLAG_COUNT (sizeof (inherit_table) / sizeof (value_table_t))
1172 #define IFLAG_COUNT_V1 6 /* Older version compatibility */
1175 * compute value from a permission table or inheritance table
1176 * based on string passed in. If positional is set then
1177 * string must match order in permtab, otherwise any order
1181 compute_values(value_table_t
*permtab
, int count
,
1182 char *permstr
, int positional
, uint32_t *mask
)
1184 uint32_t perm_val
= 0;
1192 for (i
= 0, pstr
= permstr
; i
!= count
&& pstr
&&
1193 *pstr
; i
++, pstr
++) {
1194 if (*pstr
== permtab
[i
].p_letter
) {
1195 perm_val
|= permtab
[i
].p_value
;
1196 } else if (*pstr
!= '-') {
1200 } else { /* random order single letters with no '-' */
1201 for (pstr
= permstr
; pstr
&& *pstr
; pstr
++) {
1202 for (found
= 0, i
= 0; i
!= count
; i
++) {
1203 if (*pstr
== permtab
[i
].p_letter
) {
1204 perm_val
|= permtab
[i
].p_value
;
1220 ace_inherit_helper(char *str
, uint32_t *imask
, int table_length
)
1224 if (strlen(str
) == table_length
) {
1226 * If the string == table_length then first check to see it's
1227 * in positional format. If that fails then see if it's in
1228 * non-positional format.
1230 if (compute_values(inherit_table
, table_length
, str
,
1231 1, imask
) && compute_values(inherit_table
,
1232 table_length
, str
, 0, imask
)) {
1236 rc
= compute_values(inherit_table
, table_length
, str
, 0, imask
);
1239 return (rc
? EACL_INHERIT_ERROR
: 0);
1243 * compute value for inheritance flags.
1246 compute_ace_inherit(char *str
, uint32_t *imask
)
1250 rc
= ace_inherit_helper(str
, imask
, IFLAG_COUNT
);
1252 if (rc
&& strlen(str
) != IFLAG_COUNT
) {
1254 /* is it an old formatted inherit string? */
1255 rc
= ace_inherit_helper(str
, imask
, IFLAG_COUNT_V1
);
1263 * compute value for ACE permissions.
1266 compute_ace_perms(char *str
, uint32_t *mask
)
1271 if (strlen(str
) == ACE_PERM_COUNT
)
1274 error
= compute_values(ace_perm_table
, ACE_PERM_COUNT
,
1275 str
, positional
, mask
);
1277 if (error
&& positional
) {
1279 * If positional was set, then make sure permissions
1280 * aren't actually valid in non positional case where
1281 * all permissions are specified, just in random order.
1283 error
= compute_values(ace_perm_table
,
1284 ACE_PERM_COUNT
, str
, 0, mask
);
1287 error
= EACL_PERM_MASK_ERROR
;
1295 * compute values for aclent permissions.
1298 compute_aclent_perms(char *str
, o_mode_t
*mask
)
1303 if (strlen(str
) != ACLENT_PERM_COUNT
)
1304 return (EACL_PERM_MASK_ERROR
);
1307 error
= compute_values(aclent_perm_table
, ACLENT_PERM_COUNT
,
1310 *mask
= (o_mode_t
)pmask
;
1312 error
= EACL_PERM_MASK_ERROR
;
1317 * determine ACE permissions.
1320 ace_perm_mask(struct acl_perm_type
*aclperm
, uint32_t *mask
)
1324 if (aclperm
->perm_style
== PERM_TYPE_EMPTY
) {
1329 if (aclperm
->perm_style
== PERM_TYPE_ACE
) {
1330 *mask
= aclperm
->perm_val
;
1334 error
= compute_ace_perms(aclperm
->perm_str
, mask
);
1336 acl_error(dgettext(TEXT_DOMAIN
,
1337 "Invalid permission(s) '%s' specified\n"),
1339 return (EACL_PERM_MASK_ERROR
);