ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/conf/glines.c
Revision: 749
Committed: Tue Jul 25 19:45:47 2006 UTC (20 years ago) by adx
Content type: text/x-csrc
File size: 12261 byte(s)
Log Message:
+ make everything compile, but not yet link

File Contents

# User Rev Content
1 adx 735 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * glines.c: Defines the glines{} block of ircd.conf.
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 adx 743 #include "client.h"
28 adx 749 #include "numeric.h"
29     #include "send.h"
30     #include "s_serv.h"
31 adx 735
32     int enable_glines = NO;
33     time_t gline_duration;
34     int gline_logging;
35 adx 743 int acb_type_gline;
36 adx 749 dlink_list pending_glines = {0};
37 adx 735
38 adx 743 static dlink_node *hreset, *hbanned;
39 adx 735 static char *tmpdeny_server = NULL;
40     static dlink_list tmpdeny_masks = {0};
41     static dlink_list gdeny_confs = {0};
42    
43     /*
44     * reset_glines()
45     *
46     * Frees all gline deny entries before a rehash.
47     *
48     * inputs: none
49     * output: none
50     */
51     static void *
52     reset_glines(va_list args)
53     {
54     while (gdeny_confs.head != NULL)
55     {
56     struct GlineDenyConf *conf = gdeny_confs.head->data;
57    
58     dlinkDelete(&conf->node, &gdeny_confs);
59    
60     MyFree(conf->server);
61     MyFree(conf->user);
62     MyFree(conf->host);
63     MyFree(conf);
64     }
65    
66 adx 741 gline_duration = 12*3600;
67    
68 adx 735 return pass_callback(hreset);
69     }
70    
71     /*
72     * clear_temp()
73     *
74     * Clears temporary storage after parsing a gline deny entry.
75     *
76     * inputs: none
77     * output: none
78     */
79     static void
80     clear_temp(void)
81     {
82     MyFree(tmpdeny_server);
83     tmpdeny_server = NULL;
84    
85     while (tmpdeny_masks.head)
86     {
87     struct split_nuh_item *uh = tmpdeny_masks.head->data;
88    
89     dlinkDelete(&uh->node, &tmpdeny_masks);
90    
91     MyFree(uh->userptr);
92     MyFree(uh->hostptr);
93     MyFree(uh);
94     }
95     }
96    
97     /*
98     * parse_user()
99     *
100     * Parses a "user=" field.
101     *
102     * inputs: user@host mask
103     * output: none
104     */
105     static void
106     parse_user(void *value, void *unused)
107     {
108     char *str = value;
109     char userbuf[USERLEN + 1];
110     char hostbuf[HOSTLEN + 1];
111     struct split_nuh_item nuh, *cuh;
112    
113     nuh.nuhmask = str;
114     nuh.nickptr = NULL;
115     nuh.userptr = userbuf;
116     nuh.hostptr = hostbuf;
117    
118     nuh.nicksize = 0;
119     nuh.usersize = sizeof(userbuf);
120     nuh.hostsize = sizeof(hostbuf);
121    
122     split_nuh(&nuh);
123    
124     cuh = MyMalloc(sizeof(*cuh));
125     DupString(cuh->userptr, nuh.userptr);
126     DupString(cuh->hostptr, nuh.hostptr);
127    
128     dlinkAddTail(cuh, &cuh->node, &tmpdeny_masks);
129     }
130    
131     /*
132     * do_parse_action()
133     *
134     * Parses a reject/block list.
135     *
136     * inputs:
137     * list - points to a string dlink list
138     * where - where to store the resulting flags
139     * output: none
140     */
141     static void
142     do_parse_action(void *list, void *where)
143     {
144     int flags = 0;
145     dlink_node *ptr;
146    
147     DLINK_FOREACH(ptr, ((dlink_list *) list)->head)
148     if (!irccmp(ptr->data, "reject"))
149     flags |= GDENY_REJECT;
150     else if (!irccmp(ptr->data, "block"))
151     flags |= GDENY_BLOCK;
152     else
153     flags |= GDENY_ERROR;
154    
155     if ((flags & GDENY_ERROR))
156     parse_error("Invalid gline action encountered, check your syntax");
157    
158     *(int *) where = flags;
159     }
160    
161     /*
162     * parse_action()
163     *
164     * Parses an "action=" field, eventually adding a gline exempt.
165     *
166     * inputs: pointer to a string dlink list
167     * output: none
168     */
169     static void
170     parse_action(void *list, void *unused)
171     {
172     int action, bits;
173     dlink_node *ptr;
174     struct split_nuh_item *uh;
175     struct GlineDenyConf *conf;
176    
177     do_parse_action(list, &action);
178    
179     if (!(action & GDENY_ERROR))
180     {
181     if (dlink_list_length(&tmpdeny_masks) == 0)
182     {
183     uh = MyMalloc(sizeof(*uh));
184     DupString(uh->userptr, "*");
185     DupString(uh->hostptr, "*");
186     dlinkAdd(uh, &uh->node, &tmpdeny_masks);
187     }
188    
189     DLINK_FOREACH(ptr, tmpdeny_masks.head)
190     {
191     conf = MyMalloc(sizeof(*conf));
192     DupString(conf->server, tmpdeny_server ? tmpdeny_server : "*");
193    
194     uh = ptr->data;
195     conf->user = uh->userptr;
196     conf->host = uh->hostptr;
197     uh->userptr = uh->hostptr = NULL;
198    
199     if (parse_netmask(conf->host, &conf->ip, &bits) != HM_HOST)
200     conf->ip.ss_port = bits;
201     dlinkAddTail(conf, &conf->node, &gdeny_confs);
202     }
203     }
204    
205     clear_temp();
206     }
207    
208     /*
209     * is_gline_allowed()
210     *
211     * Checks if there is a gline deny entry against a proposed gline.
212     *
213     * inputs:
214     * server - server feeding the gline to us
215     * user - username of the oper issuing the gline
216     * host - hostname of the oper
217 adx 749 * addr - IP address of the oper
218 adx 735 * output: GDENY_* flags (or 0 if no restrictions)
219     */
220     int
221     is_gline_allowed(const char *server, const char *user, const char *host,
222 adx 749 const char *addr)
223 adx 735 {
224     dlink_node *ptr;
225     struct GlineDenyConf *conf;
226 adx 749 struct irc_ssaddr ip;
227     struct addrinfo hints = {0}, *res;
228 adx 735
229 adx 749 ip.ss.sin_family = AF_UNSPEC;
230     if (EmptyString(addr))
231     addr = host;
232    
233     hints.ai_family = AF_UNSPEC;
234     hints.ai_socktype = SOCK_STREAM;
235     hints.ai_flags = AI_NUMERICHOST;
236    
237     if (!irc_getaddrinfo(addr, NULL, &hints, &res))
238     {
239     memcpy(&ip, res->ai_addr, res->ai_addrlen);
240     ip.ss.sin_family = res->ai_family;
241     ip.ss_len = res->ai_addrlen;
242     irc_freeaddrinfo(res);
243     }
244    
245 adx 735 DLINK_FOREACH(ptr, gdeny_confs.head)
246     {
247     conf = ptr->data;
248     if (!match(user, conf->user) || !match(server, conf->server))
249     continue;
250    
251 adx 749 if (ip.ss.sin_family != AF_UNSPEC &&
252     conf->ip.ss.sin_family != AF_UNSPEC && (
253 adx 735 #ifdef IPV6
254     (conf->ip.ss.sin_family == AF_INET6) ? match_ipv6 :
255     #endif
256 adx 749 match_ipv4)(&ip, &conf->ip, conf->ip.ss_port))
257 adx 735 return conf->action;
258     if (match(conf->host, host))
259     return conf->action;
260     }
261    
262     return 0;
263     }
264    
265     /*
266     * free_gline()
267     *
268     * Frees a GlineConf entry.
269     *
270     * inputs: pointer to the conf
271     * output: none
272     */
273     static void
274     free_gline(struct GlineConf *conf)
275     {
276     MyFree(conf->reason);
277     acb_generic_free(&conf->access);
278     }
279    
280     /*
281     * place_gline()
282     *
283     * Applies a new G-line locally, without checking any privileges.
284     *
285     * inputs:
286     * user - username mask
287     * host - hostname mask
288     * reason - gline reason
289     * output: pointer to the new conf item
290     */
291     struct GlineConf *
292     place_gline(const char *user, const char *host, const char *reason)
293     {
294     struct GlineConf *conf = MyMalloc(sizeof(struct GlineConf));
295    
296     conf->access.type = acb_type_gline;
297     DupString(conf->access.user, user);
298     DupString(conf->access.host, host);
299     conf->access.expires = CurrentTime + gline_duration;
300     DupString(conf->reason, reason);
301    
302     add_access_conf(&conf->access);
303     return conf;
304     }
305    
306     /*
307     * find_gline()
308     *
309     * Looks for a G-line entry for a given user@host/ip.
310     *
311     * inputs:
312     * user - username part, can be NULL
313     * host - hostname part, can be NULL
314     * ip - IP address, can be NULL
315     * output: pointer to a gline conf, if any
316     */
317     struct GlineConf *
318     find_gline(const char *user, const char *host, const struct irc_ssaddr *ip)
319     {
320 adx 749 return (struct GlineConf *) find_access_conf(acb_type_gline, user, host, ip,
321     NULL, NULL);
322 adx 735 }
323    
324     /*
325 adx 743 * is_client_glined()
326     *
327     * Hook function for is_client_banned.
328     *
329     * inputs:
330     * client - local client to check
331     * type - we set it to ban type if there's a match
332     * reason - we set it to ban reason (if any)
333     * output: not NULL if they're banned
334     */
335     static void *
336     is_client_glined(va_list args)
337     {
338     struct Client *client = va_arg(args, struct Client *);
339     char **type = va_arg(args, char **);
340     char **reason = va_arg(args, char **);
341     struct GlineConf *conf = (IsExemptGline(client) || IsExemptKline(client)) ?
342     NULL : find_gline(client->username, client->host, &client->localClient->ip);
343    
344     if (conf)
345     {
346     *type = "G-line";
347     *reason = conf->reason;
348     return conf;
349     }
350    
351     return pass_callback(hbanned, client, type, reason);
352     }
353    
354     /*
355 adx 749 * report_glines()
356     *
357     * Sends a /stats G reply to the given client.
358     *
359     * inputs: client pointer
360     * output: none
361     */
362     static int
363     do_report_glines(struct GlineConf *conf, struct Client *source_p)
364     {
365     if (conf->access.type == acb_type_gline)
366     sendto_one(source_p, form_str(RPL_STATSKLINE),
367     ID_or_name(&me, source_p->from),
368     ID_or_name(source_p, source_p->from), "G",
369     conf->access.host, conf->access.user,
370     conf->reason ? conf->reason : "No reason", "");
371     return NO;
372     }
373    
374     void
375     report_glines(struct Client *to)
376     {
377     if (enable_glines)
378     enum_access_confs((ACB_EXAMINE_HANDLER *) do_report_glines, to);
379     else
380     sendto_one(to, ":%s NOTICE %s :This server does not support G-lines",
381     ID_or_name(&me, to->from), ID_or_name(to, to->from));
382     }
383    
384     void
385     report_pending_glines(struct Client *to)
386     {
387     if (enable_glines)
388     {
389     #ifdef GLINE_VOTING
390     dlink_node *ptr;
391    
392     if (dlink_list_length(&pending_glines) > 0)
393     sendto_one(to, ":%s NOTICE %s :Pending G-lines",
394     ID_or_name(&me, to->from), ID_or_name(to, to->from));
395    
396     DLINK_FOREACH(ptr, pending_glines.head)
397     {
398     char timebuffer[MAX_DATE_STRING];
399     struct GlinePending *p = ptr->data;
400     struct tm *tmptr = localtime(&p->request1.time_request);
401    
402     strftime(timebuffer, sizeof(timebuffer), "%Y/%m/%d %H:%M:%S", tmptr);
403     sendto_one(to, ":%s NOTICE %s :1) %s!%s@%s on %s requested gline at %s "
404     "for %s@%s [%s]", ID_or_name(&me, to->from),
405     ID_or_name(to, to->from), p->request1.nick, p->request1.user,
406     p->request1.host, p->request1.server, timebuffer, p->user,
407     p->host, p->request1.reason);
408    
409     if (p->request2.nick[0])
410     {
411     tmptr = localtime(&p->request2.time_request);
412     strftime(timebuffer, sizeof(timebuffer), "%Y/%m/%d %H:%M:%S", tmptr);
413     sendto_one(to, ":%s NOTICE %s :2) %s!%s@%s on %s requested gline at %s "
414     "for %s@%s [%s]", ID_or_name(&me, to->from),
415     ID_or_name(to, to->from), p->request2.nick, p->request2.user,
416     p->request2.host, p->request2.server, timebuffer, p->user,
417     p->host, p->request2.reason);
418     }
419     }
420    
421     if (dlink_list_length(&pending_glines) > 0)
422     sendto_one(to, ":%s NOTICE %s :End of Pending G-lines",
423     ID_or_name(&me, to->from), ID_or_name(to, to->from));
424     #else
425     sendto_one(to, ":%s NOTICE %s :This server does not support G-line voting",
426     ID_or_name(&me, to->from), ID_or_name(to, to->from));
427     #endif
428     }
429     else
430     sendto_one(to, ":%s NOTICE %s :This server does not support G-lines",
431     ID_or_name(&me, to->from), ID_or_name(to, to->from));
432     }
433    
434     void
435     report_gline_deny(struct Client *to)
436     {
437     dlink_node *ptr;
438     struct GlineDenyConf *conf;
439     char buf[3] = {0};
440    
441     if (enable_glines)
442     DLINK_FOREACH(ptr, gdeny_confs.head)
443     {
444     conf = ptr->data;
445     buf[0] = (conf->action & GDENY_BLOCK) ? 'B' : 'b';
446     buf[1] = (conf->action & GDENY_REJECT) ? 'R' : 'r';
447     sendto_one(to, ":%s %d %s V %s@%s %s %s", ID_or_name(&me, to->from),
448     RPL_STATSDEBUG, ID_or_name(to, to->from), conf->user,
449     conf->host, conf->server, buf);
450     }
451     else
452     sendto_one(to, ":%s NOTICE %s :This server does not support G-lines",
453     ID_or_name(&me, to->from), ID_or_name(to, to->from));
454     }
455    
456     /*
457 adx 735 * init_glines()
458     *
459     * Defines the glines{} conf section.
460     *
461     * inputs: none
462     * output: none
463     */
464     void
465     init_glines(void)
466     {
467     struct ConfSection *s = add_conf_section("glines", 2);
468    
469     hreset = install_hook(reset_conf, reset_glines);
470 adx 743 hbanned = install_hook(is_client_banned, is_client_glined);
471 adx 735
472     acb_type_gline = register_acb_type("G-line", (ACB_FREE_HANDLER *) free_gline);
473    
474     s->before = s->after = clear_temp;
475    
476     add_conf_field(s, "enable", CT_BOOL, NULL, &enable_glines);
477     add_conf_field(s, "duration", CT_TIME, NULL, &gline_duration);
478     add_conf_field(s, "logging", CT_LIST, do_parse_action, &gline_logging);
479     add_conf_field(s, "user", CT_STRING, parse_user, NULL);
480     add_conf_field(s, "name", CT_STRING, NULL, &tmpdeny_server);
481     add_conf_field(s, "action", CT_LIST, parse_action, NULL);
482     }

Properties

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