From a4721f5e9fd9dedc68534e736075a755645621f2 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 11 Jan 2016 23:32:23 -0600 Subject: [PATCH] ircd: implement EXTENDCHANS, based on ircd-seven (with some improvements from chatircd) --- doc/ircd.conf.example | 2 + doc/reference.conf | 6 ++ extensions/Makefile.am | 1 + extensions/Makefile.in | 28 ++++++---- extensions/m_extendchans.c | 112 +++++++++++++++++++++++++++++++++++++ include/client.h | 3 + include/s_conf.h | 3 + ircd/newconf.c | 2 + ircd/s_conf.c | 1 + ircd/s_user.c | 7 +++ modules/core/m_join.c | 4 +- modules/m_info.c | 6 ++ modules/m_privs.c | 1 + 13 files changed, 164 insertions(+), 12 deletions(-) create mode 100644 extensions/m_extendchans.c diff --git a/doc/ircd.conf.example b/doc/ircd.conf.example index 6dbdfb0f..4bb1d697 100755 --- a/doc/ircd.conf.example +++ b/doc/ircd.conf.example @@ -25,6 +25,7 @@ #loadmodule "extensions/extb_server.la"; #loadmodule "extensions/extb_ssl.la"; #loadmodule "extensions/hurt.la"; +#loadmodule "extensions/m_extendchans.la"; #loadmodule "extensions/m_findforwards.la"; #loadmodule "extensions/m_identify.la"; #loadmodule "extensions/no_oper_invis.la"; @@ -349,6 +350,7 @@ channel { knock_delay = 5 minutes; knock_delay_channel = 1 minute; max_chans_per_user = 15; + max_chans_per_user_large = 60; max_bans = 100; max_bans_large = 500; default_split_user_count = 0; diff --git a/doc/reference.conf b/doc/reference.conf index 1b1bd1a5..1b94449f 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -64,6 +64,7 @@ * HURT system -- hurt.la * New host mangling (umode +x) -- ip_cloaking_4.0.la * Old host mangling (umode +h) -- ip_cloaking.la + * Dynamically extend channel limits -- m_extendchans.la * Find channel forwards -- m_findforwards.la * /identify support -- m_identify.la * Opers cannot be invisible (umode +i) -- no_oper_invis.la @@ -94,6 +95,7 @@ #loadmodule "extensions/hurt.la"; #loadmodule "extensions/ip_cloaking_4.0.la"; #loadmodule "extensions/ip_cloaking.la"; +#loadmodule "extensions/m_extendchans.la"; #loadmodule "extensions/m_findforwards.la"; #loadmodule "extensions/m_identify.la"; #loadmodule "extensions/no_oper_invis.la"; @@ -376,6 +378,7 @@ auth { * need_ident (old + flag) | require ident for user in this class * need_ssl | require SSL/TLS for user in this class * need_sasl | require SASL id for user in this class + * extend_chans | allow this user to join more channels than normal */ flags = kline_exempt, exceed_limit; @@ -735,6 +738,9 @@ channel { /* max chans: The maximum number of channels a user can join/be on. */ max_chans_per_user = 15; + /* max chans (large): The extended maximum number of channels a user can join. */ + max_chans_per_user_large = 60; + /* max bans: maximum number of +b/e/I/q modes in a channel */ max_bans = 100; diff --git a/extensions/Makefile.am b/extensions/Makefile.am index 55f8e596..54c06baa 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -41,6 +41,7 @@ extension_LTLIBRARIES = \ sno_whois.la \ m_42.la \ m_adminwall.la \ + m_extendchans.la \ m_findforwards.la \ m_identify.la \ m_mkpasswd.la \ diff --git a/extensions/Makefile.in b/extensions/Makefile.in index 0639b26c..fb67d342 100644 --- a/extensions/Makefile.in +++ b/extensions/Makefile.in @@ -227,6 +227,9 @@ m_42_la_OBJECTS = m_42.lo m_adminwall_la_LIBADD = m_adminwall_la_SOURCES = m_adminwall.c m_adminwall_la_OBJECTS = m_adminwall.lo +m_extendchans_la_LIBADD = +m_extendchans_la_SOURCES = m_extendchans.c +m_extendchans_la_OBJECTS = m_extendchans.lo m_findforwards_la_LIBADD = m_findforwards_la_SOURCES = m_findforwards.c m_findforwards_la_OBJECTS = m_findforwards.lo @@ -353,11 +356,11 @@ SOURCES = chm_adminonly.c chm_nonotice.c chm_operonly.c \ extb_realname.c extb_server.c extb_ssl.c extb_usermode.c \ force_user_invis.c hide_uncommon_channels.c hurt.c \ ip_cloaking.c ip_cloaking_3.0.c ip_cloaking_4.0.c \ - ip_cloaking_old.c m_42.c m_adminwall.c m_findforwards.c \ - m_identify.c m_mkpasswd.c m_ojoin.c m_okick.c m_omode.c \ - m_opme.c m_remove.c m_roleplay.c m_sendbans.c m_webirc.c \ - no_kill_services.c no_locops.c no_oper_invis.c override.c \ - restrict-unauthenticated.c sno_channelcreate.c \ + ip_cloaking_old.c m_42.c m_adminwall.c m_extendchans.c \ + m_findforwards.c m_identify.c m_mkpasswd.c m_ojoin.c m_okick.c \ + m_omode.c m_opme.c m_remove.c m_roleplay.c m_sendbans.c \ + m_webirc.c no_kill_services.c no_locops.c no_oper_invis.c \ + override.c restrict-unauthenticated.c sno_channelcreate.c \ sno_farconnect.c sno_globalkline.c sno_globaloper.c \ sno_whois.c spy_admin_notice.c spy_info_notice.c \ spy_links_notice.c spy_motd_notice.c spy_stats_notice.c \ @@ -370,11 +373,11 @@ DIST_SOURCES = chm_adminonly.c chm_nonotice.c chm_operonly.c \ extb_realname.c extb_server.c extb_ssl.c extb_usermode.c \ force_user_invis.c hide_uncommon_channels.c hurt.c \ ip_cloaking.c ip_cloaking_3.0.c ip_cloaking_4.0.c \ - ip_cloaking_old.c m_42.c m_adminwall.c m_findforwards.c \ - m_identify.c m_mkpasswd.c m_ojoin.c m_okick.c m_omode.c \ - m_opme.c m_remove.c m_roleplay.c m_sendbans.c m_webirc.c \ - no_kill_services.c no_locops.c no_oper_invis.c override.c \ - restrict-unauthenticated.c sno_channelcreate.c \ + ip_cloaking_old.c m_42.c m_adminwall.c m_extendchans.c \ + m_findforwards.c m_identify.c m_mkpasswd.c m_ojoin.c m_okick.c \ + m_omode.c m_opme.c m_remove.c m_roleplay.c m_sendbans.c \ + m_webirc.c no_kill_services.c no_locops.c no_oper_invis.c \ + override.c restrict-unauthenticated.c sno_channelcreate.c \ sno_farconnect.c sno_globalkline.c sno_globaloper.c \ sno_whois.c spy_admin_notice.c spy_info_notice.c \ spy_links_notice.c spy_motd_notice.c spy_stats_notice.c \ @@ -624,6 +627,7 @@ extension_LTLIBRARIES = \ sno_whois.la \ m_42.la \ m_adminwall.la \ + m_extendchans.la \ m_findforwards.la \ m_identify.la \ m_mkpasswd.la \ @@ -807,6 +811,9 @@ m_42.la: $(m_42_la_OBJECTS) $(m_42_la_DEPENDENCIES) $(EXTRA_m_42_la_DEPENDENCIES m_adminwall.la: $(m_adminwall_la_OBJECTS) $(m_adminwall_la_DEPENDENCIES) $(EXTRA_m_adminwall_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(extensiondir) $(m_adminwall_la_OBJECTS) $(m_adminwall_la_LIBADD) $(LIBS) +m_extendchans.la: $(m_extendchans_la_OBJECTS) $(m_extendchans_la_DEPENDENCIES) $(EXTRA_m_extendchans_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) -rpath $(extensiondir) $(m_extendchans_la_OBJECTS) $(m_extendchans_la_LIBADD) $(LIBS) + m_findforwards.la: $(m_findforwards_la_OBJECTS) $(m_findforwards_la_DEPENDENCIES) $(EXTRA_m_findforwards_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(extensiondir) $(m_findforwards_la_OBJECTS) $(m_findforwards_la_LIBADD) $(LIBS) @@ -927,6 +934,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_cloaking_old.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m_42.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m_adminwall.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m_extendchans.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m_findforwards.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m_identify.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m_mkpasswd.Plo@am__quote@ diff --git a/extensions/m_extendchans.c b/extensions/m_extendchans.c new file mode 100644 index 00000000..9dd33def --- /dev/null +++ b/extensions/m_extendchans.c @@ -0,0 +1,112 @@ +/* + * charybdis + * m_extendchans.c: Allow an oper or service to let a given user join more channels. + * + * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center + * Copyright (C) 1996-2002 Hybrid Development Team + * Copyright (C) 2002-2006 ircd-ratbox development team + * Copyright (C) 2006-2016 ircd-seven development team + * Copyright (C) 2015-2016 ChatLounge IRC Network Development Team + * + * 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 + */ + +#include "stdinc.h" +#include "client.h" +#include "modules.h" +#include "s_newconf.h" +#include "send.h" +#include "numeric.h" + +static int mo_extendchans(struct Client *, struct Client *, int, const char **); +static int me_extendchans(struct Client *, struct Client *, int, const char **); + +struct Message extendchans_msgtab = { + "EXTENDCHANS", 0, 0, 0, MFLG_SLOW, + { mg_unreg, mg_ignore, mg_ignore, mg_ignore, {me_extendchans, 2}, {mo_extendchans, 2}} +}; + +mapi_clist_av1 extendchans_clist[] = { &extendchans_msgtab, NULL }; + +DECLARE_MODULE_AV1(extendchans, NULL, NULL, extendchans_clist, NULL, NULL, "$Revision: $"); + +static int +mo_extendchans(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) +{ + struct Client *target_p; + + if(!HasPrivilege(source_p, "oper:extendchans")) + { + sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "extendchans"); + return 0; + } + + if(EmptyString(parv[1])) + { + sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "EXTENDCHANS"); + return 0; + } + + if((target_p = find_chasing(source_p, parv[1], NULL)) == NULL) + return 0; + + /* Is the target user local? */ + if(MyClient(target_p)) + { + sendto_one_notice(target_p, ":*** %s (%s@%s) is extending your channel limit", + source_p->name, source_p->username, source_p->host); + SetExtendChans(target_p); + } + else /* Target user isn't local, so pass it on. */ + { + struct Client *cptr = target_p->servptr; + sendto_one(cptr, ":%s ENCAP %s EXTENDCHANS %s", + get_id(source_p, cptr), cptr->name, get_id(target_p, cptr)); + } + + sendto_one_notice(source_p, ":You have extended the channel limit on: %s (%s@%s)", + target_p->name, target_p->username, target_p->orighost); + + return 0; +} + +static int +me_extendchans(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) +{ + struct Client *target_p; + + target_p = find_person(parv[1]); + if(target_p == NULL) + { + sendto_one_numeric(source_p, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), parv[1]); + return 0; + } + + /* Is the target user local? If not, pass it on. */ + if(!MyClient(target_p)) + { + struct Client *cptr = target_p->servptr; + sendto_one(cptr, ":%s ENCAP %s EXTENDCHANS %s", + get_id(source_p, cptr), cptr->name, get_id(target_p, cptr)); + return 0; + } + + sendto_one_notice(target_p, ":*** %s (%s@%s) is extending your channel limit", + source_p->name, source_p->username, source_p->host); + SetExtendChans(target_p); + + return 0; +} diff --git a/include/client.h b/include/client.h index 09bc4004..0ecebc19 100644 --- a/include/client.h +++ b/include/client.h @@ -420,6 +420,7 @@ struct PreClient /* overflow flags */ /* EARLIER FLAGS ARE IN s_newconf.h */ +#define FLAGS2_EXTENDCHANS 0x00200000 #define FLAGS2_EXEMPTRESV 0x00400000 #define FLAGS2_EXEMPTKLINE 0x00800000 #define FLAGS2_EXEMPTFLOOD 0x01000000 @@ -536,6 +537,8 @@ struct PreClient #define SetExemptResv(x) ((x)->flags2 |= FLAGS2_EXEMPTRESV) #define IsIPSpoof(x) ((x)->flags2 & FLAGS2_IP_SPOOFING) #define SetIPSpoof(x) ((x)->flags2 |= FLAGS2_IP_SPOOFING) +#define IsExtendChans(x) ((x)->flags2 & FLAGS2_EXTENDCHANS) +#define SetExtendChans(x) ((x)->flags2 |= FLAGS2_EXTENDCHANS) /* for local users: flood grace period is over * for servers: mentioned in networknotice.c notice diff --git a/include/s_conf.h b/include/s_conf.h index 42e26705..3e71f715 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -110,6 +110,7 @@ struct ConfItem #define CONF_FLAGS_EXEMPTSHIDE 0x00010000 #define CONF_FLAGS_EXEMPTJUPE 0x00020000 /* exempt from resv generating warnings */ #define CONF_FLAGS_NEED_SASL 0x00040000 +#define CONF_FLAGS_EXTEND_CHANS 0x00080000 #define CONF_FLAGS_ENCRYPTED 0x00200000 #define CONF_FLAGS_EXEMPTDNSBL 0x04000000 @@ -132,6 +133,7 @@ struct ConfItem #define IsConfEncrypted(x) ((x)->flags & CONF_FLAGS_ENCRYPTED) #define IsNeedSasl(x) ((x)->flags & CONF_FLAGS_NEED_SASL) #define IsConfExemptDNSBL(x) ((x)->flags & CONF_FLAGS_EXEMPTDNSBL) +#define IsConfExtendChans(x) ((x)->flags & CONF_FLAGS_EXTEND_CHANS) #define IsConfSSLNeeded(x) ((x)->flags & CONF_FLAGS_NEED_SSL) /* flag definitions for opers now in client.h */ @@ -248,6 +250,7 @@ struct config_channel_entry int max_bans; int max_bans_large; int max_chans_per_user; + int max_chans_per_user_large; int no_create_on_split; int no_join_on_split; int default_split_server_count; diff --git a/ircd/newconf.c b/ircd/newconf.c index 65693084..f6cbd44b 100644 --- a/ircd/newconf.c +++ b/ircd/newconf.c @@ -344,6 +344,7 @@ static struct mode_table auth_table[] = { {"have_ident", CONF_FLAGS_NEED_IDENTD }, {"need_ssl", CONF_FLAGS_NEED_SSL }, {"need_sasl", CONF_FLAGS_NEED_SASL }, + {"extend_chans", CONF_FLAGS_EXTEND_CHANS }, {NULL, 0} }; @@ -2440,6 +2441,7 @@ static struct ConfEntry conf_channel_table[] = { "max_bans", CF_INT, NULL, 0, &ConfigChannel.max_bans }, { "max_bans_large", CF_INT, NULL, 0, &ConfigChannel.max_bans_large }, { "max_chans_per_user", CF_INT, NULL, 0, &ConfigChannel.max_chans_per_user }, + { "max_chans_per_user_large", CF_INT, NULL, 0, &ConfigChannel.max_chans_per_user_large }, { "no_create_on_split", CF_YESNO, NULL, 0, &ConfigChannel.no_create_on_split }, { "no_join_on_split", CF_YESNO, NULL, 0, &ConfigChannel.no_join_on_split }, { "only_ascii_channels", CF_YESNO, NULL, 0, &ConfigChannel.only_ascii_channels }, diff --git a/ircd/s_conf.c b/ircd/s_conf.c index ebd6919b..214fc553 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -780,6 +780,7 @@ set_default_conf(void) ConfigChannel.knock_delay = 300; ConfigChannel.knock_delay_channel = 60; ConfigChannel.max_chans_per_user = 15; + ConfigChannel.max_chans_per_user_large = 60; ConfigChannel.max_bans = 25; ConfigChannel.max_bans_large = 500; ConfigChannel.only_ascii_channels = NO; diff --git a/ircd/s_user.c b/ircd/s_user.c index ad95ff54..55a0bb55 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -868,6 +868,12 @@ report_and_set_user_flags(struct Client *source_p, struct ConfItem *aconf) SetExemptShide(source_p); sendto_one_notice(source_p, ":*** You are exempt from serverhiding"); } + + if(IsConfExtendChans(aconf)) + { + SetExtendChans(source_p); + sendto_one_notice(source_p, ":*** You are exempt from normal channel limits"); + } } static void @@ -1309,6 +1315,7 @@ oper_up(struct Client *source_p, struct oper_conf *oper_p) Count.oper++; + SetExtendChans(source_p); SetExemptKline(source_p); source_p->flags2 |= oper_p->flags; diff --git a/modules/core/m_join.c b/modules/core/m_join.c index b45728e3..a19e2335 100644 --- a/modules/core/m_join.c +++ b/modules/core/m_join.c @@ -278,9 +278,9 @@ m_join(struct Client *client_p, struct Client *source_p, int parc, const char *p if((rb_dlink_list_length(&source_p->user->channel) >= (unsigned long) ConfigChannel.max_chans_per_user) && - (!IsOper(source_p) || + (!IsExtendChans(source_p) || (rb_dlink_list_length(&source_p->user->channel) >= - (unsigned long) ConfigChannel.max_chans_per_user * 3))) + (unsigned long) ConfigChannel.max_chans_per_user_large))) { sendto_one(source_p, form_str(ERR_TOOMANYCHANNELS), me.name, source_p->name, name); diff --git a/modules/m_info.c b/modules/m_info.c index 301b9645..202716a6 100644 --- a/modules/m_info.c +++ b/modules/m_info.c @@ -584,6 +584,12 @@ static struct InfoStruct info_table[] = { &ConfigChannel.max_chans_per_user, "Maximum number of channels a user can join", }, + { + "max_chans_per_user_large", + OUTPUT_DECIMAL, + &ConfigChannel.max_chans_per_user_large, + "Maximum extended number of channels a user can join", + }, { "no_create_on_split", OUTPUT_BOOLEAN_YN, diff --git a/modules/m_privs.c b/modules/m_privs.c index 65cbbf7d..8388442a 100644 --- a/modules/m_privs.c +++ b/modules/m_privs.c @@ -69,6 +69,7 @@ static struct mode_table auth_client_table[] = { {"spambot_exempt", FLAGS2_EXEMPTSPAMBOT }, {"shide_exempt", FLAGS2_EXEMPTSHIDE }, {"jupe_exempt", FLAGS2_EXEMPTJUPE }, + {"extend_chans", FLAGS2_EXTENDCHANS }, {NULL, 0} };