summaryrefslogtreecommitdiff
path: root/modules/m_dline.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/m_dline.c')
-rw-r--r--modules/m_dline.c592
1 files changed, 592 insertions, 0 deletions
diff --git a/modules/m_dline.c b/modules/m_dline.c
new file mode 100644
index 0000000..182489b
--- /dev/null
+++ b/modules/m_dline.c
@@ -0,0 +1,592 @@
+/*
+ * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
+ * m_dline.c: Bans a user.
+ *
+ * Copyright (C) 2002 by the past and present ircd coders, and others.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * $Id$
+ */
+
+#include "stdinc.h"
+#include "list.h"
+#include "channel.h"
+#include "client.h"
+#include "irc_string.h"
+#include "sprintf_irc.h"
+#include "ircd.h"
+#include "hostmask.h"
+#include "numeric.h"
+#include "fdlist.h"
+#include "s_bsd.h"
+#include "conf.h"
+#include "log.h"
+#include "s_misc.h"
+#include "send.h"
+#include "hash.h"
+#include "s_serv.h"
+#include "s_gline.h"
+#include "parse.h"
+#include "modules.h"
+
+
+/* apply_tdline()
+ *
+ * inputs -
+ * output - NONE
+ * side effects - tkline as given is placed
+ */
+static void
+apply_tdline(struct Client *source_p, struct ConfItem *conf,
+ const char *current_date, int tkline_time)
+{
+ struct AccessItem *aconf;
+
+ aconf = map_to_conf(conf);
+ aconf->hold = CurrentTime + tkline_time;
+ SetConfTemporary(aconf);
+ add_conf_by_address(CONF_DLINE, aconf);
+
+
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s added temporary %d min. D-Line for [%s] [%s]",
+ get_oper_name(source_p), tkline_time/60,
+ aconf->host, aconf->reason);
+
+ sendto_one(source_p, ":%s NOTICE %s :Added temporary %d min. D-Line [%s]",
+ MyConnect(source_p) ? me.name : ID_or_name(&me, source_p->from),
+ source_p->name, tkline_time/60, aconf->host);
+ ilog(LOG_TYPE_DLINE, "%s added temporary %d min. D-Line for [%s] [%s]",
+ source_p->name, tkline_time/60, aconf->host, aconf->reason);
+
+ rehashed_klines = 1;
+}
+
+/* static int remove_tdline_match(const char *host, const char *user)
+ * Input: An ip to undline.
+ * Output: returns YES on success, NO if no tdline removed.
+ * Side effects: Any matching tdlines are removed.
+ */
+static int
+remove_tdline_match(const char *host)
+{
+ struct irc_ssaddr iphost, *piphost;
+ struct AccessItem *aconf;
+ int t;
+
+ if ((t = parse_netmask(host, &iphost, NULL)) != HM_HOST)
+ {
+#ifdef IPV6
+ if (t == HM_IPV6)
+ t = AF_INET6;
+ else
+#endif
+ t = AF_INET;
+ piphost = &iphost;
+ }
+ else
+ {
+ t = 0;
+ piphost = NULL;
+ }
+
+ if ((aconf = find_conf_by_address(host, piphost, CONF_DLINE, t, NULL, NULL, 0)))
+ {
+ if (IsConfTemporary(aconf))
+ {
+ delete_one_address_conf(host, aconf);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* mo_dline()
+ *
+ * inputs - pointer to server
+ * - pointer to client
+ * - parameter count
+ * - parameter list
+ * output -
+ * side effects - D line is added
+ *
+ */
+static void
+mo_dline(struct Client *client_p, struct Client *source_p,
+ int parc, char *parv[])
+{
+ char def_reason[] = "<No reason specified>";
+ char *dlhost = NULL, *oper_reason = NULL, *reason = NULL;
+ char *target_server = NULL;
+ const char *creason;
+ const struct Client *target_p = NULL;
+ struct irc_ssaddr daddr;
+ struct ConfItem *conf=NULL;
+ struct AccessItem *aconf=NULL;
+ time_t tkline_time=0;
+ int bits, t;
+ const char *current_date = NULL;
+ time_t cur_time;
+ char hostip[HOSTIPLEN + 1];
+ char buffer[IRCD_BUFSIZE];
+
+ if (!HasOFlag(source_p, OPER_FLAG_DLINE))
+ {
+ sendto_one(source_p, form_str(ERR_NOPRIVS),
+ me.name, source_p->name, "dline");
+ return;
+ }
+
+ if (parse_aline("DLINE", source_p, parc, parv, AWILD, &dlhost,
+ NULL, &tkline_time, &target_server, &reason) < 0)
+ return;
+
+ if (target_server != NULL)
+ {
+ if (HasID(source_p))
+ {
+ sendto_server(NULL, CAP_DLN|CAP_TS6, NOCAPS,
+ ":%s DLINE %s %lu %s :%s",
+ source_p->id, target_server, (unsigned long)tkline_time,
+ dlhost, reason);
+ sendto_server(NULL, CAP_DLN, CAP_TS6,
+ ":%s DLINE %s %lu %s :%s",
+ source_p->name, target_server, (unsigned long)tkline_time,
+ dlhost, reason);
+ }
+ else
+ sendto_server(NULL, CAP_DLN, NOCAPS,
+ ":%s DLINE %s %lu %s :%s",
+ source_p->name, target_server, (unsigned long)tkline_time,
+ dlhost, reason);
+
+ /* Allow ON to apply local kline as well if it matches */
+ if (!match(target_server, me.name))
+ return;
+ }
+ else
+ cluster_a_line(source_p, "DLINE", CAP_DLN, SHARED_DLINE,
+ "%d %s :%s", tkline_time, dlhost, reason);
+
+ if ((t = parse_netmask(dlhost, NULL, &bits)) == HM_HOST)
+ {
+ if ((target_p = find_chasing(client_p, source_p, dlhost, NULL)) == NULL)
+ return;
+
+ if (!MyConnect(target_p))
+ {
+ sendto_one(source_p,
+ ":%s NOTICE %s :Can't DLINE nick on another server",
+ me.name, source_p->name);
+ return;
+ }
+
+ if (IsExemptKline(target_p))
+ {
+ sendto_one(source_p,
+ ":%s NOTICE %s :%s is E-lined", me.name,
+ source_p->name, target_p->name);
+ return;
+ }
+
+ getnameinfo((struct sockaddr *)&target_p->localClient->ip,
+ target_p->localClient->ip.ss_len, hostip,
+ sizeof(hostip), NULL, 0, NI_NUMERICHOST);
+ dlhost = hostip;
+ t = parse_netmask(dlhost, NULL, &bits);
+ assert(t == HM_IPV4 || t == HM_IPV6);
+ }
+
+ if (bits < 8)
+ {
+ sendto_one(source_p,
+ ":%s NOTICE %s :For safety, bitmasks less than 8 require conf access.",
+ me.name, source_p->name);
+ return;
+ }
+
+#ifdef IPV6
+ if (t == HM_IPV6)
+ t = AF_INET6;
+ else
+#endif
+ t = AF_INET;
+
+ parse_netmask(dlhost, &daddr, NULL);
+
+ if ((aconf = find_dline_conf(&daddr, t)) != NULL)
+ {
+ creason = aconf->reason ? aconf->reason : def_reason;
+ if (IsConfExemptKline(aconf))
+ sendto_one(source_p,
+ ":%s NOTICE %s :[%s] is (E)d-lined by [%s] - %s",
+ me.name, source_p->name, dlhost, aconf->host, creason);
+ else
+ sendto_one(source_p,
+ ":%s NOTICE %s :[%s] already D-lined by [%s] - %s",
+ me.name, source_p->name, dlhost, aconf->host, creason);
+ return;
+ }
+
+ cur_time = CurrentTime;
+ current_date = smalldate(cur_time);
+
+ /* Look for an oper reason */
+ if ((oper_reason = strchr(reason, '|')) != NULL)
+ *oper_reason++ = '\0';
+
+ if (!valid_comment(source_p, reason, 1))
+ return;
+
+ conf = make_conf_item(DLINE_TYPE);
+ aconf = map_to_conf(conf);
+ DupString(aconf->host, dlhost);
+
+ if (tkline_time != 0)
+ {
+ snprintf(buffer, sizeof(buffer), "Temporary D-line %d min. - %s (%s)",
+ (int)(tkline_time/60), reason, current_date);
+ DupString(aconf->reason, buffer);
+ if (oper_reason != NULL)
+ DupString(aconf->oper_reason, oper_reason);
+ apply_tdline(source_p, conf, current_date, tkline_time);
+ }
+ else
+ {
+ snprintf(buffer, sizeof(buffer), "%s (%s)", reason, current_date);
+ DupString(aconf->reason, buffer);
+ if (oper_reason != NULL)
+ DupString(aconf->oper_reason, oper_reason);
+ add_conf_by_address(CONF_DLINE, aconf);
+ write_conf_line(source_p, conf, current_date, cur_time);
+ }
+
+ rehashed_klines = 1;
+}
+
+static void
+ms_dline(struct Client *client_p, struct Client *source_p,
+ int parc, char *parv[])
+{
+ char def_reason[] = "<No reason specified>";
+ char *dlhost, *oper_reason, *reason;
+ const char *creason;
+ const struct Client *target_p = NULL;
+ struct irc_ssaddr daddr;
+ struct ConfItem *conf=NULL;
+ struct AccessItem *aconf=NULL;
+ time_t tkline_time=0;
+ int bits, t;
+ const char *current_date = NULL;
+ time_t cur_time;
+ char hostip[HOSTIPLEN + 1];
+ char buffer[IRCD_BUFSIZE];
+
+ if (parc != 5 || EmptyString(parv[4]))
+ return;
+
+ /* parv[0] parv[1] parv[2] parv[3] parv[4] */
+ /* oper target_server tkline_time host reason */
+ sendto_match_servs(source_p, parv[1], CAP_DLN,
+ "DLINE %s %s %s :%s",
+ parv[1], parv[2], parv[3], parv[4]);
+
+ if (!match(parv[1], me.name))
+ return;
+
+ tkline_time = valid_tkline(parv[2], TK_SECONDS);
+ dlhost = parv[3];
+ reason = parv[4];
+
+ if (HasFlag(source_p, FLAGS_SERVICE) || find_matching_name_conf(ULINE_TYPE, source_p->servptr->name,
+ source_p->username, source_p->host,
+ SHARED_DLINE))
+ {
+ if (!IsClient(source_p))
+ return;
+ if ((t = parse_netmask(dlhost, NULL, &bits)) == HM_HOST)
+ {
+ if ((target_p = find_chasing(client_p, source_p, dlhost, NULL)) == NULL)
+ return;
+
+ if (!MyConnect(target_p))
+ {
+ sendto_one(source_p,
+ ":%s NOTICE %s :Can't DLINE nick on another server",
+ me.name, source_p->name);
+ return;
+ }
+
+ if (IsExemptKline(target_p))
+ {
+ sendto_one(source_p,
+ ":%s NOTICE %s :%s is E-lined", me.name,
+ source_p->name, target_p->name);
+ return;
+ }
+
+ getnameinfo((struct sockaddr *)&target_p->localClient->ip,
+ target_p->localClient->ip.ss_len, hostip,
+ sizeof(hostip), NULL, 0, NI_NUMERICHOST);
+ dlhost = hostip;
+ t = parse_netmask(dlhost, NULL, &bits);
+ assert(t == HM_IPV4 || t == HM_IPV6);
+ }
+
+ if (bits < 8)
+ {
+ sendto_one(source_p,
+ ":%s NOTICE %s :For safety, bitmasks less than 8 require conf access.",
+ me.name, source_p->name);
+ return;
+ }
+
+#ifdef IPV6
+ if (t == HM_IPV6)
+ t = AF_INET6;
+ else
+#endif
+ t = AF_INET;
+
+ parse_netmask(dlhost, &daddr, NULL);
+
+ if ((aconf = find_dline_conf(&daddr, t)) != NULL)
+ {
+ creason = aconf->reason ? aconf->reason : def_reason;
+ if (IsConfExemptKline(aconf))
+ sendto_one(source_p,
+ ":%s NOTICE %s :[%s] is (E)d-lined by [%s] - %s",
+ me.name, source_p->name, dlhost, aconf->host, creason);
+ else
+ sendto_one(source_p,
+ ":%s NOTICE %s :[%s] already D-lined by [%s] - %s",
+ me.name, source_p->name, dlhost, aconf->host, creason);
+ return;
+ }
+
+ cur_time = CurrentTime;
+ current_date = smalldate(cur_time);
+
+ /* Look for an oper reason */
+ if ((oper_reason = strchr(reason, '|')) != NULL)
+ *oper_reason++ = '\0';
+
+ if (!valid_comment(source_p, reason, 1))
+ return;
+
+ conf = make_conf_item(DLINE_TYPE);
+ aconf = map_to_conf(conf);
+ DupString(aconf->host, dlhost);
+
+ if (tkline_time != 0)
+ {
+ snprintf(buffer, sizeof(buffer), "Temporary D-line %d min. - %s (%s)",
+ (int)(tkline_time/60), reason, current_date);
+ DupString(aconf->reason, buffer);
+ if (oper_reason != NULL)
+ DupString(aconf->oper_reason, oper_reason);
+ apply_tdline(source_p, conf, current_date, tkline_time);
+ }
+ else
+ {
+ snprintf(buffer, sizeof(buffer), "%s (%s)", reason, current_date);
+ DupString(aconf->reason, buffer);
+ if (oper_reason != NULL)
+ DupString(aconf->oper_reason, oper_reason);
+ add_conf_by_address(CONF_DLINE, aconf);
+ write_conf_line(source_p, conf, current_date, cur_time);
+ }
+
+ rehashed_klines = 1;
+ }
+}
+
+/*
+** m_undline
+** added May 28th 2000 by Toby Verrall <toot@melnet.co.uk>
+** based totally on m_unkline
+** added to hybrid-7 7/11/2000 --is
+**
+** parv[0] = sender nick
+** parv[1] = dline to remove
+*/
+static void
+mo_undline(struct Client *client_p, struct Client *source_p,
+ int parc, char *parv[])
+{
+ char *addr = NULL, *user = NULL;
+ char *target_server = NULL;
+
+ if (!HasOFlag(source_p, OPER_FLAG_UNDLINE))
+ {
+ sendto_one(source_p, form_str(ERR_NOPRIVS),
+ me.name, source_p->name, "undline");
+ return;
+ }
+
+ if (parc < 2 || EmptyString(parv[1]))
+ {
+ sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
+ me.name, source_p->name, "UNDLINE");
+ return;
+ }
+
+ if (parse_aline("UNDLINE", source_p, parc, parv, 0, &user,
+ &addr, NULL, &target_server, NULL) < 0)
+ return;
+
+ if (target_server != NULL)
+ {
+ sendto_match_servs(source_p, target_server, CAP_UNDLN,
+ "UNDLINE %s %s", target_server, addr);
+
+ /* Allow ON to apply local unkline as well if it matches */
+ if (!match(target_server, me.name))
+ return;
+ }
+ else
+ cluster_a_line(source_p, "UNDLINE", CAP_UNDLN, SHARED_UNDLINE,
+ "%s", addr);
+
+ if (remove_tdline_match(addr))
+ {
+ sendto_one(source_p,
+ ":%s NOTICE %s :Un-Dlined [%s] from temporary D-Lines",
+ me.name, source_p->name, addr);
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s has removed the temporary D-Line for: [%s]",
+ get_oper_name(source_p), addr);
+ ilog(LOG_TYPE_DLINE, "%s removed temporary D-Line for [%s]",
+ source_p->name, addr);
+ return;
+ }
+
+ if (remove_conf_line(DLINE_TYPE, source_p, addr, NULL) > 0)
+ {
+ sendto_one(source_p, ":%s NOTICE %s :D-Line for [%s] is removed",
+ me.name, source_p->name, addr);
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s has removed the D-Line for: [%s]",
+ get_oper_name(source_p), addr);
+ ilog(LOG_TYPE_DLINE, "%s removed D-Line for [%s]",
+ get_oper_name(source_p), addr);
+ }
+ else
+ sendto_one(source_p, ":%s NOTICE %s :No D-Line for [%s] found",
+ me.name, source_p->name, addr);
+}
+
+static void
+me_undline(struct Client *client_p, struct Client *source_p,
+ int parc, char *parv[])
+{
+ const char *addr = NULL;
+
+ if (parc != 3 || EmptyString(parv[2]))
+ return;
+
+ addr = parv[2];
+
+ if (!IsClient(source_p) || !match(parv[1], me.name))
+ return;
+
+ if (HasFlag(source_p, FLAGS_SERVICE) || find_matching_name_conf(ULINE_TYPE,
+ source_p->servptr->name,
+ source_p->username, source_p->host,
+ SHARED_UNDLINE))
+ {
+ if (remove_tdline_match(addr))
+ {
+ sendto_one(source_p,
+ ":%s NOTICE %s :Un-Dlined [%s] from temporary D-Lines",
+ me.name, source_p->name, addr);
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s has removed the temporary D-Line for: [%s]",
+ get_oper_name(source_p), addr);
+ ilog(LOG_TYPE_DLINE, "%s removed temporary D-Line for [%s]",
+ source_p->name, addr);
+ return;
+ }
+
+ if (remove_conf_line(DLINE_TYPE, source_p, addr, NULL) > 0)
+ {
+ sendto_one(source_p, ":%s NOTICE %s :D-Line for [%s] is removed",
+ me.name, source_p->name, addr);
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s has removed the D-Line for: [%s]",
+ get_oper_name(source_p), addr);
+ ilog(LOG_TYPE_DLINE, "%s removed D-Line for [%s]",
+ get_oper_name(source_p), addr);
+ }
+ else
+ sendto_one(source_p, ":%s NOTICE %s :No D-Line for [%s] found",
+ me.name, source_p->name, addr);
+ }
+}
+
+static void
+ms_undline(struct Client *client_p, struct Client *source_p,
+ int parc, char *parv[])
+{
+ if (parc != 3 || EmptyString(parv[2]))
+ return;
+
+ sendto_match_servs(source_p, parv[1], CAP_UNDLN,
+ "UNDLINE %s %s %s",
+ parv[1], parv[2]);
+
+ me_undline(client_p, source_p, parc, parv);
+}
+
+static struct Message dline_msgtab = {
+ "DLINE", 0, 0, 2, MAXPARA, MFLG_SLOW, 0,
+ {m_unregistered, m_not_oper, ms_dline, m_ignore, mo_dline, m_ignore}
+};
+
+static struct Message undline_msgtab = {
+ "UNDLINE", 0, 0, 2, MAXPARA, MFLG_SLOW, 0,
+ {m_unregistered, m_not_oper, ms_undline, m_ignore, mo_undline, m_ignore}
+};
+
+static void
+module_init(void)
+{
+ mod_add_cmd(&dline_msgtab);
+ mod_add_cmd(&undline_msgtab);
+ add_capability("DLN", CAP_DLN, 1);
+ add_capability("UNDLN", CAP_UNDLN, 1);
+}
+
+static void
+module_exit(void)
+{
+ mod_del_cmd(&dline_msgtab);
+ mod_del_cmd(&undline_msgtab);
+ delete_capability("UNDLN");
+ delete_capability("DLN");
+}
+
+struct module module_entry = {
+ .node = { NULL, NULL, NULL },
+ .name = NULL,
+ .version = "$Revision$",
+ .handle = NULL,
+ .modinit = module_init,
+ .modexit = module_exit,
+ .flags = 0
+};