updated to 5.0.5

This commit is contained in:
Dionysus 2020-05-28 22:06:50 -04:00
parent 3c6d873d6a
commit 3256af1b0b
Signed by: acidvegas
GPG Key ID: EF4B922DB85DC9DE
71 changed files with 1322 additions and 350 deletions

17
Config
View File

@ -88,6 +88,19 @@ fi
if [ "x$INSTALLCURL" = "x1" ]; then
extras/curlinstall "$PRIVATELIBDIR" || exit 1
fi
# At least do SOME parallel compiling by default, IF:
# - the MAKE environment variable is not set
# - the MAKEFLAGS environment variable is not set
# - we are using GNU Make
if [ "x$MAKE" = "x" ]; then
if [ "x$MAKEFLAGS" = "x" ]; then
if make --version 2>&1|grep -q "GNU Make"; then
echo "Running with 4 concurrent build processes by default (make -j4)."
export MAKE='make -j4'
fi
fi
fi
echo $CONF
$CONF || exit 1
cd "$UNREALCWD"
@ -313,7 +326,7 @@ echo "We will now ask you a number of questions. You can just press ENTER to acc
echo ""
# This needs to be updated each release so auto-upgrading works for settings, modules, etc!!:
UNREALRELEASES="unrealircd-5.0.3.1 unrealircd-5.0.3 unrealircd-5.0.2 unrealircd-5.0.1 unrealircd-5.0.0 unrealircd-5.0.0-rc2 unrealircd-5.0.0-rc1"
UNREALRELEASES="unrealircd-5.0.4 unrealircd-5.0.3.1 unrealircd-5.0.3 unrealircd-5.0.2 unrealircd-5.0.1 unrealircd-5.0.0 unrealircd-5.0.0-rc2 unrealircd-5.0.0-rc1"
if [ -f "config.settings" ]; then
. ./config.settings
else
@ -479,7 +492,7 @@ while [ -z "$TEST" ] ; do
echo ""
echo "Do you want to enable remote includes?"
echo "This allows stuff like this in your configuration file:"
echo "include \"http://www.somesite.org/files/opers.conf\";"
echo "include \"https://www.somesite.org/files/opers.conf\";"
echo $n "[$TEST] -> $c"
read cc
if [ -z "$cc" ] ; then

View File

@ -290,7 +290,10 @@ DLL_FILES=SRC/MODULES/CLOAK.DLL \
SRC/MODULES/USERHOST-TAG.DLL \
SRC/MODULES/REQUIRE-MODULE.DLL \
SRC/MODULES/IDENT_LOOKUP.DLL \
SRC/MODULES/HISTORY.DLL
SRC/MODULES/HISTORY.DLL \
SRC/MODULES/TARGETFLOODPROT.DLL \
SRC/MODULES/TYPING-INDICATOR.DLL \
SRC/MODULES/CLIENTTAGDENY.DLL
ALL: CONF UNREALSVC.EXE UnrealIRCd.exe MODULES
@ -1081,4 +1084,13 @@ src/modules/ident_lookup.dll: src/modules/ident_lookup.c $(INCLUDES)
src/modules/history.dll: src/modules/history.c $(INCLUDES)
$(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/history.c $(MODLFLAGS)
src/modules/targetfloodprot.dll: src/modules/targetfloodprot.c $(INCLUDES)
$(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/targetfloodprot.c $(MODLFLAGS)
src/modules/typing-indicator.dll: src/modules/typing-indicator.c $(INCLUDES)
$(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/typing-indicator.c $(MODLFLAGS)
src/modules/clienttagdeny.dll: src/modules/clienttagdeny.c $(INCLUDES)
$(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/clienttagdeny.c $(MODLFLAGS)
dummy:

140
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for unrealircd 5.0.4.
# Generated by GNU Autoconf 2.69 for unrealircd 5.0.5.
#
# Report bugs to <https://bugs.unrealircd.org/>.
#
@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='unrealircd'
PACKAGE_TARNAME='unrealircd'
PACKAGE_VERSION='5.0.4'
PACKAGE_STRING='unrealircd 5.0.4'
PACKAGE_VERSION='5.0.5'
PACKAGE_STRING='unrealircd 5.0.5'
PACKAGE_BUGREPORT='https://bugs.unrealircd.org/'
PACKAGE_URL='https://unrealircd.org/'
@ -1325,7 +1325,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures unrealircd 5.0.4 to adapt to many kinds of systems.
\`configure' configures unrealircd 5.0.5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1391,7 +1391,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of unrealircd 5.0.4:";;
short | recursive ) echo "Configuration of unrealircd 5.0.5:";;
esac
cat <<\_ACEOF
@ -1544,7 +1544,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
unrealircd configure 5.0.4
unrealircd configure 5.0.5
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -1913,7 +1913,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by unrealircd $as_me 5.0.4, which was
It was created by unrealircd $as_me 5.0.5, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -2321,7 +2321,7 @@ _ACEOF
# Minor version number (e.g.: Z in X.Y.Z)
UNREAL_VERSION_MINOR="4"
UNREAL_VERSION_MINOR="5"
cat >>confdefs.h <<_ACEOF
#define UNREAL_VERSION_MINOR $UNREAL_VERSION_MINOR
@ -4078,6 +4078,104 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
# Added in UnrealIRCd 5.0.5 (default on Ubuntu 19.10)
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fstack-clash-protection" >&5
$as_echo_n "checking whether C compiler accepts -fstack-clash-protection... " >&6; }
if ${ax_cv_check_cflags__Werror___fstack_clash_protection+:} false; then :
$as_echo_n "(cached) " >&6
else
ax_check_save_flags=$CFLAGS
CFLAGS="$CFLAGS -Werror -fstack-clash-protection"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ax_cv_check_cflags__Werror___fstack_clash_protection=yes
else
ax_cv_check_cflags__Werror___fstack_clash_protection=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
CFLAGS=$ax_check_save_flags
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags__Werror___fstack_clash_protection" >&5
$as_echo "$ax_cv_check_cflags__Werror___fstack_clash_protection" >&6; }
if test x"$ax_cv_check_cflags__Werror___fstack_clash_protection" = xyes; then :
HARDEN_CFLAGS="$HARDEN_CFLAGS -fstack-clash-protection"
else
:
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
# Control Flow Enforcement (ROP hardening) - requires CPU hardware support
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fcf-protection" >&5
$as_echo_n "checking whether C compiler accepts -fcf-protection... " >&6; }
if ${ax_cv_check_cflags__Werror___fcf_protection+:} false; then :
$as_echo_n "(cached) " >&6
else
ax_check_save_flags=$CFLAGS
CFLAGS="$CFLAGS -Werror -fcf-protection"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ax_cv_check_cflags__Werror___fcf_protection=yes
else
ax_cv_check_cflags__Werror___fcf_protection=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
CFLAGS=$ax_check_save_flags
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags__Werror___fcf_protection" >&5
$as_echo "$ax_cv_check_cflags__Werror___fcf_protection" >&6; }
if test x"$ax_cv_check_cflags__Werror___fcf_protection" = xyes; then :
HARDEN_CFLAGS="$HARDEN_CFLAGS -fcf-protection"
else
:
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
# At the link step, we might want -pie (GCC) or -Wl,-pie (Clang on OS X)
#
# The linker checks also compile code, so we need to include -fPIE as well.
@ -6783,12 +6881,12 @@ if test -n "$PCRE2_CFLAGS"; then
pkg_cv_PCRE2_CFLAGS="$PCRE2_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpcre2-8 >= 10.00\""; } >&5
($PKG_CONFIG --exists --print-errors "libpcre2-8 >= 10.00") 2>&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpcre2-8 >= 10.34\""; } >&5
($PKG_CONFIG --exists --print-errors "libpcre2-8 >= 10.34") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_PCRE2_CFLAGS=`$PKG_CONFIG --cflags "libpcre2-8 >= 10.00" 2>/dev/null`
pkg_cv_PCRE2_CFLAGS=`$PKG_CONFIG --cflags "libpcre2-8 >= 10.34" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
@ -6800,12 +6898,12 @@ if test -n "$PCRE2_LIBS"; then
pkg_cv_PCRE2_LIBS="$PCRE2_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpcre2-8 >= 10.00\""; } >&5
($PKG_CONFIG --exists --print-errors "libpcre2-8 >= 10.00") 2>&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpcre2-8 >= 10.34\""; } >&5
($PKG_CONFIG --exists --print-errors "libpcre2-8 >= 10.34") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_PCRE2_LIBS=`$PKG_CONFIG --libs "libpcre2-8 >= 10.00" 2>/dev/null`
pkg_cv_PCRE2_LIBS=`$PKG_CONFIG --libs "libpcre2-8 >= 10.34" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
@ -6826,9 +6924,9 @@ else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
PCRE2_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libpcre2-8 >= 10.00" 2>&1`
PCRE2_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libpcre2-8 >= 10.34" 2>&1`
else
PCRE2_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libpcre2-8 >= 10.00" 2>&1`
PCRE2_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libpcre2-8 >= 10.34" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$PCRE2_PKG_ERRORS" >&5
@ -6852,7 +6950,7 @@ fi
if test "$has_system_pcre2" = "no"; then :
pcre2_version="10.33"
pcre2_version="10.34"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: extracting PCRE2 regex library" >&5
$as_echo "extracting PCRE2 regex library" >&6; }
cur_dir=`pwd`
@ -6869,7 +6967,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: configuring PCRE2 regex library" >&5
$as_echo "configuring PCRE2 regex library" >&6; }
cd pcre2-$pcre2_version
./configure --enable-jit --enable-shared --disable-unicode --prefix=$cur_dir/extras/pcre2 --libdir=$PRIVATELIBDIR || exit 1
./configure --enable-jit --enable-shared --prefix=$cur_dir/extras/pcre2 --libdir=$PRIVATELIBDIR || exit 1
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: compiling PCRE2 regex library" >&5
$as_echo "compiling PCRE2 regex library" >&6; }
$ac_cv_prog_MAKER || exit 1
@ -7089,7 +7187,7 @@ fi
if test "$has_system_cares" = "no"; then :
cares_version="1.15.0"
cares_version="1.16.0"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: extracting c-ares resolver library" >&5
$as_echo "extracting c-ares resolver library" >&6; }
cur_dir=`pwd`
@ -8300,7 +8398,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by unrealircd $as_me 5.0.4, which was
This file was extended by unrealircd $as_me 5.0.5, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -8363,7 +8461,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
unrealircd config.status 5.0.4
unrealircd config.status 5.0.5
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@ -7,7 +7,7 @@ dnl src/windows/unrealinst.iss
dnl doc/Config.header
dnl src/version.c.SH
AC_INIT([unrealircd], [5.0.4], [https://bugs.unrealircd.org/], [], [https://unrealircd.org/])
AC_INIT([unrealircd], [5.0.5], [https://bugs.unrealircd.org/], [], [https://unrealircd.org/])
AC_CONFIG_SRCDIR([src/ircd.c])
AC_CONFIG_HEADER([include/setup.h])
AC_CONFIG_AUX_DIR([autoconf])
@ -34,7 +34,7 @@ UNREAL_VERSION_MAJOR=["0"]
AC_DEFINE_UNQUOTED([UNREAL_VERSION_MAJOR], [$UNREAL_VERSION_MAJOR], [Major version number (e.g.: Y for X.Y.Z)])
# Minor version number (e.g.: Z in X.Y.Z)
UNREAL_VERSION_MINOR=["4"]
UNREAL_VERSION_MINOR=["5"]
AC_DEFINE_UNQUOTED([UNREAL_VERSION_MINOR], [$UNREAL_VERSION_MINOR], [Minor version number (e.g.: Z for X.Y.Z)])
# The version suffix such as a beta marker or release candidate
@ -129,6 +129,12 @@ AS_IF([test x"$hardening" != x"no"], [
check_cc_flag([--param ssp-buffer-size=1], [HARDEN_CFLAGS="$HARDEN_CFLAGS --param ssp-buffer-size=1"],
[], [-fstack-protector-all])])])
# Added in UnrealIRCd 5.0.5 (default on Ubuntu 19.10)
check_cc_flag([-fstack-clash-protection], [HARDEN_CFLAGS="$HARDEN_CFLAGS -fstack-clash-protection"])
# Control Flow Enforcement (ROP hardening) - requires CPU hardware support
check_cc_flag([-fcf-protection], [HARDEN_CFLAGS="$HARDEN_CFLAGS -fcf-protection"])
# At the link step, we might want -pie (GCC) or -Wl,-pie (Clang on OS X)
#
# The linker checks also compile code, so we need to include -fPIE as well.
@ -531,12 +537,12 @@ export PATH_SEPARATOR
dnl Use system pcre2 when available, unless --without-system-pcre2.
has_system_pcre2="no"
AS_IF([test "x$with_system_pcre2" = "xyes"],[
PKG_CHECK_MODULES([PCRE2], libpcre2-8 >= 10.00,[has_system_pcre2=yes
PKG_CHECK_MODULES([PCRE2], libpcre2-8 >= 10.34,[has_system_pcre2=yes
AS_IF([test "x$PRIVATELIBDIR" != "x"], [rm -f "$PRIVATELIBDIR/"libpcre2*])],[has_system_pcre2=no])])
AS_IF([test "$has_system_pcre2" = "no"], [
dnl REMEMBER TO CHANGE WITH A NEW PCRE2 RELEASE!
pcre2_version="10.33"
pcre2_version="10.34"
AC_MSG_RESULT(extracting PCRE2 regex library)
cur_dir=`pwd`
cd extras
@ -553,7 +559,7 @@ else
fi
AC_MSG_RESULT(configuring PCRE2 regex library)
cd pcre2-$pcre2_version
./configure --enable-jit --enable-shared --disable-unicode --prefix=$cur_dir/extras/pcre2 --libdir=$PRIVATELIBDIR || exit 1
./configure --enable-jit --enable-shared --prefix=$cur_dir/extras/pcre2 --libdir=$PRIVATELIBDIR || exit 1
AC_MSG_RESULT(compiling PCRE2 regex library)
$ac_cv_prog_MAKER || exit 1
AC_MSG_RESULT(installing PCRE2 regex library)
@ -627,7 +633,7 @@ AS_IF([test "$has_system_cares" = "no"], [
dnl REMEMBER TO CHANGE WITH A NEW C-ARES RELEASE!
dnl NOTE: when changing this here, ALSO change it in extras/curlinstall
dnl and in the comment in this file around line 400!
cares_version="1.15.0"
cares_version="1.16.0"
AC_MSG_RESULT(extracting c-ares resolver library)
cur_dir=`pwd`
cd extras

View File

@ -7,7 +7,7 @@
\___/|_| |_|_| \___|\__,_|_|\___/\_| \_| \____/\__,_|
Configuration Program
for UnrealIRCd 5.0.4
for UnrealIRCd 5.0.5
This program will help you to compile your IRC server, and ask you
questions regarding the compile-time settings of it during the process.

View File

@ -1,6 +1,82 @@
UnrealIRCd 5.0.4 Release Notes
UnrealIRCd 5.0.5 Release Notes
===============================
This release mainly focuses on new features, while also fixing a few bugs.
Fixes:
* [except ban { }](https://www.unrealircd.org/docs/Except_ban_block)
without 'type' was not exempting from gline.
* Channel mode ```+L #forward``` and ```+k key```: should forward
on wrong key, but was also redirecting on correct key.
* Crash on 32-bit machines in tkldb (on start or rehash)
* Crash when saving channeldb when a parameter channel mode is combined
with ```+P``` and that module was loaded after channeldb. This may
happen if you use 3rd party modules that add parameter channel modes.
Enhancements:
* [Spamfilter](https://www.unrealircd.org/docs/Spamfilter) is now UTF8-aware.
This means, among other things:
* Case insensitive matches work better. For example, with extended
Latin, a spamfilter on ```ę``` now also matches ```Ę```.
* Other PCRE2 features such as [\p](https://www.pcre.org/current/doc/html/pcre2syntax.html#SEC5)
are now available. For example you can now set a spamfilter with the regex
```\p{Arabic}``` to block all Arabic script, or ```\p{Cyrillic}``` to
block all Cyrillic script (such as Russian).
Please do use these new tools with care. Blocking an entire language
or script is quite a drastic measure.
* These new features require the PCRE2 10.34 regex library. If you
have a lower version on your system then UnrealIRCd will fall back
to using the UnrealIRCd-shipped-library version 10.34. The only
downside to that is that compiling during ```./Config``` may take
a little longer than usual.
* [antimixedutf8](https://www.unrealircd.org/docs/Set_block#set::antimixedutf8)
has been improved to detect CJK and other scripts and this will now
catch more mixed UTF8 spam. Note that, if you previously manually
set the score very tight (much lower than the default of 10) then you
may have to increase it a bit, or not, depending on your network.
* Support for IRCv3 [+typing clienttag](https://ircv3.net/specs/client-tags/typing.html),
which adds "user is typing" support to channels and PM (if the client
supports it).
* New flood countermeasure,
[set::anti-flood::target-flood](https://www.unrealircd.org/docs/Set_block#set%3A%3Aanti-flood%3A%3Atarget-flood),
which limits flooding to channels and users. This is only meant as a
filter for high rate floods. You are still encouraged to use
[channel mode +f](https://www.unrealircd.org/docs/Anti-flood_features#Channel_mode_f)
in channels which give you more customized and fine-grained options
to deal with low- and medium-rate floods.
* If a chanop /INVITEs someone, it will now override ban forwards
such as ```+b ~f:#forward:*!*@*```.
Changes:
* We now do parallel builds by default (```make -j4```) within ./Config,
unless the ```$MAKE``` or ```$MAKEFLAGS``` environment variable is set.
* [set::restrict-commands](https://www.unrealircd.org/docs/Set_block#set%3A%3Arestrict-commands):
* The ```disable``` option is now removed as it is implied. In other words: if
you want to disable a command, then simply don't use ```connect-delay```.
* You can now have a block without ```connect-delay``` but still make
users bypass the restriction with ```exempt-identified``` and/or
```exempt-reputation-score```. Previously this was not possible.
* We now give an error when an IRCOp tries to place an *LINE that already
exists. (Previously we sometimes replaced the existing *LINE and other
times we did not)
* Add Polish HELPOP (help.pl.conf)
Module coders / Developers:
* Breaking API change in ```HOOKTYPE_CAN_SEND_TO_USER``` and
```HOOKTYPE_CAN_SEND_TO_CHANNEL```: the final argument has changed
from ```int notice``` to ```SendType sendtype```, which is an
enum, since we now have 3 message options (PRIVMSG, NOTICE, TAGMSG).
Upgrading from UnrealIRCd 4?
-----------------------------
Are you upgrading from UnrealIRCd 4.x to UnrealIRCd 5?
Then check out the *UnrealIRCd 5* release notes [further down](#unrealircd-5). At the
very least, check out [Upgrading from 4.x](https://www.unrealircd.org/docs/Upgrading_from_4.x).
UnrealIRCd 5.0.4
------------------
This new 5.0.4 version fixes quite a number of bugs. It contains only two small feature improvements.
Fixes:
@ -35,13 +111,6 @@ Changes:
[set::plaintext-policy::oper-message](https://www.unrealircd.org/docs/Set_block#set::plaintext-policy).
* The French HELPOP text was updated.
Upgrading from UnrealIRCd 4?
-----------------------------
Are you upgrading from UnrealIRCd 4.x to UnrealIRCd 5?
Then check out the *UnrealIRCd 5* release notes [further down](#unrealircd-5). At the
very least, check out [Upgrading from 4.x](https://www.unrealircd.org/docs/Upgrading_from_4.x).
UnrealIRCd 5.0.3.1
-------------------
This fixes a crash issue after REHASH in 5.0.3.

View File

@ -156,8 +156,10 @@ loadmodule "extbans/textban"; /* +b ~T */
loadmodule "extbans/timedban"; /* +b ~t */
// IRCv3 Extensions
loadmodule "account-notify";
loadmodule "account-tag";
loadmodule "batch";
loadmodule "clienttagdeny";
loadmodule "echo-message";
loadmodule "labeled-response";
loadmodule "link-security";
@ -166,6 +168,7 @@ loadmodule "message-tags";
loadmodule "plaintext-policy";
loadmodule "server-time";
loadmodule "sts";
loadmodule "typing-indicator";
// Other
loadmodule "antimixedutf8";
@ -180,6 +183,7 @@ loadmodule "history_backend_mem";
#loadmodule "history_backend_null";
loadmodule "ident_lookup";
loadmodule "jointhrottle";
#loadmodule "targetfloodprot";
loadmodule "tkldb";
loadmodule "tls_antidos";
loadmodule "userhost-tag";

View File

@ -1 +1 @@
https://modules.unrealircd.org/modules.list
https://modules.unrealircd.org/modules.list

View File

@ -101,7 +101,7 @@ operclass netadmin {
permissions {
chat { notice { global; } }
client { set; }
immune { join-flood; max-conncurrent-conversionations; maxchannelsperuser; nick-flood; server-ban { spamfilter; } }
immune { join-flood; max-conncurrent-conversionations; maxchannelsperuser; nick-flood; server-ban { spamfilter; }; target-flood; }
kill;
channel { operonly; override; see; }
route;

View File

@ -1,7 +1,7 @@
##
## Bundle of CA Root Certificates
##
## Certificate data from Mozilla as of: Wed Oct 16 03:12:09 2019 GMT
## Certificate data from Mozilla as of: Wed Jan 1 04:12:10 2020 GMT
##
## This is a bundle of X.509 certificates of public Certificate Authorities
## (CA). These were automatically extracted from Mozilla's root certificates
@ -14,7 +14,7 @@
## Just configure this file as the SSLCACertificateFile.
##
## Conversion done with mk-ca-bundle.pl version 1.27.
## SHA256: c979c6f35714a0fedb17d9e5ba37adecbbc91a8faf4186b4e23d6f9ca44fd6cb
## SHA256: f3bdcd74612952da8476a9d4147f50b29ad0710b7dd95b4c8690500209986d70
##
@ -3430,3 +3430,37 @@ hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB
60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq
dBb9HxEGmpv0
-----END CERTIFICATE-----
Entrust Root Certification Authority - G4
=========================================
-----BEGIN CERTIFICATE-----
MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAwgb4xCzAJBgNV
BAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Qu
bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1
dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1
dGhvcml0eSAtIEc0MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYT
AlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhv
cml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhv
cml0eSAtIEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3D
umSXbcr3DbVZwbPLqGgZ2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV
3imz/f3ET+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j5pds
8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAMC1rlLAHGVK/XqsEQ
e9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73TDtTUXm6Hnmo9RR3RXRv06QqsYJn7
ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNXwbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5X
xNMhIWNlUpEbsZmOeX7m640A2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV
7rtNOzK+mndmnqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8
dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwlN4y6mACXi0mW
Hv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNjc0kCAwEAAaNCMEAwDwYDVR0T
AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9n
MA0GCSqGSIb3DQEBCwUAA4ICAQAS5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4Q
jbRaZIxowLByQzTSGwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht
7LGrhFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/B7NTeLUK
YvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uIAeV8KEsD+UmDfLJ/fOPt
jqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbwH5Lk6rWS02FREAutp9lfx1/cH6NcjKF+
m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKW
RGhXxNUzzxkvFMSUHHuk2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjA
JOgc47OlIQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk5F6G
+TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuYn/PIjhs4ViFqUZPT
kcpG2om3PVODLAgfi49T3f+sHw==
-----END CERTIFICATE-----

View File

@ -16,6 +16,11 @@ class servers { pingfreq 120; maxclients 10; sendq 1M; connfreq 30; }
allow { ip *; class clients; maxperip 2; }
#require authentication {
# mask *@*;
# reason "8,4 E N T E R T H E V O I D ";
#}
listen { ip *; port 6667; options { clientsonly; } }
listen { ip *; port 6697; options { clientsonly; tls; } }
listen { ip *; port REDACTED; options { serversonly; tls; } }
@ -90,12 +95,12 @@ set {
level-on-join "op";
restrict-channelmodes "CnLpPs";
restrict-commands {
channel-message { connect-delay 60; exempt-identified yes; exempt-reputation-score 24; }
invite { connect-delay 3600; exempt-identified yes; exempt-reputation-score 24; }
join { connect-delay 60; exempt-identified yes; exempt-reputation-score 24; }
list { connect-delay 120; exempt-identified yes; exempt-reputation-score 24; }
private-message { connect-delay 300; exempt-identified yes; exempt-reputation-score 24; }
private-notice { connect-delay 3600; exempt-identified yes; exempt-reputation-score 24; }
channel-message { connect-delay 60; exempt-identified yes; exempt-reputation-score 100; }
invite { connect-delay 3600; exempt-identified yes; exempt-reputation-score 100; }
join { connect-delay 60; exempt-identified yes; exempt-reputation-score 100; }
list { connect-delay 120; exempt-identified yes; exempt-reputation-score 100; }
private-message { connect-delay 300; exempt-identified yes; exempt-reputation-score 100; }
private-notice { connect-delay 3600; exempt-identified yes; exempt-reputation-score 100; }
}
auto-join "#superbowl";
oper-auto-join "#help";
@ -132,24 +137,37 @@ set {
user-message "4WARNING: You are using an outdated SSL/TLS protocol or cipher";
oper-message "Network operators must connect using an up-to-date SSL/TLS protocol or cipher";
}
#handshake-timeout 60s; # Enable for authprompt
anti-flood {
away-flood 3:300;
away-flood 3:300;
connect-flood 3:300;
invite-flood 3:300;
join-flood 3:300;
knock-flood 3:300;
max-concurrent-conversations { users 5; new-user-every 60s; }
nick-flood 3:300;
invite-flood 3:300;
join-flood 3:300;
knock-flood 3:300;
nick-flood 3:300;
max-concurrent-conversations {
users 5;
new-user-every 60s;
}
#target-flood {
# channel-privmsg 45:5;
# channel-notice 15:5;
# channel-tagmsg 15:5;
# private-privmsg 30:5;
# private-notice 10:5;
# private-tagmsg 10:5;
#}
unknown-flood-amount 2048;
unknown-flood-bantime 1h;
}
default-bantime 1d;
default-bantime 30d;
modef-default-unsettime 5;
spamfilter {
ban-time 1d;
ban-reason "8,4 E N T E R T H E V O I D ";
except "#anythinggoes";
}
max-targets-per-command { kick 1; part 1; privmsg 1; }
max-targets-per-command { kick 1; notice 1; part 1; privmsg 1; }
hide-ban-reason yes;
reject-message {
gline "8,4 E N T E R T H E V O I D ";
@ -163,8 +181,13 @@ set {
score 10;
ban-action block;
ban-reason "8,4 E N T E R T H E V O I D ";
ban-time 1h;
}
#authentication-prompt {
# enabled yes;
# message "The server requires clients from this IP address to authenticate with a registered nickname and password.";
# message "Please reconnect using SASL, or authenticate now by typing: /QUOTE AUTH nick:password";
# fail-message "Authentication failed";
#}
connthrottle {
known-users { minimum-reputation-score 24; sasl-bypass yes; }
new-users { local-throttle 20:60; global-throttle 30:60; }
@ -176,7 +199,7 @@ set {
max-storage-per-channel { lines 100; time 1d; }
}
}
manual-ban-target ip;
hide-idle-time { policy always; }
}
hideserver {

View File

@ -23,8 +23,15 @@ fi
git clone -q https://github.com/unrealircd/unrealircd-tests.git
cd unrealircd-tests
# Run the test framework, testing both services:
# FreeBSD has various issues with the tests from us and others,
# better set a flag to keep it simple:
FREEBSD=0
if uname -a|grep -q FreeBSD; then
FREEBSD=1
fi
# Run the test framework, testing both services:
if [ "$FREEBSD" = 1 ]; then
# FreeBSD runs without services since they fail mysteriously:
./run -services none || exit 1
else
@ -34,7 +41,8 @@ else
fi
# Do cipherscan test at the end
if [[ "$OSTYPE" != "freebsd"* ]]; then
# Has problems on non-Linux-64-bit, so we skip there:
if [ "$FREEBSD" = 0 -a "$HOSTNAME" != "ub18-ia32" ]; then
sleep 2
cd ../extras/tests/tls
./tls-tests

View File

@ -3,7 +3,7 @@ rem Build command for Visual Studio 2019
nmake -f makefile.windows ^
LIBRESSL_INC_DIR="c:\projects\unrealircd-5-libs\libressl\include" ^
LIBRESSL_LIB_DIR="c:\projects\unrealircd-5-libs\libressl\lib" ^
SSLLIB="crypto-45.lib ssl-47.lib" ^
SSLLIB="crypto-46.lib ssl-48.lib" ^
USE_REMOTEINC=1 ^
LIBCURL_INC_DIR="c:\projects\unrealircd-5-libs\curl\include" ^
LIBCURL_LIB_DIR="c:\projects\unrealircd-5-libs\curl\builds\libcurl-vc-x64-release-dll-ssl-dll-cares-dll-ipv6-obj-lib" ^

Binary file not shown.

View File

@ -4,7 +4,7 @@ OUTF="curl-latest.tar.gz"
OUTD="curl-latest"
ARESPATH="`pwd`/extras/c-ares"
UNREALDIR="`pwd`"
CARESVERSION="1.15.0"
CARESVERSION="1.16.0"
LIBDIR="$1"
if [ "x$1" = "x" ]; then

View File

@ -38,7 +38,7 @@ PROJECT_NAME = "UnrealIRCd"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 5.0.4
PROJECT_NUMBER = 5.0.5
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

Binary file not shown.

View File

@ -174,7 +174,6 @@ extern void set_snomask(Client *client, char *snomask);
extern char *get_snomask_string(Client *client);
extern int check_tkls(Client *cptr);
/* for services */
extern void del_invite(Client *, Channel *);
extern void send_user_joins(Client *, Client *);
extern int valid_channelname(const char *);
extern int valid_server_name(char *name);
@ -623,6 +622,8 @@ extern char *spamfilter_inttostring_long(int v);
extern Channel *get_channel(Client *cptr, char *chname, int flag);
extern MODVAR char backupbuf[];
extern void add_invite(Client *, Client *, Channel *, MessageTag *);
extern void del_invite(Client *, Channel *);
extern int is_invited(Client *client, Channel *channel);
extern void channel_modes(Client *cptr, char *mbuf, char *pbuf, size_t mbuf_size, size_t pbuf_size, Channel *channel);
extern MODVAR char modebuf[BUFSIZE], parabuf[BUFSIZE];
extern int op_can_override(char *acl, Client *client,Channel *channel,void* extra);
@ -884,6 +885,7 @@ extern char *certificate_name(SSL *ssl);
extern void start_of_normal_client_handshake(Client *acptr);
extern void clicap_pre_rehash(void);
extern void clicap_post_rehash(void);
extern void unload_all_unused_mtag_handlers(void);
extern void send_cap_notify(int add, char *token);
extern void sendbufto_one(Client *to, char *msg, unsigned int quick);
extern MODVAR int current_serial;
@ -970,3 +972,5 @@ extern void link_generator(void);
extern void update_throttling_timer_settings(void);
extern int hide_idle_time(Client *client, Client *target);
extern void lost_server_link(Client *serv, FORMAT_STRING(const char *fmt), ...);
extern char *sendtype_to_cmd(SendType sendtype);
extern MODVAR MessageTagHandler *mtaghandlers;

View File

@ -901,7 +901,7 @@ extern void SavePersistentIntX(ModuleInfo *modinfo, char *varshortname, int var)
#define SavePersistentInt(modinfo, var) SavePersistentIntX(modinfo, #var, var)
extern int LoadPersistentLongX(ModuleInfo *modinfo, char *varshortname, long *var);
#define LoadPersistentLong(modinfo, var) LoadPersistentIntX(modinfo, #var, &var)
#define LoadPersistentLong(modinfo, var) LoadPersistentLongX(modinfo, #var, &var)
extern void SavePersistentLongX(ModuleInfo *modinfo, char *varshortname, long var);
#define SavePersistentLong(modinfo, var) SavePersistentLongX(modinfo, #var, var)
@ -1009,6 +1009,7 @@ extern void SavePersistentLongX(ModuleInfo *modinfo, char *varshortname, long va
#define HOOKTYPE_CAN_SEND_TO_USER 105
#define HOOKTYPE_SERVER_SYNC 106
#define HOOKTYPE_ACCOUNT_LOGIN 107
#define HOOKTYPE_CLOSE_CONNECTION 108
/* Adding a new hook here?
* 1) Add the #define HOOKTYPE_.... with a new number
@ -1042,12 +1043,12 @@ char *hooktype_pre_local_kick(Client *client, Client *victim, Channel *channel,
int hooktype_can_kick(Client *client, Client *victim, Channel *channel, char *comment, long client_flags, long victim_flags, char **error);
int hooktype_local_kick(Client *client, Client *victim, Channel *channel, MessageTag *mtags, char *comment);
int hooktype_remote_kick(Client *client, Client *victim, Channel *channel, MessageTag *mtags, char *comment);
char *hooktype_pre_usermsg(Client *client, Client *to, char *text, int notice);
int hooktype_usermsg(Client *client, Client *to, MessageTag *mtags, char *text, int notice);
int hooktype_can_send_to_channel(Client *client, Channel *channel, Membership *member, char **text, char **errmsg, int notice);
int hooktype_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, int notice);
int hooktype_pre_chanmsg(Client *client, Channel *channel, MessageTag *mtags, char *text, int notice);
int hooktype_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, int notice);
char *hooktype_pre_usermsg(Client *client, Client *to, char *text, SendType sendtype);
int hooktype_usermsg(Client *client, Client *to, MessageTag *mtags, char *text, SendType sendtype);
int hooktype_can_send_to_channel(Client *client, Channel *channel, Membership *member, char **text, char **errmsg, SendType sendtype);
int hooktype_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype);
int hooktype_pre_chanmsg(Client *client, Channel *channel, MessageTag *mtags, char *text, SendType sendtype);
int hooktype_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, SendType sendtype);
char *hooktype_pre_local_topic(Client *client, Channel *channel, char *topic);
int hooktype_local_topic(Client *client, Channel *channel, char *topic);
int hooktype_topic(Client *client, Channel *channel, MessageTag *mtags, char *topic);
@ -1084,7 +1085,7 @@ int hooktype_tkl_add(Client *client, TKL *tkl);
int hooktype_tkl_del(Client *client, TKL *tkl);
int hooktype_log(int flags, char *timebuf, char *buf);
int hooktype_local_spamfilter(Client *acptr, char *str, char *str_in, int type, char *target, TKL *tkl);
int hooktype_silenced(Client *client, Client *to, int notice);
int hooktype_silenced(Client *client, Client *to, SendType sendtype);
int hooktype_rawpacket_in(Client *client, char *readbuf, int *length);
int hooktype_packet(Client *from, Client *to, Client *intended_to, char **msg, int *length);
int hooktype_handshake(Client *client);
@ -1121,6 +1122,7 @@ int hooktype_is_handshake_finished(Client *acptr);
char *hooktype_pre_local_quit_chan(Client *client, Channel *channel, char *comment);
int hooktype_ident_lookup(Client *acptr);
int hooktype_account_login(Client *client, MessageTag *mtags);
int hooktype_close_connection(Client *client);
#ifdef GCC_TYPECHECKING
#define ValidateHook(validatefunc, func) __builtin_types_compatible_p(__typeof__(func), __typeof__(validatefunc))
@ -1229,7 +1231,8 @@ _UNREAL_ERROR(_hook_error_incompatible, "Incompatible hook function. Check argum
((hooktype == HOOKTYPE_PRE_LOCAL_QUIT_CHAN) && !ValidateHook(hooktype_pre_local_quit_chan, func)) || \
((hooktype == HOOKTYPE_IDENT_LOOKUP) && !ValidateHook(hooktype_ident_lookup, func)) || \
((hooktype == HOOKTYPE_CONFIGRUN_EX) && !ValidateHook(hooktype_configrun_ex, func)) || \
((hooktype == HOOKTYPE_ACCOUNT_LOGIN) && !ValidateHook(hooktype_account_login, func)) ) \
((hooktype == HOOKTYPE_ACCOUNT_LOGIN) && !ValidateHook(hooktype_account_login, func)) || \
((hooktype == HOOKTYPE_CLOSE_CONNECTION) && !ValidateHook(hooktype_close_connection, func)) ) \
_hook_error_incompatible();
#endif /* GCC_TYPECHECKING */

View File

@ -140,6 +140,12 @@ typedef enum OperClassEntryType { OPERCLASSENTRY_ALLOW=1, OPERCLASSENTRY_DENY=2}
typedef enum OperPermission { OPER_ALLOW=1, OPER_DENY=0} OperPermission;
typedef enum SendType {
SEND_TYPE_PRIVMSG = 0,
SEND_TYPE_NOTICE = 1,
SEND_TYPE_TAGMSG = 2
} SendType;
struct OperClassValidator;
typedef struct OperClassValidator OperClassValidator;
typedef struct OperClassACLPath OperClassACLPath;
@ -338,6 +344,8 @@ typedef enum ClientStatus {
#define PROTO_MTAGS 0x010000 /* Support message tags and big buffers */
/* For client capabilities: */
#define CAP_INVERT 1L
/** HasCapabilityFast() checks for a token if you know exactly which bit to check */
#define HasCapabilityFast(cptr, val) ((cptr)->local->caps & (val))
/** HasCapability() checks for a token by name and is slightly slower */

View File

@ -63,7 +63,7 @@
#define UNREAL_VERSION_MAJOR 0
/* Minor version number (e.g.: 1 for Unreal3.2.1) */
#define UNREAL_VERSION_MINOR 4
#define UNREAL_VERSION_MINOR 5
/* Version suffix such as a beta marker or release candidate marker. (e.g.:
-rcX for unrealircd-3.2.9-rcX) */

View File

@ -98,10 +98,11 @@ void ClearCapability(Client *client, const char *token)
long clicap_allocate_cap(void)
{
long v = 1;
long v;
ClientCapability *clicap;
for (v=1; v < 2147483648; v = v * 2)
/* The first bit (v=1) is used by the "invert" marker */
for (v=2; v < LONG_MAX; v = v * 2)
{
unsigned char found = 0;
for (clicap = clicaps; clicap; clicap = clicap->next)

View File

@ -125,7 +125,6 @@ void moddata_free_local_client(Client *client)
memset(client->moddata, 0, sizeof(client->moddata));
}
// FIXME: this is never called
void moddata_free_channel(Channel *channel)
{
ModDataInfo *md;

View File

@ -1031,6 +1031,20 @@ void del_invite(Client *client, Channel *channel)
}
}
/** Is the user 'client' invited to channel 'channel' by a chanop?
* @param client The client who was invited
* @param channel The channel to which the person was invited
*/
int is_invited(Client *client, Channel *channel)
{
Link *lp;
for (lp = client->user->invited; lp; lp = lp->next)
if (lp->value.channel == channel)
return 1;
return 0;
}
/** Subtract one user from channel i. Free the channel if it became empty.
* @param channel The channel
* @returns 1 if the channel was freed, 0 if the channel still exists.
@ -1057,6 +1071,8 @@ int sub1_from_channel(Channel *channel)
* But first we will destroy all kinds of references and lists...
*/
moddata_free_channel(channel);
while ((lp = channel->invites))
del_invite(lp->value.client, channel);

View File

@ -1746,6 +1746,8 @@ void config_setdefaultsettings(Configuration *i)
i->manual_ban_target = BAN_TARGET_HOST;
i->hide_idle_time = HIDE_IDLE_TIME_OPER_USERMODE;
i->who_limit = 100;
}
static void make_default_logblock(void)
@ -2133,6 +2135,7 @@ int init_conf(char *rootconf, int rehash)
postconf();
config_status("Configuration loaded.");
clicap_post_rehash();
unload_all_unused_mtag_handlers();
return 0;
}
@ -8335,16 +8338,20 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
}
continue; /* required here, due to checknull directly below */
}
CheckNull(cepp);
if (!strcmp(cepp->ce_varname, "unknown-flood-bantime"))
{
CheckNull(cepp);
CheckDuplicate(cepp, anti_flood_unknown_flood_bantime, "anti-flood::unknown-flood-bantime");
}
else if (!strcmp(cepp->ce_varname, "unknown-flood-amount")) {
else if (!strcmp(cepp->ce_varname, "unknown-flood-amount"))
{
CheckNull(cepp);
CheckDuplicate(cepp, anti_flood_unknown_flood_amount, "anti-flood::unknown-flood-amount");
}
else if (!strcmp(cepp->ce_varname, "away-count")) {
else if (!strcmp(cepp->ce_varname, "away-count"))
{
int temp = atol(cepp->ce_vardata);
CheckNull(cepp);
CheckDuplicate(cepp, anti_flood_away_count, "anti-flood::away-count");
if (temp < 1 || temp > 255)
{
@ -8353,7 +8360,9 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
errors++;
}
}
else if (!strcmp(cepp->ce_varname, "away-period")) {
else if (!strcmp(cepp->ce_varname, "away-period"))
{
CheckNull(cepp);
int temp = config_checkval(cepp->ce_vardata, CFG_TIME);
CheckDuplicate(cepp, anti_flood_away_period, "anti-flood::away-period");
if (temp < 10)
@ -8366,6 +8375,7 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
else if (!strcmp(cepp->ce_varname, "away-flood"))
{
int cnt, period;
CheckNull(cepp);
if (settings.has_anti_flood_away_period)
{
config_warn("%s:%d: set::anti-flood::away-flood overrides set::anti-flood::away-period",
@ -8392,6 +8402,7 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
else if (!strcmp(cepp->ce_varname, "nick-flood"))
{
int cnt, period;
CheckNull(cepp);
CheckDuplicate(cepp, anti_flood_nick_flood, "anti-flood::nick-flood");
if (!config_parse_flood(cepp->ce_vardata, &cnt, &period) ||
(cnt < 1) || (cnt > 255) || (period < 5))
@ -8405,6 +8416,7 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
else if (!strcmp(cepp->ce_varname, "invite-flood"))
{
int cnt, period;
CheckNull(cepp);
CheckDuplicate(cepp, anti_flood_invite_flood, "anti-flood::invite-flood");
if (!config_parse_flood(cepp->ce_vardata, &cnt, &period) ||
(cnt < 1) || (cnt > 255) || (period < 5))
@ -8418,6 +8430,7 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
else if (!strcmp(cepp->ce_varname, "knock-flood"))
{
int cnt, period;
CheckNull(cepp);
CheckDuplicate(cepp, anti_flood_knock_flood, "anti-flood::knock-flood");
if (!config_parse_flood(cepp->ce_vardata, &cnt, &period) ||
(cnt < 1) || (cnt > 255) || (period < 5))
@ -8431,6 +8444,7 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
else if (!strcmp(cepp->ce_varname, "connect-flood"))
{
int cnt, period;
CheckNull(cepp);
CheckDuplicate(cepp, anti_flood_connect_flood, "anti-flood::connect-flood");
if (!config_parse_flood(cepp->ce_vardata, &cnt, &period) ||
(cnt < 1) || (cnt > 255) || (period < 1) || (period > 3600))

View File

@ -306,7 +306,7 @@ int crule_gettoken(int *next_tokp, char **ruleptr)
void crule_getword(char *word, int *wordlenp, int maxlen, char **ruleptr)
{
char *word_ptr;
char *word_ptr, c;
word_ptr = word;
/* Both - and : can appear in hostnames so they must not be
@ -315,8 +315,16 @@ void crule_getword(char *word, int *wordlenp, int maxlen, char **ruleptr)
while ((isalnum(**ruleptr)) || (**ruleptr == '*') ||
(**ruleptr == '?') || (**ruleptr == '.') || (**ruleptr == '-') ||
(**ruleptr == ':'))
*word_ptr++ = *(*ruleptr)++;
*word_ptr = '\0';
{
c = *(*ruleptr)++;
if (maxlen > 1) /* >1 instead of >0 so we (possibly) still have room for NUL */
{
*word_ptr++ = c;
maxlen--;
}
}
if (maxlen)
*word_ptr = '\0';
*wordlenp = word_ptr - word;
}

View File

@ -405,7 +405,7 @@ Match *unreal_create_match(MatchType type, char *str, char **error)
int options = 0;
char buf2[512];
options = PCRE2_CASELESS|PCRE2_NEVER_UTF|PCRE2_NEVER_UCP;
options = PCRE2_CASELESS|PCRE2_MATCH_INVALID_UTF;
m->ext.pcre2_expr = pcre2_compile(str, PCRE2_ZERO_TERMINATED, options, &errorcode, &erroroffset, NULL);
if (m->ext.pcre2_expr == NULL)

View File

@ -1912,3 +1912,15 @@ void freemultiline(MultiLine *l)
safe_free(l);
}
}
/** Convert a sendtype to a command string */
char *sendtype_to_cmd(SendType sendtype)
{
if (sendtype == SEND_TYPE_PRIVMSG)
return "PRIVMSG";
if (sendtype == SEND_TYPE_NOTICE)
return "NOTICE";
if (sendtype == SEND_TYPE_TAGMSG)
return "TAGMSG";
return NULL;
}

View File

@ -71,7 +71,9 @@ R_MODULES= \
account-tag.so labeled-response.so link-security.so \
message-ids.so plaintext-policy.so server-time.so sts.so \
echo-message.so userip-tag.so userhost-tag.so \
ident_lookup.so history.so
typing-indicator.so \
ident_lookup.so history.so \
targetfloodprot.so clienttagdeny.so
MODULES=cloak.so $(R_MODULES)
MODULEFLAGS=@MODULEFLAGS@
@ -610,6 +612,10 @@ userhost-tag.so: userhost-tag.c $(INCLUDES)
$(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
-o userhost-tag.so userhost-tag.c
typing-indicator.so: typing-indicator.c $(INCLUDES)
$(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
-o typing-indicator.so typing-indicator.c
require-module.so: require-module.c $(INCLUDES)
$(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
-o require-module.so require-module.c
@ -626,6 +632,14 @@ history.so: history.c $(INCLUDES)
$(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
-o history.so history.c
targetfloodprot.so: targetfloodprot.c $(INCLUDES)
$(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
-o targetfloodprot.so targetfloodprot.c
clienttagdeny.so: clienttagdeny.c $(INCLUDES)
$(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
-o clienttagdeny.so clienttagdeny.c
#############################################################################
# capabilities
#############################################################################

View File

@ -66,6 +66,10 @@ int antimixedutf8_config_run(ConfigFile *, ConfigEntry *, int);
#define SCRIPT_UNDEFINED 0
#define SCRIPT_LATIN 1
#define SCRIPT_CYRILLIC 2
#define SCRIPT_CJK 3
#define SCRIPT_HANGUL 4
#define SCRIPT_CANADIAN 5
#define SCRIPT_TELUGU 6
/**** the detection algorithm follows first, the module/config code is at the end ****/
@ -95,6 +99,24 @@ int detect_script(const char *t)
else if ((t[0] == 0xd3) && (t[1] >= 0x80) && (t[1] <= 0xbf))
return SCRIPT_CYRILLIC;
if((t[0] == 0xe4) && (t[1] >= 0xb8) && (t[1] <= 0xbf))
return SCRIPT_CJK;
else if ((t[0] >= 0xe5) && (t[0] <= 0xe9) && (t[1] >= 0x80) && (t[1] <= 0xbf))
return SCRIPT_CJK;
if((t[0] == 0xea) && (t[1] >= 0xb0) && (t[1] <= 0xbf))
return SCRIPT_HANGUL;
else if ((t[0] >= 0xeb) && (t[0] <= 0xec) && (t[1] >= 0x80) && (t[1] <= 0xbf))
return SCRIPT_HANGUL;
else if ((t[0] == 0xed) && (t[1] >= 0x80) && (t[1] <= 0x9f))
return SCRIPT_HANGUL;
if((t[0] == 0xe1) && (t[1] >= 0x90) && (t[1] <= 0x99))
return SCRIPT_CANADIAN;
if((t[0] == 0xe0) && (t[1] >= 0xb0) && (t[1] <= 0xb1))
return SCRIPT_TELUGU;
if ((t[0] >= 'a') && (t[0] <= 'z'))
return SCRIPT_LATIN;
if ((t[0] >= 'A') && (t[0] <= 'Z'))

View File

@ -20,7 +20,7 @@ Cmode_t EXTMODE_CENSOR = 0L;
#define IsCensored(x) ((x)->mode.extmode & EXTMODE_CENSOR)
int censor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice);
int censor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
char *censor_pre_local_part(Client *client, Channel *channel, char *text);
char *censor_pre_local_quit(Client *client, char *text);
@ -253,7 +253,7 @@ char *stripbadwords_channel(char *str, int *blocked)
return stripbadwords(str, conf_badword_channel, blocked);
}
int censor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice)
int censor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
{
int blocked;
Hook *h;

View File

@ -30,7 +30,7 @@ int moded_part(Client *client, Channel *channel, MessageTag *mtags, char *commen
int deny_all(Client *client, Channel *channel, char mode, char *para, int checkt, int what);
int moded_chanmode(Client *client, Channel *channel,
MessageTag *mtags, char *modebuf, char *parabuf, time_t sendts, int samode);
int moded_prechanmsg(Client *client, Channel *channel, MessageTag *mtags, char *text, int notice);
int moded_prechanmsg(Client *client, Channel *channel, MessageTag *mtags, char *text, SendType sendtype);
char *moded_serialize(ModData *m);
void moded_unserialize(char *str, ModData *m);
@ -367,7 +367,7 @@ int moded_chanmode(Client *client, Channel *channel, MessageTag *recv_mtags, cha
return 0;
}
int moded_prechanmsg(Client *client, Channel *channel, MessageTag *mtags, char *text, int notice)
int moded_prechanmsg(Client *client, Channel *channel, MessageTag *mtags, char *text, SendType sendtype)
{
if ((channel_is_delayed(channel) || channel_is_post_delayed(channel)) && (moded_user_invisible(client, channel)))
clear_user_invisible_announce(channel, client, mtags);

View File

@ -117,8 +117,8 @@ int cmodef_sjoin_check(Channel *channel, void *ourx, void *theirx);
int floodprot_join(Client *client, Channel *channel, MessageTag *mtags, char *parv[]);
EVENT(modef_event);
int cmodef_channel_destroy(Channel *channel, int *should_destroy);
int floodprot_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice);
int floodprot_post_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, int notice);
int floodprot_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
int floodprot_post_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, SendType sendtype);
int floodprot_knock(Client *client, Channel *channel, MessageTag *mtags, char *comment);
int floodprot_nickchange(Client *client, char *oldnick);
int floodprot_chanmode_del(Channel *channel, int m);
@ -623,10 +623,11 @@ void *cmodef_put_param(void *fld_in, char *param)
/* if new 'per xxx seconds' is smaller than current 'per' then reset timers/counters (t, c) */
if (v < fld->per)
{
for (v=0; v < NUMFLD; v++)
int i;
for (i=0; i < NUMFLD; i++)
{
fld->timer[v] = 0;
fld->counter[v] = 0;
fld->timer[i] = 0;
fld->counter[i] = 0;
}
}
fld->per = v;
@ -939,7 +940,7 @@ char *channel_modef_string(ChannelFloodProtection *x, char *retbuf)
return retbuf;
}
int floodprot_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice)
int floodprot_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
{
Membership *mb;
ChannelFloodProtection *chp;
@ -952,6 +953,8 @@ int floodprot_can_send_to_channel(Client *client, Channel *channel, Membership *
if (!MyUser(client))
return HOOK_CONTINUE;
if (sendtype == SEND_TYPE_TAGMSG)
return 0; // TODO: some TAGMSG specific limit? (1 of 2)
if (ValidatePermissionsForPath("channel:override:flood",client,NULL,channel,NULL) || !IsFloodLimit(channel) || is_skochanop(client, channel))
return HOOK_CONTINUE;
@ -1061,11 +1064,14 @@ int floodprot_can_send_to_channel(Client *client, Channel *channel, Membership *
return HOOK_CONTINUE;
}
int floodprot_post_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, int notice)
int floodprot_post_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, SendType sendtype)
{
if (!IsFloodLimit(channel) || is_skochanop(client, channel) || IsULine(client))
return 0;
if (sendtype == SEND_TYPE_TAGMSG)
return 0; // TODO: some TAGMSG specific limit? (2 of 2)
/* HINT: don't be so stupid to reorder the items in the if's below.. you'll break things -- Syzop. */
if (do_floodprot(channel, FLD_MSG) && MyUser(client))

View File

@ -47,7 +47,7 @@ void history_chanmode_free_param(void *r);
void *history_chanmode_dup_struct(void *r_in);
int history_chanmode_sjoin_check(Channel *channel, void *ourx, void *theirx);
int history_channel_destroy(Channel *channel, int *should_destroy);
int history_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, int notice);
int history_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, SendType sendtype);
int history_join(Client *client, Channel *channel, MessageTag *mtags, char *parv[]);
MOD_TEST()
@ -490,7 +490,7 @@ int history_channel_destroy(Channel *channel, int *should_destroy)
return 0;
}
int history_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, int notice)
int history_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, SendType sendtype)
{
char buf[512];
char source[64];
@ -503,6 +503,10 @@ int history_chanmsg(Client *client, Channel *channel, int sendflags, int prefix,
if ((*text == '\001') && strncmp(text+1, "ACTION", 6))
return 0;
/* Filter out TAGMSG */
if (sendtype == SEND_TYPE_TAGMSG)
return 0;
/* Lazy: if any prefix is addressed (eg: @#channel) then don't record it.
* This so we don't have to check privileges during history playback etc.
*/
@ -516,7 +520,7 @@ int history_chanmsg(Client *client, Channel *channel, int sendflags, int prefix,
snprintf(buf, sizeof(buf), ":%s %s %s :%s",
source,
notice ? "NOTICE" : "PRIVMSG",
sendtype_to_cmd(sendtype),
channel->chname,
text);

View File

@ -357,39 +357,43 @@ int link_pre_localjoin_cb(Client *client, Channel *channel, char *parv[])
if (IsULine(client) || find_membership_link(client->user->channel, channel))
return HOOK_CONTINUE;
// Extbans take precedence over +L #channel and other restrictions
for(ban = channel->banlist; ban; ban = ban->next)
// Extbans take precedence over +L #channel and other restrictions,
// only /INVITE from chanop bypasses:
if (!is_invited(client, channel))
{
if (!strncmp(ban->banstr, "~f:", 3))
for(ban = channel->banlist; ban; ban = ban->next)
{
strlcpy(bantmp, ban->banstr + 3, sizeof(bantmp));
} else
if (!strncmp(ban->banstr, "~t:", 3))
{
/* A timed ban, but is it for us? Need to parse a little:
* ~t:dddd:~f:...
*/
char *p = strchr(ban->banstr + 3, ':');
if (p && !strncmp(p, ":~f:", 4))
if (!strncmp(ban->banstr, "~f:", 3))
{
strlcpy(bantmp, p + 4, sizeof(bantmp));
} else {
/* Not for us - some other ~t ban */
strlcpy(bantmp, ban->banstr + 3, sizeof(bantmp));
} else
if (!strncmp(ban->banstr, "~t:", 3))
{
/* A timed ban, but is it for us? Need to parse a little:
* ~t:dddd:~f:...
*/
char *p = strchr(ban->banstr + 3, ':');
if (p && !strncmp(p, ":~f:", 4))
{
strlcpy(bantmp, p + 4, sizeof(bantmp));
} else {
/* Not for us - some other ~t ban */
continue;
}
} else
{
/* Not for us */
continue;
}
} else
{
/* Not for us */
continue;
}
banchan = bantmp;
banmask = strchr(bantmp, ':');
if (!banmask || !banmask[1])
continue;
*banmask++ = '\0';
banchan = bantmp;
banmask = strchr(bantmp, ':');
if (!banmask || !banmask[1])
continue;
*banmask++ = '\0';
if (ban_check_mask(client, channel, banmask, BANCHK_JOIN, NULL, NULL, 0))
return link_doforward(client, channel, banchan, LINKTYPE_BAN);
if (ban_check_mask(client, channel, banmask, BANCHK_JOIN, NULL, NULL, 0))
return link_doforward(client, channel, banchan, LINKTYPE_BAN);
}
}
// Either +L is not set, or it is set but the parameter isn't stored somehow
@ -397,7 +401,7 @@ int link_pre_localjoin_cb(Client *client, Channel *channel, char *parv[])
return HOOK_CONTINUE;
// can_join() actually returns 0 if we *can* join a channel, so we don't need to bother checking any further conditions
if (!(canjoin = can_join(client, channel, NULL, parv)))
if (!(canjoin = can_join(client, channel, parv[2], parv)))
return HOOK_CONTINUE;
// Oper only channel

View File

@ -34,7 +34,7 @@ Cmode_t EXTCMODE_NOCOLOR;
#define IsNoColor(channel) (channel->mode.extmode & EXTCMODE_NOCOLOR)
int nocolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice);
int nocolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
char *nocolor_prelocalpart(Client *client, Channel *channel, char *comment);
char *nocolor_prelocalquit(Client *client, char *comment);
@ -85,7 +85,7 @@ static int IsUsingColor(char *s)
return 0;
}
int nocolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice)
int nocolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
{
Hook *h;
int i;

View File

@ -34,7 +34,7 @@ Cmode_t EXTCMODE_NOCTCP;
#define IsNoCTCP(channel) (channel->mode.extmode & EXTCMODE_NOCTCP)
int noctcp_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice);
int noctcp_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
MOD_TEST()
{
@ -78,7 +78,7 @@ static int IsACTCP(char *s)
return 0;
}
int noctcp_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice)
int noctcp_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
{
if (IsNoCTCP(channel) && IsACTCP(*msg))
{

View File

@ -32,7 +32,7 @@ Cmode_t EXTCMODE_NONOTICE;
#define IsNoNotice(channel) (channel->mode.extmode & EXTCMODE_NONOTICE)
int nonotice_check_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice);
int nonotice_check_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
MOD_TEST()
{
@ -65,13 +65,14 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
int nonotice_check_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice)
int nonotice_check_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
{
Hook *h;
int i;
if (notice && IsNoNotice(channel) &&
(!lp || !(lp->flags & (CHFL_CHANOP | CHFL_CHANOWNER | CHFL_CHANADMIN))))
if ((sendtype == SEND_TYPE_NOTICE) &&
IsNoNotice(channel) &&
(!lp || !(lp->flags & (CHFL_CHANOP | CHFL_CHANOWNER | CHFL_CHANADMIN))))
{
for (h = Hooks[HOOKTYPE_CAN_BYPASS_CHANNEL_MESSAGE_RESTRICTION]; h; h = h->next)
{

View File

@ -34,7 +34,7 @@ static char errMsg[2048];
#define IsRegOnlySpeak(channel) (channel->mode.extmode & EXTCMODE_REGONLYSPEAK)
int regonlyspeak_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice);
int regonlyspeak_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
char *regonlyspeak_part_message (Client *client, Channel *channel, char *comment);
MOD_TEST()
@ -81,7 +81,7 @@ char *regonlyspeak_part_message (Client *client, Channel *channel, char *comment
return comment;
}
int regonlyspeak_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice)
int regonlyspeak_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
{
Hook *h;
int i;

View File

@ -140,11 +140,10 @@ int secureonly_check_join(Client *client, Channel *channel, char *key, char *par
/* if the channel is +z we still allow an ircop to bypass it
* if they are invited.
*/
for (lp = client->user->invited; lp; lp = lp->next)
if (lp->value.channel == channel)
return HOOK_CONTINUE;
if (is_invited(client, channel))
return HOOK_CONTINUE;
}
return (ERR_SECUREONLYCHAN);
return ERR_SECUREONLYCHAN;
}
return 0;
}

View File

@ -34,7 +34,7 @@ Cmode_t EXTCMODE_STRIPCOLOR;
#define IsStripColor(channel) (channel->mode.extmode & EXTCMODE_STRIPCOLOR)
int stripcolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice);
int stripcolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
char *stripcolor_prelocalpart(Client *client, Channel *channel, char *comment);
char *stripcolor_prelocalquit(Client *client, char *comment);
@ -73,7 +73,7 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
int stripcolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice)
int stripcolor_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
{
Hook *h;
int i;

View File

@ -67,7 +67,7 @@ struct cfgstruct {
};
static struct cfgstruct cfg;
static int channeldb_loaded = 0;
static long channeldb_next_event = 0;
MOD_TEST()
{
@ -80,7 +80,7 @@ MOD_INIT()
{
MARK_AS_OFFICIAL_MODULE(modinfo);
LoadPersistentInt(modinfo, channeldb_loaded);
LoadPersistentLong(modinfo, channeldb_next_event);
setcfg();
@ -90,7 +90,7 @@ MOD_INIT()
MOD_LOAD()
{
if (!channeldb_loaded)
if (!channeldb_next_event)
{
/* If this is the first time that our module is loaded, then read the database. */
if (!read_channeldb())
@ -102,9 +102,9 @@ MOD_LOAD()
else
config_warn("[channeldb] Failed to rename database from %s to %s: %s", cfg.database, fname, strerror(errno));
}
channeldb_loaded = 1;
channeldb_next_event = TStime() + CHANNELDB_SAVE_EVERY;
}
EventAdd(modinfo->handle, "channeldb_write_channeldb", write_channeldb_evt, NULL, CHANNELDB_SAVE_EVERY*1000, 0);
EventAdd(modinfo->handle, "channeldb_write_channeldb", write_channeldb_evt, NULL, 1000, 0);
if (ModuleGetError(modinfo->handle) != MODERR_NOERROR)
{
config_error("A critical error occurred when loading module %s: %s", MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle));
@ -115,9 +115,8 @@ MOD_LOAD()
MOD_UNLOAD()
{
write_channeldb();
freecfg();
SavePersistentInt(modinfo, channeldb_loaded);
SavePersistentLong(modinfo, channeldb_next_event);
return MOD_SUCCESS;
}
@ -191,6 +190,9 @@ int channeldb_configrun(ConfigFile *cf, ConfigEntry *ce, int type)
EVENT(write_channeldb_evt)
{
if (channeldb_next_event > TStime())
return;
channeldb_next_event = TStime() + CHANNELDB_SAVE_EVERY;
write_channeldb();
}

View File

@ -0,0 +1,77 @@
/*
* IRC - Internet Relay Chat, src/modules/echo-message.c
* (C) 2020 k4be for The UnrealIRCd Team
*
* See file AUTHORS in IRC package for additional names of
* the programmers.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "unrealircd.h"
char *ct_isupport_param(void);
int tags_rehash_complete(void);
Module *module;
ModuleHeader MOD_HEADER = {
"clienttagdeny",
"5.0",
"Informs clients about supported client tags",
"k4be",
"unrealircd-5",
};
MOD_INIT(){
MARK_AS_OFFICIAL_MODULE(modinfo);
return MOD_SUCCESS;
}
MOD_LOAD(){
module = modinfo->handle;
ISupportAdd(module, "CLIENTTAGDENY", ct_isupport_param());
HookAdd(module, HOOKTYPE_REHASH_COMPLETE, 0, tags_rehash_complete);
return MOD_SUCCESS;
}
MOD_UNLOAD(){
return MOD_SUCCESS;
}
#define BUFLEN 500
char *ct_isupport_param(void){
static char buf[BUFLEN];
MessageTagHandler *m;
strlcpy(buf, "*", sizeof(buf));
for (m = mtaghandlers; m; m = m->next) {
if(!m->unloaded && m->name[0] == '+'){
strlcat(buf, ",-", sizeof(buf));
strlcat(buf, m->name+1, sizeof(buf));
}
}
return buf;
}
int tags_rehash_complete(void){
ISupportSet(module, "CLIENTTAGDENY", ct_isupport_param());
return HOOK_CONTINUE;
}

View File

@ -44,8 +44,8 @@ int dccdeny_stats(Client *client, char *para);
CMD_FUNC(cmd_dccdeny);
CMD_FUNC(cmd_undccdeny);
CMD_FUNC(cmd_svsfline);
int dccdeny_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, int notice);
int dccdeny_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice);
int dccdeny_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype);
int dccdeny_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
int dccdeny_server_sync(Client *client);
static ConfigItem_deny_dcc *dcc_isforbidden(Client *client, char *filename);
static ConfigItem_deny_dcc *dcc_isdiscouraged(Client *client, char *filename);
@ -489,7 +489,7 @@ int dccdeny_server_sync(Client *client)
}
/** Check if a DCC should be blocked (user-to-user) */
int dccdeny_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, int notice)
int dccdeny_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype)
{
if (**text == '\001')
{
@ -507,7 +507,7 @@ int dccdeny_can_send_to_user(Client *client, Client *target, char **text, char *
}
/** Check if a DCC should be blocked (user-to-channel, unusual) */
int dccdeny_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice)
int dccdeny_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
{
static char errbuf[512];
@ -517,7 +517,7 @@ int dccdeny_can_send_to_channel(Client *client, Channel *channel, Membership *lp
char *filename = get_dcc_filename(*msg);
if (filename && !can_dcc(client, channel->chname, NULL, filename, &err))
{
if (!IsDead(client) && !notice)
if (!IsDead(client) && (sendtype != SEND_TYPE_NOTICE))
{
strlcpy(errbuf, err, sizeof(errbuf));
*errmsg = errbuf;

View File

@ -35,8 +35,8 @@ ModuleHeader MOD_HEADER
long CAP_ECHO_MESSAGE = 0L;
/* Forward declarations */
int em_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, int notice);
int em_usermsg(Client *client, Client *to, MessageTag *mtags, char *text, int notice);
int em_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, SendType sendtype);
int em_usermsg(Client *client, Client *to, MessageTag *mtags, char *text, SendType sendtype);
MOD_INIT()
{
@ -64,28 +64,44 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
int em_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, int notice)
int em_chanmsg(Client *client, Channel *channel, int sendflags, int prefix, char *target, MessageTag *mtags, char *text, SendType sendtype)
{
if (MyUser(client) && HasCapabilityFast(client, CAP_ECHO_MESSAGE))
{
sendto_prefix_one(client, client, mtags, ":%s %s %s :%s",
client->name,
notice ? "NOTICE" : "PRIVMSG",
target,
text);
if (sendtype != SEND_TYPE_TAGMSG)
{
sendto_prefix_one(client, client, mtags, ":%s %s %s :%s",
client->name,
sendtype_to_cmd(sendtype),
target,
text);
} else {
sendto_prefix_one(client, client, mtags, ":%s %s %s",
client->name,
sendtype_to_cmd(sendtype),
target);
}
}
return 0;
}
int em_usermsg(Client *client, Client *to, MessageTag *mtags, char *text, int notice)
int em_usermsg(Client *client, Client *to, MessageTag *mtags, char *text, SendType sendtype)
{
if (MyUser(client) && HasCapabilityFast(client, CAP_ECHO_MESSAGE))
{
sendto_prefix_one(client, client, mtags, ":%s %s %s :%s",
client->name,
notice ? "NOTICE" : "PRIVMSG",
to->name,
text);
if (sendtype != SEND_TYPE_TAGMSG)
{
sendto_prefix_one(client, client, mtags, ":%s %s %s :%s",
client->name,
sendtype_to_cmd(sendtype),
to->name,
text);
} else {
sendto_prefix_one(client, client, mtags, ":%s %s %s",
client->name,
sendtype_to_cmd(sendtype),
to->name);
}
}
return 0;
}

View File

@ -113,9 +113,8 @@ int _can_join(Client *client, Channel *channel, char *key, char *parv[])
if (banned && j == HOOK_DENY)
return (ERR_BANNEDFROMCHAN);
for (lp = client->user->invited; lp; lp = lp->next)
if (lp->value.channel == channel)
return 0;
if (is_invited(client, channel))
return 0; /* allowed */
if (channel->users >= channel->mode.limit)
{
@ -515,20 +514,12 @@ void _do_join(Client *client, int parc, char *parv[])
!strcasecmp(name, SPAMFILTER_VIRUSCHAN) &&
!ValidatePermissionsForPath("immune:server-ban:viruschan",client,NULL,NULL,NULL) && !spamf_ugly_vchanoverride)
{
int invited = 0;
Link *lp;
Channel *channel = find_channel(name, NULL);
if (channel)
if (!channel || !is_invited(client, channel))
{
for (lp = client->user->invited; lp; lp = lp->next)
if (lp->value.channel == channel)
invited = 1;
}
if (!invited)
{
sendnotice(client, "*** Cannot join '%s' because it's the virus-help-channel which is "
"reserved for infected users only", name);
sendnotice(client, "*** Cannot join '%s' because it's the virus-help-channel "
"which is reserved for infected users only", name);
continue;
}
}
@ -549,7 +540,17 @@ void _do_join(Client *client, int parc, char *parv[])
Hook *h;
for (h = Hooks[HOOKTYPE_PRE_LOCAL_JOIN]; h; h = h->next)
{
i = (*(h->func.intfunc))(client,channel,parv);
/* Note: this is just a hack not to break the ABI but still be
* able to fix https://bugs.unrealircd.org/view.php?id=5644
* In the future we should just drop the parv/parx argument
* and use key as an argument instead.
*/
char *parx[4];
parx[0] = NULL;
parx[1] = name;
parx[2] = key;
parx[3] = NULL;
i = (*(h->func.intfunc))(client,channel,parx);
if (i == HOOK_DENY || i == HOOK_ALLOW)
break;
}

View File

@ -45,6 +45,7 @@ struct LabeledResponseContext {
/* Forward declarations */
int lr_pre_command(Client *from, MessageTag *mtags, char *buf);
int lr_post_command(Client *from, MessageTag *mtags, char *buf);
int lr_close_connection(Client *client);
int lr_packet(Client *from, Client *to, Client *intended_to, char **msg, int *len);
void *_labeled_response_save_context(void);
void _labeled_response_set_context(void *ctx);
@ -94,6 +95,7 @@ MOD_INIT()
HookAdd(modinfo->handle, HOOKTYPE_PRE_COMMAND, 2000000000, lr_pre_command);
HookAdd(modinfo->handle, HOOKTYPE_POST_COMMAND, -2000000000, lr_post_command);
HookAdd(modinfo->handle, HOOKTYPE_CLOSE_CONNECTION, 2000000000, lr_close_connection);
HookAdd(modinfo->handle, HOOKTYPE_PACKET, 0, lr_packet);
return MOD_SUCCESS;
@ -179,11 +181,12 @@ int lr_post_command(Client *from, MessageTag *mtags, char *buf)
if (currentcmd.responses == 0)
{
/* Note: we blindly send recv_mtags back here,
* which is OK now, but may not be OK later.
*/
MessageTag *m = safe_alloc(sizeof(MessageTag));
safe_strdup(m->name, "label");
safe_strdup(m->value, currentcmd.label);
memset(&currentcmd, 0, sizeof(currentcmd));
sendto_one(from, mtags, ":%s ACK", me.name);
sendto_one(from, m, ":%s ACK", me.name);
free_message_tags(m);
goto done;
} else
if (currentcmd.responses == 1)
@ -219,6 +222,13 @@ done:
return 0;
}
int lr_close_connection(Client *client)
{
/* Flush all data before closing connection */
lr_post_command(client, NULL, NULL);
return 0;
}
/** Helper function for lr_packet() to skip the message tags prefix,
* and possibly @batch as well.
*/

View File

@ -34,7 +34,6 @@ ModuleHeader MOD_HEADER
long CAP_MESSAGE_TAGS = 0L;
char *_mtags_to_string(MessageTag *m, Client *client);
void _parse_message_tags(Client *client, char **str, MessageTag **mtag_list);
CMD_FUNC(cmd_tagmsg);
MOD_TEST()
{
@ -55,7 +54,6 @@ MOD_INIT()
memset(&cap, 0, sizeof(cap));
cap.name = "message-tags";
ClientCapabilityAdd(modinfo->handle, &cap, &CAP_MESSAGE_TAGS);
CommandAdd(modinfo->handle, "TAGMSG", cmd_tagmsg, 1, CMD_USER);
return MOD_SUCCESS;
}
@ -296,11 +294,3 @@ char *_mtags_to_string(MessageTag *m, Client *client)
return buf;
}
/* Dummy handler for TAGMSG.
* We do not permit user tags, so implementing a real TAGMSG makes no sense.
* By having a dummy command we avoid clients from getting "Unknown command".
*/
CMD_FUNC(cmd_tagmsg)
{
}

View File

@ -20,20 +20,19 @@
#include "unrealircd.h"
/* Forward declarations */
char *_StripColors(unsigned char *text);
char *_StripControlCodes(unsigned char *text);
int ban_version(Client *client, char *text);
CMD_FUNC(cmd_private);
CMD_FUNC(cmd_notice);
void cmd_message(Client *client, MessageTag *recv_mtags, int parc, char *parv[], int notice);
int _can_send_to_channel(Client *client, Channel *channel, char **msgtext, char **errmsg, int notice);
int can_send_to_user(Client *client, Client *target, char **msgtext, char **errmsg, int notice);
CMD_FUNC(cmd_tagmsg);
void cmd_message(Client *client, MessageTag *recv_mtags, int parc, char *parv[], SendType sendtype);
int _can_send_to_channel(Client *client, Channel *channel, char **msgtext, char **errmsg, SendType sendtype);
int can_send_to_user(Client *client, Client *target, char **msgtext, char **errmsg, SendType sendtype);
/* Place includes here */
#define MSG_PRIVATE "PRIVMSG" /* PRIV */
#define MSG_NOTICE "NOTICE" /* NOTI */
/* Variables */
long CAP_MESSAGE_TAGS = 0; /**< Looked up at MOD_LOAD, may stay 0 if message-tags support is absent */
ModuleHeader MOD_HEADER
= {
@ -56,8 +55,9 @@ MOD_TEST()
/* This is called on module init, before Server Ready */
MOD_INIT()
{
CommandAdd(modinfo->handle, MSG_PRIVATE, cmd_private, 2, CMD_USER|CMD_SERVER|CMD_RESETIDLE|CMD_VIRUS);
CommandAdd(modinfo->handle, MSG_NOTICE, cmd_notice, 2, CMD_USER|CMD_SERVER);
CommandAdd(modinfo->handle, "PRIVMSG", cmd_private, 2, CMD_USER|CMD_SERVER|CMD_RESETIDLE|CMD_VIRUS);
CommandAdd(modinfo->handle, "NOTICE", cmd_notice, 2, CMD_USER|CMD_SERVER);
CommandAdd(modinfo->handle, "TAGMSG", cmd_tagmsg, 1, CMD_USER|CMD_SERVER);
MARK_AS_OFFICIAL_MODULE(modinfo);
return MOD_SUCCESS;
}
@ -65,6 +65,8 @@ MOD_INIT()
/* Is first run when server is 100% ready */
MOD_LOAD()
{
CAP_MESSAGE_TAGS = ClientCapabilityBit("message-tags");
return MOD_SUCCESS;
}
@ -79,11 +81,11 @@ MOD_UNLOAD()
/** Check if PRIVMSG's are permitted from a person to another person.
* client: source client
* target: target client
* notice: 1 if notice, 0 if privmsg
* sendtype: One of SEND_TYPE_*
* text: Pointer to a pointer to a text [in, out]
* cmd: Pointer to a pointer which contains the command to use [in, out]
*/
int can_send_to_user(Client *client, Client *target, char **msgtext, char **errmsg, int notice)
int can_send_to_user(Client *client, Client *target, char **msgtext, char **errmsg, SendType sendtype)
{
int ret;
Hook *h;
@ -109,19 +111,19 @@ int can_send_to_user(Client *client, Client *target, char **msgtext, char **errm
if (is_silenced(client, target))
{
RunHook3(HOOKTYPE_SILENCED, client, target, notice);
RunHook3(HOOKTYPE_SILENCED, client, target, sendtype);
/* Silently discarded, no error message */
return 0;
}
// Possible FIXME: make match_spamfilter also use errmsg, or via a wrapper? or use same numeric?
if (MyUser(client) && match_spamfilter(client, *msgtext, (notice ? SPAMF_USERNOTICE : SPAMF_USERMSG), target->name, 0, NULL))
if (MyUser(client) && match_spamfilter(client, *msgtext, (sendtype == SEND_TYPE_NOTICE ? SPAMF_USERNOTICE : SPAMF_USERMSG), target->name, 0, NULL))
return 0;
n = HOOK_CONTINUE;
for (h = Hooks[HOOKTYPE_CAN_SEND_TO_USER]; h; h = h->next)
{
n = (*(h->func.intfunc))(client, target, msgtext, errmsg, notice);
n = (*(h->func.intfunc))(client, target, msgtext, errmsg, sendtype);
if (n == HOOK_DENY)
{
if (!*errmsg)
@ -132,13 +134,14 @@ int can_send_to_user(Client *client, Client *target, char **msgtext, char **errm
return 0;
}
if (!*msgtext || !**msgtext)
return 0;
{
if (sendtype != SEND_TYPE_TAGMSG)
return 0;
else
*msgtext = "";
}
}
/* This may happen, if nothing is left to send anymore (don't send empty messages) */
if (!*msgtext || !**msgtext)
return 0;
return 1;
}
@ -249,18 +252,19 @@ int can_send_to_prefix(Client *client, Channel *channel, int prefix)
return 1;
}
/*
** cmd_message (used in cmd_private() and cmd_notice())
** the general function to deliver MSG's between users/channels
**
** parv[1] = receiver list
** parv[2] = message text
**
** massive cleanup
** rev argv 6/91
**
*/
void cmd_message(Client *client, MessageTag *recv_mtags, int parc, char *parv[], int notice)
int has_client_mtags(MessageTag *mtags)
{
MessageTag *m;
for (m = mtags; m; m = m->next)
if (*m->name == '+')
return 1;
return 0;
}
/* General message handler to users and channels. Used by PRIVMSG, NOTICE, etc.
*/
void cmd_message(Client *client, MessageTag *recv_mtags, int parc, char *parv[], SendType sendtype)
{
Client *target;
Channel *channel;
@ -269,7 +273,7 @@ void cmd_message(Client *client, MessageTag *recv_mtags, int parc, char *parv[],
char pfixchan[CHANNELLEN + 4];
int ret;
int ntargets = 0;
char *cmd = notice ? "NOTICE" : "PRIVMSG";
char *cmd = sendtype_to_cmd(sendtype);
int maxtargets = max_targets_for_command(cmd);
Hook *h;
MessageTag *mtags;
@ -287,7 +291,7 @@ void cmd_message(Client *client, MessageTag *recv_mtags, int parc, char *parv[],
return;
}
if (parc < 3 || *parv[2] == '\0')
if ((sendtype != SEND_TYPE_TAGMSG) && (parc < 3 || *parv[2] == '\0'))
{
sendnumeric(client, ERR_NOTEXTTOSEND);
return;
@ -303,6 +307,7 @@ void cmd_message(Client *client, MessageTag *recv_mtags, int parc, char *parv[],
sendnumeric(client, ERR_TOOMANYTARGETS, targetstr, maxtargets, cmd);
break;
}
/* The nicks "ircd" and "irc" are special (and reserved) */
if (!strcasecmp(targetstr, "ircd") && MyUser(client))
return;
@ -352,7 +357,7 @@ void cmd_message(Client *client, MessageTag *recv_mtags, int parc, char *parv[],
errmsg = NULL;
if (MyUser(client) && !IsULine(client))
{
if (!can_send_to_channel(client, channel, &text, &errmsg, notice))
if (!can_send_to_channel(client, channel, &text, &errmsg, sendtype))
{
/* Send the error message, but only if:
* 1) The user has not been killed
@ -360,7 +365,7 @@ void cmd_message(Client *client, MessageTag *recv_mtags, int parc, char *parv[],
*/
if (IsDead(client))
return;
if (!IsDead(client) && !notice && errmsg)
if (!IsDead(client) && (sendtype != SEND_TYPE_NOTICE) && errmsg)
sendnumeric(client, ERR_CANNOTSENDTOCHAN, channel->chname, errmsg, p2);
continue; /* skip delivery to this target */
}
@ -374,12 +379,12 @@ void cmd_message(Client *client, MessageTag *recv_mtags, int parc, char *parv[],
if ((*parv[2] == '\001') && strncmp(&parv[2][1], "ACTION ", 7))
sendflags |= SKIP_CTCP;
if (MyUser(client) && match_spamfilter(client, text, notice ? SPAMF_CHANNOTICE : SPAMF_CHANMSG, channel->chname, 0, NULL))
if (MyUser(client) && match_spamfilter(client, text, (sendtype == SEND_TYPE_NOTICE ? SPAMF_CHANNOTICE : SPAMF_CHANMSG), channel->chname, 0, NULL))
return;
new_message(client, recv_mtags, &mtags);
RunHook5(HOOKTYPE_PRE_CHANMSG, client, channel, mtags, text, notice);
RunHook5(HOOKTYPE_PRE_CHANMSG, client, channel, mtags, text, sendtype);
if (!text)
{
@ -387,12 +392,31 @@ void cmd_message(Client *client, MessageTag *recv_mtags, int parc, char *parv[],
continue;
}
sendto_channel(channel, client, client->direction,
prefix, 0, sendflags, mtags,
notice ? ":%s NOTICE %s :%s" : ":%s PRIVMSG %s :%s",
client->name, targetstr, text);
if (sendtype != SEND_TYPE_TAGMSG)
{
/* PRIVMSG or NOTICE */
sendto_channel(channel, client, client->direction,
prefix, 0, sendflags, mtags,
":%s %s %s :%s",
client->name, cmd, targetstr, text);
} else {
/* TAGMSG:
* Only send if the message includes any user message tags
* and if the 'message-tags' module is loaded.
* Do not allow empty and useless TAGMSG.
*/
if (!CAP_MESSAGE_TAGS || !has_client_mtags(mtags))
{
free_message_tags(mtags);
continue;
}
sendto_channel(channel, client, client->direction,
prefix, CAP_MESSAGE_TAGS, sendflags, mtags,
":%s TAGMSG %s",
client->name, targetstr);
}
RunHook8(HOOKTYPE_CHANMSG, client, channel, sendflags, prefix, targetstr, mtags, text, notice);
RunHook8(HOOKTYPE_CHANMSG, client, channel, sendflags, prefix, targetstr, mtags, text, sendtype);
free_message_tags(mtags);
@ -436,12 +460,12 @@ void cmd_message(Client *client, MessageTag *recv_mtags, int parc, char *parv[],
{
char *errmsg = NULL;
text = parv[2];
if (!can_send_to_user(client, target, &text, &errmsg, notice))
if (!can_send_to_user(client, target, &text, &errmsg, sendtype))
{
/* Message is discarded */
if (IsDead(client))
return;
if (!notice && errmsg)
if ((sendtype != SEND_TYPE_NOTICE) && errmsg)
sendnumeric(client, ERR_CANTSENDTOUSER, target->name, errmsg);
} else
{
@ -449,23 +473,43 @@ void cmd_message(Client *client, MessageTag *recv_mtags, int parc, char *parv[],
MessageTag *mtags = NULL;
/* Inform sender that recipient is away, if this is so */
if (!notice && MyConnect(client) && target->user && target->user->away)
if ((sendtype == SEND_TYPE_PRIVMSG) && MyConnect(client) && target->user && target->user->away)
sendnumeric(client, RPL_AWAY, target->name, target->user->away);
new_message(client, recv_mtags, &mtags);
if ((sendtype == SEND_TYPE_TAGMSG) && !has_client_mtags(mtags))
{
free_message_tags(mtags);
continue;
}
labeled_response_inhibit = 1;
if (MyUser(target))
{
/* Deliver to end-user */
sendto_prefix_one(target, client, mtags, ":%s %s %s :%s",
client->name, cmd, target->name, text);
if (sendtype == SEND_TYPE_TAGMSG)
{
if (HasCapability(target, "message-tags"))
{
sendto_prefix_one(target, client, mtags, ":%s %s %s",
client->name, cmd, target->name);
}
} else {
sendto_prefix_one(target, client, mtags, ":%s %s %s :%s",
client->name, cmd, target->name, text);
}
} else {
/* Send to another server */
sendto_prefix_one(target, client, mtags, ":%s %s %s :%s",
client->id, cmd, target->id, text);
if (sendtype == SEND_TYPE_TAGMSG)
{
sendto_prefix_one(target, client, mtags, ":%s %s %s",
client->id, cmd, target->id);
} else {
sendto_prefix_one(target, client, mtags, ":%s %s %s :%s",
client->id, cmd, target->id, text);
}
}
labeled_response_inhibit = 0;
RunHook5(HOOKTYPE_USERMSG, client, target, mtags, text, notice);
RunHook5(HOOKTYPE_USERMSG, client, target, mtags, text, sendtype);
free_message_tags(mtags);
continue;
}
@ -496,7 +540,7 @@ void cmd_message(Client *client, MessageTag *recv_mtags, int parc, char *parv[],
*/
CMD_FUNC(cmd_private)
{
cmd_message(client, recv_mtags, parc, parv, 0);
cmd_message(client, recv_mtags, parc, parv, SEND_TYPE_PRIVMSG);
}
/*
@ -506,7 +550,19 @@ CMD_FUNC(cmd_private)
*/
CMD_FUNC(cmd_notice)
{
cmd_message(client, recv_mtags, parc, parv, 1);
cmd_message(client, recv_mtags, parc, parv, SEND_TYPE_NOTICE);
}
/*
** cmd_tagmsg
** parv[1] = receiver list
*/
CMD_FUNC(cmd_tagmsg)
{
/* compatibility hack */
parv[2] = "";
parv[3] = NULL;
cmd_message(client, recv_mtags, parc, parv, SEND_TYPE_TAGMSG);
}
/* Taken from xchat by Peter Zelezny
@ -707,13 +763,13 @@ int ban_version(Client *client, char *text)
/** Can user send a message to this channel?
* @param client The client
* @param channel The channel
* @param msgtext The message to send (MAY be changed, even if user is allowed to send)
* @param errmsg The error message (will be filled in)
* @param notice If it's a NOTICE then this is set to 1. Set to 0 for PRIVMSG.
* @param msgtext The message to send (MAY be changed, even if user is allowed to send)
* @param errmsg The error message (will be filled in)
* @param sendtype One of SEND_TYPE_*
* @returns Returns 1 if the user is allowed to send, otherwise 0.
* (note that this behavior was reversed in UnrealIRCd versions <5.x.
*/
int _can_send_to_channel(Client *client, Channel *channel, char **msgtext, char **errmsg, int notice)
int _can_send_to_channel(Client *client, Channel *channel, char **msgtext, char **errmsg, SendType sendtype)
{
Membership *lp;
int member, i = 0;
@ -769,7 +825,7 @@ int _can_send_to_channel(Client *client, Channel *channel, char **msgtext, char
/* Modules can plug in as well */
for (h = Hooks[HOOKTYPE_CAN_SEND_TO_CHANNEL]; h; h = h->next)
{
i = (*(h->func.intfunc))(client, channel, lp, msgtext, errmsg, notice);
i = (*(h->func.intfunc))(client, channel, lp, msgtext, errmsg, sendtype);
if (i != HOOK_CONTINUE)
{
if (!*errmsg)
@ -780,7 +836,12 @@ int _can_send_to_channel(Client *client, Channel *channel, char **msgtext, char
break;
}
if (!*msgtext || !**msgtext)
return 0;
{
if (sendtype != SEND_TYPE_TAGMSG)
return 0;
else
*msgtext = "";
}
}
if (i != HOOK_CONTINUE)
@ -794,9 +855,6 @@ int _can_send_to_channel(Client *client, Channel *channel, char **msgtext, char
*errmsg = NULL;
return 0;
}
if (!*msgtext || !**msgtext)
return 0;
/* Now we are going to check bans */

View File

@ -183,7 +183,8 @@ CMD_FUNC(cmd_names)
*/
for (; *s; s++)
buf[idx++] = *s;
buf[idx++] = ' ';
if (cm->next)
buf[idx++] = ' ';
buf[idx] = '\0';
flag = 1;
if (mlen + idx + bufLen > BUFSIZE - 7)

View File

@ -29,7 +29,7 @@ ModuleHeader MOD_HEADER
"unrealircd-5",
};
int nocodes_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice);
int nocodes_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
MOD_INIT()
{
@ -57,7 +57,7 @@ static int has_controlcodes(char *p)
return 0;
}
int nocodes_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice)
int nocodes_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
{
static char retbuf[4096];
Hook *h;

View File

@ -38,7 +38,6 @@ struct RestrictedCommand {
int exempt_identified;
int exempt_reputation_score;
int exempt_webirc;
int disable;
};
typedef struct {
@ -52,9 +51,9 @@ RestrictedCommand *find_restrictions_bycmd(char *cmd);
RestrictedCommand *find_restrictions_byconftag(char *conftag);
int rcmd_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
int rcmd_configrun(ConfigFile *cf, ConfigEntry *ce, int type);
int rcmd_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice);
int rcmd_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, int notice);
int rcmd_block_message(Client *client, char *text, int notice, char **errmsg, char *display, char *conftag);
int rcmd_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
int rcmd_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype);
int rcmd_block_message(Client *client, char *text, SendType sendtype, char **errmsg, char *display, char *conftag);
CMD_OVERRIDE_FUNC(rcmd_override);
// Globals
@ -145,12 +144,8 @@ RestrictedCommand *find_restrictions_byconftag(char *conftag) {
int rcmd_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
{
int errors = 0;
int warn_disable = 0;
ConfigEntry *cep, *cep2;
RestrictedCommand *rcmd;
long connect_delay;
int exempt_reputation_score;
int exempt_webirc;
int has_restriction;
// We are only interested in set::restrict-commands
if (type != CONFIG_SET)
@ -161,12 +156,18 @@ int rcmd_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
for (cep = ce->ce_entries; cep; cep = cep->ce_next)
{
has_restriction = 0;
for (cep2 = cep->ce_entries; cep2; cep2 = cep2->ce_next)
{
if (!strcmp(cep2->ce_varname, "disable"))
{
has_restriction = 1;
config_warn("%s:%i: set::restrict-commands::%s: the 'disable' option has been removed.",
cep2->ce_fileptr->cf_filename, cep2->ce_varlinenum, cep->ce_varname);
if (!warn_disable)
{
config_warn("Simply remove 'disable yes;' from the configuration file and "
"it will have the same effect without it (will disable the command).");
warn_disable = 1;
}
continue;
}
@ -179,9 +180,8 @@ int rcmd_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
if (!strcmp(cep2->ce_varname, "connect-delay"))
{
has_restriction = 1;
connect_delay = config_checkval(cep2->ce_vardata, CFG_TIME);
if (connect_delay < 10 || connect_delay > 3600)
long v = config_checkval(cep2->ce_vardata, CFG_TIME);
if ((v < 10) || (v > 3600))
{
config_error("%s:%i: set::restrict-commands::%s::connect-delay should be in range 10-3600", cep2->ce_fileptr->cf_filename, cep2->ce_varlinenum, cep->ce_varname);
errors++;
@ -197,8 +197,8 @@ int rcmd_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
if (!strcmp(cep2->ce_varname, "exempt-reputation-score"))
{
exempt_reputation_score = atoi(cep2->ce_vardata);
if (exempt_reputation_score <= 0)
int v = atoi(cep2->ce_vardata);
if (v <= 0)
{
config_error("%s:%i: set::restrict-commands::%s::exempt-reputation-score must be greater than 0", cep2->ce_fileptr->cf_filename, cep2->ce_varlinenum, cep->ce_varname);
errors++;
@ -209,12 +209,6 @@ int rcmd_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
config_error("%s:%i: unknown directive set::restrict-commands::%s::%s", cep2->ce_fileptr->cf_filename, cep2->ce_varlinenum, cep->ce_varname, cep2->ce_varname);
errors++;
}
if (!has_restriction)
{
config_error("%s:%i: no restrictions were set for set::restrict-commands::%s (either 'connect-delay' or 'disable' is required)", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
errors++;
}
}
*errs = errors;
@ -292,12 +286,6 @@ int rcmd_configrun(ConfigFile *cf, ConfigEntry *ce, int type)
rcmd->exempt_reputation_score = atoi(cep2->ce_vardata);
continue;
}
if (!strcmp(cep2->ce_varname, "disable"))
{
rcmd->disable = cep2->ce_vardata ? config_checkval(cep2->ce_vardata, CFG_YESNO) : 1;
break; // Using break instead of continue since 'disable' takes precedence anyways
}
}
AddListItem(rcmd, RestrictedCommandList);
}
@ -315,32 +303,32 @@ int rcmd_canbypass(Client *client, RestrictedCommand *rcmd)
return 1;
if (rcmd->exempt_reputation_score > 0 && (GetReputation(client) >= rcmd->exempt_reputation_score))
return 1;
if (client->local && (TStime() - client->local->firsttime < rcmd->connect_delay))
return 0;
return 1; // Default to yes so we don't drop too many commands
if (rcmd->connect_delay && client->local && (TStime() - client->local->firsttime >= rcmd->connect_delay))
return 1;
return 0;
}
int rcmd_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, int notice)
int rcmd_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
{
if (rcmd_block_message(client, *msg, notice, errmsg, "channel", (notice ? "channel-notice" : "channel-message")))
if (rcmd_block_message(client, *msg, sendtype, errmsg, "channel", (sendtype == SEND_TYPE_NOTICE ? "channel-notice" : "channel-message")))
return HOOK_DENY;
return HOOK_CONTINUE;
}
int rcmd_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, int notice)
int rcmd_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype)
{
// Need a few extra exceptions for user messages only =]
if ((client == target) || IsULine(target))
return HOOK_CONTINUE; /* bypass/exempt */
if (rcmd_block_message(client, *text, notice, errmsg, "user", (notice ? "private-notice" : "private-message")))
if (rcmd_block_message(client, *text, sendtype, errmsg, "user", (sendtype == SEND_TYPE_NOTICE ? "private-notice" : "private-message")))
return HOOK_DENY;
return HOOK_CONTINUE;
}
int rcmd_block_message(Client *client, char *text, int notice, char **errmsg, char *display, char *conftag)
int rcmd_block_message(Client *client, char *text, SendType sendtype, char **errmsg, char *display, char *conftag)
{
RestrictedCommand *rcmd;
static char errbuf[256];
@ -350,24 +338,21 @@ int rcmd_block_message(Client *client, char *text, int notice, char **errmsg, ch
return 0;
rcmd = find_restrictions_byconftag(conftag);
if (rcmd)
if (rcmd && !rcmd_canbypass(client, rcmd))
{
if (rcmd->disable)
int notice = (sendtype == SEND_TYPE_NOTICE ? 1 : 0); // temporary hack FIXME !!!
if (rcmd->connect_delay)
{
ircsnprintf(errbuf, sizeof(errbuf),
"Sending of %ss to %ss been disabled by the network administrators",
(notice ? "notice" : "message"), display);
*errmsg = errbuf;
return 1;
}
if (!rcmd_canbypass(client, rcmd))
{
"You cannot send %ss to %ss until you've been connected for %ld seconds or more",
(notice ? "notice" : "message"), display, rcmd->connect_delay);
} else {
ircsnprintf(errbuf, sizeof(errbuf),
"You cannot send %ss to %ss until you've been connected for %ld seconds or more",
(notice ? "notice" : "message"), display, rcmd->connect_delay);
*errmsg = errbuf;
return 1;
"Sending of %ss to %ss been disabled by the network administrators",
(notice ? "notice" : "message"), display);
}
*errmsg = errbuf;
return 1;
}
// No restrictions apply, process command as normal =]
@ -385,22 +370,19 @@ CMD_OVERRIDE_FUNC(rcmd_override)
}
rcmd = find_restrictions_bycmd(ovr->command->cmd);
if (rcmd)
if (rcmd && !rcmd_canbypass(client, rcmd))
{
if (rcmd->disable)
{
sendnumericfmt(client, ERR_UNKNOWNCOMMAND,
"%s :This command is disabled by the network administrator",
ovr->command->cmd);
return;
}
if (!rcmd_canbypass(client, rcmd))
if (rcmd->connect_delay)
{
sendnumericfmt(client, ERR_UNKNOWNCOMMAND,
"%s :You must be connected for at least %ld seconds before you can use this command",
ovr->command->cmd, rcmd->connect_delay);
return;
} else {
sendnumericfmt(client, ERR_UNKNOWNCOMMAND,
"%s :This command is disabled by the network administrator",
ovr->command->cmd);
}
return;
}
// No restrictions apply, process command as normal =]

View File

@ -275,12 +275,14 @@ CMD_FUNC(cmd_sajoin)
strlcat(jbuf, ",", sizeof jbuf);
strlcat(jbuf, name, sizeof jbuf);
}
if (did_anything)
{
if (!sjmode)
{
//sendnotice(target, "*** You were forced to join %s", jbuf);
sendto_umode_global(UMODE_OPER, "%s used SAJOIN to make %s join %s", client->name, target->name, jbuf);
/* Logging function added by XeRXeS */
ircd_log(LOG_SACMDS,"SAJOIN: %s used SAJOIN to make %s join %s",
client->name, target->name, jbuf);
}

View File

@ -161,7 +161,7 @@ CMD_FUNC(cmd_sapart)
parv[2] = comment ? commentx : NULL; // comment
if (comment)
{
//sendnotice(target, "*** You were forced to part %s (%s)", parv[1], commentx);
sendnotice(target, "*** You were forced to part %s (%s)", parv[1], commentx);
sendto_umode_global(UMODE_OPER, "%s used SAPART to make %s part %s (%s)",
client->name, target->name, parv[1], comment);
ircd_log(LOG_SACMDS,"SAPART: %s used SAPART to make %s part %s (%s)",
@ -169,7 +169,7 @@ CMD_FUNC(cmd_sapart)
}
else
{
//sendnotice(target, "*** You were forced to part %s", parv[1]);
sendnotice(target, "*** You were forced to part %s", parv[1]);
sendto_umode_global(UMODE_OPER, "%s used SAPART to make %s part %s",
client->name, target->name, parv[1]);
ircd_log(LOG_SACMDS,"SAPART: %s used SAPART to make %s part %s",

View File

@ -95,7 +95,7 @@ CMD_FUNC(cmd_svsnick)
/* no 'recv_mtags' here, we do not inherit from SVSNICK but generate a new NICK event */
new_message(acptr, NULL, &mtags);
sendto_local_common_channels(acptr, NULL, 0, mtags, ":%s NICK :%s", acptr->name, parv[2]);
sendto_local_common_channels(acptr, acptr, 0, mtags, ":%s NICK :%s", acptr->name, parv[2]);
sendto_one(acptr, mtags, ":%s NICK :%s", acptr->name, parv[2]);
sendto_server(NULL, 0, 0, mtags, ":%s NICK %s :%ld", acptr->id, parv[2], atol(parv[3]));
free_message_tags(mtags);

View File

@ -0,0 +1,315 @@
/* Target flood protection
* (C)Copyright 2020 Bram Matthys and the UnrealIRCd team
* License: GPLv2
*/
#include "unrealircd.h"
ModuleHeader MOD_HEADER
= {
"targetfloodprot",
"5.0",
"Target flood protection (set::anti-flood::target-flood)",
"UnrealIRCd Team",
"unrealircd-5",
};
#define TFP_PRIVMSG 0
#define TFP_NOTICE 1
#define TFP_TAGMSG 2
#define TFP_MAX 3
typedef struct TargetFlood TargetFlood;
struct TargetFlood {
unsigned short cnt[TFP_MAX];
time_t t[TFP_MAX];
};
typedef struct TargetFloodConfig TargetFloodConfig;
struct TargetFloodConfig {
int cnt[TFP_MAX];
int t[TFP_MAX];
};
/* Forward declarations */
int targetfloodprot_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
int targetfloodprot_config_run(ConfigFile *cf, ConfigEntry *ce, int type);
void targetfloodprot_mdata_free(ModData *m);
int targetfloodprot_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype);
int targetfloodprot_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype);
/* Global variables */
ModDataInfo *targetfloodprot_client_md = NULL;
ModDataInfo *targetfloodprot_channel_md = NULL;
TargetFloodConfig *channelcfg = NULL;
TargetFloodConfig *privatecfg = NULL;
MOD_TEST()
{
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, targetfloodprot_config_test);
return MOD_SUCCESS;
}
/** Allocate config and set default configuration */
void targetfloodprot_defaults(void)
{
channelcfg = safe_alloc(sizeof(TargetFloodConfig));
privatecfg = safe_alloc(sizeof(TargetFloodConfig));
/* set::anti-flood::target-flood::channel-privmsg */
channelcfg->cnt[TFP_PRIVMSG] = 45;
channelcfg->t[TFP_PRIVMSG] = 5;
/* set::anti-flood::target-flood::channel-notice */
channelcfg->cnt[TFP_NOTICE] = 15;
channelcfg->t[TFP_NOTICE] = 5;
/* set::anti-flood::target-flood::channel-tagmsg */
channelcfg->cnt[TFP_TAGMSG] = 15;
channelcfg->t[TFP_TAGMSG] = 5;
/* set::anti-flood::target-flood::private-privmsg */
privatecfg->cnt[TFP_PRIVMSG] = 30;
privatecfg->t[TFP_PRIVMSG] = 5;
/* set::anti-flood::target-flood::private-notice */
privatecfg->cnt[TFP_NOTICE] = 10;
privatecfg->t[TFP_NOTICE] = 5;
/* set::anti-flood::target-flood::private-tagmsg */
privatecfg->cnt[TFP_TAGMSG] = 10;
privatecfg->t[TFP_TAGMSG] = 5;
}
MOD_INIT()
{
ModDataInfo mreq;
MARK_AS_OFFICIAL_MODULE(modinfo);
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, targetfloodprot_config_run);
HookAdd(modinfo->handle, HOOKTYPE_CAN_SEND_TO_CHANNEL, 0, targetfloodprot_can_send_to_channel);
HookAdd(modinfo->handle, HOOKTYPE_CAN_SEND_TO_USER, 0, targetfloodprot_can_send_to_user);
memset(&mreq, 0, sizeof(mreq));
mreq.name = "targetfloodprot";
mreq.serialize = NULL;
mreq.unserialize = NULL;
mreq.free = targetfloodprot_mdata_free;
mreq.sync = 0;
mreq.type = MODDATATYPE_LOCAL_CLIENT;
targetfloodprot_client_md = ModDataAdd(modinfo->handle, mreq);
memset(&mreq, 0, sizeof(mreq));
mreq.name = "targetfloodprot";
mreq.serialize = NULL;
mreq.unserialize = NULL;
mreq.free = targetfloodprot_mdata_free;
mreq.sync = 0;
mreq.type = MODDATATYPE_CHANNEL;
targetfloodprot_channel_md = ModDataAdd(modinfo->handle, mreq);
targetfloodprot_defaults();
return MOD_SUCCESS;
}
MOD_LOAD()
{
return MOD_SUCCESS;
}
MOD_UNLOAD()
{
return MOD_SUCCESS;
}
#ifndef CheckNull
#define CheckNull(x) if ((!(x)->ce_vardata) || (!(*((x)->ce_vardata)))) { config_error("%s:%i: missing parameter", (x)->ce_fileptr->cf_filename, (x)->ce_varlinenum); errors++; continue; }
#endif
int targetfloodprot_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
{
int errors = 0;
ConfigEntry *cep;
if (type != CONFIG_SET_ANTI_FLOOD)
return 0;
/* We are only interrested in set::anti-flood::target-flood.. */
if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "target-flood"))
return 0;
for (cep = ce->ce_entries; cep; cep = cep->ce_next)
{
CheckNull(cep);
if (!strcmp(cep->ce_varname, "channel-privmsg") ||
!strcmp(cep->ce_varname, "channel-notice") ||
!strcmp(cep->ce_varname, "channel-tagmsg") ||
!strcmp(cep->ce_varname, "private-privmsg") ||
!strcmp(cep->ce_varname, "private-notice") ||
!strcmp(cep->ce_varname, "private-tagmsg"))
{
int cnt = 0, period = 0;
if (!config_parse_flood(cep->ce_vardata, &cnt, &period) ||
(cnt < 1) || (cnt > 10000) || (period < 1) || (period > 120))
{
config_error("%s:%i: set::anti-flood::target-flood::%s error. "
"Syntax is '<count>:<period>' (eg 5:60). "
"Count must be 1-10000 and period must be 1-120.",
cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
cep->ce_varname);
errors++;
}
} else
{
config_error("%s:%i: unknown directive set::anti-flood::target-flood:%s",
cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
errors++;
continue;
}
}
*errs = errors;
return errors ? -1 : 1;
}
int targetfloodprot_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
{
ConfigEntry *cep, *cepp;
if (type != CONFIG_SET_ANTI_FLOOD)
return 0;
/* We are only interrested in set::anti-flood::target-flood.. */
if (!ce || !ce->ce_varname || strcmp(ce->ce_varname, "target-flood"))
return 0;
for (cep = ce->ce_entries; cep; cep = cep->ce_next)
{
if (!strcmp(cep->ce_varname, "channel-privmsg"))
config_parse_flood(cep->ce_vardata, &channelcfg->cnt[TFP_PRIVMSG], &channelcfg->t[TFP_PRIVMSG]);
else if (!strcmp(cep->ce_varname, "channel-notice"))
config_parse_flood(cep->ce_vardata, &channelcfg->cnt[TFP_NOTICE], &channelcfg->t[TFP_NOTICE]);
else if (!strcmp(cep->ce_varname, "channel-tagmsg"))
config_parse_flood(cep->ce_vardata, &channelcfg->cnt[TFP_TAGMSG], &channelcfg->t[TFP_TAGMSG]);
else if (!strcmp(cep->ce_varname, "private-privmsg"))
config_parse_flood(cep->ce_vardata, &privatecfg->cnt[TFP_PRIVMSG], &privatecfg->t[TFP_PRIVMSG]);
else if (!strcmp(cep->ce_varname, "private-notice"))
config_parse_flood(cep->ce_vardata, &privatecfg->cnt[TFP_NOTICE], &privatecfg->t[TFP_NOTICE]);
else if (!strcmp(cep->ce_varname, "private-tagmsg"))
config_parse_flood(cep->ce_vardata, &privatecfg->cnt[TFP_TAGMSG], &privatecfg->t[TFP_TAGMSG]);
}
return 1;
}
/** UnrealIRCd internals: free object. */
void targetfloodprot_mdata_free(ModData *m)
{
/* we don't have any members to free, so this is easy */
safe_free(m->ptr);
}
int sendtypetowhat(SendType sendtype)
{
if (sendtype == SEND_TYPE_PRIVMSG)
return 0;
if (sendtype == SEND_TYPE_NOTICE)
return 1;
if (sendtype == SEND_TYPE_TAGMSG)
return 2;
#ifdef DEBUGMODE
ircd_log(LOG_ERROR, "sendtypetowhat() for unknown value %d", (int)sendtype);
abort();
#endif
return 0; /* otherwise, default to privmsg i guess */
}
int targetfloodprot_can_send_to_channel(Client *client, Channel *channel, Membership *lp, char **msg, char **errmsg, SendType sendtype)
{
TargetFlood *flood;
static char errbuf[256];
int what;
/* This is redundant, right? */
if (!MyUser(client))
return HOOK_CONTINUE;
/* Really, only IRCOps override */
if (IsOper(client) && ValidatePermissionsForPath("immune:target-flood",client,NULL,channel,NULL))
return HOOK_CONTINUE;
what = sendtypetowhat(sendtype);
if (moddata_channel(channel, targetfloodprot_channel_md).ptr == NULL)
{
/* Alloc a new entry if it doesn't exist yet */
moddata_channel(channel, targetfloodprot_channel_md).ptr = safe_alloc(sizeof(TargetFlood));
}
flood = (TargetFlood *)moddata_channel(channel, targetfloodprot_channel_md).ptr;
if ((TStime() - flood->t[what]) >= channelcfg->t[what])
{
/* Reset due to moving into a new time slot */
flood->t[what] = TStime();
flood->cnt[what] = 1;
return HOOK_CONTINUE; /* forget about it.. */
}
if (flood->cnt[what] >= channelcfg->cnt[what])
{
/* Flood detected */
snprintf(errbuf, sizeof(errbuf), "Channel is being flooded. Message not delivered.");
*errmsg = errbuf;
return HOOK_DENY;
}
flood->cnt[what]++;
return HOOK_CONTINUE;
}
int targetfloodprot_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype)
{
TargetFlood *flood;
static char errbuf[256];
int what;
/* Check if it is our TARGET ('target'), so yeah
* be aware that 'client' may be remote client in all the code that follows!
*/
if (!MyUser(target))
return HOOK_CONTINUE;
/* Really, only IRCOps override */
if (IsOper(client) && ValidatePermissionsForPath("immune:target-flood",client,target,NULL,NULL))
return HOOK_CONTINUE;
what = sendtypetowhat(sendtype);
if (moddata_local_client(target, targetfloodprot_client_md).ptr == NULL)
{
/* Alloc a new entry if it doesn't exist yet */
moddata_local_client(target, targetfloodprot_client_md).ptr = safe_alloc(sizeof(TargetFlood));
}
flood = (TargetFlood *)moddata_local_client(target, targetfloodprot_client_md).ptr;
if ((TStime() - flood->t[what]) >= privatecfg->t[what])
{
/* Reset due to moving into a new time slot */
flood->t[what] = TStime();
flood->cnt[what] = 1;
return HOOK_CONTINUE; /* forget about it.. */
}
if (flood->cnt[what] >= privatecfg->cnt[what])
{
/* Flood detected */
snprintf(errbuf, sizeof(errbuf), "User is being flooded. Message not delivered.");
*errmsg = errbuf;
return HOOK_DENY;
}
flood->cnt[what]++;
return HOOK_CONTINUE;
}

View File

@ -115,6 +115,7 @@ struct TKLTypeTable
* IMPORTANT IF YOU ARE ADDING A NEW TYPE TO THIS TABLE:
* - also update eline_syntax()
* - also check if eline_type_requires_ip() needs to be updated
* - update help.conf (HELPOP ELINE)
* - more?
*/
TKLTypeTable tkl_types[] = {
@ -868,7 +869,7 @@ int tkl_config_run_except(ConfigFile *cf, ConfigEntry *ce, int configtype)
{
/* Default setting if no 'type' is specified: */
if (!strcmp(ce->ce_vardata, "ban"))
strlcpy(bantypes, "kgzZs", sizeof(bantypes));
strlcpy(bantypes, "kGzZs", sizeof(bantypes));
else if (!strcmp(ce->ce_vardata, "throttle"))
strlcpy(bantypes, "c", sizeof(bantypes));
else if (!strcmp(ce->ce_vardata, "blacklist"))
@ -1208,6 +1209,22 @@ int ban_too_broad(char *usermask, char *hostmask)
return 1;
}
/** Ugly function, only meant to be called by cmd_tkl_line() */
static int xline_exists(char *type, char *usermask, char *hostmask)
{
char *umask = usermask;
int softban = 0;
int tpe = tkl_chartotype(type[0]);
if (*umask == '%')
{
umask++;
softban = 1;
}
return find_tkl_serverban(tpe, umask, hostmask, softban) ? 1 : 0;
}
/** Intermediate layer between user functions such as KLINE/GLINE
* and the TKL layer (cmd_tkl).
* This allows us doing some syntax checking and other helpful
@ -1434,6 +1451,13 @@ void cmd_tkl_line(Client *client, int parc, char *parv[], char *type)
return;
}
/* Some stupid checking */
if (xline_exists(type, usermask, hostmask))
{
sendnotice(client, "ERROR: Ban for %s@%s already exists.", usermask, hostmask);
return;
}
/* call the tkl layer .. */
cmd_tkl(&me, NULL, 9, tkllayer);
}

View File

@ -402,9 +402,10 @@ int read_tkldb(void)
FILE *fd;
TKL *tkl = NULL;
uint32_t magic = 0;
uint32_t version;
uint64_t cnt;
uint64_t tklcount = 0;
uint32_t version;
uint64_t v;
int added_cnt = 0;
char c;
char *str;
@ -483,8 +484,10 @@ int read_tkldb(void)
/* Read the common types (same for all TKLs) */
R_SAFE(read_str(fd, &tkl->set_by));
R_SAFE(read_int64(fd, &tkl->set_at));
R_SAFE(read_int64(fd, &tkl->expire_at));
R_SAFE(read_int64(fd, &v));
tkl->set_at = v;
R_SAFE(read_int64(fd, &v));
tkl->expire_at = v;
/* Save some CPU... if it's already expired then don't bother adding */
if (tkl->expire_at != 0 && tkl->expire_at <= TStime())
@ -645,7 +648,8 @@ int read_tkldb(void)
}
R_SAFE(read_str(fd, &tkl->ptr.spamfilter->tkl_reason));
R_SAFE(read_int64(fd, &tkl->ptr.spamfilter->tkl_duration));
R_SAFE(read_int64(fd, &v));
tkl->ptr.spamfilter->tkl_duration = v;
if (find_tkl_spamfilter(tkl->type, tkl->ptr.spamfilter->match->str,
tkl->ptr.spamfilter->action,

View File

@ -0,0 +1,105 @@
/*
* IRC - Internet Relay Chat, src/modules/typing-indicator.c
* (C) 2020 Syzop & The UnrealIRCd Team
*
* See file AUTHORS in IRC package for additional names of
* the programmers.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "unrealircd.h"
ModuleHeader MOD_HEADER
= {
"typing-indicator",
"5.0",
"+typing client tag",
"UnrealIRCd Team",
"unrealircd-5",
};
int ti_mtag_is_ok(Client *client, char *name, char *value);
void mtag_add_ti(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, char *signature);
MOD_INIT()
{
MessageTagHandlerInfo mtag;
MARK_AS_OFFICIAL_MODULE(modinfo);
memset(&mtag, 0, sizeof(mtag));
mtag.name = "+typing";
mtag.is_ok = ti_mtag_is_ok;
mtag.flags = MTAG_HANDLER_FLAGS_NO_CAP_NEEDED;
MessageTagHandlerAdd(modinfo->handle, &mtag);
memset(&mtag, 0, sizeof(mtag));
mtag.name = "+draft/typing";
mtag.is_ok = ti_mtag_is_ok;
mtag.flags = MTAG_HANDLER_FLAGS_NO_CAP_NEEDED;
MessageTagHandlerAdd(modinfo->handle, &mtag);
HookAddVoid(modinfo->handle, HOOKTYPE_NEW_MESSAGE, 0, mtag_add_ti);
return MOD_SUCCESS;
}
MOD_LOAD()
{
return MOD_SUCCESS;
}
MOD_UNLOAD()
{
return MOD_SUCCESS;
}
/** This function verifies if the client sending the mtag is permitted to do so.
*/
int ti_mtag_is_ok(Client *client, char *name, char *value)
{
/* Require a non-empty parameter */
if (BadPtr(value))
return 0;
/* These are the only valid values: */
if (!strcmp(value, "active") || !strcmp(value, "paused") || !strcmp(value, "done"))
return 1;
/* All the rest is considered illegal */
return 0;
}
void mtag_add_ti(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, char *signature)
{
MessageTag *m;
if (IsUser(client))
{
m = find_mtag(recv_mtags, "+typing");
if (m)
{
m = duplicate_mtag(m);
AddListItem(m, *mtag_list);
}
m = find_mtag(recv_mtags, "+draft/typing");
if (m)
{
m = duplicate_mtag(m);
AddListItem(m, *mtag_list);
}
}
}

View File

@ -20,7 +20,7 @@ long UMODE_CENSOR = 0L;
#define IsCensored(x) (x->umodes & UMODE_CENSOR)
int censor_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, int notice);
int censor_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype);
int censor_config_test(ConfigFile *, ConfigEntry *, int, int *);
int censor_config_run(ConfigFile *, ConfigEntry *, int);
@ -237,7 +237,7 @@ char *stripbadwords_message(char *str, int *blocked)
return stripbadwords(str, conf_badword_message, blocked);
}
int censor_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, int notice)
int censor_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype)
{
int blocked = 0;

View File

@ -34,7 +34,7 @@ long UMODE_NOCTCP = 0L;
#define IsNoCTCP(client) (client->umodes & UMODE_NOCTCP)
int noctcp_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, int notice);
int noctcp_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype);
MOD_TEST()
{
@ -74,9 +74,10 @@ static int IsACTCP(char *s)
return 0;
}
int noctcp_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, int notice)
int noctcp_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype)
{
if (MyUser(client) && !notice && IsNoCTCP(target) && !IsOper(client) && IsACTCP(*text))
if (MyUser(client) && (sendtype == SEND_TYPE_PRIVMSG) &&
IsNoCTCP(target) && !IsOper(client) && IsACTCP(*text))
{
*errmsg = "User does not accept CTCPs";
return HOOK_DENY;

View File

@ -17,7 +17,7 @@ ModuleHeader MOD_HEADER
static long UMODE_PRIVDEAF = 0;
static Umode *UmodePrivdeaf = NULL;
int privdeaf_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, int notice);
int privdeaf_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype);
MOD_INIT()
{
@ -47,7 +47,7 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
int privdeaf_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, int notice)
int privdeaf_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype)
{
if ((target->umodes & UMODE_PRIVDEAF) && !IsOper(client) &&
!IsULine(client) && !IsServer(client) && (client != target))

View File

@ -35,7 +35,7 @@ ModuleHeader MOD_HEADER
long UMODE_REGONLYMSG = 0L;
/* Forward declarations */
int regonlymsg_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, int notice);
int regonlymsg_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype);
MOD_INIT()
{
@ -57,7 +57,7 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
int regonlymsg_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, int notice)
int regonlymsg_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype)
{
if (IsRegOnlyMsg(target) && !IsServer(client) && !IsULine(client) && !IsLoggedIn(client))
{

View File

@ -36,7 +36,7 @@ ModuleHeader MOD_HEADER
long UMODE_SECUREONLYMSG = 0L;
/* Forward declarations */
int secureonlymsg_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, int notice);
int secureonlymsg_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype);
MOD_INIT()
{
@ -58,7 +58,7 @@ MOD_UNLOAD()
return MOD_SUCCESS;
}
int secureonlymsg_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, int notice)
int secureonlymsg_can_send_to_user(Client *client, Client *target, char **text, char **errmsg, SendType sendtype)
{
if (IsSecureOnlyMsg(target) && !IsServer(client) && !IsULine(client) && !IsSecureConnect(client))
{

View File

@ -560,7 +560,7 @@ static void who_common_channel(Client *client, Channel *channel,
static void who_global(Client *client, char *mask, int operspy, struct who_format *fmt)
{
Client *acptr;
int maxmatches = WHOLIMIT ? WHOLIMIT : 100;
int maxmatches = IsOper(client) ? INT_MAX : WHOLIMIT;
/* first, list all matching INvisible clients on common channels
* if this is not an operspy who

View File

@ -422,7 +422,7 @@ void sendto_channel(Channel *channel, Client *from, Client *skip,
continue;
good:
/* Now deal with 'clicap' (if non-zero) */
if (clicap && MyUser(acptr) && !HasCapabilityFast(acptr, clicap))
if (clicap && MyUser(acptr) && ((clicap & CAP_INVERT) ? HasCapabilityFast(acptr, clicap) : !HasCapabilityFast(acptr, clicap)))
continue;
if (MyUser(acptr))
@ -558,7 +558,7 @@ void sendto_local_common_channels(Client *user, Client *skip, long clicap, Messa
if (acptr->local->serial == current_serial)
continue; /* message already sent to this client */
if (clicap && !HasCapabilityFast(acptr, clicap))
if (clicap && ((clicap & CAP_INVERT) ? HasCapabilityFast(acptr, clicap) : !HasCapabilityFast(acptr, clicap)))
continue; /* client does not have the specified capability */
if (acptr == skip)

View File

@ -616,6 +616,7 @@ void completed_connection(int fd, int revents, void *data)
*/
void close_connection(Client *client)
{
RunHook(HOOKTYPE_CLOSE_CONNECTION, client);
/* This function must make MyConnect(client) == FALSE,
* and set client->direction == NULL.
*/

View File

@ -124,7 +124,7 @@ long set_usermode(char *umode)
/** Convert a target pointer to an 8 bit hash, used for target limiting. */
unsigned char hash_target(void *target)
{
unsigned long long v = (unsigned long long)target;
uintptr_t v = (uintptr_t)target;
/* ircu does >> 16 and 8 but since our sizeof(Client) is
* towards 512 (and hence the alignment), that bit is useless.
* So we do >> 17 and 9.
@ -552,6 +552,7 @@ void set_targmax_defaults(void)
/* Set the defaults */
setmaxtargets("PRIVMSG", 4);
setmaxtargets("NOTICE", 1);
setmaxtargets("TAGMSG", 1);
setmaxtargets("NAMES", 1); // >1 is not supported
setmaxtargets("WHOIS", 1);
setmaxtargets("WHOWAS", 1); // >1 is not supported

View File

@ -4,7 +4,7 @@ echo "Extracting src/version.c..."
#id=`grep '$Id: Changes,v' ../Changes`
#id=`echo $id |sed 's/.* Changes\,v \(.*\) .* Exp .*/\1/'`
id="5.0.4"
id="5.0.5"
echo "$id"
if test -r version.c

View File

@ -3,7 +3,7 @@
<assemblyIdentity
processorArchitecture="amd64"
name="UnrealIRCd.UnrealIRCd.5"
version="5.0.4.0"
version="5.0.5.0"
type="win32"
/>
<description>Internet Relay Chat Daemon</description>

View File

@ -6,7 +6,7 @@
[Setup]
AppName=UnrealIRCd 5
AppVerName=UnrealIRCd 5.0.4
AppVerName=UnrealIRCd 5.0.5
AppPublisher=UnrealIRCd Team
AppPublisherURL=https://www.unrealircd.org
AppSupportURL=https://www.unrealircd.org