908a5930 |
1 | /* -*-c-*- |
2 | * |
b0f66028 |
3 | * $Id: bcquery.c,v 1.5 2003/11/29 23:39:16 mdw Exp $ |
908a5930 |
4 | * |
5 | * Query and dump Become's configuration file |
6 | * |
7 | * (c) 1998 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: bcquery.c,v $ |
b0f66028 |
32 | * Revision 1.5 2003/11/29 23:39:16 mdw |
33 | * Debianization. |
34 | * |
f60a3434 |
35 | * Revision 1.4 2003/10/12 00:14:55 mdw |
36 | * Major overhaul. Now uses DSA signatures rather than the bogus symmetric |
37 | * encrypt-and-hope thing. Integrated with mLib and Catacomb. |
38 | * |
79fae27d |
39 | * Revision 1.3 1999/05/04 16:17:11 mdw |
40 | * Change to header file name for parser. See log for `parse.h' for |
41 | * details. |
42 | * |
43 | * Revision 1.2 1998/06/26 10:32:31 mdw |
7df38e1e |
44 | * Cosmetic change: use sizeof(destination) in memcpy. |
45 | * |
908a5930 |
46 | * Revision 1.1 1998/04/23 13:20:20 mdw |
47 | * Added new program to verify and query Become configuration files. |
48 | * |
49 | */ |
50 | |
51 | /*----- Header files ------------------------------------------------------*/ |
52 | |
53 | /* --- ANSI headers --- */ |
54 | |
55 | #include <ctype.h> |
56 | #include <errno.h> |
57 | #include <limits.h> |
58 | #include <stdio.h> |
59 | #include <stdlib.h> |
60 | #include <string.h> |
61 | #include <time.h> |
62 | |
63 | /* --- Unix headers --- */ |
64 | |
65 | #include <sys/types.h> |
66 | #include <sys/stat.h> |
67 | #include <sys/socket.h> |
68 | #include <sys/utsname.h> |
69 | |
70 | #include <netinet/in.h> |
71 | |
72 | #include <arpa/inet.h> |
73 | |
74 | #include <netdb.h> |
75 | #include <grp.h> |
76 | #include <pwd.h> |
77 | #include <syslog.h> |
78 | #include <unistd.h> |
79 | |
f60a3434 |
80 | /* --- mLib headers --- */ |
81 | |
82 | #include <mLib/alloc.h> |
83 | #include <mLib/mdwopt.h> |
84 | #include <mLib/quis.h> |
85 | #include <mLib/report.h> |
86 | #include <mLib/sym.h> |
87 | |
908a5930 |
88 | /* --- Local headers --- */ |
89 | |
90 | #include "become.h" |
91 | #include "class.h" |
92 | #include "config.h" |
93 | #include "daemon.h" |
94 | #include "lexer.h" |
908a5930 |
95 | #include "name.h" |
96 | #include "netg.h" |
79fae27d |
97 | #include "parse.h" |
908a5930 |
98 | #include "rule.h" |
908a5930 |
99 | #include "userdb.h" |
100 | |
101 | /*----- Type definitions --------------------------------------------------*/ |
102 | |
103 | enum { |
104 | cat_where = 1u, |
105 | cat_from = 2u, |
106 | cat_to = 4u, |
107 | cat_what = 8u, |
108 | cat_and = 16u, |
109 | cat_or = 17u, |
110 | cat_not = 18u |
111 | }; |
112 | |
113 | typedef struct qnode { |
114 | unsigned q_cat; |
115 | union { |
116 | uid_t uid; |
117 | struct in_addr in; |
118 | const char *cmd; |
119 | struct { |
120 | struct qnode *l, *r; |
121 | } q; |
122 | } q; |
123 | #define q_uid q.uid |
124 | #define q_in q.in |
125 | #define q_cmd q.cmd |
126 | #define q_left q.q.l |
127 | #define q_right q.q.r |
128 | #define q_arg q_left |
129 | } qnode; |
130 | |
131 | /*----- Static variables --------------------------------------------------*/ |
132 | |
133 | enum { |
134 | f_dump = 1u, |
135 | f_userdb = 2u, |
136 | f_header = 4u, |
137 | f_match = 8u, |
138 | f_single = 16u, |
139 | f_simple = 32u, |
140 | f_force = 64u, |
141 | f_check = 128u, |
142 | f_nohead = 256u |
143 | }; |
144 | |
145 | static int ac; |
146 | static char **av; |
147 | static int opt; |
148 | static unsigned flags; |
149 | static const char *cf = file_RULES; |
150 | static unsigned outmask = cat_where | cat_from | cat_to | cat_what; |
151 | |
152 | /*----- Low-level options handling ----------------------------------------*/ |
153 | |
154 | /* --- @optname@ --- * |
155 | * |
156 | * Arguments: --- |
157 | * |
158 | * Returns: Pointer to a string describing the current option. |
159 | * |
160 | * Use: Creates a textual description of an option for use in |
161 | * error messages. |
162 | */ |
163 | |
164 | static const char *optname(void) |
165 | { |
166 | static char buf[2]; |
167 | switch (opt) { |
168 | case 'H': return ("-host"); |
169 | case 'F': return ("-from"); |
170 | case 'T': return ("-to"); |
171 | case 'C': return ("-command"); |
172 | case 0: return (optarg); |
173 | case '(': case ')': case '&': case '|': case '!': |
174 | buf[0] = opt; |
175 | buf[1] = 0; |
176 | return (buf); |
177 | case EOF: return ("<eof>"); |
178 | default: return ("<unknown>"); |
179 | } |
180 | } |
181 | |
182 | /* --- @nextopt@ --- * |
183 | * |
184 | * Arguments: --- |
185 | * |
186 | * Returns: Next option id, or @EOF@. |
187 | * |
188 | * Use: Reads the next option. Does a lot of the messy work of |
189 | * options parsing. |
190 | */ |
191 | |
192 | static int nextopt(void) |
193 | { |
194 | const static struct option opts[] = { |
195 | { "help", 0, 0, 'h' }, |
196 | |
197 | { "file", gFlag_argReq, 0, 'f' }, |
198 | { "dump", 0, 0, 'd' }, |
199 | { "check", 0, 0, 'k' }, |
200 | |
201 | { "output", gFlag_argReq, 0, 'o' }, |
202 | { "columns", 0, 0, '|' }, |
203 | { "rows", 0, 0, '-' }, |
204 | { "nohead", 0, 0, 'n' }, |
205 | |
206 | { "host", gFlag_argReq, 0, 'H' }, |
207 | { "from", gFlag_argReq, 0, 'F' }, |
208 | { "to", gFlag_argReq, 0, 'T' }, |
209 | { "command", gFlag_argReq, 0, 'C' }, |
210 | |
211 | { "and", 0, 0, '&' }, |
212 | { "or", 0, 0, '|' }, |
213 | { "not", 0, 0, '!' }, |
214 | |
215 | { 0, 0, 0, 0 } |
216 | }; |
217 | |
218 | again: |
219 | opt = mdwopt(ac, av, "-", opts, 0, 0, gFlag_noShorts); |
220 | |
221 | switch (opt) { |
222 | case 'h': |
223 | printf("" |
224 | "Usage: %s [-help]\n" |
225 | " %s [-output COLS] [-dump] [-file FILE] [EXPR | -check]\n" |
226 | "\n" |
227 | "Reads the `become' configuration file FILE (or " file_RULES " by\n" |
228 | "default) and writes the rules which match the EXPR.\n" |
229 | "\n" |
230 | "EXPR may make use of the following operators: `-host HOST', `-from USER',\n" |
231 | "`-to USER', and `-command CMD'. You may join them together with `-and',\n" |
232 | "`-or' and `-not' operators (which may be spelled `&', `|' and `!' if you\n" |
233 | "prefer), and group subexpressions with parentheses `(' and `)'.\n", |
234 | quis(), quis()); |
235 | exit(0); |
236 | case 'd': |
237 | flags |= f_dump; |
238 | goto again; |
239 | case 'f': |
240 | cf = optarg; |
241 | goto again; |
242 | case '|': |
243 | flags |= f_simple; |
244 | /* Drop through */ |
245 | case '-': |
246 | flags |= f_force; |
247 | goto again; |
248 | case 'k': |
249 | flags |= f_check; |
250 | goto again; |
251 | case 'n': |
252 | flags |= f_nohead; |
253 | goto again; |
254 | case 'o': { |
255 | char *p = optarg; |
256 | enum { m_replace, m_add, m_remove } mode = m_replace; |
257 | unsigned bit; |
258 | |
259 | while (*p) { |
260 | switch (*p) { |
261 | case '+': |
262 | mode = m_add; |
263 | break; |
264 | case '-': |
265 | mode = m_remove; |
266 | break; |
267 | case 'h': |
268 | bit = cat_where; |
269 | goto setbits; |
270 | case 'f': |
271 | bit = cat_from; |
272 | goto setbits; |
273 | case 't': |
274 | bit = cat_to; |
275 | goto setbits; |
276 | case 'c': |
277 | bit = cat_what; |
278 | goto setbits; |
279 | default: |
f60a3434 |
280 | die(1, "unknown column specifier `%c'", *p); |
908a5930 |
281 | break; |
282 | setbits: |
283 | if (mode == m_replace) { |
284 | outmask = 0; |
285 | mode = m_add; |
286 | } |
287 | if (mode == m_add) |
288 | outmask |= bit; |
289 | else if (mode == m_remove) |
290 | outmask &= ~bit; |
291 | else |
f60a3434 |
292 | die(1, "bad mode while setting output mask: %u", mode); |
908a5930 |
293 | break; |
294 | } |
295 | p++; |
296 | } |
297 | goto again; |
298 | } |
299 | case '?': |
f60a3434 |
300 | die(1, "type `%s --help' for usage information", quis()); |
908a5930 |
301 | case 0: |
302 | if (optarg[0] && optarg[1] == 0) switch (optarg[0]) { |
303 | case '(': case ')': |
304 | case '&': case '|': case '!': |
305 | opt = optarg[0]; |
306 | break; |
307 | } |
308 | if (!opt) |
f60a3434 |
309 | die(1, "unexpected text `%s' found", optarg); |
908a5930 |
310 | break; |
311 | } |
312 | |
313 | return (opt); |
314 | } |
315 | |
316 | /*----- Recursive descent query parser ------------------------------------*/ |
317 | |
318 | /* --- @qparse@ --- * |
319 | * |
320 | * Arguments: --- |
321 | * |
322 | * Returns: A pointer to the finished tree. |
323 | * |
324 | * Use: Scans the command line arguments and makes them into a tree. |
325 | */ |
326 | |
327 | static qnode *qparse_expr(void); |
328 | |
329 | static qnode *qparse_atom(void) |
330 | { |
331 | switch (opt) { |
332 | case '(': { |
333 | qnode *q; |
334 | nextopt(); |
335 | q = qparse_expr(); |
336 | if (opt != ')') |
f60a3434 |
337 | die(1, "syntax error: expected `)', found `%s'", optname()); |
908a5930 |
338 | nextopt(); |
339 | return (q); |
340 | } |
341 | case 'H': { |
342 | struct hostent *h; |
343 | qnode *q = xmalloc(sizeof(*q)); |
344 | h = gethostbyname(optarg); |
345 | if (!h) |
f60a3434 |
346 | die(1, "unknown host `%s'", optarg); |
908a5930 |
347 | q->q_cat = cat_where; |
7df38e1e |
348 | memcpy(&q->q_in, h->h_addr, sizeof(q->q_in)); |
908a5930 |
349 | nextopt(); |
350 | return (q); |
351 | } |
352 | case 'F': case 'T': { |
353 | qnode *q = xmalloc(sizeof(*q)); |
354 | q->q_cat = (opt == 'F' ? cat_from : cat_to); |
355 | if (isdigit((unsigned char)optarg[0])) |
356 | q->q_uid = atoi(optarg); |
357 | else { |
358 | struct passwd *pw; |
359 | if (!(flags & f_userdb)) { |
360 | userdb_init(); |
361 | userdb_local(); |
362 | userdb_yp(); |
363 | flags |= f_userdb; |
364 | } |
365 | pw = userdb_userByName(optarg); |
366 | if (!pw) |
f60a3434 |
367 | die(1, "unknown user `%s'", optarg); |
908a5930 |
368 | q->q_uid = pw->pw_uid; |
369 | } |
370 | nextopt(); |
371 | return (q); |
372 | } |
373 | case 'C': { |
374 | qnode *q = xmalloc(sizeof(*q)); |
375 | q->q_cat = cat_what; |
376 | q->q_cmd = optarg; |
377 | nextopt(); |
378 | return (q); |
379 | } |
380 | default: |
f60a3434 |
381 | die(1, "unexpected token: `%s'", optname()); |
908a5930 |
382 | } |
383 | return (0); |
384 | } |
385 | |
386 | static qnode *qparse_factor(void) |
387 | { |
388 | if (opt == '!') { |
389 | qnode *q = xmalloc(sizeof(*q)); |
390 | nextopt(); |
391 | q->q_cat = cat_not; |
392 | q->q_arg = qparse_atom(); |
393 | return (q); |
394 | } else |
395 | return (qparse_atom()); |
396 | } |
397 | |
398 | static qnode *qparse_term(void) |
399 | { |
400 | qnode *top, *q, **qq; |
401 | qq = ⊤ |
402 | |
403 | again: |
404 | q = qparse_factor(); |
405 | switch (opt) { |
406 | case '&': |
407 | nextopt(); |
408 | case 'H': case 'F': case 'T': case 'C': case '!': case '(': |
409 | *qq = xmalloc(sizeof(*q)); |
410 | (*qq)->q_cat = cat_and; |
411 | (*qq)->q_left = q; |
412 | qq = &(*qq)->q_right; |
413 | goto again; |
414 | default: |
415 | *qq = q; |
416 | break; |
417 | } |
418 | return (top); |
419 | } |
420 | |
421 | static qnode *qparse_expr(void) |
422 | { |
423 | qnode *top, *q, **qq; |
424 | qq = ⊤ |
425 | |
426 | again: |
427 | q = qparse_term(); |
428 | switch (opt) { |
429 | case '|': |
430 | nextopt(); |
431 | *qq = xmalloc(sizeof(*q)); |
432 | (*qq)->q_cat = cat_or; |
433 | (*qq)->q_left = q; |
434 | qq = &(*qq)->q_right; |
435 | goto again; |
436 | default: |
437 | *qq = q; |
438 | break; |
439 | } |
440 | return (top); |
441 | } |
442 | |
443 | static qnode *qparse(void) |
444 | { |
445 | qnode *q; |
446 | nextopt(); |
447 | if (opt == EOF) |
448 | return (0); |
449 | q = qparse_expr(); |
450 | if (opt != EOF) |
f60a3434 |
451 | die(1, "syntax error: `%s' unexpected", optname()); |
908a5930 |
452 | return (q); |
453 | } |
454 | |
455 | /* --- @dumptree@ --- * |
456 | * |
457 | * Arguments: @qnode *q@ = pointer to tree to dump |
458 | * @int indent@ = indentation for this subtree |
459 | * |
460 | * Returns: --- |
461 | * |
462 | * Use: Dumps a tree to stdout for debugging purposes. |
463 | */ |
464 | |
465 | static void dumptree(qnode *q, int indent) |
466 | { |
b0f66028 |
467 | if (!q) { |
908a5930 |
468 | printf("<empty> -- magic query which matches everything\n"); |
b0f66028 |
469 | return; |
470 | } |
908a5930 |
471 | |
472 | again: |
473 | printf("%*s", indent * 2, ""); |
474 | indent++; |
475 | switch (q->q_cat) { |
476 | case cat_where: |
477 | printf("host = %s\n", inet_ntoa(q->q_in)); |
478 | break; |
479 | case cat_from: |
480 | printf("from = %u\n", (unsigned)q->q_uid); |
481 | break; |
482 | case cat_to: |
483 | printf("to = %u\n", (unsigned)q->q_uid); |
484 | break; |
485 | case cat_what: |
486 | printf("command = `%s'\n", q->q_cmd); |
487 | break; |
488 | case cat_not: |
489 | printf("not\n"); |
490 | q = q->q_arg; |
491 | goto again; |
492 | case cat_and: |
493 | case cat_or: { |
494 | unsigned cat = q->q_cat; |
495 | printf(cat == cat_and ? "and\n" : "or\n"); |
496 | while (q->q_cat == cat) { |
497 | dumptree(q->q_left, indent); |
498 | q = q->q_right; |
499 | } |
500 | goto again; |
501 | } |
502 | default: |
503 | printf("unknown type %u\n", q->q_cat); |
504 | } |
505 | } |
506 | |
507 | /*----- Recursive query matching ------------------------------------------*/ |
508 | |
509 | /* --- @checkrule@ --- * |
510 | * |
511 | * Arguments: @rule *r@ = pointer to a rule |
512 | * @qnode *q@ = pointer to a query tree |
513 | * |
514 | * Returns: Nonzero if the query matches the rule. |
515 | * |
516 | * Use: Matches rules and queries. |
517 | */ |
518 | |
519 | static int checkrule(rule *r, qnode *q) |
520 | { |
521 | again: |
522 | switch (q->q_cat) { |
523 | |
524 | /* --- Handle the compound query types --- */ |
525 | |
526 | case cat_not: |
527 | return (!checkrule(r, q->q_arg)); |
528 | |
529 | case cat_and: |
530 | if (!checkrule(r, q->q_left)) |
531 | return (0); |
532 | q = q->q_right; |
533 | goto again; |
534 | |
535 | case cat_or: |
536 | if (checkrule(r, q->q_left)) |
537 | return (1); |
538 | q = q->q_right; |
539 | goto again; |
540 | |
541 | /* --- And now the simple query types --- */ |
542 | |
543 | case cat_where: |
544 | return (class_matchHost(r->host, q->q_in)); |
545 | case cat_from: |
546 | return (class_matchUser(r->from, q->q_uid)); |
547 | case cat_to: |
548 | return (class_matchUser(r->to, q->q_uid)); |
549 | case cat_what: |
550 | return (class_matchCommand(r->cmd, q->q_cmd)); |
551 | } |
552 | |
553 | /* --- Anything else is bogus (and a bug) --- */ |
554 | |
f60a3434 |
555 | die(1, "unexpected cat code %u in checkrule", q->q_cat); |
908a5930 |
556 | return (-1); |
557 | } |
558 | |
559 | /*----- Rule output -------------------------------------------------------*/ |
560 | |
561 | /* --- @showrule@ --- * |
562 | * |
563 | * Arguments: @rule *r@ = pointer to a rule block |
564 | * |
565 | * Returns: --- |
566 | * |
567 | * Use: Writes a rule block to the output in a pleasant way. |
568 | */ |
569 | |
570 | static const char *xltuser(uid_t u) |
571 | { |
572 | static char buf[16]; |
573 | struct passwd *pw = userdb_userById(u); |
574 | if (pw) |
575 | return (pw->pw_name); |
576 | sprintf(buf, "%u", (unsigned)u); |
577 | return (buf); |
578 | } |
579 | |
580 | static void classfirstrow(class_node *c, const char *fmt, sym_iter *i, |
581 | unsigned bit, unsigned *imask) |
582 | { |
583 | switch (c->type & clNode_mask) { |
584 | case clNode_any: |
585 | printf(fmt, (c == class_all ? "ALL" : |
586 | c == class_none ? "NONE" : |
587 | "<bug>")); |
588 | break; |
589 | case clNode_immed: |
590 | printf(fmt, (c->type & clType_user) ? xltuser(c->v.u) : c->v.s); |
591 | break; |
592 | case clNode_hash: { |
593 | sym_base *b; |
f60a3434 |
594 | sym_mkiter(i, &c->v.t); |
908a5930 |
595 | b = sym_next(i); |
596 | if (!b) { |
597 | printf(fmt, ""); |
598 | break; |
599 | } else if (c->type & clType_user) |
600 | printf(fmt, xltuser(*(uid_t *)b->name)); |
601 | else |
602 | printf(fmt, b->name); |
603 | *imask |= bit; |
604 | } break; |
605 | default: |
606 | printf(fmt, "<complex>"); |
607 | break; |
608 | } |
609 | } |
610 | |
611 | static void showclass(class_node *c, |
612 | void (*sc)(class_node *c), |
613 | void (*sh)(sym_base *b)) |
614 | { |
615 | const char *op; |
616 | unsigned type; |
617 | |
618 | switch (c->type & clNode_mask) { |
619 | case clNode_any: |
620 | fputs(c == class_all ? "ALL" : |
621 | c == class_none ? "NONE" : "<buggy>", |
622 | stdout); |
623 | break; |
624 | case clNode_immed: |
625 | sc(c); |
626 | break; |
627 | case clNode_hash: { |
628 | sym_iter i; |
629 | sym_base *b; |
f60a3434 |
630 | sym_mkiter(&i, &c->v.t); |
908a5930 |
631 | fputc('(', stdout); |
632 | if ((b = sym_next(&i)) != 0) { |
633 | sh(b); |
634 | while ((b = sym_next(&i)) != 0) { |
635 | fputs(", ", stdout); |
636 | sh(b); |
637 | } |
638 | } |
639 | fputc(')', stdout); |
640 | } break; |
641 | case clNode_union: |
642 | op = " | "; |
643 | goto binop; |
644 | case clNode_diff: |
645 | op = " - "; |
646 | goto binop; |
647 | case clNode_isect: |
648 | op = " & "; |
649 | goto binop; |
650 | default: |
651 | fputs("<unknown node type>", stdout); |
652 | break; |
653 | binop: |
654 | type = c->type & clNode_mask; |
655 | fputc('(', stdout); |
656 | do { |
657 | showclass(c->v.c.l, sc, sh); |
658 | fputs(op, stdout); |
659 | c = c->v.c.r; |
660 | } while ((c->type & clNode_mask) == type); |
661 | showclass(c, sc, sh); |
662 | fputc(')', stdout); |
663 | break; |
664 | } |
665 | } |
666 | |
667 | static void showuseri(class_node *c) { fputs(xltuser(c->v.u), stdout); } |
668 | |
669 | static void showuserh(sym_base *b) |
670 | { |
671 | fputs(xltuser(*(uid_t *)b->name), stdout); |
672 | } |
673 | |
674 | static void showstringi(class_node *c) { fputs(c->v.s, stdout); } |
675 | |
676 | static void showstringh(sym_base *b) { fputs(b->name, stdout); } |
677 | |
678 | static void showrule(rule *r) |
679 | { |
680 | /* --- First up: display of simple classes in columns --- */ |
681 | |
682 | if (flags & f_simple) { |
683 | sym_iter a, b, c, d; |
684 | sym_base *w = 0, *x = 0, *y = 0, *z = 0; |
685 | unsigned imask = 0; |
686 | |
687 | /* --- Print the header line if necessary --- */ |
688 | |
689 | if (!(flags & f_header)) { |
690 | if (!(flags & f_nohead)) { |
691 | if (outmask & cat_from) printf("%-15s ", "FROM"); |
692 | if (outmask & cat_to) printf("%-15s ", "TO"); |
693 | if (outmask & cat_where) printf("%-24s ", "HOST"); |
694 | if (outmask & cat_what) printf("%s", "COMMAND"); |
695 | fputc('\n', stdout); |
696 | fputc('\n', stdout); |
697 | } |
698 | flags |= f_header; |
699 | } else |
700 | fputc('\n', stdout); |
701 | |
702 | /* --- Print out the first row --- */ |
703 | |
704 | if (outmask & cat_from) |
705 | classfirstrow(r->from, "%-15.15s ", &a, cat_from, &imask); |
706 | if (outmask & cat_to) |
707 | classfirstrow(r->to, "%-15.15s ", &b, cat_to, &imask); |
708 | if (outmask & cat_where) |
709 | classfirstrow(r->host, "%-24.24s ", &c, cat_where, &imask); |
710 | if (outmask & cat_what) |
711 | classfirstrow(r->cmd, "%s", &d, cat_what, &imask); |
712 | fputc('\n', stdout); |
713 | |
714 | /* --- And now for the rest --- */ |
715 | |
716 | for (;;) { |
717 | if ((imask & cat_from) && (w = sym_next(&a)) == 0) |
718 | imask &= ~cat_from; |
719 | if ((imask & cat_to) && (x = sym_next(&b)) == 0) |
720 | imask &= ~cat_to; |
721 | if ((imask & cat_where) && (y = sym_next(&c)) == 0) |
722 | imask &= ~cat_where; |
723 | if ((imask & cat_what) && (z = sym_next(&d)) == 0) |
724 | imask &= ~cat_what; |
725 | |
726 | if (!imask) |
727 | break; |
728 | |
729 | if (outmask & cat_from) { |
730 | printf("%-15.15s ", |
731 | !(imask & cat_from) ? "" : xltuser(*(uid_t *)w->name)); |
732 | } |
733 | |
734 | if (outmask & cat_to) { |
735 | printf("%-15.15s ", |
736 | !(imask & cat_to) ? "" : xltuser(*(uid_t *)x->name)); |
737 | } |
738 | |
739 | if (outmask & cat_where) |
740 | printf("%-24.24s ", !(imask & cat_where) ? "" : y->name); |
741 | |
742 | if (outmask & cat_what) |
743 | printf("%s", !(imask & cat_what) ? "" : z->name); |
744 | |
745 | fputc('\n', stdout); |
746 | } |
747 | } |
748 | |
749 | /* --- Otherwise deal with complex cases --- */ |
750 | |
751 | else { |
752 | if (flags & f_header) |
753 | fputc('\n', stdout); |
754 | else |
755 | flags |= f_header; |
756 | if (outmask & cat_from) { |
757 | fputs(" From: ", stdout); |
758 | showclass(r->from, showuseri, showuserh); |
759 | fputc('\n', stdout); |
760 | } |
761 | if (outmask & cat_to) { |
762 | fputs(" To: ", stdout); |
763 | showclass(r->to, showuseri, showuserh); |
764 | fputc('\n', stdout); |
765 | } |
766 | if (outmask & cat_where) { |
767 | fputs(" Hosts: ", stdout); |
768 | showclass(r->host, showstringi, showstringh); |
769 | fputc('\n', stdout); |
770 | } |
771 | if (outmask & cat_what) { |
772 | fputs("Commands: ", stdout); |
773 | showclass(r->cmd, showstringi, showstringh); |
774 | fputc('\n', stdout); |
775 | } |
776 | } |
777 | } |
778 | |
779 | /*----- Dummy functions ---------------------------------------------------*/ |
780 | |
781 | void daemon_usePort(int p) { ; } |
782 | void daemon_readKey(const char *f) { ; } |
783 | |
784 | /*----- Main code ---------------------------------------------------------*/ |
785 | |
786 | /* --- @main@ --- * |
787 | * |
788 | * Arguments: @int argc@ = number of command line arguments |
789 | * @char *argv[]@ = pointer to command line arguments |
790 | * |
791 | * Returns: Zero if all went OK. |
792 | * |
793 | * Use: Verifies and queries the `become' configuration file. |
794 | */ |
795 | |
796 | int main(int argc, char *argv[]) |
797 | { |
798 | qnode *qtree; |
799 | |
800 | /* --- Initialise things --- */ |
801 | |
802 | ego(argv[0]); |
803 | ac = argc; av = argv; |
804 | |
805 | /* --- Read the query tree --- */ |
806 | |
807 | qtree = qparse(); |
808 | |
809 | /* --- Dump the tree if so requested --- */ |
810 | |
811 | if (flags & f_dump) { |
812 | dumptree(qtree, 0); |
813 | return (0); |
814 | } |
815 | |
816 | /* --- Check columns requested --- */ |
817 | |
818 | if (outmask == (outmask & (outmask - 1))) |
819 | flags |= f_single; |
820 | |
821 | /* --- Read the ruleset --- */ |
822 | |
823 | if (!(flags & f_userdb)) { |
824 | userdb_init(); |
825 | userdb_local(); |
826 | userdb_yp(); |
827 | } |
828 | |
829 | netg_init(); |
830 | name_init(); |
831 | rule_init(); |
832 | |
833 | { |
834 | FILE *fp = fopen(cf, "r"); |
835 | int ok; |
836 | |
837 | if (!fp) |
f60a3434 |
838 | die(1, "couldn't open configuration file `%s': %s", cf, strerror(errno)); |
908a5930 |
839 | lexer_scan(fp); |
840 | ok = parse(); |
841 | if (flags & f_check) |
842 | exit(ok); |
843 | } |
844 | |
845 | /* --- Now scan the query --- */ |
846 | |
847 | { |
848 | rule *rl = rule_list(), *r; |
849 | |
850 | /* --- Decide on output format if not already chosen --- */ |
851 | |
852 | if (!(flags & f_force)) { |
853 | r = rl; |
854 | flags |= f_simple; |
855 | while (r) { |
856 | if ((!qtree || checkrule(r, qtree)) && |
857 | ((r->host->type & clNode_mask) >= clNode_binop || |
858 | (r->from->type & clNode_mask) >= clNode_binop || |
859 | (r->to->type & clNode_mask) >= clNode_binop || |
860 | (r->cmd->type & clNode_mask) >= clNode_binop)) { |
861 | flags &= ~f_simple; |
862 | break; |
863 | } |
864 | r = r->next; |
865 | } |
866 | } |
867 | |
868 | /* --- Now just dump the matching items --- */ |
869 | |
870 | r = rl; |
871 | while (r) { |
872 | if (!qtree || checkrule(r, qtree)) { |
873 | flags |= f_match; |
874 | showrule(r); |
875 | } |
876 | r = r->next; |
877 | } |
878 | } |
879 | |
880 | /* --- Done --- */ |
881 | |
882 | if (!(flags & f_match)) |
f60a3434 |
883 | die(1, "no match"); |
908a5930 |
884 | return (0); |
885 | } |
886 | |
887 | /*----- That's all, folks -------------------------------------------------*/ |