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