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 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
22 * Use is subject to license terms.
23 */
24
25%{
26#include <sys/acl.h>
27#include <aclutils.h>
28#include <idmap.h>
29#include <errno.h>
30#include "acl.tab.h"
31
32#ifdef input
33#undef input
34#endif
35
36#ifdef unput
37#undef unput
38#endif
39
40int grab_string(char *terminators);
41static int input();
42static void unput(int);
43
44int
45yyerror(const char *s)
46{
47	return (0);
48}
49
50int
51yywrap(void)
52{
53	return (1);
54}
55
56extern char *yybuf;
57int yybufpos;
58
59/*
60 * Used for tracking allocated strings while walking through an ACL.
61 */
62struct yystrings {
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 */
67} yystrings;
68
69%}
70
71%e 1500
72%s TS NS PS AIS AS US ES
73%p 5000
74
75/*
76 * TS = type state
77 * NS = name state
78 * PS = Permission state
79 * AIS = Allow/deny/inheritance state
80 * AS = Allow state (only used when inheritance detected)
81 * US = UID/GID state
82 * ES = End state
83 */
84
85ID	[0-9]+
86SID	S-[^:,\n]+
87LOGNAME [^:]+:
88PERM_STR [rRwWxpdDaAcCos-]+
89INHERIT_STR [fdinFSI-]+
90
91%%
92
93<TS>user:		{
94				BEGIN NS;
95				yylval.val = USER_TOK;
96				return (ENTRY_TYPE);
97			}
98<TS>usersid:		{
99				BEGIN NS;
100				yylval.val = USER_SID_TOK;
101				return (ENTRY_TYPE);
102			}
103<TS>owner@:		{
104				BEGIN PS;
105				yylval.val = OWNERAT_TOK;
106				return (ENTRY_TYPE);
107			}
108<TS>group@:		{
109				BEGIN PS;
110				yylval.val = GROUPAT_TOK;
111				return (ENTRY_TYPE);
112			}
113<TS>everyone@:		{
114				BEGIN PS;
115				yylval.val = EVERYONEAT_TOK;
116				return (ENTRY_TYPE);
117			}
118<TS>group:		{
119				BEGIN NS;
120				yylval.val = GROUP_TOK;
121				return (ENTRY_TYPE);
122			}
123<TS>groupsid:		{
124				BEGIN NS;
125				yylval.val = GROUP_SID_TOK;
126				return (ENTRY_TYPE);
127			}
128<TS>sid:		{
129				BEGIN NS;
130				yylval.val = GROUP_SID_TOK;
131				return (ENTRY_TYPE);
132			}
133<TS>mask:		{
134				BEGIN PS;
135				yylval.val = MASK_TOK;
136				return (ENTRY_TYPE);
137			}
138<TS>mask::		{
139				BEGIN PS;
140				yylval.val = MASK_TOK;
141				return (ENTRY_TYPE);
142			}
143<TS>other:		{
144				BEGIN PS;
145				yylval.val = OTHER_TOK;
146				return (ENTRY_TYPE);
147			}
148<TS>other::		{
149				BEGIN PS;
150				yylval.val = OTHER_TOK;
151				return (ENTRY_TYPE);
152			}
153<TS>defaultuser: 	{
154				BEGIN NS;
155				yylval.val = DEFAULT_USER_TOK;
156				return (ENTRY_TYPE);
157			}
158<TS>default:user:	{
159				BEGIN NS;
160				yylval.val = DEFAULT_USER_TOK;
161				return (ENTRY_TYPE);
162			}
163<TS>defaultgroup: 	{
164				BEGIN NS;
165				yylval.val = DEFAULT_GROUP_TOK;
166				return (ENTRY_TYPE);
167			}
168<TS>default:group:	{
169				BEGIN NS;
170				yylval.val = DEFAULT_GROUP_TOK;
171				return (ENTRY_TYPE);
172			}
173<TS>defaultother: 	{
174				BEGIN PS;
175				yylval.val = DEFAULT_OTHER_TOK;
176				return (ENTRY_TYPE);
177			}
178<TS>defaultother:: 	{
179				BEGIN PS;
180				yylval.val = DEFAULT_OTHER_TOK;
181				return (ENTRY_TYPE);
182			}
183<TS>default:other:	{
184				BEGIN PS;
185				yylval.val = DEFAULT_OTHER_TOK;
186				return (ENTRY_TYPE);
187			}
188<TS>defaultmask: 	{
189				BEGIN PS;
190				yylval.val = DEFAULT_MASK_TOK;
191				return (ENTRY_TYPE);
192			}
193<TS>defaultmask:: 	{
194				BEGIN PS;
195				yylval.val = DEFAULT_MASK_TOK;
196				return (ENTRY_TYPE);
197			}
198<TS>default:mask:		{
199				BEGIN PS;
200				yylval.val = DEFAULT_MASK_TOK;
201				return (ENTRY_TYPE);
202			}
203<TS>"\n"		{
204				return (NL);
205			}
206<TS>.			{
207				if (grab_string(":,\n") != 0) {
208					acl_error(dgettext(TEXT_DOMAIN,
209					    "Failed to retrieve"
210					    " error string.\n"));
211					yylval.val = EACL_MEM_ERROR;
212					return (ERROR);
213				}
214				acl_error(dgettext(TEXT_DOMAIN,
215				    "Invalid ACL entry "
216				    "type '%s' specified.\n"), yylval.str);
217				free(yylval.str);
218				yylval.val = EACL_ENTRY_ERROR;
219				return (ERROR);
220			}
221<NS>:			{
222				BEGIN PS;
223				return (COLON);
224			}
225<NS>{LOGNAME}		{
226				yylval.str = strdup(yytext);
227				if (yylval.str == NULL) {
228					yylval.val = EACL_MEM_ERROR;
229					return (ERROR);
230				}
231				yylval.str[strlen(yylval.str) -1] = '\0';
232				yystrings.y_logname = yylval.str;
233				BEGIN PS;
234				return (IDNAME);
235			}
236<NS>"\n"		{
237				acl_error(dgettext(TEXT_DOMAIN,
238				    "Missing user/group name"
239				    " from ACL specification.\n"));
240				yylval.val = EACL_MISSING_FIELDS;
241				return (ERROR);
242			}
243<NS>.			{
244				int error;
245
246				error = grab_string(":,\n");
247				if (error != 0) {
248					acl_error(dgettext(TEXT_DOMAIN,
249					    "Invalid user/group "
250					    "name specification.\n"));
251					yylval.val = EACL_INVALID_USER_GROUP;
252				} else {
253					acl_error(dgettext(TEXT_DOMAIN,
254					    "User/Group name "
255					    "'%s' not specified correctly.\n"),
256					    yylval.str);
257					free(yylval.str);
258					yylval.val = EACL_ENTRY_ERROR;
259				}
260				return (ERROR);
261			}
262<PS>read_data/[:/,]	{
263				yylval.val = ACE_READ_DATA;
264				return (ACE_PERM);
265			}
266<PS>list_directory/[:/,] {
267				yylval.val = ACE_LIST_DIRECTORY;
268			 	return (ACE_PERM);
269			}
270<PS>write_data/[:/,]	{
271				yylval.val = ACE_WRITE_DATA;
272				return (ACE_PERM);
273			}
274<PS>add_file/[:/,]	{
275				yylval.val = ACE_ADD_FILE;
276				return (ACE_PERM);
277			}
278<PS>append_data/[:/,]	{
279				yylval.val = ACE_APPEND_DATA;
280				return (ACE_PERM);
281			}
282<PS>add_subdirectory/[:/,] {
283				yylval.val = ACE_ADD_SUBDIRECTORY;
284				return (ACE_PERM);
285			}
286<PS>read_xattr/[:/,]	{
287				yylval.val = ACE_READ_NAMED_ATTRS;
288				return (ACE_PERM);
289			}
290<PS>write_xattr/[:/,]	{
291				yylval.val = ACE_WRITE_NAMED_ATTRS;
292				return (ACE_PERM);
293			}
294<PS>execute/[:/,]	{
295				yylval.val = ACE_EXECUTE;
296				return (ACE_PERM);
297			}
298<PS>delete_child/[:/,]	{
299				yylval.val = ACE_DELETE_CHILD;
300				return (ACE_PERM);
301			}
302<PS>read_attributes/[:/,] {
303				yylval.val = ACE_READ_ATTRIBUTES;
304				return (ACE_PERM);
305			}
306<PS>write_attributes/[:/,] {
307				yylval.val = ACE_WRITE_ATTRIBUTES;
308			 	return (ACE_PERM);
309			}
310<PS>delete/[:/,]		{
311				yylval.val = ACE_DELETE;
312				return (ACE_PERM);
313			}
314<PS>read_acl/[:/,]	{
315				yylval.val = ACE_READ_ACL;
316				return (ACE_PERM);
317			}
318<PS>write_acl/[:/,]	{
319				yylval.val = ACE_WRITE_ACL;
320				return (ACE_PERM);
321			}
322<PS>write_owner/[:/,]	{
323				yylval.val = ACE_WRITE_OWNER;
324				return (ACE_PERM);
325			}
326<PS>synchronize/[:/,]	{
327				yylval.val = ACE_SYNCHRONIZE;
328				return (ACE_PERM);
329			}
330<PS>read_set/[:/,]	{
331				yylval.val = ACE_READ_PERMS;
332				return (ACE_PERM);
333			}
334<PS>write_set/[:/,]	{
335				yylval.val = ACE_WRITE_PERMS;
336				return (ACE_PERM);
337			}
338<PS>modify_set/[:/,]	{
339				yylval.val = ACE_MODIFY_PERMS;
340				return (ACE_PERM);
341			}
342<PS>full_set/[:/,]	{
343				yylval.val = ACE_ALL_PERMS;
344				return (ACE_PERM);
345			}
346<PS>{PERM_STR}/[:,\n]	{
347				int c;
348
349				c = input();
350				unput(c);
351				yylval.str = strdup(yytext);
352				if (yylval.str == NULL) {
353					yylval.val = EACL_MEM_ERROR;
354					return (ERROR);
355				}
356				yystrings.y_perms = yylval.str;
357
358				/*
359				 * aclent are done after permissions.
360				 */
361				if (isdigit(c))
362					BEGIN US;
363				else if (c != ':')
364					BEGIN ES;
365
366				return (PERM_TOK);
367			}
368<PS>"/:"		{
369				acl_error(dgettext(TEXT_DOMAIN,
370				    "Invalid permission /: specified.\n"));
371				yylval.val = EACL_ENTRY_ERROR;
372				return (ERROR);
373			}
374<PS>:			{
375				int c;
376
377				c = input();
378				unput(c);
379				if (isdigit(c))
380					BEGIN (US);
381				else
382					BEGIN AIS;
383				return (COLON);
384			}
385<PS>"/"			{
386				return (SLASH);
387			}
388<PS>"\n"		{
389				acl_error(dgettext(TEXT_DOMAIN,
390				    "ACL entry is missing "
391				    "permission fields.\n"));
392				yylval.val = EACL_MISSING_FIELDS;
393				return (ERROR);
394			}
395<PS>","			{
396				acl_error(
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;
403				return (ERROR);
404			}
405<PS>. 			{
406				if (grab_string("/:,\n") != 0) {
407					acl_error(dgettext(TEXT_DOMAIN,
408					    "Failed to retrieve"
409					    " error string.\n"));
410					yylval.val = EACL_MEM_ERROR;
411					return (ERROR);
412				}
413				acl_error(dgettext(TEXT_DOMAIN,
414				    "Invalid permission(s) '%s' "
415				    "specified.\n"), yylval.str);
416				free(yylval.str);
417				yylval.val = EACL_PERM_MASK_ERROR;
418				return (ERROR);
419			}
420<AS>allow/[:,\n]	{
421
422				int c;
423
424				c = input();
425				unput(c);
426				if (c == ',' || c == '\n')
427					BEGIN ES;
428				else
429					BEGIN US;
430				yylval.val = ACE_ACCESS_ALLOWED_ACE_TYPE;
431				return (ACCESS_TYPE);
432			}
433<AS>deny/[:,\n]		{
434
435				int c;
436
437				c = input();
438				unput(c);
439				if (c == ',' || c == '\n')
440					BEGIN ES;
441				else
442					BEGIN US;
443
444				yylval.val = ACE_ACCESS_DENIED_ACE_TYPE;
445				return (ACCESS_TYPE);
446			}
447<AS>audit/[:,\n]	{
448				int c;
449
450				c = input();
451				unput(c);
452				if (c == ',' || c == '\n')
453					BEGIN ES;
454				else
455					BEGIN US;
456
457				yylval.val = ACE_SYSTEM_AUDIT_ACE_TYPE;
458				return (ACCESS_TYPE);
459			}
460<AS>alarm/[:,\n]	{
461				int c;
462
463				c = input();
464				unput(c);
465				if (c == ',' || c == '\n')
466					BEGIN ES;
467				else
468					BEGIN US;
469
470				yylval.val = ACE_SYSTEM_ALARM_ACE_TYPE;
471				return (ACCESS_TYPE);
472			}
473<AS>:			{
474
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;
480				return (ERROR);
481			}
482<AS>"\n"		{
483				acl_error(dgettext(TEXT_DOMAIN,
484				    "ACL access type must be specified.\n"));
485				yylval.val = EACL_INVALID_ACCESS_TYPE;
486				return (ERROR);
487			}
488<AS>.			{
489				if (yytext[0] != '\n' && yytext[0] != '\0') {
490					if (grab_string(":,\n") != 0) {
491						acl_error(dgettext(TEXT_DOMAIN,
492						    "Failed to "
493						    "retrieve error "
494						    "string.\n"));
495						yylval.val = EACL_MEM_ERROR;
496						return (ERROR);
497					}
498					acl_error(
499					    dgettext(TEXT_DOMAIN,
500					    "Invalid access "
501					    "type '%s' specified.\n"),
502					    yylval.str);
503				} else {
504					acl_error(
505					    dgettext(TEXT_DOMAIN,
506					    "No access "
507					    "type specified.\n"), yylval.str);
508				}
509
510				free(yylval.str);
511				yylval.val = EACL_INVALID_ACCESS_TYPE;
512				return (ERROR);
513			}
514<AIS>allow/[:,\n]	{
515
516				int c;
517
518				c = input();
519				unput(c);
520				if (c == ',' || c == '\n')
521					BEGIN ES;
522				else
523					BEGIN US;
524				yylval.val = ACE_ACCESS_ALLOWED_ACE_TYPE;
525				return (ACCESS_TYPE);
526			}
527<AIS>deny/[:,\n]	{
528
529				int c;
530
531				c = input();
532				unput(c);
533				if (c == ',' || c == '\n')
534					BEGIN ES;
535				else
536					BEGIN US;
537
538				yylval.val = ACE_ACCESS_DENIED_ACE_TYPE;
539				return (ACCESS_TYPE);
540			}
541<AIS>audit/[:,\n]	{
542				int c;
543
544				c = input();
545				unput(c);
546				if (c == ',' || c == '\n')
547					BEGIN ES;
548				else
549					BEGIN US;
550
551				yylval.val = ACE_SYSTEM_AUDIT_ACE_TYPE;
552				return (ACCESS_TYPE);
553			}
554<AIS>alarm/[:,\n]	{
555
556				int c;
557
558				c = input();
559				unput(c);
560				if (c == ',' || c == '\n')
561					BEGIN ES;
562				else
563					BEGIN US;
564
565				yylval.val = ACE_SYSTEM_ALARM_ACE_TYPE;
566				return (ACCESS_TYPE);
567			}
568<AIS>file_inherit/[:/,] {
569				yylval.val = ACE_FILE_INHERIT_ACE;
570				return (ACE_INHERIT);
571			}
572<AIS>dir_inherit/[:/,]	{
573				yylval.val = ACE_DIRECTORY_INHERIT_ACE;
574				return (ACE_INHERIT);
575			}
576<AIS>no_propagate/[/:,]	{
577				yylval.val = ACE_NO_PROPAGATE_INHERIT_ACE;
578				return (ACE_INHERIT);
579			}
580<AIS>inherit_only/[/:,]	{
581				yylval.val = ACE_INHERIT_ONLY_ACE;
582				return (ACE_INHERIT);
583			}
584
585<AIS>successful_access/[/:,] {
586				yylval.val = ACE_SUCCESSFUL_ACCESS_ACE_FLAG;
587				return (ACE_INHERIT);
588			}
589<AIS>failed_access/[/:,] {
590				yylval.val = ACE_FAILED_ACCESS_ACE_FLAG;
591				return (ACE_INHERIT);
592			}
593<AIS>inherited/[/:,] {
594				yylval.val = ACE_INHERITED_ACE;
595				return (ACE_INHERIT);
596			}
597<AIS>{INHERIT_STR}/[:]	{
598				yylval.str = strdup(yytext);
599				if (yylval.str == NULL) {
600					yylval.val = EACL_MEM_ERROR;
601					return (ERROR);
602				}
603				yystrings.y_iflags = yylval.str;
604				return (INHERIT_TOK);
605			}
606<AIS>:			{
607				/*
608				 * Only inheritance fields should hit this.
609				 * allow/deny fields match on ":" as part
610				 * of the regexp.
611				 */
612				BEGIN AS;
613				return (COLON);
614			}
615<AIS>"/"		{
616				return (SLASH);
617			}
618<AIS>"\n"		{
619				acl_error(
620				    dgettext(TEXT_DOMAIN,
621				    "Invalid ACL specification."
622				    "\nWas expecting to find"
623				    " access type or inheritance flags.\n"),
624				    yylval.str);
625				yylval.val = EACL_UNKNOWN_DATA;
626				return (ERROR);
627			}
628<AIS>","		{
629				acl_error(
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;
636				return (ERROR);
637			}
638<AIS>.			{
639				if (yytext[0] != '\n' && yytext[0] != '\0') {
640					if (grab_string(":,\n") != 0) {
641						acl_error(dgettext(TEXT_DOMAIN,
642						    "Failed to "
643						    "retrieve error "
644						    "string.\n"));
645						yylval.val = EACL_MEM_ERROR;
646						return (ERROR);
647					}
648					acl_error(
649					    dgettext(TEXT_DOMAIN,
650					    "Invalid inheritance or"
651				    	    " access type '%s' specified.\n"),
652				    	    yylval.str);
653				} else {
654					acl_error(
655					    dgettext(TEXT_DOMAIN,
656					    "No inheritance or "
657					    "access type specified.\n"),
658					    yylval.str);
659				}
660
661				free(yylval.str);
662				yylval.val = EACL_INVALID_ACCESS_TYPE;
663				return (ERROR);
664			}
665<US>{ID}/[,\n]		{
666				BEGIN ES;
667				yylval.str = strdup(yytext);
668				if (yylval.str == NULL) {
669					yylval.val = EACL_MEM_ERROR;
670					return (ERROR);
671				}
672				yystrings.y_idstr = yylval.str;
673				return (ID);
674			}
675<US>{SID}/[,\n]		{
676				BEGIN ES;
677				yylval.str = strdup(yytext);
678				if (yylval.str == NULL) {
679					yylval.val = EACL_MEM_ERROR;
680					return (ERROR);
681				}
682				yystrings.y_idstr = yylval.str;
683				return (SID);
684			}
685<US>:			{
686				return (COLON);
687			}
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.
693				 */
694				acl_error(dgettext(TEXT_DOMAIN,
695				    "Access type should be final"
696				    " field in ACL specification.\n"));
697				yylval.val = EACL_ENTRY_ERROR;
698				return (ERROR);
699			}
700<US>.			{
701				if (grab_string(",\n") != 0) {
702					acl_error(dgettext(TEXT_DOMAIN,
703					    "Failed to retrieve"
704					    " error string.\n"));
705					yylval.val = EACL_MEM_ERROR;
706					return (ERROR);
707				}
708				acl_error(
709				    dgettext(TEXT_DOMAIN,
710				    "Invalid data ':%s' specified"
711				    " on end of ACL.\n"), yylval.str);
712				free(yylval.str);
713				yylval.val = EACL_ENTRY_ERROR;
714				return (ERROR);
715			}
716<US>"\n"		{
717				acl_error(dgettext(TEXT_DOMAIN,
718				    "Missing fields in ACL "
719				    "specification.\nWas expecting to find "
720				    "uid/gid.\n"));
721				yylval.val = EACL_ENTRY_ERROR;
722				return (ERROR);
723			}
724<ES>","			{
725				BEGIN TS;
726				return (COMMA);
727			}
728<ES>.			{
729				if (grab_string("/:,\n") != 0) {
730					acl_error(
731					    dgettext(TEXT_DOMAIN,
732					    "Failed to retrieve error"
733				    	    " string.\n"));
734					yylval.val = EACL_MEM_ERROR;
735					return (ERROR);
736				}
737				acl_error(
738				    dgettext(TEXT_DOMAIN,
739				    "Unrecognized data '%s' found"
740			    	    " in ACL specification.\n"), yylval.str);
741				free(yylval.str);
742				yylval.val = EACL_UNKNOWN_DATA;
743				return (ERROR);
744			}
745<ES>"\n"		{
746				return (NL);
747			}
748%%
749
750
751/*
752 * Pull string up to terminator off of input string.
753 * used for retrieving illegal data in ACL specification.
754 *
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.
759 */
760int
761grab_string(char *terminators)
762{
763		int c;
764		int done = 0;
765		int cnt;
766		int alloced;
767		int error = 0;
768		char *ptr;
769
770		cnt = strlen(yytext);
771		yylval.str = calloc(cnt + 1, sizeof (char));
772		if (yylval.str == NULL) {
773			return (1);
774		}
775		alloced = cnt + 1;
776		strcpy(yylval.str, yytext);
777
778		do {
779			c = input();
780			if (c == EOF)
781				break;
782
783			for (ptr = terminators; *ptr; ptr++) {
784				if (c == *ptr) {
785					done = 1;
786					break;
787				}
788			}
789
790			if (done)
791				break;
792
793			if (cnt + 1 >= alloced) {
794				yylval.str = realloc(yylval.str,
795				    alloced + 80);
796					alloced += 80;
797				if (yylval.str == NULL)
798					return (1);
799
800				memset(yylval.str + cnt, 0,
801				    alloced - strlen(yylval.str));
802			}
803			yylval.str[strlen(yylval.str)] = c;
804			cnt++;
805		} while (!done);
806
807		return (error);
808}
809
810static int
811input(void)
812{
813	int c;
814
815	c = yybuf[yybufpos++];
816	if (c == '\0') {
817		return (EOF);
818	}
819
820	return (c);
821}
822
823static void
824unput(int c)
825{
826	if (c == '\0') {
827		return;
828	}
829
830	if (yybufpos > 0) {
831		--yybufpos;
832	}
833}
834
835/*
836 * return ACE entry type
837 */
838int
839ace_entry_type(int type)
840{
841	int ret = -1;
842	switch (type) {
843		case USER_TOK:
844		case USER_SID_TOK:
845			ret = 0;
846			break;
847		case GROUP_TOK:
848		case GROUP_SID_TOK:
849			ret = ACE_IDENTIFIER_GROUP;
850			break;
851		case OWNERAT_TOK:
852			ret = ACE_OWNER;
853			break;
854		case GROUPAT_TOK:
855			ret = ACE_IDENTIFIER_GROUP | ACE_GROUP;
856			break;
857		case EVERYONEAT_TOK:
858			ret = ACE_EVERYONE;
859			break;
860	}
861	return (ret);
862}
863
864
865/*
866 * return aclent entry type
867 */
868int
869aclent_entry_type(int type, int owning, int *ret)
870{
871
872	*ret = 0;
873
874	switch (type) {
875	case USER_TOK:
876		*ret = (owning == 0) ? USER : USER_OBJ;
877		break;
878	case GROUP_TOK:
879		*ret = (owning == 0) ? GROUP : GROUP_OBJ;
880		break;
881	case OTHER_TOK:
882		*ret = OTHER_OBJ;
883		break;
884	case MASK_TOK:
885		*ret = CLASS_OBJ;
886		break;
887	case DEFAULT_USER_TOK:
888		*ret = (owning == 0) ? DEF_USER : DEF_USER_OBJ;
889		break;
890	case DEFAULT_GROUP_TOK:
891		*ret = (owning == 0) ? DEF_GROUP : DEF_GROUP_OBJ;
892		break;
893	case DEFAULT_MASK_TOK:
894		*ret = DEF_CLASS_OBJ;
895		break;
896	case DEFAULT_OTHER_TOK:
897		*ret = DEF_OTHER_OBJ;
898		break;
899	default:
900		return (EACL_ENTRY_ERROR);
901	}
902
903	return (0);
904}
905
906/*
907 * convert string into numeric id.
908 */
909static int
910acl_str_to_id(char *str, uid_t *id)
911{
912	char *end;
913	uid_t value;
914
915	errno = 0;
916	value = strtoul(str, &end, 10);
917
918	if (errno != 0 || *end != '\0')
919		return (EACL_INVALID_USER_GROUP);
920
921	*id = value;
922
923	return (0);
924}
925
926/*
927 * determine either uid/gid for given entry type
928 */
929int
930get_id(int entry_type, char *name, uid_t *id)
931{
932	struct passwd *pw;
933	struct group *gr;
934	int error = 0;
935
936	switch (entry_type) {
937	case USER_TOK:
938	case DEFAULT_USER_TOK:
939		if ((error = acl_str_to_id(name, id)) == 0)
940			break;
941		pw = getpwnam(name);
942		if (pw) {
943			*id = pw->pw_uid;
944			error = 0;
945		}
946		break;
947
948	case GROUP_TOK:
949	case DEFAULT_GROUP_TOK:
950		if ((error = acl_str_to_id(name, id)) == 0)
951			break;
952		gr = getgrnam(name);
953		if (gr) {
954			*id = gr->gr_gid;
955			error = 0;
956		}
957		break;
958	case USER_SID_TOK:
959		if (sid_to_id(name, B_TRUE, id))
960			error = EACL_INVALID_USER_GROUP;
961		break;
962
963	case GROUP_SID_TOK:
964		if (sid_to_id(name, B_FALSE, id))
965			error = EACL_INVALID_USER_GROUP;
966		break;
967	}
968
969	return (error);
970}
971
972int
973get_id_nofail(int entry_type, char *name)
974{
975	uid_t id;
976
977	if (get_id(entry_type, name, &id))
978		return (UID_NOBODY);
979	else
980		return (id);
981}
982
983/*
984 * reset beginning state to TS and set character position
985 * back to zero.
986 */
987void
988yyreset()
989{
990	yybufpos = 0;
991	memset(&yystrings, 0, sizeof (yystrings));
992	BEGIN TS;
993}
994
995void
996yycleanup()
997{
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;
1010}
1011