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]
21 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
22 * Use is subject to license terms.
40 int grab_string(char *terminators);
42 static void unput(int);
45 yyerror(const char *s)
60 * Used for tracking allocated strings while walking through an ACL.
63 char *y_logname; /* user/group name from LOGNAME */
64 char *y_perms; /* permssions from PERM_TOK */
65 char *y_iflags; /* iflags from INHERIT_TOK */
66 char *y_idstr; /* string of appened id */
72 %s TS NS PS AIS AS US ES
78 * PS = Permission state
79 * AIS = Allow/deny/inheritance state
80 * AS = Allow state (only used when inheritance detected)
88 PERM_STR [rRwWxpdDaAcCos-]+
89 INHERIT_STR [fdinFSI-]+
95 yylval.val = USER_TOK;
100 yylval.val = USER_SID_TOK;
105 yylval.val = OWNERAT_TOK;
110 yylval.val = GROUPAT_TOK;
115 yylval.val = EVERYONEAT_TOK;
120 yylval.val = GROUP_TOK;
125 yylval.val = GROUP_SID_TOK;
130 yylval.val = GROUP_SID_TOK;
135 yylval.val = MASK_TOK;
140 yylval.val = MASK_TOK;
145 yylval.val = OTHER_TOK;
150 yylval.val = OTHER_TOK;
155 yylval.val = DEFAULT_USER_TOK;
160 yylval.val = DEFAULT_USER_TOK;
165 yylval.val = DEFAULT_GROUP_TOK;
170 yylval.val = DEFAULT_GROUP_TOK;
175 yylval.val = DEFAULT_OTHER_TOK;
180 yylval.val = DEFAULT_OTHER_TOK;
185 yylval.val = DEFAULT_OTHER_TOK;
190 yylval.val = DEFAULT_MASK_TOK;
195 yylval.val = DEFAULT_MASK_TOK;
200 yylval.val = DEFAULT_MASK_TOK;
207 if (grab_string(":,\n") != 0) {
208 acl_error(dgettext(TEXT_DOMAIN,
210 " error string.\n"));
211 yylval.val = EACL_MEM_ERROR;
214 acl_error(dgettext(TEXT_DOMAIN,
216 "type '%s' specified.\n"), yylval.str);
218 yylval.val = EACL_ENTRY_ERROR;
226 yylval.str = strdup(yytext);
227 if (yylval.str == NULL) {
228 yylval.val = EACL_MEM_ERROR;
231 yylval.str[strlen(yylval.str) -1] = '\0';
232 yystrings.y_logname = yylval.str;
237 acl_error(dgettext(TEXT_DOMAIN,
238 "Missing user/group name"
239 " from ACL specification.\n"));
240 yylval.val = EACL_MISSING_FIELDS;
246 error = grab_string(":,\n");
248 acl_error(dgettext(TEXT_DOMAIN,
249 "Invalid user/group "
250 "name specification.\n"));
251 yylval.val = EACL_INVALID_USER_GROUP;
253 acl_error(dgettext(TEXT_DOMAIN,
255 "'%s' not specified correctly.\n"),
258 yylval.val = EACL_ENTRY_ERROR;
262 <PS>read_data/[:/,] {
263 yylval.val = ACE_READ_DATA;
266 <PS>list_directory/[:/,] {
267 yylval.val = ACE_LIST_DIRECTORY;
270 <PS>write_data/[:/,] {
271 yylval.val = ACE_WRITE_DATA;
275 yylval.val = ACE_ADD_FILE;
278 <PS>append_data/[:/,] {
279 yylval.val = ACE_APPEND_DATA;
282 <PS>add_subdirectory/[:/,] {
283 yylval.val = ACE_ADD_SUBDIRECTORY;
286 <PS>read_xattr/[:/,] {
287 yylval.val = ACE_READ_NAMED_ATTRS;
290 <PS>write_xattr/[:/,] {
291 yylval.val = ACE_WRITE_NAMED_ATTRS;
295 yylval.val = ACE_EXECUTE;
298 <PS>delete_child/[:/,] {
299 yylval.val = ACE_DELETE_CHILD;
302 <PS>read_attributes/[:/,] {
303 yylval.val = ACE_READ_ATTRIBUTES;
306 <PS>write_attributes/[:/,] {
307 yylval.val = ACE_WRITE_ATTRIBUTES;
311 yylval.val = ACE_DELETE;
315 yylval.val = ACE_READ_ACL;
318 <PS>write_acl/[:/,] {
319 yylval.val = ACE_WRITE_ACL;
322 <PS>write_owner/[:/,] {
323 yylval.val = ACE_WRITE_OWNER;
326 <PS>synchronize/[:/,] {
327 yylval.val = ACE_SYNCHRONIZE;
331 yylval.val = ACE_READ_PERMS;
334 <PS>write_set/[:/,] {
335 yylval.val = ACE_WRITE_PERMS;
338 <PS>modify_set/[:/,] {
339 yylval.val = ACE_MODIFY_PERMS;
343 yylval.val = ACE_ALL_PERMS;
346 <PS>{PERM_STR}/[:,\n] {
351 yylval.str = strdup(yytext);
352 if (yylval.str == NULL) {
353 yylval.val = EACL_MEM_ERROR;
356 yystrings.y_perms = yylval.str;
359 * aclent are done after permissions.
369 acl_error(dgettext(TEXT_DOMAIN,
370 "Invalid permission /: specified.\n"));
371 yylval.val = EACL_ENTRY_ERROR;
389 acl_error(dgettext(TEXT_DOMAIN,
390 "ACL entry is missing "
391 "permission fields.\n"));
392 yylval.val = EACL_MISSING_FIELDS;
397 dgettext(TEXT_DOMAIN,
398 "The ',' is not a valid permission field "
399 "separator.\nThe comma is used to separate "
400 "access control entries.\nSee acl(5) for "
401 "examples of specifying ACL entries.\n"));
402 yylval.val = EACL_PERM_MASK_ERROR;
406 if (grab_string("/:,\n") != 0) {
407 acl_error(dgettext(TEXT_DOMAIN,
409 " error string.\n"));
410 yylval.val = EACL_MEM_ERROR;
413 acl_error(dgettext(TEXT_DOMAIN,
414 "Invalid permission(s) '%s' "
415 "specified.\n"), yylval.str);
417 yylval.val = EACL_PERM_MASK_ERROR;
426 if (c == ',' || c == '\n')
430 yylval.val = ACE_ACCESS_ALLOWED_ACE_TYPE;
431 return (ACCESS_TYPE);
439 if (c == ',' || c == '\n')
444 yylval.val = ACE_ACCESS_DENIED_ACE_TYPE;
445 return (ACCESS_TYPE);
452 if (c == ',' || c == '\n')
457 yylval.val = ACE_SYSTEM_AUDIT_ACE_TYPE;
458 return (ACCESS_TYPE);
465 if (c == ',' || c == '\n')
470 yylval.val = ACE_SYSTEM_ALARM_ACE_TYPE;
471 return (ACCESS_TYPE);
475 acl_error(dgettext(TEXT_DOMAIN,
476 "Invalid Access type "
477 "specified.\nThe field is blank, when"
478 " it should be either allow or deny.\n"));
479 yylval.val = EACL_INVALID_ACCESS_TYPE;
483 acl_error(dgettext(TEXT_DOMAIN,
484 "ACL access type must be specified.\n"));
485 yylval.val = EACL_INVALID_ACCESS_TYPE;
489 if (yytext[0] != '\n' && yytext[0] != '\0') {
490 if (grab_string(":,\n") != 0) {
491 acl_error(dgettext(TEXT_DOMAIN,
495 yylval.val = EACL_MEM_ERROR;
499 dgettext(TEXT_DOMAIN,
501 "type '%s' specified.\n"),
505 dgettext(TEXT_DOMAIN,
507 "type specified.\n"), yylval.str);
511 yylval.val = EACL_INVALID_ACCESS_TYPE;
520 if (c == ',' || c == '\n')
524 yylval.val = ACE_ACCESS_ALLOWED_ACE_TYPE;
525 return (ACCESS_TYPE);
533 if (c == ',' || c == '\n')
538 yylval.val = ACE_ACCESS_DENIED_ACE_TYPE;
539 return (ACCESS_TYPE);
546 if (c == ',' || c == '\n')
551 yylval.val = ACE_SYSTEM_AUDIT_ACE_TYPE;
552 return (ACCESS_TYPE);
560 if (c == ',' || c == '\n')
565 yylval.val = ACE_SYSTEM_ALARM_ACE_TYPE;
566 return (ACCESS_TYPE);
568 <AIS>file_inherit/[:/,] {
569 yylval.val = ACE_FILE_INHERIT_ACE;
570 return (ACE_INHERIT);
572 <AIS>dir_inherit/[:/,] {
573 yylval.val = ACE_DIRECTORY_INHERIT_ACE;
574 return (ACE_INHERIT);
576 <AIS>no_propagate/[/:,] {
577 yylval.val = ACE_NO_PROPAGATE_INHERIT_ACE;
578 return (ACE_INHERIT);
580 <AIS>inherit_only/[/:,] {
581 yylval.val = ACE_INHERIT_ONLY_ACE;
582 return (ACE_INHERIT);
585 <AIS>successful_access/[/:,] {
586 yylval.val = ACE_SUCCESSFUL_ACCESS_ACE_FLAG;
587 return (ACE_INHERIT);
589 <AIS>failed_access/[/:,] {
590 yylval.val = ACE_FAILED_ACCESS_ACE_FLAG;
591 return (ACE_INHERIT);
593 <AIS>inherited/[/:,] {
594 yylval.val = ACE_INHERITED_ACE;
595 return (ACE_INHERIT);
597 <AIS>{INHERIT_STR}/[:] {
598 yylval.str = strdup(yytext);
599 if (yylval.str == NULL) {
600 yylval.val = EACL_MEM_ERROR;
603 yystrings.y_iflags = yylval.str;
604 return (INHERIT_TOK);
608 * Only inheritance fields should hit this.
609 * allow/deny fields match on ":" as part
620 dgettext(TEXT_DOMAIN,
621 "Invalid ACL specification."
622 "\nWas expecting to find"
623 " access type or inheritance flags.\n"),
625 yylval.val = EACL_UNKNOWN_DATA;
630 dgettext(TEXT_DOMAIN,
631 "The ',' is not a valid inheritance field "
632 "separator.\nThe comma is used to separate "
633 "access control entries.\nSee acl(5) for "
634 "examples of specifying ACL entries.\n"));
635 yylval.val = EACL_INVALID_ACCESS_TYPE;
639 if (yytext[0] != '\n' && yytext[0] != '\0') {
640 if (grab_string(":,\n") != 0) {
641 acl_error(dgettext(TEXT_DOMAIN,
645 yylval.val = EACL_MEM_ERROR;
649 dgettext(TEXT_DOMAIN,
650 "Invalid inheritance or"
651 " access type '%s' specified.\n"),
655 dgettext(TEXT_DOMAIN,
657 "access type specified.\n"),
662 yylval.val = EACL_INVALID_ACCESS_TYPE;
667 yylval.str = strdup(yytext);
668 if (yylval.str == NULL) {
669 yylval.val = EACL_MEM_ERROR;
672 yystrings.y_idstr = yylval.str;
677 yylval.str = strdup(yytext);
678 if (yylval.str == NULL) {
679 yylval.val = EACL_MEM_ERROR;
682 yystrings.y_idstr = yylval.str;
688 <US>{INHERIT_STR} { /*
689 * Catch specific error to produce
690 * nice message for users who are trying
691 * to use old syntax format which had
692 * inheritance flags as the last field.
694 acl_error(dgettext(TEXT_DOMAIN,
695 "Access type should be final"
696 " field in ACL specification.\n"));
697 yylval.val = EACL_ENTRY_ERROR;
701 if (grab_string(",\n") != 0) {
702 acl_error(dgettext(TEXT_DOMAIN,
704 " error string.\n"));
705 yylval.val = EACL_MEM_ERROR;
709 dgettext(TEXT_DOMAIN,
710 "Invalid data ':%s' specified"
711 " on end of ACL.\n"), yylval.str);
713 yylval.val = EACL_ENTRY_ERROR;
717 acl_error(dgettext(TEXT_DOMAIN,
718 "Missing fields in ACL "
719 "specification.\nWas expecting to find "
721 yylval.val = EACL_ENTRY_ERROR;
729 if (grab_string("/:,\n") != 0) {
731 dgettext(TEXT_DOMAIN,
732 "Failed to retrieve error"
734 yylval.val = EACL_MEM_ERROR;
738 dgettext(TEXT_DOMAIN,
739 "Unrecognized data '%s' found"
740 " in ACL specification.\n"), yylval.str);
742 yylval.val = EACL_UNKNOWN_DATA;
752 * Pull string up to terminator off of input string.
753 * used for retrieving illegal data in ACL specification.
755 * The first set of characters is retrieved from yytext.
756 * subsequent characters are pulled from the input stream,
757 * until either EOF or one of the requested terminators is scene.
758 * Result is returned in yylval.str which is malloced.
761 grab_string(char *terminators)
770 cnt = strlen(yytext);
771 yylval.str = calloc(cnt + 1, sizeof (char));
772 if (yylval.str == NULL) {
776 strcpy(yylval.str, yytext);
783 for (ptr = terminators; *ptr; ptr++) {
793 if (cnt + 1 >= alloced) {
794 yylval.str = realloc(yylval.str,
797 if (yylval.str == NULL)
800 memset(yylval.str + cnt, 0,
801 alloced - strlen(yylval.str));
803 yylval.str[strlen(yylval.str)] = c;
815 c = yybuf[yybufpos++];
836 * return ACE entry type
839 ace_entry_type(int type)
849 ret = ACE_IDENTIFIER_GROUP;
855 ret = ACE_IDENTIFIER_GROUP | ACE_GROUP;
866 * return aclent entry type
869 aclent_entry_type(int type, int owning, int *ret)
876 *ret = (owning == 0) ? USER : USER_OBJ;
879 *ret = (owning == 0) ? GROUP : GROUP_OBJ;
887 case DEFAULT_USER_TOK:
888 *ret = (owning == 0) ? DEF_USER : DEF_USER_OBJ;
890 case DEFAULT_GROUP_TOK:
891 *ret = (owning == 0) ? DEF_GROUP : DEF_GROUP_OBJ;
893 case DEFAULT_MASK_TOK:
894 *ret = DEF_CLASS_OBJ;
896 case DEFAULT_OTHER_TOK:
897 *ret = DEF_OTHER_OBJ;
900 return (EACL_ENTRY_ERROR);
907 * convert string into numeric id.
910 acl_str_to_id(char *str, uid_t *id)
916 value = strtoul(str, &end, 10);
918 if (errno != 0 || *end != '\0')
919 return (EACL_INVALID_USER_GROUP);
927 * determine either uid/gid for given entry type
930 get_id(int entry_type, char *name, uid_t *id)
936 switch (entry_type) {
938 case DEFAULT_USER_TOK:
939 if ((error = acl_str_to_id(name, id)) == 0)
949 case DEFAULT_GROUP_TOK:
950 if ((error = acl_str_to_id(name, id)) == 0)
959 if (sid_to_id(name, B_TRUE, id))
960 error = EACL_INVALID_USER_GROUP;
964 if (sid_to_id(name, B_FALSE, id))
965 error = EACL_INVALID_USER_GROUP;
973 get_id_nofail(int entry_type, char *name)
977 if (get_id(entry_type, name, &id))
984 * reset beginning state to TS and set character position
991 memset(&yystrings, 0, sizeof (yystrings));
998 if (yystrings.y_logname)
999 free(yystrings.y_logname);
1000 if (yystrings.y_perms)
1001 free(yystrings.y_perms);
1002 if (yystrings.y_iflags)
1003 free(yystrings.y_iflags);
1004 if (yystrings.y_idstr)
1005 free(yystrings.y_idstr);
1006 yystrings.y_logname = NULL;
1007 yystrings.y_perms = NULL;
1008 yystrings.y_iflags = NULL;
1009 yystrings.y_idstr = NULL;