summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2016-06-05 14:24:20 +0100
committerRussell King <rmk+kernel@armlinux.org.uk>2019-07-21 20:59:35 +0100
commit0c7b47e34df24af022c3dca8a572ec373480a634 (patch)
tree33800e305bdba67ed3fd4110d1ebc597689545a5
parent8cab8aa79f5bb7221aee58869b14d6b320a7287a (diff)
Add forcenick support
-rw-r--r--contrib/Makefile.am3
-rw-r--r--contrib/Makefile.in16
-rw-r--r--contrib/m_forcenick.c357
3 files changed, 374 insertions, 2 deletions
diff --git a/contrib/Makefile.am b/contrib/Makefile.am
index 22015c9..65e368c 100644
--- a/contrib/Makefile.am
+++ b/contrib/Makefile.am
@@ -10,6 +10,7 @@ modules_LTLIBRARIES = example_module.la \
m_clearchan.la \
m_ctrace.la \
m_force.la \
+ m_forcenick.la \
m_ltrace.la \
m_ojoin.la \
m_operspy.la \
@@ -22,6 +23,7 @@ m_change_la_LDFLAGS = $(MODULE_FLAGS)
m_clearchan_la_LDFLAGS = $(MODULE_FLAGS)
m_ctrace_la_LDFLAGS = $(MODULE_FLAGS)
m_force_la_LDFLAGS = $(MODULE_FLAGS)
+m_forcenick_la_LDFLAGS = $(MODULE_FLAGS)
m_ltrace_la_LDFLAGS = $(MODULE_FLAGS)
m_ojoin_la_LDFLAGS = $(MODULE_FLAGS)
m_operspy_la_LDFLAGS = $(MODULE_FLAGS)
@@ -35,6 +37,7 @@ m_change_la_SOURCES = m_change.c
m_clearchan_la_SOURCES = m_clearchan.c
m_ctrace_la_SOURCES = m_ctrace.c
m_force_la_SOURCES = m_force.c
+m_forcenick_la_SOURCES = m_forcenick.c
m_ltrace_la_SOURCES = m_ltrace.c
m_ojoin_la_SOURCES = m_ojoin.c
m_operspy_la_SOURCES = m_operspy.c
diff --git a/contrib/Makefile.in b/contrib/Makefile.in
index bd63c4b..73c098a 100644
--- a/contrib/Makefile.in
+++ b/contrib/Makefile.in
@@ -127,6 +127,12 @@ m_force_la_OBJECTS = $(am_m_force_la_OBJECTS)
m_force_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(m_force_la_LDFLAGS) $(LDFLAGS) -o $@
+m_forcenick_la_LIBADD =
+am_m_forcenick_la_OBJECTS = m_forcenick.lo
+m_forcenick_la_OBJECTS = $(am_m_forcenick_la_OBJECTS)
+m_forcenick_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(m_forcenick_la_LDFLAGS) $(LDFLAGS) -o $@
m_ltrace_la_LIBADD =
am_m_ltrace_la_OBJECTS = m_ltrace.lo
m_ltrace_la_OBJECTS = $(am_m_ltrace_la_OBJECTS)
@@ -172,13 +178,13 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(example_module_la_SOURCES) $(ip_cloaking_la_SOURCES) \
$(m_change_la_SOURCES) $(m_clearchan_la_SOURCES) \
- $(m_ctrace_la_SOURCES) $(m_force_la_SOURCES) \
+ $(m_ctrace_la_SOURCES) $(m_force_la_SOURCES) $(m_forcenick_la_SOURCES) \
$(m_ltrace_la_SOURCES) $(m_ojoin_la_SOURCES) \
$(m_operspy_la_SOURCES) $(m_opme_la_SOURCES) \
$(m_webirc_la_SOURCES)
DIST_SOURCES = $(example_module_la_SOURCES) $(ip_cloaking_la_SOURCES) \
$(m_change_la_SOURCES) $(m_clearchan_la_SOURCES) \
- $(m_ctrace_la_SOURCES) $(m_force_la_SOURCES) \
+ $(m_ctrace_la_SOURCES) $(m_force_la_SOURCES) $(m_forcenick_la_SOURCES) \
$(m_ltrace_la_SOURCES) $(m_ojoin_la_SOURCES) \
$(m_operspy_la_SOURCES) $(m_opme_la_SOURCES) \
$(m_webirc_la_SOURCES)
@@ -340,6 +346,7 @@ modules_LTLIBRARIES = example_module.la \
m_clearchan.la \
m_ctrace.la \
m_force.la \
+ m_forcenick.la \
m_ltrace.la \
m_ojoin.la \
m_operspy.la \
@@ -352,6 +359,7 @@ m_change_la_LDFLAGS = $(MODULE_FLAGS)
m_clearchan_la_LDFLAGS = $(MODULE_FLAGS)
m_ctrace_la_LDFLAGS = $(MODULE_FLAGS)
m_force_la_LDFLAGS = $(MODULE_FLAGS)
+m_forcenick_la_LDFLAGS = $(MODULE_FLAGS)
m_ltrace_la_LDFLAGS = $(MODULE_FLAGS)
m_ojoin_la_LDFLAGS = $(MODULE_FLAGS)
m_operspy_la_LDFLAGS = $(MODULE_FLAGS)
@@ -363,6 +371,7 @@ m_change_la_SOURCES = m_change.c
m_clearchan_la_SOURCES = m_clearchan.c
m_ctrace_la_SOURCES = m_ctrace.c
m_force_la_SOURCES = m_force.c
+m_forcenick_la_SOURCES = m_forcenick.c
m_ltrace_la_SOURCES = m_ltrace.c
m_ojoin_la_SOURCES = m_ojoin.c
m_operspy_la_SOURCES = m_operspy.c
@@ -448,6 +457,8 @@ m_ctrace.la: $(m_ctrace_la_OBJECTS) $(m_ctrace_la_DEPENDENCIES) $(EXTRA_m_ctrace
$(m_ctrace_la_LINK) -rpath $(modulesdir) $(m_ctrace_la_OBJECTS) $(m_ctrace_la_LIBADD) $(LIBS)
m_force.la: $(m_force_la_OBJECTS) $(m_force_la_DEPENDENCIES) $(EXTRA_m_force_la_DEPENDENCIES)
$(m_force_la_LINK) -rpath $(modulesdir) $(m_force_la_OBJECTS) $(m_force_la_LIBADD) $(LIBS)
+m_forcenick.la: $(m_forcenick_la_OBJECTS) $(m_forcenick_la_DEPENDENCIES) $(EXTRA_m_forcenick_la_DEPENDENCIES)
+ $(m_forcenick_la_LINK) -rpath $(modulesdir) $(m_forcenick_la_OBJECTS) $(m_forcenick_la_LIBADD) $(LIBS)
m_ltrace.la: $(m_ltrace_la_OBJECTS) $(m_ltrace_la_DEPENDENCIES) $(EXTRA_m_ltrace_la_DEPENDENCIES)
$(m_ltrace_la_LINK) -rpath $(modulesdir) $(m_ltrace_la_OBJECTS) $(m_ltrace_la_LIBADD) $(LIBS)
m_ojoin.la: $(m_ojoin_la_OBJECTS) $(m_ojoin_la_DEPENDENCIES) $(EXTRA_m_ojoin_la_DEPENDENCIES)
@@ -471,6 +482,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m_clearchan.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m_ctrace.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m_force.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m_forcenick.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m_ltrace.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m_ojoin.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m_operspy.Plo@am__quote@
diff --git a/contrib/m_forcenick.c b/contrib/m_forcenick.c
new file mode 100644
index 0000000..6440ae1
--- /dev/null
+++ b/contrib/m_forcenick.c
@@ -0,0 +1,357 @@
+/*
+ * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
+ * m_nick.c: Sets a users nick.
+ *
+ * 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 "client.h"
+#include "hash.h"
+#include "fdlist.h"
+#include "irc_string.h"
+#include "ircd.h"
+#include "conf.h"
+#include "log.h"
+#include "numeric.h"
+#include "channel_mode.h"
+#include "s_user.h"
+#include "hash.h"
+#include "whowas.h"
+#include "s_serv.h"
+#include "send.h"
+#include "list.h"
+#include "channel.h"
+#include "resv.h"
+#include "parse.h"
+#include "modules.h"
+#include "packet.h"
+#include "watch.h"
+
+static char buf[IRCD_BUFSIZE];
+
+static int m_forcenick(struct Client *, struct Client *, int, char**);
+static int mo_forcenick(struct Client *, struct Client *, int, char**);
+
+static int clean_nick_name(char *);
+static void relay_kill(struct Client *one, struct Client *source_p,
+ struct Client *target_p, const char *inpath,
+ const char *reason);
+
+/*
+ * m_forcenick
+ * parv[1] = old nick
+ * parv[2] = new nick
+ */
+static int m_forcenick(struct Client *client_p, struct Client *source_p,
+ int parc, char *parv[])
+{
+ sendto_one(client_p, ":%s %d %s FORCENICK :Unknown command",
+ me.name, ERR_UNKNOWNCOMMAND, client_p->name);
+ return 0;
+}
+
+static void
+change_local_nick(struct Client *source_p, const char *nick)
+{
+ assert(source_p->name[0] && !EmptyString(nick));
+ assert(MyConnect(source_p));
+
+ /*
+ * Client just changing his/her nick. If he/she is
+ * on a channel, send note of change to all clients
+ * on that channel. Propagate notice to other servers.
+ */
+ if ((source_p->localClient->last_nick_change +
+ ConfigFileEntry.max_nick_time) < CurrentTime)
+ source_p->localClient->number_of_nick_changes = 0;
+ source_p->localClient->last_nick_change = CurrentTime;
+ source_p->localClient->number_of_nick_changes++;
+
+ if ((ConfigFileEntry.anti_nick_flood &&
+ (source_p->localClient->number_of_nick_changes
+ <= ConfigFileEntry.max_nick_changes)) ||
+ !ConfigFileEntry.anti_nick_flood ||
+ (HasUMode(source_p, UMODE_OPER) && ConfigFileEntry.no_oper_flood))
+ {
+ int samenick = !irccmp(source_p->name, nick);
+
+ if (!samenick)
+ {
+ source_p->tsinfo = CurrentTime;
+ clear_ban_cache_client(source_p);
+ watch_check_hash(source_p, RPL_LOGOFF);
+
+ if (HasUMode(source_p, UMODE_REGISTERED))
+ {
+ unsigned int oldmodes = source_p->umodes;
+ char modebuf[IRCD_BUFSIZE] = { '\0' };
+
+ DelUMode(source_p, UMODE_REGISTERED);
+ send_umode(source_p, source_p, oldmodes, 0xffffffff, modebuf);
+ }
+ }
+
+ /* XXX - the format of this notice should eventually be changed
+ * to either %s[%s@%s], or even better would be get_client_name() -bill
+ */
+ sendto_realops_flags(UMODE_NCHANGE, L_ALL, SEND_NOTICE,
+ "Nick change: From %s to %s [%s@%s]",
+ source_p->name, nick, source_p->username, source_p->host);
+ sendto_common_channels_local(source_p, 1, 0, ":%s!%s@%s NICK :%s",
+ source_p->name, source_p->username,
+ source_p->host, nick);
+ whowas_add_history(source_p, 1);
+
+ sendto_server(source_p, CAP_TS6, NOCAPS,
+ ":%s NICK %s :%lu",
+ ID(source_p), nick, (unsigned long)source_p->tsinfo);
+ sendto_server(source_p, NOCAPS, CAP_TS6,
+ ":%s NICK %s :%lu",
+ source_p->name, nick, (unsigned long)source_p->tsinfo);
+
+ hash_del_client(source_p);
+ strcpy(source_p->name, nick);
+ hash_add_client(source_p);
+
+ if (!samenick)
+ watch_check_hash(source_p, RPL_LOGON);
+
+ /* fd_desc is long enough */
+ fd_note(&source_p->localClient->fd, "Nick: %s", nick);
+ }
+ else
+ sendto_one(source_p, form_str(ERR_NICKTOOFAST),
+ me.name, source_p->name, source_p->name,
+ nick, ConfigFileEntry.max_nick_time);
+}
+
+/*
+ * mo_forcenick
+ * parv[0] = sender prefix
+ * parv[1] = old nick
+ * parv[2] = new nick
+ */
+static int mo_forcenick(struct Client *client_p, struct Client *source_p,
+ int parc, char *parv[])
+{
+ char vnick[NICKLEN];
+ char tnick[NICKLEN];
+ struct Client *victim_p;
+ struct Client *target_p;
+
+ if (!HasUMode(client_p, UMODE_ADMIN) || (parc != 3)) {
+ sendto_one(client_p, ":%s %d %s FORCENICK :Unknown command",
+ me.name, ERR_UNKNOWNCOMMAND, client_p->name);
+ return 0;
+ }
+
+ /* XXX BadPtr is needed */
+ if(parc < 2 || !parv[1] || parv[1] == '\0')
+ {
+ sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN),
+ me.name, parv[0]);
+ return 0;
+ }
+
+ /* terminate nick to NICKLEN */
+ strlcpy(vnick, parv[1], NICKLEN);
+ strlcpy(tnick, parv[2], NICKLEN);
+
+ if (!(victim_p = hash_find_client(vnick))) {
+ /* not a local client */
+ sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, parv[0], vnick);
+ return 0;
+ }
+
+ if (!MyConnect(victim_p)) {
+ sendto_one(source_p, ":%s NOTICE %s :Nick %s isn't on your server",
+ me.name, parv[0], victim_p->name);
+ return 0;
+ }
+
+ /* check the nickname is ok */
+ if(!clean_nick_name(tnick))
+ {
+ sendto_one(source_p, ":%s NOTICE %s :Nick %s is invalid",
+ me.name, parv[0], tnick);
+ return 0;
+ }
+
+ if ((target_p = hash_find_client(tnick)) != NULL)
+ {
+ /* If(target_p == source_p) the client is changing nicks between
+ * equivalent nicknames ie: [nick] -> {nick}
+ */
+
+ if(target_p == victim_p)
+ {
+ /* check the nick isnt exactly the same */
+ if(strcmp(target_p->name, tnick))
+ {
+ change_local_nick(victim_p, tnick);
+ return 0;
+ }
+ else
+ {
+ /* client is doing :old NICK old
+ * ignore it..
+ */
+ return 0;
+ }
+ }
+
+ /* if the client that has the nick isnt registered yet (nick but no
+ * user) then drop the unregged client
+ */
+ if(IsUnknown(target_p))
+ {
+ /* the old code had an if(MyConnect(target_p)) here.. but I cant see
+ * how that can happen, m_nick() is local only --fl_
+ */
+
+ exit_client(target_p, &me, "Overridden");
+ change_local_nick(victim_p, tnick);
+ return 0;
+ }
+ else
+ {
+ if (!MyConnect(target_p))
+ {
+ snprintf(buf, sizeof(buf), "renaming %s", victim_p->name);
+ relay_kill(client_p, source_p, target_p, client_p->name, buf);
+ target_p->flags |= FLAGS_KILLED;
+ }
+ snprintf(buf, sizeof(buf), "Killed by %s (renaming %s)", source_p->name,
+ victim_p->name);
+ exit_client(target_p, source_p, buf);
+ sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
+ "Force nick %s -> %s by %s!%s@%s",
+ vnick, tnick, source_p->name, source_p->username,
+ source_p->host);
+ ilog(LOG_TYPE_IRCD, "FORCENICK From %s!%s@%s (%s -> %s)", source_p->name,
+ source_p->username, source_p->host, vnick, tnick);
+ change_local_nick(victim_p, tnick);
+ return 0;
+ }
+
+ }
+ else
+ {
+ sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
+ "Force nick %s -> %s by %s!%s@%s",
+ vnick, tnick, source_p->name, source_p->username,
+ source_p->host);
+ ilog(LOG_TYPE_IRCD, "FORCENICK From %s!%s@%s (%s -> %s)", source_p->name,
+ source_p->username, source_p->host, vnick, tnick);
+ change_local_nick(victim_p, tnick);
+ }
+
+ return 0;
+}
+
+/* clean_nick_name()
+ *
+ * input - nickname
+ * output - none
+ * side effects - walks through the nickname, returning 0 if erroneous
+ */
+static int
+clean_nick_name(char *nick)
+{
+ assert(nick);
+ if(nick == NULL)
+ return (0);
+
+ /* nicks cant start with a digit or - or be 0 length */
+ /* This closer duplicates behaviour of hybrid-6 */
+
+ if (*nick == '-' || IsDigit(*nick) || *nick == '\0')
+ return (0);
+
+ for(; *nick; nick++)
+ {
+ if(!IsNickChar(*nick))
+ return (0);
+ }
+
+ return (1);
+}
+
+static void
+relay_kill(struct Client *one, struct Client *source_p,
+ struct Client *target_p, const char *inpath, const char *reason)
+{
+ dlink_node *ptr;
+ struct Client *client_p;
+ char* user;
+
+ for( ptr = serv_list.head; ptr; ptr = ptr->next )
+ {
+ client_p = (struct Client *) ptr->data;
+
+ if( !client_p || client_p == one )
+ continue;
+
+ /* check the server supports UID */
+ user = ID_or_name(target_p, client_p);
+
+ if(MyClient(source_p))
+ {
+ sendto_one(client_p, ":%s KILL %s :%s!%s!%s!%s (%s)",
+ source_p->name, user,
+ me.name, source_p->host, source_p->username,
+ source_p->name, reason);
+ }
+ else
+ {
+ sendto_one(client_p, ":%s KILL %s :%s %s",
+ source_p->name, user,
+ inpath, reason);
+ }
+ }
+}
+
+struct Message forcenick_msgtab = {
+ "FORCENICK", 0, 0, 0, MAXPARA, MFLG_SLOW|MFLG_HIDDEN, 0,
+ {m_ignore, m_forcenick, m_forcenick, m_forcenick, mo_forcenick, m_ignore}
+};
+
+static void
+module_init(void)
+{
+ mod_add_cmd(&forcenick_msgtab);
+}
+
+static void
+module_exit(void)
+{
+ mod_del_cmd(&forcenick_msgtab);
+}
+
+struct module module_entry = {
+ .node = { NULL, NULL, NULL },
+ .name = NULL,
+ .version = "$Revision: 0.0 $",
+ .handle = NULL,
+ .modinit = module_init,
+ .modexit = module_exit,
+ .flags = 0
+};