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