ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_gline.c
Revision: 1666
Committed: Sun Nov 18 17:03:18 2012 UTC (12 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 18374 byte(s)
Log Message:
- Cleanup unused header file includes
- Fixed minor compile warning in conf.c

File Contents

# User Rev Content
1 adx 30 /*
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 michael 1008 /*! \file m_gline.c
23     * \brief Includes required functions for processing the GLINE command.
24     * \version $Id$
25     */
26    
27 adx 30 #include "stdinc.h"
28 michael 1011 #include "list.h"
29 adx 30 #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 michael 1632 #include "conf.h"
36 adx 30 #include "hostmask.h"
37     #include "numeric.h"
38     #include "s_bsd.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 michael 1309 #include "log.h"
46 michael 1622 #include "conf_db.h"
47 michael 1666 #include "memory.h"
48 adx 30
49     #define GLINE_NOT_PLACED 0
50     #define GLINE_ALREADY_VOTED -1
51     #define GLINE_PLACED 1
52    
53    
54 michael 1009 /*! \brief Adds a GLINE to the configuration subsystem.
55     *
56     * \param source_p Operator requesting gline
57     * \param user Username covered by the gline
58     * \param host Hostname covered by the gline
59     * \param reason Reason for the gline
60     */
61     static void
62     set_local_gline(const struct Client *source_p, const char *user,
63     const char *host, const char *reason)
64     {
65     char buffer[IRCD_BUFSIZE];
66 michael 1632 struct MaskItem *conf = conf_make(CONF_GLINE);
67 michael 1008
68 michael 1009 snprintf(buffer, sizeof(buffer), "%s (%s)", reason, smalldate(CurrentTime));
69 michael 1646 conf->reason = xstrdup(buffer);
70     conf->user = xstrdup(user);
71     conf->host = xstrdup(host);
72 michael 1009
73 michael 1632 conf->setat = CurrentTime;
74 michael 1649 conf->until = CurrentTime + ConfigFileEntry.gline_time;
75 michael 1632 SetConfDatabase(conf);
76 michael 1009
77 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
78 michael 1009 "%s added G-Line for [%s@%s] [%s]",
79     get_oper_name(source_p),
80 michael 1632 conf->user, conf->host, conf->reason);
81 michael 1247 ilog(LOG_TYPE_GLINE, "%s added G-Line for [%s@%s] [%s]",
82 michael 1632 get_oper_name(source_p), conf->user, conf->host, conf->reason);
83 michael 1247
84 michael 1632 add_conf_by_address(CONF_GLINE, conf);
85 michael 1009 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 michael 1369 struct irc_ssaddr iphost, *piphost;
97 michael 1632 struct MaskItem *conf;
98 michael 1644 int t = 0;
99     int aftype = 0;
100 michael 1009
101 michael 1369 if ((t = parse_netmask(host, &iphost, NULL)) != HM_HOST)
102 michael 1009 {
103     #ifdef IPV6
104 michael 1369 if (t == HM_IPV6)
105 michael 1644 aftype = AF_INET6;
106 michael 1369 else
107 michael 1009 #endif
108 michael 1644 aftype = AF_INET;
109 michael 1369 piphost = &iphost;
110     }
111     else
112     piphost = NULL;
113    
114 michael 1644 if ((conf = find_conf_by_address(host, piphost, CONF_GLINE, aftype, user, NULL, 0)))
115 michael 1369 {
116 michael 1632 if (IsConfDatabase(conf))
117 michael 1628 {
118 michael 1632 delete_one_address_conf(host, conf);
119 michael 1628 return 1;
120     }
121 michael 1009 }
122    
123     return 0;
124     }
125    
126 michael 1008 /*! \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 adx 30 *
132 michael 1008 * \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 adx 30 */
139 michael 1008 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 adx 30 *
164 michael 1008 * \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 adx 30 */
176 michael 1008 static int
177     check_majority(const struct Client *source_p, const char *user,
178     const char *host, const char *reason, const int type)
179 adx 30 {
180 michael 1008 dlink_node *dn_ptr = NULL;
181 adx 30
182 michael 1008 cleanup_glines(NULL);
183 adx 30
184 michael 1008 /* 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 adx 30 {
190 michael 1008 struct gline_pending *gp_ptr = dn_ptr->data;
191 adx 30
192 michael 1008 if (irccmp(gp_ptr->user, user) ||
193     irccmp(gp_ptr->host, host))
194     continue;
195 adx 30
196 michael 1008 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 adx 30 {
203 michael 1008 /* 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 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
214 michael 1008 "%s has removed the G-Line for: [%s@%s]",
215     get_oper_name(source_p), user, host);
216 michael 1247 ilog(LOG_TYPE_GLINE, "%s removed G-Line for [%s@%s]",
217 michael 1008 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 adx 30 }
227 michael 1008
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 adx 30 }
242    
243 michael 552 /*
244 michael 1008 * Didn't find this user@host gline in pending gline list
245     * so add it.
246 adx 30 */
247 michael 1008 add_new_majority(source_p, user, host, reason, type);
248     return GLINE_NOT_PLACED;
249 adx 30 }
250    
251     static void
252 michael 1008 do_sgline(struct Client *source_p, int parc, char *parv[], int prop)
253 adx 30 {
254     const char *reason = NULL; /* reason for "victims" demise */
255 michael 1463 const char *user = NULL;
256     const char *host = NULL; /* user and host of GLINE "victim" */
257 adx 30
258 michael 1482 if (!IsClient(source_p))
259     return;
260 adx 30
261 michael 1482 if (parc != 4 || EmptyString(parv[3]))
262     return;
263    
264 adx 30 assert(source_p->servptr != NULL);
265    
266 michael 1482 user = parv[1];
267     host = parv[2];
268     reason = parv[3];
269 adx 30
270 michael 1474 sendto_server(source_p->from, CAP_GLN|CAP_TS6, NOCAPS,
271 michael 1459 ":%s GLINE %s %s :%s",
272 michael 1463 ID(source_p), user, host, reason);
273 michael 1474 sendto_server(source_p->from, CAP_GLN, CAP_TS6,
274 michael 1463 ":%s GLINE %s %s :%s",
275 michael 1459 source_p->name, user, host, reason);
276 michael 1463
277 adx 30 if (ConfigFileEntry.glines)
278     {
279 michael 1243 if (!valid_wild_card(source_p, 1, 2, user, host))
280 adx 30 return;
281    
282     if (IsClient(source_p))
283     {
284     const char *p = NULL;
285 michael 958
286 adx 30 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 michael 1618 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 adx 30 return;
299     }
300     }
301     }
302    
303     /* If at least 3 opers agree this user should be G lined then do it */
304 michael 988 if (check_majority(source_p, user, host, reason, GLINE_PENDING_ADD_TYPE) ==
305 adx 30 GLINE_ALREADY_VOTED)
306     {
307 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
308     "oper or server has already voted");
309 adx 30 return;
310     }
311    
312 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
313 michael 554 "%s requesting G-Line for [%s@%s] [%s]",
314     get_oper_name(source_p),
315     user, host, reason);
316 michael 1247 ilog(LOG_TYPE_GLINE, "#gline for %s@%s [%s] requested by %s",
317 adx 30 user, host, reason, get_oper_name(source_p));
318     }
319     }
320    
321 michael 1008
322     /*! \brief GLINE command handler (called by operators)
323 adx 30 *
324 michael 1008 * \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 adx 30 */
336     static void
337 michael 1008 mo_gline(struct Client *client_p, struct Client *source_p,
338     int parc, char *parv[])
339 adx 30 {
340 michael 1008 char *user = NULL;
341     char *host = NULL;
342     char *reason = NULL;
343     char *p;
344 adx 30
345 michael 1463 if (!HasOFlag(source_p, OPER_FLAG_GLINE))
346 michael 1008 {
347 michael 1463 sendto_one(source_p, form_str(ERR_NOPRIVS),
348     me.name, source_p->name, "gline");
349 michael 1008 return;
350     }
351 adx 30
352 michael 1463 if (!ConfigFileEntry.glines)
353 michael 1008 {
354 michael 1463 sendto_one(source_p, ":%s NOTICE %s :GLINE disabled",
355     me.name, source_p->name);
356 michael 1008 return;
357     }
358 adx 30
359 michael 1008 if (parse_aline("GLINE", source_p, parc, parv, AWILD,
360     &user, &host, NULL, NULL, &reason) < 0)
361     return;
362 adx 30
363 michael 1008 if ((p = strchr(host, '/')) != NULL)
364 adx 30 {
365 michael 1008 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 adx 30 {
370 michael 1008 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 michael 957 }
374 adx 30 }
375 michael 1008
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 adx 30
386 michael 957 /*
387 michael 1008 * call these two functions first so the 'requesting' notice always comes
388     * before the 'has triggered' notice. -bill
389 adx 30 */
390 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
391 michael 1008 "%s requesting G-Line for [%s@%s] [%s]",
392     get_oper_name(source_p),
393     user, host, reason);
394 michael 1247 ilog(LOG_TYPE_GLINE, "#gline for %s@%s [%s] requested by %s!%s@%s",
395 michael 1008 user, host, reason, source_p->name, source_p->username,
396     source_p->host);
397 adx 30
398 michael 1008 /* 4 param version for hyb-7 servers */
399 michael 1474 sendto_server(NULL, CAP_GLN|CAP_TS6, NOCAPS,
400 michael 1008 ":%s GLINE %s %s :%s",
401     ID(source_p), user, host, reason);
402 michael 1474 sendto_server(NULL, CAP_GLN, CAP_TS6,
403 michael 1008 ":%s GLINE %s %s :%s",
404     source_p->name, user, host, reason);
405 adx 30 }
406    
407 michael 1008 /* ms_gline()
408     * me_gline()
409     * do_sgline()
410 db 937 *
411     * inputs - The usual for a m_ function
412     * output -
413     * side effects -
414     *
415 michael 1008 * Place a G line if 3 opers agree on the identical user@host
416 db 937 *
417 michael 1008 * 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 db 937 */
422    
423     static void
424 michael 1008 ms_gline(struct Client *client_p, struct Client *source_p,
425     int parc, char *parv[])
426 db 937 {
427 michael 1008 do_sgline(source_p, parc, parv, 1);
428 db 937 }
429    
430     static void
431 michael 1008 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 michael 1006 do_sungline(struct Client *source_p, const char *user,
439     const char *host, const char *reason, int prop)
440 db 937 {
441     assert(source_p->servptr != NULL);
442    
443 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
444 michael 957 "%s requesting UNG-Line for [%s@%s] [%s]",
445 michael 1006 get_oper_name(source_p), user, host, reason);
446 michael 1247 ilog(LOG_TYPE_GLINE, "#ungline for %s@%s [%s] requested by %s",
447 michael 957 user, host, reason, get_oper_name(source_p));
448 db 937
449 michael 957 /* If at least 3 opers agree this user should be un G lined then do it */
450 michael 958 if (check_majority(source_p, user, host, reason, GLINE_PENDING_DEL_TYPE) ==
451 michael 957 GLINE_ALREADY_VOTED)
452 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
453     "oper or server has already voted");
454 michael 1006
455     if (prop)
456     {
457 michael 1474 sendto_server(source_p->from, CAP_ENCAP|CAP_TS6, NOCAPS,
458 michael 1006 ":%s ENCAP * GUNGLINE %s %s :%s",
459     ID(source_p), user, host, reason);
460 michael 1474 sendto_server(source_p->from, CAP_ENCAP, CAP_TS6,
461 michael 1006 ":%s ENCAP * GUNGLINE %s %s :%s",
462     source_p->name, user, host, reason);
463     }
464 db 937 }
465    
466 michael 1008 /*! \brief GUNGLINE command handler (called in response to an encapsulated
467     * GUNGLINE command)
468 db 937 *
469 michael 1008 * \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 db 937 */
482 michael 1008 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 db 937 *
492 michael 1008 * \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 db 937 */
504     static void
505 db 940 mo_gungline(struct Client *client_p, struct Client *source_p,
506 michael 957 int parc, char *parv[])
507 db 937 {
508     char *user = NULL;
509 michael 1008 char *host = NULL;
510     char *reason = NULL;
511 db 937
512 michael 1463 if (!HasOFlag(source_p, OPER_FLAG_GLINE))
513 db 937 {
514 michael 1463 sendto_one(source_p, form_str(ERR_NOPRIVS),
515     me.name, source_p->name, "gline");
516 db 937 return;
517     }
518    
519 michael 1463 if (!ConfigFileEntry.glines)
520 db 937 {
521 michael 1463 sendto_one(source_p, ":%s NOTICE %s :GUNGLINE disabled",
522     me.name, source_p->name);
523 db 937 return;
524     }
525    
526 michael 957 if (parse_aline("GUNGLINE", source_p, parc, parv, 0, &user,
527     &host, NULL, NULL, &reason) < 0)
528 db 937 return;
529    
530 michael 1006 do_sungline(source_p, user, host, reason, 1);
531 db 937 }
532 michael 1230
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