ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_gline.c
Revision: 1482
Committed: Tue Jul 24 18:17:54 2012 UTC (14 years, 2 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/modules/m_gline.c
File size: 18349 byte(s)
Log Message:
- m_gline.c: hybrid 6 GLINE compatibility mode has been removed

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

Properties

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