Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / lib / libsec / common / acl.y
blob138b988730c04dfeb6a5b90624508e5aff74a43e
1 %{
2 /*
3 * CDDL HEADER START
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License (the "License").
7 * You may not use this file except in compliance with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <acl_common.h>
27 #include <aclutils.h>
29 extern int yyinteractive;
30 extern int yylex(void);
31 extern acl_t *yyacl;
34 %union {
35 char *str;
36 int val;
37 struct acl_perm_type acl_perm;
38 ace_t ace;
39 aclent_t aclent;
40 acl_t *acl;
44 %token USER_TOK USER_SID_TOK GROUP_TOK GROUP_SID_TOK MASK_TOK OTHER_TOK
45 %token OWNERAT_TOK GROUPAT_TOK EVERYONEAT_TOK DEFAULT_USER_TOK
46 %token DEFAULT_GROUP_TOK DEFAULT_MASK_TOK DEFAULT_OTHER_TOK
47 %token COLON COMMA NL SLASH
48 %token <str> ID IDNAME PERM_TOK INHERIT_TOK SID
49 %token <val> ERROR ACE_PERM ACE_INHERIT ENTRY_TYPE ACCESS_TYPE
51 %type <str> idname id
52 %type <acl_perm> perms perm aclent_perm ace_perms
53 %type <acl> acl_entry
54 %type <ace> ace
55 %type <aclent> aclent
56 %type <val> iflags verbose_iflag compact_iflag access_type entry_type
58 %left ERROR COLON
62 acl: acl_entry NL
64 yyacl = $1;
65 return (0);
68 /* This seems illegal, but the old aclfromtext() allows it */
69 | acl_entry COMMA NL
71 yyacl = $1;
72 return (0);
74 | acl_entry COMMA acl
76 yyacl = $1;
77 return (0);
80 acl_entry: ace
82 ace_t *acep;
84 if (yyacl == NULL) {
85 yyacl = acl_alloc(ACE_T);
86 if (yyacl == NULL) {
87 yycleanup();
88 return (EACL_MEM_ERROR);
92 $$ = yyacl;
93 if ($$->acl_type == ACLENT_T) {
94 acl_error(dgettext(TEXT_DOMAIN,
95 "Cannot have POSIX draft ACL entries"
96 " with NFSv4/ZFS ACL entries.\n"));
97 acl_free(yyacl);
98 yyacl = NULL;
99 yycleanup();
100 return (EACL_DIFF_TYPE);
103 $$->acl_aclp = realloc($$->acl_aclp,
104 ($$->acl_entry_size * ($$->acl_cnt + 1)));
105 if ($$->acl_aclp == NULL) {
106 free (yyacl);
107 yycleanup();
108 return (EACL_MEM_ERROR);
110 acep = $$->acl_aclp;
111 acep[$$->acl_cnt] = $1;
112 $$->acl_cnt++;
113 yycleanup();
115 | aclent
117 aclent_t *aclent;
119 if (yyacl == NULL) {
120 yyacl = acl_alloc(ACLENT_T);
121 if (yyacl == NULL) {
122 yycleanup();
123 return (EACL_MEM_ERROR);
127 $$ = yyacl;
128 if ($$->acl_type == ACE_T) {
129 acl_error(dgettext(TEXT_DOMAIN,
130 "Cannot have NFSv4/ZFS ACL entries"
131 " with POSIX draft ACL entries.\n"));
132 acl_free(yyacl);
133 yyacl = NULL;
134 yycleanup();
135 return (EACL_DIFF_TYPE);
138 $$->acl_aclp = realloc($$->acl_aclp,
139 ($$->acl_entry_size * ($$->acl_cnt +1)));
140 if ($$->acl_aclp == NULL) {
141 free (yyacl);
142 yycleanup();
143 return (EACL_MEM_ERROR);
145 aclent = $$->acl_aclp;
146 aclent[$$->acl_cnt] = $1;
147 $$->acl_cnt++;
148 yycleanup();
151 ace: entry_type idname ace_perms access_type
153 int error;
154 uid_t id;
155 int mask;
157 error = get_id($1, $2, &id);
158 if (error) {
159 bad_entry_type($1, $2);
160 yycleanup();
161 return (EACL_INVALID_USER_GROUP);
164 $$.a_who = id;
165 $$.a_flags = ace_entry_type($1);
166 error = ace_perm_mask(&$3, &$$.a_access_mask);
167 if (error) {
168 yycleanup();
169 return (error);
171 $$.a_type = $4;
174 | entry_type idname ace_perms access_type COLON id
176 int error;
177 uid_t id;
179 if (yyinteractive) {
180 acl_error(dgettext(TEXT_DOMAIN,
181 "Extra fields on the end of "
182 "ACL specification.\n"));
183 yycleanup();
184 return (EACL_UNKNOWN_DATA);
186 error = get_id($1, $2, &id);
187 if (error) {
188 $$.a_who = get_id_nofail($1, $6);
189 } else {
190 $$.a_who = id;
192 $$.a_flags = ace_entry_type($1);
193 error = ace_perm_mask(&$3, &$$.a_access_mask);
194 if (error) {
195 yycleanup();
196 return (error);
198 $$.a_type = $4;
200 | entry_type idname ace_perms iflags access_type
202 int error;
203 uid_t id;
205 error = get_id($1, $2, &id);
206 if (error) {
207 bad_entry_type($1, $2);
208 yycleanup();
209 return (EACL_INVALID_USER_GROUP);
212 $$.a_who = id;
213 $$.a_flags = ace_entry_type($1);
214 error = ace_perm_mask(&$3, &$$.a_access_mask);
215 if (error) {
216 yycleanup();
217 return (error);
219 $$.a_type = $5;
220 $$.a_flags |= $4;
222 | entry_type idname ace_perms iflags access_type COLON id
224 int error;
225 uid_t id;
227 if (yyinteractive) {
228 acl_error(dgettext(TEXT_DOMAIN,
229 "Extra fields on the end of "
230 "ACL specification.\n"));
231 yycleanup();
232 return (EACL_UNKNOWN_DATA);
234 error = get_id($1, $2, &id);
235 if (error) {
236 $$.a_who = get_id_nofail($1, $7);
237 } else {
238 $$.a_who = id;
241 $$.a_flags = ace_entry_type($1);
242 error = ace_perm_mask(&$3, &$$.a_access_mask);
243 if (error) {
244 yycleanup();
245 return (error);
248 $$.a_type = $5;
249 $$.a_flags |= $4;
251 | entry_type ace_perms access_type
253 int error;
255 $$.a_who = -1;
256 $$.a_flags = ace_entry_type($1);
257 error = ace_perm_mask(&$2, &$$.a_access_mask);
258 if (error) {
259 yycleanup();
260 return (error);
262 $$.a_type = $3;
264 | entry_type ace_perms access_type COLON id
266 yycleanup();
267 if (yyinteractive) {
268 acl_error(dgettext(TEXT_DOMAIN,
269 "Extra fields on the end of "
270 "ACL specification.\n"));
271 return (EACL_UNKNOWN_DATA);
274 return (EACL_ENTRY_ERROR);
276 | entry_type ace_perms iflags access_type
278 int error;
280 $$.a_who = -1;
281 $$.a_flags = ace_entry_type($1);
282 error = ace_perm_mask(&$2, &$$.a_access_mask);
283 if (error) {
284 yycleanup();
285 return (error);
287 $$.a_type = $4;
288 $$.a_flags |= $3;
291 | entry_type ace_perms iflags access_type COLON id
293 yycleanup();
294 if (yyinteractive) {
295 acl_error(dgettext(TEXT_DOMAIN,
296 "Extra fields on the end of "
297 "ACL specification.\n"));
298 return (EACL_UNKNOWN_DATA);
300 return (EACL_ENTRY_ERROR);
303 aclent: entry_type idname aclent_perm /* user or group */
305 int error;
306 uid_t id;
308 error = get_id($1, $2, &id);
309 if (error) {
310 bad_entry_type($1, $2);
311 yycleanup();
312 return (EACL_INVALID_USER_GROUP);
315 error = compute_aclent_perms($3.perm_str, &$$.a_perm);
316 if (error) {
317 acl_error(dgettext(TEXT_DOMAIN,
318 "Invalid permission(s) '%s' specified.\n"),
319 $3.perm_str);
320 yycleanup();
321 return (error);
323 $$.a_id = id;
324 error = aclent_entry_type($1, 0, &$$.a_type);
325 if (error) {
326 acl_error(
327 dgettext(TEXT_DOMAIN,
328 "Invalid ACL entry type '%s' specified.\n"), $1);
329 yycleanup();
330 return (error);
333 | entry_type COLON aclent_perm /* owner group other */
335 int error;
337 error = compute_aclent_perms($3.perm_str, &$$.a_perm);
338 if (error) {
339 acl_error(dgettext(TEXT_DOMAIN,
340 "Invalid permission(s) '%s' specified.\n"),
341 $3.perm_str);
342 yycleanup();
343 return (error);
345 $$.a_id = -1;
346 error = aclent_entry_type($1, 1, &$$.a_type);
347 if (error) {
348 acl_error(
349 dgettext(TEXT_DOMAIN,
350 "Invalid ACL entry type '%s' specified.\n"), $1);
351 yycleanup();
352 return (error);
355 | entry_type COLON aclent_perm COLON id
357 yycleanup();
358 if (yyinteractive) {
359 acl_error(dgettext(TEXT_DOMAIN,
360 "Extra fields on the end of ACL specification.\n"));
361 return (EACL_UNKNOWN_DATA);
363 return (EACL_ENTRY_ERROR);
365 | entry_type idname aclent_perm COLON id /* user or group */
367 int error;
368 uid_t id;
370 if (yyinteractive) {
371 acl_error(dgettext(TEXT_DOMAIN,
372 "Extra fields on the end of ACL specification.\n"));
373 yycleanup();
374 return (EACL_UNKNOWN_DATA);
376 error = compute_aclent_perms($3.perm_str, &$$.a_perm);
377 if (error) {
378 acl_error(dgettext(TEXT_DOMAIN,
379 "Invalid permission(s) '%s' specified.\n"),
380 $3.perm_str);
381 yycleanup();
382 return (error);
384 error = get_id($1, $2, &id);
385 if (error) {
386 $$.a_id = get_id_nofail($1, $5);
387 } else
388 $$.a_id = id;
390 error = aclent_entry_type($1, 0, &$$.a_type);
391 if (error) {
392 acl_error(
393 dgettext(TEXT_DOMAIN,
394 "Invalid ACL entry type '%s' specified.\n"), $1);
395 yycleanup();
396 return (error);
399 | entry_type aclent_perm /* mask entry */
401 int error;
403 error = compute_aclent_perms($2.perm_str, &$$.a_perm);
404 if (error) {
405 acl_error(dgettext(TEXT_DOMAIN,
406 "Invalid permission(s) '%s' specified.\n"),
407 $2.perm_str);
408 yycleanup();
409 return (error);
411 $$.a_id = -1;
412 error = aclent_entry_type($1, 0, &$$.a_type);
413 if (error) {
414 acl_error(
415 dgettext(TEXT_DOMAIN,
416 "Invalid ACL entry type specified %d.\n"),
417 error);
418 yycleanup();
419 return (error);
422 | entry_type aclent_perm COLON id
424 yycleanup();
425 if (yyinteractive) {
426 acl_error(dgettext(TEXT_DOMAIN,
427 "Extra fields on the end of ACL specification.\n"));
428 return (EACL_UNKNOWN_DATA);
430 return (EACL_ENTRY_ERROR);
433 iflags: compact_iflag COLON {$$ = $1;}
434 | verbose_iflag COLON {$$ = $1;}
435 | COLON {$$ = 0;}
437 compact_iflag : INHERIT_TOK
439 int error;
440 uint32_t iflags;
442 error = compute_ace_inherit($1, &iflags);
443 if (error) {
444 acl_error(dgettext(TEXT_DOMAIN,
445 "Invalid inheritance flags '%s' specified.\n"), $1);
446 yycleanup();
447 return (error);
449 $$ = iflags;
451 | INHERIT_TOK SLASH verbose_iflag
453 acl_error(dgettext(TEXT_DOMAIN,
454 "Can't mix compact inherit flags with"
455 " verbose inheritance flags.\n"));
456 yycleanup();
457 return (EACL_INHERIT_ERROR);
460 verbose_iflag: ACE_INHERIT {$$ |= $1;}
461 | ACE_INHERIT SLASH verbose_iflag {$$ = $1 | $3;}
462 | ACE_INHERIT SLASH compact_iflag
464 acl_error(dgettext(TEXT_DOMAIN,
465 "Can't mix verbose inherit flags with"
466 " compact inheritance flags.\n"));
467 yycleanup();
468 return (EACL_INHERIT_ERROR);
470 | ACE_INHERIT SLASH ACCESS_TYPE
472 acl_error(dgettext(TEXT_DOMAIN,
473 "Inheritance flags can't be mixed with access type.\n"));
474 yycleanup();
475 return (EACL_INHERIT_ERROR);
477 | ACE_INHERIT SLASH ERROR
479 yycleanup();
480 return ($3);
483 aclent_perm: PERM_TOK
485 $$.perm_style = PERM_TYPE_UNKNOWN;
486 $$.perm_str = $1;
487 $$.perm_val = 0;
489 | PERM_TOK ERROR
491 acl_error(dgettext(TEXT_DOMAIN,
492 "ACL entry permissions are incorrectly specified.\n"));
493 yycleanup();
494 return ($2);
497 access_type: ACCESS_TYPE {$$ = $1;}
498 | ERROR
500 yycleanup();
501 return ($1);
504 id: ID {$$ = $1;}
505 | SID {$$ = $1;}
506 | COLON
508 acl_error(dgettext(TEXT_DOMAIN,
509 "Invalid uid/gid specified.\nThe field"
510 " should be a numeric value.\n"));
511 yycleanup();
512 return (EACL_UNKNOWN_DATA);
514 | ERROR
516 yycleanup();
517 return ($1);
520 ace_perms: perm {$$ = $1;}
521 | aclent_perm COLON {$$ = $1;}
522 | ERROR
524 yycleanup();
525 return ($1);
528 perm: perms COLON {$$ = $1;}
529 | COLON {$$.perm_style = PERM_TYPE_EMPTY;}
531 perms: ACE_PERM
533 $$.perm_style = PERM_TYPE_ACE;
534 $$.perm_val |= $1;
536 | ACE_PERM SLASH perms
538 $$.perm_style = PERM_TYPE_ACE;
539 $$.perm_val = $1 | $3.perm_val;
541 | ACE_PERM SLASH aclent_perm
544 acl_error(dgettext(TEXT_DOMAIN,
545 "Can't mix verbose permissions with"
546 " compact permission.\n"));
547 yycleanup();
548 return (EACL_PERM_MASK_ERROR);
551 | ACE_PERM SLASH ERROR
553 yycleanup();
554 return ($3);
558 idname: IDNAME {$$ = $1;}
560 entry_type: ENTRY_TYPE {$$ = $1;}
561 | ERROR
563 yycleanup();
564 return ($1);
568 static void
569 bad_entry_type(int toketype, char *str)
571 switch(toketype) {
572 case USER_TOK:
573 case DEFAULT_USER_TOK:
574 acl_error(dgettext(TEXT_DOMAIN,
575 "Invalid user %s specified.\n"), str);
576 break;
578 case GROUP_TOK:
579 case DEFAULT_GROUP_TOK:
580 acl_error(dgettext(TEXT_DOMAIN,
581 "Invalid group %s specified.\n"), str);
582 break;
584 case USER_SID_TOK:
585 acl_error(dgettext(TEXT_DOMAIN,
586 "Invalid user SID %s specified.\n"), str);
587 break;
589 case GROUP_SID_TOK:
590 acl_error(dgettext(TEXT_DOMAIN,
591 "Invalid group SID %s specified.\n"), str);