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