c4f2d992 |
1 | /* -*-c-*- |
2 | * |
c758e654 |
3 | * $Id: parser.y,v 1.5 1998/01/12 16:46:22 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 $ |
c758e654 |
32 | * Revision 1.5 1998/01/12 16:46:22 mdw |
33 | * Fix copyright date. |
34 | * |
35 | * Revision 1.4 1997/09/17 10:26:52 mdw |
c327f3bc |
36 | * Use rewritten class handler. Makes the expression parsers considerably |
37 | * simpler. |
38 | * |
f3debbd8 |
39 | * Revision 1.3 1997/09/09 18:17:06 mdw |
40 | * Allow default port to be given as a service name or port number. |
41 | * |
03f996bd |
42 | * Revision 1.2 1997/08/04 10:24:24 mdw |
43 | * Sources placed under CVS control. |
44 | * |
45 | * Revision 1.1 1997/07/21 13:47:45 mdw |
c4f2d992 |
46 | * Initial revision |
47 | * |
48 | */ |
49 | |
50 | /*----- Header files ------------------------------------------------------*/ |
51 | %{ |
52 | |
53 | /* --- ANSI headers --- */ |
54 | |
55 | #include <stdio.h> |
56 | #include <stdlib.h> |
57 | #include <string.h> |
58 | |
59 | /* --- Unix headers --- */ |
60 | |
61 | #include <sys/types.h> |
f3debbd8 |
62 | #include <sys/socket.h> |
63 | |
64 | #include <netinet/in.h> |
c4f2d992 |
65 | |
f3debbd8 |
66 | #include <arpa/inet.h> |
67 | |
68 | #include <netdb.h> |
c4f2d992 |
69 | #include <pwd.h> |
70 | #include <unistd.h> |
71 | |
72 | /* --- Local headers --- */ |
73 | |
74 | #include "class.h" |
75 | #include "daemon.h" |
76 | #include "lexer.h" |
77 | #include "name.h" |
78 | #include "rule.h" |
c4f2d992 |
79 | #include "sym.h" |
80 | #include "userdb.h" |
81 | #include "utils.h" |
82 | |
83 | %} |
84 | /*----- Stack type --------------------------------------------------------*/ |
85 | |
86 | %union { |
87 | long i; |
88 | char *s; |
89 | name *n; |
c327f3bc |
90 | class_node *c; |
c4f2d992 |
91 | } |
92 | |
93 | /*----- Token and rule declarations ---------------------------------------*/ |
94 | |
95 | /* --- Tokens --- */ |
96 | |
97 | %token BADTOKEN |
98 | %token USER |
99 | %token COMMAND |
100 | %token HOST |
101 | %token ALLOW |
102 | %token PORT |
103 | %token KEYFILE |
104 | %token <i> INT |
105 | %token <s> WORD |
106 | %token <s> STRING |
107 | %token ARROW |
108 | |
109 | %left ',' |
110 | %left '-' |
111 | %left '|' |
112 | %left '&' |
113 | |
114 | /* --- Rules --- */ |
115 | |
116 | %type <c> user_class command_class host_class |
117 | %type <c> user_class_opt command_class_opt host_class_opt |
118 | %type <n> name |
119 | |
120 | /*----- Error reporting ---------------------------------------------------*/ |
121 | %{ |
122 | |
123 | #define YYDEBUG 1 |
124 | #define YYERROR_VERBOSE |
125 | |
126 | /* --- @yyprint@ --- * |
127 | * |
128 | * Arguments: @FILE *fp@ = pointer to stream to write on |
129 | * @int type@ = pointer to token type |
130 | * @YYSTYPE v@ = token value |
131 | * |
132 | * Returns: --- |
133 | * |
134 | * Use: Displays the semantic value of a token. |
135 | */ |
136 | |
137 | #define YYPRINT(fp, type, value) yyprint(fp, type, value) |
138 | |
139 | static void yyprint(FILE *fp, int type, YYSTYPE v) |
140 | { |
141 | switch (type) { |
142 | case INT: |
143 | fprintf(fp, " %li", v.i); |
144 | break; |
145 | case WORD: |
146 | case STRING: |
147 | fprintf(fp, " `%s'", v.s); |
148 | break; |
149 | } |
150 | } |
151 | |
152 | /* --- @yyerror@ --- * |
153 | * |
154 | * Arguments: @const char *msg@ = pointer to error message |
155 | * |
156 | * Returns: --- |
157 | * |
158 | * Use: Reports parse errors. |
159 | */ |
160 | |
161 | static void yyerror(const char *msg) |
162 | { |
163 | moan("%s at line %i", msg, lex_line); |
164 | } |
165 | |
166 | %} |
167 | %% |
168 | /*----- The actual grammar ------------------------------------------------*/ |
169 | |
170 | /* --- Simple driver things --- */ |
171 | |
172 | file : /* empty */ |
173 | | file statement |
174 | ; |
175 | |
176 | statement : user_spec |
177 | | command_spec |
178 | | host_spec |
179 | | allow_spec |
180 | | port_spec |
181 | | key_spec |
182 | | error ';' |
183 | ; |
184 | |
185 | /* --- Main statement types --- */ |
186 | |
187 | user_spec : USER name '=' user_class ';' { |
188 | if ($2->c) |
189 | class_dec($2->c); |
190 | $2->c = $4; |
191 | } |
192 | ; |
193 | |
194 | command_spec : COMMAND name '=' command_class ';' { |
195 | if ($2->c) |
196 | class_dec($2->c); |
197 | $2->c = $4; |
198 | } |
199 | ; |
200 | |
201 | host_spec : HOST name '=' host_class ';' { |
202 | if ($2->c) |
203 | class_dec($2->c); |
204 | $2->c = $4; |
205 | } |
206 | ; |
207 | |
f3debbd8 |
208 | port_spec : PORT STRING ';' { |
209 | struct servent *s = getservbyname($2, "udp"); |
210 | if (!s) { |
211 | moan("unknown service `%s' at line %i", |
212 | $2, lex_line); |
213 | YYERROR; |
214 | } |
215 | daemon_usePort(s->s_port); |
216 | } |
217 | | PORT INT ';' { daemon_usePort(htons($2)); } |
c4f2d992 |
218 | ; |
219 | |
220 | key_spec : KEYFILE STRING ';' { daemon_readKey($2); } |
221 | |
222 | /* --- Parsing allow specifications --- */ |
223 | |
224 | allow_spec : ALLOW host_class_opt user_class ARROW |
225 | user_class_opt command_class_opt ';' { |
226 | rule_add($2, $3, $5, $6); |
227 | } |
228 | |
229 | host_class_opt : /* empty */ { $$ = class_all; } |
230 | | '[' host_class ']' { $$ = $2; } |
231 | ; |
232 | |
233 | user_class_opt : /* empty */ { $$ = class_all; } |
234 | | user_class { $$ = $1; } |
235 | ; |
236 | |
237 | command_class_opt : /* empty */ { $$ = class_all; } |
238 | | ':' command_class { $$ = $2; } |
239 | ; |
240 | |
241 | /* --- Names get translated into symbols quickly --- */ |
242 | |
243 | name : WORD { |
244 | unsigned f; |
245 | name *n = name_find($1, 1, &f); |
246 | if (!f) |
247 | n->c = 0; |
248 | $$ = n; |
249 | } |
250 | |
251 | /*----- Various class expression types ------------------------------------* |
252 | * |
253 | * Unfortunately, all these need to handle token types slightly differently |
254 | * and I can't be bothered to remember the current state. |
255 | */ |
256 | |
257 | /* --- User class expressions --- */ |
258 | |
259 | user_class : user_class ',' user_class { |
c327f3bc |
260 | if (($$ = class_union($1, $3)) == 0) { |
c4f2d992 |
261 | yyerror("type mismatch"); |
c4f2d992 |
262 | YYERROR; |
c4f2d992 |
263 | } |
264 | } |
265 | | user_class '-' user_class { |
c327f3bc |
266 | if (($$ = class_diff($1, $3)) == 0) { |
c4f2d992 |
267 | yyerror("type mismatch"); |
c4f2d992 |
268 | YYERROR; |
c4f2d992 |
269 | } |
270 | } |
271 | | user_class '&' user_class { |
c327f3bc |
272 | if (($$ = class_isect($1, $3)) == 0) { |
c4f2d992 |
273 | yyerror("type mismatch"); |
c4f2d992 |
274 | YYERROR; |
c4f2d992 |
275 | } |
276 | } |
277 | | user_class '|' user_class { |
c327f3bc |
278 | if (($$ = class_union($1, $3)) == 0) { |
c4f2d992 |
279 | yyerror("type mismatch"); |
c4f2d992 |
280 | YYERROR; |
c4f2d992 |
281 | } |
282 | } |
c327f3bc |
283 | | INT { $$ = class_fromUser(clType_user, $1); } |
c4f2d992 |
284 | | STRING { |
285 | struct passwd *pw; |
c4f2d992 |
286 | if ((pw = userdb_userByName($1)) == 0) { |
287 | moan("user `%s' not known at line %i", |
288 | $1, lex_line); |
289 | YYERROR; |
c327f3bc |
290 | } else |
291 | $$ = class_fromUser(clType_user, pw->pw_uid); |
c4f2d992 |
292 | } |
293 | | WORD { |
294 | name *n = name_find($1, 0, 0); |
295 | if (!n || !n->c) { |
296 | moan("class `%s' not found at line %i", |
297 | $1, lex_line); |
298 | YYERROR; |
299 | } else if (~n->c->type & clType_user) { |
300 | yyerror("type mismatch"); |
301 | YYERROR; |
302 | } else { |
303 | $$ = n->c; |
304 | class_inc(n->c); |
305 | } |
306 | } |
307 | | '(' user_class ')' { $$ = $2; } |
308 | ; |
309 | |
310 | /* --- Command class expressions --- */ |
311 | |
312 | command_class : command_class ',' command_class { |
c327f3bc |
313 | if (($$ = class_union($1, $3)) == 0) { |
c4f2d992 |
314 | yyerror("type mismatch"); |
c4f2d992 |
315 | YYERROR; |
c4f2d992 |
316 | } |
317 | } |
318 | | command_class '-' command_class { |
c327f3bc |
319 | if (($$ = class_diff($1, $3)) == 0) { |
c4f2d992 |
320 | yyerror("type mismatch"); |
c4f2d992 |
321 | YYERROR; |
c4f2d992 |
322 | } |
323 | } |
324 | | command_class '&' command_class { |
c327f3bc |
325 | if (($$ = class_isect($1, $3)) == 0) { |
c4f2d992 |
326 | yyerror("type mismatch"); |
c4f2d992 |
327 | YYERROR; |
c4f2d992 |
328 | } |
329 | } |
330 | | command_class '|' command_class { |
c327f3bc |
331 | if (($$ = class_union($1, $3)) == 0) { |
c4f2d992 |
332 | yyerror("type mismatch"); |
c4f2d992 |
333 | YYERROR; |
c4f2d992 |
334 | } |
335 | } |
c327f3bc |
336 | | STRING { $$ = class_fromString(clType_command, $1); } |
c4f2d992 |
337 | | WORD { |
338 | name *n = name_find($1, 0, 0); |
339 | if (!n || !n->c) { |
340 | moan("class `%s' not found at line %i", |
341 | $1, lex_line); |
342 | YYERROR; |
343 | } else if (~n->c->type & clType_command) { |
344 | yyerror("type mismatch"); |
345 | YYERROR; |
346 | } else { |
347 | $$ = n->c; |
348 | class_inc(n->c); |
349 | } |
350 | } |
351 | | '(' command_class ')' { $$ = $2; } |
352 | ; |
353 | |
354 | /* --- Host class expressions --- */ |
355 | |
c327f3bc |
356 | host_class : host_class ',' host_class { |
357 | if (($$ = class_union($1, $3)) == 0) { |
c4f2d992 |
358 | yyerror("type mismatch"); |
c4f2d992 |
359 | YYERROR; |
c4f2d992 |
360 | } |
361 | } |
362 | | host_class '-' host_class { |
c327f3bc |
363 | if (($$ = class_diff($1, $3)) == 0) { |
c4f2d992 |
364 | yyerror("type mismatch"); |
c4f2d992 |
365 | YYERROR; |
c4f2d992 |
366 | } |
367 | } |
368 | | host_class '&' host_class { |
c327f3bc |
369 | if (($$ = class_isect($1, $3)) == 0) { |
c4f2d992 |
370 | yyerror("type mismatch"); |
c4f2d992 |
371 | YYERROR; |
c4f2d992 |
372 | } |
373 | } |
374 | | host_class '|' host_class { |
c327f3bc |
375 | if (($$ = class_union($1, $3)) == 0) { |
c4f2d992 |
376 | yyerror("type mismatch"); |
c4f2d992 |
377 | YYERROR; |
c4f2d992 |
378 | } |
379 | } |
c327f3bc |
380 | | STRING { $$ = class_fromString(clType_host, $1); } |
c4f2d992 |
381 | | WORD { |
382 | name *n = name_find($1, 0, 0); |
383 | if (!n || !n->c) { |
384 | moan("class `%s' not found at line %i", |
385 | $1, lex_line); |
386 | YYERROR; |
387 | } else if (~n->c->type & clType_host) { |
388 | yyerror("type mismatch"); |
389 | YYERROR; |
390 | } else { |
391 | $$ = n->c; |
392 | class_inc(n->c); |
393 | } |
394 | } |
395 | | '(' host_class ')' { $$ = $2; } |
396 | ; |
397 | |
398 | /*----- That's all, folks -------------------------------------------------*/ |