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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1622 - (show annotations)
Thu Nov 1 13:16:37 2012 UTC (7 years, 10 months ago) by michael
File MIME type: text/x-chdr
File size: 18384 byte(s)
- klines, dlines, xlines, glines and resv now make use of the new database;
  also, temporary *lines are now stored, so they're not lost after
  restarting the ircd. This also applies to G-lines.

1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 *
4 * Copyright (C) 2002 by the past and present ircd coders, and others.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 * USA
20 */
21
22 /*! \file m_gline.c
23 * \brief Includes required functions for processing the GLINE command.
24 * \version $Id$
25 */
26
27 #include "stdinc.h"
28 #include "list.h"
29 #include "s_gline.h"
30 #include "channel.h"
31 #include "client.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 "s_bsd.h"
38 #include "conf.h"
39 #include "s_misc.h"
40 #include "send.h"
41 #include "s_serv.h"
42 #include "hash.h"
43 #include "parse.h"
44 #include "modules.h"
45 #include "log.h"
46 #include "conf_db.h"
47
48 #define GLINE_NOT_PLACED 0
49 #define GLINE_ALREADY_VOTED -1
50 #define GLINE_PLACED 1
51
52
53 /*! \brief Adds a GLINE to the configuration subsystem.
54 *
55 * \param source_p Operator requesting gline
56 * \param user Username covered by the gline
57 * \param host Hostname covered by the gline
58 * \param reason Reason for the gline
59 */
60 static void
61 set_local_gline(const struct Client *source_p, const char *user,
62 const char *host, const char *reason)
63 {
64 char buffer[IRCD_BUFSIZE];
65 struct AccessItem *aconf = map_to_conf(make_conf_item(GLINE_TYPE));
66
67 snprintf(buffer, sizeof(buffer), "%s (%s)", reason, smalldate(CurrentTime));
68 DupString(aconf->reason, buffer);
69 DupString(aconf->user, user);
70 DupString(aconf->host, host);
71
72 aconf->setat = CurrentTime;
73 aconf->hold = CurrentTime + ConfigFileEntry.gline_time;
74 SetConfTemporary(aconf);
75
76 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
77 "%s added G-Line for [%s@%s] [%s]",
78 get_oper_name(source_p),
79 aconf->user, aconf->host, aconf->reason);
80 ilog(LOG_TYPE_GLINE, "%s added G-Line for [%s@%s] [%s]",
81 get_oper_name(source_p), aconf->user, aconf->host, aconf->reason);
82
83 add_conf_by_address(CONF_GLINE, aconf);
84 save_gline_database();
85 rehashed_klines = 1;
86 }
87
88 /*! \brief Removes a GLINE from the configuration subsystem.
89 *
90 * \param user Username covered by the gline
91 * \param host Hostname covered by the gline
92 */
93 static int
94 remove_gline_match(const char *user, const char *host)
95 {
96 struct irc_ssaddr iphost, *piphost;
97 struct AccessItem *aconf;
98 int t;
99
100 if ((t = parse_netmask(host, &iphost, NULL)) != HM_HOST)
101 {
102 #ifdef IPV6
103 if (t == HM_IPV6)
104 t = AF_INET6;
105 else
106 #endif
107 t = AF_INET;
108 piphost = &iphost;
109 }
110 else
111 {
112 t = 0;
113 piphost = NULL;
114 }
115
116 if ((aconf = find_conf_by_address(host, piphost, CONF_GLINE, t, user, NULL, 0)))
117 {
118 delete_one_address_conf(host, aconf);
119 save_gline_database();
120 return 1;
121 }
122
123 return 0;
124 }
125
126 /*! \brief This function is called once a majority of opers have agreed on a
127 * GLINE/GUNGLINE, and it can be placed. The information about an
128 * operator being passed to us happens to be the operator who pushed us
129 * over the "majority" level needed. See check_majority() for more
130 * information.
131 *
132 * \param source_p Operator requesting gline
133 * \param user Username covered by the gline
134 * \param host Hostname covered by the gline
135 * \param reason Reason for the gline
136 * \param type Valid values are either GLINE_PENDING_ADD_TYPE, or
137 * GLINE_PENDING_DEL_TYPE
138 */
139 static void
140 add_new_majority(const struct Client *source_p, const char *user,
141 const char *host, const char *reason, const unsigned int type)
142 {
143 struct gline_pending *pending = MyMalloc(sizeof(struct gline_pending));
144
145 strlcpy(pending->vote_1.oper_nick, source_p->name, sizeof(pending->vote_1.oper_nick));
146 strlcpy(pending->vote_1.oper_user, source_p->username, sizeof(pending->vote_1.oper_user));
147 strlcpy(pending->vote_1.oper_host, source_p->host, sizeof(pending->vote_1.oper_host));
148 strlcpy(pending->vote_1.oper_server, source_p->servptr->name, sizeof(pending->vote_1.oper_server));
149
150 strlcpy(pending->user, user, sizeof(pending->user));
151 strlcpy(pending->host, host, sizeof(pending->host));
152 strlcpy(pending->vote_1.reason, reason, sizeof(pending->vote_1.reason));
153
154 pending->last_gline_time = CurrentTime;
155 pending->vote_1.time_request = CurrentTime;
156
157 dlinkAdd(pending, &pending->node, &pending_glines[type]);
158 }
159
160 /*! \brief See if there is a majority agreement on a GLINE on the given user.
161 * There must be at least 3 different opers agreeing on this
162 * GLINE/GUNGLINE
163 *
164 * \param source_p Operator requesting gline
165 * \param user Username covered by the gline
166 * \param host Hostname covered by the gline
167 * \param reason Reason for the gline
168 * \param type Valid values are either GLINE_PENDING_ADD_TYPE, or
169 * GLINE_PENDING_DEL_TYPE
170 *
171 * \return
172 * - GLINE_ALREADY_VOTED returned if oper/server has already voted
173 * - GLINE_PLACED returned if this triggers a gline
174 * - GLINE_NOT_PLACED returned if not triggered
175 */
176 static int
177 check_majority(const struct Client *source_p, const char *user,
178 const char *host, const char *reason, const int type)
179 {
180 dlink_node *dn_ptr = NULL;
181
182 cleanup_glines(NULL);
183
184 /* if its already glined, why bother? :) -- fl_ */
185 if ((type == GLINE_PENDING_ADD_TYPE) && find_is_glined(host, user))
186 return GLINE_NOT_PLACED;
187
188 DLINK_FOREACH(dn_ptr, pending_glines[type].head)
189 {
190 struct gline_pending *gp_ptr = dn_ptr->data;
191
192 if (irccmp(gp_ptr->user, user) ||
193 irccmp(gp_ptr->host, host))
194 continue;
195
196 if ((!irccmp(gp_ptr->vote_1.oper_user, source_p->username) &&
197 !irccmp(gp_ptr->vote_1.oper_host, source_p->host)) ||
198 !irccmp(gp_ptr->vote_1.oper_server, source_p->servptr->name))
199 return GLINE_ALREADY_VOTED;
200
201 if (gp_ptr->vote_2.oper_user[0] != '\0')
202 {
203 /* if two other opers on two different servers have voted yes */
204 if ((!irccmp(gp_ptr->vote_2.oper_user, source_p->username) &&
205 !irccmp(gp_ptr->vote_2.oper_host, source_p->host)) ||
206 !irccmp(gp_ptr->vote_2.oper_server, source_p->servptr->name))
207 return GLINE_ALREADY_VOTED;
208
209 if (type == GLINE_PENDING_DEL_TYPE)
210 {
211 if (remove_gline_match(user, host))
212 {
213 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
214 "%s has removed the G-Line for: [%s@%s]",
215 get_oper_name(source_p), user, host);
216 ilog(LOG_TYPE_GLINE, "%s removed G-Line for [%s@%s]",
217 get_oper_name(source_p), user, host);
218 }
219 }
220 else
221 /* trigger the gline using the original reason --fl */
222 set_local_gline(source_p, user, host, gp_ptr->vote_1.reason);
223
224 cleanup_glines(gp_ptr);
225 return GLINE_PLACED;
226 }
227
228 strlcpy(gp_ptr->vote_2.oper_nick, source_p->name,
229 sizeof(gp_ptr->vote_2.oper_nick));
230 strlcpy(gp_ptr->vote_2.oper_user, source_p->username,
231 sizeof(gp_ptr->vote_2.oper_user));
232 strlcpy(gp_ptr->vote_2.oper_host, source_p->host,
233 sizeof(gp_ptr->vote_2.oper_host));
234 strlcpy(gp_ptr->vote_2.reason, reason,
235 sizeof(gp_ptr->vote_2.reason));
236 strlcpy(gp_ptr->vote_2.oper_server, source_p->servptr->name,
237 sizeof(gp_ptr->vote_2.oper_server));
238 gp_ptr->last_gline_time = CurrentTime;
239 gp_ptr->vote_2.time_request = CurrentTime;
240 return GLINE_NOT_PLACED;
241 }
242
243 /*
244 * Didn't find this user@host gline in pending gline list
245 * so add it.
246 */
247 add_new_majority(source_p, user, host, reason, type);
248 return GLINE_NOT_PLACED;
249 }
250
251 static void
252 do_sgline(struct Client *source_p, int parc, char *parv[], int prop)
253 {
254 const char *reason = NULL; /* reason for "victims" demise */
255 const char *user = NULL;
256 const char *host = NULL; /* user and host of GLINE "victim" */
257
258 if (!IsClient(source_p))
259 return;
260
261 if (parc != 4 || EmptyString(parv[3]))
262 return;
263
264 assert(source_p->servptr != NULL);
265
266 user = parv[1];
267 host = parv[2];
268 reason = parv[3];
269
270 sendto_server(source_p->from, CAP_GLN|CAP_TS6, NOCAPS,
271 ":%s GLINE %s %s :%s",
272 ID(source_p), user, host, reason);
273 sendto_server(source_p->from, CAP_GLN, CAP_TS6,
274 ":%s GLINE %s %s :%s",
275 source_p->name, user, host, reason);
276
277 if (ConfigFileEntry.glines)
278 {
279 if (!valid_wild_card(source_p, 1, 2, user, host))
280 return;
281
282 if (IsClient(source_p))
283 {
284 const char *p = NULL;
285
286 if ((p = strchr(host, '/')))
287 {
288 int bitlen = strtol(++p, NULL, 10);
289 int min_bitlen = strchr(host, ':') ? ConfigFileEntry.gline_min_cidr6 :
290 ConfigFileEntry.gline_min_cidr;
291
292 if (bitlen < min_bitlen)
293 {
294 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
295 "%s is requesting a GLINE with a CIDR mask < %d for [%s@%s] [%s]",
296 get_oper_name(source_p), min_bitlen,
297 user, host, reason);
298 return;
299 }
300 }
301 }
302
303 /* If at least 3 opers agree this user should be G lined then do it */
304 if (check_majority(source_p, user, host, reason, GLINE_PENDING_ADD_TYPE) ==
305 GLINE_ALREADY_VOTED)
306 {
307 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
308 "oper or server has already voted");
309 return;
310 }
311
312 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
313 "%s requesting G-Line for [%s@%s] [%s]",
314 get_oper_name(source_p),
315 user, host, reason);
316 ilog(LOG_TYPE_GLINE, "#gline for %s@%s [%s] requested by %s",
317 user, host, reason, get_oper_name(source_p));
318 }
319 }
320
321
322 /*! \brief GLINE command handler (called by operators)
323 *
324 * \param client_p Pointer to allocated Client struct with physical connection
325 * to this server, i.e. with an open socket connected.
326 * \param source_p Pointer to allocated Client struct from which the message
327 * originally comes from. This can be a local or remote client.
328 * \param parc Integer holding the number of supplied arguments.
329 * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
330 * pointers.
331 * \note Valid arguments for this command are:
332 * - parv[0] = sender prefix
333 * - parv[1] = user\@host mask
334 * - parv[2] = reason
335 */
336 static void
337 mo_gline(struct Client *client_p, struct Client *source_p,
338 int parc, char *parv[])
339 {
340 char *user = NULL;
341 char *host = NULL;
342 char *reason = NULL;
343 char *p;
344
345 if (!HasOFlag(source_p, OPER_FLAG_GLINE))
346 {
347 sendto_one(source_p, form_str(ERR_NOPRIVS),
348 me.name, source_p->name, "gline");
349 return;
350 }
351
352 if (!ConfigFileEntry.glines)
353 {
354 sendto_one(source_p, ":%s NOTICE %s :GLINE disabled",
355 me.name, source_p->name);
356 return;
357 }
358
359 if (parse_aline("GLINE", source_p, parc, parv, AWILD,
360 &user, &host, NULL, NULL, &reason) < 0)
361 return;
362
363 if ((p = strchr(host, '/')) != NULL)
364 {
365 int bitlen = strtol(++p, NULL, 10);
366 int min_bitlen = strchr(host, ':') ? ConfigFileEntry.gline_min_cidr6 :
367 ConfigFileEntry.gline_min_cidr;
368 if (bitlen < min_bitlen)
369 {
370 sendto_one(source_p, ":%s NOTICE %s :Cannot set G-Lines with CIDR length < %d",
371 me.name, source_p->name, min_bitlen);
372 return;
373 }
374 }
375
376 /* If at least 3 opers agree this user should be G lined then do it */
377 if (check_majority(source_p, user, host, reason, GLINE_PENDING_ADD_TYPE) ==
378 GLINE_ALREADY_VOTED)
379 {
380 sendto_one(source_p,
381 ":%s NOTICE %s :This server or oper has already voted",
382 me.name, source_p->name);
383 return;
384 }
385
386 /*
387 * call these two functions first so the 'requesting' notice always comes
388 * before the 'has triggered' notice. -bill
389 */
390 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
391 "%s requesting G-Line for [%s@%s] [%s]",
392 get_oper_name(source_p),
393 user, host, reason);
394 ilog(LOG_TYPE_GLINE, "#gline for %s@%s [%s] requested by %s!%s@%s",
395 user, host, reason, source_p->name, source_p->username,
396 source_p->host);
397
398 /* 4 param version for hyb-7 servers */
399 sendto_server(NULL, CAP_GLN|CAP_TS6, NOCAPS,
400 ":%s GLINE %s %s :%s",
401 ID(source_p), user, host, reason);
402 sendto_server(NULL, CAP_GLN, CAP_TS6,
403 ":%s GLINE %s %s :%s",
404 source_p->name, user, host, reason);
405 }
406
407 /* ms_gline()
408 * me_gline()
409 * do_sgline()
410 *
411 * inputs - The usual for a m_ function
412 * output -
413 * side effects -
414 *
415 * Place a G line if 3 opers agree on the identical user@host
416 *
417 * Allow this server to pass along GLINE if received and
418 * GLINES is not defined.
419 *
420 * ENCAP'd GLINES are propagated by encap code.
421 */
422
423 static void
424 ms_gline(struct Client *client_p, struct Client *source_p,
425 int parc, char *parv[])
426 {
427 do_sgline(source_p, parc, parv, 1);
428 }
429
430 static void
431 me_gline(struct Client *client_p, struct Client *source_p,
432 int parc, char *parv[])
433 {
434 do_sgline(source_p, parc, parv, 0);
435 }
436
437 static void
438 do_sungline(struct Client *source_p, const char *user,
439 const char *host, const char *reason, int prop)
440 {
441 assert(source_p->servptr != NULL);
442
443 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
444 "%s requesting UNG-Line for [%s@%s] [%s]",
445 get_oper_name(source_p), user, host, reason);
446 ilog(LOG_TYPE_GLINE, "#ungline for %s@%s [%s] requested by %s",
447 user, host, reason, get_oper_name(source_p));
448
449 /* If at least 3 opers agree this user should be un G lined then do it */
450 if (check_majority(source_p, user, host, reason, GLINE_PENDING_DEL_TYPE) ==
451 GLINE_ALREADY_VOTED)
452 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
453 "oper or server has already voted");
454
455 if (prop)
456 {
457 sendto_server(source_p->from, CAP_ENCAP|CAP_TS6, NOCAPS,
458 ":%s ENCAP * GUNGLINE %s %s :%s",
459 ID(source_p), user, host, reason);
460 sendto_server(source_p->from, CAP_ENCAP, CAP_TS6,
461 ":%s ENCAP * GUNGLINE %s %s :%s",
462 source_p->name, user, host, reason);
463 }
464 }
465
466 /*! \brief GUNGLINE command handler (called in response to an encapsulated
467 * GUNGLINE command)
468 *
469 * \param client_p Pointer to allocated Client struct with physical connection
470 * to this server, i.e. with an open socket connected.
471 * \param source_p Pointer to allocated Client struct from which the message
472 * originally comes from. This can be a local or remote client.
473 * \param parc Integer holding the number of supplied arguments.
474 * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
475 * pointers.
476 * \note Valid arguments for this command are:
477 * - parv[0] = sender prefix
478 * - parv[1] = username
479 * - parv[2] = hostname
480 * - parv[3] = reason
481 */
482 static void
483 me_gungline(struct Client *client_p, struct Client *source_p,
484 int parc, char *parv[])
485 {
486 if (ConfigFileEntry.glines)
487 do_sungline(source_p, parv[1], parv[2], parv[3], 0);
488 }
489
490 /*! \brief GUNGLINE command handler (called by operators)
491 *
492 * \param client_p Pointer to allocated Client struct with physical connection
493 * to this server, i.e. with an open socket connected.
494 * \param source_p Pointer to allocated Client struct from which the message
495 * originally comes from. This can be a local or remote client.
496 * \param parc Integer holding the number of supplied arguments.
497 * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
498 * pointers.
499 * \note Valid arguments for this command are:
500 * - parv[0] = sender prefix
501 * - parv[1] = user\@host mask
502 * - parv[2] = reason
503 */
504 static void
505 mo_gungline(struct Client *client_p, struct Client *source_p,
506 int parc, char *parv[])
507 {
508 char *user = NULL;
509 char *host = NULL;
510 char *reason = NULL;
511
512 if (!HasOFlag(source_p, OPER_FLAG_GLINE))
513 {
514 sendto_one(source_p, form_str(ERR_NOPRIVS),
515 me.name, source_p->name, "gline");
516 return;
517 }
518
519 if (!ConfigFileEntry.glines)
520 {
521 sendto_one(source_p, ":%s NOTICE %s :GUNGLINE disabled",
522 me.name, source_p->name);
523 return;
524 }
525
526 if (parse_aline("GUNGLINE", source_p, parc, parv, 0, &user,
527 &host, NULL, NULL, &reason) < 0)
528 return;
529
530 do_sungline(source_p, user, host, reason, 1);
531 }
532
533 /*
534 * gline enforces 3 parameters to force operator to give a reason
535 * a gline is not valid with "No reason"
536 * -db
537 */
538 static struct Message gline_msgtab = {
539 "GLINE", 0, 0, 3, MAXPARA, MFLG_SLOW, 0,
540 { m_unregistered, m_not_oper, ms_gline, me_gline, mo_gline, m_ignore }
541 };
542
543 static struct Message ungline_msgtab = {
544 "GUNGLINE", 0, 0, 3, MAXPARA, MFLG_SLOW, 0,
545 { m_unregistered, m_not_oper, m_ignore, me_gungline, mo_gungline, m_ignore }
546 };
547
548 static void
549 module_init(void)
550 {
551 mod_add_cmd(&gline_msgtab);
552 mod_add_cmd(&ungline_msgtab);
553 add_capability("GLN", CAP_GLN, 1);
554 }
555
556 static void
557 module_exit(void)
558 {
559 mod_del_cmd(&gline_msgtab);
560 mod_del_cmd(&ungline_msgtab);
561 delete_capability("GLN");
562 }
563
564 struct module module_entry = {
565 .node = { NULL, NULL, NULL },
566 .name = NULL,
567 .version = "$Revision$",
568 .handle = NULL,
569 .modinit = module_init,
570 .modexit = module_exit,
571 .flags = 0
572 };

Properties

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

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