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