/[svn]/ircd-hybrid-7.2/modules/m_gline.c
ViewVC logotype

Annotation of /ircd-hybrid-7.2/modules/m_gline.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 885 - (hide annotations)
Wed Oct 31 18:09:24 2007 UTC (12 years, 7 months ago) by michael
File MIME type: text/x-chdr
File size: 19379 byte(s)
- Removed LazyLinks in 7.2 to stop people from asking why we keep
  broken code for half a decade. LL will be implemented in a smarter
  fashion in due time

1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * m_gline.c: Votes towards globally banning a mask.
4     *
5     * Copyright (C) 2002 by the past and present ircd coders, and others.
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 knight 31 * $Id$
23 adx 30 */
24    
25     #include "stdinc.h"
26     #include "tools.h"
27     #include "handlers.h"
28     #include "s_gline.h"
29     #include "channel.h"
30     #include "client.h"
31     #include "common.h"
32     #include "irc_string.h"
33     #include "sprintf_irc.h"
34     #include "ircd.h"
35     #include "hostmask.h"
36     #include "numeric.h"
37     #include "fdlist.h"
38     #include "s_bsd.h"
39     #include "s_conf.h"
40     #include "s_misc.h"
41     #include "send.h"
42     #include "msg.h"
43     #include "fileio.h"
44     #include "s_serv.h"
45     #include "hash.h"
46     #include "parse.h"
47     #include "modules.h"
48     #include "list.h"
49     #include "s_log.h"
50    
51     #define GLINE_NOT_PLACED 0
52     #ifdef GLINE_VOTING
53     #define GLINE_ALREADY_VOTED -1
54     #endif /* GLINE_VOTING */
55     #define GLINE_PLACED 1
56    
57     extern dlink_list gdeny_items;
58    
59     /* internal functions */
60     static void set_local_gline(const struct Client *,
61     const char *, const char *, const char *);
62    
63     #ifdef GLINE_VOTING
64     static int check_majority_gline(const struct Client *,
65     const char *, const char *, const char *);
66    
67     static void add_new_majority_gline(const struct Client *,
68     const char *, const char *, const char *);
69     #endif /* GLINE_VOTING */
70    
71     static void do_sgline(struct Client *, struct Client *, int, char **, int);
72    
73     static void me_gline(struct Client *, struct Client *, int, char **);
74     static void ms_gline(struct Client *, struct Client *, int, char **);
75     static void mo_gline(struct Client *, struct Client *, int, char **);
76     static void mo_ungline(struct Client *, struct Client *, int, char **);
77    
78     /*
79     * gline enforces 3 parameters to force operator to give a reason
80     * a gline is not valid with "No reason"
81     * -db
82     */
83     struct Message gline_msgtab = {
84     "GLINE", 0, 0, 3, 0, MFLG_SLOW, 0,
85     {m_unregistered, m_not_oper, ms_gline, me_gline, mo_gline, m_ignore}
86     };
87    
88     struct Message ungline_msgtab = {
89     "UNGLINE", 0, 0, 2, 0, MFLG_SLOW, 0,
90     {m_unregistered, m_not_oper, m_error, m_ignore, mo_ungline, m_ignore}
91     };
92    
93     #ifndef STATIC_MODULES
94     void
95     _modinit(void)
96     {
97     mod_add_cmd(&gline_msgtab);
98     mod_add_cmd(&ungline_msgtab);
99     add_capability("GLN", CAP_GLN, 1);
100     }
101    
102     void
103     _moddeinit(void)
104     {
105     mod_del_cmd(&gline_msgtab);
106     mod_del_cmd(&ungline_msgtab);
107     delete_capability("GLN");
108     }
109    
110 knight 31 const char *_version = "$Revision$";
111 adx 30 #endif
112    
113     /* mo_gline()
114     *
115     * inputs - The usual for a m_ function
116     * output -
117     * side effects -
118     *
119     * Place a G line if 3 opers agree on the identical user@host
120     *
121     */
122     /* Allow this server to pass along GLINE if received and
123     * GLINES is not defined.
124     *
125     */
126    
127     static void
128     mo_gline(struct Client *client_p, struct Client *source_p,
129     int parc, char *parv[])
130     {
131     char *user = NULL;
132     char *host = NULL; /* user and host of GLINE "victim" */
133     char *reason = NULL; /* reason for "victims" demise */
134     char *p;
135    
136     if (!ConfigFileEntry.glines)
137     {
138     sendto_one(source_p, ":%s NOTICE %s :GLINE disabled",
139     me.name, source_p->name);
140     return;
141     }
142    
143     if (!IsOperGline(source_p))
144     {
145     sendto_one(source_p, form_str(ERR_NOPRIVS),
146     me.name, source_p->name, "gline");
147     return;
148     }
149    
150     if (parse_aline("GLINE", source_p, parc, parv,
151     AWILD, &user, &host, NULL, NULL, &reason) < 0)
152     return;
153    
154     if ((p = strchr(host, '/')) != NULL)
155     {
156     int bitlen = strtol(++p, NULL, 10);
157     int min_bitlen = strchr(host, ':') ? ConfigFileEntry.gline_min_cidr6 :
158     ConfigFileEntry.gline_min_cidr;
159     if (bitlen < min_bitlen)
160     {
161     sendto_one(source_p, ":%s NOTICE %s :Cannot set G-Lines with CIDR length < %d",
162     me.name, source_p->name, min_bitlen);
163     return;
164     }
165     }
166    
167     #ifdef GLINE_VOTING
168     /* If at least 3 opers agree this user should be G lined then do it */
169     if (check_majority_gline(source_p, user, host, reason) ==
170     GLINE_ALREADY_VOTED)
171     {
172     sendto_one(source_p,
173     ":%s NOTICE %s :This server or oper has already voted",
174     me.name, source_p->name);
175     return;
176     }
177    
178 michael 552 /*
179     * call these two functions first so the 'requesting' notice always comes
180 adx 30 * before the 'has triggered' notice. -bill
181     */
182     sendto_realops_flags(UMODE_ALL, L_ALL,
183     "%s requesting G-Line for [%s@%s] [%s]",
184     get_oper_name(source_p),
185     user, host, reason);
186     ilog(L_TRACE, "#gline for %s@%s [%s] requested by %s!%s@%s",
187     user, host, reason, source_p->name, source_p->username,
188     source_p->host);
189     #else
190     set_local_gline(source_p, user, host, reason);
191     #endif /* GLINE_VOTING */
192    
193     /* 4 param version for hyb-7 servers */
194 michael 885 sendto_server(NULL, NULL, CAP_GLN|CAP_TS6, NOCAPS,
195     ":%s GLINE %s %s :%s",
196 adx 30 ID(source_p), user, host, reason);
197 michael 885 sendto_server(NULL, NULL, CAP_GLN, CAP_TS6,
198     ":%s GLINE %s %s :%s",
199 adx 30 source_p->name, user, host, reason);
200    
201     /* 8 param for hyb-6 */
202 michael 885 sendto_server(NULL, NULL, CAP_TS6, CAP_GLN,
203 adx 30 ":%s GLINE %s %s %s %s %s %s :%s",
204     ID(&me),
205     ID(source_p), source_p->username,
206     source_p->host, source_p->servptr->name, user, host,
207     reason);
208 michael 885 sendto_server(NULL, NULL, NOCAPS, CAP_GLN|CAP_TS6,
209 adx 30 ":%s GLINE %s %s %s %s %s %s :%s",
210     me.name, source_p->name, source_p->username,
211     source_p->host, source_p->servptr->name, user, host,
212     reason);
213     }
214    
215     /* ms_gline()
216     * me_gline()
217     * do_sgline()
218     *
219     * inputs - The usual for a m_ function
220     * output -
221     * side effects -
222     *
223     * Place a G line if 3 opers agree on the identical user@host
224     *
225     * Allow this server to pass along GLINE if received and
226     * GLINES is not defined.
227     *
228     * ENCAP'd GLINES are propagated by encap code.
229     */
230    
231     static void
232     ms_gline(struct Client *client_p, struct Client *source_p,
233     int parc, char *parv[])
234     {
235     do_sgline(client_p, source_p, parc, parv, 1);
236     }
237    
238     static void
239     me_gline(struct Client *client_p, struct Client *source_p,
240     int parc, char *parv[])
241     {
242     do_sgline(client_p, source_p, parc, parv, 0);
243     }
244    
245     static void
246     do_sgline(struct Client *client_p, struct Client *source_p,
247     int parc, char *parv[], int prop)
248     {
249     const char *reason = NULL; /* reason for "victims" demise */
250     char *user = NULL;
251     char *host = NULL; /* user and host of GLINE "victim" */
252     int var_offset, logged = 0;
253     dlink_node *ptr;
254     struct ConfItem *conf;
255     struct AccessItem *aconf;
256    
257     /* hyb-7 style gline (post beta3) */
258     if (parc == 4 && IsClient(source_p))
259     var_offset = 0;
260     /* or it's a hyb-6 style */
261     else if (parc == 8 && IsServer(source_p))
262     {
263     var_offset = 4;
264    
265     /*
266     * if we are dealing with an old style formatted gline,
267     * the gline message is originating from the oper's server,
268     * so we update source_p to point to the oper now, so that
269     * logging works down the line. -bill
270     */
271     if ((source_p = find_person(client_p, parv[1])) == NULL)
272     return;
273    
274     if (irccmp(parv[2], source_p->username) != 0 ||
275     irccmp(parv[3], source_p->host) != 0 ||
276     irccmp(parv[4], source_p->servptr->name) != 0)
277     {
278     /*
279     * at this point we know one of the parameters provided by
280     * the h6 server was faulty. bail out.
281     */
282     return;
283     }
284     }
285     /* none of the above */
286     else
287     return;
288    
289     assert(source_p->servptr != NULL);
290    
291     user = parv[++var_offset];
292     host = parv[++var_offset];
293     reason = parv[++var_offset];
294    
295     var_offset = 0;
296    
297     DLINK_FOREACH(ptr, gdeny_items.head)
298     {
299     conf = ptr->data;
300     aconf = (struct AccessItem *)map_to_conf(conf);
301    
302     if (match(conf->name, source_p->servptr->name) &&
303     match(aconf->user, source_p->username) &&
304     match(aconf->host, source_p->host))
305     {
306     var_offset = aconf->flags;
307     break;
308     }
309     }
310    
311     if (prop && !(var_offset & GDENY_BLOCK))
312     {
313 michael 885 sendto_server(client_p, NULL, CAP_GLN, NOCAPS,
314 adx 30 ":%s GLINE %s %s :%s",
315     source_p->name, user, host, reason);
316     /* hyb-6 version to the rest */
317 michael 885 sendto_server(client_p, NULL, NOCAPS, CAP_GLN,
318 adx 30 ":%s GLINE %s %s %s %s %s %s :%s",
319     source_p->servptr->name,
320     source_p->name, source_p->username, source_p->host,
321     source_p->servptr->name,
322     user, host, reason);
323     }
324     else if (ConfigFileEntry.gline_logging & GDENY_BLOCK && ServerInfo.hub)
325     {
326     sendto_realops_flags(UMODE_ALL, L_ALL, "Blocked G-Line %s requested on [%s@%s] [%s]",
327     get_oper_name(source_p), user, host, reason);
328     ilog(L_TRACE, "Blocked G-Line %s requested on [%s@%s] [%s]",
329     get_oper_name(source_p), user, host, reason);
330     logged = 1;
331     }
332    
333    
334     if (var_offset & GDENY_REJECT)
335     {
336     if (ConfigFileEntry.gline_logging & GDENY_REJECT && !logged)
337     {
338     sendto_realops_flags(UMODE_ALL, L_ALL, "Rejected G-Line %s requested on [%s@%s] [%s]",
339     get_oper_name(source_p), user, host, reason);
340     ilog(L_TRACE, "Rejected G-Line %s requested on [%s@%s] [%s]",
341     get_oper_name(source_p), user, host, reason);
342     }
343     return;
344     }
345    
346     if (ConfigFileEntry.glines)
347     {
348     if (!valid_wild_card(source_p, YES, 2, user, host))
349     return;
350    
351     if (IsClient(source_p))
352     {
353     const char *p = NULL;
354     if ((p = strchr(host, '/')))
355     {
356     int bitlen = strtol(++p, NULL, 10);
357     int min_bitlen = strchr(host, ':') ? ConfigFileEntry.gline_min_cidr6 :
358     ConfigFileEntry.gline_min_cidr;
359    
360     if (bitlen < min_bitlen)
361     {
362     sendto_realops_flags(UMODE_ALL, L_ALL, "%s!%s@%s on %s is requesting "
363     "a GLINE with a CIDR mask < %d for [%s@%s] [%s]",
364     source_p->name, source_p->username, source_p->host,
365     source_p->servptr->name, min_bitlen, user, host, reason);
366     return;
367     }
368     }
369     }
370    
371     #ifdef GLINE_VOTING
372     /* If at least 3 opers agree this user should be G lined then do it */
373     if (check_majority_gline(source_p, user, host, reason) ==
374     GLINE_ALREADY_VOTED)
375     {
376     sendto_realops_flags(UMODE_ALL, L_ALL, "oper or server has already voted");
377     return;
378     }
379    
380 michael 554 sendto_realops_flags(UMODE_ALL, L_ALL,
381     "%s requesting G-Line for [%s@%s] [%s]",
382     get_oper_name(source_p),
383     user, host, reason);
384 adx 30 ilog(L_TRACE, "#gline for %s@%s [%s] requested by %s",
385     user, host, reason, get_oper_name(source_p));
386     #else
387     set_local_gline(source_p, user, host, reason);
388     #endif /* GLINE_VOTING */
389     }
390     }
391    
392     /* set_local_gline()
393     *
394     * inputs - pointer to client struct of oper
395     * - pointer to victim user
396     * - pointer to victim host
397     * - pointer reason
398     * output - NONE
399     * side effects -
400     */
401     static void
402     set_local_gline(const struct Client *source_p, const char *user,
403     const char *host, const char *reason)
404     {
405     char buffer[IRCD_BUFSIZE];
406     struct ConfItem *conf;
407     struct AccessItem *aconf;
408     const char *current_date;
409     time_t cur_time;
410    
411     set_time();
412     cur_time = CurrentTime;
413    
414     current_date = smalldate(cur_time);
415     conf = make_conf_item(GLINE_TYPE);
416     aconf = (struct AccessItem *)map_to_conf(conf);
417    
418     ircsprintf(buffer, "%s (%s)", reason, current_date);
419     DupString(aconf->reason, buffer);
420     DupString(aconf->user, user);
421     DupString(aconf->host, host);
422    
423     aconf->hold = CurrentTime + ConfigFileEntry.gline_time;
424     add_temp_line(conf);
425    
426     sendto_realops_flags(UMODE_ALL, L_ALL,
427     "%s added G-Line for [%s@%s] [%s]",
428     get_oper_name(source_p),
429     aconf->user, aconf->host, aconf->reason);
430     ilog(L_TRACE, "%s added G-Line for [%s@%s] [%s]",
431     get_oper_name(source_p), aconf->user, aconf->host, aconf->reason);
432     log_oper_action(LOG_GLINE_TYPE, source_p, "[%s@%s] [%s]\n",
433     aconf->user, aconf->host, aconf->reason);
434     /* Now, activate gline against current online clients */
435     rehashed_klines = 1;
436     }
437    
438     #ifdef GLINE_VOTING
439     /* add_new_majority_gline()
440     *
441     * inputs - operator requesting gline
442     * - username covered by the gline
443     * - hostname covered by the gline
444     * - reason for the gline
445     * output - NONE
446     * side effects -
447     * This function is called once a majority of opers
448     * have agreed on a gline, and it can be placed. The
449     * information about an operator being passed to us
450     * happens to be the operator who pushed us over the
451     * "majority" level needed. See check_majority_gline()
452     * for more information.
453     */
454     static void
455     add_new_majority_gline(const struct Client *source_p,
456     const char *user, const char *host, const char *reason)
457     {
458     struct gline_pending *pending = MyMalloc(sizeof(struct gline_pending));
459    
460     strlcpy(pending->oper_nick1, source_p->name, sizeof(pending->oper_nick1));
461     strlcpy(pending->oper_user1, source_p->username, sizeof(pending->oper_user1));
462     strlcpy(pending->oper_host1, source_p->host, sizeof(pending->oper_host1));
463    
464     strlcpy(pending->oper_server1, source_p->servptr->name, sizeof(pending->oper_server1));
465    
466     strlcpy(pending->user, user, sizeof(pending->user));
467     strlcpy(pending->host, host, sizeof(pending->host));
468     strlcpy(pending->reason1, reason, sizeof(pending->reason1));
469    
470     pending->last_gline_time = CurrentTime;
471     pending->time_request1 = CurrentTime;
472    
473     dlinkAdd(pending, &pending->node, &pending_glines);
474     }
475    
476     /* check_majority_gline()
477     *
478     * inputs - source, user, host, reason
479     *
480     * output - one of three results
481     *
482     * GLINE_ALREADY_VOTED - returned if oper/server has already voted
483     * GLINE_PLACED - returned if this triggers a gline
484     * GLINE_NOT_PLACED - returned if not triggered
485     *
486     * Side effects -
487     * See if there is a majority agreement on a GLINE on the given user
488     * There must be at least 3 different opers agreeing on this GLINE
489     *
490     */
491     static int
492     check_majority_gline(const struct Client *source_p,
493     const char *user, const char *host, const char *reason)
494     {
495     dlink_node *pending_node;
496     struct gline_pending *gline_pending_ptr;
497    
498     /* if its already glined, why bother? :) -- fl_ */
499     if (find_is_glined(host, user))
500     return(GLINE_NOT_PLACED);
501    
502     /* special case condition where there are no pending glines */
503     if (dlink_list_length(&pending_glines) == 0) /* first gline request placed */
504     {
505     add_new_majority_gline(source_p, user, host, reason);
506     return(GLINE_NOT_PLACED);
507     }
508    
509     DLINK_FOREACH(pending_node, pending_glines.head)
510     {
511     gline_pending_ptr = pending_node->data;
512    
513     if ((irccmp(gline_pending_ptr->user, user) == 0) &&
514     (irccmp(gline_pending_ptr->host, host) == 0))
515     {
516     if (((irccmp(gline_pending_ptr->oper_user1, source_p->username) == 0) ||
517     (irccmp(gline_pending_ptr->oper_host1, source_p->host) == 0)) ||
518     (irccmp(gline_pending_ptr->oper_server1, source_p->servptr->name) == 0))
519     {
520     return(GLINE_ALREADY_VOTED);
521     }
522    
523     if (gline_pending_ptr->oper_user2[0] != '\0')
524     {
525     /* if two other opers on two different servers have voted yes */
526    
527     if(((irccmp(gline_pending_ptr->oper_user2, source_p->username)==0) ||
528     (irccmp(gline_pending_ptr->oper_host2, source_p->host)==0)) ||
529     (irccmp(gline_pending_ptr->oper_server2, source_p->servptr->name)==0))
530     {
531     return(GLINE_ALREADY_VOTED);
532     }
533    
534     /* trigger the gline using the original reason --fl */
535     set_local_gline(source_p, user, host, gline_pending_ptr->reason1);
536     cleanup_glines(NULL);
537     return(GLINE_PLACED);
538     }
539     else
540     {
541     strlcpy(gline_pending_ptr->oper_nick2, source_p->name,
542     sizeof(gline_pending_ptr->oper_nick2));
543     strlcpy(gline_pending_ptr->oper_user2, source_p->username,
544     sizeof(gline_pending_ptr->oper_user2));
545     strlcpy(gline_pending_ptr->oper_host2, source_p->host,
546     sizeof(gline_pending_ptr->oper_host2));
547     strlcpy(gline_pending_ptr->reason2, reason,
548     sizeof(gline_pending_ptr->reason2));
549     strlcpy(gline_pending_ptr->oper_server2, source_p->servptr->name,
550     sizeof(gline_pending_ptr->oper_server2));
551     gline_pending_ptr->last_gline_time = CurrentTime;
552     gline_pending_ptr->time_request2 = CurrentTime;
553     return(GLINE_NOT_PLACED);
554     }
555     }
556     }
557    
558     /* Didn't find this user@host gline in pending gline list
559     * so add it.
560     */
561     add_new_majority_gline(source_p, user, host, reason);
562     return(GLINE_NOT_PLACED);
563     }
564     #endif /* GLINE_VOTING */
565    
566     static int
567     remove_gline_match(const char *user, const char *host)
568     {
569     struct AccessItem *aconf;
570     dlink_node *ptr = NULL;
571     struct irc_ssaddr addr, caddr;
572     int nm_t, cnm_t, bits, cbits;
573    
574     nm_t = parse_netmask(host, &addr, &bits);
575    
576     DLINK_FOREACH(ptr, temporary_glines.head)
577     {
578     aconf = map_to_conf(ptr->data);
579     cnm_t = parse_netmask(aconf->host, &caddr, &cbits);
580    
581     if (cnm_t != nm_t || irccmp(user, aconf->user))
582     continue;
583    
584     if ((nm_t == HM_HOST && !irccmp(aconf->host, host)) ||
585     (nm_t == HM_IPV4 && bits == cbits && match_ipv4(&addr, &caddr, bits))
586     #ifdef IPV6
587     || (nm_t == HM_IPV6 && bits == cbits && match_ipv6(&addr, &caddr, bits))
588     #endif
589     )
590     {
591     dlinkDelete(ptr, &temporary_glines);
592     delete_one_address_conf(aconf->host, aconf);
593     return(1);
594     }
595     }
596    
597     return(0);
598     }
599    
600     /*
601     ** m_ungline
602     ** added May 29th 2000 by Toby Verrall <toot@melnet.co.uk>
603     ** added to hybrid-7 7/11/2000 --is
604     **
605     ** parv[0] = sender nick
606     ** parv[1] = gline to remove
607     */
608     static void
609     mo_ungline(struct Client *client_p, struct Client *source_p,
610     int parc, char *parv[])
611     {
612     char *user, *host;
613    
614     if (!ConfigFileEntry.glines)
615     {
616     sendto_one(source_p, ":%s NOTICE %s :UNGLINE disabled",
617     me.name, source_p->name);
618     return;
619     }
620    
621     if (!IsOperUnkline(source_p) || !IsOperGline(source_p))
622     {
623     sendto_one(source_p, form_str(ERR_NOPRIVS),
624     me.name, source_p->name, "gline");
625     return;
626     }
627    
628     if (parse_aline("UNGLINE", source_p, parc, parv,
629     0, &user, &host, NULL, NULL, NULL) < 0)
630     return;
631    
632     if (remove_gline_match(user, host))
633     {
634     sendto_one(source_p, ":%s NOTICE %s :G-Line for [%s@%s] is removed",
635     me.name, source_p->name, user, host);
636     sendto_realops_flags(UMODE_ALL, L_ALL,
637     "%s has removed the G-Line for: [%s@%s]",
638     get_oper_name(source_p), user, host);
639     ilog(L_NOTICE, "%s removed G-Line for [%s@%s]",
640     get_oper_name(source_p), user, host);
641     }
642     else
643     {
644     sendto_one(source_p, ":%s NOTICE %s :No G-Line for %s@%s",
645     me.name, source_p->name, user, host);
646     }
647     }

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28