chiark / gitweb /
Major overhaul. Now uses DSA signatures rather than the bogus symmetric
[become] / src / parser.y
CommitLineData
c4f2d992 1/* -*-c-*-
2 *
f60a3434 3 * $Id: parser.y,v 1.8 2003/10/12 00:14:55 mdw Exp $
c4f2d992 4 *
5 * Parser for `become.conf' files
6 *
c758e654 7 * (c) 1998 EBI
c4f2d992 8 */
9
03f996bd 10/*----- Licensing notice --------------------------------------------------*
c4f2d992 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
03f996bd 25 * along with `become'; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
c4f2d992 27 */
28
29/*----- Revision history --------------------------------------------------*
30 *
31 * $Log: parser.y,v $
f60a3434 32 * Revision 1.8 2003/10/12 00:14:55 mdw
33 * Major overhaul. Now uses DSA signatures rather than the bogus symmetric
34 * encrypt-and-hope thing. Integrated with mLib and Catacomb.
35 *
9285878d 36 * Revision 1.7 1999/03/26 15:25:22 mdw
37 * Insert some missing semicolons. Bison didn't seem to care, but other
38 * programs like `yyextract' do, so it's worth fixing.
39 *
082ddb26 40 * Revision 1.6 1998/04/23 13:26:49 mdw
41 * New `parse' interface to configuration file parser; informs caller
42 * whether parsing encountered any errors. Also support no-network
43 * configuration.
44 *
c758e654 45 * Revision 1.5 1998/01/12 16:46:22 mdw
46 * Fix copyright date.
47 *
48 * Revision 1.4 1997/09/17 10:26:52 mdw
c327f3bc 49 * Use rewritten class handler. Makes the expression parsers considerably
50 * simpler.
51 *
f3debbd8 52 * Revision 1.3 1997/09/09 18:17:06 mdw
53 * Allow default port to be given as a service name or port number.
54 *
03f996bd 55 * Revision 1.2 1997/08/04 10:24:24 mdw
56 * Sources placed under CVS control.
57 *
58 * Revision 1.1 1997/07/21 13:47:45 mdw
c4f2d992 59 * Initial revision
60 *
61 */
62
63/*----- Header files ------------------------------------------------------*/
64%{
65
66/* --- ANSI headers --- */
67
68#include <stdio.h>
69#include <stdlib.h>
70#include <string.h>
71
72/* --- Unix headers --- */
73
74#include <sys/types.h>
f3debbd8 75#include <sys/socket.h>
76
77#include <netinet/in.h>
c4f2d992 78
f3debbd8 79#include <arpa/inet.h>
80
81#include <netdb.h>
c4f2d992 82#include <pwd.h>
83#include <unistd.h>
84
f60a3434 85/* --- mLib headers --- */
86
87#include <mLib/report.h>
88#include <mLib/sym.h>
89
c4f2d992 90/* --- Local headers --- */
91
92#include "class.h"
93#include "daemon.h"
94#include "lexer.h"
95#include "name.h"
96#include "rule.h"
c4f2d992 97#include "userdb.h"
c4f2d992 98
99%}
100/*----- Stack type --------------------------------------------------------*/
101
102%union {
103 long i;
104 char *s;
105 name *n;
c327f3bc 106 class_node *c;
c4f2d992 107}
108
109/*----- Token and rule declarations ---------------------------------------*/
110
111/* --- Tokens --- */
112
113%token BADTOKEN
114%token USER
115%token COMMAND
116%token HOST
117%token ALLOW
118%token PORT
119%token KEYFILE
120%token <i> INT
121%token <s> WORD
122%token <s> STRING
123%token ARROW
124
125%left ','
126%left '-'
127%left '|'
128%left '&'
129
130/* --- Rules --- */
131
132%type <c> user_class command_class host_class
133%type <c> user_class_opt command_class_opt host_class_opt
134%type <n> name
135
136/*----- Error reporting ---------------------------------------------------*/
137%{
138
139#define YYDEBUG 1
140#define YYERROR_VERBOSE
141
142/* --- @yyprint@ --- *
143 *
144 * Arguments: @FILE *fp@ = pointer to stream to write on
145 * @int type@ = pointer to token type
146 * @YYSTYPE v@ = token value
147 *
148 * Returns: ---
149 *
150 * Use: Displays the semantic value of a token.
151 */
152
153#define YYPRINT(fp, type, value) yyprint(fp, type, value)
154
155static void yyprint(FILE *fp, int type, YYSTYPE v)
156{
157 switch (type) {
158 case INT:
159 fprintf(fp, " %li", v.i);
160 break;
161 case WORD:
162 case STRING:
163 fprintf(fp, " `%s'", v.s);
164 break;
165 }
166}
167
168/* --- @yyerror@ --- *
169 *
170 * Arguments: @const char *msg@ = pointer to error message
171 *
172 * Returns: ---
173 *
174 * Use: Reports parse errors.
175 */
176
177static void yyerror(const char *msg)
178{
179 moan("%s at line %i", msg, lex_line);
180}
181
182%}
183%%
184/*----- The actual grammar ------------------------------------------------*/
185
186/* --- Simple driver things --- */
187
188file : /* empty */
189 | file statement
190 ;
191
192statement : user_spec
193 | command_spec
194 | host_spec
195 | allow_spec
196 | port_spec
197 | key_spec
198 | error ';'
199 ;
200
201/* --- Main statement types --- */
202
203user_spec : USER name '=' user_class ';' {
204 if ($2->c)
205 class_dec($2->c);
206 $2->c = $4;
207 }
208 ;
209
210command_spec : COMMAND name '=' command_class ';' {
211 if ($2->c)
212 class_dec($2->c);
213 $2->c = $4;
214 }
215 ;
216
217host_spec : HOST name '=' host_class ';' {
218 if ($2->c)
219 class_dec($2->c);
220 $2->c = $4;
221 }
222 ;
223
f3debbd8 224port_spec : PORT STRING ';' {
082ddb26 225#ifndef NONETWORK
f3debbd8 226 struct servent *s = getservbyname($2, "udp");
227 if (!s) {
228 moan("unknown service `%s' at line %i",
229 $2, lex_line);
082ddb26 230 yynerrs++; YYERROR;
f3debbd8 231 }
232 daemon_usePort(s->s_port);
082ddb26 233#else
234 yyerror("`port' command unsupported");
235 yynerrs++; YYERROR;
236#endif
237 }
238 | PORT INT ';' {
239#ifndef NONETWORK
240 daemon_usePort(htons($2));
241#else
242 yyerror("`port' command unsupported");
243 yynerrs++; YYERROR;
244#endif
f3debbd8 245 }
c4f2d992 246 ;
247
082ddb26 248key_spec : KEYFILE STRING ';' {
249#ifndef NONETWORK
250 daemon_readKey($2);
251#else
252 yyerror("`keyfile' command unsupported");
253 yynerrs++; YYERROR;
254#endif
255 }
9285878d 256 ;
c4f2d992 257
258/* --- Parsing allow specifications --- */
259
260allow_spec : ALLOW host_class_opt user_class ARROW
261 user_class_opt command_class_opt ';' {
262 rule_add($2, $3, $5, $6);
263 }
9285878d 264 ;
c4f2d992 265
266host_class_opt : /* empty */ { $$ = class_all; }
267 | '[' host_class ']' { $$ = $2; }
268 ;
269
270user_class_opt : /* empty */ { $$ = class_all; }
271 | user_class { $$ = $1; }
272 ;
273
274command_class_opt : /* empty */ { $$ = class_all; }
275 | ':' command_class { $$ = $2; }
276 ;
277
278/* --- Names get translated into symbols quickly --- */
279
280name : WORD {
281 unsigned f;
282 name *n = name_find($1, 1, &f);
283 if (!f)
284 n->c = 0;
285 $$ = n;
286 }
9285878d 287 ;
c4f2d992 288
289/*----- Various class expression types ------------------------------------*
290 *
291 * Unfortunately, all these need to handle token types slightly differently
292 * and I can't be bothered to remember the current state.
293 */
294
295/* --- User class expressions --- */
296
297user_class : user_class ',' user_class {
c327f3bc 298 if (($$ = class_union($1, $3)) == 0) {
c4f2d992 299 yyerror("type mismatch");
082ddb26 300 yynerrs++; YYERROR;
c4f2d992 301 }
302 }
303 | user_class '-' user_class {
c327f3bc 304 if (($$ = class_diff($1, $3)) == 0) {
c4f2d992 305 yyerror("type mismatch");
082ddb26 306 yynerrs++; YYERROR;
c4f2d992 307 }
308 }
309 | user_class '&' user_class {
c327f3bc 310 if (($$ = class_isect($1, $3)) == 0) {
c4f2d992 311 yyerror("type mismatch");
082ddb26 312 yynerrs++; YYERROR;
c4f2d992 313 }
314 }
315 | user_class '|' user_class {
c327f3bc 316 if (($$ = class_union($1, $3)) == 0) {
c4f2d992 317 yyerror("type mismatch");
082ddb26 318 yynerrs++; YYERROR;
c4f2d992 319 }
320 }
c327f3bc 321 | INT { $$ = class_fromUser(clType_user, $1); }
c4f2d992 322 | STRING {
323 struct passwd *pw;
c4f2d992 324 if ((pw = userdb_userByName($1)) == 0) {
325 moan("user `%s' not known at line %i",
326 $1, lex_line);
082ddb26 327 yynerrs++; YYERROR;
c327f3bc 328 } else
329 $$ = class_fromUser(clType_user, pw->pw_uid);
c4f2d992 330 }
331 | WORD {
332 name *n = name_find($1, 0, 0);
333 if (!n || !n->c) {
334 moan("class `%s' not found at line %i",
335 $1, lex_line);
082ddb26 336 yynerrs++; YYERROR;
c4f2d992 337 } else if (~n->c->type & clType_user) {
082ddb26 338 yynerrs++; yyerror("type mismatch");
339 yynerrs++; YYERROR;
c4f2d992 340 } else {
341 $$ = n->c;
342 class_inc(n->c);
343 }
344 }
345 | '(' user_class ')' { $$ = $2; }
346 ;
347
348/* --- Command class expressions --- */
349
350command_class : command_class ',' command_class {
c327f3bc 351 if (($$ = class_union($1, $3)) == 0) {
c4f2d992 352 yyerror("type mismatch");
082ddb26 353 yynerrs++; YYERROR;
c4f2d992 354 }
355 }
356 | command_class '-' command_class {
c327f3bc 357 if (($$ = class_diff($1, $3)) == 0) {
c4f2d992 358 yyerror("type mismatch");
082ddb26 359 yynerrs++; YYERROR;
c4f2d992 360 }
361 }
362 | command_class '&' command_class {
c327f3bc 363 if (($$ = class_isect($1, $3)) == 0) {
c4f2d992 364 yyerror("type mismatch");
082ddb26 365 yynerrs++; YYERROR;
c4f2d992 366 }
367 }
368 | command_class '|' command_class {
c327f3bc 369 if (($$ = class_union($1, $3)) == 0) {
c4f2d992 370 yyerror("type mismatch");
082ddb26 371 yynerrs++; YYERROR;
c4f2d992 372 }
373 }
c327f3bc 374 | STRING { $$ = class_fromString(clType_command, $1); }
c4f2d992 375 | WORD {
376 name *n = name_find($1, 0, 0);
377 if (!n || !n->c) {
378 moan("class `%s' not found at line %i",
379 $1, lex_line);
082ddb26 380 yynerrs++; YYERROR;
c4f2d992 381 } else if (~n->c->type & clType_command) {
382 yyerror("type mismatch");
082ddb26 383 yynerrs++; YYERROR;
c4f2d992 384 } else {
385 $$ = n->c;
386 class_inc(n->c);
387 }
388 }
389 | '(' command_class ')' { $$ = $2; }
390 ;
391
392/* --- Host class expressions --- */
393
c327f3bc 394host_class : host_class ',' host_class {
395 if (($$ = class_union($1, $3)) == 0) {
c4f2d992 396 yyerror("type mismatch");
082ddb26 397 yynerrs++; YYERROR;
c4f2d992 398 }
399 }
400 | host_class '-' host_class {
c327f3bc 401 if (($$ = class_diff($1, $3)) == 0) {
c4f2d992 402 yyerror("type mismatch");
082ddb26 403 yynerrs++; YYERROR;
c4f2d992 404 }
405 }
406 | host_class '&' host_class {
c327f3bc 407 if (($$ = class_isect($1, $3)) == 0) {
c4f2d992 408 yyerror("type mismatch");
082ddb26 409 yynerrs++; YYERROR;
c4f2d992 410 }
411 }
412 | host_class '|' host_class {
c327f3bc 413 if (($$ = class_union($1, $3)) == 0) {
c4f2d992 414 yyerror("type mismatch");
082ddb26 415 yynerrs++; YYERROR;
c4f2d992 416 }
417 }
c327f3bc 418 | STRING { $$ = class_fromString(clType_host, $1); }
c4f2d992 419 | WORD {
420 name *n = name_find($1, 0, 0);
421 if (!n || !n->c) {
422 moan("class `%s' not found at line %i",
423 $1, lex_line);
082ddb26 424 yynerrs++; YYERROR;
c4f2d992 425 } else if (~n->c->type & clType_host) {
426 yyerror("type mismatch");
082ddb26 427 yynerrs++; YYERROR;
c4f2d992 428 } else {
429 $$ = n->c;
430 class_inc(n->c);
431 }
432 }
433 | '(' host_class ')' { $$ = $2; }
434 ;
435
082ddb26 436/*----- Helper functions --------------------------------------------------*/
437%%
438/* --- @parse@ --- *
439 *
440 * Arguments: ---
441 *
442 * Returns: Zero if it worked, nonzero if it didn't.
443 *
444 * Use: Parses configuration files.
445 */
446
447int parse(void)
448{
449 yynerrs = 0;
450 return (yyparse() || yynerrs);
451}
452
c4f2d992 453/*----- That's all, folks -------------------------------------------------*/