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