diff options
| author | 2019-01-24 15:58:57 +0000 | |
|---|---|---|
| committer | 2019-01-24 15:58:57 +0000 | |
| commit | 1799bcff97e8018156df809fd3cae3ed3d663591 (patch) | |
| tree | e8ed9f51b8d52f188c9b3d18abab4ebde915c3d4 | |
| parent | Add translation for casemapping between 2.0/3.0 (#1544) (diff) | |
| parent | Add translation for casemapping between 2.0/3.0 (#1544) (diff) | |
| download | inspircd++-1799bcff97e8018156df809fd3cae3ed3d663591.tar.gz inspircd++-1799bcff97e8018156df809fd3cae3ed3d663591.tar.bz2 inspircd++-1799bcff97e8018156df809fd3cae3ed3d663591.zip | |
Merge branch 'insp3' into master
64 files changed, 615 insertions, 450 deletions
@@ -20,8 +20,6 @@ If you encounter any bugs then [please file an issue](https://github.com/inspirc ## Installation -**The `master` branch contains the latest development version. If you are running a server then you probably want the `insp20` branch. You can obtain this from [the releases page](https://github.com/inspircd/inspircd/releases) or by running `git checkout $(git describe --abbrev=0 --tags insp20)` if you are installing via Git.** - Most InspIRCd users running a UNIX-like system build from source. A guide about how to do this is available on [the InspIRCd wiki](https://wiki.inspircd.org/Installation_From_Source). Building from source on Windows is generally not recommended but [a guide is available](https://github.com/inspircd/inspircd/blob/master/win/README.txt) if you wish to do this. @@ -244,7 +244,7 @@ affect the running of your server. It is recommended that you use a stable version instead. You can obtain the latest stable version from http://www.inspircd.org/ or by -running `<|GREEN git checkout $(git describe --abbrev=0 --tags insp20)|>` if you are +running `<|GREEN git checkout $(git describe --abbrev=0 --tags insp3)|>` if you are installing from Git. EOW if (!prompt_bool $interactive, 'I understand this warning and want to continue anyway.', $opt_development // 0) { diff --git a/docs/conf/censor.conf.example b/docs/conf/censor.conf.example deleted file mode 100644 index 23924d14b..000000000 --- a/docs/conf/censor.conf.example +++ /dev/null @@ -1,12 +0,0 @@ -# Configuration file for the censor module - -# The tags for this module are formatted as follows: -# -# <badword text="simple word" -# replace="text to replace with"> -# -# You can specify <badword text="simple word" replace=""> -# to block lines containing the word - -<badword text="shit" replace="poo"> -<badword text="fuck" replace="(censored)"> diff --git a/docs/conf/filter.conf.example b/docs/conf/filter.conf.example index 26c68d2c3..29e1f530c 100644 --- a/docs/conf/filter.conf.example +++ b/docs/conf/filter.conf.example @@ -6,7 +6,7 @@ # reason="reason for filtering" # action="action to take" # flags="filter flags" -# duration="optional length of gline"> +# duration="optional duration of the G-line, Z-line or shun"> # # Valid actions for 'action' are: # @@ -25,15 +25,21 @@ # kill This disconnects the user, with the 'reason' parameter as # the kill reason. # -# gline G-LINE the user for 'duration' length of time. Durations may +# gline G-line the user for 'duration' length of time. Durations may # be specified using the notation 1y2d3h4m6s in a similar way to -# other glines, omitting the duration or setting it to 0 makes -# any glines set by this filter be permanent. +# other G-lines, omitting the duration or setting it to 0 makes +# any G-lines set by this filter be permanent. # -# zline Z-LINE the user for 'duration' length of time. Durations may +# zline Z-line the user for 'duration' length of time. Durations may # be specified using the notation 1y2d3h4m6s in a similar way to -# other zlines, omitting the duration or setting it to 0 makes -# any zlines set by this filter be permanent. +# other Z-lines, omitting the duration or setting it to 0 makes +# any Z-lines set by this filter be permanent. +# +# shun Shun the user for 'duration' length of time. Durations may +# be specified using the notation 1y2d3h4m6s in a similar way to +# other X-lines, omitting the duration or setting it to 0 makes +# any shuns set by this filter be permanent. +# Requires the shun module to be loaded. # # You can add filters from IRC using the /FILTER command. If you do this, they # will be set globally to your entire network. diff --git a/docs/conf/helpop-full.conf.example b/docs/conf/helpop-full.conf.example index 6834ca7c8..dec0e23d1 100644 --- a/docs/conf/helpop-full.conf.example +++ b/docs/conf/helpop-full.conf.example @@ -475,8 +475,8 @@ numeric lists)"> This command will add a filter when more than one parameter is given, for messages of the types specified by the flags, with the given -filter definition, action, duration (when the action is 'gline' or 'shun'), -and reason. +filter definition, action, duration (when the action is 'gline', +'zline' or 'shun'), and reason. The filter will take effect when a message of any type specified by the flags and matching the definition is sent to the server, and @@ -492,8 +492,8 @@ Block Blocks message and informs +s IRCops of the blocked message and all relevant info Silent Blocks message, but does not notify IRCops Kill Kills the user -Gline Glines the user for the specified duration -Zline Zlines the user for the specified duration +Gline G-lines the user for the specified duration +Zline Z-lines the user for the specified duration Shun Shuns the user for the specified duration (requires the shun module) Valid FILTER Flags @@ -513,8 +513,8 @@ The reason for the filter will be used as the reason for the action, unless the action is 'none', and is sent to the user when their text is blocked by 'block' and 'silent' actions. -A gline duration may be specified in seconds, or in the format -1y2w3d4h5m6s - meaning one year, two weeks, three days, 4 hours, 5 +A G-line, Z-line or shun duration may be specified in seconds, or in the +format 1y2w3d4h5m6s - meaning one year, two weeks, three days, 4 hours, 5 minutes and 6 seconds. All fields in this format are optional. When only one parameter is provided (the filter pattern) the provided @@ -721,7 +721,7 @@ Unloads and reloads a module on all linked servers."> <helpop key="kline" value="/KLINE <user@host> [<duration> :<reason>] -Sets or removes a k-line (local host based ban) on a host and ident mask. +Sets or removes a K-line (local host based ban) on a host and ident mask. You must specify all three parameters to add a ban, and one parameter to remove a ban (just the user@host section). @@ -731,7 +731,7 @@ The duration may be specified in seconds, or in the format <helpop key="zline" value="/ZLINE <ipmask> [<duration> :<reason>] -Sets or removes a z-line (ip based ban) on an ip range mask. +Sets or removes a Z-line (ip based ban) on an ip range mask. You must specify all three parameters to add a ban, and one parameter to remove a ban (just the ipmask). @@ -741,7 +741,7 @@ The duration may be specified in seconds, or in the format <helpop key="qline" value="/QLINE <nickmask> [<duration> :<reason>] -Sets or removes a q-line (nick based ban) on a nick mask. +Sets or removes a Q-line (nick based ban) on a nick mask. You must specify all three parameters to add a ban, and one parameter to remove a ban (just the nickmask). @@ -751,7 +751,7 @@ The duration may be specified in seconds, or in the format <helpop key="gline" value="/GLINE <user@host> [<duration> :<reason>] -Sets or removes a g-line (host based ban) on host mask. +Sets or removes a G-line (host based ban) on host mask. You must specify all three parameters to add a ban, and one parameter to remove a ban (just the user@host section). @@ -761,7 +761,7 @@ The duration may be specified in seconds, or in the format <helpop key="eline" value="/ELINE <user@host> [<duration> :<reason>] -Sets or removes a e-line (global ban exception) on host mask. +Sets or removes a E-line (global ban exception) on host mask. You must specify at least 3 parameters to add an exception, and one parameter to remove an exception (just the user@host section). @@ -770,9 +770,9 @@ The duration may be specified in seconds, or in the format 5 minutes and 6 seconds. All fields in this format are optional. This command has a few important limitations. Bans on *@<ip> can only -be negated by an eline on *@<ip>, bans on *@<host> can be negated by -elines on *@<ip>, or *@<host>, and bans on <ident>@* or <ident>@<host> -can be negated by any eline that matches."> +be negated by an E-line on *@<ip>, bans on *@<host> can be negated by +E-lines on *@<ip>, or *@<host>, and bans on <ident>@* or <ident>@<host> +can be negated by any E-line that matches."> <helpop key="wallops" value="/WALLOPS <message> @@ -780,9 +780,9 @@ Sends a message to all +w users."> <helpop key="rline" value="/RLINE <regex> [<duration> :<reason>] -Sets or removes an r-line (regex line) on a n!u@h\srealname mask. You -must specify all three parameters to add an rline, and one parameter -to remove an rline (just the regex). +Sets or removes an R-line (regex line) on a n!u@h\srealname mask. You +must specify all three parameters to add an R-line, and one parameter +to remove an R-line (just the regex). The duration may be specified in seconds, or in the format 1y2w3d4h5m6s - meaning one year, two weeks, three days, 4 hours, @@ -794,11 +794,11 @@ Closes all unregistered connections to the local server."> <helpop key="clearchan" value="/CLEARCHAN <channel> [<KILL|KICK|G|Z>] [<reason>] -Quits or kicks all non-opers from a channel, optionally G/Z-Lines them. +Quits or kicks all non-opers from a channel, optionally G/Z-lines them. Useful for quickly nuking bot channels. The default method, KILL, simply disconnects the victims from the server, -while methods G and Z also add G/Z-Lines for all the targets. +while methods G and Z also add G/Z-lines for all the targets. When used, the victims won't see each other getting kicked or quitting."> @@ -1070,8 +1070,8 @@ Note that all /STATS use is broadcast to online IRC operators."> R Allows receipt of remote oper commands (requires the operlog module). t Allows receipt of attempts to use /STATS (local and remote). v Allows receipt of oper-override notices (requires the override module). - x Allows receipt of local Xline notices (g/Z/q/k/e/R/shuns). - X Allows receipt of remote Xline notices (g/Z/q/k/e/R/shuns)."> + x Allows receipt of local X-line notices (G/Z/Q/K/E/R/SHUN/CBan). + X Allows receipt of remote X-line notices (G/Z/Q/K/E/R/SHUN/CBan)."> ###################### # EXTBANS # diff --git a/docs/conf/helpop.conf.example b/docs/conf/helpop.conf.example index 5285a4b6c..a4bfc751b 100644 --- a/docs/conf/helpop.conf.example +++ b/docs/conf/helpop.conf.example @@ -257,8 +257,8 @@ help channel if you have any questions."> R Allows receipt of remote oper commands (requires the operlog module). t Allows receipt of attempts to use /STATS (local and remote). v Allows receipt of oper-override notices (requires the override module). - x Allows receipt of local Xline notices (g/Z/q/k/e/R/shuns). - X Allows receipt of remote Xline notices (g/Z/q/k/e/R/shuns)."> + x Allows receipt of local X-line notices (G/Z/Q/K/E/R/SHUN/CBan). + X Allows receipt of remote X-line notices (G/Z/Q/K/E/R/SHUN/CBan)."> <helpop key="extbans" value="Extended Bans ---------- diff --git a/docs/conf/inspircd.conf.example b/docs/conf/inspircd.conf.example index 952b981f3..890c9cc4c 100644 --- a/docs/conf/inspircd.conf.example +++ b/docs/conf/inspircd.conf.example @@ -367,11 +367,11 @@ # softsendq: amount of data in a client's send queue before the server # begins delaying their commands in order to allow the sendq to drain - softsendq="8192" + softsendq="10240" # recvq: amount of data allowed in a client's queue before they are dropped. - # Entering "8K" is equivalent to "8192", see above. - recvq="8K" + # Entering "10K" is equivalent to "10240", see above. + recvq="10K" # threshold: This specifies the amount of command penalty a user is allowed to have # before being quit or fakelagged due to flood. Normal commands have a penalty of 1, @@ -520,25 +520,6 @@ # up to 100 entries. <maxlist chan="*" limit="100"> -#-#-#-#-#-#-#-#-#-#-#- DISABLED FEATURES -#-#-#-#-#-#-#-#-#-#-#-#-#-# -# # -# This tag is optional, and specifies one or more features which are # -# not available to non-operators. # -# # -# For example you may wish to disable NICK and prevent non-opers from # -# changing their nicknames. # -# Note that any disabled commands take effect only after the user has # -# 'registered' (e.g. after the initial USER/NICK/PASS on connection) # -# so for example disabling NICK will not cripple your network. # -# # -# You can also define if you want to disable any channelmodes # -# or usermodes from your users. # -# # -# `fakenonexistant' will make the ircd pretend that nonexistant # -# commands simply don't exist to non-opers ("no such command"). # -# # -#<disabled commands="TOPIC MODE" usermodes="" chanmodes="" fakenonexistant="yes"> - #-#-#-#-#-#-#-#-#-#-#-#-#- SERVER OPTIONS -#-#-#-#-#-#-#-#-#-#-#-#-# # # # Settings to define which features are usable on your server. # @@ -748,7 +729,7 @@ # when a remote whois (/WHOIS <nick> <nick>) is used. #hideserver="*.example.com" - # hidebans: If this value is set to yes, when a user is banned ([gkz]lined) + # hidebans: If this value is set to yes, when a user is banned ([KGZ]-lined) # only opers will see the ban message when the user is removed # from the server. hidebans="no" @@ -960,7 +941,7 @@ <badhost host="root@*" reason="Don't IRC as root!"> <badhost host="*@198.51.100.0/24" reason="This subnet is bad."> -# exception: Hosts that are exempt from [kgz]lines. +# exception: Hosts that are exempt from [KGZ]-lines. <exception # host: ident@hostname to exempt. # Wildcards and CIDR (if you specify an IP) can be used. @@ -971,14 +952,14 @@ #-#-#-#-#-#-#-#-#-#-#- INSANE BAN OPTIONS -#-#-#-#-#-#-#-#-#-#-#-#-#-# # # -# This optional tag allows you to specify how wide a gline, eline, # -# kline, zline or qline can be before it is forbidden from being # -# set. By setting hostmasks="yes", you can allow all G, K, E lines, # +# This optional tag allows you to specify how wide a G-line, E-line, # +# K-line, Z-line or Q-line can be before it is forbidden from being # +# set. By setting hostmasks="yes", you can allow all G-, K-, E-lines, # # no matter how many users the ban would cover. This is not # -# recommended! By setting ipmasks="yes", you can allow all Z lines, # +# recommended! By setting ipmasks="yes", you can allow all Z-lines, # # no matter how many users these cover too. Needless to say we # # don't recommend you do this, or, set nickmasks="yes", which will # -# allow any qline. # +# allow any Q-line. # # # <insane diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example index 3b7d30e8f..ba674d2bd 100644 --- a/docs/conf/modules.conf.example +++ b/docs/conf/modules.conf.example @@ -312,16 +312,21 @@ #<module name="cban"> #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# -# Censor module: Adds channel and user mode +G. +# Censor module: Adds channel and user mode +G which block phrases that +# are listed in the server bad words list. #<module name="censor"> # #-#-#-#-#-#-#-#-#-#-#- CENSOR CONFIGURATION -#-#-#-#-#-#-#-#-#-#-#-# # # -# Optional - If you specify to use the censor module, then you must # -# specify some censor tags. See also: # -# https://wiki.inspircd.org/Modules/3.0/censor # -# -#<include file="examples/censor.conf.example"> +# If you have the censor module loaded you should specify one or more # +# phrases to replace/block in user messages. The config for this is # +# formatted as follows: # +# # +# Replaces "eggplant" with "aubergine" within messages: # +# <badword text="eggplant" replace="aubergine"> # +# # +# Blocks messages that contain "fluffy capybaras": # +#<badword text="fluffy capybaras"> # #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# # CGI:IRC module: Enables forwarding the real IP address of a user from @@ -500,8 +505,8 @@ #<module name="classban"> #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# -# Clear chan module: Allows opers to masskick, masskill or mass-G/ZLine -# all users on a channel using /CLEARCHAN. +# Clear chan module: Allows opers to masskick, masskill or +# mass G/Z-line all users on a channel using /CLEARCHAN. #<module name="clearchan"> #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# @@ -619,7 +624,7 @@ #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# # Connectban: Provides IP connection throttling. Any IP range that -# connects too many times (configurable) in an hour is Z-Lined for a +# connects too many times (configurable) in an hour is Z-lined for a # (configurable) duration, and their count resets to 0. #<module name="connectban"> # @@ -765,6 +770,43 @@ # Glob masks are accepted here also. # #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# +# Disable module: Provides support for disabling commands and modes. # +#<module name="disable"> +# +#-#-#-#-#-#-#-#-#-#-#-#- DISABLE CONFIGURATION -#-#-#-#-#-#-#-#-#-#-#-# +# # +# If you have the disable module loaded then you need to specify the # +# commands and modes that you want disabled. Users who have not fully # +# connected yet are exempt from this module so you can e.g. disable # +# the NICK command but still allow users to connect to the server. # +# # +# commands - A space-delimited list of commands that can not be used # +# by users. You can exempt server operators from this with # +# the servers/use-disabled-commands privilege. # +# # +# chanmodes - One or more channel modes that can not be added/removed # +# by users. You can exempt server operators from this # +# with the servers/use-disabled-commands privilege. # +# # +# usermodes - One or more user modes that can not be added/removed by # +# users. You can exempt server operators from this with # +# the servers/use-disabled-commands privilege. # +# # +# fakenonexistent - Whether to pretend that a disabled command/mode # +# does not exist when executed/changed by a user. # +# Defaults to no. # +# # +# notifyopers - Whether to send a notice to snomask `a` when a user # +# is prevented from using a disabled command/mode. # +# Defaults to no. # +# # +#<disabled commands="KICK TOPIC" # +# chanmodes="kp" # +# usermodes="iw" # +# fakenonexistent="yes" # +# notifyopers="no"> # + +#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# # DNS blacklist module: Provides support for looking up IPs on one or # # more blacklists. # #<module name="dnsbl"> # @@ -1021,7 +1063,6 @@ # the timeout for ident lookups here. If not defined, it will default # # to 5 seconds. This is a non-blocking timeout which holds the user # # in a 'connecting' state until the lookup is complete. # -# The bind value indicates which IP to bind outbound requests to. # # nolookupprefix: If on, the idents of users being in a connect class # # with ident lookups disabled (i.e. <connect useident="off">) will be # # prefixed with a "~". If off, the ident of those users will not be # @@ -1621,7 +1662,7 @@ #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# # Regular expression provider for glob or wildcard (?/*) matching. -# You must have at least 1 provider loaded to use the filter or rline +# You must have at least 1 provider loaded to use the filter or R-line # modules. This module has no additional requirements, as it uses the # matching already present in InspIRCd core. #<module name="regex_glob"> @@ -1630,7 +1671,7 @@ # Regular expression provider for PCRE (Perl-Compatible Regular # Expressions). You need libpcre installed to compile and load this # module. You must have at least 1 provider loaded to use the filter or -# rline modules. +# R-line modules. #<module name="regex_pcre"> #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# @@ -1643,7 +1684,7 @@ # Regular expression provider for POSIX regular expressions. # You shouldn't need any additional libraries on a POSIX-compatible # system (i.e.: any Linux, BSD, but not Windows). You must have at -# least 1 provider loaded to use filter or rline. +# least 1 provider loaded to use the filter or R-line modules. # On POSIX-compliant systems, regex syntax can be found by using the # command: 'man 7 regex'. #<module name="regex_posix"> @@ -1723,7 +1764,7 @@ #<module name="restrictmsg"> #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# -# R-Line module: Ban users through regular expression patterns. +# R-line module: Ban users through regular expression patterns. #<module name="rline"> # #-#-#-#-#-#-#-#-#-#-#-#- RLINE CONFIGURATION -#-#-#-#-#-#-#-#-#-#-#-#-# @@ -1732,15 +1773,15 @@ # useful under some situations, but *can* also use CPU with more users # on a server) then set 'matchonnickchange' to yes. # Also, this is where you set what Regular Expression engine is to be -# used. If you ever change it while running, all of your R-Lines will -# be wiped. This is the regex engine used by all R-Lines set, and +# used. If you ever change it while running, all of your R-lines will +# be wiped. This is the regex engine used by all R-lines set, and # regex_<engine> must be loaded, or rline will be non-functional # until you load it or change the engine to one that is loaded. # #<rline matchonnickchange="yes" engine="pcre"> # -# Generally, you will NOT want to use 'glob' here, as this turns -# rline into just another gline. The exceptions are that rline will +# Generally, you will NOT want to use 'glob' here, as this turns an +# R-line into just another G-line. The exceptions are that R-lines will # always use the full "nick!user@host realname" string, rather than only # user@host, but beware that only the ? and * wildcards are available, # and are the only way to specify where the space can occur if you do @@ -2089,7 +2130,7 @@ #<module name="starttls"> #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# -# SVSHold module: Implements SVSHOLD. Like Q:Lines, but can only be # +# SVSHold module: Implements SVSHOLD. Like Q-lines, but can only be # # added/removed by Services. # #<module name="svshold"> # SVSHOLD does not generate server notices by default, you can turn @@ -2185,7 +2226,7 @@ # <wsorigin allow="https://*.example.com/"> #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# -# XLine database: Stores all *Lines (G/Z/K/R/any added by other modules) +# XLine database: Stores all *-lines (G/Z/K/R/any added by other modules) # in a file which is re-loaded on restart. This is useful # for two reasons: it keeps bans so users may not evade them, and on # bigger networks, server connections will take less time as there will diff --git a/include/bancache.h b/include/bancache.h index 6e19e1ebe..e0c84ab54 100644 --- a/include/bancache.h +++ b/include/bancache.h @@ -62,7 +62,7 @@ class CoreExport BanCacheManager * @param ip The IP the item is for. * @param type The type of ban cache item. std::string. .empty() means it's a negative match (user is allowed freely). * @param reason The reason for the ban. Left .empty() if it's a negative match. - * @param seconds Number of seconds before nuking the bancache entry, the default is a day. This might seem long, but entries will be removed as glines/etc expire. + * @param seconds Number of seconds before nuking the bancache entry, the default is a day. This might seem long, but entries will be removed as G-lines/etc expire. */ BanCacheHit *AddHit(const std::string &ip, const std::string &type, const std::string &reason, time_t seconds = 0); BanCacheHit *GetHit(const std::string &ip); diff --git a/include/clientprotocol.h b/include/clientprotocol.h index 10b70e80b..ec033e166 100644 --- a/include/clientprotocol.h +++ b/include/clientprotocol.h @@ -549,7 +549,7 @@ class ClientProtocol::MessageTagProvider : public Events::ModuleEventListener * MOD_RES_PASSTHRU to make no decision. If no hooks accept a tag, the tag is rejected. * The default implementation returns MOD_RES_PASSTHRU. */ - virtual ModResult OnClientProtocolProcessTag(User* user, const std::string& tagname, std::string& tagvalue) + virtual ModResult OnProcessTag(User* user, const std::string& tagname, std::string& tagvalue) { return MOD_RES_PASSTHRU; } diff --git a/include/configreader.h b/include/configreader.h index 4360b8661..511bedbee 100644 --- a/include/configreader.h +++ b/include/configreader.h @@ -332,18 +332,6 @@ class CoreExport ServerConfig */ std::string ServerDesc; - /** Pretend disabled commands don't exist. - */ - bool DisabledDontExist; - - /** This variable identifies which usermodes have been diabled. - */ - std::bitset<64> DisabledUModes; - - /** This variable identifies which chanmodes have been disabled. - */ - std::bitset<64> DisabledCModes; - /** How to treat a user in a channel who is banned. */ BannedUserTreatment RestrictBannedUsers; @@ -379,8 +367,8 @@ class CoreExport ServerConfig /** The number of seconds that the server clock can skip by before server operators are warned. */ time_t TimeSkipWarn; - /** True if we're going to hide ban reasons for non-opers (e.g. G-Lines, - * K-Lines, Z-Lines) + /** True if we're going to hide ban reasons for non-opers (e.g. G-lines, + * K-lines, Z-lines) */ bool HideBans; @@ -466,9 +454,6 @@ class CoreExport ServerConfig void Fill(); - /** Disables the commands specified in <disabled:commands>. */ - bool ApplyDisabledCommands(); - /** Escapes a value for storage in a configuration key. * @param str The string to escape. * @param xml Are we using the XML config format? diff --git a/include/ctables.h b/include/ctables.h index 8be40cc54..1c7d5b4bd 100644 --- a/include/ctables.h +++ b/include/ctables.h @@ -163,10 +163,6 @@ class CoreExport CommandBase : public ServiceProvider */ unsigned long use_count; - /** True if the command is disabled to non-opers - */ - bool disabled; - /** True if the command can be issued before registering */ bool works_before_reg; @@ -212,23 +208,6 @@ class CoreExport CommandBase : public ServiceProvider */ virtual void EncodeParameter(std::string& parameter, unsigned int index); - /** Disable or enable this command. - * @param setting True to disable the command. - */ - void Disable(bool setting) - { - disabled = setting; - } - - /** Obtain this command's disable state. - * @return true if the command is currently disabled - * (disabled commands can be used only by operators) - */ - bool IsDisabled() - { - return disabled; - } - /** @return true if the command works before registration. */ bool WorksBeforeReg() diff --git a/include/hashcomp.h b/include/hashcomp.h index f0e092729..80c02332d 100644 --- a/include/hashcomp.h +++ b/include/hashcomp.h @@ -197,7 +197,10 @@ namespace irc public: /** Create a tokenstream and fill it with the provided data. */ - tokenstream(const std::string& msg, size_t start = 0); + tokenstream(const std::string& msg, size_t start = 0, size_t end = std::string::npos); + + /** Retrieves the underlying message. */ + std::string& GetMessage() { return message; } /** Retrieve the next \<middle> token in the token stream. * @param token The next token available, or an empty string if none remain. diff --git a/include/inspircd.h b/include/inspircd.h index 8ca2314eb..f5c7dbafb 100644 --- a/include/inspircd.h +++ b/include/inspircd.h @@ -284,7 +284,7 @@ class CoreExport InspIRCd */ TimerManager Timers; - /** X-Line manager. Handles G/K/Q/E line setting, removal and matching + /** X-line manager. Handles G/K/Q/E-line setting, removal and matching */ XLineManager* XLines; diff --git a/include/inspsocket.h b/include/inspsocket.h index e432f9c16..69fdaac8b 100644 --- a/include/inspsocket.h +++ b/include/inspsocket.h @@ -312,8 +312,9 @@ class CoreExport StreamSocket : public EventHandler /** Called when the endpoint addresses are changed. * @param local The new local endpoint. * @param remote The new remote endpoint. + * @return true if the connection is still open, false if it has been closed */ - virtual void OnSetEndPoint(const irc::sockets::sockaddrs& local, const irc::sockets::sockaddrs& remote) { } + virtual bool OnSetEndPoint(const irc::sockets::sockaddrs& local, const irc::sockets::sockaddrs& remote); /** Send the given data out the socket, either now or when writes unblock */ diff --git a/include/modules.h b/include/modules.h index b4f13c6b7..b8c860fbc 100644 --- a/include/modules.h +++ b/include/modules.h @@ -99,7 +99,8 @@ struct ModResult { /** InspIRCd major version. * 1.2 -> 102; 2.1 -> 201; 2.12 -> 212 */ -#define INSPIRCD_VERSION_MAJ 202 +#define INSPIRCD_VERSION_MAJ 300 + /** InspIRCd API version. * If you change any API elements, increment this value. This counter should be * reset whenever the major version is changed. Modules can use these two values diff --git a/include/users.h b/include/users.h index ef19adb5d..3937f74aa 100644 --- a/include/users.h +++ b/include/users.h @@ -380,9 +380,9 @@ class CoreExport User : public Extensible /** Sets the client IP for this user * @return true if the conversion was successful */ - virtual bool SetClientIP(const std::string& address, bool recheck_eline = true); + virtual bool SetClientIP(const std::string& address); - virtual void SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline = true); + virtual void SetClientIP(const irc::sockets::sockaddrs& sa); /** Constructor * @throw CoreException if the UID allocated to the user already exists @@ -681,15 +681,18 @@ class CoreExport User : public Extensible class CoreExport UserIOHandler : public StreamSocket { + private: + size_t checked_until; public: LocalUser* const user; UserIOHandler(LocalUser* me) : StreamSocket(StreamSocket::SS_USER) + , checked_until(0) , user(me) { } void OnDataReady() CXX11_OVERRIDE; - void OnSetEndPoint(const irc::sockets::sockaddrs& local, const irc::sockets::sockaddrs& remote) CXX11_OVERRIDE; + bool OnSetEndPoint(const irc::sockets::sockaddrs& local, const irc::sockets::sockaddrs& remote) CXX11_OVERRIDE; void OnError(BufferedSocketError error) CXX11_OVERRIDE; /** Adds to the user's write buffer. @@ -784,7 +787,7 @@ class CoreExport LocalUser : public User, public insp::intrusive_list_node<Local */ unsigned int lastping:1; - /** This is true if the user matched an exception (E:Line). It is used to save time on ban checks. + /** This is true if the user matched an exception (E-line). It is used to save time on ban checks. */ unsigned int exempt:1; @@ -803,14 +806,14 @@ class CoreExport LocalUser : public User, public insp::intrusive_list_node<Local already_sent_t already_sent; - /** Check if the user matches a G or K line, and disconnect them if they do. - * @param doZline True if ZLines should be checked (if IP has changed since initial connect) + /** Check if the user matches a G- or K-line, and disconnect them if they do. + * @param doZline True if Z-lines should be checked (if IP has changed since initial connect) * Returns true if the user matched a ban, false else. */ bool CheckLines(bool doZline = false); /** Use this method to fully connect a user. - * This will send the message of the day, check G/K/E lines, etc. + * This will send the message of the day, check G/K/E-lines, etc. */ void FullConnect(); @@ -820,9 +823,9 @@ class CoreExport LocalUser : public User, public insp::intrusive_list_node<Local */ void SetClass(const std::string &explicit_name = ""); - bool SetClientIP(const std::string& address, bool recheck_eline = true) CXX11_OVERRIDE; + bool SetClientIP(const std::string& address) CXX11_OVERRIDE; - void SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline = true) CXX11_OVERRIDE; + void SetClientIP(const irc::sockets::sockaddrs& sa) CXX11_OVERRIDE; /** Send a NOTICE message from the local server to the user. * The message will be sent even if the user is connected to a remote server. diff --git a/include/xline.h b/include/xline.h index 44f16cadf..dbb89277b 100644 --- a/include/xline.h +++ b/include/xline.h @@ -22,7 +22,7 @@ #pragma once -/** XLine is the base class for ban lines such as G lines and K lines. +/** XLine is the base class for ban lines such as G-lines and K-lines. * Modules may derive from this, and their xlines will automatically be * handled as expected by any protocol modules (e.g. m_spanningtree will * propogate them using AddLine). The process of translating a type+pattern @@ -67,7 +67,7 @@ class CoreExport XLine : public classbase } /** Change creation time of an xline. Updates expiry - * to be after the creation time + * to be after the creation time. */ virtual void SetCreateTime(time_t created) { @@ -102,7 +102,7 @@ class CoreExport XLine : public classbase virtual void Unset() { } /** Called when the expiry message is to be displayed for the - * line. Usually a line in the form 'expiring Xline blah, set by...' + * line. Usually a line in the form 'expiring X-line blah, set by...' * see the DisplayExpiry methods of GLine, ELine etc. */ virtual void DisplayExpiry(); @@ -111,7 +111,7 @@ class CoreExport XLine : public classbase * e.g. '*\@foo' or '*baz*'. This must always return the full pattern * in a form which can be used to construct an entire derived xline, * even if it is stored differently internally (e.g. GLine stores the - * ident and host parts seperately but will still return ident\@host + * ident and host parts separately but will still return ident\@host * for its Displayable() method). */ virtual const std::string& Displayable() = 0; @@ -157,7 +157,7 @@ class CoreExport KLine : public XLine { public: - /** Create a K-Line. + /** Create a K-line. * @param s_time The set time * @param d The duration of the xline * @param src The sender of the xline @@ -203,7 +203,7 @@ class CoreExport KLine : public XLine class CoreExport GLine : public XLine { public: - /** Create a G-Line. + /** Create a G-line. * @param s_time The set time * @param d The duration of the xline * @param src The sender of the xline @@ -247,7 +247,7 @@ class CoreExport GLine : public XLine class CoreExport ELine : public XLine { public: - /** Create an E-Line. + /** Create an E-line. * @param s_time The set time * @param d The duration of the xline * @param src The sender of the xline @@ -291,7 +291,7 @@ class CoreExport ELine : public XLine class CoreExport ZLine : public XLine { public: - /** Create a Z-Line. + /** Create a Z-line. * @param s_time The set time * @param d The duration of the xline * @param src The sender of the xline @@ -327,7 +327,7 @@ class CoreExport ZLine : public XLine class CoreExport QLine : public XLine { public: - /** Create a G-Line. + /** Create a Q-line. * @param s_time The set time * @param d The duration of the xline * @param src The sender of the xline @@ -399,7 +399,7 @@ class CoreExport XLineFactory virtual ~XLineFactory() { } }; -/** XLineManager is a class used to manage glines, klines, elines, zlines and qlines, +/** XLineManager is a class used to manage G-lines, K-lines, E-lines, Z-lines and Q-lines, * or any other line created by a module. It also manages XLineFactory classes which * can generate a specialized XLine for use by another module. */ @@ -436,7 +436,7 @@ class CoreExport XLineManager */ IdentHostPair IdentSplit(const std::string &ident_and_host); - /** Checks what users match e:lines and sets their ban exempt flag accordingly. + /** Checks what users match E-lines and sets their ban exempt flag accordingly. */ void CheckELines(); @@ -476,7 +476,7 @@ class CoreExport XLineManager /** Registers an xline factory. * An xline factory is a class which when given a particular xline type, * will generate a new XLine specialized to that type. For example if you - * pass the XLineFactory that handles glines some data it will return a + * pass the XLineFactory that handles G-lines some data it will return a * pointer to a GLine, polymorphically represented as XLine. This is used where * you do not know the full details of the item you wish to create, e.g. in a * server protocol module like m_spanningtree, when you receive xlines from other diff --git a/src/clientprotocol.cpp b/src/clientprotocol.cpp index a732855a5..212d65d6b 100644 --- a/src/clientprotocol.cpp +++ b/src/clientprotocol.cpp @@ -35,7 +35,7 @@ bool ClientProtocol::Serializer::HandleTag(LocalUser* user, const std::string& t for (::Events::ModuleEventProvider::SubscriberList::const_iterator i = list.begin(); i != list.end(); ++i) { MessageTagProvider* const tagprov = static_cast<MessageTagProvider*>(*i); - const ModResult res = tagprov->OnClientProtocolProcessTag(user, tagname, tagvalue); + const ModResult res = tagprov->OnProcessTag(user, tagname, tagvalue); if (res == MOD_RES_ALLOW) return tags.insert(std::make_pair(tagname, MessageTagData(tagprov, tagvalue))).second; else if (res == MOD_RES_DENY) diff --git a/src/command_parse.cpp b/src/command_parse.cpp index c2ae39d49..7a732f8b5 100644 --- a/src/command_parse.cpp +++ b/src/command_parse.cpp @@ -266,24 +266,6 @@ void CommandParser::ProcessCommand(LocalUser* user, std::string& command, Comman } } - if ((user->registered == REG_ALL) && (!user->IsOper()) && (handler->IsDisabled())) - { - /* command is disabled! */ - user->CommandFloodPenalty += failpenalty; - if (ServerInstance->Config->DisabledDontExist) - { - user->WriteNumeric(ERR_UNKNOWNCOMMAND, command, "Unknown command"); - } - else - { - user->WriteNumeric(ERR_UNKNOWNCOMMAND, command, "This command has been disabled."); - } - - ServerInstance->SNO->WriteToSnoMask('a', "%s denied for %s (%s@%s)", - command.c_str(), user->nick.c_str(), user->ident.c_str(), user->GetRealHost().c_str()); - return; - } - if ((!command_p.empty()) && (command_p.back().empty()) && (!handler->allow_empty_last_param)) command_p.pop_back(); @@ -333,7 +315,6 @@ CommandBase::CommandBase(Module* mod, const std::string& cmd, unsigned int minpa , min_params(minpara) , max_params(maxpara) , use_count(0) - , disabled(false) , works_before_reg(false) , allow_empty_last_param(true) , Penalty(1) diff --git a/src/configreader.cpp b/src/configreader.cpp index ce03f1d9e..5a0ceff06 100644 --- a/src/configreader.cpp +++ b/src/configreader.cpp @@ -72,31 +72,6 @@ ServerConfig::~ServerConfig() delete EmptyTag; } -bool ServerConfig::ApplyDisabledCommands() -{ - // Enable everything first. - const CommandParser::CommandMap& commands = ServerInstance->Parser.GetCommands(); - for (CommandParser::CommandMap::const_iterator x = commands.begin(); x != commands.end(); ++x) - x->second->Disable(false); - - // Now disable the commands specified in the config. - std::string command; - irc::spacesepstream commandlist(ConfValue("disabled")->getString("commands")); - while (commandlist.GetToken(command)) - { - Command* handler = ServerInstance->Parser.GetHandler(command); - if (!handler) - { - ServerInstance->Logs->Log("CONFIG", LOG_DEBUG, "Unable to disable the %s command as it does not exist!", command.c_str()); - continue; - } - - ServerInstance->Logs->Log("CONFIG", LOG_DEBUG, "The %s command has been disabled", command.c_str()); - handler->Disable(true); - } - return true; -} - static void ReadXLine(ServerConfig* conf, const std::string& tag, const std::string& key, XLineFactory* make) { ConfigTagList tags = conf->ConfTags(tag); @@ -378,7 +353,6 @@ void ServerConfig::Fill() ServerDesc = server->getString("description", "Configure Me"); Network = server->getString("network", "Network"); NetBufferSize = ConfValue("performance")->getInt("netbuffersize", 10240, 1024, 65534); - DisabledDontExist = ConfValue("disabled")->getBool("fakenonexistant"); CustomVersion = security->getString("customversion"); HideBans = security->getBool("hidebans"); HideServer = security->getString("hideserver", security->getString("hidewhois")); @@ -429,25 +403,6 @@ void ServerConfig::Fill() RestrictBannedUsers = ServerConfig::BUT_RESTRICT_NOTIFY; else throw CoreException(restrictbannedusers + " is an invalid <options:restrictbannedusers> value, at " + options->getTagLocation()); - - DisabledUModes.reset(); - std::string modes = ConfValue("disabled")->getString("usermodes"); - for (std::string::const_iterator p = modes.begin(); p != modes.end(); ++p) - { - // Complain when the character is not a valid mode character. - if (!ModeParser::IsModeChar(*p)) - throw CoreException("Invalid usermode " + std::string(1, *p) + " was found."); - DisabledUModes.set(*p - 'A'); - } - - DisabledCModes.reset(); - modes = ConfValue("disabled")->getString("chanmodes"); - for (std::string::const_iterator p = modes.begin(); p != modes.end(); ++p) - { - if (!ModeParser::IsModeChar(*p)) - throw CoreException("Invalid chanmode " + std::string(1, *p) + " was found."); - DisabledCModes.set(*p - 'A'); - } } // WARNING: it is not safe to use most of the codebase in this function, as it @@ -723,7 +678,6 @@ void ConfigReaderThread::Finish() ServerInstance->Users.RehashCloneCounts(); ServerInstance->XLines->CheckELines(); ServerInstance->XLines->ApplyLines(); - Config->ApplyDisabledCommands(); User* user = ServerInstance->FindNick(TheUserUID); ConfigStatus status(user); diff --git a/src/coremods/core_hostname_lookup.cpp b/src/coremods/core_hostname_lookup.cpp index ec93732b1..85d0f530c 100644 --- a/src/coremods/core_hostname_lookup.cpp +++ b/src/coremods/core_hostname_lookup.cpp @@ -193,18 +193,14 @@ class ModuleHostnameLookup : public Module void OnSetUserIP(LocalUser* user) CXX11_OVERRIDE { + // If core_dns is not loaded or hostname resolution is disabled for the user's + // connect class then the logic in this function does not apply. if (!DNS || !user->MyClass->resolvehostnames) - { - user->WriteNotice("*** Skipping host resolution (disabled by server administrator)"); return; - } // Clients can't have a DNS hostname if they aren't connected via IPv4 or IPv6. if (user->client_sa.family() != AF_INET && user->client_sa.family() != AF_INET6) - { - user->WriteNotice("*** Skipping host resolution (connected via a non-IP socket)"); return; - } user->WriteNotice("*** Looking up your hostname..."); diff --git a/src/coremods/core_info/cmd_version.cpp b/src/coremods/core_info/cmd_version.cpp index 29d96169e..57f9b05cf 100644 --- a/src/coremods/core_info/cmd_version.cpp +++ b/src/coremods/core_info/cmd_version.cpp @@ -29,8 +29,12 @@ CommandVersion::CommandVersion(Module* parent) CmdResult CommandVersion::Handle(User* user, const Params& parameters) { - std::string version = ServerInstance->GetVersionString((user->IsOper())); - user->WriteNumeric(RPL_VERSION, version); + Numeric::Numeric numeric(RPL_VERSION); + irc::tokenstream tokens(ServerInstance->GetVersionString(user->IsOper())); + for (std::string token; tokens.GetTrailing(token); ) + numeric.push(token); + user->WriteNumeric(numeric); + LocalUser *lu = IS_LOCAL(user); if (lu != NULL) { diff --git a/src/coremods/core_privmsg.cpp b/src/coremods/core_privmsg.cpp index dae770abe..692a661b3 100644 --- a/src/coremods/core_privmsg.cpp +++ b/src/coremods/core_privmsg.cpp @@ -95,12 +95,24 @@ class MessageCommandBase : public Command ChanModeReference noextmsgmode; /** Send a PRIVMSG or NOTICE message to all local users from the given user - * @param user User sending the message - * @param msg The message to send - * @param mt Type of the message (MSG_PRIVMSG or MSG_NOTICE) - * @param tags Message tags to include in the outgoing protocol message + * @param source The user sending the message. + * @param msg The details of the message to send. */ - static void SendAll(User* user, const std::string& msg, MessageType mt, const ClientProtocol::TagMap& tags); + static void SendAll(User* source, const MessageDetails& details) + { + ClientProtocol::Messages::Privmsg message(ClientProtocol::Messages::Privmsg::nocopy, source, "$*", details.text, details.type); + message.AddTags(details.tags_out); + message.SetSideEffect(true); + ClientProtocol::Event messageevent(ServerInstance->GetRFCEvents().privmsg, message); + + const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers(); + for (UserManager::LocalList::const_iterator i = list.begin(); i != list.end(); ++i) + { + LocalUser* user = *i; + if ((user->registered == REG_ALL) && (!details.exemptions.count(user))) + user->Send(messageevent); + } + } public: MessageCommandBase(Module* parent, MessageType mt) @@ -128,21 +140,6 @@ class MessageCommandBase : public Command } }; -void MessageCommandBase::SendAll(User* user, const std::string& msg, MessageType mt, const ClientProtocol::TagMap& tags) -{ - ClientProtocol::Messages::Privmsg message(ClientProtocol::Messages::Privmsg::nocopy, user, "$*", msg, mt); - message.AddTags(tags); - message.SetSideEffect(true); - ClientProtocol::Event messageevent(ServerInstance->GetRFCEvents().privmsg, message); - - const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers(); - for (UserManager::LocalList::const_iterator i = list.begin(); i != list.end(); ++i) - { - if ((*i)->registered == REG_ALL) - (*i)->Send(messageevent); - } -} - CmdResult MessageCommandBase::HandleMessage(User* user, const Params& parameters, MessageType mt) { User *dest; @@ -171,7 +168,7 @@ CmdResult MessageCommandBase::HandleMessage(User* user, const Params& parameters FOREACH_MOD(OnUserMessage, (user, msgtarget, msgdetails)); if (InspIRCd::Match(ServerInstance->Config->ServerName, servername, NULL)) { - SendAll(user, msgdetails.text, mt, msgdetails.tags_out); + SendAll(user, msgdetails); } FOREACH_MOD(OnUserPostMessage, (user, msgtarget, msgdetails)); return CMD_SUCCESS; diff --git a/src/coremods/core_serialize_rfc.cpp b/src/coremods/core_serialize_rfc.cpp index 1ba330146..23a4c2052 100644 --- a/src/coremods/core_serialize_rfc.cpp +++ b/src/coremods/core_serialize_rfc.cpp @@ -19,11 +19,20 @@ #include "inspircd.h" +enum +{ + // From ircu. + ERR_INPUTTOOLONG = 417 +}; + class RFCSerializer : public ClientProtocol::Serializer { - /** Maximum size of the message tags portion of the message, including the `@` and the trailing space characters. - */ - static const std::string::size_type MAX_MESSAGE_TAG_LENGTH = 512; + + /** The maximum size of client-originated message tags in an incoming message including the `@`. */ + static const std::string::size_type MAX_CLIENT_MESSAGE_TAG_LENGTH = 4095; + + /** The maximum size of server-originated message tags in an outgoing message including the `@`. */ + static const std::string::size_type MAX_SERVER_MESSAGE_TAG_LENGTH = 511; static void SerializeTags(const ClientProtocol::TagMap& tags, const ClientProtocol::TagSelection& tagwl, std::string& line); @@ -47,15 +56,32 @@ bool RFCSerializer::Parse(LocalUser* user, const std::string& line, ClientProtoc return false; } - ServerInstance->Logs->Log("USERINPUT", LOG_RAWIO, "C[%s] I %s", user->uuid.c_str(), line.c_str()); + // Work out how long the message can actually be. + size_t maxline = ServerInstance->Config->Limits.MaxLine - start - 2; + if (line[start] == '@') + maxline += MAX_CLIENT_MESSAGE_TAG_LENGTH + 1; - irc::tokenstream tokens(line, start); - std::string token; + irc::tokenstream tokens(line, start, maxline); + ServerInstance->Logs->Log("USERINPUT", LOG_RAWIO, "C[%s] I %s", user->uuid.c_str(), tokens.GetMessage().c_str()); // This will always exist because of the check at the start of the function. + std::string token; tokens.GetMiddle(token); if (token[0] == '@') { + // Check that the client tags fit within the client tag space. + if (token.length() > MAX_CLIENT_MESSAGE_TAG_LENGTH) + { + user->WriteNumeric(ERR_INPUTTOOLONG, "Input line was too long"); + user->CommandFloodPenalty += 2000; + return false; + } + + // Truncate the RFC part of the message if it is too long. + size_t maxrfcline = token.length() + ServerInstance->Config->Limits.MaxLine - 1; + if (tokens.GetMessage().length() > maxrfcline) + tokens.GetMessage().erase(maxrfcline); + // Line begins with message tags, parse them. std::string tagval; irc::sepstream ss(token.substr(1), ';'); @@ -78,7 +104,6 @@ bool RFCSerializer::Parse(LocalUser* user, const std::string& line, ClientProtoc HandleTag(user, token, tagval, parseoutput.tags); } - // Try to read the prefix or command name. if (!tokens.GetMiddle(token)) { @@ -114,17 +139,29 @@ bool RFCSerializer::Parse(LocalUser* user, const std::string& line, ClientProtoc return true; } +namespace +{ + void CheckTagLength(std::string& line, size_t prevsize, size_t& length, size_t maxlength) + { + const std::string::size_type diffsize = line.size() - prevsize; + if (length + diffsize > maxlength) + line.erase(prevsize); + else + length += diffsize; + } +} + void RFCSerializer::SerializeTags(const ClientProtocol::TagMap& tags, const ClientProtocol::TagSelection& tagwl, std::string& line) { - char prefix = '@'; // First tag name is prefixed with a '@' + size_t client_tag_length = 0; + size_t server_tag_length = 0; for (ClientProtocol::TagMap::const_iterator i = tags.begin(); i != tags.end(); ++i) { if (!tagwl.IsSelected(tags, i)) continue; const std::string::size_type prevsize = line.size(); - line.push_back(prefix); - prefix = ';'; // Remaining tags are prefixed with ';' + line.push_back(prevsize ? ';' : '@'); line.append(i->first); const std::string& val = i->second.value; if (!val.empty()) @@ -133,16 +170,14 @@ void RFCSerializer::SerializeTags(const ClientProtocol::TagMap& tags, const Clie line.append(val); } - // The tags part of the message mustn't grow longer than what is allowed by the spec. If it does, - // remove last tag and stop adding more tags. - // - // One is subtracted from the limit before comparing because there must be a ' ' char after the last tag - // which also counts towards the limit. - if (line.size() > MAX_MESSAGE_TAG_LENGTH-1) - { - line.erase(prevsize); - break; - } + // The tags part of the message must not contain more client and server tags than allowed by the + // message tags specification. This is complicated by the tag space having separate limits for + // both server-originated and client-originated tags. If either of the tag limits is exceeded then + // the most recently added tag is removed. + if (i->first[0] == '+') + CheckTagLength(line, prevsize, client_tag_length, MAX_CLIENT_MESSAGE_TAG_LENGTH); + else + CheckTagLength(line, prevsize, server_tag_length, MAX_SERVER_MESSAGE_TAG_LENGTH); } if (!line.empty()) diff --git a/src/coremods/core_xline/cmd_eline.cpp b/src/coremods/core_xline/cmd_eline.cpp index a3a4d9466..3010e0f61 100644 --- a/src/coremods/core_xline/cmd_eline.cpp +++ b/src/coremods/core_xline/cmd_eline.cpp @@ -50,7 +50,7 @@ CmdResult CommandEline::Handle(User* user, const Params& parameters) if (ih.first.empty()) { - user->WriteNotice("*** Target not found"); + user->WriteNotice("*** Target not found."); return CMD_FAILURE; } @@ -61,7 +61,7 @@ CmdResult CommandEline::Handle(User* user, const Params& parameters) unsigned long duration; if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for E-line"); + user->WriteNotice("*** Invalid duration for E-line."); return CMD_FAILURE; } ELine* el = new ELine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str()); @@ -82,7 +82,7 @@ CmdResult CommandEline::Handle(User* user, const Params& parameters) else { delete el; - user->WriteNotice("*** E-Line for " + target + " already exists"); + user->WriteNotice("*** E-line for " + target + " already exists."); } } else @@ -93,7 +93,7 @@ CmdResult CommandEline::Handle(User* user, const Params& parameters) } else { - user->WriteNotice("*** E-Line " + target + " not found in list, try /stats e"); + user->WriteNotice("*** E-line " + target + " not found in list, try /stats e."); } } diff --git a/src/coremods/core_xline/cmd_gline.cpp b/src/coremods/core_xline/cmd_gline.cpp index a9de707c4..60dcd714a 100644 --- a/src/coremods/core_xline/cmd_gline.cpp +++ b/src/coremods/core_xline/cmd_gline.cpp @@ -50,7 +50,7 @@ CmdResult CommandGline::Handle(User* user, const Params& parameters) if (ih.first.empty()) { - user->WriteNotice("*** Target not found"); + user->WriteNotice("*** Target not found."); return CMD_FAILURE; } @@ -60,14 +60,14 @@ CmdResult CommandGline::Handle(User* user, const Params& parameters) else if (target.find('!') != std::string::npos) { - user->WriteNotice("*** G-Line cannot operate on nick!user@host masks"); + user->WriteNotice("*** G-line cannot operate on nick!user@host masks."); return CMD_FAILURE; } unsigned long duration; if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for G-line"); + user->WriteNotice("*** Invalid duration for G-line."); return CMD_FAILURE; } GLine* gl = new GLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str()); @@ -90,7 +90,7 @@ CmdResult CommandGline::Handle(User* user, const Params& parameters) else { delete gl; - user->WriteNotice("** G-Line for " + target + " already exists"); + user->WriteNotice("** G-line for " + target + " already exists."); } } @@ -102,7 +102,7 @@ CmdResult CommandGline::Handle(User* user, const Params& parameters) } else { - user->WriteNotice("*** G-Line " + target + " not found in list, try /stats g."); + user->WriteNotice("*** G-line " + target + " not found in list, try /stats g."); } } diff --git a/src/coremods/core_xline/cmd_kline.cpp b/src/coremods/core_xline/cmd_kline.cpp index 9b474d16c..813b9afa6 100644 --- a/src/coremods/core_xline/cmd_kline.cpp +++ b/src/coremods/core_xline/cmd_kline.cpp @@ -50,7 +50,7 @@ CmdResult CommandKline::Handle(User* user, const Params& parameters) if (ih.first.empty()) { - user->WriteNotice("*** Target not found"); + user->WriteNotice("*** Target not found."); return CMD_FAILURE; } @@ -60,14 +60,14 @@ CmdResult CommandKline::Handle(User* user, const Params& parameters) if (target.find('!') != std::string::npos) { - user->WriteNotice("*** K-Line cannot operate on nick!user@host masks"); + user->WriteNotice("*** K-line cannot operate on nick!user@host masks."); return CMD_FAILURE; } unsigned long duration; if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for K-line"); + user->WriteNotice("*** Invalid duration for K-line."); return CMD_FAILURE; } KLine* kl = new KLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str()); @@ -90,7 +90,7 @@ CmdResult CommandKline::Handle(User* user, const Params& parameters) else { delete kl; - user->WriteNotice("*** K-Line for " + target + " already exists"); + user->WriteNotice("*** K-line for " + target + " already exists."); } } else @@ -101,7 +101,7 @@ CmdResult CommandKline::Handle(User* user, const Params& parameters) } else { - user->WriteNotice("*** K-Line " + target + " not found in list, try /stats k."); + user->WriteNotice("*** K-line " + target + " not found in list, try /stats k."); } } diff --git a/src/coremods/core_xline/cmd_qline.cpp b/src/coremods/core_xline/cmd_qline.cpp index 893c8d213..086d860fc 100644 --- a/src/coremods/core_xline/cmd_qline.cpp +++ b/src/coremods/core_xline/cmd_qline.cpp @@ -40,14 +40,14 @@ CmdResult CommandQline::Handle(User* user, const Params& parameters) if (parameters[0].find('@') != std::string::npos || parameters[0].find('!') != std::string::npos || parameters[0].find('.') != std::string::npos) { - user->WriteNotice("*** A Q-Line only bans a nick pattern, not a nick!user@host pattern."); + user->WriteNotice("*** A Q-line only bans a nick pattern, not a nick!user@host pattern."); return CMD_FAILURE; } unsigned long duration; if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for Q-line"); + user->WriteNotice("*** Invalid duration for Q-line."); return CMD_FAILURE; } QLine* ql = new QLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str()); @@ -69,7 +69,7 @@ CmdResult CommandQline::Handle(User* user, const Params& parameters) else { delete ql; - user->WriteNotice("*** Q-Line for " + parameters[0] + " already exists"); + user->WriteNotice("*** Q-line for " + parameters[0] + " already exists."); } } else @@ -80,7 +80,7 @@ CmdResult CommandQline::Handle(User* user, const Params& parameters) } else { - user->WriteNotice("*** Q-Line " + parameters[0] + " not found in list, try /stats q."); + user->WriteNotice("*** Q-line " + parameters[0] + " not found in list, try /stats q."); return CMD_FAILURE; } } diff --git a/src/coremods/core_xline/cmd_zline.cpp b/src/coremods/core_xline/cmd_zline.cpp index e81fc727f..31030adce 100644 --- a/src/coremods/core_xline/cmd_zline.cpp +++ b/src/coremods/core_xline/cmd_zline.cpp @@ -38,7 +38,7 @@ CmdResult CommandZline::Handle(User* user, const Params& parameters) { if (target.find('!') != std::string::npos) { - user->WriteNotice("*** You cannot include a nickname in a zline, a zline must ban only an IP mask"); + user->WriteNotice("*** You cannot include a nickname in a Z-line, a Z-line must ban only an IP mask."); return CMD_FAILURE; } @@ -65,7 +65,7 @@ CmdResult CommandZline::Handle(User* user, const Params& parameters) unsigned long duration; if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for Z-line"); + user->WriteNotice("*** Invalid duration for Z-line."); return CMD_FAILURE; } ZLine* zl = new ZLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ipaddr); @@ -87,7 +87,7 @@ CmdResult CommandZline::Handle(User* user, const Params& parameters) else { delete zl; - user->WriteNotice("*** Z-Line for " + std::string(ipaddr) + " already exists"); + user->WriteNotice("*** Z-line for " + std::string(ipaddr) + " already exists."); } } else @@ -98,7 +98,7 @@ CmdResult CommandZline::Handle(User* user, const Params& parameters) } else { - user->WriteNotice("*** Z-Line " + target + " not found in list, try /stats Z."); + user->WriteNotice("*** Z-line " + target + " not found in list, try /stats Z."); return CMD_FAILURE; } } diff --git a/src/coremods/core_xline/core_xline.cpp b/src/coremods/core_xline/core_xline.cpp index ab80ab4ed..c53834fc0 100644 --- a/src/coremods/core_xline/core_xline.cpp +++ b/src/coremods/core_xline/core_xline.cpp @@ -64,18 +64,27 @@ class CoreModXLine : public Module { } + void OnSetUserIP(LocalUser* user) CXX11_OVERRIDE + { + if (user->quitting) + return; + + user->exempt = (ServerInstance->XLines->MatchesLine("E", user) != NULL); + user->CheckLines(true); + } + ModResult OnUserPreNick(LocalUser* user, const std::string& newnick) CXX11_OVERRIDE { - // Check Q-Lines (for local nick changes only, remote servers have our Q-Lines to enforce themselves) + // Check Q-lines (for local nick changes only, remote servers have our Q-lines to enforce themselves) XLine* xline = ServerInstance->XLines->MatchesLine("Q", newnick); if (!xline) return MOD_RES_PASSTHRU; // No match - // A Q-Line matched the new nick, tell opers if the user is registered + // A Q-line matched the new nick, tell opers if the user is registered if (user->registered == REG_ALL) { - ServerInstance->SNO->WriteGlobalSno('a', "Q-Lined nickname %s from %s: %s", + ServerInstance->SNO->WriteGlobalSno('a', "Q-lined nickname %s from %s: %s", newnick.c_str(), user->GetFullRealHost().c_str(), xline->reason.c_str()); } diff --git a/src/coremods/core_xline/core_xline.h b/src/coremods/core_xline/core_xline.h index 1e0bc74cc..c607797f1 100644 --- a/src/coremods/core_xline/core_xline.h +++ b/src/coremods/core_xline/core_xline.h @@ -70,7 +70,7 @@ class InsaneBan class CommandEline : public Command { public: - /** Constructor for eline. + /** Constructor for E-line. */ CommandEline(Module* parent); @@ -87,7 +87,7 @@ class CommandEline : public Command class CommandGline : public Command { public: - /** Constructor for gline. + /** Constructor for G-line. */ CommandGline(Module* parent); @@ -104,7 +104,7 @@ class CommandGline : public Command class CommandKline : public Command { public: - /** Constructor for kline. + /** Constructor for K-line. */ CommandKline(Module* parent); @@ -127,7 +127,7 @@ class CommandQline : public Command }; public: - /** Constructor for qline. + /** Constructor for Q-line. */ CommandQline(Module* parent); @@ -150,7 +150,7 @@ class CommandZline : public Command }; public: - /** Constructor for zline. + /** Constructor for Z-line. */ CommandZline(Module* parent); diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp index 8febcbb5f..a51430a4b 100644 --- a/src/hashcomp.cpp +++ b/src/hashcomp.cpp @@ -193,8 +193,8 @@ size_t irc::insensitive::operator()(const std::string &s) const return t; } -irc::tokenstream::tokenstream(const std::string& msg, size_t start) - : message(msg, start) +irc::tokenstream::tokenstream(const std::string& msg, size_t start, size_t end) + : message(msg, start, end) , position(0) { } diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 7e299700b..09e48ea1f 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -442,7 +442,6 @@ InspIRCd::InspIRCd(int argc, char** argv) : // Build ISupport as ModuleManager::LoadAll() does not do it this->ISupport.Build(); - Config->ApplyDisabledCommands(); if (!pl.empty()) { diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp index 69c427212..ebbff448e 100644 --- a/src/inspsocket.cpp +++ b/src/inspsocket.cpp @@ -358,6 +358,11 @@ void StreamSocket::FlushSendQ(SendQueue& sq) } } +bool StreamSocket::OnSetEndPoint(const irc::sockets::sockaddrs& local, const irc::sockets::sockaddrs& remote) +{ + return false; +} + void StreamSocket::WriteData(const std::string &data) { if (fd < 0) diff --git a/src/mode.cpp b/src/mode.cpp index 0bb97cc9e..459eb21c8 100644 --- a/src/mode.cpp +++ b/src/mode.cpp @@ -312,17 +312,6 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, Mode } } - if (IS_LOCAL(user) && !user->IsOper()) - { - const std::bitset<64>& disabled = (type == MODETYPE_CHANNEL) ? ServerInstance->Config->DisabledCModes : ServerInstance->Config->DisabledUModes; - if (disabled.test(modechar - 'A')) - { - user->WriteNumeric(ERR_NOPRIVILEGES, InspIRCd::Format("Permission Denied - %s mode %c has been locked by the administrator", - type == MODETYPE_CHANNEL ? "channel" : "user", modechar)); - return MODEACTION_DENY; - } - } - if ((adding) && (IS_LOCAL(user)) && (mh->NeedsOper()) && (!user->HasModePermission(mh))) { /* It's an oper only mode, and they don't have access to it. */ @@ -587,7 +576,8 @@ ModeHandler::Id ModeParser::AllocateModeId(ModeType mt) void ModeParser::AddMode(ModeHandler* mh) { if (!ModeParser::IsModeChar(mh->GetModeChar())) - throw ModuleException("Invalid letter for mode " + mh->name); + throw ModuleException(InspIRCd::Format("Mode letter for %s is invalid: %c", + mh->name.c_str(), mh->GetModeChar())); /* A mode prefix of ',' is not acceptable, it would fuck up server to server. * A mode prefix of ':' will fuck up both server to server, and client to server. @@ -597,15 +587,19 @@ void ModeParser::AddMode(ModeHandler* mh) if (pm) { if ((pm->GetPrefix() > 126) || (pm->GetPrefix() == ',') || (pm->GetPrefix() == ':') || (pm->GetPrefix() == '#')) - throw ModuleException("Invalid prefix for mode " + mh->name); + throw ModuleException(InspIRCd::Format("Mode prefix for %s is invalid: %c", + mh->name.c_str(), pm->GetPrefix())); - if (FindPrefix(pm->GetPrefix())) - throw ModuleException("Prefix already exists for mode " + mh->name); + PrefixMode* otherpm = FindPrefix(pm->GetPrefix()); + if (otherpm) + throw ModuleException(InspIRCd::Format("Mode prefix for %s already by used by %s from %s: %c", + mh->name.c_str(), otherpm->name.c_str(), otherpm->creator->ModuleSourceFile.c_str(), pm->GetPrefix())); } ModeHandler*& slot = modehandlers[mh->GetModeType()][mh->GetModeChar()-65]; if (slot) - throw ModuleException("Letter is already in use for mode " + mh->name); + throw ModuleException(InspIRCd::Format("Mode letter for %s already by used by %s from %s: %c", + mh->name.c_str(), slot->name.c_str(), slot->creator->ModuleSourceFile.c_str(), mh->GetModeChar())); // The mode needs an id if it is either a user mode, a simple mode (flag) or a parameter mode. // Otherwise (for listmodes and prefix modes) the id remains MODEID_MAX, which is invalid. @@ -613,8 +607,13 @@ void ModeParser::AddMode(ModeHandler* mh) if ((mh->GetModeType() == MODETYPE_USER) || (mh->IsParameterMode()) || (!mh->IsListMode())) modeid = AllocateModeId(mh->GetModeType()); - if (!modehandlersbyname[mh->GetModeType()].insert(std::make_pair(mh->name, mh)).second) - throw ModuleException("Mode name already in use: " + mh->name); + std::pair<ModeHandlerMap::iterator, bool> res = modehandlersbyname[mh->GetModeType()].insert(std::make_pair(mh->name, mh)); + if (!res.second) + { + ModeHandler* othermh = res.first->second; + throw ModuleException(InspIRCd::Format("Mode name %s already used by %c from %s", + mh->name.c_str(), othermh->GetModeChar(), othermh->creator->ModuleSourceFile.c_str())); + } // Everything is fine, add the mode diff --git a/src/modules/m_alias.cpp b/src/modules/m_alias.cpp index 4d1dd65c9..3e00db765 100644 --- a/src/modules/m_alias.cpp +++ b/src/modules/m_alias.cpp @@ -107,6 +107,7 @@ class ModuleAlias : public Module ModuleAlias() : botmode(this, "bot") + , active(false) { } diff --git a/src/modules/m_cban.cpp b/src/modules/m_cban.cpp index e0768aa88..3cdbbbdfb 100644 --- a/src/modules/m_cban.cpp +++ b/src/modules/m_cban.cpp @@ -114,7 +114,7 @@ class CommandCBan : public Command unsigned long duration; if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for CBan"); + user->WriteNotice("*** Invalid duration for CBan."); return CMD_FAILURE; } const char *reason = (parameters.size() > 2) ? parameters[2].c_str() : "No reason supplied"; @@ -202,7 +202,7 @@ class ModuleCBan : public Module, public Stats::EventListener Version GetVersion() CXX11_OVERRIDE { - return Version("Gives /cban, aka C:lines. Think Q:lines, for channels.", VF_COMMON | VF_VENDOR); + return Version("Gives /cban, aka C-lines. Think Q-lines, for channels.", VF_COMMON | VF_VENDOR); } }; diff --git a/src/modules/m_cgiirc.cpp b/src/modules/m_cgiirc.cpp index 4a5a4fb03..df8201bde 100644 --- a/src/modules/m_cgiirc.cpp +++ b/src/modules/m_cgiirc.cpp @@ -34,29 +34,6 @@ enum RPL_WHOISGATEWAY = 350 }; -// We need this method up here so that it can be accessed from anywhere -static void ChangeIP(LocalUser* user, const irc::sockets::sockaddrs& sa) -{ - // Set the users IP address and make sure they are in the right clone pool. - ServerInstance->Users->RemoveCloneCounts(user); - user->SetClientIP(sa); - ServerInstance->Users->AddClone(user); - if (user->quitting) - return; - - // Recheck the connect class. - user->MyClass = NULL; - user->SetClass(); - user->CheckClass(); - if (user->quitting) - return; - - // Check if this user matches any XLines. - user->CheckLines(true); - if (user->quitting) - return; -} - // Encapsulates information about an ident host. class IdentHost { @@ -215,7 +192,7 @@ class CommandWebIRC : public SplitCommand // Set the IP address sent via WEBIRC. We ignore the hostname and lookup // instead do our own DNS lookups because of unreliable gateways. - ChangeIP(user, ipaddr); + user->SetClientIP(ipaddr); return CMD_SUCCESS; } @@ -391,7 +368,7 @@ class ModuleCgiIRC user->uuid.c_str(), user->GetIPString().c_str(), address.addr().c_str(), user->ident.c_str(), newident.c_str()); user->ChangeIdent(newident); - ChangeIP(user, address); + user->SetClientIP(address); break; } return MOD_RES_PASSTHRU; diff --git a/src/modules/m_check.cpp b/src/modules/m_check.cpp index f820f2bd0..1d030acc6 100644 --- a/src/modules/m_check.cpp +++ b/src/modules/m_check.cpp @@ -200,7 +200,7 @@ class CommandCheck : public Command opcmdlist.Add(oper->AllowedOperCommands.ToString()); opcmdlist.Flush(); CheckContext::List privlist(context, "permissions"); - opcmdlist.Add(oper->AllowedPrivs.ToString()); + privlist.Add(oper->AllowedPrivs.ToString()); privlist.Flush(); } } diff --git a/src/modules/m_clearchan.cpp b/src/modules/m_clearchan.cpp index 016d28737..dec49866c 100644 --- a/src/modules/m_clearchan.cpp +++ b/src/modules/m_clearchan.cpp @@ -211,7 +211,7 @@ class ModuleClearChan : public Module Version GetVersion() CXX11_OVERRIDE { - return Version("Adds /CLEARCHAN that allows opers to masskick, masskill or mass-G/ZLine users on a channel", VF_VENDOR|VF_OPTCOMMON); + return Version("Adds /CLEARCHAN that allows opers to masskick, masskill or mass G/Z-line users on a channel.", VF_VENDOR|VF_OPTCOMMON); } }; diff --git a/src/modules/m_conn_umodes.cpp b/src/modules/m_conn_umodes.cpp index 1f2fe7455..3132aed40 100644 --- a/src/modules/m_conn_umodes.cpp +++ b/src/modules/m_conn_umodes.cpp @@ -38,10 +38,6 @@ class ModuleModesOnConnect : public Module void OnUserConnect(LocalUser* user) CXX11_OVERRIDE { - // Backup and zero out the disabled usermodes, so that we can override them here. - const std::bitset<64> save = ServerInstance->Config->DisabledUModes; - ServerInstance->Config->DisabledUModes.reset(); - ConfigTag* tag = user->MyClass->config; std::string ThisModes = tag->getString("modes"); if (!ThisModes.empty()) @@ -58,8 +54,6 @@ class ModuleModesOnConnect : public Module ServerInstance->Parser.CallHandler("MODE", modes, user); } - - ServerInstance->Config->DisabledUModes = save; } }; diff --git a/src/modules/m_connectban.cpp b/src/modules/m_connectban.cpp index d57ffca02..20121f5f9 100644 --- a/src/modules/m_connectban.cpp +++ b/src/modules/m_connectban.cpp @@ -73,7 +73,7 @@ class ModuleConnectBan : public Module if (i->second >= threshold) { - // Create zline for set duration. + // Create Z-line for set duration. ZLine* zl = new ZLine(ServerInstance->Time(), banduration, ServerInstance->Config->ServerName, banmessage, mask.str()); if (!ServerInstance->XLines->AddLine(zl, NULL)) { @@ -83,7 +83,7 @@ class ModuleConnectBan : public Module ServerInstance->XLines->ApplyLines(); std::string maskstr = mask.str(); std::string timestr = InspIRCd::TimeString(zl->expiry); - ServerInstance->SNO->WriteGlobalSno('x',"Module m_connectban added Z:line on *@%s to expire on %s: Connect flooding", + ServerInstance->SNO->WriteGlobalSno('x',"Module m_connectban added Z-line on %s to expire on %s: Connect flooding", maskstr.c_str(), timestr.c_str()); ServerInstance->SNO->WriteGlobalSno('a', "Connect flooding from IP range %s (%d)", maskstr.c_str(), threshold); connects.erase(i); diff --git a/src/modules/m_disable.cpp b/src/modules/m_disable.cpp new file mode 100644 index 000000000..203f9ee64 --- /dev/null +++ b/src/modules/m_disable.cpp @@ -0,0 +1,189 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2019 Peter Powell <petpow@saberuk.com> + * + * This file is part of InspIRCd. InspIRCd 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, version 2. + * + * 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, see <http://www.gnu.org/licenses/>. + */ + + +#include "inspircd.h" + +enum +{ + // From ircu. + ERR_DISABLED = 517 +}; + +// Holds a list of disabled commands. +typedef std::vector<std::string> CommandList; + +// Holds whether modes are disabled or not. +typedef std::bitset<64> ModeStatus; + +class ModuleDisable : public Module +{ + private: + CommandList commands; + ModeStatus chanmodes; + bool fakenonexistent; + bool notifyopers; + ModeStatus usermodes; + + void ReadModes(ConfigTag* tag, const std::string& field, ModeType type, ModeStatus& status) + { + const std::string modes = tag->getString(field); + for (std::string::const_iterator iter = modes.begin(); iter != modes.end(); ++iter) + { + const char& chr = *iter; + + // Check that the character is a valid mode letter. + if (!ModeParser::IsModeChar(chr)) + throw ModuleException(InspIRCd::Format("Invalid mode '%c' was specified in <disabled:%s> at %s", + chr, field.c_str(), tag->getTagLocation().c_str())); + + // Check that the mode actually exists. + ModeHandler* mh = ServerInstance->Modes->FindMode(chr, type); + if (!chr) + throw ModuleException(InspIRCd::Format("Non-existent mode '%c' was specified in <disabled:%s> at %s", + chr, field.c_str(), tag->getTagLocation().c_str())); + + // Disable the mode. + ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "The %c (%s) %s mode has been disabled", + mh->GetModeChar(), mh->name.c_str(), type == MODETYPE_CHANNEL ? "channel" : "user"); + status.set(chr - 'A'); + } + } + + void WriteLog(const char* message, ...) CUSTOM_PRINTF(2, 3) + { + std::string buffer; + VAFORMAT(buffer, message, message); + + if (notifyopers) + ServerInstance->SNO->WriteToSnoMask('a', buffer); + else + ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, buffer); + } + + public: + void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE + { + ConfigTag* tag = ServerInstance->Config->ConfValue("disabled"); + + // Parse the disabled commands. + CommandList newcommands; + irc::spacesepstream commandlist(tag->getString("commands")); + for (std::string command; commandlist.GetToken(command); ) + { + // Check that the command actually exists. + Command* handler = ServerInstance->Parser.GetHandler(command); + if (!handler) + throw ModuleException(InspIRCd::Format("Non-existent command '%s' was specified in <disabled:commands> at %s", + command.c_str(), tag->getTagLocation().c_str())); + + // Prevent admins from disabling COMMANDS and MODULES for transparency reasons. + if (handler->name == "COMMANDS" || handler->name == "MODULES") + continue; + + // Disable the command. + ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "The %s command has been disabled", handler->name.c_str()); + newcommands.push_back(handler->name); + } + + // Parse the disabled channel modes. + ModeStatus newchanmodes; + ReadModes(tag, "chanmodes", MODETYPE_CHANNEL, newchanmodes); + + // Parse the disabled user modes. + ModeStatus newusermodes; + ReadModes(tag, "usermodes", MODETYPE_USER, newusermodes); + + // The server config was valid so we can use these now. + chanmodes = newchanmodes; + usermodes = newusermodes; + commands.swap(newcommands); + + // Whether we should fake the non-existence of disabled things. + fakenonexistent = tag->getBool("fakenonexistent", tag->getBool("fakenonexistant")); + + // Whether to notify server operators via snomask `a` about the attempted use of disabled commands/modes. + notifyopers = tag->getBool("notifyopers"); + } + + ModResult OnPreCommand(std::string& command, CommandBase::Params& parameters, LocalUser* user, bool validated) CXX11_OVERRIDE + { + // If a command is unvalidated or the source is not registered we do nothing. + if (!validated || user->registered != REG_ALL) + return MOD_RES_PASSTHRU; + + // If the command is not disabled or the user has the servers/use-disabled-commands priv we do nothing. + if (!stdalgo::isin(commands, command) || user->HasPrivPermission("servers/use-disabled-commands")) + return MOD_RES_PASSTHRU; + + // The user has tried to execute a disabled command! + user->CommandFloodPenalty += 2000; + WriteLog("%s was blocked from executing the disabled %s command", user->GetFullRealHost().c_str(), command.c_str()); + + if (fakenonexistent) + { + // The server administrator has specified that disabled commands should be + // treated as if they do not exist. + user->WriteNumeric(ERR_UNKNOWNCOMMAND, command, "Unknown command"); + ServerInstance->stats.Unknown++; + return MOD_RES_DENY; + } + + // Inform the user that the command they executed has been disabled. + user->WriteNumeric(ERR_DISABLED, command, "Command disabled"); + return MOD_RES_DENY; + } + + ModResult OnRawMode(User* user, Channel* chan, ModeHandler* mh, const std::string& param, bool adding) CXX11_OVERRIDE + { + // If a mode change is remote or the source is not registered we do nothing. + if (!IS_LOCAL(user) || user->registered != REG_ALL) + return MOD_RES_PASSTHRU; + + // If the mode is not disabled or the user has the servers/use-disabled-modes priv we do nothing. + const std::bitset<64>& disabled = (mh->GetModeType() == MODETYPE_CHANNEL) ? chanmodes : usermodes; + if (!disabled.test(mh->GetModeChar() - 'A') || user->HasPrivPermission("servers/use-disabled-modes")) + return MOD_RES_PASSTHRU; + + // The user has tried to change a disabled mode! + const char* what = mh->GetModeType() == MODETYPE_CHANNEL ? "channel" : "user"; + WriteLog("%s was blocked from executing the disabled %s mode %c (%s)", + user->GetFullRealHost().c_str(), what, mh->GetModeChar(), mh->name.c_str()); + + if (fakenonexistent) + { + // The server administrator has specified that disabled modes should be + // treated as if they do not exist. + user->WriteNumeric(mh->GetModeType() == MODETYPE_CHANNEL ? ERR_UNKNOWNMODE : ERR_UNKNOWNSNOMASK, + mh->GetModeChar(), "is unknown mode char to me"); + return MOD_RES_DENY; + } + + // Inform the user that the mode they changed has been disabled. + user->WriteNumeric(ERR_NOPRIVILEGES, InspIRCd::Format("Permission Denied - %s mode %c (%s) is disabled", + what, mh->GetModeChar(), mh->name.c_str())); + return MOD_RES_DENY; + } + + Version GetVersion() CXX11_OVERRIDE + { + return Version("Provides support for disabling commands and modes", VF_VENDOR); + } +}; + +MODULE_INIT(ModuleDisable) diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp index d1ca800b3..eade39bd7 100644 --- a/src/modules/m_dnsbl.cpp +++ b/src/modules/m_dnsbl.cpp @@ -148,7 +148,7 @@ class DNSBLResolver : public DNS::Request if (ServerInstance->XLines->AddLine(kl,NULL)) { std::string timestr = InspIRCd::TimeString(kl->expiry); - ServerInstance->SNO->WriteGlobalSno('x',"K:line added due to DNSBL match on *@%s to expire on %s: %s", + ServerInstance->SNO->WriteGlobalSno('x', "K-line added due to DNSBL match on *@%s to expire on %s: %s", them->GetIPString().c_str(), timestr.c_str(), reason.c_str()); ServerInstance->XLines->ApplyLines(); } @@ -166,7 +166,7 @@ class DNSBLResolver : public DNS::Request if (ServerInstance->XLines->AddLine(gl,NULL)) { std::string timestr = InspIRCd::TimeString(gl->expiry); - ServerInstance->SNO->WriteGlobalSno('x',"G:line added due to DNSBL match on *@%s to expire on %s: %s", + ServerInstance->SNO->WriteGlobalSno('x', "G-line added due to DNSBL match on *@%s to expire on %s: %s", them->GetIPString().c_str(), timestr.c_str(), reason.c_str()); ServerInstance->XLines->ApplyLines(); } @@ -184,7 +184,7 @@ class DNSBLResolver : public DNS::Request if (ServerInstance->XLines->AddLine(zl,NULL)) { std::string timestr = InspIRCd::TimeString(zl->expiry); - ServerInstance->SNO->WriteGlobalSno('x',"Z:line added due to DNSBL match on %s to expire on %s: %s", + ServerInstance->SNO->WriteGlobalSno('x', "Z-line added due to DNSBL match on %s to expire on %s: %s", them->GetIPString().c_str(), timestr.c_str(), reason.c_str()); ServerInstance->XLines->ApplyLines(); } @@ -420,10 +420,14 @@ class ModuleDNSBL : public Module, public Stats::EventListener std::string dnsbl; if (!myclass->config->readString("dnsbl", dnsbl)) return MOD_RES_PASSTHRU; + std::string* match = nameExt.get(user); - std::string myname = match ? *match : ""; - if (dnsbl == myname) + if (!match) + return MOD_RES_PASSTHRU; + + if (InspIRCd::Match(*match, dnsbl)) return MOD_RES_PASSTHRU; + return MOD_RES_DENY; } diff --git a/src/modules/m_filter.cpp b/src/modules/m_filter.cpp index 0c8b81e4b..849f99086 100644 --- a/src/modules/m_filter.cpp +++ b/src/modules/m_filter.cpp @@ -421,7 +421,7 @@ ModResult ModuleFilter::OnUserPreMessage(User* user, const MessageTarget& msgtar else if (f->action == FA_GLINE) { GLine* gl = new GLine(ServerInstance->Time(), f->duration, ServerInstance->Config->ServerName.c_str(), f->reason.c_str(), "*", user->GetIPString()); - ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was glined because their message to %s matched %s (%s)", + ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was G-lined because their message to %s matched %s (%s)", user->nick.c_str(), target.c_str(), f->freeform.c_str(), f->reason.c_str())); if (ServerInstance->XLines->AddLine(gl,NULL)) { @@ -433,7 +433,7 @@ ModResult ModuleFilter::OnUserPreMessage(User* user, const MessageTarget& msgtar else if (f->action == FA_ZLINE) { ZLine* zl = new ZLine(ServerInstance->Time(), f->duration, ServerInstance->Config->ServerName.c_str(), f->reason.c_str(), user->GetIPString()); - ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was zlined because their message to %s matched %s (%s)", + ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was Z-lined because their message to %s matched %s (%s)", user->nick.c_str(), target.c_str(), f->freeform.c_str(), f->reason.c_str())); if (ServerInstance->XLines->AddLine(zl,NULL)) { @@ -506,9 +506,9 @@ ModResult ModuleFilter::OnPreCommand(std::string& command, CommandBase::Params& } if (f->action == FA_GLINE) { - /* Note: We gline *@IP so that if their host doesnt resolve the gline still applies. */ + /* Note: We G-line *@IP so that if their host doesn't resolve the G-line still applies. */ GLine* gl = new GLine(ServerInstance->Time(), f->duration, ServerInstance->Config->ServerName.c_str(), f->reason.c_str(), "*", user->GetIPString()); - ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was glined because their %s message matched %s (%s)", + ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was G-lined because their %s message matched %s (%s)", user->nick.c_str(), command.c_str(), f->freeform.c_str(), f->reason.c_str())); if (ServerInstance->XLines->AddLine(gl,NULL)) @@ -521,7 +521,7 @@ ModResult ModuleFilter::OnPreCommand(std::string& command, CommandBase::Params& if (f->action == FA_ZLINE) { ZLine* zl = new ZLine(ServerInstance->Time(), f->duration, ServerInstance->Config->ServerName.c_str(), f->reason.c_str(), user->GetIPString()); - ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was zlined because their %s message matched %s (%s)", + ServerInstance->SNO->WriteGlobalSno('f', InspIRCd::Format("%s was Z-lined because their %s message matched %s (%s)", user->nick.c_str(), command.c_str(), f->freeform.c_str(), f->reason.c_str())); if (ServerInstance->XLines->AddLine(zl,NULL)) diff --git a/src/modules/m_haproxy.cpp b/src/modules/m_haproxy.cpp index e92c45686..ee9079cbf 100644 --- a/src/modules/m_haproxy.cpp +++ b/src/modules/m_haproxy.cpp @@ -240,7 +240,7 @@ class HAProxyHook : public IOHookMiddle { case AF_INET: memcpy(&client.in4.sin_addr.s_addr, &recvq[0], 4); - memcpy(&server.in4.sin_addr.s_addr, &recvq[4], 8); + memcpy(&server.in4.sin_addr.s_addr, &recvq[4], 4); memcpy(&client.in4.sin_port, &recvq[8], 2); memcpy(&server.in4.sin_port, &recvq[10], 2); tlv_index = 12; @@ -256,12 +256,13 @@ class HAProxyHook : public IOHookMiddle case AF_UNIX: memcpy(client.un.sun_path, &recvq[0], 108); - memcpy(client.un.sun_path, &recvq[108], 108); + memcpy(server.un.sun_path, &recvq[108], 108); tlv_index = 216; break; } - sock->OnSetEndPoint(server, client); + if (!sock->OnSetEndPoint(server, client)) + return -1; // Parse any available TLVs. while (tlv_index < address_length) diff --git a/src/modules/m_hostchange.cpp b/src/modules/m_hostchange.cpp index 201c4b59b..4c9b24140 100644 --- a/src/modules/m_hostchange.cpp +++ b/src/modules/m_hostchange.cpp @@ -47,7 +47,7 @@ class HostRule std::string suffix; public: - HostRule(const std::string& Host, const std::string& Mask, const insp::flat_set<int>& Ports) + HostRule(const std::string& Mask, const std::string& Host, const insp::flat_set<int>& Ports) : action(HCA_SET) , host(Host) , mask(Mask) diff --git a/src/modules/m_ident.cpp b/src/modules/m_ident.cpp index ca12a9ba3..803c19846 100644 --- a/src/modules/m_ident.cpp +++ b/src/modules/m_ident.cpp @@ -275,12 +275,24 @@ class ModuleIdent : public Module NoLookupPrefix = tag->getBool("nolookupprefix", false); } - void OnUserInit(LocalUser *user) CXX11_OVERRIDE + void OnSetUserIP(LocalUser* user) CXX11_OVERRIDE { + IdentRequestSocket* isock = ext.get(user); + if (isock) + { + // If an ident lookup request was in progress then cancel it. + isock->Close(); + ext.unset(user); + } + // The ident protocol requires that clients are connecting over a protocol with ports. if (user->client_sa.family() != AF_INET && user->client_sa.family() != AF_INET6) return; + // We don't want to look this up once the user has connected. + if (user->registered == REG_ALL) + return; + ConfigTag* tag = user->MyClass->config; if (!tag->getBool("useident", true)) return; @@ -289,7 +301,7 @@ class ModuleIdent : public Module try { - IdentRequestSocket *isock = new IdentRequestSocket(user); + isock = new IdentRequestSocket(user); ext.set(user, isock); } catch (ModuleException &e) diff --git a/src/modules/m_ircv3_echomessage.cpp b/src/modules/m_ircv3_echomessage.cpp index f6eae5a00..b407aece4 100644 --- a/src/modules/m_ircv3_echomessage.cpp +++ b/src/modules/m_ircv3_echomessage.cpp @@ -40,25 +40,26 @@ class ModuleIRCv3EchoMessage : public Module LocalUser* const localuser = static_cast<LocalUser*>(user); const std::string& text = details.echo_original ? details.original_text : details.text; + const ClientProtocol::TagMap& tags = details.echo_original ? details.tags_in : details.tags_out; if (target.type == MessageTarget::TYPE_USER) { User* destuser = target.Get<User>(); ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, user, destuser, text, details.type); - privmsg.AddTags(details.tags_in); + privmsg.AddTags(tags); localuser->Send(ServerInstance->GetRFCEvents().privmsg, privmsg); } else if (target.type == MessageTarget::TYPE_CHANNEL) { Channel* chan = target.Get<Channel>(); ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, user, chan, text, details.type, target.status); - privmsg.AddTags(details.tags_in); + privmsg.AddTags(tags); localuser->Send(ServerInstance->GetRFCEvents().privmsg, privmsg); } else { const std::string* servername = target.Get<std::string>(); ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, user, *servername, text, details.type); - privmsg.AddTags(details.tags_in); + privmsg.AddTags(tags); localuser->Send(ServerInstance->GetRFCEvents().privmsg, privmsg); } } diff --git a/src/modules/m_passforward.cpp b/src/modules/m_passforward.cpp index 08d3533cd..37efec02b 100644 --- a/src/modules/m_passforward.cpp +++ b/src/modules/m_passforward.cpp @@ -18,6 +18,7 @@ #include "inspircd.h" +#include "modules/account.h" class ModulePassForward : public Module { @@ -82,6 +83,13 @@ class ModulePassForward : public Module if (!user->MyClass->config->getString("password").empty()) return; + AccountExtItem* actext = GetAccountExtItem(); + if (actext && actext->get(user)) + { + // User is logged in already (probably via SASL) don't forward the password + return; + } + if (!nickrequired.empty()) { /* Check if nick exists and its server is ulined */ diff --git a/src/modules/m_rline.cpp b/src/modules/m_rline.cpp index 77b3bc3aa..1247e81d3 100644 --- a/src/modules/m_rline.cpp +++ b/src/modules/m_rline.cpp @@ -32,7 +32,7 @@ class RLine : public XLine { public: - /** Create a R-Line. + /** Create a R-line. * @param s_time The set time * @param d The duration of the xline * @param src The sender of the xline @@ -81,7 +81,7 @@ class RLine : public XLine if (ServerInstance->XLines->AddLine(zl, NULL)) { std::string timestr = InspIRCd::TimeString(zl->expiry); - ServerInstance->SNO->WriteToSnoMask('x', "Z-line added due to R-line match on *@%s%s%s: %s", + ServerInstance->SNO->WriteToSnoMask('x', "Z-line added due to R-line match on %s%s%s: %s", zl->ipaddr.c_str(), zl->duration ? " to expire on " : "", zl->duration ? timestr.c_str() : "", zl->reason.c_str()); added_zline = true; } @@ -150,7 +150,7 @@ class CommandRLine : public Command unsigned long duration; if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for R-line"); + user->WriteNotice("*** Invalid duration for R-line."); return CMD_FAILURE; } XLine *r = NULL; @@ -184,7 +184,7 @@ class CommandRLine : public Command else { delete r; - user->WriteNotice("*** R-Line for " + parameters[0] + " already exists"); + user->WriteNotice("*** R-line for " + parameters[0] + " already exists."); } } } @@ -196,7 +196,7 @@ class CommandRLine : public Command } else { - user->WriteNotice("*** R-Line " + parameters[0] + " not found in list, try /stats R."); + user->WriteNotice("*** R-line " + parameters[0] + " not found in list, try /stats R."); } } @@ -279,15 +279,15 @@ class ModuleRLine : public Module, public Stats::EventListener if (!rxfactory) { if (newrxengine.empty()) - ServerInstance->SNO->WriteToSnoMask('a', "WARNING: No regex engine loaded - R-Line functionality disabled until this is corrected."); + ServerInstance->SNO->WriteToSnoMask('a', "WARNING: No regex engine loaded - R-line functionality disabled until this is corrected."); else - ServerInstance->SNO->WriteToSnoMask('a', "WARNING: Regex engine '%s' is not loaded - R-Line functionality disabled until this is corrected.", newrxengine.c_str()); + ServerInstance->SNO->WriteToSnoMask('a', "WARNING: Regex engine '%s' is not loaded - R-line functionality disabled until this is corrected.", newrxengine.c_str()); ServerInstance->XLines->DelAll(f.GetType()); } else if ((!initing) && (rxfactory.operator->() != factory)) { - ServerInstance->SNO->WriteToSnoMask('a', "Regex engine has changed, removing all R-Lines"); + ServerInstance->SNO->WriteToSnoMask('a', "Regex engine has changed, removing all R-lines."); ServerInstance->XLines->DelAll(f.GetType()); } @@ -331,7 +331,7 @@ class ModuleRLine : public Module, public Stats::EventListener void OnUnloadModule(Module* mod) CXX11_OVERRIDE { - // If the regex engine became unavailable or has changed, remove all rlines + // If the regex engine became unavailable or has changed, remove all R-lines. if (!rxfactory) { ServerInstance->XLines->DelAll(f.GetType()); diff --git a/src/modules/m_samode.cpp b/src/modules/m_samode.cpp index 8f28a7e9c..db3345b98 100644 --- a/src/modules/m_samode.cpp +++ b/src/modules/m_samode.cpp @@ -124,6 +124,9 @@ class ModuleSaMode : public Module void Prioritize() CXX11_OVERRIDE { + Module* disabled = ServerInstance->Modules->Find("m_disabled.so"); + ServerInstance->Modules->SetPriority(this, I_OnRawMode, PRIORITY_BEFORE, disabled); + Module *override = ServerInstance->Modules->Find("m_override.so"); ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_BEFORE, override); } diff --git a/src/modules/m_shun.cpp b/src/modules/m_shun.cpp index e4fb2c11d..6453ace81 100644 --- a/src/modules/m_shun.cpp +++ b/src/modules/m_shun.cpp @@ -92,7 +92,7 @@ class CommandShun : public Command { if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for SHUN"); + user->WriteNotice("*** Invalid duration for SHUN."); return CMD_FAILURE; } expr = parameters[2]; @@ -122,7 +122,7 @@ class CommandShun : public Command else { delete r; - user->WriteNotice("*** Shun for " + target + " already exists"); + user->WriteNotice("*** Shun for " + target + " already exists."); return CMD_FAILURE; } } diff --git a/src/modules/m_spanningtree/away.cpp b/src/modules/m_spanningtree/away.cpp index 13972589b..62300580f 100644 --- a/src/modules/m_spanningtree/away.cpp +++ b/src/modules/m_spanningtree/away.cpp @@ -47,6 +47,6 @@ CmdResult CommandAway::HandleRemote(::RemoteUser* u, Params& params) CommandAway::Builder::Builder(User* user) : CmdBuilder(user, "AWAY") { - if (user->awaymsg.empty()) + if (!user->awaymsg.empty()) push_int(user->awaytime).push_last(user->awaymsg); } diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp index 985762872..de1e8eb19 100644 --- a/src/modules/m_spanningtree/main.cpp +++ b/src/modules/m_spanningtree/main.cpp @@ -324,8 +324,12 @@ ModResult ModuleSpanningTree::HandleVersion(const CommandBase::Params& parameter // If it's empty it might be that the server is still syncing (full version hasn't arrived yet) // or the server is a 2.0 server and does not send a full version. bool showfull = ((user->IsOper()) && (!found->GetFullVersion().empty())); - const std::string& Version = (showfull ? found->GetFullVersion() : found->GetVersion()); - user->WriteNumeric(RPL_VERSION, Version); + + Numeric::Numeric numeric(RPL_VERSION); + irc::tokenstream tokens(showfull ? found->GetFullVersion() : found->GetVersion()); + for (std::string token; tokens.GetTrailing(token); ) + numeric.push(token); + user->WriteNumeric(numeric); } else { diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h index 878b34ad7..6206448c1 100644 --- a/src/modules/m_spanningtree/treesocket.h +++ b/src/modules/m_spanningtree/treesocket.h @@ -259,7 +259,7 @@ class TreeSocket : public BufferedSocket */ void SendFJoins(Channel* c); - /** Send G, Q, Z and E lines */ + /** Send G-, Q-, Z- and E-lines */ void SendXLines(); /** Send all known information about a channel */ diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp index dc24802fb..45f8a380f 100644 --- a/src/modules/m_spanningtree/treesocket2.cpp +++ b/src/modules/m_spanningtree/treesocket2.cpp @@ -292,7 +292,7 @@ void TreeSocket::ProcessTag(User* source, const std::string& tag, ClientProtocol for (Events::ModuleEventProvider::SubscriberList::const_iterator i = list.begin(); i != list.end(); ++i) { ClientProtocol::MessageTagProvider* const tagprov = static_cast<ClientProtocol::MessageTagProvider*>(*i); - const ModResult res = tagprov->OnClientProtocolProcessTag(source, tagkey, tagval); + const ModResult res = tagprov->OnProcessTag(source, tagkey, tagval); if (res == MOD_RES_ALLOW) tags.insert(std::make_pair(tagkey, ClientProtocol::MessageTagData(tagprov, tagval))); else if (res == MOD_RES_DENY) diff --git a/src/modules/m_sslinfo.cpp b/src/modules/m_sslinfo.cpp index 54aeb9755..30dfd9a76 100644 --- a/src/modules/m_sslinfo.cpp +++ b/src/modules/m_sslinfo.cpp @@ -54,8 +54,7 @@ class SSLCertExt : public ExtensionItem void unset(Extensible* container) { - void* old = unset_raw(container); - delete static_cast<std::string*>(old); + free(container, unset_raw(container)); } std::string serialize(SerializeFormat format, const Extensible* container, void* item) const CXX11_OVERRIDE diff --git a/src/modules/m_svshold.cpp b/src/modules/m_svshold.cpp index 52c250fef..0aaf113f0 100644 --- a/src/modules/m_svshold.cpp +++ b/src/modules/m_svshold.cpp @@ -76,7 +76,7 @@ class SVSHoldFactory : public XLineFactory public: SVSHoldFactory() : XLineFactory("SVSHOLD") { } - /** Generate a shun + /** Generate an SVSHOLD */ XLine* Generate(time_t set_time, unsigned long duration, const std::string& source, const std::string& reason, const std::string& xline_specific_mask) CXX11_OVERRIDE { @@ -130,7 +130,7 @@ class CommandSvshold : public Command unsigned long duration; if (!InspIRCd::Duration(parameters[1], duration)) { - user->WriteNotice("*** Invalid duration for SVSHOLD"); + user->WriteNotice("*** Invalid duration for SVSHOLD."); return CMD_FAILURE; } SVSHold* r = new SVSHold(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str()); @@ -221,7 +221,7 @@ class ModuleSVSHold : public Module, public Stats::EventListener Version GetVersion() CXX11_OVERRIDE { - return Version("Implements SVSHOLD. Like Q:Lines, but can only be added/removed by Services.", VF_COMMON | VF_VENDOR); + return Version("Implements SVSHOLD. Like Q-lines, but can only be added/removed by Services.", VF_COMMON | VF_VENDOR); } }; diff --git a/src/snomasks.cpp b/src/snomasks.cpp index 0b266ff7e..e39fb84fb 100644 --- a/src/snomasks.cpp +++ b/src/snomasks.cpp @@ -69,8 +69,8 @@ SnomaskManager::SnomaskManager() EnableSnomask('q',"QUIT"); /* Local quit notices */ EnableSnomask('k',"KILL"); /* Kill notices */ EnableSnomask('o',"OPER"); /* Oper up/down notices */ - EnableSnomask('a',"ANNOUNCEMENT"); /* formerly WriteOpers() - generic notices to all opers */ - EnableSnomask('x',"XLINE"); /* Xline notice (g/z/q/k/e) */ + EnableSnomask('a',"ANNOUNCEMENT"); /* formerly WriteOpers() - generic notices to all opers */ + EnableSnomask('x',"XLINE"); /* X-line notices (G/Z/Q/K/E/R/SHUN/CBan) */ EnableSnomask('t',"STATS"); /* Local or remote stats request */ } diff --git a/src/usermanager.cpp b/src/usermanager.cpp index 6f9d15502..053a308cb 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -76,6 +76,7 @@ void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs this->clientlist[New->nick] = New; this->AddClone(New); this->local_users.push_front(New); + FOREACH_MOD(OnUserInit, (New)); if (!SocketEngine::AddFd(eh, FD_WANT_FAST_READ | FD_WANT_EDGE_WRITE)) { @@ -132,7 +133,7 @@ void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs New->WriteNumeric(ERR_YOUREBANNEDCREEP, ServerInstance->Config->XLineMessage); if (ServerInstance->Config->HideBans) - this->QuitUser(New, b->Type + "-Lined", &b->Reason); + this->QuitUser(New, b->Type + "-lined", &b->Reason); else this->QuitUser(New, b->Reason); return; @@ -162,8 +163,6 @@ void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs FOREACH_MOD(OnSetUserIP, (New)); if (New->quitting) return; - - FOREACH_MOD(OnUserInit, (New)); } void UserManager::QuitUser(User* user, const std::string& quitreason, const std::string* operreason) diff --git a/src/users.cpp b/src/users.cpp index f11a7a380..506cdf6d8 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -239,23 +239,30 @@ void UserIOHandler::OnDataReady() if (!user->HasPrivPermission("users/flood/no-fakelag")) penaltymax = user->MyClass->GetPenaltyThreshold() * 1000; - // The maximum size of an IRC message minus the terminating CR+LF. - const size_t maxmessage = ServerInstance->Config->Limits.MaxLine - 2; + // The cleaned message sent by the user or empty if not found yet. std::string line; - line.reserve(maxmessage); - bool eol_found; + // The position of the most \n character or npos if not found yet. + std::string::size_type eolpos; + + // The position within the recvq of the current character. std::string::size_type qpos; while (user->CommandFloodPenalty < penaltymax && getSendQSize() < sendqmax) { - qpos = 0; - eol_found = false; + // Check the newly received data for an EOL. + eolpos = recvq.find('\n', checked_until); + if (eolpos == std::string::npos) + { + checked_until = recvq.length(); + return; + } - const size_t qlen = recvq.length(); - while (qpos < qlen) + // We've found a line! Clean it up and move it to the line buffer. + line.reserve(eolpos); + for (qpos = 0; qpos < eolpos; ++qpos) { - char c = recvq[qpos++]; + char c = recvq[qpos]; switch (c) { case '\0': @@ -263,25 +270,14 @@ void UserIOHandler::OnDataReady() break; case '\r': continue; - case '\n': - eol_found = true; - break; } - if (eol_found) - break; - - if (line.length() < maxmessage) - line.push_back(c); + line.push_back(c); } - // if we return here, we haven't found a newline and make no modifications to recvq - // so we can wait for more data - if (!eol_found) - return; - // just found a newline. Terminate the string, and pull it out of recvq - recvq.erase(0, qpos); + recvq.erase(0, eolpos + 1); + checked_until = 0; // TODO should this be moved to when it was inserted in recvq? ServerInstance->stats.Recv += qpos; @@ -318,10 +314,11 @@ void UserIOHandler::AddWriteBuf(const std::string &data) WriteData(data); } -void UserIOHandler::OnSetEndPoint(const irc::sockets::sockaddrs& server, const irc::sockets::sockaddrs& client) +bool UserIOHandler::OnSetEndPoint(const irc::sockets::sockaddrs& server, const irc::sockets::sockaddrs& client) { memcpy(&user->server_sa, &server, sizeof(irc::sockets::sockaddrs)); user->SetClientIP(client); + return !user->quitting; } void UserIOHandler::OnError(BufferedSocketError) @@ -723,17 +720,17 @@ irc::sockets::cidr_mask User::GetCIDRMask() return irc::sockets::cidr_mask(client_sa, range); } -bool User::SetClientIP(const std::string& address, bool recheck_eline) +bool User::SetClientIP(const std::string& address) { irc::sockets::sockaddrs sa; if (!irc::sockets::aptosa(address, client_sa.port(), sa)) return false; - User::SetClientIP(sa, recheck_eline); + User::SetClientIP(sa); return true; } -void User::SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline) +void User::SetClientIP(const irc::sockets::sockaddrs& sa) { const std::string oldip(GetIPString()); memcpy(&client_sa, &sa, sizeof(irc::sockets::sockaddrs)); @@ -746,26 +743,33 @@ void User::SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline) ChangeDisplayedHost(GetIPString()); } -bool LocalUser::SetClientIP(const std::string& address, bool recheck_eline) +bool LocalUser::SetClientIP(const std::string& address) { irc::sockets::sockaddrs sa; if (!irc::sockets::aptosa(address, client_sa.port(), sa)) return false; - LocalUser::SetClientIP(sa, recheck_eline); + LocalUser::SetClientIP(sa); return true; } -void LocalUser::SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline) +void LocalUser::SetClientIP(const irc::sockets::sockaddrs& sa) { - if (sa != client_sa) - { - User::SetClientIP(sa); - if (recheck_eline) - this->exempt = (ServerInstance->XLines->MatchesLine("E", this) != NULL); + if (sa == client_sa) + return; - FOREACH_MOD(OnSetUserIP, (this)); - } + ServerInstance->Users->RemoveCloneCounts(this); + + User::SetClientIP(sa); + + FOREACH_MOD(OnSetUserIP, (this)); + + ServerInstance->Users->AddClone(this); + + // Recheck the connect class. + this->MyClass = NULL; + this->SetClass(); + this->CheckClass(); } void LocalUser::Write(const ClientProtocol::SerializedMessage& text) @@ -796,7 +800,11 @@ void LocalUser::Write(const ClientProtocol::SerializedMessage& text) void LocalUser::Send(ClientProtocol::Event& protoev) { if (!serializer) + { + ServerInstance->Logs->Log("USERS", LOG_DEBUG, "BUG: LocalUser::Send() called on %s who does not have a serializer!", + GetFullRealHost().c_str()); return; + } // In the most common case a static LocalUser field, sendmsglist, is passed to the event to be // populated. The list is cleared before returning. diff --git a/src/xline.cpp b/src/xline.cpp index 9c84101e1..55496b424 100644 --- a/src/xline.cpp +++ b/src/xline.cpp @@ -329,7 +329,7 @@ void ELine::Unset() ServerInstance->XLines->CheckELines(); } -// returns a pointer to the reason if a nickname matches a qline, NULL if it didnt match +// returns a pointer to the reason if a nickname matches a Q-line, NULL if it didn't match XLine* XLineManager::MatchesLine(const std::string &type, User* user) { @@ -523,13 +523,13 @@ bool XLine::IsBurstable() void XLine::DefaultApply(User* u, const std::string &line, bool bancache) { - const std::string banReason = line + "-Lined: " + reason; + const std::string banReason = line + "-lined: " + reason; if (!ServerInstance->Config->XLineMessage.empty()) u->WriteNumeric(ERR_YOUREBANNEDCREEP, ServerInstance->Config->XLineMessage); if (ServerInstance->Config->HideBans) - ServerInstance->Users->QuitUser(u, line + "-Lined", &banReason); + ServerInstance->Users->QuitUser(u, line + "-lined", &banReason); else ServerInstance->Users->QuitUser(u, banReason); @@ -629,7 +629,7 @@ bool QLine::Matches(User *u) void QLine::Apply(User* u) { - /* Force to uuid on apply of qline, no need to disconnect any more :) */ + /* Force to uuid on apply of Q-line, no need to disconnect anymore :) */ u->ChangeNick(u->uuid); } @@ -667,7 +667,7 @@ bool GLine::Matches(const std::string &str) void ELine::OnAdd() { - /* When adding one eline, only check the one eline */ + /* When adding one E-line, only check the one E-line */ const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers(); for (UserManager::LocalList::const_iterator u2 = list.begin(); u2 != list.end(); u2++) { @@ -681,7 +681,7 @@ void XLine::DisplayExpiry() { bool onechar = (type.length() == 1); ServerInstance->SNO->WriteToSnoMask('x', "Removing expired %s%s %s (set by %s %ld seconds ago): %s", - type.c_str(), (onechar ? "-Line" : ""), Displayable().c_str(), source.c_str(), (long)(ServerInstance->Time() - set_time), reason.c_str()); + type.c_str(), (onechar ? "-line" : ""), Displayable().c_str(), source.c_str(), (long)(ServerInstance->Time() - set_time), reason.c_str()); } const std::string& ELine::Displayable() |
