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 extern int yylex(void); 34 35 %} 36 37 %union { 38 char *str; 39 int val; 40 struct acl_perm_type acl_perm; 41 ace_t ace; 42 aclent_t aclent; 43 acl_t *acl; 44 } 45 46 %token BARE_SID_TOK 47 %token USER_TOK USER_SID_TOK GROUP_TOK GROUP_SID_TOK MASK_TOK OTHER_TOK 48 %token OWNERAT_TOK GROUPAT_TOK EVERYONEAT_TOK DEFAULT_USER_TOK 49 %token DEFAULT_GROUP_TOK DEFAULT_MASK_TOK DEFAULT_OTHER_TOK 50 %token COLON COMMA NL SLASH 51 %token <str> ID IDNAME PERM_TOK INHERIT_TOK SID 52 %token <val> ERROR ACE_PERM ACE_INHERIT ENTRY_TYPE ACCESS_TYPE 53 54 %type <str> idname id 55 %type <acl_perm> perms perm aclent_perm ace_perms 56 %type <acl> acl_entry 57 %type <ace> ace 58 %type <aclent> aclent 59 %type <val> iflags verbose_iflag compact_iflag access_type entry_type 60 61 %left ERROR COLON 62 63 %% 64 65 acl: acl_entry NL 66 { 67 yyacl = $1; 68 return (0); 69 } 70 71 /* This seems illegal, but the old aclfromtext() allows it */ 72 | acl_entry COMMA NL 73 { 74 yyacl = $1; 75 return (0); 76 } 77 | acl_entry COMMA acl 78 { 79 yyacl = $1; 80 return (0); 81 } 82 83 acl_entry: ace 84 { 85 ace_t *acep; 86 87 if (yyacl == NULL) { 88 yyacl = acl_alloc(ACE_T); 89 if (yyacl == NULL) { 90 yycleanup(); 91 return (EACL_MEM_ERROR); 92 } 93 } 94 95 $$ = yyacl; 96 if ($$->acl_type == ACLENT_T) { 97 acl_error(dgettext(TEXT_DOMAIN, 98 "Cannot have POSIX draft ACL entries" 99 " with NFSv4/ZFS ACL entries.\n")); 100 acl_free(yyacl); 101 yyacl = NULL; 102 yycleanup(); 103 return (EACL_DIFF_TYPE); 104 } 105 106 $$->acl_aclp = realloc($$->acl_aclp, 107 ($$->acl_entry_size * ($$->acl_cnt + 1))); 108 if ($$->acl_aclp == NULL) { 109 free (yyacl); 110 yycleanup(); 111 return (EACL_MEM_ERROR); 112 } 113 acep = $$->acl_aclp; 114 acep[$$->acl_cnt] = $1; 115 $$->acl_cnt++; 116 yycleanup(); 117 } 118 | aclent 119 { 120 aclent_t *aclent; 121 122 if (yyacl == NULL) { 123 yyacl = acl_alloc(ACLENT_T); 124 if (yyacl == NULL) { 125 yycleanup(); 126 return (EACL_MEM_ERROR); 127 } 128 } 129 130 $$ = yyacl; 131 if ($$->acl_type == ACE_T) { 132 acl_error(dgettext(TEXT_DOMAIN, 133 "Cannot have NFSv4/ZFS ACL entries" 134 " with POSIX draft ACL entries.\n")); 135 acl_free(yyacl); 136 yyacl = NULL; 137 yycleanup(); 138 return (EACL_DIFF_TYPE); 139 } 140 141 $$->acl_aclp = realloc($$->acl_aclp, 142 ($$->acl_entry_size * ($$->acl_cnt +1))); 143 if ($$->acl_aclp == NULL) { 144 free (yyacl); 145 yycleanup(); 146 return (EACL_MEM_ERROR); 147 } 148 aclent = $$->acl_aclp; 149 aclent[$$->acl_cnt] = $1; 150 $$->acl_cnt++; 151 yycleanup(); 152 } 153 154 ace: entry_type idname ace_perms access_type 155 { 156 int error; 157 uid_t id; 158 int mask; 159 160 error = get_id($1, $2, &id); 161 if (error) { 162 bad_entry_type($1, $2); 163 yycleanup(); 164 return (EACL_INVALID_USER_GROUP); 165 } 166 167 $$.a_who = id; 168 $$.a_flags = ace_entry_type($1); 169 error = ace_perm_mask(&$3, &$$.a_access_mask); 170 if (error) { 171 yycleanup(); 172 return (error); 173 } 174 $$.a_type = $4; 175 176 } 177 | entry_type idname ace_perms access_type COLON id 178 { 179 int error; 180 uid_t id; 181 182 if (yyinteractive) { 183 acl_error(dgettext(TEXT_DOMAIN, 184 "Extra fields on the end of " 185 "ACL specification.\n")); 186 yycleanup(); 187 return (EACL_UNKNOWN_DATA); 188 } 189 error = get_id($1, $2, &id); 190 if (error) { 191 $$.a_who = get_id_nofail($1, $6); 192 } else { 193 $$.a_who = id; 194 } 195 $$.a_flags = ace_entry_type($1); 196 error = ace_perm_mask(&$3, &$$.a_access_mask); 197 if (error) { 198 yycleanup(); 199 return (error); 200 } 201 $$.a_type = $4; 202 } 203 | entry_type idname ace_perms iflags access_type 204 { 205 int error; 206 uid_t id; 207 208 error = get_id($1, $2, &id); 209 if (error) { 210 bad_entry_type($1, $2); 211 yycleanup(); 212 return (EACL_INVALID_USER_GROUP); 213 } 214 215 $$.a_who = id; 216 $$.a_flags = ace_entry_type($1); 217 error = ace_perm_mask(&$3, &$$.a_access_mask); 218 if (error) { 219 yycleanup(); 220 return (error); 221 } 222 $$.a_type = $5; 223 $$.a_flags |= $4; 224 } 225 | entry_type idname ace_perms iflags access_type COLON id 226 { 227 int error; 228 uid_t id; 229 230 if (yyinteractive) { 231 acl_error(dgettext(TEXT_DOMAIN, 232 "Extra fields on the end of " 233 "ACL specification.\n")); 234 yycleanup(); 235 return (EACL_UNKNOWN_DATA); 236 } 237 error = get_id($1, $2, &id); 238 if (error) { 239 $$.a_who = get_id_nofail($1, $7); 240 } else { 241 $$.a_who = id; 242 } 243 244 $$.a_flags = ace_entry_type($1); 245 error = ace_perm_mask(&$3, &$$.a_access_mask); 246 if (error) { 247 yycleanup(); 248 return (error); 249 } 250 251 $$.a_type = $5; 252 $$.a_flags |= $4; 253 } 254 | entry_type ace_perms access_type 255 { 256 int error; 257 258 $$.a_who = -1; 259 $$.a_flags = ace_entry_type($1); 260 error = ace_perm_mask(&$2, &$$.a_access_mask); 261 if (error) { 262 yycleanup(); 263 return (error); 264 } 265 $$.a_type = $3; 266 } 267 | entry_type ace_perms access_type COLON id 268 { 269 yycleanup(); 270 if (yyinteractive) { 271 acl_error(dgettext(TEXT_DOMAIN, 272 "Extra fields on the end of " 273 "ACL specification.\n")); 274 return (EACL_UNKNOWN_DATA); 275 } 276 277 return (EACL_ENTRY_ERROR); 278 } 279 | entry_type ace_perms iflags access_type 280 { 281 int error; 282 283 $$.a_who = -1; 284 $$.a_flags = ace_entry_type($1); 285 error = ace_perm_mask(&$2, &$$.a_access_mask); 286 if (error) { 287 yycleanup(); 288 return (error); 289 } 290 $$.a_type = $4; 291 $$.a_flags |= $3; 292 293 } 294 | entry_type ace_perms iflags access_type COLON id 295 { 296 yycleanup(); 297 if (yyinteractive) { 298 acl_error(dgettext(TEXT_DOMAIN, 299 "Extra fields on the end of " 300 "ACL specification.\n")); 301 return (EACL_UNKNOWN_DATA); 302 } 303 return (EACL_ENTRY_ERROR); 304 } 305 306 aclent: entry_type idname aclent_perm /* user or group */ 307 { 308 int error; 309 uid_t id; 310 311 error = get_id($1, $2, &id); 312 if (error) { 313 bad_entry_type($1, $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 uid_t 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 = get_id_nofail($1, $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 | SID {$$ = $1;} 509 | COLON 510 { 511 acl_error(dgettext(TEXT_DOMAIN, 512 "Invalid uid/gid specified.\nThe field" 513 " should be a numeric value.\n")); 514 yycleanup(); 515 return (EACL_UNKNOWN_DATA); 516 } 517 | ERROR 518 { 519 yycleanup(); 520 return ($1); 521 } 522 523 ace_perms: perm {$$ = $1;} 524 | aclent_perm COLON {$$ = $1;} 525 | ERROR 526 { 527 yycleanup(); 528 return ($1); 529 } 530 531 perm: perms COLON {$$ = $1;} 532 | COLON {$$.perm_style = PERM_TYPE_EMPTY;} 533 534 perms: ACE_PERM 535 { 536 $$.perm_style = PERM_TYPE_ACE; 537 $$.perm_val |= $1; 538 } 539 | ACE_PERM SLASH perms 540 { 541 $$.perm_style = PERM_TYPE_ACE; 542 $$.perm_val = $1 | $3.perm_val; 543 } 544 | ACE_PERM SLASH aclent_perm 545 { 546 547 acl_error(dgettext(TEXT_DOMAIN, 548 "Can't mix verbose permissions with" 549 " compact permission.\n")); 550 yycleanup(); 551 return (EACL_PERM_MASK_ERROR); 552 553 } 554 | ACE_PERM SLASH ERROR 555 { 556 yycleanup(); 557 return ($3); 558 } 559 560 561 idname: IDNAME {$$ = $1;} 562 563 entry_type: ENTRY_TYPE {$$ = $1;} 564 | ERROR 565 { 566 yycleanup(); 567 return ($1); 568 } 569 570 %% 571 static void 572 bad_entry_type(int toketype, char *str) 573 { 574 switch(toketype) { 575 case USER_TOK: 576 case DEFAULT_USER_TOK: 577 acl_error(dgettext(TEXT_DOMAIN, 578 "Invalid user %s specified.\n"), str); 579 break; 580 581 case GROUP_TOK: 582 case DEFAULT_GROUP_TOK: 583 acl_error(dgettext(TEXT_DOMAIN, 584 "Invalid group %s specified.\n"), str); 585 break; 586 587 case USER_SID_TOK: 588 acl_error(dgettext(TEXT_DOMAIN, 589 "Invalid user SID %s specified.\n"), str); 590 break; 591 592 case GROUP_SID_TOK: 593 acl_error(dgettext(TEXT_DOMAIN, 594 "Invalid group SID %s specified.\n"), str); 595 break; 596 597 case BARE_SID_TOK: 598 acl_error(dgettext(TEXT_DOMAIN, 599 "Invalid SID %s specified.\n"), str); 600 break; 601 } 602 } 603