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 * Copyright 2022 RackTop Systems, Inc. 26 */ 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 %token BARE_SID_TOK 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> ID IDNAME PERM_TOK INHERIT_TOK SID 50 %token <val> ERROR ACE_PERM ACE_INHERIT ENTRY_TYPE ACCESS_TYPE 51 52 %type <str> idname id 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 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 = get_id_nofail($1, $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 = get_id_nofail($1, $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 = get_id_nofail($1, $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 | SID {$$ = $1;} 507 | COLON 508 { 509 acl_error(dgettext(TEXT_DOMAIN, 510 "Invalid uid/gid specified.\nThe field" 511 " should be a numeric value.\n")); 512 yycleanup(); 513 return (EACL_UNKNOWN_DATA); 514 } 515 | ERROR 516 { 517 yycleanup(); 518 return ($1); 519 } 520 521 ace_perms: perm {$$ = $1;} 522 | aclent_perm COLON {$$ = $1;} 523 | ERROR 524 { 525 yycleanup(); 526 return ($1); 527 } 528 529 perm: perms COLON {$$ = $1;} 530 | COLON {$$.perm_style = PERM_TYPE_EMPTY;} 531 532 perms: ACE_PERM 533 { 534 $$.perm_style = PERM_TYPE_ACE; 535 $$.perm_val |= $1; 536 } 537 | ACE_PERM SLASH perms 538 { 539 $$.perm_style = PERM_TYPE_ACE; 540 $$.perm_val = $1 | $3.perm_val; 541 } 542 | ACE_PERM SLASH aclent_perm 543 { 544 545 acl_error(dgettext(TEXT_DOMAIN, 546 "Can't mix verbose permissions with" 547 " compact permission.\n")); 548 yycleanup(); 549 return (EACL_PERM_MASK_ERROR); 550 551 } 552 | ACE_PERM SLASH ERROR 553 { 554 yycleanup(); 555 return ($3); 556 } 557 558 559 idname: IDNAME {$$ = $1;} 560 561 entry_type: ENTRY_TYPE {$$ = $1;} 562 | ERROR 563 { 564 yycleanup(); 565 return ($1); 566 } 567 568 %% 569 static void 570 bad_entry_type(int toketype, char *str) 571 { 572 switch(toketype) { 573 case USER_TOK: 574 case DEFAULT_USER_TOK: 575 acl_error(dgettext(TEXT_DOMAIN, 576 "Invalid user %s specified.\n"), str); 577 break; 578 579 case GROUP_TOK: 580 case DEFAULT_GROUP_TOK: 581 acl_error(dgettext(TEXT_DOMAIN, 582 "Invalid group %s specified.\n"), str); 583 break; 584 585 case USER_SID_TOK: 586 acl_error(dgettext(TEXT_DOMAIN, 587 "Invalid user SID %s specified.\n"), str); 588 break; 589 590 case GROUP_SID_TOK: 591 acl_error(dgettext(TEXT_DOMAIN, 592 "Invalid group SID %s specified.\n"), str); 593 break; 594 595 case BARE_SID_TOK: 596 acl_error(dgettext(TEXT_DOMAIN, 597 "Invalid SID %s specified.\n"), str); 598 break; 599 } 600 } 601