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 2006 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 <sys/acl.h> 29 #include <aclutils.h> 30 31 extern int yyinteractive; 32 extern acl_t *yyacl; 33 %} 34 35 36 %union { 37 char *str; 38 int val; 39 struct acl_perm_type acl_perm; 40 ace_t ace; 41 aclent_t aclent; 42 acl_t *acl; 43 } 44 45 46 %token USER_TOK GROUP_TOK MASK_TOK OTHER_TOK OWNERAT_TOK 47 %token GROUPAT_TOK EVERYONEAT_TOK DEFAULT_USER_TOK DEFAULT_GROUP_TOK 48 %token DEFAULT_MASK_TOK DEFAULT_OTHER_TOK 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 return (EACL_MEM_ERROR); 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 return (EACL_DIFF_TYPE); 99 } 100 101 $$->acl_aclp = realloc($$->acl_aclp, 102 ($$->acl_entry_size * ($$->acl_cnt + 1))); 103 if ($$->acl_aclp == NULL) { 104 free (yyacl); 105 return (EACL_MEM_ERROR); 106 } 107 acep = $$->acl_aclp; 108 acep[$$->acl_cnt] = $1; 109 $$->acl_cnt++; 110 } 111 | aclent 112 { 113 aclent_t *aclent; 114 115 if (yyacl == NULL) { 116 yyacl = acl_alloc(ACLENT_T); 117 if (yyacl == NULL) 118 return (EACL_MEM_ERROR); 119 } 120 121 $$ = yyacl; 122 if ($$->acl_type == ACE_T) { 123 acl_error(dgettext(TEXT_DOMAIN, 124 "Cannot have NFSv4/ZFS ACL entries" 125 " with POSIX draft ACL entries.\n")); 126 acl_free(yyacl); 127 yyacl = NULL; 128 return (EACL_DIFF_TYPE); 129 } 130 131 $$->acl_aclp = realloc($$->acl_aclp, 132 ($$->acl_entry_size * ($$->acl_cnt +1))); 133 if ($$->acl_aclp == NULL) { 134 free (yyacl); 135 return (EACL_MEM_ERROR); 136 } 137 aclent = $$->acl_aclp; 138 aclent[$$->acl_cnt] = $1; 139 $$->acl_cnt++; 140 } 141 142 ace: entry_type idname ace_perms access_type 143 { 144 int error; 145 int id; 146 int mask; 147 148 error = get_id($1, $2, &id); 149 if (error) { 150 acl_error(dgettext(TEXT_DOMAIN, 151 "Invalid user %s specified.\n"), $2); 152 free($2); 153 return (EACL_INVALID_USER_GROUP); 154 } 155 156 $$.a_who = id; 157 $$.a_flags = ace_entry_type($1); 158 free($2); 159 error = ace_perm_mask(&$3, &$$.a_access_mask); 160 if (error) 161 return (error); 162 $$.a_type = $4; 163 164 } 165 | entry_type idname ace_perms access_type COLON id 166 { 167 int error; 168 int id; 169 170 if (yyinteractive) { 171 acl_error(dgettext(TEXT_DOMAIN, 172 "Extra fields on the end of " 173 "ACL specification.\n")); 174 return (EACL_UNKNOWN_DATA); 175 } 176 error = get_id($1, $2, &id); 177 if (error) { 178 $$.a_who = $6; 179 } else { 180 $$.a_who = id; 181 } 182 $$.a_flags = ace_entry_type($1); 183 free($2); 184 error = ace_perm_mask(&$3, &$$.a_access_mask); 185 if (error) 186 return (error); 187 $$.a_type = $4; 188 } 189 | entry_type idname ace_perms iflags access_type 190 { 191 int error; 192 int id; 193 194 error = get_id($1, $2, &id); 195 if (error) { 196 acl_error(dgettext(TEXT_DOMAIN, 197 "Invalid user %s specified.\n"), $2); 198 free($2); 199 return (EACL_INVALID_USER_GROUP); 200 } 201 202 $$.a_who = id; 203 $$.a_flags = ace_entry_type($1); 204 free($2); 205 error = ace_perm_mask(&$3, &$$.a_access_mask); 206 if (error) 207 return (error); 208 $$.a_type = $5; 209 $$.a_flags |= $4; 210 } 211 | entry_type idname ace_perms iflags access_type COLON id 212 { 213 int error; 214 int id; 215 216 if (yyinteractive) { 217 acl_error(dgettext(TEXT_DOMAIN, 218 "Extra fields on the end of " 219 "ACL specification.\n")); 220 return (EACL_UNKNOWN_DATA); 221 } 222 error = get_id($1, $2, &id); 223 if (error) { 224 $$.a_who = $7; 225 } else { 226 $$.a_who = id; 227 } 228 229 $$.a_flags = ace_entry_type($1); 230 free($2); 231 error = ace_perm_mask(&$3, &$$.a_access_mask); 232 if (error) 233 return (error); 234 235 $$.a_type = $5; 236 $$.a_flags |= $4; 237 } 238 | entry_type ace_perms access_type 239 { 240 int error; 241 242 $$.a_who = -1; 243 $$.a_flags = ace_entry_type($1); 244 error = ace_perm_mask(&$2, &$$.a_access_mask); 245 if (error) { 246 return (error); 247 } 248 $$.a_type = $3; 249 } 250 | entry_type ace_perms access_type COLON id 251 { 252 if (yyinteractive) { 253 acl_error(dgettext(TEXT_DOMAIN, 254 "Extra fields on the end of " 255 "ACL specification.\n")); 256 return (EACL_UNKNOWN_DATA); 257 } 258 259 return (EACL_ENTRY_ERROR); 260 } 261 | entry_type ace_perms iflags access_type 262 { 263 int error; 264 265 $$.a_who = -1; 266 $$.a_flags = ace_entry_type($1); 267 error = ace_perm_mask(&$2, &$$.a_access_mask); 268 if (error) 269 return (error); 270 $$.a_type = $4; 271 $$.a_flags |= $3; 272 273 } 274 | entry_type ace_perms iflags access_type COLON id 275 { 276 if (yyinteractive) { 277 acl_error(dgettext(TEXT_DOMAIN, 278 "Extra fields on the end of " 279 "ACL specification.\n")); 280 return (EACL_UNKNOWN_DATA); 281 } 282 return (EACL_ENTRY_ERROR); 283 } 284 285 aclent: entry_type idname aclent_perm /* user or group */ 286 { 287 int error; 288 int id; 289 290 error = get_id($1, $2, &id); 291 if (error) { 292 acl_error(dgettext(TEXT_DOMAIN, 293 "Invalid user '%s' specified.\n"), $2); 294 free($2); 295 return (EACL_INVALID_USER_GROUP); 296 } 297 298 error = compute_aclent_perms($3.perm_str, &$$.a_perm); 299 if (error) { 300 free($2); 301 acl_error(dgettext(TEXT_DOMAIN, 302 "Invalid permission(s) '%s' specified.\n"), 303 $3.perm_str); 304 return (error); 305 } 306 $$.a_id = id; 307 error = aclent_entry_type($1, 0, &$$.a_type); 308 free($2); 309 if (error) { 310 acl_error( 311 dgettext(TEXT_DOMAIN, 312 "Invalid ACL entry type '%s' specified.\n"), $1); 313 return (error); 314 } 315 } 316 | entry_type COLON aclent_perm /* owner group other */ 317 { 318 int error; 319 320 error = compute_aclent_perms($3.perm_str, &$$.a_perm); 321 if (error) { 322 acl_error(dgettext(TEXT_DOMAIN, 323 "Invalid permission(s) '%s' specified.\n"), 324 $3.perm_str); 325 return (error); 326 } 327 $$.a_id = -1; 328 error = aclent_entry_type($1, 1, &$$.a_type); 329 if (error) { 330 acl_error( 331 dgettext(TEXT_DOMAIN, 332 "Invalid ACL entry type '%s' specified.\n"), $1); 333 return (error); 334 } 335 } 336 | entry_type COLON aclent_perm COLON id 337 { 338 if (yyinteractive) { 339 acl_error(dgettext(TEXT_DOMAIN, 340 "Extra fields on the end of ACL specification.\n")); 341 return (EACL_UNKNOWN_DATA); 342 } 343 return (EACL_ENTRY_ERROR); 344 } 345 | entry_type idname aclent_perm COLON id /* user or group */ 346 { 347 int error; 348 int id; 349 350 if (yyinteractive) { 351 acl_error(dgettext(TEXT_DOMAIN, 352 "Extra fields on the end of ACL specification.\n")); 353 return (EACL_UNKNOWN_DATA); 354 } 355 error = compute_aclent_perms($3.perm_str, &$$.a_perm); 356 if (error) { 357 free($2); 358 acl_error(dgettext(TEXT_DOMAIN, 359 "Invalid permission(s) '%s' specified.\n"), 360 $3.perm_str); 361 return (error); 362 } 363 error = get_id($1, $2, &id); 364 if (error) 365 $$.a_id = $5; 366 else 367 $$.a_id = id; 368 369 error = aclent_entry_type($1, 0, &$$.a_type); 370 free($2); 371 if (error) { 372 acl_error( 373 dgettext(TEXT_DOMAIN, 374 "Invalid ACL entry type '%s' specified.\n"), $1); 375 return (error); 376 } 377 } 378 | entry_type aclent_perm /* mask entry */ 379 { 380 int error; 381 382 error = compute_aclent_perms($2.perm_str, &$$.a_perm); 383 if (error) { 384 acl_error(dgettext(TEXT_DOMAIN, 385 "Invalid permission(s) '%s' specified.\n"), 386 $2.perm_str); 387 return (error); 388 } 389 $$.a_id = -1; 390 error = aclent_entry_type($1, 0, &$$.a_type); 391 if (error) { 392 acl_error( 393 dgettext(TEXT_DOMAIN, 394 "Invalid ACL entry type specified %d.\n"), 395 error); 396 return (error); 397 } 398 } 399 | entry_type aclent_perm COLON id 400 { 401 if (yyinteractive) { 402 acl_error(dgettext(TEXT_DOMAIN, 403 "Extra fields on the end of ACL specification.\n")); 404 return (EACL_UNKNOWN_DATA); 405 } 406 return (EACL_ENTRY_ERROR); 407 } 408 409 iflags: compact_iflag COLON {$$ = $1;} 410 | verbose_iflag COLON {$$ = $1;} 411 | COLON {$$ = 0;} 412 413 compact_iflag : INHERIT_TOK 414 { 415 int error; 416 uint32_t iflags; 417 418 error = compute_ace_inherit($1, &iflags); 419 if (error) { 420 acl_error(dgettext(TEXT_DOMAIN, 421 "Invalid inheritance flags '%s' specified.\n"), $1); 422 free($1); 423 return (error); 424 } 425 $$ = iflags; 426 } 427 | INHERIT_TOK SLASH verbose_iflag 428 { 429 acl_error(dgettext(TEXT_DOMAIN, 430 "Can't mix compact inherit flags with" 431 " verbose inheritance flags.\n")); 432 return (EACL_INHERIT_ERROR); 433 } 434 435 verbose_iflag: ACE_INHERIT {$$ |= $1;} 436 | ACE_INHERIT SLASH verbose_iflag {$$ = $1 | $3;} 437 | ACE_INHERIT SLASH compact_iflag 438 { 439 acl_error(dgettext(TEXT_DOMAIN, 440 "Can't mix verbose inherit flags with" 441 " compact inheritance flags.\n")); 442 return (EACL_INHERIT_ERROR); 443 } 444 | ACE_INHERIT SLASH ACCESS_TYPE 445 { 446 acl_error(dgettext(TEXT_DOMAIN, 447 "Inheritance flags can't be mixed with access type.\n")); 448 return (EACL_INHERIT_ERROR); 449 } 450 | ACE_INHERIT SLASH ERROR {return ($3);} 451 452 aclent_perm: PERM_TOK 453 { 454 $$.perm_style = PERM_TYPE_UNKNOWN; 455 $$.perm_str = $1; 456 $$.perm_val = 0; 457 } 458 | PERM_TOK ERROR 459 { 460 acl_error(dgettext(TEXT_DOMAIN, 461 "ACL entry permissions are incorrectly specified.\n")); 462 return ($2); 463 } 464 465 access_type: ACCESS_TYPE {$$ = $1;} 466 | ERROR {return ($1);} 467 468 id: ID {$$ = $1;} 469 | COLON 470 { 471 acl_error(dgettext(TEXT_DOMAIN, 472 "Invalid uid/gid specified.\nThe field" 473 " should be a numeric value.\n")); 474 return (EACL_UNKNOWN_DATA); 475 } 476 | ERROR {return ($1);} 477 478 ace_perms: perm {$$ = $1;} 479 | aclent_perm COLON {$$ = $1;} 480 | ERROR {return ($1);} 481 482 perm: perms COLON {$$ = $1;} 483 | COLON {$$.perm_style = PERM_TYPE_EMPTY;} 484 485 perms: ACE_PERM 486 { 487 $$.perm_style = PERM_TYPE_ACE; 488 $$.perm_val |= $1; 489 } 490 | ACE_PERM SLASH perms 491 { 492 $$.perm_style = PERM_TYPE_ACE; 493 $$.perm_val = $1 | $3.perm_val; 494 } 495 | ACE_PERM SLASH aclent_perm 496 { 497 498 acl_error(dgettext(TEXT_DOMAIN, 499 "Can't mix verbose permissions with" 500 " compact permission.\n")); 501 return (EACL_PERM_MASK_ERROR); 502 503 } 504 | ACE_PERM SLASH ERROR {return ($3);} 505 506 507 idname: IDNAME {$$ = $1;} 508 509 entry_type: ENTRY_TYPE {$$ = $1;} 510 | ERROR {return ($1);} 511