ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/conf/access.c
Revision: 729
Committed: Mon Jul 17 12:52:05 2006 UTC (19 years, 1 month ago) by adx
Content type: text/x-csrc
File size: 9221 byte(s)
Log Message:
+ implemented auth{}

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * access.c: Common code for user@host access control blocks.
4 *
5 * Copyright (C) 2006 by the Hybrid Development Team.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 */
24
25 #include "stdinc.h"
26 #include "conf/conf.h"
27
28 struct AccessConf *atable[ATABLE_SIZE] = {0};
29 struct Callback *cb_expire_confs = NULL;
30
31 static ACB_FREE_HANDLER *acb_types[MAX_ACB_TYPES] = {0};
32 static dlink_node *hreset;
33
34 /*
35 * hash_ipv4()
36 *
37 * Hash algorithm for IPv4.
38 *
39 * inputs: the IP address
40 * output: hash value
41 */
42 static unsigned int
43 hash_ipv4(const struct irc_ssaddr *addr, int bits)
44 {
45 if (bits != 0)
46 {
47 const struct sockaddr_in *v4 = (const struct sockaddr_in *) addr;
48 unsigned int av = ntohl(v4->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
49
50 return (av ^ (av >> 12) ^ (av >> 24)) % ATABLE_SIZE;
51 }
52
53 return 0;
54 }
55
56 /*
57 * hash_ipv6()
58 *
59 * Hash algorithm for IPv6.
60 *
61 * inputs: the IP address
62 * output: hash value
63 */
64 #ifdef IPV6
65 static unsigned int
66 hash_ipv6(const struct irc_ssaddr *addr, int bits)
67 {
68 const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *) addr;
69 unsigned int av = 0, n;
70
71 for (n = 0; n < 16; n++)
72 if (bits >= 8)
73 {
74 av ^= v6->sin6_addr.s6_addr[n];
75 bits -= 8;
76 }
77 else
78 {
79 if (bits > 0)
80 av ^= v6->sin6_addr.s6_addr[n] & ~((1 << (8 - bits)) - 1);
81 break;
82 }
83
84 return av % ATABLE_SIZE;
85 }
86 #endif
87
88 /*
89 * hash_text()
90 *
91 * Hash algorithm for DNS names.
92 *
93 * inputs: the start of text to hash
94 * output: hash value
95 */
96 static unsigned int
97 hash_text(const char *p)
98 {
99 unsigned int av = 0;
100
101 for (; *p; p++)
102 av = (av << 4) - (av + ToLower(*p));
103
104 return av % ATABLE_SIZE;
105 }
106
107 /*
108 * hash_hostmask()
109 *
110 * Calculates the hash value for a given hostmask.
111 *
112 * inputs:
113 * p - the hostname to hash
114 * addr - where to store mask info
115 * output: hash value
116 */
117 static unsigned int
118 hash_hostmask(const char *p, struct irc_ssaddr *addr)
119 {
120 int bits;
121 unsigned int hv;
122 const char *seg;
123
124 switch (parse_netmask(p, addr, &bits))
125 {
126 case HM_IPV4:
127 hv = hash_ipv4(addr, bits - bits % 8);
128 break;
129 #ifdef IPV6
130 case HM_IPV6:
131 hv = hash_ipv6(addr, bits - bits % 16);
132 break;
133 #endif
134 default:
135 //
136 // Choose the longest domain substring which contains no wildcards.
137 // This way hash value will be as precise as possible.
138 //
139 for (seg = p; *p; p++)
140 if (*p == '.' && !seg)
141 seg = p + 1;
142 else if (IsMWildChar(*p))
143 seg = NULL;
144
145 hv = seg ? hash_text(seg) : 0;
146 }
147
148 addr->ss_port = (in_port_t) bits;
149
150 return hv;
151 }
152
153 /*
154 * add_access_conf()
155 *
156 * Adds an AccessConf entry to the hash table.
157 *
158 * inputs: pointer to AccessConf struct
159 * output: none
160 */
161 void
162 add_access_conf(struct AccessConf *conf)
163 {
164 unsigned int hv = hash_hostmask(conf->host, &conf->ip);
165 static uint64_t curprec = ~0;
166
167 conf->precedence = curprec--;
168 conf->hnext = atable[hv];
169 atable[hv] = conf;
170 }
171
172 /*
173 * destroy_access_conf()
174 *
175 * Deletes an AccessConf entry from the hash table and frees its memory.
176 *
177 * inputs: pointer to AccessConf struct
178 * output: none
179 */
180 void
181 destroy_access_conf(struct AccessConf *conf)
182 {
183 struct irc_ssaddr addr;
184 unsigned int hv = hash_hostmask(conf->host, &addr);
185 struct AccessConf *prev;
186
187 if (conf == atable[hv])
188 atable[hv] = conf->hnext;
189 else
190 {
191 for (prev = atable[hv]; prev->hnext != conf; prev = prev->hnext)
192 ; // let it core if not found
193 prev->hnext = conf->hnext;
194 }
195
196 acb_types[conf->type](conf);
197 }
198
199 /*
200 * acb_generic_free()
201 *
202 * Generic free procedure for ACB's.
203 *
204 * inputs: pointer to AccessConf struct
205 * output: none
206 */
207 void
208 acb_generic_free(struct AccessConf *conf)
209 {
210 MyFree(conf->user);
211 MyFree(conf->host);
212 MyFree(conf);
213 }
214
215 /*
216 * enum_access_confs()
217 *
218 * Enumerates all AccessConfs. Calls the supplied routine on each one,
219 * if 1 is returned then this one is deleted and freed.
220 * Any number of AccessConfs can be deleted by this function.
221 *
222 * inputs: pointer to checking routine
223 * output: none
224 */
225 void
226 enum_access_confs(ACB_EXAMINE_HANDLER *examine, void *param)
227 {
228 unsigned int hv;
229 struct AccessConf *prev, *conf;
230
231 for (hv = 0; hv < ATABLE_SIZE; hv++)
232 for (prev = NULL, conf = atable[hv]; conf != NULL;
233 conf = (prev ? prev->hnext : atable[hv]))
234 {
235 if (examine(conf, param))
236 {
237 if (prev != NULL)
238 prev->hnext = conf->hnext;
239 else
240 atable[hv] = conf->hnext;
241
242 acb_types[conf->type](conf);
243 }
244 else
245 prev = conf;
246 }
247 }
248
249 static int is_acb_permanent(struct AccessConf *conf, void *unused)
250 {
251 return !conf->expires;
252 }
253
254 static int is_acb_expired(struct AccessConf *conf, void *unused)
255 {
256 return conf->expires && conf->expires <= CurrentTime;
257 }
258
259 static int is_acb_orphaned(struct AccessConf *conf, void *unused)
260 {
261 return !acb_types[conf->type];
262 }
263
264 /*
265 * register_acb_type()
266 *
267 * Allocates a unique value for AccessConf.type field to be used by modules.
268 *
269 * inputs: pointer to routine which frees a conf entry of this type
270 * output: requested value
271 */
272 int
273 register_acb_type(void *fh)
274 {
275 int i;
276
277 for (i = 0; i < MAX_ACB_TYPES; i++)
278 if (acb_types[i] == NULL)
279 {
280 acb_types[i] = (ACB_FREE_HANDLER *) fh;
281 return i;
282 }
283
284 return -1;
285 }
286
287 /*
288 * unregister_acb_type()
289 *
290 * Deallocates an AccessConf.type specifier.
291 *
292 * inputs: type value
293 * output: none
294 */
295 void
296 unregister_acb_type(int id)
297 {
298 acb_types[id] = NULL;
299 enum_access_confs(is_acb_orphaned, NULL);
300 }
301
302 /*
303 * reset_access()
304 *
305 * Deletes all non-expiring ACB's before a rehash.
306 *
307 * inputs: none
308 * output: none
309 */
310 static void *
311 reset_access(va_list args)
312 {
313 enum_access_confs(is_acb_permanent, NULL);
314 return pass_callback(hreset);
315 }
316
317 /*
318 * find_access_conf()
319 *
320 * Looks for an access conf matching given criteria.
321 *
322 * inputs:
323 * type - only check confs of this type
324 * user - if non-NULL, limit to confs matching given username
325 * host - limit to confs matching given hostname...
326 * ip - ...or IP address (either host or ip must be non-NULL)
327 * func - function which verifies additional criteria, can be NULL
328 * output: pointer to struct AccessConf or NULL if not found
329 */
330 struct AccessConf *
331 find_access_conf(int type, const char *user, const char *host,
332 const struct irc_ssaddr *ip, ACB_EXAMINE_HANDLER *func,
333 void *param)
334 {
335 struct AccessConf *conf, *best = NULL;
336 int bits;
337
338 if (ip != NULL)
339 if (ip->ss.sin_family == AF_INET)
340 for (bits = 32; bits >= 0; bits -= 8)
341 for (conf = atable[hash_ipv4(ip, bits)]; conf; conf = conf->hnext)
342 if ((best == NULL || conf->precedence > best->precedence) &&
343 conf->type == type && match_ipv4(ip, &conf->ip, conf->ip.ss_port)
344 && (EmptyString(user) || match(conf->user, user)) &&
345 (!func || func(conf, param)))
346 best = conf;
347 #ifdef IPV6
348 else if (ip->ss.sin_family == AF_INET6)
349 for (bits = 128; bits >= 0; bits -= 16)
350 for (conf = atable[hash_ipv6(ip, bits)]; conf; conf = conf->hnext)
351 if ((best == NULL || conf->precedence > best->precedence) &&
352 conf->type == type && match_ipv6(ip, &conf->ip, conf->ip.ss_port)
353 && (EmptyString(user) || match(conf->user, user)) &&
354 (!func || func(conf, param)))
355 best = conf;
356 #endif
357
358 if (host != NULL)
359 while (1)
360 {
361 for (conf = atable[hash_text(host)]; conf; conf = conf->hnext)
362 if ((best == NULL || conf->precedence > best->precedence) &&
363 conf->type == type && match(conf->host, host) &&
364 (EmptyString(user) || match(conf->user, user)) &&
365 (!func || func(conf, param)))
366 best = conf;
367
368 if (*host)
369 do {
370 if (*host++ == '.')
371 break;
372 }
373 while (*host);
374 else
375 break;
376 }
377
378 return best;
379 }
380
381 /*
382 * expire_confs()
383 *
384 * Called periodically to remove expired conf entries.
385 *
386 * inputs: none
387 * output: none
388 */
389 static void
390 expire_confs(void *unused)
391 {
392 enum_access_confs(is_acb_expired, NULL);
393 execute_callback(cb_expire_confs);
394 }
395
396 /*
397 * init_access()
398 *
399 * Initializes ACB's support.
400 *
401 * inputs: none
402 * output: none
403 */
404 void
405 init_access(void)
406 {
407 hreset = install_hook(reset_conf, reset_access);
408
409 cb_expire_confs = register_callback(NULL, NULL);
410 eventAddIsh("expire_confs", expire_confs, NULL, EXPIRE_FREQUENCY);
411 }

Properties

Name Value
svn:eol-style native
svn:keywords "Id Revision"