summaryrefslogtreecommitdiff
path: root/modules/m_kline.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/m_kline.c')
-rw-r--r--modules/m_kline.c563
1 files changed, 563 insertions, 0 deletions
diff --git a/modules/m_kline.c b/modules/m_kline.c
new file mode 100644
index 0000000..8833fe5
--- /dev/null
+++ b/modules/m_kline.c
@@ -0,0 +1,563 @@
+/*
+ * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
+ * m_kline.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"
+
+
+static int already_placed_kline(struct Client *, const char *, const char *, int);
+static void apply_kline(struct Client *, struct ConfItem *, const char *, time_t);
+static void apply_tkline(struct Client *, struct ConfItem *, int);
+
+static char buffer[IRCD_BUFSIZE];
+static int remove_tkline_match(const char *, const char *);
+
+
+/* mo_kline()
+ *
+ * inputs - pointer to server
+ * - pointer to client
+ * - parameter count
+ * - parameter list
+ * output -
+ * side effects - k line is added
+ */
+static void
+mo_kline(struct Client *client_p, struct Client *source_p,
+ int parc, char *parv[])
+{
+ char *reason = NULL;
+ char *oper_reason;
+ char *user = NULL;
+ char *host = NULL;
+ const char *current_date;
+ char *target_server = NULL;
+ struct ConfItem *conf;
+ struct AccessItem *aconf;
+ time_t tkline_time = 0;
+ time_t cur_time;
+
+ if (!HasOFlag(source_p, OPER_FLAG_K))
+ {
+ sendto_one(source_p, form_str(ERR_NOPRIVS),
+ me.name, source_p->name, "kline");
+ return;
+ }
+
+ if (parse_aline("KLINE", source_p, parc, parv,
+ AWILD, &user, &host, &tkline_time, &target_server, &reason) < 0)
+ return;
+
+ if (target_server != NULL)
+ {
+ if (HasID(source_p))
+ {
+ sendto_server(NULL, CAP_KLN|CAP_TS6, NOCAPS,
+ ":%s KLINE %s %lu %s %s :%s",
+ source_p->id, target_server, (unsigned long)tkline_time,
+ user, host, reason);
+ sendto_server(NULL, CAP_KLN, CAP_TS6,
+ ":%s KLINE %s %lu %s %s :%s",
+ source_p->name, target_server, (unsigned long)tkline_time,
+ user, host, reason);
+ }
+ else
+ sendto_server(NULL, CAP_KLN, NOCAPS,
+ ":%s KLINE %s %lu %s %s :%s",
+ source_p->name, target_server, (unsigned long)tkline_time,
+ user, host, 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, "KLINE", CAP_KLN, SHARED_KLINE,
+ "%d %s %s :%s", tkline_time, user, host, reason);
+
+ if (already_placed_kline(source_p, user, host, 1))
+ return;
+
+ /* Look for an oper reason */
+ if ((oper_reason = strchr(reason, '|')) != NULL)
+ *oper_reason++ = '\0';
+
+ cur_time = CurrentTime;
+ current_date = smalldate(cur_time);
+ conf = make_conf_item(KLINE_TYPE);
+ aconf = map_to_conf(conf);
+
+ DupString(aconf->host, host);
+ DupString(aconf->user, user);
+
+ if (tkline_time != 0)
+ {
+ snprintf(buffer, sizeof(buffer), "Temporary K-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_tkline(source_p, conf, 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);
+ apply_kline(source_p, conf, current_date, cur_time);
+ }
+}
+
+/* me_kline - handle remote kline. no propagation */
+static void
+me_kline(struct Client *client_p, struct Client *source_p,
+ int parc, char *parv[])
+{
+ struct ConfItem *conf=NULL;
+ struct AccessItem *aconf=NULL;
+ int tkline_time;
+ const char* current_date;
+ time_t cur_time;
+ char *kuser, *khost, *kreason, *oper_reason;
+
+ if (parc != 6 || EmptyString(parv[5]))
+ return;
+
+ if (!match(parv[1], me.name))
+ return;
+
+ tkline_time = valid_tkline(parv[2], TK_SECONDS);
+ kuser = parv[3];
+ khost = parv[4];
+ kreason = parv[5];
+
+ if ((oper_reason = strchr(kreason, '|')) != NULL)
+ *oper_reason++ = '\0';
+
+ cur_time = CurrentTime;
+ current_date = smalldate(cur_time);
+
+ if (HasFlag(source_p, FLAGS_SERVICE) || find_matching_name_conf(ULINE_TYPE, source_p->servptr->name,
+ source_p->username, source_p->host,
+ SHARED_KLINE))
+ {
+ if (!IsClient(source_p) ||
+ already_placed_kline(source_p, kuser, khost, 1))
+ return;
+
+ conf = make_conf_item(KLINE_TYPE);
+ aconf = map_to_conf(conf);
+ DupString(aconf->host, khost);
+ DupString(aconf->user, kuser);
+
+ if (tkline_time != 0)
+ {
+ snprintf(buffer, sizeof(buffer), "Temporary K-line %d min. - %s (%s)",
+ (int)(tkline_time/60), kreason, current_date);
+ DupString(aconf->reason, buffer);
+
+ if (oper_reason != NULL)
+ DupString(aconf->oper_reason, oper_reason);
+ apply_tkline(source_p, conf, tkline_time);
+ }
+ else
+ {
+ snprintf(buffer, sizeof(buffer), "%s (%s)", kreason, current_date);
+ DupString(aconf->reason, buffer);
+
+ if (oper_reason != NULL)
+ DupString(aconf->oper_reason, oper_reason);
+ apply_kline(source_p, conf, current_date, cur_time);
+ }
+ }
+}
+
+static void
+ms_kline(struct Client *client_p, struct Client *source_p,
+ int parc, char *parv[])
+{
+ if (parc != 6 || EmptyString(parv[5]))
+ return;
+
+ /* parv[0] parv[1] parv[2] parv[3] parv[4] parv[5] */
+ /* oper target_server tkline_time user host reason */
+ sendto_match_servs(source_p, parv[1], CAP_KLN,
+ "KLINE %s %s %s %s :%s",
+ parv[1], parv[2], parv[3], parv[4], parv[5]);
+
+ me_kline(client_p, source_p, parc, parv);
+}
+
+/* apply_kline()
+ *
+ * inputs -
+ * output - NONE
+ * side effects - kline as given, is added to the hashtable
+ * and conf file
+ */
+static void
+apply_kline(struct Client *source_p, struct ConfItem *conf,
+ const char *current_date, time_t cur_time)
+{
+ struct AccessItem *aconf = map_to_conf(conf);
+
+ add_conf_by_address(CONF_KLINE, aconf);
+ write_conf_line(source_p, conf, current_date, cur_time);
+ /* Now, activate kline against current online clients */
+ rehashed_klines = 1;
+}
+
+/* apply_tkline()
+ *
+ * inputs -
+ * output - NONE
+ * side effects - tkline as given is placed
+ */
+static void
+apply_tkline(struct Client *source_p, struct ConfItem *conf,
+ int tkline_time)
+{
+ struct AccessItem *aconf;
+
+ aconf = (struct AccessItem *)map_to_conf(conf);
+ aconf->hold = CurrentTime + tkline_time;
+ SetConfTemporary(aconf);
+ add_conf_by_address(CONF_KLINE, aconf);
+
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s added temporary %d min. K-Line for [%s@%s] [%s]",
+ get_oper_name(source_p), tkline_time/60,
+ aconf->user, aconf->host,
+ aconf->reason);
+ sendto_one(source_p, ":%s NOTICE %s :Added temporary %d min. K-Line [%s@%s]",
+ MyConnect(source_p) ? me.name : ID_or_name(&me, source_p->from),
+ source_p->name, tkline_time/60, aconf->user, aconf->host);
+ ilog(LOG_TYPE_KLINE, "%s added temporary %d min. K-Line for [%s@%s] [%s]",
+ source_p->name, tkline_time/60,
+ aconf->user, aconf->host, aconf->reason);
+
+ rehashed_klines = 1;
+}
+
+/* already_placed_kline()
+ * inputs - user to complain to, username & host to check for
+ * outputs - returns 1 on existing K-line, 0 if doesn't exist
+ * side effects - notifies source_p if the K-line already exists
+ */
+/*
+ * Note: This currently works if the new K-line is a special case of an
+ * existing K-line, but not the other way round. To do that we would
+ * have to walk the hash and check every existing K-line. -A1kmm.
+ */
+static int
+already_placed_kline(struct Client *source_p, const char *luser, const char *lhost, int warn)
+{
+ const char *reason;
+ struct irc_ssaddr iphost, *piphost;
+ struct AccessItem *aconf;
+ int t;
+
+ if ((t = parse_netmask(lhost, &iphost, &t)) != 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(lhost, piphost, CONF_KLINE, t, luser, NULL, 0)))
+ {
+ if (warn)
+ {
+ reason = aconf->reason ? aconf->reason : "No reason";
+ sendto_one(source_p,
+ ":%s NOTICE %s :[%s@%s] already K-Lined by [%s@%s] - %s",
+ me.name, source_p->name, luser, lhost, aconf->user,
+ aconf->host, reason);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+** mo_unkline
+** Added Aug 31, 1997
+** common (Keith Fralick) fralick@gate.net
+**
+** parv[0] = sender
+** parv[1] = address to remove
+*
+*
+*/
+static void
+mo_unkline(struct Client *client_p,struct Client *source_p,
+ int parc, char *parv[])
+{
+ char *target_server = NULL;
+ char *user, *host;
+
+ if (!HasOFlag(source_p, OPER_FLAG_UNKLINE))
+ {
+ sendto_one(source_p, form_str(ERR_NOPRIVS),
+ me.name, source_p->name, "unkline");
+ return;
+ }
+
+ if (parc < 2 || EmptyString(parv[1]))
+ {
+ sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
+ me.name, source_p->name, "UNKLINE");
+ return;
+ }
+
+ if (parse_aline("UNKLINE", source_p, parc, parv, 0, &user,
+ &host, NULL, &target_server, NULL) < 0)
+ return;
+
+ if (target_server != NULL)
+ {
+ sendto_match_servs(source_p, target_server, CAP_UNKLN,
+ "UNKLINE %s %s %s",
+ target_server, user, host);
+
+ /* Allow ON to apply local unkline as well if it matches */
+ if (!match(target_server, me.name))
+ return;
+ }
+ else
+ cluster_a_line(source_p, "UNKLINE", CAP_UNKLN, SHARED_UNKLINE,
+ "%s %s", user, host);
+
+ if (remove_tkline_match(host, user))
+ {
+ sendto_one(source_p,
+ ":%s NOTICE %s :Un-klined [%s@%s] from temporary K-Lines",
+ me.name, source_p->name, user, host);
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s has removed the temporary K-Line for: [%s@%s]",
+ get_oper_name(source_p), user, host);
+ ilog(LOG_TYPE_KLINE, "%s removed temporary K-Line for [%s@%s]",
+ source_p->name, user, host);
+ return;
+ }
+
+ if (remove_conf_line(KLINE_TYPE, source_p, user, host) > 0)
+ {
+ sendto_one(source_p, ":%s NOTICE %s :K-Line for [%s@%s] is removed",
+ me.name, source_p->name, user,host);
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s has removed the K-Line for: [%s@%s]",
+ get_oper_name(source_p), user, host);
+ ilog(LOG_TYPE_KLINE, "%s removed K-Line for [%s@%s]",
+ source_p->name, user, host);
+ }
+ else
+ sendto_one(source_p, ":%s NOTICE %s :No K-Line for [%s@%s] found",
+ me.name, source_p->name, user, host);
+}
+
+/* me_unkline()
+ *
+ * inputs - server
+ * - client
+ * - parc
+ * - parv
+ * outputs - none
+ * side effects - if server is authorized, kline is removed
+ * does not propagate message
+ */
+static void
+me_unkline(struct Client *client_p, struct Client *source_p,
+ int parc, char *parv[])
+{
+ const char *kuser, *khost;
+
+ if (parc != 4)
+ return;
+
+ kuser = parv[2];
+ khost = parv[3];
+
+ 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_UNKLINE))
+ {
+ if (remove_tkline_match(khost, kuser))
+ {
+ sendto_one(source_p,
+ ":%s NOTICE %s :Un-klined [%s@%s] from temporary K-Lines",
+ me.name, source_p->name, kuser, khost);
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s has removed the temporary K-Line for: [%s@%s]",
+ get_oper_name(source_p), kuser, khost);
+ ilog(LOG_TYPE_KLINE, "%s removed temporary K-Line for [%s@%s]",
+ source_p->name, kuser, khost);
+ return;
+ }
+
+ if (remove_conf_line(KLINE_TYPE, source_p, kuser, khost) > 0)
+ {
+ sendto_one(source_p, ":%s NOTICE %s :K-Line for [%s@%s] is removed",
+ me.name, source_p->name, kuser, khost);
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s has removed the K-Line for: [%s@%s]",
+ get_oper_name(source_p), kuser, khost);
+
+ ilog(LOG_TYPE_KLINE, "%s removed K-Line for [%s@%s]",
+ source_p->name, kuser, khost);
+ }
+ else
+ sendto_one(source_p, ":%s NOTICE %s :No K-Line for [%s@%s] found",
+ me.name, source_p->name, kuser, khost);
+ }
+}
+
+/* ms_unkline - propagates and handles a remote unkline message */
+static void
+ms_unkline(struct Client *client_p, struct Client *source_p,
+ int parc, char *parv[])
+{
+ if (parc != 4)
+ return;
+
+ sendto_match_servs(source_p, parv[1], CAP_UNKLN,
+ "UNKLINE %s %s %s",
+ parv[1], parv[2], parv[3]);
+
+ me_unkline(client_p, source_p, parc, parv);
+}
+
+/* static int remove_tkline_match(const char *host, const char *user)
+ * Input: A hostname, a username to unkline.
+ * Output: returns YES on success, NO if no tkline removed.
+ * Side effects: Any matching tklines are removed.
+ */
+static int
+remove_tkline_match(const char *host, const char *user)
+{
+ 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_KLINE, t, user, NULL, 0)))
+ {
+ if (IsConfTemporary(aconf))
+ {
+ delete_one_address_conf(host, aconf);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static struct Message kline_msgtab = {
+ "KLINE", 0, 0, 2, MAXPARA, MFLG_SLOW, 0,
+ {m_unregistered, m_not_oper, ms_kline, me_kline, mo_kline, m_ignore}
+};
+
+static struct Message unkline_msgtab = {
+ "UNKLINE", 0, 0, 2, MAXPARA, MFLG_SLOW, 0,
+ {m_unregistered, m_not_oper, ms_unkline, me_unkline, mo_unkline, m_ignore}
+};
+
+static void
+module_init(void)
+{
+ mod_add_cmd(&kline_msgtab);
+ mod_add_cmd(&unkline_msgtab);
+ add_capability("KLN", CAP_KLN, 1);
+ add_capability("UNKLN", CAP_UNKLN, 1);
+}
+
+static void
+module_exit(void)
+{
+ mod_del_cmd(&kline_msgtab);
+ mod_del_cmd(&unkline_msgtab);
+ delete_capability("UNKLN");
+ delete_capability("KLN");
+}
+
+struct module module_entry = {
+ .node = { NULL, NULL, NULL },
+ .name = NULL,
+ .version = "$Revision$",
+ .handle = NULL,
+ .modinit = module_init,
+ .modexit = module_exit,
+ .flags = 0
+};