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