(Log entry for previous version is bogus.) Minor changes to host
[become] / src / class.c
1 /* -*-c-*-
2 *
3 * $Id: class.c,v 1.4 1997/08/07 09:56:37 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.4 1997/08/07 09:56:37 mdw
33 * (Log entry for previous version is bogus.) Minor changes to host
34 * checking code.
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 -------------------------------------------------*/