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