c4f2d992 |
1 | /* -*-c-*- |
2 | * |
3 | * $Id: parser.y,v 1.1 1997/07/21 13:47:45 mdw Exp $ |
4 | * |
5 | * Parser for `become.conf' files |
6 | * |
7 | * (c) 1997 EBI |
8 | */ |
9 | |
10 | /*----- Licencing notice --------------------------------------------------* |
11 | * |
12 | * This file is part of `become' |
13 | * |
14 | * `Become' is free software; you can redistribute it and/or modify |
15 | * it under the terms of the GNU General Public License as published by |
16 | * the Free Software Foundation; either version 2 of the License, or |
17 | * (at your option) any later version. |
18 | * |
19 | * `Become' is distributed in the hope that it will be useful, |
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22 | * GNU General Public License for more details. |
23 | * |
24 | * You should have received a copy of the GNU General Public License |
25 | * along with `become'; if not, write to the Free Software |
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
27 | */ |
28 | |
29 | /*----- Revision history --------------------------------------------------* |
30 | * |
31 | * $Log: parser.y,v $ |
32 | * Revision 1.1 1997/07/21 13:47:45 mdw |
33 | * Initial revision |
34 | * |
35 | */ |
36 | |
37 | /*----- Header files ------------------------------------------------------*/ |
38 | %{ |
39 | |
40 | /* --- ANSI headers --- */ |
41 | |
42 | #include <stdio.h> |
43 | #include <stdlib.h> |
44 | #include <string.h> |
45 | |
46 | /* --- Unix headers --- */ |
47 | |
48 | #include <sys/types.h> |
49 | |
50 | #include <pwd.h> |
51 | #include <unistd.h> |
52 | |
53 | /* --- Local headers --- */ |
54 | |
55 | #include "class.h" |
56 | #include "daemon.h" |
57 | #include "lexer.h" |
58 | #include "name.h" |
59 | #include "rule.h" |
60 | #include "set.h" |
61 | #include "sym.h" |
62 | #include "userdb.h" |
63 | #include "utils.h" |
64 | |
65 | %} |
66 | /*----- Stack type --------------------------------------------------------*/ |
67 | |
68 | %union { |
69 | long i; |
70 | char *s; |
71 | name *n; |
72 | classdef *c; |
73 | } |
74 | |
75 | /*----- Token and rule declarations ---------------------------------------*/ |
76 | |
77 | /* --- Tokens --- */ |
78 | |
79 | %token BADTOKEN |
80 | %token USER |
81 | %token COMMAND |
82 | %token HOST |
83 | %token ALLOW |
84 | %token PORT |
85 | %token KEYFILE |
86 | %token <i> INT |
87 | %token <s> WORD |
88 | %token <s> STRING |
89 | %token ARROW |
90 | |
91 | %left ',' |
92 | %left '-' |
93 | %left '|' |
94 | %left '&' |
95 | |
96 | /* --- Rules --- */ |
97 | |
98 | %type <c> user_class command_class host_class |
99 | %type <c> user_class_opt command_class_opt host_class_opt |
100 | %type <n> name |
101 | |
102 | /*----- Error reporting ---------------------------------------------------*/ |
103 | %{ |
104 | |
105 | #define YYDEBUG 1 |
106 | #define YYERROR_VERBOSE |
107 | |
108 | /* --- @yyprint@ --- * |
109 | * |
110 | * Arguments: @FILE *fp@ = pointer to stream to write on |
111 | * @int type@ = pointer to token type |
112 | * @YYSTYPE v@ = token value |
113 | * |
114 | * Returns: --- |
115 | * |
116 | * Use: Displays the semantic value of a token. |
117 | */ |
118 | |
119 | #define YYPRINT(fp, type, value) yyprint(fp, type, value) |
120 | |
121 | static void yyprint(FILE *fp, int type, YYSTYPE v) |
122 | { |
123 | switch (type) { |
124 | case INT: |
125 | fprintf(fp, " %li", v.i); |
126 | break; |
127 | case WORD: |
128 | case STRING: |
129 | fprintf(fp, " `%s'", v.s); |
130 | break; |
131 | } |
132 | } |
133 | |
134 | /* --- @yyerror@ --- * |
135 | * |
136 | * Arguments: @const char *msg@ = pointer to error message |
137 | * |
138 | * Returns: --- |
139 | * |
140 | * Use: Reports parse errors. |
141 | */ |
142 | |
143 | static void yyerror(const char *msg) |
144 | { |
145 | moan("%s at line %i", msg, lex_line); |
146 | } |
147 | |
148 | %} |
149 | %% |
150 | /*----- The actual grammar ------------------------------------------------*/ |
151 | |
152 | /* --- Simple driver things --- */ |
153 | |
154 | file : /* empty */ |
155 | | file statement |
156 | ; |
157 | |
158 | statement : user_spec |
159 | | command_spec |
160 | | host_spec |
161 | | allow_spec |
162 | | port_spec |
163 | | key_spec |
164 | | error ';' |
165 | ; |
166 | |
167 | /* --- Main statement types --- */ |
168 | |
169 | user_spec : USER name '=' user_class ';' { |
170 | if ($2->c) |
171 | class_dec($2->c); |
172 | $2->c = $4; |
173 | } |
174 | ; |
175 | |
176 | command_spec : COMMAND name '=' command_class ';' { |
177 | if ($2->c) |
178 | class_dec($2->c); |
179 | $2->c = $4; |
180 | } |
181 | ; |
182 | |
183 | host_spec : HOST name '=' host_class ';' { |
184 | if ($2->c) |
185 | class_dec($2->c); |
186 | $2->c = $4; |
187 | } |
188 | ; |
189 | |
190 | port_spec : PORT INT ';' { daemon_usePort($2); } |
191 | ; |
192 | |
193 | key_spec : KEYFILE STRING ';' { daemon_readKey($2); } |
194 | |
195 | /* --- Parsing allow specifications --- */ |
196 | |
197 | allow_spec : ALLOW host_class_opt user_class ARROW |
198 | user_class_opt command_class_opt ';' { |
199 | rule_add($2, $3, $5, $6); |
200 | } |
201 | |
202 | host_class_opt : /* empty */ { $$ = class_all; } |
203 | | '[' host_class ']' { $$ = $2; } |
204 | ; |
205 | |
206 | user_class_opt : /* empty */ { $$ = class_all; } |
207 | | user_class { $$ = $1; } |
208 | ; |
209 | |
210 | command_class_opt : /* empty */ { $$ = class_all; } |
211 | | ':' command_class { $$ = $2; } |
212 | ; |
213 | |
214 | /* --- Names get translated into symbols quickly --- */ |
215 | |
216 | name : WORD { |
217 | unsigned f; |
218 | name *n = name_find($1, 1, &f); |
219 | if (!f) |
220 | n->c = 0; |
221 | $$ = n; |
222 | } |
223 | |
224 | /*----- Various class expression types ------------------------------------* |
225 | * |
226 | * Unfortunately, all these need to handle token types slightly differently |
227 | * and I can't be bothered to remember the current state. |
228 | */ |
229 | |
230 | /* --- User class expressions --- */ |
231 | |
232 | user_class : user_class ',' user_class { |
233 | if ($1->type != $3->type) { |
234 | yyerror("type mismatch"); |
235 | class_dec($1); |
236 | class_dec($3); |
237 | YYERROR; |
238 | } else { |
239 | if ($1 == class_all) |
240 | $$ = class_all; |
241 | else |
242 | $$ = class_create($1->type, |
243 | set_union($1->t, $3->t)); |
244 | class_dec($1); |
245 | class_dec($3); |
246 | } |
247 | } |
248 | | user_class '-' user_class { |
249 | if ($1->type != $3->type) { |
250 | yyerror("type mismatch"); |
251 | class_dec($1); |
252 | class_dec($3); |
253 | YYERROR; |
254 | } else { |
255 | $$ = class_create($1->type, |
256 | set_subtract($1->t, $3->t)); |
257 | class_dec($1); |
258 | class_dec($3); |
259 | } |
260 | } |
261 | | user_class '&' user_class { |
262 | if ($1->type != $3->type) { |
263 | yyerror("type mismatch"); |
264 | class_dec($1); |
265 | class_dec($3); |
266 | YYERROR; |
267 | } else { |
268 | if ($1 == class_all) |
269 | $$ = class_all; |
270 | else |
271 | $$ = class_create($1->type, |
272 | set_intersect($1->t, $3->t)); |
273 | class_dec($1); |
274 | class_dec($3); |
275 | } |
276 | } |
277 | | user_class '|' user_class { |
278 | if ($1->type != $3->type) { |
279 | yyerror("type mismatch"); |
280 | class_dec($1); |
281 | class_dec($3); |
282 | YYERROR; |
283 | } else { |
284 | if ($1 == class_all) |
285 | $$ = class_all; |
286 | else |
287 | $$ = class_create($1->type, |
288 | set_union($1->t, $3->t)); |
289 | class_dec($1); |
290 | class_dec($3); |
291 | } |
292 | } |
293 | | INT { |
294 | sym_table *t = xmalloc(sizeof(*t)); |
295 | int u = $1; |
296 | sym_createTable(t); |
297 | sym_find(t, (char *)&u, sizeof(u), |
298 | sizeof(sym_base), 0); |
299 | $$ = class_create(clType_user, t); |
300 | } |
301 | | STRING { |
302 | struct passwd *pw; |
303 | sym_table *t; |
304 | int u; |
305 | if ((pw = userdb_userByName($1)) == 0) { |
306 | moan("user `%s' not known at line %i", |
307 | $1, lex_line); |
308 | YYERROR; |
309 | } else { |
310 | t = xmalloc(sizeof(*t)); |
311 | u = pw->pw_uid; |
312 | sym_createTable(t); |
313 | sym_find(t, (char *)&u, sizeof(u), |
314 | sizeof(sym_base), 0); |
315 | $$ = class_create(clType_user, t); |
316 | } |
317 | } |
318 | | WORD { |
319 | name *n = name_find($1, 0, 0); |
320 | if (!n || !n->c) { |
321 | moan("class `%s' not found at line %i", |
322 | $1, lex_line); |
323 | YYERROR; |
324 | } else if (~n->c->type & clType_user) { |
325 | yyerror("type mismatch"); |
326 | YYERROR; |
327 | } else { |
328 | $$ = n->c; |
329 | class_inc(n->c); |
330 | } |
331 | } |
332 | | '(' user_class ')' { $$ = $2; } |
333 | ; |
334 | |
335 | /* --- Command class expressions --- */ |
336 | |
337 | command_class : command_class ',' command_class { |
338 | if ($1->type != $3->type) { |
339 | yyerror("type mismatch"); |
340 | class_dec($1); |
341 | class_dec($3); |
342 | YYERROR; |
343 | } else { |
344 | if ($1 == class_all) |
345 | $$ = class_all; |
346 | else |
347 | $$ = class_create($1->type, |
348 | set_union($1->t, $3->t)); |
349 | class_dec($1); |
350 | class_dec($3); |
351 | } |
352 | } |
353 | | command_class '-' command_class { |
354 | if ($1->type != $3->type) { |
355 | yyerror("type mismatch"); |
356 | class_dec($1); |
357 | class_dec($3); |
358 | YYERROR; |
359 | } else { |
360 | $$ = class_create($1->type, |
361 | set_subtract($1->t, $3->t)); |
362 | class_dec($1); |
363 | class_dec($3); |
364 | } |
365 | } |
366 | | command_class '&' command_class { |
367 | if ($1->type != $3->type) { |
368 | yyerror("type mismatch"); |
369 | class_dec($1); |
370 | class_dec($3); |
371 | YYERROR; |
372 | } else { |
373 | if ($1 == class_all) |
374 | $$ = class_all; |
375 | else |
376 | $$ = class_create($1->type, |
377 | set_intersect($1->t, $3->t)); |
378 | class_dec($1); |
379 | class_dec($3); |
380 | } |
381 | } |
382 | | command_class '|' command_class { |
383 | if ($1->type != $3->type) { |
384 | yyerror("type mismatch"); |
385 | class_dec($1); |
386 | class_dec($3); |
387 | YYERROR; |
388 | } else { |
389 | if ($1 == class_all) |
390 | $$ = class_all; |
391 | else |
392 | $$ = class_create($1->type, |
393 | set_union($1->t, $3->t)); |
394 | class_dec($1); |
395 | class_dec($3); |
396 | } |
397 | } |
398 | | STRING { |
399 | sym_table *t = xmalloc(sizeof(*t)); |
400 | sym_createTable(t); |
401 | sym_find(t, $1, -1, sizeof(sym_base), 0); |
402 | $$ = class_create(clType_command, t); |
403 | } |
404 | | WORD { |
405 | name *n = name_find($1, 0, 0); |
406 | if (!n || !n->c) { |
407 | moan("class `%s' not found at line %i", |
408 | $1, lex_line); |
409 | YYERROR; |
410 | } else if (~n->c->type & clType_command) { |
411 | yyerror("type mismatch"); |
412 | YYERROR; |
413 | } else { |
414 | $$ = n->c; |
415 | class_inc(n->c); |
416 | } |
417 | } |
418 | | '(' command_class ')' { $$ = $2; } |
419 | ; |
420 | |
421 | /* --- Host class expressions --- */ |
422 | |
423 | host_class : host_class ',' host_class { |
424 | if ($1->type != $3->type) { |
425 | yyerror("type mismatch"); |
426 | class_dec($1); |
427 | class_dec($3); |
428 | YYERROR; |
429 | } else { |
430 | if ($1 == class_all) |
431 | $$ = class_all; |
432 | else |
433 | $$ = class_create($1->type, |
434 | set_union($1->t, $3->t)); |
435 | class_dec($1); |
436 | class_dec($3); |
437 | } |
438 | } |
439 | | host_class '-' host_class { |
440 | if ($1->type != $3->type) { |
441 | yyerror("type mismatch"); |
442 | class_dec($1); |
443 | class_dec($3); |
444 | YYERROR; |
445 | } else { |
446 | $$ = class_create($1->type, |
447 | set_subtract($1->t, $3->t)); |
448 | class_dec($1); |
449 | class_dec($3); |
450 | } |
451 | } |
452 | | host_class '&' host_class { |
453 | if ($1->type != $3->type) { |
454 | yyerror("type mismatch"); |
455 | class_dec($1); |
456 | class_dec($3); |
457 | YYERROR; |
458 | } else { |
459 | if ($1 == class_all) |
460 | $$ = class_all; |
461 | else |
462 | $$ = class_create($1->type, |
463 | set_intersect($1->t, $3->t)); |
464 | class_dec($1); |
465 | class_dec($3); |
466 | } |
467 | } |
468 | | host_class '|' host_class { |
469 | if ($1->type != $3->type) { |
470 | yyerror("type mismatch"); |
471 | class_dec($1); |
472 | class_dec($3); |
473 | YYERROR; |
474 | } else { |
475 | if ($1 == class_all) |
476 | $$ = class_all; |
477 | else |
478 | $$ = class_create($1->type, |
479 | set_union($1->t, $3->t)); |
480 | class_dec($1); |
481 | class_dec($3); |
482 | } |
483 | } |
484 | | STRING { |
485 | sym_table *t = xmalloc(sizeof(*t)); |
486 | sym_createTable(t); |
487 | sym_find(t, $1, -1, sizeof(sym_base), 0); |
488 | $$ = class_create(clType_host, t); |
489 | } |
490 | | WORD { |
491 | name *n = name_find($1, 0, 0); |
492 | if (!n || !n->c) { |
493 | moan("class `%s' not found at line %i", |
494 | $1, lex_line); |
495 | YYERROR; |
496 | } else if (~n->c->type & clType_host) { |
497 | yyerror("type mismatch"); |
498 | YYERROR; |
499 | } else { |
500 | $$ = n->c; |
501 | class_inc(n->c); |
502 | } |
503 | } |
504 | | '(' host_class ')' { $$ = $2; } |
505 | ; |
506 | |
507 | /*----- That's all, folks -------------------------------------------------*/ |