Home | History | Annotate | Download | only in common
      1 %{
      2 /*
      3  * CDDL HEADER START
      4  *
      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.
      8  *
      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.
     13  *
     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]
     19  *
     20  * CDDL HEADER END
     21  *
     22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <acl_common.h>
     27 #include <aclutils.h>
     28 
     29 extern int yyinteractive;
     30 extern acl_t *yyacl;
     31 %}
     32 
     33 %union {
     34 	char *str;
     35 	int val;
     36 	struct acl_perm_type acl_perm;
     37 	ace_t ace;
     38 	aclent_t aclent;
     39 	acl_t *acl;
     40 }
     41 
     42 
     43 %token USER_TOK USER_SID_TOK GROUP_TOK GROUP_SID_TOK MASK_TOK OTHER_TOK
     44 %token OWNERAT_TOK GROUPAT_TOK EVERYONEAT_TOK DEFAULT_USER_TOK
     45 %token DEFAULT_GROUP_TOK DEFAULT_MASK_TOK DEFAULT_OTHER_TOK
     46 %token COLON COMMA NL SLASH
     47 %token <str> ID IDNAME PERM_TOK INHERIT_TOK SID
     48 %token <val> ERROR ACE_PERM ACE_INHERIT ENTRY_TYPE ACCESS_TYPE
     49 
     50 %type <str> idname id
     51 %type <acl_perm> perms perm aclent_perm ace_perms
     52 %type <acl> acl_entry
     53 %type <ace> ace
     54 %type <aclent> aclent
     55 %type <val> iflags verbose_iflag compact_iflag access_type entry_type
     56 
     57 %left ERROR COLON
     58 
     59 %%
     60 
     61 acl:	acl_entry NL
     62 	{
     63 		yyacl = $1;
     64 		return (0);
     65 	}
     66 
     67 	/* This seems illegal, but the old aclfromtext() allows it */
     68 	| acl_entry COMMA NL
     69 	{
     70 		yyacl = $1;
     71 		return (0);
     72 	}
     73 	| acl_entry COMMA acl
     74 	{
     75 		yyacl = $1;
     76 		return (0);
     77 	}
     78 
     79 acl_entry: ace
     80 	{
     81 		ace_t *acep;
     82 
     83 		if (yyacl == NULL) {
     84 			yyacl = acl_alloc(ACE_T);
     85 			if (yyacl == NULL) {
     86 				yycleanup();
     87 				return (EACL_MEM_ERROR);
     88 			}
     89 		}
     90 
     91 		$$ = yyacl;
     92 		if ($$->acl_type == ACLENT_T) {
     93 			acl_error(dgettext(TEXT_DOMAIN,
     94 			    "Cannot have POSIX draft ACL entries"
     95 			    " with NFSv4/ZFS ACL entries.\n"));
     96 			acl_free(yyacl);
     97 			yyacl = NULL;
     98 			yycleanup();
     99 			return (EACL_DIFF_TYPE);
    100 		}
    101 
    102 		$$->acl_aclp = realloc($$->acl_aclp,
    103 		    ($$->acl_entry_size * ($$->acl_cnt + 1)));
    104 		if ($$->acl_aclp == NULL) {
    105 			free (yyacl);
    106 			yycleanup();
    107 			return (EACL_MEM_ERROR);
    108 		}
    109 		acep = $$->acl_aclp;
    110 		acep[$$->acl_cnt] = $1;
    111 		$$->acl_cnt++;
    112 		yycleanup();
    113 	}
    114 	| aclent
    115 	{
    116 		aclent_t *aclent;
    117 
    118 		if (yyacl == NULL) {
    119 			yyacl = acl_alloc(ACLENT_T);
    120 			if (yyacl == NULL) {
    121 				yycleanup();
    122 				return (EACL_MEM_ERROR);
    123 			}
    124 		}
    125 
    126 		$$ = yyacl;
    127 		if ($$->acl_type == ACE_T) {
    128 			acl_error(dgettext(TEXT_DOMAIN,
    129 			    "Cannot have NFSv4/ZFS ACL entries"
    130 			    " with POSIX draft ACL entries.\n"));
    131 			acl_free(yyacl);
    132 			yyacl = NULL;
    133 			yycleanup();
    134 			return (EACL_DIFF_TYPE);
    135 		}
    136 
    137 		$$->acl_aclp = realloc($$->acl_aclp,
    138 		    ($$->acl_entry_size  * ($$->acl_cnt +1)));
    139 		if ($$->acl_aclp == NULL) {
    140 			free (yyacl);
    141 			yycleanup();
    142 			return (EACL_MEM_ERROR);
    143 		}
    144 		aclent = $$->acl_aclp;
    145 		aclent[$$->acl_cnt] = $1;
    146 		$$->acl_cnt++;
    147 		yycleanup();
    148 	}
    149 
    150 ace:	entry_type idname ace_perms access_type
    151 	{
    152 		int error;
    153 		uid_t id;
    154 		int mask;
    155 
    156 		error = get_id($1, $2, &id);
    157 		if (error) {
    158 			bad_entry_type($1, $2);
    159 			yycleanup();
    160 			return (EACL_INVALID_USER_GROUP);
    161 		}
    162 
    163 		$$.a_who = id;
    164 		$$.a_flags = ace_entry_type($1);
    165 		error = ace_perm_mask(&$3, &$$.a_access_mask);
    166 		if (error) {
    167 			yycleanup();
    168 			return (error);
    169 		}
    170 		$$.a_type = $4;
    171 
    172 	}
    173 	| entry_type idname ace_perms access_type COLON id
    174 	{
    175 		int error;
    176 		uid_t id;
    177 
    178 		if (yyinteractive) {
    179 			acl_error(dgettext(TEXT_DOMAIN,
    180 			    "Extra fields on the end of "
    181 			    "ACL specification.\n"));
    182 			yycleanup();
    183 			return (EACL_UNKNOWN_DATA);
    184 		}
    185 		error = get_id($1, $2, &id);
    186 		if (error) {
    187 			$$.a_who = get_id_nofail($1, $6);
    188 		} else {
    189 			$$.a_who = id;
    190 		}
    191 		$$.a_flags = ace_entry_type($1);
    192 		error = ace_perm_mask(&$3, &$$.a_access_mask);
    193 		if (error) {
    194 			yycleanup();
    195 			return (error);
    196 		}
    197 		$$.a_type = $4;
    198 	}
    199 	| entry_type idname ace_perms iflags access_type
    200 	{
    201 		int error;
    202 		uid_t id;
    203 
    204 		error = get_id($1, $2, &id);
    205 		if (error) {
    206 			bad_entry_type($1, $2);
    207 			yycleanup();
    208 			return (EACL_INVALID_USER_GROUP);
    209 		}
    210 
    211 		$$.a_who = id;
    212 		$$.a_flags = ace_entry_type($1);
    213 		error = ace_perm_mask(&$3, &$$.a_access_mask);
    214 		if (error) {
    215 			yycleanup();
    216 			return (error);
    217 		}
    218 		$$.a_type = $5;
    219 		$$.a_flags |= $4;
    220 	}
    221 	| entry_type idname ace_perms iflags access_type COLON id
    222 	{
    223 		int error;
    224 		uid_t  id;
    225 
    226 		if (yyinteractive) {
    227 			acl_error(dgettext(TEXT_DOMAIN,
    228 			    "Extra fields on the end of "
    229 			    "ACL specification.\n"));
    230 			yycleanup();
    231 			return (EACL_UNKNOWN_DATA);
    232 		}
    233 		error = get_id($1, $2, &id);
    234 		if (error) {
    235 			$$.a_who = get_id_nofail($1, $7);
    236 		} else {
    237 			$$.a_who = id;
    238 		}
    239 
    240 		$$.a_flags = ace_entry_type($1);
    241 		error = ace_perm_mask(&$3, &$$.a_access_mask);
    242 		if (error) {
    243 			yycleanup();
    244 			return (error);
    245 		}
    246 
    247 		$$.a_type = $5;
    248 		$$.a_flags |= $4;
    249 	}
    250 	| entry_type ace_perms access_type
    251 	{
    252 		int error;
    253 
    254 		$$.a_who = -1;
    255 		$$.a_flags = ace_entry_type($1);
    256 		error = ace_perm_mask(&$2, &$$.a_access_mask);
    257 		if (error) {
    258 			yycleanup();
    259 			return (error);
    260 		}
    261 		$$.a_type = $3;
    262 	}
    263 	| entry_type ace_perms access_type COLON id
    264 	{
    265 		yycleanup();
    266 		if (yyinteractive) {
    267 			acl_error(dgettext(TEXT_DOMAIN,
    268 			    "Extra fields on the end of "
    269 			    "ACL specification.\n"));
    270 			return (EACL_UNKNOWN_DATA);
    271 		}
    272 
    273 		return (EACL_ENTRY_ERROR);
    274 	}
    275 	| entry_type ace_perms iflags access_type
    276 	{
    277 		int error;
    278 
    279 		$$.a_who = -1;
    280 		$$.a_flags = ace_entry_type($1);
    281 		error = ace_perm_mask(&$2, &$$.a_access_mask);
    282 		if (error) {
    283 			yycleanup();
    284 			return (error);
    285 		}
    286 		$$.a_type = $4;
    287 		$$.a_flags |= $3;
    288 
    289 	}
    290 	| entry_type ace_perms iflags access_type COLON id
    291 	{
    292 		yycleanup();
    293 		if (yyinteractive) {
    294 			acl_error(dgettext(TEXT_DOMAIN,
    295 			    "Extra fields on the end of "
    296 			    "ACL specification.\n"));
    297 			return (EACL_UNKNOWN_DATA);
    298 		}
    299 		return (EACL_ENTRY_ERROR);
    300 	}
    301 
    302 aclent: entry_type idname aclent_perm	/* user or group */
    303 	{
    304 		int error;
    305 		uid_t id;
    306 
    307 		error = get_id($1, $2, &id);
    308 		if (error) {
    309 			bad_entry_type($1, $2);
    310 			yycleanup();
    311 			return (EACL_INVALID_USER_GROUP);
    312 		}
    313 
    314 		error = compute_aclent_perms($3.perm_str, &$$.a_perm);
    315 		if (error) {
    316 			acl_error(dgettext(TEXT_DOMAIN,
    317 			    "Invalid permission(s) '%s' specified.\n"),
    318 			    $3.perm_str);
    319 			yycleanup();
    320 			return (error);
    321 		}
    322 		$$.a_id = id;
    323 		error = aclent_entry_type($1, 0, &$$.a_type);
    324 		if (error) {
    325 			acl_error(
    326 			    dgettext(TEXT_DOMAIN,
    327 			    "Invalid ACL entry type '%s' specified.\n"), $1);
    328 			yycleanup();
    329 			return (error);
    330 		}
    331 	}
    332 	| entry_type COLON aclent_perm		/* owner group other */
    333 	{
    334 		int error;
    335 
    336 		error = compute_aclent_perms($3.perm_str, &$$.a_perm);
    337 		if (error) {
    338 			acl_error(dgettext(TEXT_DOMAIN,
    339 			    "Invalid permission(s) '%s' specified.\n"),
    340 			    $3.perm_str);
    341 			yycleanup();
    342 			return (error);
    343 		}
    344 		$$.a_id = -1;
    345 		error = aclent_entry_type($1, 1, &$$.a_type);
    346 		if (error) {
    347 			acl_error(
    348 			    dgettext(TEXT_DOMAIN,
    349 			    "Invalid ACL entry type '%s' specified.\n"), $1);
    350 			yycleanup();
    351 			return (error);
    352 		}
    353 	}
    354 	| entry_type COLON aclent_perm COLON id
    355 	{
    356 		yycleanup();
    357 		if (yyinteractive) {
    358 			acl_error(dgettext(TEXT_DOMAIN,
    359 			    "Extra fields on the end of ACL specification.\n"));
    360 			return (EACL_UNKNOWN_DATA);
    361 		}
    362 		return (EACL_ENTRY_ERROR);
    363 	}
    364 	| entry_type idname aclent_perm COLON id 	/* user or group */
    365 	{
    366 		int error;
    367 		uid_t id;
    368 
    369 		if (yyinteractive) {
    370 			acl_error(dgettext(TEXT_DOMAIN,
    371 			    "Extra fields on the end of ACL specification.\n"));
    372 			yycleanup();
    373 			return (EACL_UNKNOWN_DATA);
    374 		}
    375 		error = compute_aclent_perms($3.perm_str, &$$.a_perm);
    376 		if (error) {
    377 			acl_error(dgettext(TEXT_DOMAIN,
    378 			    "Invalid permission(s) '%s' specified.\n"),
    379 			    $3.perm_str);
    380 			yycleanup();
    381 			return (error);
    382 		}
    383 		error = get_id($1, $2, &id);
    384 		if (error) {
    385 			$$.a_id = get_id_nofail($1, $5);
    386 		} else
    387 			$$.a_id = id;
    388 
    389 		error = aclent_entry_type($1, 0, &$$.a_type);
    390 		if (error) {
    391 			acl_error(
    392 			    dgettext(TEXT_DOMAIN,
    393 			    "Invalid ACL entry type '%s' specified.\n"), $1);
    394 			yycleanup();
    395 			return (error);
    396 		}
    397 	}
    398 	| entry_type aclent_perm  /* mask entry */
    399 	{
    400 		int error;
    401 
    402 		error = compute_aclent_perms($2.perm_str, &$$.a_perm);
    403 		if (error) {
    404 			acl_error(dgettext(TEXT_DOMAIN,
    405 			    "Invalid permission(s) '%s' specified.\n"),
    406 			    $2.perm_str);
    407 			yycleanup();
    408 			return (error);
    409 		}
    410 		$$.a_id = -1;
    411 		error = aclent_entry_type($1, 0, &$$.a_type);
    412 		if (error) {
    413 			acl_error(
    414 			    dgettext(TEXT_DOMAIN,
    415 			    "Invalid ACL entry type specified %d.\n"),
    416 			    error);
    417 			yycleanup();
    418 			return (error);
    419 		}
    420 	}
    421 	| entry_type aclent_perm COLON id
    422 	{
    423 		yycleanup();
    424 		if (yyinteractive) {
    425 			acl_error(dgettext(TEXT_DOMAIN,
    426 			    "Extra fields on the end of ACL specification.\n"));
    427 			return (EACL_UNKNOWN_DATA);
    428 		}
    429 		return (EACL_ENTRY_ERROR);
    430 	}
    431 
    432 iflags: compact_iflag COLON {$$ = $1;}
    433 	| verbose_iflag COLON {$$ = $1;}
    434 	| COLON {$$ = 0;}
    435 
    436 compact_iflag : INHERIT_TOK
    437 	{
    438 		int error;
    439 		uint32_t iflags;
    440 
    441 		error = compute_ace_inherit($1, &iflags);
    442 		if (error) {
    443 			acl_error(dgettext(TEXT_DOMAIN,
    444 			    "Invalid inheritance flags '%s' specified.\n"), $1);
    445 			yycleanup();
    446 			return (error);
    447 		}
    448 		$$ = iflags;
    449 	}
    450 	| INHERIT_TOK SLASH verbose_iflag
    451 	{
    452 		acl_error(dgettext(TEXT_DOMAIN,
    453 		    "Can't mix compact inherit flags with"
    454 		    " verbose inheritance flags.\n"));
    455 		yycleanup();
    456 		return (EACL_INHERIT_ERROR);
    457 	}
    458 
    459 verbose_iflag: ACE_INHERIT	{$$ |= $1;}
    460 	| ACE_INHERIT SLASH verbose_iflag {$$ = $1 | $3;}
    461 	| ACE_INHERIT SLASH compact_iflag
    462 	{
    463 		acl_error(dgettext(TEXT_DOMAIN,
    464 		    "Can't mix verbose inherit flags with"
    465 		    " compact inheritance flags.\n"));
    466 		yycleanup();
    467 		return (EACL_INHERIT_ERROR);
    468 	}
    469 	| ACE_INHERIT SLASH ACCESS_TYPE
    470 	{
    471 		acl_error(dgettext(TEXT_DOMAIN,
    472 		    "Inheritance flags can't be mixed with access type.\n"));
    473 		yycleanup();
    474 		return (EACL_INHERIT_ERROR);
    475 	}
    476 	| ACE_INHERIT SLASH ERROR
    477 	{
    478 		yycleanup();
    479 		return ($3);
    480 	}
    481 
    482 aclent_perm: PERM_TOK
    483 	{
    484 		$$.perm_style = PERM_TYPE_UNKNOWN;
    485 		$$.perm_str = $1;
    486 		$$.perm_val = 0;
    487 	}
    488 	| PERM_TOK ERROR
    489 	{
    490 		acl_error(dgettext(TEXT_DOMAIN,
    491 		    "ACL entry permissions are incorrectly specified.\n"));
    492 		yycleanup();
    493 		return ($2);
    494 	}
    495 
    496 access_type: ACCESS_TYPE {$$ = $1;}
    497 	| ERROR
    498 	{
    499 		yycleanup();
    500 		return ($1);
    501 	}
    502 
    503 id: ID {$$ = $1;}
    504 	| SID {$$ = $1;}
    505   	| COLON
    506 	{
    507 		acl_error(dgettext(TEXT_DOMAIN,
    508 		    "Invalid uid/gid specified.\nThe field"
    509 		    " should be a numeric value.\n"));
    510 		yycleanup();
    511 		return (EACL_UNKNOWN_DATA);
    512 	}
    513 	| ERROR
    514 	{
    515 		yycleanup();
    516 		return ($1);
    517 	}
    518 
    519 ace_perms: perm {$$ = $1;}
    520 	| aclent_perm COLON {$$ = $1;}
    521 	| ERROR
    522 	{
    523 		yycleanup();
    524 		return ($1);
    525 	}
    526 
    527 perm: perms COLON {$$ = $1;}
    528     	| COLON {$$.perm_style = PERM_TYPE_EMPTY;}
    529 
    530 perms: ACE_PERM
    531      	{
    532 		$$.perm_style = PERM_TYPE_ACE;
    533 		$$.perm_val |= $1;
    534 	}
    535 	| ACE_PERM SLASH perms
    536 	{
    537 		$$.perm_style = PERM_TYPE_ACE;
    538 		$$.perm_val = $1 | $3.perm_val;
    539 	}
    540 	| ACE_PERM SLASH aclent_perm
    541 	{
    542 
    543 		acl_error(dgettext(TEXT_DOMAIN,
    544 		   "Can't mix verbose permissions with"
    545 		    " compact permission.\n"));
    546 		yycleanup();
    547 		return (EACL_PERM_MASK_ERROR);
    548 
    549 	}
    550 	| ACE_PERM SLASH ERROR
    551 	{
    552 		yycleanup();
    553 		return ($3);
    554 	}
    555 
    556 
    557 idname: IDNAME {$$ = $1;}
    558 
    559 entry_type: ENTRY_TYPE {$$ = $1;}
    560 	| ERROR
    561 	{
    562 		yycleanup();
    563 		return ($1);
    564 	}
    565 
    566 %%
    567 static void
    568 bad_entry_type(int toketype, char *str)
    569 {
    570 	switch(toketype) {
    571 	case USER_TOK:
    572 	case DEFAULT_USER_TOK:
    573 		acl_error(dgettext(TEXT_DOMAIN,
    574 		    "Invalid user %s specified.\n"), str);
    575 		break;
    576 
    577 	case GROUP_TOK:
    578 	case DEFAULT_GROUP_TOK:
    579 		acl_error(dgettext(TEXT_DOMAIN,
    580 		    "Invalid group %s specified.\n"), str);
    581 		break;
    582 
    583 	case USER_SID_TOK:
    584 		acl_error(dgettext(TEXT_DOMAIN,
    585 		    "Invalid user SID %s specified.\n"), str);
    586 		break;
    587 
    588 	case GROUP_SID_TOK:
    589 		acl_error(dgettext(TEXT_DOMAIN,
    590 		    "Invalid group SID %s specified.\n"), str);
    591 	}
    592 
    593 }
    594