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