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