chiark / gitweb /
3ee5f7d1abb0615af88648afecf9468cf248d932
[become] / src / class.c
1 /* -*-c-*-
2  *
3  * $Id: class.c,v 1.3 1997/08/07 09:49:38 mdw Exp $
4  *
5  * Handling classes of things nicely
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: class.c,v $
32  * Revision 1.3  1997/08/07 09:49:38  mdw
33  * Extensive modifications to handle netgroups.  Also sanitise user and group
34  * names before adding them to the symbol table.
35  *
36  * Revision 1.2  1997/08/04 10:24:21  mdw
37  * Sources placed under CVS control.
38  *
39  * Revision 1.1  1997/07/21  13:47:52  mdw
40  * Initial revision
41  *
42  */
43
44 /*----- Header files ------------------------------------------------------*/
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
63 /* --- Local headers --- */
64
65 #include "become.h"
66 #include "class.h"
67 #include "set.h"
68 #include "sym.h"
69 #include "utils.h"
70
71 /*----- Global variables --------------------------------------------------*/
72
73 static classdef class__all = { clType_all, -1, 0 };
74 classdef *class_all = &class__all;
75
76 /*----- Wildcard matching -------------------------------------------------*/
77
78 /* --- @class__wildMatch@ --- *
79  *
80  * Arguments:   @const char *pat@ = pointer to pattern string
81  *              @const char *p@ = pointer to target string
82  *
83  * Returns:     Zero if no match, nonzero if match.
84  *
85  * Use:         Wildcard-matches the pattern against the target string.
86  */
87
88 static int class__wildMatch(const char *pat, const char *p)
89 {
90   for (;;) {
91     if (*pat == 0 && *p == 0)
92       return (42); /* For sadism's sake */
93     else if (*pat == '*') {
94       while (*pat == '*')
95         pat++;
96       do {
97         if (class__wildMatch(pat, p))
98           return (27); /* Nyahaha */
99         p++;
100       } while (*p);
101       return (0);
102     } else if (*pat == '?' || *pat == *p)
103       p++, pat++;
104     else
105       return (0);
106   }
107 }
108
109 /*----- Main code ---------------------------------------------------------*/
110
111 /* --- @class_create@ --- *
112  *
113  * Arguments:   @unsigned type@ = type of the class to create
114  *              @sym_table *t@ = pointer to symbol table which stores info
115  *
116  * Returns:     Pointer to a @classdef@ which maintains the class's info.
117  *
118  * Use:         Creates a new class definition.  The new definition has one
119  *              reference attached to it (which is the one you get returned).
120  */
121
122 classdef *class_create(unsigned type, sym_table *t)
123 {
124   classdef *c = xmalloc(sizeof(*c));
125   c->type = type;
126   c->ref = 1;
127   c->t = t;
128   return (c);
129 }
130
131 /* --- @class_inc@ --- *
132  *
133  * Arguments:   @classdef *c@ = pointer to a class block
134  *
135  * Returns:     ---
136  *
137  * Use:         Adds a reference to the class definition.
138  */
139
140 void class_inc(classdef *c)
141 {
142   if (c != class_all)
143     c->ref++;
144 }
145
146 /* --- @class_dec@ --- *
147  *
148  * Arguments:   @classdef *c@ = pointer to a class block
149  *
150  * Returns:     ---
151  *
152  * Use:         Removes a reference to a class block.
153  */
154
155 void class_dec(classdef *c)
156 {
157   if (c != class_all && !--c->ref) {
158     sym_destroyTable(c->t);
159     free(c);
160   }
161 }
162
163 /* --- @class_userMatch@ --- *
164  *
165  * Arguments:   @classdef *c@ = pointer to a class block
166  *              @int u@ = uid number to check against
167  *
168  * Returns:     Zero if no match, nonzero if it matched.
169  *
170  * Use:         Looks to see if a user is in a group.
171  */
172
173 int class_userMatch(classdef *c, int u)
174 {
175   if (~c->type & clType_user)
176     return (0);
177   else if (c == class_all) {
178     T( trace(TRACE_CHECK, "check: user %i matched by all", u); )
179     return (1);
180   } else {
181     sym_base *s = sym_find(c->t, (char *)&u, sizeof(u), 0, 0);
182     T( trace(TRACE_CHECK,
183              s ? "check: user %i matched" : "check: user %i not matched",
184              u); )
185     return (s != 0);
186   }
187 }
188
189 /* --- @class_commandMatch@ --- *
190  *
191  * Arguments:   @classdef *c@ = pointer to a class block
192  *              @const char *p@ = pointer to command string to match
193  *
194  * Returns:     Zero for no match, nonzero if it matched.
195  *
196  * Use:         Tries to match a string against the wildcard patterns in the
197  *              given class.  Note that this involves examining all the
198  *              items, so it's not too quick.  Then again, you don't have
199  *              big command classes, do you...?
200  */
201
202 int class_commandMatch(classdef *c, const char *p)
203 {
204   sym_iter i;
205   sym_base *s;
206
207   if (~c->type & clType_command)
208     return (0);
209   else if (c == class_all) {
210     T( trace(TRACE_CHECK, "check: command `%s' matched by all", p); )
211     return (1);
212   } else {
213     for (sym_createIter(&i, c->t); (s = sym_next(&i)) != 0; ) {
214       if (class__wildMatch(s->name, p)) {
215         T( trace(TRACE_CHECK, "check: command `%s' matched by `%s'",
216                  p, s->name); )
217         return (1);
218       }
219     }
220     T( trace(TRACE_CHECK, "check: command `%s' not matched", p); )
221     return (0);
222   }
223 }
224
225 /* --- @class_hostMatch@ --- *
226  *
227  * Arguments:   @classdef *c@ = pointer to class block
228  *              @struct in_addr addr@ = IP address to match
229  *
230  * Returns:     Zero for no match, nonzero if it matched.
231  *
232  * Use:         Tries to match an IP address against the patterns and masks
233  *              in the given class.
234  */
235
236 int class_hostMatch(classdef *c, struct in_addr addr)
237 {
238   sym_iter i;
239   sym_base *s;
240   const char *a;
241   struct hostent *he;
242   char **p;
243
244   if (~c->type & clType_host)
245     return (0);
246   else if (c == class_all) {
247     T( trace(TRACE_CHECK, "check: host %s matched by all",
248              inet_ntoa(addr)); )
249     return (1);
250   } else {
251
252     /* --- Get the dotted-quad and other names for the address --- */
253
254     if ((a = inet_ntoa(addr)) == 0) {
255       T( trace(TRACE_CHECK, "check: couldn't translate address (erk!)"); )
256       return (0);
257     }
258
259     if ((he = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET)) == 0)
260       T( trace(TRACE_CHECK, "check: couldn't resolve hostname for %s", a); )
261
262     /* --- Now search the list for a match --- *
263      *
264      * This is almost infinitely slow, I'm afraid.
265      */
266
267     for (sym_createIter(&i, c->t); (s = sym_next(&i)) != 0; ) {
268
269       /* --- Check the dotted-quad name first --- */
270
271       if (class__wildMatch(s->name, a)) {
272         T( trace(TRACE_CHECK, "check: host address `%s' matched by `%s'",
273                  a, s->name); )
274         return (1);
275       }
276
277       if (he) {
278
279         /* --- Now try the host's main name --- */
280
281         if (class__wildMatch(s->name, he->h_name)) {
282           T( trace(TRACE_CHECK, "check: host name `%s' matched by `%s'",
283                    he->h_name, s->name); )
284           return (1);
285         }
286
287         /* --- Now go through all the names --- */
288
289         for (p = he->h_aliases; *p; p++) {
290           if (class__wildMatch(s->name, *p)) {
291             T( trace(TRACE_CHECK, "check: host alias `%s' matched by `%s'",
292                      *p, s->name); )
293             return (1);
294           }
295         }
296       }
297     }
298
299     T( trace(TRACE_CHECK, "check: couldn't match hostname `%s'",
300              he->h_name); )
301     return (0);
302   }
303 }
304
305 /* --- @class_dump@ --- *
306  *
307  * Arguments:   @classdef *c@ = pointer to a class block
308  *
309  * Returns:     ---
310  *
311  * Use:         Dumps the contents of a class to a stream.
312  */
313
314 void class_dump(classdef *c)
315 {
316   sym_iter i;
317   sym_base *s;
318
319   /* --- Dump the table --- */
320
321   if (c->type != clType_all) {
322     for (sym_createIter(&i, c->t); (s = sym_next(&i)) != 0; ) {
323       switch (c->type) {
324         case clType_user:
325           trace(TRACE_RULE, "    %i", *(int *)s->name);
326           break;
327         case clType_command:
328         case clType_host:
329           trace(TRACE_RULE, "    `%s'", s->name);
330           break;
331       }
332     }
333   }
334   else
335     trace(TRACE_RULE, "    ALL");
336 }
337
338 /*----- That's all, folks -------------------------------------------------*/