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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 933 - (show annotations)
Wed Apr 8 20:32:49 2009 UTC (10 years, 9 months ago) by db
File MIME type: text/x-chdr
File size: 17765 byte(s)
- Remove the old m_ungline code to start.



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

Properties

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

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