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