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