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