mirror of
git://git.acid.vegas/unrealircd.git
synced 2024-12-25 15:56:38 +00:00
Updated to 5.0.8
This commit is contained in:
parent
b351238d42
commit
88a904d7f7
510
Config
510
Config
@ -104,49 +104,59 @@ fi
|
||||
echo $CONF
|
||||
$CONF || exit 1
|
||||
cd "$UNREALCWD"
|
||||
if [ "$QUICK" != "1" ] ; then
|
||||
if [ ! -f $CONFDIR/tls/server.cert.pem -a ! -f $CONFDIR/ssl/server.cert.pem ]; then
|
||||
export OPENSSLPATH
|
||||
TEST=""
|
||||
while [ -z "$TEST" ] ; do
|
||||
if [ "$GENCERTIFICATE" = "1" ] ; then
|
||||
TEST="Yes"
|
||||
else
|
||||
TEST="No"
|
||||
fi
|
||||
echo ""
|
||||
echo "Do you want to generate an SSL certificate for the IRCd?"
|
||||
echo "Only answer No if you already have one."
|
||||
echo $n "[$TEST] -> $c"
|
||||
read cc
|
||||
if [ -z "$cc" ] ; then
|
||||
cc=$TEST
|
||||
fi
|
||||
case "$cc" in
|
||||
[Yy]*)
|
||||
GENCERTIFICATE="1"
|
||||
;;
|
||||
[Nn]*)
|
||||
GENCERTIFICATE=""
|
||||
;;
|
||||
*)
|
||||
echo ""
|
||||
echo "You must enter either Yes or No"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if [ "$GENCERTIFICATE" = 1 ]; then
|
||||
make pem
|
||||
echo "Certificate created successfully."
|
||||
sleep 1
|
||||
else
|
||||
echo "Ok, not generating SSL certificate. Make sure that the certificate and key"
|
||||
echo "are installed in conf/tls/server.crt.pem and conf/tls/server.key.pem prior to starting the IRCd."
|
||||
fi
|
||||
else
|
||||
echo "SSL certificate already exists in configuration directory, no need to regenerate."
|
||||
fi
|
||||
|
||||
if [ "$QUICK" != "1" ] ; then
|
||||
if [ ! -f $CONFDIR/tls/server.cert.pem -a ! -f $CONFDIR/ssl/server.cert.pem ]; then
|
||||
export OPENSSLPATH
|
||||
TEST=""
|
||||
while [ -z "$TEST" ] ; do
|
||||
if [ "$GENCERTIFICATE" = "1" ] ; then
|
||||
TEST="Yes"
|
||||
else
|
||||
TEST="No"
|
||||
fi
|
||||
echo ""
|
||||
echo "UnrealIRCd requires an SSL certificate in order to work."
|
||||
echo "Do you want to generate an SSL certificate for the IRCd?"
|
||||
echo "Only answer No if you already have one."
|
||||
echo $n "[$TEST] -> $c"
|
||||
read cc
|
||||
if [ -z "$cc" ] ; then
|
||||
cc=$TEST
|
||||
fi
|
||||
case "$cc" in
|
||||
[Yy]*)
|
||||
GENCERTIFICATE="1"
|
||||
;;
|
||||
[Nn]*)
|
||||
GENCERTIFICATE=""
|
||||
;;
|
||||
*)
|
||||
echo ""
|
||||
echo "You must enter either Yes or No"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if [ "$GENCERTIFICATE" = 1 ]; then
|
||||
echo
|
||||
echo "*******************************************************************************"
|
||||
echo "Next you will be asked some questions in order to generate the SSL certificate."
|
||||
echo "IMPORTANT: If you don't own a domain or don't know what to answer, then you can"
|
||||
echo " simply press ENTER or use fictional names for each question!"
|
||||
echo "*******************************************************************************"
|
||||
echo "Press ENTER to continue"
|
||||
read cc
|
||||
make pem
|
||||
echo "Certificate created successfully."
|
||||
sleep 1
|
||||
else
|
||||
echo "Ok, not generating SSL certificate. Make sure that the certificate and key"
|
||||
echo "are installed in conf/tls/server.cert.pem and conf/tls/server.key.pem prior to starting the IRCd."
|
||||
fi
|
||||
else
|
||||
echo "SSL certificate already exists in configuration directory, no need to regenerate."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Silently force a 'make clean' as otherwise part (or whole) of the
|
||||
@ -158,89 +168,89 @@ make clean 1>/dev/null 2>&1
|
||||
RUN_ADVANCED () {
|
||||
TEST=""
|
||||
while [ -z "$TEST" ] ; do
|
||||
if [ "$SHOWLISTMODES" = "1" ] ; then
|
||||
TEST="Yes"
|
||||
else
|
||||
TEST="No"
|
||||
fi
|
||||
echo ""
|
||||
echo "Do you want to show the modes a channel has set in the /list output?"
|
||||
echo $n "[$TEST] -> $c"
|
||||
if [ "$SHOWLISTMODES" = "1" ] ; then
|
||||
TEST="Yes"
|
||||
else
|
||||
TEST="No"
|
||||
fi
|
||||
echo ""
|
||||
echo "Do you want to show the modes a channel has set in the /list output?"
|
||||
echo $n "[$TEST] -> $c"
|
||||
read cc
|
||||
if [ -z "$cc" ] ; then
|
||||
cc=$TEST
|
||||
fi
|
||||
case "$cc" in
|
||||
if [ -z "$cc" ] ; then
|
||||
cc=$TEST
|
||||
fi
|
||||
case "$cc" in
|
||||
[Yy]*)
|
||||
SHOWLISTMODES="1"
|
||||
;;
|
||||
SHOWLISTMODES="1"
|
||||
;;
|
||||
[Nn]*)
|
||||
SHOWLISTMODES=""
|
||||
;;
|
||||
SHOWLISTMODES=""
|
||||
;;
|
||||
*)
|
||||
echo ""
|
||||
echo "You must enter either Yes or No"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
echo ""
|
||||
echo "You must enter either Yes or No"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
TEST=""
|
||||
while [ -z "$TEST" ] ; do
|
||||
if [ "$NOOPEROVERRIDE" = "1" ] ; then
|
||||
TEST="Yes"
|
||||
else
|
||||
TEST="No"
|
||||
fi
|
||||
echo ""
|
||||
echo "Do you want to disable oper override?"
|
||||
echo $n "[$TEST] -> $c"
|
||||
if [ "$NOOPEROVERRIDE" = "1" ] ; then
|
||||
TEST="Yes"
|
||||
else
|
||||
TEST="No"
|
||||
fi
|
||||
echo ""
|
||||
echo "Do you want to disable oper override?"
|
||||
echo $n "[$TEST] -> $c"
|
||||
read cc
|
||||
if [ -z "$cc" ] ; then
|
||||
cc=$TEST
|
||||
fi
|
||||
case "$cc" in
|
||||
if [ -z "$cc" ] ; then
|
||||
cc=$TEST
|
||||
fi
|
||||
case "$cc" in
|
||||
[Yy]*)
|
||||
NOOPEROVERRIDE="1"
|
||||
;;
|
||||
NOOPEROVERRIDE="1"
|
||||
;;
|
||||
[Nn]*)
|
||||
NOOPEROVERRIDE=""
|
||||
;;
|
||||
NOOPEROVERRIDE=""
|
||||
;;
|
||||
*)
|
||||
echo ""
|
||||
echo "You must enter either Yes or No"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
echo ""
|
||||
echo "You must enter either Yes or No"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
TEST=""
|
||||
while [ -z "$TEST" ] ; do
|
||||
if [ "$OPEROVERRIDEVERIFY" = "1" ] ; then
|
||||
TEST="Yes"
|
||||
else
|
||||
TEST="No"
|
||||
fi
|
||||
echo ""
|
||||
echo "Do you want to require opers to /invite themselves into a +s or +p channel?"
|
||||
echo $n "[$TEST] -> $c"
|
||||
if [ "$OPEROVERRIDEVERIFY" = "1" ] ; then
|
||||
TEST="Yes"
|
||||
else
|
||||
TEST="No"
|
||||
fi
|
||||
echo ""
|
||||
echo "Do you want to require opers to /invite themselves into a +s or +p channel?"
|
||||
echo $n "[$TEST] -> $c"
|
||||
read cc
|
||||
if [ -z "$cc" ] ; then
|
||||
cc=$TEST
|
||||
fi
|
||||
case "$cc" in
|
||||
if [ -z "$cc" ] ; then
|
||||
cc=$TEST
|
||||
fi
|
||||
case "$cc" in
|
||||
[Yy]*)
|
||||
OPEROVERRIDEVERIFY="1"
|
||||
;;
|
||||
OPEROVERRIDEVERIFY="1"
|
||||
;;
|
||||
[Nn]*)
|
||||
OPEROVERRIDEVERIFY=""
|
||||
;;
|
||||
OPEROVERRIDEVERIFY=""
|
||||
;;
|
||||
*)
|
||||
echo ""
|
||||
echo "You must enter either Yes or No"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
echo ""
|
||||
echo "You must enter either Yes or No"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
}
|
||||
@ -250,7 +260,7 @@ UNREALCWD="`pwd`"
|
||||
BASEPATH="$HOME/unrealircd"
|
||||
DEFPERM="0600"
|
||||
SSLDIR=""
|
||||
NICKNAMEHISTORYLENGTH="100"
|
||||
NICKNAMEHISTORYLENGTH="2000"
|
||||
MAXCONNECTIONS_REQUEST="auto"
|
||||
REMOTEINC="1"
|
||||
CURLDIR=""
|
||||
@ -261,9 +271,9 @@ OPEROVERRIDEVERIFY=""
|
||||
GENCERTIFICATE="1"
|
||||
EXTRAPARA=""
|
||||
if [ "`eval echo -n 'a'`" = "-n a" ] ; then
|
||||
c="\c"
|
||||
c="\c"
|
||||
else
|
||||
n="-n"
|
||||
n="-n"
|
||||
fi
|
||||
|
||||
|
||||
@ -314,19 +324,19 @@ fi
|
||||
|
||||
clear
|
||||
|
||||
if [ -f "doc/Config.header" -a -z "$NOINTRO" ] ; then
|
||||
more doc/Config.header
|
||||
echo ""
|
||||
echo $n "[Press Enter to continue]"
|
||||
read cc
|
||||
clear
|
||||
fi
|
||||
if [ -f "doc/Config.header" -a -z "$NOINTRO" ] ; then
|
||||
more doc/Config.header
|
||||
echo ""
|
||||
echo $n "[Press Enter to continue]"
|
||||
read cc
|
||||
clear
|
||||
fi
|
||||
|
||||
echo "We will now ask you a number of questions. You can just press ENTER to accept the defaults!"
|
||||
echo ""
|
||||
|
||||
# This needs to be updated each release so auto-upgrading works for settings, modules, etc!!:
|
||||
UNREALRELEASES="unrealircd-5.0.7-rc1 unrealircd-5.0.6 unrealircd-5.0.5.1 unrealircd-5.0.5 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"
|
||||
UNREALRELEASES="unrealircd-5.0.8-rc1 unrealircd-5.0.7 unrealircd-5.0.7-rc1 unrealircd-5.0.6 unrealircd-5.0.5.1 unrealircd-5.0.5 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"
|
||||
if [ -f "config.settings" ]; then
|
||||
. ./config.settings
|
||||
else
|
||||
@ -405,9 +415,9 @@ echo " If this directory does not exist it will be created.)"
|
||||
echo $n "[$TEST] -> $c"
|
||||
read cc
|
||||
if [ -z "$cc" ] ; then
|
||||
BASEPATH=$TEST
|
||||
BASEPATH=$TEST
|
||||
else
|
||||
BASEPATH=`eval echo $cc` # modified
|
||||
BASEPATH=`eval echo $cc` # modified
|
||||
fi
|
||||
if [ "$BASEPATH" = "$UNREALCWD" ]; then
|
||||
echo ""
|
||||
@ -431,32 +441,28 @@ PRIVATELIBDIR="$BASEPATH/lib"
|
||||
|
||||
TEST=""
|
||||
while [ -z "$TEST" ] ; do
|
||||
TEST="$DEFPERM"
|
||||
echo ""
|
||||
echo "What should the default permissions for your configuration files be? (Set this to 0 to disable)"
|
||||
echo "It is strongly recommended that you use 0600 to prevent unwanted reading of the file"
|
||||
echo $n "[$TEST] -> $c"
|
||||
TEST="$DEFPERM"
|
||||
echo ""
|
||||
echo "What should the default permissions for your configuration files be? (Set this to 0 to disable)"
|
||||
echo "It is strongly recommended that you use 0600 to prevent unwanted reading of the file"
|
||||
echo $n "[$TEST] -> $c"
|
||||
read cc
|
||||
if [ -z "$cc" ] ; then
|
||||
DEFPERM=$TEST
|
||||
break
|
||||
fi
|
||||
case "$cc" in
|
||||
if [ -z "$cc" ] ; then
|
||||
DEFPERM=$TEST
|
||||
break
|
||||
fi
|
||||
case "$cc" in
|
||||
[0-9]*)
|
||||
DEFPERM="$cc"
|
||||
;;
|
||||
DEFPERM="$cc"
|
||||
;;
|
||||
*)
|
||||
echo ""
|
||||
echo "You must enter a number"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo "You must enter a number"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
|
||||
|
||||
echo ""
|
||||
echo "If you want, you can manually enter the path to OpenSSL/LibreSSL here."
|
||||
echo "In most cases you can leave this blank and it will be detected automatically."
|
||||
@ -475,43 +481,43 @@ fi
|
||||
|
||||
TEST="$SSLDIR"
|
||||
echo $n "[$TEST] -> $c"
|
||||
read cc
|
||||
read cc
|
||||
if [ -z "$cc" ] ; then
|
||||
SSLDIR="$TEST"
|
||||
SSLDIR="$TEST"
|
||||
else
|
||||
SSLDIR=`eval echo $cc` # modified
|
||||
SSLDIR=`eval echo $cc` # modified
|
||||
fi
|
||||
|
||||
TEST=""
|
||||
while [ -z "$TEST" ] ; do
|
||||
if [ "$REMOTEINC" = "1" ] ; then
|
||||
TEST="Yes"
|
||||
else
|
||||
TEST="No"
|
||||
fi
|
||||
echo ""
|
||||
echo "Do you want to enable remote includes?"
|
||||
echo "This allows stuff like this in your configuration file:"
|
||||
echo "include \"https://www.somesite.org/files/opers.conf\";"
|
||||
echo $n "[$TEST] -> $c"
|
||||
if [ "$REMOTEINC" = "1" ] ; then
|
||||
TEST="Yes"
|
||||
else
|
||||
TEST="No"
|
||||
fi
|
||||
echo ""
|
||||
echo "Do you want to enable remote includes?"
|
||||
echo "This allows stuff like this in your configuration file:"
|
||||
echo "include \"https://www.somesite.org/files/opers.conf\";"
|
||||
echo $n "[$TEST] -> $c"
|
||||
read cc
|
||||
if [ -z "$cc" ] ; then
|
||||
cc=$TEST
|
||||
fi
|
||||
case "$cc" in
|
||||
if [ -z "$cc" ] ; then
|
||||
cc=$TEST
|
||||
fi
|
||||
case "$cc" in
|
||||
[Yy]*)
|
||||
REMOTEINC="1"
|
||||
;;
|
||||
REMOTEINC="1"
|
||||
;;
|
||||
[Nn]*)
|
||||
REMOTEINC=""
|
||||
CURLDIR=""
|
||||
;;
|
||||
REMOTEINC=""
|
||||
CURLDIR=""
|
||||
;;
|
||||
*)
|
||||
echo ""
|
||||
echo "You must enter either Yes or No"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
echo ""
|
||||
echo "You must enter either Yes or No"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$REMOTEINC" = "1" ] ; then
|
||||
@ -589,108 +595,108 @@ if [ "$REMOTEINC" = "1" ] ; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "x$CURLDIR" = "x" ]; then
|
||||
# Still empty?
|
||||
TEST=""
|
||||
while [ -z "$TEST" ] ; do
|
||||
TEST="Yes"
|
||||
echo ""
|
||||
echo "Do you want me to automatically download and install curl for you?"
|
||||
echo $n "[$TEST] -> $c"
|
||||
read cc
|
||||
if [ -z "$cc" ] ; then
|
||||
cc=$TEST
|
||||
fi
|
||||
case "$cc" in
|
||||
[Yy]*)
|
||||
INSTALLCURL="1"
|
||||
CURLDIR="$UNREALCWD/extras/curl"
|
||||
;;
|
||||
[Nn]*)
|
||||
INSTALLCURL="0"
|
||||
;;
|
||||
*)
|
||||
echo ""
|
||||
echo "You must enter either Yes or No"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
if [ "x$CURLDIR" = "x" ]; then
|
||||
# Still empty?
|
||||
TEST=""
|
||||
while [ -z "$TEST" ] ; do
|
||||
TEST="Yes"
|
||||
echo ""
|
||||
echo "Do you want me to automatically download and install curl for you?"
|
||||
echo $n "[$TEST] -> $c"
|
||||
read cc
|
||||
if [ -z "$cc" ] ; then
|
||||
cc=$TEST
|
||||
fi
|
||||
case "$cc" in
|
||||
[Yy]*)
|
||||
INSTALLCURL="1"
|
||||
CURLDIR="$UNREALCWD/extras/curl"
|
||||
;;
|
||||
[Nn]*)
|
||||
INSTALLCURL="0"
|
||||
;;
|
||||
*)
|
||||
echo ""
|
||||
echo "You must enter either Yes or No"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$INSTALLCURL" != "1" ]; then
|
||||
TEST=""
|
||||
while [ -z "$TEST" ] ; do
|
||||
TEST="$CURLDIR"
|
||||
echo ""
|
||||
echo "Specify the directory you installed libcurl to"
|
||||
echo $n "[$TEST] -> $c"
|
||||
read cc
|
||||
if [ -z "$cc" ] ; then
|
||||
cc=$TEST
|
||||
else
|
||||
TEST=$cc
|
||||
CURLDIR=`eval echo $cc` # modified
|
||||
fi
|
||||
done
|
||||
fi
|
||||
TEST=""
|
||||
while [ -z "$TEST" ] ; do
|
||||
TEST="$CURLDIR"
|
||||
echo ""
|
||||
echo "Specify the directory you installed libcurl to"
|
||||
echo $n "[$TEST] -> $c"
|
||||
read cc
|
||||
if [ -z "$cc" ] ; then
|
||||
cc=$TEST
|
||||
else
|
||||
TEST=$cc
|
||||
CURLDIR=`eval echo $cc` # modified
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
TEST=""
|
||||
while [ -z "$TEST" ] ; do
|
||||
if [ "$PREFIXAQ" = "1" ] ; then
|
||||
TEST="Yes"
|
||||
else
|
||||
TEST="No"
|
||||
fi
|
||||
echo ""
|
||||
echo "Do you want to enable prefixes for chanadmin and chanowner?"
|
||||
echo "This will give +a the & prefix and ~ for +q (just like +o is @)"
|
||||
echo "Supported by the major clients (mIRC, xchat, epic, eggdrop, Klient,"
|
||||
echo "PJIRC, irssi, CGI:IRC, etc.)"
|
||||
echo "This feature should be enabled/disabled network-wide."
|
||||
echo $n "[$TEST] -> $c"
|
||||
if [ "$PREFIXAQ" = "1" ] ; then
|
||||
TEST="Yes"
|
||||
else
|
||||
TEST="No"
|
||||
fi
|
||||
echo ""
|
||||
echo "Do you want to enable prefixes for chanadmin and chanowner?"
|
||||
echo "This will give +a the & prefix and ~ for +q (just like +o is @)"
|
||||
echo "Supported by the major clients (mIRC, xchat, epic, eggdrop, Klient,"
|
||||
echo "PJIRC, irssi, CGI:IRC, etc.)"
|
||||
echo "This feature should be enabled/disabled network-wide."
|
||||
echo $n "[$TEST] -> $c"
|
||||
read cc
|
||||
if [ -z "$cc" ] ; then
|
||||
cc=$TEST
|
||||
fi
|
||||
case "$cc" in
|
||||
if [ -z "$cc" ] ; then
|
||||
cc=$TEST
|
||||
fi
|
||||
case "$cc" in
|
||||
[Yy]*)
|
||||
PREFIXAQ="1"
|
||||
;;
|
||||
PREFIXAQ="1"
|
||||
;;
|
||||
[Nn]*)
|
||||
PREFIXAQ=""
|
||||
;;
|
||||
PREFIXAQ=""
|
||||
;;
|
||||
*)
|
||||
echo ""
|
||||
echo "You must enter either Yes or No"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
echo ""
|
||||
echo "You must enter either Yes or No"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
TEST=""
|
||||
while [ -z "$TEST" ] ; do
|
||||
TEST="$NICKNAMEHISTORYLENGTH"
|
||||
echo ""
|
||||
echo "How far back do you want to keep the nickname history?"
|
||||
echo $n "[$TEST] -> $c"
|
||||
TEST="$NICKNAMEHISTORYLENGTH"
|
||||
echo ""
|
||||
echo "How far back do you want to keep the nickname history?"
|
||||
echo $n "[$TEST] -> $c"
|
||||
read cc
|
||||
if [ -z "$cc" ] ; then
|
||||
NICKNAMEHISTORYLENGTH=$TEST
|
||||
break
|
||||
fi
|
||||
case "$cc" in
|
||||
if [ -z "$cc" ] ; then
|
||||
NICKNAMEHISTORYLENGTH=$TEST
|
||||
break
|
||||
fi
|
||||
case "$cc" in
|
||||
[1-9]*)
|
||||
NICKNAMEHISTORYLENGTH="$cc"
|
||||
;;
|
||||
NICKNAMEHISTORYLENGTH="$cc"
|
||||
;;
|
||||
*)
|
||||
echo ""
|
||||
echo "You must enter a number"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
echo ""
|
||||
echo "You must enter a number"
|
||||
TEST=""
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo ""
|
||||
@ -737,7 +743,7 @@ echo "Otherwise, see \`./configure --help' and write them here:"
|
||||
echo $n "[$TEST] -> $c"
|
||||
read EXTRAPARA
|
||||
if [ -z "$EXTRAPARA" ]; then
|
||||
EXTRAPARA="$TEST"
|
||||
EXTRAPARA="$TEST"
|
||||
fi
|
||||
|
||||
rm -f config.settings
|
||||
|
84
Makefile.in
84
Makefile.in
@ -164,54 +164,56 @@ depend:
|
||||
done
|
||||
|
||||
install: all
|
||||
$(INSTALL) -m 0700 -d @BINDIR@
|
||||
$(INSTALL) -m 0700 src/ircd @BINDIR@/unrealircd
|
||||
$(INSTALL) -m 0700 -d @DOCDIR@
|
||||
$(INSTALL) -m 0600 doc/Authors doc/coding-guidelines doc/tao.of.irc @DOCDIR@
|
||||
$(INSTALL) -m 0700 -d @CONFDIR@
|
||||
$(INSTALL) -m 0600 doc/conf/*.conf @CONFDIR@
|
||||
$(INSTALL) -m 0600 doc/conf/*.motd @CONFDIR@
|
||||
$(INSTALL) -m 0600 doc/conf/modules.sources.list @CONFDIR@ ; \
|
||||
$(INSTALL) -m 0700 unrealircd @SCRIPTDIR@
|
||||
$(INSTALL) -m 0700 -d @MODULESDIR@
|
||||
@rm -f @MODULESDIR@/*.so 1>/dev/null 2>&1
|
||||
$(INSTALL) -m 0700 src/modules/*.so @MODULESDIR@
|
||||
$(INSTALL) -m 0700 -d @MODULESDIR@/usermodes
|
||||
@rm -f @MODULESDIR@/usermodes/*.so 1>/dev/null 2>&1
|
||||
$(INSTALL) -m 0700 src/modules/usermodes/*.so @MODULESDIR@/usermodes
|
||||
$(INSTALL) -m 0700 -d @MODULESDIR@/chanmodes
|
||||
@rm -f @MODULESDIR@/chanmodes/*.so 1>/dev/null 2>&1
|
||||
$(INSTALL) -m 0700 src/modules/chanmodes/*.so @MODULESDIR@/chanmodes
|
||||
$(INSTALL) -m 0700 -d @MODULESDIR@/snomasks
|
||||
@rm -f @MODULESDIR@/snomasks/*.so 1>/dev/null 2>&1
|
||||
$(INSTALL) -m 0700 src/modules/snomasks/*.so @MODULESDIR@/snomasks
|
||||
$(INSTALL) -m 0700 -d @MODULESDIR@/extbans
|
||||
@rm -f @MODULESDIR@/extbans/*.so 1>/dev/null 2>&1
|
||||
$(INSTALL) -m 0700 src/modules/extbans/*.so @MODULESDIR@/extbans
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@BINDIR@
|
||||
$(INSTALL) -m 0700 src/ircd $(DESTDIR)@BINDIR@/unrealircd
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@DOCDIR@
|
||||
$(INSTALL) -m 0600 doc/Authors doc/coding-guidelines doc/tao.of.irc $(DESTDIR)@DOCDIR@
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@CONFDIR@
|
||||
$(INSTALL) -m 0600 doc/conf/*.conf $(DESTDIR)@CONFDIR@
|
||||
$(INSTALL) -m 0600 doc/conf/*.motd $(DESTDIR)@CONFDIR@
|
||||
$(INSTALL) -m 0600 doc/conf/modules.sources.list $(DESTDIR)@CONFDIR@ ; \
|
||||
$(INSTALL) -m 0700 unrealircd $(DESTDIR)@SCRIPTDIR@
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@MODULESDIR@
|
||||
@rm -f $(DESTDIR)@MODULESDIR@/*.so 1>/dev/null 2>&1
|
||||
$(INSTALL) -m 0700 src/modules/*.so $(DESTDIR)@MODULESDIR@
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@MODULESDIR@/usermodes
|
||||
@rm -f $(DESTDIR)@MODULESDIR@/usermodes/*.so 1>/dev/null 2>&1
|
||||
$(INSTALL) -m 0700 src/modules/usermodes/*.so $(DESTDIR)@MODULESDIR@/usermodes
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@MODULESDIR@/chanmodes
|
||||
@rm -f $(DESTDIR)@MODULESDIR@/chanmodes/*.so 1>/dev/null 2>&1
|
||||
$(INSTALL) -m 0700 src/modules/chanmodes/*.so $(DESTDIR)@MODULESDIR@/chanmodes
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@MODULESDIR@/snomasks
|
||||
@rm -f $(DESTDIR)@MODULESDIR@/snomasks/*.so 1>/dev/null 2>&1
|
||||
$(INSTALL) -m 0700 src/modules/snomasks/*.so $(DESTDIR)@MODULESDIR@/snomasks
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@MODULESDIR@/extbans
|
||||
@rm -f $(DESTDIR)@MODULESDIR@/extbans/*.so 1>/dev/null 2>&1
|
||||
$(INSTALL) -m 0700 src/modules/extbans/*.so $(DESTDIR)@MODULESDIR@/extbans
|
||||
@#If the conf/ssl directory exists then rename it here to conf/tls
|
||||
@#and add a symlink for backwards compatibility (so that f.e. certbot
|
||||
@#doesn't randomly fail after an upgrade to U5).
|
||||
-@if [ -d "@CONFDIR@/ssl" ] ; then \
|
||||
mv "@CONFDIR@/ssl" "@CONFDIR@/tls" ; \
|
||||
ln -s "@CONFDIR@/tls" "@CONFDIR@/ssl" ; \
|
||||
-@if [ -d "$(DESTDIR)@CONFDIR@/ssl" ] ; then \
|
||||
mv "$(DESTDIR)@CONFDIR@/ssl" "$(DESTDIR)@CONFDIR@/tls" ; \
|
||||
ln -s "$(DESTDIR)@CONFDIR@/tls" "$(DESTDIR)@CONFDIR@/ssl" ; \
|
||||
fi
|
||||
$(INSTALL) -m 0700 -d @CONFDIR@/tls
|
||||
$(INSTALL) -m 0600 doc/conf/tls/curl-ca-bundle.crt @CONFDIR@/tls
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@CONFDIR@/tls
|
||||
$(INSTALL) -m 0600 doc/conf/tls/curl-ca-bundle.crt $(DESTDIR)@CONFDIR@/tls
|
||||
@# delete modules/cap directory, to avoid confusing with U4 to U5 upgrades:
|
||||
rm -rf @MODULESDIR@/cap
|
||||
$(INSTALL) -m 0700 -d @MODULESDIR@/third
|
||||
@rm -f @MODULESDIR@/third/*.so 1>/dev/null 2>&1
|
||||
rm -rf $(DESTDIR)@MODULESDIR@/cap
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@MODULESDIR@/third
|
||||
@rm -f $(DESTDIR)@MODULESDIR@/third/*.so 1>/dev/null 2>&1
|
||||
@#This step can fail with zero files, so we ignore exit status:
|
||||
-$(INSTALL) -m 0700 src/modules/third/*.so @MODULESDIR@/third
|
||||
$(INSTALL) -m 0700 -d @TMPDIR@
|
||||
$(INSTALL) -m 0700 -d @CACHEDIR@
|
||||
$(INSTALL) -m 0700 -d @PERMDATADIR@
|
||||
$(INSTALL) -m 0700 -d @LOGDIR@
|
||||
-@if [ ! -f "@CONFDIR@/tls/server.cert.pem" ] ; then \
|
||||
$(INSTALL) -m 0600 server.req.pem @CONFDIR@/tls ; \
|
||||
$(INSTALL) -m 0600 server.key.pem @CONFDIR@/tls ; \
|
||||
$(INSTALL) -m 0600 server.cert.pem @CONFDIR@/tls ; \
|
||||
-$(INSTALL) -m 0700 src/modules/third/*.so $(DESTDIR)@MODULESDIR@/third
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@TMPDIR@
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@CACHEDIR@
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@PERMDATADIR@
|
||||
$(INSTALL) -m 0700 -d $(DESTDIR)@LOGDIR@
|
||||
-@if [ ! -f "$(DESTDIR)@CONFDIR@/tls/server.cert.pem" ] ; then \
|
||||
$(INSTALL) -m 0600 server.req.pem $(DESTDIR)@CONFDIR@/tls ; \
|
||||
$(INSTALL) -m 0600 server.key.pem $(DESTDIR)@CONFDIR@/tls ; \
|
||||
$(INSTALL) -m 0600 server.cert.pem $(DESTDIR)@CONFDIR@/tls ; \
|
||||
fi
|
||||
@rm -f $(DESTDIR)@SCRIPTDIR@/source
|
||||
ln -s @BUILDDIR@ $(DESTDIR)@SCRIPTDIR@/source
|
||||
@echo ''
|
||||
@echo '* UnrealIRCd is now installed.'
|
||||
|
||||
|
@ -269,6 +269,7 @@ DLL_FILES=SRC/MODULES/CLOAK.DLL \
|
||||
SRC/MODULES/EXTBANS/MSGBYPASS.DLL \
|
||||
SRC/MODULES/EXTBANS/TIMEDBAN.DLL \
|
||||
SRC/MODULES/EXTBANS/PARTMSG.DLL \
|
||||
SRC/MODULES/EXTBANS/SECURITYGROUP.DLL \
|
||||
SRC/MODULES/ACCOUNT-NOTIFY.DLL \
|
||||
SRC/MODULES/MESSAGE-TAGS.DLL \
|
||||
SRC/MODULES/BATCH.DLL \
|
||||
@ -1018,6 +1019,9 @@ src/modules/extbans/timedban.dll: src/modules/extbans/timedban.c $(INCLUDES)
|
||||
src/modules/extbans/partmsg.dll: src/modules/extbans/partmsg.c $(INCLUDES)
|
||||
$(CC) $(MODCFLAGS) /Fosrc/modules/extbans/ /Fesrc/modules/extbans/ src/modules/extbans/partmsg.c $(MODLFLAGS)
|
||||
|
||||
src/modules/extbans/securitygroup.dll: src/modules/extbans/securitygroup.c $(INCLUDES)
|
||||
$(CC) $(MODCFLAGS) /Fosrc/modules/extbans/ /Fesrc/modules/extbans/ src/modules/extbans/securitygroup.c $(MODLFLAGS)
|
||||
|
||||
src/modules/account-notify.dll: src/modules/account-notify.c $(INCLUDES)
|
||||
$(CC) $(MODCFLAGS) /Fosrc/modules/ /Fesrc/modules/ src/modules/account-notify.c $(MODLFLAGS)
|
||||
|
||||
|
21
SECURITY.md
Normal file
21
SECURITY.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
* The latest *stable* release of the 5.x branch
|
||||
|
||||
See [UnrealIRCd releases](https://www.unrealircd.org/docs/UnrealIRCd_releases) for information on older versions and End Of Life dates.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please report issues on the [bug tracker](https://bugs.unrealircd.org) and in the bug submit form **set the 'View Status' to 'private'**.
|
||||
|
||||
Do not report security issues on the forums or in a public IRC channel such as #unreal-support.
|
||||
If you insist on e-mail then you can use syzop@unrealircd.org or security@unrealircd.org. Again, the bug tracker is preferred.
|
||||
|
||||
If you are *unsure* if something is a security issue, then report it at the bug tracker as a 'private' bug anyway. Better safe than sorry.
|
||||
Do not ask around in public channels or forums.
|
||||
|
||||
You should get a response or at least an acknowledgement soon. If you don't hear back within 24 hours, then please try to contact us again.
|
||||
|
||||
## Full policy
|
||||
See https://www.unrealircd.org/docs/Policy:_Handling_of_security_issues for full information.
|
@ -272,3 +272,43 @@ else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN([CHECK_ASN1_TIME_diff],
|
||||
[
|
||||
AC_MSG_CHECKING([for ASN1_TIME_diff in SSL library])
|
||||
AC_LANG_PUSH(C)
|
||||
SAVE_LIBS="$LIBS"
|
||||
LIBS="$LIBS $CRYPTOLIB"
|
||||
AC_TRY_LINK([#include <openssl/ssl.h>],
|
||||
[int one, two; ASN1_TIME_diff(&one, &two, NULL, NULL);],
|
||||
has_function=1,
|
||||
has_function=0)
|
||||
LIBS="$SAVE_LIBS"
|
||||
AC_LANG_POP(C)
|
||||
if test $has_function = 1; then
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([HAS_ASN1_TIME_diff], [], [Define if ssl library has ASN1_TIME_diff])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN([CHECK_X509_get0_notAfter],
|
||||
[
|
||||
AC_MSG_CHECKING([for X509_get0_notAfter in SSL library])
|
||||
AC_LANG_PUSH(C)
|
||||
SAVE_LIBS="$LIBS"
|
||||
LIBS="$LIBS $CRYPTOLIB"
|
||||
AC_TRY_LINK([#include <openssl/ssl.h>],
|
||||
[X509_get0_notAfter(NULL);],
|
||||
has_function=1,
|
||||
has_function=0)
|
||||
LIBS="$SAVE_LIBS"
|
||||
AC_LANG_POP(C)
|
||||
if test $has_function = 1; then
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([HAS_X509_get0_notAfter], [], [Define if ssl library has X509_get0_notAfter])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
])
|
||||
|
114
configure
vendored
114
configure
vendored
@ -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.7.
|
||||
# Generated by GNU Autoconf 2.69 for unrealircd 5.0.8.
|
||||
#
|
||||
# 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.7'
|
||||
PACKAGE_STRING='unrealircd 5.0.7'
|
||||
PACKAGE_VERSION='5.0.8'
|
||||
PACKAGE_STRING='unrealircd 5.0.8'
|
||||
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.7 to adapt to many kinds of systems.
|
||||
\`configure' configures unrealircd 5.0.8 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.7:";;
|
||||
short | recursive ) echo "Configuration of unrealircd 5.0.8:";;
|
||||
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.7
|
||||
unrealircd configure 5.0.8
|
||||
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.7, which was
|
||||
It was created by unrealircd $as_me 5.0.8, 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="7"
|
||||
UNREAL_VERSION_MINOR="8"
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define UNREAL_VERSION_MINOR $UNREAL_VERSION_MINOR
|
||||
@ -6528,6 +6528,100 @@ else
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ASN1_TIME_diff in SSL library" >&5
|
||||
$as_echo_n "checking for ASN1_TIME_diff in SSL library... " >&6; }
|
||||
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
|
||||
|
||||
SAVE_LIBS="$LIBS"
|
||||
LIBS="$LIBS $CRYPTOLIB"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <openssl/ssl.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
int one, two; ASN1_TIME_diff(&one, &two, NULL, NULL);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
has_function=1
|
||||
else
|
||||
has_function=0
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS="$SAVE_LIBS"
|
||||
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
|
||||
|
||||
if test $has_function = 1; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
|
||||
$as_echo "#define HAS_ASN1_TIME_diff /**/" >>confdefs.h
|
||||
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for X509_get0_notAfter in SSL library" >&5
|
||||
$as_echo_n "checking for X509_get0_notAfter in SSL library... " >&6; }
|
||||
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
|
||||
|
||||
SAVE_LIBS="$LIBS"
|
||||
LIBS="$LIBS $CRYPTOLIB"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <openssl/ssl.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
X509_get0_notAfter(NULL);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
has_function=1
|
||||
else
|
||||
has_function=0
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS="$SAVE_LIBS"
|
||||
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
|
||||
|
||||
if test $has_function = 1; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
|
||||
$as_echo "#define HAS_X509_get0_notAfter /**/" >>confdefs.h
|
||||
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
# Check whether --enable-dynamic-linking was given.
|
||||
if test "${enable_dynamic_linking+set}" = set; then :
|
||||
enableval=$enable_dynamic_linking; enable_dynamic_linking=$enableval
|
||||
@ -8398,7 +8492,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.7, which was
|
||||
This file was extended by unrealircd $as_me 5.0.8, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@ -8461,7 +8555,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.7
|
||||
unrealircd config.status 5.0.8
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
@ -7,7 +7,7 @@ dnl src/windows/unrealinst.iss
|
||||
dnl doc/Config.header
|
||||
dnl src/version.c.SH
|
||||
|
||||
AC_INIT([unrealircd], [5.0.7], [https://bugs.unrealircd.org/], [], [https://unrealircd.org/])
|
||||
AC_INIT([unrealircd], [5.0.8], [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=["7"]
|
||||
UNREAL_VERSION_MINOR=["8"]
|
||||
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
|
||||
@ -504,6 +504,8 @@ CHECK_SSL
|
||||
CHECK_SSL_CTX_SET1_CURVES_LIST
|
||||
CHECK_SSL_CTX_SET_MIN_PROTO_VERSION
|
||||
CHECK_SSL_CTX_SET_SECURITY_LEVEL
|
||||
CHECK_ASN1_TIME_diff
|
||||
CHECK_X509_get0_notAfter
|
||||
AC_ARG_ENABLE(dynamic-linking, [AS_HELP_STRING([--disable-dynamic-linking], [Make the IRCd statically link with shared objects rather than dynamically (noone knows if disabling dynamic linking actually does anything or not)])],
|
||||
[enable_dynamic_linking=$enableval], [enable_dynamic_linking="yes"])
|
||||
AS_IF([test $enable_dynamic_linking = "yes"],
|
||||
|
@ -7,7 +7,7 @@
|
||||
\___/|_| |_|_| \___|\__,_|_|\___/\_| \_| \____/\__,_|
|
||||
|
||||
Configuration Program
|
||||
for UnrealIRCd 5.0.7
|
||||
for UnrealIRCd 5.0.8
|
||||
|
||||
This program will help you to compile your IRC server, and ask you
|
||||
questions regarding the compile-time settings of it during the process.
|
||||
|
@ -1,6 +1,72 @@
|
||||
UnrealIRCd 5.0.7 Release Notes
|
||||
UnrealIRCd 5.0.8 Release Notes
|
||||
===============================
|
||||
|
||||
The main purpose of this release is to enhance the
|
||||
[reputation](https://www.unrealircd.org/docs/Reputation_score)
|
||||
functionality. There have also been some other changes and minor
|
||||
bug fixes. For more information, see below.
|
||||
|
||||
Enhancements:
|
||||
* Support for [security groups](https://www.unrealircd.org/docs/Security-group_block),
|
||||
of which four groups always exist by default: known-users, unknown-users,
|
||||
tls-users and tls-and-known-users.
|
||||
* New extended ban ```~G:securitygroupname```. Typical usage would be
|
||||
```MODE #chan +b ~G:unknown-users``` which will ban all users from the
|
||||
channel that are not identified to services and have a reputation
|
||||
score below 25 (by default). The exact settings can be tweaked in the
|
||||
[security group block](https://www.unrealircd.org/docs/Security-group_block).
|
||||
* The reputation command (IRCOp-only) has been extended to make it
|
||||
easier to look for potential troublemakers:
|
||||
* ```REPUTATION Nick``` shows reputation about the nick name
|
||||
* ```REPUTATION IP``` shows reputation about the IP address
|
||||
* ```REPUTATION #channel``` lists users in channel with their reputation score
|
||||
* ```REPUTATION <NN``` lists users with reputation scores below value NN
|
||||
* Only send the first 1000 matches on ```STATS gline``` or a
|
||||
similar command. This to prevent the IRCOp from being flooded off.
|
||||
This value can be changed via
|
||||
[set::max-stats-matches](https://www.unrealircd.org/docs/Set_block#set::max-stats-matches)
|
||||
* Warn when the SSL/TLS server certificate is expired or expires soon
|
||||
(within 7 days).
|
||||
* New option allow::options::reject-on-auth-failure if you want to
|
||||
stop matching on a passworded allow block, see the
|
||||
[allow password documentation](https://www.unrealircd.org/docs/Allow_block#password)
|
||||
for more information. Note that most people won't use this.
|
||||
|
||||
Fixes:
|
||||
* The ```WHO``` command searched on nick name even if it was told
|
||||
to search on a specific account name via WHOX options.
|
||||
* Some typos in the Config script and a warning
|
||||
* Counting clients twice in some circumstances
|
||||
|
||||
Changes:
|
||||
* Support for $(DESTDIR) in 'make install' if packaging for a distro
|
||||
* Mention the ban reason in Q-line server notices
|
||||
* Add self-test to module manager and improve the error message in case
|
||||
the IRCd source directory does not exist.
|
||||
* Print out a more helpful error if you run the unrealircd binary
|
||||
rather than the unrealircd script with an argument like 'mkpasswd' etc.
|
||||
* On *NIX create a symlink 'source' to the UnrealIRCd source
|
||||
|
||||
Module coders / Developers:
|
||||
* The [Doxygen module API docs](https://www.unrealircd.org/api/5/index.html)
|
||||
have been improved, in particular the
|
||||
[Hook API](https://www.unrealircd.org/api/5/group__HookAPI.html)
|
||||
is now 100% documented.
|
||||
|
||||
Reminder: UnrealIRCd 4 is no longer supported
|
||||
----------------------------------------------
|
||||
|
||||
UnrealIRCd 4.x is [no longer supported](https://www.unrealircd.org/docs/UnrealIRCd_4_EOL).
|
||||
Admins must upgrade to UnrealIRCd 5.
|
||||
|
||||
Upgrading from 4.x to 5.x?
|
||||
Then check out the *UnrealIRCd 5* release notes [further down](#unrealircd-5).
|
||||
Or, at the very least, check out
|
||||
[Upgrading from 4.x](https://www.unrealircd.org/docs/Upgrading_from_4.x).
|
||||
|
||||
UnrealIRCd 5.0.7
|
||||
-----------------
|
||||
|
||||
UnrealIRCd 5.0.7 consists mainly of fixes for the 5.x stable series,
|
||||
with some minor enhancements.
|
||||
|
||||
@ -34,17 +100,6 @@ Module coders / Developers:
|
||||
* No changes, only some small additions to the
|
||||
[Doxygen module API docs](https://www.unrealircd.org/api/5/index.html)
|
||||
|
||||
Reminder: UnrealIRCd 4 is End Of Life
|
||||
---------------------------------------
|
||||
|
||||
All support for the previous series, UnrealIRCd 4.x, will stop after
|
||||
[December 31, 2020](https://www.unrealircd.org/docs/UnrealIRCd_4_EOL).
|
||||
If you haven't upgraded yet, do so soon!
|
||||
|
||||
Upgrading from 4.x to 5.x?
|
||||
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.6
|
||||
-----------------
|
||||
|
||||
|
@ -37,6 +37,11 @@ rem And we re-run the exact same command:
|
||||
call extras\build-tests\windows\compilecmd\%SHORTNAME%.bat
|
||||
if %ERRORLEVEL% NEQ 0 EXIT /B 1
|
||||
|
||||
rem Compile dependencies for unrealircd-tests -- this doesn't belong here though..
|
||||
curl -fsS -o src\modules\third\fakereputation.c https://raw.githubusercontent.com/unrealircd/unrealircd-tests/master/serverconfig/unrealircd/modules/fakereputation.c
|
||||
call extras\build-tests\windows\compilecmd\%SHORTNAME%.bat CUSTOMMODULE MODULEFILE=fakereputation
|
||||
if %ERRORLEVEL% NEQ 0 EXIT /B 1
|
||||
|
||||
rem Convert c:\dev to c:\projects\unrealircd-5-libs
|
||||
rem TODO: should use environment variable in innosetup script?
|
||||
sed -i "s/c:\\dev\\unrealircd-5-libs/c:\\projects\\unrealircd-5-libs/gi" src\windows\unrealinst.iss
|
||||
|
@ -8,10 +8,11 @@ Here you should be able to find a lot of information on the data structures
|
||||
and functions available to you when coding for UnrealIRCd.
|
||||
|
||||
## Wiki documentation ##
|
||||
* Be sure to check the [Module API](https://www.unrealircd.org/docs/Dev:Module_API) article on the wiki, which currently provides a better overview of the module API.
|
||||
* Be sure to check the [Module API](https://www.unrealircd.org/docs/Dev:Module_API) article on the wiki
|
||||
as well, which provides a better *overview* of the module API
|
||||
|
||||
## Doxygen docs ##
|
||||
* [Functions and structs ordered by purpose](modules.html) - **this contains most of the module API!**
|
||||
* [The most common structs](group__CommonStructs.html) - like Client, User, Server, Channel, etc.
|
||||
* [All structs](classes.html) - in a simple alphabetical index
|
||||
* [Functions and structs ordered by purpose](modules.html) - this is work in progress and still needs expansion!
|
||||
* [Browse by source file](dir_68267d1309a1af8e8297ef4c3efbcdba.html) - see all src/*.c files and their (documented) functions.
|
||||
|
@ -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.7
|
||||
PROJECT_NUMBER = 5.0.8
|
||||
|
||||
# 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
|
||||
|
42
include/h.h
42
include/h.h
@ -90,6 +90,7 @@ extern MODVAR ConfigItem_alias *conf_alias;
|
||||
extern MODVAR ConfigItem_include *conf_include;
|
||||
extern MODVAR ConfigItem_help *conf_help;
|
||||
extern MODVAR ConfigItem_offchans *conf_offchans;
|
||||
extern MODVAR SecurityGroup *securitygroups;
|
||||
extern void completed_connection(int, int, void *);
|
||||
extern void clear_unknown();
|
||||
extern EVENT(e_unload_module_delayed);
|
||||
@ -163,7 +164,6 @@ extern MODVAR struct list_head global_server_list;
|
||||
extern MODVAR struct list_head dead_list;
|
||||
extern RealCommand *find_command(char *cmd, int flags);
|
||||
extern RealCommand *find_command_simple(char *cmd);
|
||||
extern Channel *find_channel(char *, Channel *);
|
||||
extern Membership *find_membership_link(Membership *lp, Channel *ptr);
|
||||
extern Member *find_member_link(Member *, Client *);
|
||||
extern int remove_user_from_channel(Client *, Channel *);
|
||||
@ -336,7 +336,7 @@ extern void del_queries(char *);
|
||||
#define WATCH_HASH_TABLE_SIZE 32768
|
||||
#define WHOWAS_HASH_TABLE_SIZE 32768
|
||||
#define THROTTLING_HASH_TABLE_SIZE 8192
|
||||
#define find_channel hash_find_channel
|
||||
#define hash_find_channel find_channel
|
||||
extern uint64_t siphash(const char *in, const char *k);
|
||||
extern uint64_t siphash_raw(const char *in, size_t len, const char *k);
|
||||
extern uint64_t siphash_nocase(const char *in, const char *k);
|
||||
@ -359,7 +359,7 @@ extern Channel *hash_get_chan_bucket(uint64_t);
|
||||
extern Client *hash_find_client(const char *, Client *);
|
||||
extern Client *hash_find_id(const char *, Client *);
|
||||
extern Client *hash_find_nickatserver(const char *, Client *);
|
||||
extern Channel *hash_find_channel(char *name, Channel *channel);
|
||||
extern Channel *find_channel(char *name, Channel *channel);
|
||||
extern Client *hash_find_server(const char *, Client *);
|
||||
extern struct MODVAR ThrottlingBucket *ThrottlingHash[THROTTLING_HASH_TABLE_SIZE];
|
||||
|
||||
@ -460,6 +460,7 @@ extern void count_memory(Client *cptr, char *nick);
|
||||
extern void list_scache(Client *client);
|
||||
extern char *oflagstr(long oflag);
|
||||
extern int rehash(Client *client, int sig);
|
||||
extern void s_die();
|
||||
extern int match_simple(const char *mask, const char *name);
|
||||
extern int match_esc(const char *mask, const char *name);
|
||||
extern int add_listener(ConfigItem_listen *conf);
|
||||
@ -549,10 +550,6 @@ extern void *safe_alloc(size_t size);
|
||||
extern char *our_strdup(const char *str);
|
||||
extern char *our_strldup(const char *str, size_t max);
|
||||
|
||||
extern MODFUNC char *tls_get_cipher(SSL *ssl);
|
||||
extern TLSOptions *get_tls_options_for_client(Client *acptr);
|
||||
extern int outdated_tls_client(Client *acptr);
|
||||
extern char *outdated_tls_client_build_string(char *pattern, Client *acptr);
|
||||
extern long config_checkval(char *value, unsigned short flags);
|
||||
extern void config_status(FORMAT_STRING(const char *format), ...) __attribute__((format(printf,1,2)));
|
||||
extern void init_random();
|
||||
@ -701,7 +698,7 @@ extern MODVAR int (*find_shun)(Client *cptr);
|
||||
extern MODVAR int (*find_spamfilter_user)(Client *client, int flags);
|
||||
extern MODVAR TKL *(*find_qline)(Client *cptr, char *nick, int *ishold);
|
||||
extern MODVAR TKL *(*find_tkline_match_zap)(Client *cptr);
|
||||
extern MODVAR void (*tkl_stats)(Client *cptr, int type, char *para);
|
||||
extern MODVAR void (*tkl_stats)(Client *cptr, int type, char *para, int *cnt);
|
||||
extern MODVAR void (*tkl_sync)(Client *client);
|
||||
extern MODVAR void (*cmd_tkl)(Client *client, MessageTag *recv_mtags, int parc, char *parv[]);
|
||||
extern MODVAR int (*place_host_ban)(Client *client, BanAction action, char *reason, long duration);
|
||||
@ -753,6 +750,25 @@ extern MODVAR void (*labeled_response_force_end)(void);
|
||||
extern MODVAR void (*kick_user)(MessageTag *mtags, Channel *channel, Client *client, Client *victim, char *comment);
|
||||
/* /Efuncs */
|
||||
|
||||
/* SSL/TLS functions */
|
||||
extern int early_init_ssl();
|
||||
extern int init_ssl();
|
||||
extern int ssl_handshake(Client *); /* Handshake the accpeted con.*/
|
||||
extern int ssl_client_handshake(Client *, ConfigItem_link *); /* and the initiated con.*/
|
||||
extern int ircd_SSL_accept(Client *acptr, int fd);
|
||||
extern int ircd_SSL_connect(Client *acptr, int fd);
|
||||
extern int SSL_smart_shutdown(SSL *ssl);
|
||||
extern void ircd_SSL_client_handshake(int, int, void *);
|
||||
extern void SSL_set_nonblocking(SSL *s);
|
||||
extern SSL_CTX *init_ctx(TLSOptions *tlsoptions, int server);
|
||||
extern MODFUNC char *tls_get_cipher(SSL *ssl);
|
||||
extern TLSOptions *get_tls_options_for_client(Client *acptr);
|
||||
extern int outdated_tls_client(Client *acptr);
|
||||
extern char *outdated_tls_client_build_string(char *pattern, Client *acptr);
|
||||
extern int check_certificate_expiry_ctx(SSL_CTX *ctx, char **errstr);
|
||||
extern EVENT(tls_check_expiry);
|
||||
/* End of SSL/TLS functions */
|
||||
|
||||
extern void parse_message_tags_default_handler(Client *client, char **str, MessageTag **mtag_list);
|
||||
extern char *mtags_to_string_default_handler(MessageTag *m, Client *client);
|
||||
extern void *labeled_response_save_context_default_handler(void);
|
||||
@ -793,6 +809,8 @@ extern char *cm_getparameter_ex(void **p, char mode);
|
||||
extern void cm_putparameter_ex(void **p, char mode, char *str);
|
||||
extern void cm_freeparameter_ex(void **p, char mode, char *str);
|
||||
extern int file_exists(char *file);
|
||||
extern time_t get_file_time(char *fname);
|
||||
extern long get_file_size(char *fname);
|
||||
extern void free_motd(MOTDFile *motd); /* s_serv.c */
|
||||
extern void fix_timers(void);
|
||||
extern char *chfl_to_sjoin_symbol(int s);
|
||||
@ -974,3 +992,11 @@ 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;
|
||||
extern int security_group_valid_name(char *name);
|
||||
extern int security_group_exists(char *name);
|
||||
extern SecurityGroup *add_security_group(char *name, int order);
|
||||
extern SecurityGroup *find_security_group(char *name);
|
||||
extern void free_security_group(SecurityGroup *s);
|
||||
extern void set_security_group_defaults(void);
|
||||
extern int user_allowed_by_security_group(Client *client, SecurityGroup *s);
|
||||
extern int user_allowed_by_security_group_name(Client *client, char *secgroupname);
|
||||
|
@ -430,11 +430,62 @@ SINLINE void list_splice_tail_init(struct list_head *list,
|
||||
pos != (head); \
|
||||
pos = n, n = pos->prev)
|
||||
|
||||
/**
|
||||
* list_for_each_entry - iterate over list of given type
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
/** Walk through client lists (with examples).
|
||||
* @param pos The variable to use as a loop cursor
|
||||
* @param head The head of your list
|
||||
* @param member The name of the list_struct within the struct.
|
||||
* @ingroup ListFunctions
|
||||
* @section Examples
|
||||
* @subsection client_list List all clients
|
||||
* @code
|
||||
* CMD_FUNC(cmd_listallclients)
|
||||
* {
|
||||
* Client *acptr;
|
||||
* sendnotice(client, "List of all clients:");
|
||||
* list_for_each_entry(acptr, &client_list, client_node)
|
||||
* sendnotice(client, "Client %s", acptr->name);
|
||||
* }
|
||||
* @endcode
|
||||
* @subsection lclient_list List all LOCAL clients
|
||||
* @code
|
||||
* CMD_FUNC(cmd_listalllocalclients)
|
||||
* {
|
||||
* Client *acptr;
|
||||
* sendnotice(client, "List of all local clients:");
|
||||
* list_for_each_entry(acptr, &lclient_list, lclient_node)
|
||||
* sendnotice(client, "Client %s", acptr->name);
|
||||
* }
|
||||
* @endcode
|
||||
* @subsection global_server_list List all servers
|
||||
* @code
|
||||
* CMD_FUNC(cmd_listallservers)
|
||||
* {
|
||||
* Client *acptr;
|
||||
* sendnotice(client, "List of all servers:");
|
||||
* list_for_each_entry(acptr, &global_server_list, client_node)
|
||||
* sendnotice(client, "Server %s", acptr->name);
|
||||
* }
|
||||
* @endcode
|
||||
* @subsection server_list List all LOCALLY connected servers
|
||||
* @code
|
||||
* CMD_FUNC(cmd_listallservers)
|
||||
* {
|
||||
* Client *acptr;
|
||||
* sendnotice(client, "List of all LOCAL servers:");
|
||||
* list_for_each_entry(acptr, &server_list, special_node)
|
||||
* sendnotice(client, "Server %s", acptr->name);
|
||||
* }
|
||||
* @endcode
|
||||
* @subsection oper_list List all LOCALLY connected IRCOps
|
||||
* @code
|
||||
* CMD_FUNC(cmd_listlocalircops)
|
||||
* {
|
||||
* Client *acptr;
|
||||
* sendnotice(client, "List of all LOCAL IRCOps:");
|
||||
* list_for_each_entry(acptr, &oper_list, special_node)
|
||||
* sendnotice(client, "User %s", acptr->name);
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member); \
|
||||
@ -514,12 +565,16 @@ SINLINE void list_splice_tail_init(struct list_head *list,
|
||||
for (; &pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
/** Walk through client lists - special 'safe' version.
|
||||
* This is a special version, in case clients are removed from the list
|
||||
* while the list is iterated. It is unlikely that you need to use this
|
||||
* from modules, so use list_for_each_entry() instead.
|
||||
* Examples are also in list_for_each_entry().
|
||||
* @param pos The variable to use as a loop cursor
|
||||
* @param n Variable to be used for temporary storage
|
||||
* @param head The head of your list
|
||||
* @param member The name of the list_struct within the struct.
|
||||
* @ingroup ListFunctions
|
||||
*/
|
||||
#define list_for_each_entry_safe(pos, n, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
||||
|
1314
include/modules.h
1314
include/modules.h
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,9 @@
|
||||
/* Define if you have the <glob.h> header file. */
|
||||
#undef GLOBH
|
||||
|
||||
/* Define if ssl library has ASN1_TIME_diff */
|
||||
#undef HAS_ASN1_TIME_diff
|
||||
|
||||
/* Define if ssl library has SSL_CTX_set1_curves_list */
|
||||
#undef HAS_SSL_CTX_SET1_CURVES_LIST
|
||||
|
||||
@ -37,6 +40,9 @@
|
||||
/* Define if ssl library has SSL_CTX_set_security_level */
|
||||
#undef HAS_SSL_CTX_SET_SECURITY_LEVEL
|
||||
|
||||
/* Define if ssl library has X509_get0_notAfter */
|
||||
#undef HAS_X509_get0_notAfter
|
||||
|
||||
/* Define if you have crypt */
|
||||
#undef HAVE_CRYPT
|
||||
|
||||
|
@ -108,6 +108,7 @@ typedef struct ConfigItem_include ConfigItem_include;
|
||||
typedef struct ConfigItem_blacklist_module ConfigItem_blacklist_module;
|
||||
typedef struct ConfigItem_help ConfigItem_help;
|
||||
typedef struct ConfigItem_offchans ConfigItem_offchans;
|
||||
typedef struct SecurityGroup SecurityGroup;
|
||||
typedef struct ListStruct ListStruct;
|
||||
typedef struct ListStructPrio ListStructPrio;
|
||||
|
||||
@ -285,7 +286,7 @@ typedef enum ClientStatus {
|
||||
#define SetUser(x) ((x)->status = CLIENT_STATUS_USER)
|
||||
#define SetLog(x) ((x)->status = CLIENT_STATUS_LOG)
|
||||
|
||||
/* @} */
|
||||
/** @} */
|
||||
|
||||
/** Used for checking certain properties of clients, such as IsSecure() and IsULine().
|
||||
* @defgroup ClientFlags Client flags
|
||||
@ -487,7 +488,7 @@ typedef enum ClientStatus {
|
||||
#define ClearULine(x) do { (x)->flags &= ~CLIENT_FLAG_ULINE; } while(0)
|
||||
#define ClearVirus(x) do { (x)->flags &= ~CLIENT_FLAG_VIRUS; } while(0)
|
||||
#define ClearIdentLookupSent(x) do { (x)->flags &= ~CLIENT_FLAG_IDENTLOOKUPSENT; } while(0)
|
||||
/* @} */
|
||||
/** @} */
|
||||
|
||||
|
||||
/* Others that access client structs: */
|
||||
@ -498,6 +499,9 @@ typedef enum ClientStatus {
|
||||
#define IsSynched(x) (x->serv->flags.synced)
|
||||
#define IsServerSent(x) (x->serv && x->serv->flags.server_sent)
|
||||
|
||||
/* And more that access client stuff - but actually modularized */
|
||||
#define GetReputation(client) (moddata_client_get(client, "reputation") ? atoi(moddata_client_get(client, "reputation")) : 0) /**< Get reputation value for a client */
|
||||
|
||||
/* PROTOCTL (Server protocol) stuff */
|
||||
#ifndef DEBUGMODE
|
||||
#define CHECKSERVERPROTO(x,y) (((x)->local->proto & y) == y)
|
||||
@ -792,7 +796,8 @@ struct SWhois {
|
||||
char *setby;
|
||||
};
|
||||
|
||||
/** The command API - used by modules and the core.
|
||||
/** The command API - used by modules and the core to add commands, overrides, etc.
|
||||
* See also https://www.unrealircd.org/docs/Dev:Command_API for a higher level overview and example.
|
||||
* @defgroup CommandAPI Command API
|
||||
* @{
|
||||
*/
|
||||
@ -829,7 +834,7 @@ struct SWhois {
|
||||
* E.g. parv[3] in the above example is out of bounds.
|
||||
*/
|
||||
#define CMD_FUNC(x) void (x) (Client *client, MessageTag *recv_mtags, int parc, char *parv[])
|
||||
/* @} */
|
||||
/** @} */
|
||||
|
||||
/** Command override function - used by all command override handlers.
|
||||
* This is used in the code like <pre>CMD_OVERRIDE_FUNC(ovr_somecmd)</pre> as a function definition.
|
||||
@ -1217,7 +1222,7 @@ struct Server {
|
||||
} features;
|
||||
};
|
||||
|
||||
/* @} */
|
||||
/** @} */
|
||||
|
||||
struct MessageTag {
|
||||
MessageTag *prev, *next;
|
||||
@ -1379,6 +1384,7 @@ struct ConfigFlag_allow {
|
||||
unsigned noident :1;
|
||||
unsigned useip :1;
|
||||
unsigned tls :1;
|
||||
unsigned reject_on_auth_failure :1;
|
||||
};
|
||||
|
||||
struct ConfigItem_allow {
|
||||
@ -1715,6 +1721,16 @@ struct ConfigItem_offchans {
|
||||
char *topic;
|
||||
};
|
||||
|
||||
#define SECURITYGROUPLEN 48
|
||||
struct SecurityGroup {
|
||||
SecurityGroup *prev, *next;
|
||||
int priority;
|
||||
char name[SECURITYGROUPLEN+1];
|
||||
int identified;
|
||||
int reputation_score;
|
||||
int webirc;
|
||||
int tls;
|
||||
};
|
||||
|
||||
#define HM_HOST 1
|
||||
#define HM_IPV4 2
|
||||
@ -2010,18 +2026,6 @@ extern MODVAR SSL_CTX *ctx;
|
||||
extern MODVAR SSL_CTX *ctx_server;
|
||||
extern MODVAR SSL_CTX *ctx_client;
|
||||
|
||||
extern SSL_METHOD *meth;
|
||||
extern int early_init_ssl();
|
||||
extern int init_ssl();
|
||||
extern int ssl_handshake(Client *); /* Handshake the accpeted con.*/
|
||||
extern int ssl_client_handshake(Client *, ConfigItem_link *); /* and the initiated con.*/
|
||||
extern int ircd_SSL_accept(Client *acptr, int fd);
|
||||
extern int ircd_SSL_connect(Client *acptr, int fd);
|
||||
extern int SSL_smart_shutdown(SSL *ssl);
|
||||
extern void ircd_SSL_client_handshake(int, int, void *);
|
||||
extern void SSL_set_nonblocking(SSL *s);
|
||||
extern SSL_CTX *init_ctx(TLSOptions *tlsoptions, int server);
|
||||
|
||||
#define TLS_PROTOCOL_TLSV1 0x0001
|
||||
#define TLS_PROTOCOL_TLSV1_1 0x0002
|
||||
#define TLS_PROTOCOL_TLSV1_2 0x0004
|
||||
|
@ -63,7 +63,7 @@
|
||||
#define UNREAL_VERSION_MAJOR 0
|
||||
|
||||
/* Minor version number (e.g.: 1 for Unreal3.2.1) */
|
||||
#define UNREAL_VERSION_MINOR 7
|
||||
#define UNREAL_VERSION_MINOR 8
|
||||
|
||||
/* Version suffix such as a beta marker or release candidate marker. (e.g.:
|
||||
-rcX for unrealircd-3.2.9-rcX) */
|
||||
|
@ -26,7 +26,9 @@
|
||||
|
||||
#include "unrealircd.h"
|
||||
|
||||
/** This is the extended channel mode API
|
||||
/** This is the extended channel mode API,
|
||||
* see also https://www.unrealircd.org/docs/Dev:Channel_Mode_API
|
||||
* for more information.
|
||||
* @defgroup ChannelModeAPI Channel mode API
|
||||
* @{
|
||||
*/
|
||||
|
@ -63,7 +63,7 @@ int (*find_shun)(Client *client);
|
||||
int(*find_spamfilter_user)(Client *client, int flags);
|
||||
TKL *(*find_qline)(Client *client, char *nick, int *ishold);
|
||||
TKL *(*find_tkline_match_zap)(Client *client);
|
||||
void (*tkl_stats)(Client *client, int type, char *para);
|
||||
void (*tkl_stats)(Client *client, int type, char *para, int *cnt);
|
||||
void (*tkl_sync)(Client *client);
|
||||
void (*cmd_tkl)(Client *client, MessageTag *mtags, int parc, char *parv[]);
|
||||
int (*place_host_ban)(Client *client, BanAction action, char *reason, long duration);
|
||||
|
@ -240,4 +240,5 @@ void SetupEvents(void)
|
||||
EventAdd(NULL, "check_deadsockets", check_deadsockets, NULL, 1000, 0);
|
||||
EventAdd(NULL, "handshake_timeout", handshake_timeout, NULL, 1000, 0);
|
||||
EventAdd(NULL, "try_connections", try_connections, NULL, 2000, 0);
|
||||
EventAdd(NULL, "tls_check_expiry", tls_check_expiry, NULL, (86400/2)*1000, 0);
|
||||
}
|
||||
|
@ -25,7 +25,9 @@
|
||||
*/
|
||||
#include "unrealircd.h"
|
||||
|
||||
/** This is the message tags API (message-tags)
|
||||
/** This is the message tags API (message-tags).
|
||||
* For an overview of message tags in general (not the API)
|
||||
* see https://www.unrealircd.org/docs/Message_tags
|
||||
* @defgroup MessagetagAPI Message tag API
|
||||
* @{
|
||||
*/
|
||||
|
@ -28,7 +28,16 @@
|
||||
long opermode = 0;
|
||||
/** Lazy way to signal an SAJOIN MODE */
|
||||
long sajoinmode = 0;
|
||||
/** List of all channels on the server */
|
||||
/** List of all channels on the server.
|
||||
* @ingroup ListFunctions
|
||||
* @section channels_example Example
|
||||
* This code will list all channels on the network.
|
||||
* @code
|
||||
* sendnotice(client, "List of all channels:");
|
||||
* for (channel = channels; channel; channel=channel->nextch)
|
||||
* sendnotice(client, "Channel %s", channel->name);
|
||||
* @endcode
|
||||
*/
|
||||
Channel *channels = NULL;
|
||||
|
||||
/* some buffers for rebuilding channel/nick lists with comma's */
|
||||
@ -1144,7 +1153,7 @@ void set_channel_mlock(Client *client, Channel *channel, const char *newmlock, i
|
||||
* @in modebuf_in Buffer pointing to mode characters (eg: +snk-l)
|
||||
* @in parabuf_in Buffer pointing to all parameters (eg: key 123)
|
||||
* @retval Returns 1 if we have valid data to return, 0 if at end of mode line.
|
||||
* @section ex1 Example:
|
||||
* @section parse_chanmode_example Example:
|
||||
* @code
|
||||
* ParseMode pm;
|
||||
* int ret;
|
||||
|
102
src/conf.c
102
src/conf.c
@ -69,7 +69,8 @@ static int _conf_log (ConfigFile *conf, ConfigEntry *ce);
|
||||
static int _conf_alias (ConfigFile *conf, ConfigEntry *ce);
|
||||
static int _conf_help (ConfigFile *conf, ConfigEntry *ce);
|
||||
static int _conf_offchans (ConfigFile *conf, ConfigEntry *ce);
|
||||
static int _conf_sni (ConfigFile *conf, ConfigEntry *ce);
|
||||
static int _conf_sni (ConfigFile *conf, ConfigEntry *ce);
|
||||
static int _conf_security_group (ConfigFile *conf, ConfigEntry *ce);
|
||||
|
||||
/*
|
||||
* Validation commands
|
||||
@ -101,7 +102,8 @@ static int _test_log (ConfigFile *conf, ConfigEntry *ce);
|
||||
static int _test_alias (ConfigFile *conf, ConfigEntry *ce);
|
||||
static int _test_help (ConfigFile *conf, ConfigEntry *ce);
|
||||
static int _test_offchans (ConfigFile *conf, ConfigEntry *ce);
|
||||
static int _test_sni (ConfigFile *conf, ConfigEntry *ce);
|
||||
static int _test_sni (ConfigFile *conf, ConfigEntry *ce);
|
||||
static int _test_security_group (ConfigFile *conf, ConfigEntry *ce);
|
||||
|
||||
/* This MUST be alphabetized */
|
||||
static ConfigCommand _ConfigCommands[] = {
|
||||
@ -126,6 +128,7 @@ static ConfigCommand _ConfigCommands[] = {
|
||||
{ "oper", _conf_oper, _test_oper },
|
||||
{ "operclass", _conf_operclass, _test_operclass },
|
||||
{ "require", _conf_require, _test_require },
|
||||
{ "security-group", _conf_security_group, _test_security_group },
|
||||
{ "set", _conf_set, _test_set },
|
||||
{ "sni", _conf_sni, _test_sni },
|
||||
{ "tld", _conf_tld, _test_tld },
|
||||
@ -254,6 +257,7 @@ ConfigItem_include *conf_include = NULL;
|
||||
ConfigItem_blacklist_module *conf_blacklist_module = NULL;
|
||||
ConfigItem_help *conf_help = NULL;
|
||||
ConfigItem_offchans *conf_offchans = NULL;
|
||||
SecurityGroup *securitygroups = NULL;
|
||||
|
||||
MODVAR Configuration iConf;
|
||||
MODVAR Configuration tempiConf;
|
||||
@ -1902,6 +1906,7 @@ void postconf(void)
|
||||
postconf_fixes();
|
||||
do_weird_shun_stuff();
|
||||
isupport_init(); /* for all the 005 values that changed.. */
|
||||
tls_check_expiry(NULL);
|
||||
}
|
||||
|
||||
int isanyserverlinked(void)
|
||||
@ -2072,6 +2077,7 @@ int init_conf(char *rootconf, int rehash)
|
||||
callbacks_switchover();
|
||||
efunctions_switchover();
|
||||
set_targmax_defaults();
|
||||
set_security_group_defaults();
|
||||
if (rehash)
|
||||
{
|
||||
Hook *h;
|
||||
@ -5350,6 +5356,8 @@ int _conf_allow(ConfigFile *conf, ConfigEntry *ce)
|
||||
allow->flags.useip = 1;
|
||||
else if (!strcmp(cepp->ce_varname, "ssl") || !strcmp(cepp->ce_varname, "tls"))
|
||||
allow->flags.tls = 1;
|
||||
else if (!strcmp(cepp->ce_varname, "reject-on-auth-failure"))
|
||||
allow->flags.reject_on_auth_failure = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5545,6 +5553,8 @@ int _test_allow(ConfigFile *conf, ConfigEntry *ce)
|
||||
{}
|
||||
else if (!strcmp(cepp->ce_varname, "ssl") || !strcmp(cepp->ce_varname, "tls"))
|
||||
{}
|
||||
else if (!strcmp(cepp->ce_varname, "reject-on-auth-failure"))
|
||||
{}
|
||||
else if (!strcmp(cepp->ce_varname, "sasl"))
|
||||
{
|
||||
config_error("%s:%d: The option allow::options::sasl no longer exists. "
|
||||
@ -9317,7 +9327,7 @@ int _test_offchans(ConfigFile *conf, ConfigEntry *ce)
|
||||
return 1;
|
||||
}
|
||||
|
||||
config_warn("set::oficial-channels is deprecated. It often does not do what you want. "
|
||||
config_warn("set::official-channels is deprecated. It often does not do what you want. "
|
||||
"You're better of creating a channel, setting all modes, topic, etc. to your liking "
|
||||
"and then making the channel permanent (MODE #channel +P). "
|
||||
"The channel will then be stored in a database to preserve it between restarts.");
|
||||
@ -10044,6 +10054,91 @@ int _test_deny(ConfigFile *conf, ConfigEntry *ce)
|
||||
return errors;
|
||||
}
|
||||
|
||||
int _test_security_group(ConfigFile *conf, ConfigEntry *ce)
|
||||
{
|
||||
int errors = 0;
|
||||
ConfigEntry *cep;
|
||||
|
||||
if (!ce->ce_vardata)
|
||||
{
|
||||
config_error("%s:%i: security-group block needs a name, eg: security-group web-users {",
|
||||
ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
|
||||
errors++;
|
||||
} else {
|
||||
if (!strcasecmp(ce->ce_vardata, "unknown-users"))
|
||||
{
|
||||
config_error("%s:%i: The 'unknown-users' group is a special group that is the "
|
||||
"inverse of 'known-users', you cannot create or adjust it in the "
|
||||
"config file, as it is created automatically by UnrealIRCd.",
|
||||
ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
|
||||
errors++;
|
||||
return errors;
|
||||
}
|
||||
if (!security_group_valid_name(ce->ce_vardata))
|
||||
{
|
||||
config_error("%s:%i: security-group block name '%s' contains invalid characters or is too long. "
|
||||
"Only letters, numbers, underscore and hyphen are allowed.",
|
||||
ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
for (cep = ce->ce_entries; cep; cep = cep->ce_next)
|
||||
{
|
||||
if (!strcmp(cep->ce_varname, "webirc"))
|
||||
{
|
||||
CheckNull(cep);
|
||||
} else
|
||||
if (!strcmp(cep->ce_varname, "identified"))
|
||||
{
|
||||
CheckNull(cep);
|
||||
} else
|
||||
if (!strcmp(cep->ce_varname, "reputation-score"))
|
||||
{
|
||||
int v;
|
||||
CheckNull(cep);
|
||||
v = atoi(cep->ce_vardata);
|
||||
if ((v < 1) || (v > 10000))
|
||||
{
|
||||
config_error("%s:%i: security-group::reputation-score needs to be a value of 1-10000",
|
||||
cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
|
||||
errors++;
|
||||
}
|
||||
} else
|
||||
{
|
||||
config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
|
||||
"security-group", cep->ce_varname);
|
||||
errors++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int _conf_security_group(ConfigFile *conf, ConfigEntry *ce)
|
||||
{
|
||||
ConfigEntry *cep;
|
||||
SecurityGroup *s = add_security_group(ce->ce_vardata, 1);
|
||||
|
||||
for (cep = ce->ce_entries; cep; cep = cep->ce_next)
|
||||
{
|
||||
if (!strcmp(cep->ce_varname, "webirc"))
|
||||
s->webirc = config_checkval(cep->ce_vardata, CFG_YESNO);
|
||||
else if (!strcmp(cep->ce_varname, "identified"))
|
||||
s->identified = config_checkval(cep->ce_vardata, CFG_YESNO);
|
||||
else if (!strcmp(cep->ce_varname, "reputation-score"))
|
||||
s->reputation_score = atoi(cep->ce_vardata);
|
||||
else if (!strcmp(cep->ce_varname, "priority"))
|
||||
{
|
||||
s->priority = atoi(cep->ce_vardata);
|
||||
DelListItem(s, securitygroups);
|
||||
AddListItemPrio(s, securitygroups, s->priority);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef USE_LIBCURL
|
||||
static void conf_download_complete(const char *url, const char *file, const char *errorbuf, int cached, void *inc_key)
|
||||
{
|
||||
@ -10641,6 +10736,7 @@ void link_generator(void)
|
||||
" outgoing {\n"
|
||||
" hostname %s;\n"
|
||||
" port %d;\n"
|
||||
" options { tls; autoconnect; }\n"
|
||||
" }\n"
|
||||
" password \"%s\" { spkifp; }\n"
|
||||
" class servers;\n"
|
||||
|
@ -13,17 +13,6 @@ extern void StartUnrealAgain(void);
|
||||
|
||||
extern char *getosname(void);
|
||||
|
||||
|
||||
time_t get_file_time(char *fname)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(fname, &st) != 0)
|
||||
return 0;
|
||||
|
||||
return (time_t)st.st_ctime;
|
||||
}
|
||||
|
||||
char *find_best_coredump(void)
|
||||
{
|
||||
static char best_fname[512];
|
||||
@ -560,17 +549,6 @@ int running_interactive(void)
|
||||
#define REPORT_ASK 0
|
||||
#define REPORT_AUTO 1
|
||||
|
||||
|
||||
int getfilesize(char *fname)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(fname, &st) != 0)
|
||||
return -1;
|
||||
|
||||
return (int)st.st_size;
|
||||
}
|
||||
|
||||
#define CRASH_REPORT_HOST "crash.unrealircd.org"
|
||||
|
||||
SSL_CTX *crashreport_init_ssl(void)
|
||||
@ -614,7 +592,7 @@ int crashreport_send(char *fname)
|
||||
int xfr = 0;
|
||||
char *errstr = NULL;
|
||||
|
||||
filesize = getfilesize(fname);
|
||||
filesize = get_file_size(fname);
|
||||
if (filesize < 0)
|
||||
return 0;
|
||||
|
||||
|
40
src/hash.c
40
src/hash.c
@ -500,11 +500,21 @@ Client *hash_find_server(const char *server, Client *def)
|
||||
return def;
|
||||
}
|
||||
|
||||
/** Find a client, user (person), server or channel by name.
|
||||
* If you are looking for "other find functions", then the alphabetical index of functions
|
||||
* at 'f' is your best bet: https://www.unrealircd.org/api/5/globals_func_f.html#index_f
|
||||
* @defgroup FindFunctions Find functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Find a client by name.
|
||||
* This searches in the list of all types of clients, user/person, servers or an unregistered clients.
|
||||
* If you know what type of client to search for, then use find_server() or find_person() instead!
|
||||
* @param name The name to search for (eg: "nick" or "irc.example.net")
|
||||
* @param requester The client that is searching for this name
|
||||
* @note If 'requester' is a server or NULL, then we also check
|
||||
* the ID table, otherwise not.
|
||||
* @returns If the client is found then the Client is returned, otherwise NULL.
|
||||
*/
|
||||
Client *find_client(char *name, Client *requester)
|
||||
{
|
||||
@ -525,6 +535,7 @@ Client *find_client(char *name, Client *requester)
|
||||
* @param requester The client searching for the name.
|
||||
* @note If 'requester' is a server or NULL, then we also check
|
||||
* the ID table, otherwise not.
|
||||
* @returns If the server is found then the Client is returned, otherwise NULL.
|
||||
*/
|
||||
Client *find_server(char *name, Client *requester)
|
||||
{
|
||||
@ -539,13 +550,14 @@ Client *find_server(char *name, Client *requester)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Find a person.
|
||||
/** Find a person (a user).
|
||||
* @param name The name to search for (eg: "nick" or "001ABCDEFG")
|
||||
* @param requester The client that is searching for this name
|
||||
* @note If 'requester' is a server or NULL, then we also check
|
||||
* the ID table, otherwise not.
|
||||
* @returns If the user is found then the Client is returned, otherwise NULL.
|
||||
*/
|
||||
Client *find_person(char *name, Client *requester)
|
||||
Client *find_person(char *name, Client *requester) /* TODO: this should have been called find_user() to be consistent */
|
||||
{
|
||||
Client *c2ptr;
|
||||
|
||||
@ -558,10 +570,12 @@ Client *find_person(char *name, Client *requester)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* hash_find_channel
|
||||
/** Find a channel by name.
|
||||
* @param name The channel name to search for
|
||||
* @param default_result If the channel is not found, this value is returned.
|
||||
* @returns If the channel exists then the Channel is returned, otherwise default_result is returned.
|
||||
*/
|
||||
Channel *hash_find_channel(char *name, Channel *channel)
|
||||
Channel *find_channel(char *name, Channel *default_result)
|
||||
{
|
||||
unsigned int hashv;
|
||||
Channel *tmp;
|
||||
@ -573,9 +587,11 @@ Channel *hash_find_channel(char *name, Channel *channel)
|
||||
if (smycmp(name, tmp->chname) == 0)
|
||||
return tmp;
|
||||
}
|
||||
return channel;
|
||||
return default_result;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
Channel *hash_get_chan_bucket(uint64_t hashv)
|
||||
{
|
||||
if (hashv > CHAN_HASH_TABLE_SIZE)
|
||||
@ -963,18 +979,14 @@ EVENT(throttling_check_expire)
|
||||
char *p = serveropts + strlen(serveropts);
|
||||
Module *mi;
|
||||
t = TStime();
|
||||
if (!Hooks[17] && strchr(serveropts, 'm'))
|
||||
if (!Hooks[HOOKTYPE_USERMSG] && strchr(serveropts, 'm'))
|
||||
{ p = strchr(serveropts, 'm'); *p = '\0'; }
|
||||
if (!Hooks[18] && strchr(serveropts, 'M'))
|
||||
if (!Hooks[HOOKTYPE_CHANMSG] && strchr(serveropts, 'M'))
|
||||
{ p = strchr(serveropts, 'M'); *p = '\0'; }
|
||||
if (!Hooks[49] && !Hooks[51] && strchr(serveropts, 'R'))
|
||||
{ p = strchr(serveropts, 'R'); *p = '\0'; }
|
||||
if (Hooks[17] && !strchr(serveropts, 'm'))
|
||||
if (Hooks[HOOKTYPE_USERMSG] && !strchr(serveropts, 'm'))
|
||||
*p++ = 'm';
|
||||
if (Hooks[18] && !strchr(serveropts, 'M'))
|
||||
if (Hooks[HOOKTYPE_CHANMSG] && !strchr(serveropts, 'M'))
|
||||
*p++ = 'M';
|
||||
if ((Hooks[49] || Hooks[51]) && !strchr(serveropts, 'R'))
|
||||
*p++ = 'R';
|
||||
*p = '\0';
|
||||
for (mi = Modules; mi; mi = mi->next)
|
||||
if (!(mi->options & MOD_OPT_OFFICIAL))
|
||||
|
42
src/ircd.c
42
src/ircd.c
@ -96,7 +96,7 @@ void s_die()
|
||||
#else
|
||||
unload_all_modules();
|
||||
unlink(conf_files ? conf_files->pid_file : IRCD_PIDFILE);
|
||||
exit(-1);
|
||||
exit(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -269,14 +269,7 @@ EVENT(garbage_collect)
|
||||
loop.do_garbage_collect = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** try_connections
|
||||
**
|
||||
** Scan through configuration and try new connections.
|
||||
** Returns the calendar time when the next call to this
|
||||
** function should be made latest. (No harm done if this
|
||||
** is called earlier or later...)
|
||||
*/
|
||||
/** Perform autoconnect to servers that are not linked yet. */
|
||||
EVENT(try_connections)
|
||||
{
|
||||
ConfigItem_link *aconf;
|
||||
@ -287,7 +280,7 @@ EVENT(try_connections)
|
||||
|
||||
for (aconf = conf_link; aconf; aconf = aconf->next)
|
||||
{
|
||||
/* We're only interested in autoconnect blocks that are valid (and ignore temporary link blocks) */
|
||||
/* We're only interested in autoconnect blocks that are valid. Also, we ignore temporary link blocks. */
|
||||
if (!(aconf->outgoing.options & CONNECT_AUTO) || !aconf->outgoing.hostname || (aconf->flag.temporary == 1))
|
||||
continue;
|
||||
|
||||
@ -296,6 +289,7 @@ EVENT(try_connections)
|
||||
/* Only do one connection attempt per <connfreq> seconds (for the same server) */
|
||||
if ((aconf->hold > TStime()))
|
||||
continue;
|
||||
|
||||
confrq = class->connfreq;
|
||||
aconf->hold = TStime() + confrq;
|
||||
|
||||
@ -380,8 +374,7 @@ int match_tkls(Client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Time out connections that are still in handshake.
|
||||
*/
|
||||
/** Time out connections that are still in handshake. */
|
||||
EVENT(handshake_timeout)
|
||||
{
|
||||
Client *client, *next;
|
||||
@ -466,11 +459,7 @@ void check_ping(Client *client)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check registered connections for PING timeout.
|
||||
* XXX: also does some other stuff still, need to sort this. --nenolod
|
||||
* Perhaps it would be wise to ping servers as well mr nenolod, just an idea -- Syzop
|
||||
*/
|
||||
/** Check registered connections for ping timeout. Also, check for server bans. */
|
||||
EVENT(check_pings)
|
||||
{
|
||||
Client *client, *next;
|
||||
@ -493,6 +482,7 @@ EVENT(check_pings)
|
||||
/* done */
|
||||
}
|
||||
|
||||
/** Check for clients that are pending to be terminated */
|
||||
EVENT(check_deadsockets)
|
||||
{
|
||||
Client *client, *next;
|
||||
@ -550,18 +540,10 @@ static int bad_command(const char *argv0)
|
||||
if (!argv0)
|
||||
argv0 = "unrealircd";
|
||||
|
||||
(void)printf
|
||||
("Usage: %s [-f <config>] [-F]\n"
|
||||
"\n"
|
||||
"UnrealIRCd\n"
|
||||
" -f <config> Load configuration from <config> instead of the default\n"
|
||||
" (%s).\n"
|
||||
" -F Don't fork() when starting up. Use this when running\n"
|
||||
" UnrealIRCd under gdb or when playing around with settings\n"
|
||||
" on a non-production setup.\n"
|
||||
"\n",
|
||||
argv0, CONFIGFILE);
|
||||
(void)printf("Server not started\n\n");
|
||||
printf("ERROR: Incorrect command line argument encountered.\n"
|
||||
"This is the unrealircd BINARY. End-users should NOT call this binary directly.\n"
|
||||
"Please run the SCRIPT instead: %s/unrealircd\n", SCRIPTDIR);
|
||||
printf("Server not started\n\n");
|
||||
#else
|
||||
if (!IsService) {
|
||||
MessageBox(NULL,
|
||||
@ -1098,7 +1080,7 @@ int InitUnrealIRCd(int argc, char *argv[])
|
||||
bootopt |= BOOT_TTY;
|
||||
break;
|
||||
case 'v':
|
||||
(void)printf("%s build %s\n", version, buildid);
|
||||
(void)printf("%s\n", version);
|
||||
#else
|
||||
case 'v':
|
||||
if (!IsService) {
|
||||
|
56
src/misc.c
56
src/misc.c
@ -810,7 +810,6 @@ void exit_client(Client *client, MessageTag *recv_mtags, char *comment)
|
||||
exit_one_client(client, recv_mtags, comment);
|
||||
|
||||
free_message_tags(mtags_generated);
|
||||
|
||||
}
|
||||
|
||||
/** Initialize the (quite useless) IRC statistics */
|
||||
@ -851,7 +850,7 @@ void verify_opercount(Client *orig, char *tag)
|
||||
int valid_host(char *host)
|
||||
{
|
||||
char *p;
|
||||
|
||||
|
||||
if (strlen(host) > HOSTLEN)
|
||||
return 0; /* too long hosts are invalid too */
|
||||
|
||||
@ -1032,7 +1031,7 @@ int is_autojoin_chan(char *chname)
|
||||
if (!strcasecmp(name, chname))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if (AUTO_JOIN_CHANS)
|
||||
{
|
||||
strlcpy(buf, AUTO_JOIN_CHANS, sizeof(buf));
|
||||
@ -1069,7 +1068,7 @@ int char_to_channelflag(char c)
|
||||
int mixed_network(void)
|
||||
{
|
||||
Client *client;
|
||||
|
||||
|
||||
list_for_each_entry(client, &server_list, special_node)
|
||||
{
|
||||
if (!IsServer(client) || IsULine(client))
|
||||
@ -1083,7 +1082,7 @@ int mixed_network(void)
|
||||
void unreal_delete_masks(ConfigItem_mask *m)
|
||||
{
|
||||
ConfigItem_mask *m_next;
|
||||
|
||||
|
||||
for (; m; m = m_next)
|
||||
{
|
||||
m_next = m->next;
|
||||
@ -1104,7 +1103,7 @@ static void unreal_add_mask(ConfigItem_mask **head, ConfigEntry *ce)
|
||||
safe_strdup(m->mask, ce->ce_vardata);
|
||||
else
|
||||
safe_strdup(m->mask, ce->ce_varname);
|
||||
|
||||
|
||||
add_ListItem((ListStruct *)m, (ListStruct **)head);
|
||||
}
|
||||
|
||||
@ -1137,7 +1136,7 @@ int unreal_mask_match(Client *client, ConfigItem_mask *m)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1191,7 +1190,7 @@ int swhois_add(Client *client, char *tag, int priority, char *swhois, Client *fr
|
||||
safe_strdup(s->setby, tag);
|
||||
s->priority = priority;
|
||||
AddListItemPrio(s, client->user->swhois, s->priority);
|
||||
|
||||
|
||||
sendto_server(skip, 0, PROTO_EXTSWHOIS, NULL, ":%s SWHOIS %s :%s",
|
||||
from->id, client->id, swhois);
|
||||
|
||||
@ -1215,11 +1214,11 @@ int swhois_delete(Client *client, char *tag, char *swhois, Client *from, Client
|
||||
{
|
||||
SWhois *s, *s_next;
|
||||
int ret = -1; /* default to 'not found' */
|
||||
|
||||
|
||||
for (s = client->user->swhois; s; s = s_next)
|
||||
{
|
||||
s_next = s->next;
|
||||
|
||||
|
||||
/* If ( same swhois or "*" ) AND same tag */
|
||||
if ( ((!strcmp(s->line, swhois) || !strcmp(swhois, "*")) &&
|
||||
!strcmp(s->setby, tag)))
|
||||
@ -1234,7 +1233,7 @@ int swhois_delete(Client *client, char *tag, char *swhois, Client *from, Client
|
||||
|
||||
sendto_server(skip, PROTO_EXTSWHOIS, 0, NULL, ":%s SWHOIS %s - %s %d :%s",
|
||||
from->id, client->id, tag, 0, swhois);
|
||||
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
@ -1893,6 +1892,41 @@ int filename_has_suffix(const char *fname, const char *suffix)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Check if the specified file exists */
|
||||
int file_exists(char *file)
|
||||
{
|
||||
FILE *fd;
|
||||
|
||||
fd = fopen(file, "r");
|
||||
if (!fd)
|
||||
return 0;
|
||||
|
||||
fclose(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Get the file creation time */
|
||||
time_t get_file_time(char *fname)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(fname, &st) != 0)
|
||||
return 0;
|
||||
|
||||
return (time_t)st.st_ctime;
|
||||
}
|
||||
|
||||
/** Get the size of a file */
|
||||
long get_file_size(char *fname)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(fname, &st) != 0)
|
||||
return -1;
|
||||
|
||||
return (long)st.st_size;
|
||||
}
|
||||
|
||||
/** Add a line to a MultiLine list */
|
||||
void addmultiline(MultiLine **l, char *line)
|
||||
{
|
||||
|
@ -1643,11 +1643,33 @@ void mm_parse_c_file(int argc, char *args[])
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void mm_self_test(void)
|
||||
{
|
||||
char name[512];
|
||||
snprintf(name, sizeof(name), "%s/src/modules/third", BUILDDIR);
|
||||
if (file_exists(name))
|
||||
return;
|
||||
if (!file_exists(BUILDDIR))
|
||||
{
|
||||
fprintf(stderr, "ERROR: Directory %s does not exist.\n"
|
||||
"The UnrealIRCd source is required for the module manager to work!\n",
|
||||
BUILDDIR);
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: Directory %s exists, but %s does not.\n"
|
||||
"The UnrealIRCd source is required for the module manager to work.\n"
|
||||
"It seems you only have a partial build directory??\n",
|
||||
BUILDDIR, name);
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void modulemanager(int argc, char *args[])
|
||||
{
|
||||
if (!args[0])
|
||||
mm_usage();
|
||||
|
||||
mm_self_test();
|
||||
|
||||
/* The following operations do not require reading
|
||||
* of the repository list and are always available:
|
||||
*/
|
||||
|
@ -34,7 +34,6 @@ Cmode_t EXTCMODE_SECUREONLY;
|
||||
|
||||
int secureonly_check_join(Client *client, Channel *channel, char *key, char *parv[]);
|
||||
int secureonly_channel_sync (Channel *channel, int merge, int removetheirs, int nomode);
|
||||
int secureonly_send_channel(Client *client, Channel *channel);
|
||||
int secureonly_check_secure(Channel *channel);
|
||||
int secureonly_check_sajoin(Client *target, Channel *channel, Client *requester);
|
||||
int secureonly_specialcheck(Client *client, Channel *channel, char *parv[]);
|
||||
@ -58,7 +57,6 @@ MOD_INIT()
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CAN_JOIN, 0, secureonly_check_join);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CHANNEL_SYNCED, 0, secureonly_channel_sync);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_IS_CHANNEL_SECURE, 0, secureonly_check_secure);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_SEND_CHANNEL, 0, secureonly_send_channel);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CAN_SAJOIN, 0, secureonly_check_sajoin);
|
||||
|
||||
|
||||
@ -165,15 +163,6 @@ int secureonly_channel_sync(Channel *channel, int merge, int removetheirs, int n
|
||||
return 0;
|
||||
}
|
||||
|
||||
int secureonly_send_channel(Client *client, Channel *channel)
|
||||
{
|
||||
if (IsSecureOnly(channel))
|
||||
if (!IsSecure(client))
|
||||
return HOOK_DENY;
|
||||
|
||||
return HOOK_CONTINUE;
|
||||
}
|
||||
|
||||
int secureonly_check_sajoin(Client *target, Channel *channel, Client *requester)
|
||||
{
|
||||
if (IsSecureOnly(channel) && !IsSecure(target))
|
||||
|
@ -67,8 +67,6 @@ UCounter *ucounter = NULL;
|
||||
|
||||
#define MSG_THROTTLE "THROTTLE"
|
||||
|
||||
#define GetReputation(client) (moddata_client_get(client, "reputation") ? atoi(moddata_client_get(client, "reputation")) : 0)
|
||||
|
||||
/* Forward declarations */
|
||||
int ct_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
|
||||
int ct_config_posttest(int *errs);
|
||||
|
@ -34,7 +34,7 @@ INCLUDES = ../../include/channel.h \
|
||||
R_MODULES= \
|
||||
join.so quiet.so nickchange.so inchannel.so realname.so \
|
||||
account.so operclass.so certfp.so textban.so msgbypass.so \
|
||||
timedban.so partmsg.so
|
||||
timedban.so partmsg.so securitygroup.so
|
||||
|
||||
MODULES=$(R_MODULES)
|
||||
MODULEFLAGS=@MODULEFLAGS@
|
||||
@ -102,3 +102,7 @@ timedban.so: timedban.c $(INCLUDES)
|
||||
partmsg.so: partmsg.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
|
||||
-o partmsg.so partmsg.c
|
||||
|
||||
securitygroup.so: securitygroup.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
|
||||
-o securitygroup.so securitygroup.c
|
||||
|
141
src/modules/extbans/securitygroup.c
Normal file
141
src/modules/extbans/securitygroup.c
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Extended ban to ban based on security groups such as "unknown-users"
|
||||
* (C) Copyright 2020 Bram Matthys (Syzop) and the UnrealIRCd team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 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
|
||||
= {
|
||||
"extbans/securitygroup",
|
||||
"4.2",
|
||||
"ExtBan ~G - Ban based on security-group",
|
||||
"UnrealIRCd Team",
|
||||
"unrealircd-5",
|
||||
};
|
||||
|
||||
/* Forward declarations */
|
||||
char *extban_securitygroup_conv_param(char *para);
|
||||
int extban_securitygroup_is_ok(Client *client, Channel *channel, char *para, int checkt, int what, int what2);
|
||||
int extban_securitygroup_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg);
|
||||
|
||||
/** Called upon module init */
|
||||
MOD_INIT()
|
||||
{
|
||||
ExtbanInfo req;
|
||||
|
||||
req.flag = 'G';
|
||||
req.conv_param = extban_securitygroup_conv_param;
|
||||
req.is_ok = extban_securitygroup_is_ok;
|
||||
req.is_banned = extban_securitygroup_is_banned;
|
||||
req.options = EXTBOPT_INVEX|EXTBOPT_TKL;
|
||||
if (!ExtbanAdd(modinfo->handle, req))
|
||||
{
|
||||
config_error("could not register extended ban type ~G");
|
||||
return MOD_FAILED;
|
||||
}
|
||||
|
||||
MARK_AS_OFFICIAL_MODULE(modinfo);
|
||||
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
/** Called upon module load */
|
||||
MOD_LOAD()
|
||||
{
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
/** Called upon unload */
|
||||
MOD_UNLOAD()
|
||||
{
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
/* Helper function for extban_securitygroup_is_ok() and extban_securitygroup_conv_param()
|
||||
* to do ban validation.
|
||||
*/
|
||||
int extban_securitygroup_generic(char *para, int strict)
|
||||
{
|
||||
char *mask;
|
||||
|
||||
mask = para+3;
|
||||
|
||||
/* ! at the start means negative match */
|
||||
if (*mask == '!')
|
||||
mask++;
|
||||
|
||||
/* Check if the rest of the security group name is valid */
|
||||
if (strict)
|
||||
{
|
||||
if (!security_group_exists(mask))
|
||||
return 0; /* security group does not exist */
|
||||
} else {
|
||||
if (!security_group_valid_name(mask))
|
||||
return 0; /* invalid characters or too long */
|
||||
}
|
||||
|
||||
if (!*mask)
|
||||
return 0; /* don't allow "~G:" nor "~G:!" */
|
||||
|
||||
if (strlen(mask) > SECURITYGROUPLEN + 3)
|
||||
mask[SECURITYGROUPLEN + 3] = '\0';
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int extban_securitygroup_is_ok(Client *client, Channel *channel, char *para, int checkt, int what, int what2)
|
||||
{
|
||||
if (MyUser(client) && (what == MODE_ADD) && (checkt == EXBCHK_PARAM))
|
||||
{
|
||||
char banbuf[SECURITYGROUPLEN+8];
|
||||
strlcpy(banbuf, para, sizeof(banbuf));
|
||||
if (!extban_securitygroup_generic(banbuf, 1))
|
||||
{
|
||||
SecurityGroup *s;
|
||||
sendnotice(client, "ERROR: Unknown security-group '%s'. Syntax: +b ~G:securitygroup or +b ~G:!securitygroup", para+3);
|
||||
sendnotice(client, "Available security groups:");
|
||||
for (s = securitygroups; s; s = s->next)
|
||||
sendnotice(client, "%s", s->name);
|
||||
sendnotice(client, "unknown-users");
|
||||
sendnotice(client, "End of security group list.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Security group extban - conv_param */
|
||||
char *extban_securitygroup_conv_param(char *para)
|
||||
{
|
||||
static char retbuf[SECURITYGROUPLEN + 8];
|
||||
|
||||
strlcpy(retbuf, para, sizeof(retbuf));
|
||||
if (!extban_securitygroup_generic(retbuf, 0))
|
||||
return NULL;
|
||||
|
||||
return retbuf;
|
||||
}
|
||||
|
||||
/** Is the user banned by ~G:something ? */
|
||||
int extban_securitygroup_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg)
|
||||
{
|
||||
char *ban = banin+3;
|
||||
|
||||
if (*ban == '!')
|
||||
return !user_allowed_by_security_group_name(client, ban+1);
|
||||
return user_allowed_by_security_group_name(client, ban);
|
||||
}
|
@ -1367,6 +1367,9 @@ int paracount_for_chanmode_from_server(Client *client, u_int what, char mode)
|
||||
if (mode == '&')
|
||||
return 0; /* & indicates bounce, it is not an actual mode character */
|
||||
|
||||
if (mode == 'F')
|
||||
return (what == MODE_ADD) ? 1 : 0; /* Future compatibility */
|
||||
|
||||
/* If we end up here it means we have no idea if it is a parameter-eating or paramless
|
||||
* channel mode. That's actually pretty bad. This shouldn't happen since CHANMODES=
|
||||
* is sent since 2003 and the (often also required) EAUTH PROTOCTL is in there since 2010.
|
||||
|
@ -315,8 +315,8 @@ CMD_FUNC(cmd_nick_local)
|
||||
{
|
||||
client->local->since += 4; /* lag them up */
|
||||
sendnumeric(client, ERR_ERRONEUSNICKNAME, nick, tklban->ptr.nameban->reason);
|
||||
sendto_snomask(SNO_QLINE, "Forbidding Q-lined nick %s from %s.",
|
||||
nick, get_client_name(cptr, FALSE));
|
||||
sendto_snomask(SNO_QLINE, "Forbidding Q-lined nick %s from %s (%s)",
|
||||
nick, get_client_name(cptr, FALSE), tklban->ptr.nameban->reason);
|
||||
return; /* NICK message ignored */
|
||||
}
|
||||
/* fallthrough for ircops that have sufficient privileges */
|
||||
@ -866,6 +866,12 @@ int _register_user(Client *client, char *nick, char *username, char *umode, char
|
||||
/* Check G/Z lines before shuns -- kill before quite -- codemastr */
|
||||
if (find_tkline_match(client, 0))
|
||||
{
|
||||
if (!IsDead(client) && client->local->class)
|
||||
{
|
||||
/* Fix client count bug, in case that it was a hold such as via authprompt */
|
||||
client->local->class->clients--;
|
||||
client->local->class = NULL;
|
||||
}
|
||||
ircstats.is_ref++;
|
||||
return 0;
|
||||
}
|
||||
@ -892,7 +898,17 @@ int _register_user(Client *client, char *nick, char *username, char *umode, char
|
||||
{
|
||||
i = (*(h->func.intfunc))(client);
|
||||
if (i == HOOK_DENY)
|
||||
{
|
||||
if (!IsDead(client) && client->local->class)
|
||||
{
|
||||
/* Fix client count bug, in case that
|
||||
* the HOOK_DENY was only meant temporarily.
|
||||
*/
|
||||
client->local->class->clients--;
|
||||
client->local->class = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (i == HOOK_ALLOW)
|
||||
break;
|
||||
}
|
||||
@ -1316,12 +1332,9 @@ int AllowClient(Client *client, char *username)
|
||||
|
||||
for (aconf = conf_allow; aconf; aconf = aconf->next)
|
||||
{
|
||||
if (!aconf->hostname || !aconf->ip)
|
||||
goto attach;
|
||||
if (aconf->auth && !client->local->passwd && !moddata_client_get(client, "certfp"))
|
||||
continue;
|
||||
if (aconf->flags.tls && !IsSecure(client))
|
||||
continue;
|
||||
|
||||
if (hp && hp->h_name)
|
||||
{
|
||||
hname = hp->h_name;
|
||||
@ -1376,8 +1389,21 @@ int AllowClient(Client *client, char *username)
|
||||
goto attach;
|
||||
}
|
||||
|
||||
continue;
|
||||
continue; /* No match */
|
||||
attach:
|
||||
/* Check authentication */
|
||||
if (aconf->auth && !Auth_Check(client, aconf->auth, client->local->passwd))
|
||||
{
|
||||
/* Incorrect password/authentication - but was is it required? */
|
||||
if (aconf->flags.reject_on_auth_failure)
|
||||
{
|
||||
exit_client(client, NULL, iConf.reject_message_unauthorized);
|
||||
return 0;
|
||||
} else {
|
||||
continue; /* Continue (this is the default behavior) */
|
||||
}
|
||||
}
|
||||
|
||||
if (!aconf->flags.noident)
|
||||
SetUseIdent(client);
|
||||
if (!aconf->flags.useip && hp)
|
||||
@ -1393,12 +1419,6 @@ int AllowClient(Client *client, char *username)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (aconf->auth && !Auth_Check(client, aconf->auth, client->local->passwd))
|
||||
{
|
||||
/* Always continue if password was wrong. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!((aconf->class->clients + 1) > aconf->class->maxclients))
|
||||
{
|
||||
client->local->class = aconf->class;
|
||||
|
@ -343,9 +343,9 @@ CMD_FUNC(cmd_protoctl)
|
||||
(long long)(TStime() - t));
|
||||
snprintf(msg, sizeof(msg),
|
||||
"Rejecting link %s: our clock is %lld seconds ahead. "
|
||||
"Correct time is very important in IRC. Please "
|
||||
"verify the clock on both %s (them) and %s (us), "
|
||||
"fix it and then try linking again",
|
||||
"Please verify the clock on both %s (them) and %s (us). "
|
||||
"Correct time is very important for IRC servers, "
|
||||
"see https://www.unrealircd.org/docs/FAQ#fix-your-clock",
|
||||
get_client_name(client, TRUE),
|
||||
(long long)(TStime() - t),
|
||||
client->name, me.name);
|
||||
@ -359,9 +359,9 @@ CMD_FUNC(cmd_protoctl)
|
||||
(long long)(t - TStime()));
|
||||
snprintf(msg, sizeof(msg),
|
||||
"Rejecting link %s: our clock is %lld seconds behind. "
|
||||
"Correct time is very important in IRC. Please "
|
||||
"verify the clock on both %s (them) and %s (us), "
|
||||
"fix it and then try linking again",
|
||||
"Please verify the clock on both %s (them) and %s (us). "
|
||||
"Correct time is very important for IRC servers, "
|
||||
"see https://www.unrealircd.org/docs/FAQ#fix-your-clock",
|
||||
get_client_name(client, TRUE),
|
||||
(long long)(t - TStime()),
|
||||
client->name, me.name);
|
||||
|
@ -682,6 +682,107 @@ int count_reputation_records(void)
|
||||
return total;
|
||||
}
|
||||
|
||||
void reputation_channel_query(Client *client, Channel *channel)
|
||||
{
|
||||
Member *m;
|
||||
char buf[512];
|
||||
char tbuf[256];
|
||||
char **nicks;
|
||||
int *scores;
|
||||
int cnt = 0, i, j;
|
||||
ReputationEntry *e;
|
||||
|
||||
sendtxtnumeric(client, "Users and reputation scores for %s:", channel->chname);
|
||||
|
||||
/* Step 1: build a list of nicks and their reputation */
|
||||
nicks = safe_alloc((channel->users+1) * sizeof(char *));
|
||||
scores = safe_alloc((channel->users+1) * sizeof(int));
|
||||
for (m = channel->members; m; m = m->next)
|
||||
{
|
||||
nicks[cnt] = m->client->name;
|
||||
if (m->client->ip)
|
||||
{
|
||||
e = find_reputation_entry(m->client->ip);
|
||||
if (e)
|
||||
scores[cnt] = e->score;
|
||||
}
|
||||
if (++cnt > channel->users)
|
||||
{
|
||||
sendto_ops("[BUG] reputation_channel_query() expected %d users but %d (or more) were present in %s",
|
||||
channel->users, cnt, channel->chname);
|
||||
#ifdef DEBUGMODE
|
||||
abort();
|
||||
#endif
|
||||
break; /* safety net */
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 2: lazy selection sort */
|
||||
for (i = 0; i < cnt && nicks[i]; i++)
|
||||
{
|
||||
for (j = i+1; j < cnt && nicks[j]; j++)
|
||||
{
|
||||
if (scores[i] < scores[j])
|
||||
{
|
||||
char *nick_tmp;
|
||||
int score_tmp;
|
||||
nick_tmp = nicks[i];
|
||||
score_tmp = scores[i];
|
||||
nicks[i] = nicks[j];
|
||||
scores[i] = scores[j];
|
||||
nicks[j] = nick_tmp;
|
||||
scores[j] = score_tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 3: send the (ordered) list to the user */
|
||||
*buf = '\0';
|
||||
for (i = 0; i < cnt && nicks[i]; i++)
|
||||
{
|
||||
snprintf(tbuf, sizeof(tbuf), "%s\00314(%d)\003 ", nicks[i], scores[i]);
|
||||
if ((strlen(tbuf)+strlen(buf) > 400) || !nicks[i+1])
|
||||
{
|
||||
sendtxtnumeric(client, "%s%s", buf, tbuf);
|
||||
*buf = '\0';
|
||||
} else {
|
||||
strlcat(buf, tbuf, sizeof(buf));
|
||||
}
|
||||
}
|
||||
sendtxtnumeric(client, "End of list.");
|
||||
safe_free(nicks);
|
||||
safe_free(scores);
|
||||
}
|
||||
|
||||
void reputation_list_query(Client *client, int maxscore)
|
||||
{
|
||||
Client *target;
|
||||
ReputationEntry *e;
|
||||
|
||||
sendtxtnumeric(client, "Users and reputation scores <%d:", maxscore);
|
||||
|
||||
list_for_each_entry(target, &client_list, client_node)
|
||||
{
|
||||
int score = 0;
|
||||
|
||||
if (!IsUser(target) || IsULine(target) || !target->ip)
|
||||
continue;
|
||||
|
||||
e = find_reputation_entry(target->ip);
|
||||
if (e)
|
||||
score = e->score;
|
||||
if (score >= maxscore)
|
||||
continue;
|
||||
sendtxtnumeric(client, "%s!%s@%s [%s] \017(score: %d)",
|
||||
target->name,
|
||||
target->user->username,
|
||||
target->user->realhost,
|
||||
target->ip,
|
||||
score);
|
||||
}
|
||||
sendtxtnumeric(client, "End of list.");
|
||||
}
|
||||
|
||||
CMD_FUNC(reputation_user_cmd)
|
||||
{
|
||||
ReputationEntry *e;
|
||||
@ -709,13 +810,45 @@ CMD_FUNC(reputation_user_cmd)
|
||||
}
|
||||
sendnotice(client, "Current number of records (IP's): %d", count_reputation_records());
|
||||
sendnotice(client, "-");
|
||||
sendnotice(client, "For more specific information, use: /REPUTATION [nick|IP-address]");
|
||||
sendnotice(client, "Available commands:");
|
||||
sendnotice(client, "/REPUTATION [nick] Show reputation info about nick name");
|
||||
sendnotice(client, "/REPUTATION [ip] Show reputation info about IP address");
|
||||
sendnotice(client, "/REPUTATION [channel] List users in channel along with their reputation score");
|
||||
sendnotice(client, "/REPUTATION <NN List users with reputation score below value NN");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strchr(parv[1], '.') || strchr(parv[1], ':'))
|
||||
{
|
||||
ip = parv[1];
|
||||
} else
|
||||
if (parv[1][0] == '#')
|
||||
{
|
||||
Channel *channel = find_channel(parv[1], NULL);
|
||||
if (!channel)
|
||||
{
|
||||
sendnumeric(client, ERR_NOSUCHCHANNEL, parv[1]);
|
||||
return;
|
||||
}
|
||||
/* corner case: ircop without proper permissions and not in channel */
|
||||
if (!ValidatePermissionsForPath("channel:see:names:invisible",client,NULL,NULL,NULL) && !get_access(client,channel))
|
||||
{
|
||||
sendnumeric(client, ERR_NOTONCHANNEL, channel->chname);
|
||||
return;
|
||||
}
|
||||
reputation_channel_query(client, channel);
|
||||
return;
|
||||
} else
|
||||
if (parv[1][0] == '<')
|
||||
{
|
||||
int max = atoi(parv[1] + 1);
|
||||
if (max < 1)
|
||||
{
|
||||
sendnotice(client, "REPUTATION: Invalid search value specified. Use for example '/REPUTATION <5' to search on less-than-five");
|
||||
return;
|
||||
}
|
||||
reputation_list_query(client, max);
|
||||
return;
|
||||
} else {
|
||||
Client *target = find_person(parv[1], NULL);
|
||||
if (!target)
|
||||
|
@ -27,8 +27,6 @@ ModuleHeader MOD_HEADER = {
|
||||
"unrealircd-5",
|
||||
};
|
||||
|
||||
#define GetReputation(client) (moddata_client_get(client, "reputation") ? atoi(moddata_client_get(client, "reputation")) : 0)
|
||||
|
||||
typedef struct RestrictedCommand RestrictedCommand;
|
||||
struct RestrictedCommand {
|
||||
RestrictedCommand *prev, *next;
|
||||
|
@ -462,22 +462,25 @@ int stats_denylinkall(Client *client, char *para)
|
||||
|
||||
int stats_gline(Client *client, char *para)
|
||||
{
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_KILL, para);
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_ZAP, para);
|
||||
int cnt = 0;
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_KILL, para, &cnt);
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_ZAP, para, &cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stats_spamfilter(Client *client, char *para)
|
||||
{
|
||||
tkl_stats(client, TKL_SPAMF, para);
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_SPAMF, para);
|
||||
int cnt = 0;
|
||||
tkl_stats(client, TKL_SPAMF, para, &cnt);
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_SPAMF, para, &cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stats_except(Client *client, char *para)
|
||||
{
|
||||
tkl_stats(client, TKL_EXCEPTION, para);
|
||||
tkl_stats(client, TKL_EXCEPTION|TKL_GLOBAL, para);
|
||||
int cnt = 0;
|
||||
tkl_stats(client, TKL_EXCEPTION, para, &cnt);
|
||||
tkl_stats(client, TKL_EXCEPTION|TKL_GLOBAL, para, &cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -564,8 +567,9 @@ int stats_port(Client *client, char *para)
|
||||
|
||||
int stats_bannick(Client *client, char *para)
|
||||
{
|
||||
tkl_stats(client, TKL_NAME, para);
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_NAME, para);
|
||||
int cnt = 0;
|
||||
tkl_stats(client, TKL_NAME, para, &cnt);
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_NAME, para, &cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -699,8 +703,9 @@ int stats_denylinkauto(Client *client, char *para)
|
||||
|
||||
int stats_kline(Client *client, char *para)
|
||||
{
|
||||
tkl_stats(client, TKL_KILL, NULL);
|
||||
tkl_stats(client, TKL_ZAP, NULL);
|
||||
int cnt = 0;
|
||||
tkl_stats(client, TKL_KILL, NULL, &cnt);
|
||||
tkl_stats(client, TKL_ZAP, NULL, &cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -720,7 +725,8 @@ int stats_banrealname(Client *client, char *para)
|
||||
|
||||
int stats_sqline(Client *client, char *para)
|
||||
{
|
||||
tkl_stats(client, TKL_NAME|TKL_GLOBAL, para);
|
||||
int cnt = 0;
|
||||
tkl_stats(client, TKL_NAME|TKL_GLOBAL, para, &cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -741,7 +747,8 @@ int stats_chanrestrict(Client *client, char *para)
|
||||
|
||||
int stats_shun(Client *client, char *para)
|
||||
{
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_SHUN, para);
|
||||
int cnt = 0;
|
||||
tkl_stats(client, TKL_GLOBAL|TKL_SHUN, para, &cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -234,8 +234,8 @@ int targetfloodprot_can_send_to_channel(Client *client, Channel *channel, Member
|
||||
if (!MyUser(client))
|
||||
return HOOK_CONTINUE;
|
||||
|
||||
/* Really, only IRCOps override */
|
||||
if (IsOper(client) && ValidatePermissionsForPath("immune:target-flood",client,NULL,channel,NULL))
|
||||
/* IRCOps and U-Lines override */
|
||||
if (IsULine(client) || (IsOper(client) && ValidatePermissionsForPath("immune:target-flood",client,NULL,channel,NULL)))
|
||||
return HOOK_CONTINUE;
|
||||
|
||||
what = sendtypetowhat(sendtype);
|
||||
@ -280,8 +280,8 @@ int targetfloodprot_can_send_to_user(Client *client, Client *target, char **text
|
||||
if (!MyUser(target))
|
||||
return HOOK_CONTINUE;
|
||||
|
||||
/* Really, only IRCOps override */
|
||||
if (IsOper(client) && ValidatePermissionsForPath("immune:target-flood",client,target,NULL,NULL))
|
||||
/* IRCOps and U-Lines override */
|
||||
if (IsULine(client) || (IsOper(client) && ValidatePermissionsForPath("immune:target-flood",client,target,NULL,NULL)))
|
||||
return HOOK_CONTINUE;
|
||||
|
||||
what = sendtypetowhat(sendtype);
|
||||
|
@ -39,6 +39,8 @@ int tkl_config_test_ban(ConfigFile *, ConfigEntry *, int, int *);
|
||||
int tkl_config_run_ban(ConfigFile *, ConfigEntry *, int);
|
||||
int tkl_config_test_except(ConfigFile *, ConfigEntry *, int, int *);
|
||||
int tkl_config_run_except(ConfigFile *, ConfigEntry *, int);
|
||||
int tkl_config_test_set(ConfigFile *, ConfigEntry *, int, int *);
|
||||
int tkl_config_run_set(ConfigFile *, ConfigEntry *, int);
|
||||
CMD_FUNC(cmd_gline);
|
||||
CMD_FUNC(cmd_shun);
|
||||
CMD_FUNC(cmd_tempshun);
|
||||
@ -76,7 +78,7 @@ int _find_shun(Client *client);
|
||||
int _find_spamfilter_user(Client *client, int flags);
|
||||
TKL *_find_qline(Client *client, char *nick, int *ishold);
|
||||
TKL *_find_tkline_match_zap(Client *client);
|
||||
void _tkl_stats(Client *client, int type, char *para);
|
||||
void _tkl_stats(Client *client, int type, char *para, int *cnt);
|
||||
void _tkl_sync(Client *client);
|
||||
CMD_FUNC(_cmd_tkl);
|
||||
int _place_host_ban(Client *client, BanAction action, char *reason, long duration);
|
||||
@ -142,12 +144,15 @@ TKLTypeTable tkl_types[] = {
|
||||
};
|
||||
#define ALL_VALID_EXCEPTION_TYPES "kline, gline, zline, gzline, spamfilter, shun, qline, blacklist, connect-flood, unknown-data-flood, antirandom, antimixedutf8, ban-version"
|
||||
|
||||
int max_stats_matches = 1000;
|
||||
|
||||
MOD_TEST()
|
||||
{
|
||||
MARK_AS_OFFICIAL_MODULE(modinfo);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, tkl_config_test_spamfilter);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, tkl_config_test_ban);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, tkl_config_test_except);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, tkl_config_test_set);
|
||||
EfunctionAdd(modinfo->handle, EFUNC_TKL_HASH, _tkl_hash);
|
||||
EfunctionAdd(modinfo->handle, EFUNC_TKL_TYPETOCHAR, TO_INTFUNC(_tkl_typetochar));
|
||||
EfunctionAdd(modinfo->handle, EFUNC_TKL_CHARTOTYPE, TO_INTFUNC(_tkl_chartotype));
|
||||
@ -190,6 +195,7 @@ MOD_INIT()
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkl_config_match_spamfilter);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkl_config_run_ban);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkl_config_run_except);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, tkl_config_run_set);
|
||||
CommandAdd(modinfo->handle, "GLINE", cmd_gline, 3, CMD_OPER);
|
||||
CommandAdd(modinfo->handle, "SHUN", cmd_shun, 3, CMD_OPER);
|
||||
CommandAdd(modinfo->handle, "TEMPSHUN", cmd_tempshun, 2, CMD_OPER);
|
||||
@ -902,6 +908,44 @@ int tkl_config_run_except(ConfigFile *cf, ConfigEntry *ce, int configtype)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tkl_config_test_set(ConfigFile *cf, ConfigEntry *ce, int configtype, int *errs)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
/* We are only interested in set { } blocks */
|
||||
if (configtype != CONFIG_SET)
|
||||
return 0;
|
||||
|
||||
if (!strcmp(ce->ce_varname, "max-stats-matches"))
|
||||
{
|
||||
if (!ce->ce_vardata)
|
||||
{
|
||||
config_error("%s:%i: set::max-stats-matches: no value specified",
|
||||
ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
|
||||
errors++;
|
||||
}
|
||||
// allow any other value, including 0 and negative.
|
||||
*errs = errors;
|
||||
return errors ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tkl_config_run_set(ConfigFile *cf, ConfigEntry *ce, int configtype)
|
||||
{
|
||||
/* We are only interested in set { } blocks */
|
||||
if (configtype != CONFIG_SET)
|
||||
return 0;
|
||||
|
||||
if (!strcmp(ce->ce_varname, "max-stats-matches"))
|
||||
{
|
||||
max_stats_matches = atoi(ce->ce_vardata);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return unique spamfilter id for TKL */
|
||||
char *spamfilter_id(TKL *tk)
|
||||
{
|
||||
@ -1269,7 +1313,7 @@ void cmd_tkl_line(Client *client, int parc, char *parv[], char *type)
|
||||
mask++;
|
||||
}
|
||||
|
||||
if (strchr(mask, '!'))
|
||||
if ((*mask != '~') && strchr(mask, '!'))
|
||||
{
|
||||
sendnotice(client, "[error] Cannot have '!' in masks.");
|
||||
return;
|
||||
@ -1590,7 +1634,7 @@ CMD_FUNC(cmd_eline)
|
||||
reason = parv[4];
|
||||
}
|
||||
|
||||
if (strchr(mask, '!'))
|
||||
if ((*mask != '~') && strchr(mask, '!'))
|
||||
{
|
||||
sendnotice(client, "[error] Cannot have '!' in masks.");
|
||||
return;
|
||||
@ -3298,7 +3342,7 @@ static void parse_stats_params(char *para, TKLFlag *flag)
|
||||
/** Does this TKL entry match the search terms?
|
||||
* This is a helper function for tkl_stats().
|
||||
*/
|
||||
void tkl_stats_matcher(Client *client, int type, char *para, TKLFlag *tklflags, TKL *tkl)
|
||||
int tkl_stats_matcher(Client *client, int type, char *para, TKLFlag *tklflags, TKL *tkl)
|
||||
{
|
||||
/***** First, handle the selection ******/
|
||||
|
||||
@ -3306,66 +3350,66 @@ void tkl_stats_matcher(Client *client, int type, char *para, TKLFlag *tklflags,
|
||||
{
|
||||
if (tklflags->flags & BY_SETBY)
|
||||
if (!match_simple(tklflags->set_by, tkl->set_by))
|
||||
return;
|
||||
return 0;
|
||||
if (tklflags->flags & NOT_BY_SETBY)
|
||||
if (match_simple(tklflags->set_by, tkl->set_by))
|
||||
return;
|
||||
return 0;
|
||||
if (TKLIsServerBan(tkl))
|
||||
{
|
||||
if (tklflags->flags & BY_MASK)
|
||||
{
|
||||
if (!match_simple(tklflags->mask, make_user_host(tkl->ptr.serverban->usermask, tkl->ptr.serverban->hostmask)))
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (tklflags->flags & NOT_BY_MASK)
|
||||
{
|
||||
if (match_simple(tklflags->mask, make_user_host(tkl->ptr.serverban->usermask, tkl->ptr.serverban->hostmask)))
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (tklflags->flags & BY_REASON)
|
||||
if (!match_simple(tklflags->reason, tkl->ptr.serverban->reason))
|
||||
return;
|
||||
return 0;
|
||||
if (tklflags->flags & NOT_BY_REASON)
|
||||
if (match_simple(tklflags->reason, tkl->ptr.serverban->reason))
|
||||
return;
|
||||
return 0;
|
||||
} else
|
||||
if (TKLIsNameBan(tkl))
|
||||
{
|
||||
if (tklflags->flags & BY_MASK)
|
||||
{
|
||||
if (!match_simple(tklflags->mask, tkl->ptr.nameban->name))
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (tklflags->flags & NOT_BY_MASK)
|
||||
{
|
||||
if (match_simple(tklflags->mask, tkl->ptr.nameban->name))
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (tklflags->flags & BY_REASON)
|
||||
if (!match_simple(tklflags->reason, tkl->ptr.nameban->reason))
|
||||
return;
|
||||
return 0;
|
||||
if (tklflags->flags & NOT_BY_REASON)
|
||||
if (match_simple(tklflags->reason, tkl->ptr.nameban->reason))
|
||||
return;
|
||||
return 0;
|
||||
} else
|
||||
if (TKLIsBanException(tkl))
|
||||
{
|
||||
if (tklflags->flags & BY_MASK)
|
||||
{
|
||||
if (!match_simple(tklflags->mask, make_user_host(tkl->ptr.banexception->usermask, tkl->ptr.banexception->hostmask)))
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (tklflags->flags & NOT_BY_MASK)
|
||||
{
|
||||
if (match_simple(tklflags->mask, make_user_host(tkl->ptr.banexception->usermask, tkl->ptr.banexception->hostmask)))
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (tklflags->flags & BY_REASON)
|
||||
if (!match_simple(tklflags->reason, tkl->ptr.banexception->reason))
|
||||
return;
|
||||
return 0;
|
||||
if (tklflags->flags & NOT_BY_REASON)
|
||||
if (match_simple(tklflags->reason, tkl->ptr.banexception->reason))
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3444,16 +3488,24 @@ void tkl_stats_matcher(Client *client, int type, char *para, TKLFlag *tklflags,
|
||||
tkl->ptr.banexception->bantypes,
|
||||
(tkl->expire_at != 0) ? (tkl->expire_at - TStime()) : 0,
|
||||
(TStime() - tkl->set_at), tkl->set_by, tkl->ptr.banexception->reason);
|
||||
} else
|
||||
{
|
||||
/* That's weird, unknown TKL type */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* TKL Stats. This is used by /STATS gline and all the others */
|
||||
void _tkl_stats(Client *client, int type, char *para)
|
||||
void _tkl_stats(Client *client, int type, char *para, int *cnt)
|
||||
{
|
||||
TKL *tk;
|
||||
TKLFlag tklflags;
|
||||
int index, index2;
|
||||
|
||||
if ((max_stats_matches > 0) && (*cnt >= max_stats_matches))
|
||||
return;
|
||||
|
||||
if (!BadPtr(para))
|
||||
parse_stats_params(para, &tklflags);
|
||||
|
||||
@ -3467,7 +3519,16 @@ void _tkl_stats(Client *client, int type, char *para)
|
||||
{
|
||||
if (type && tk->type != type)
|
||||
continue;
|
||||
tkl_stats_matcher(client, type, para, &tklflags, tk);
|
||||
if (tkl_stats_matcher(client, type, para, &tklflags, tk))
|
||||
{
|
||||
*cnt += 1;
|
||||
if ((max_stats_matches > 0) && (*cnt >= max_stats_matches))
|
||||
{
|
||||
sendnumeric(client, ERR_TOOMANYMATCHES, "STATS", "too many matches (set::max-stats-matches)");
|
||||
sendnotice(client, "Consider searching on something more specific, eg '/STATS gline +m *.nl'. See '/STATS' (without parameters) for help.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3479,7 +3540,16 @@ void _tkl_stats(Client *client, int type, char *para)
|
||||
{
|
||||
if (type && tk->type != type)
|
||||
continue;
|
||||
tkl_stats_matcher(client, type, para, &tklflags, tk);
|
||||
if (tkl_stats_matcher(client, type, para, &tklflags, tk))
|
||||
{
|
||||
*cnt += 1;
|
||||
if ((max_stats_matches > 0) && (*cnt >= max_stats_matches))
|
||||
{
|
||||
sendnumeric(client, ERR_TOOMANYMATCHES, "STATS", "too many matches (set::max-stats-matches)");
|
||||
sendnotice(client, "Consider searching on something more specific, eg '/STATS gline +m *.nl'. See '/STATS' (without parameters) for help.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -351,45 +351,6 @@ CMD_FUNC(cmd_whox)
|
||||
return;
|
||||
}
|
||||
|
||||
/* '/who nick' */
|
||||
if (((acptr = find_person(mask, NULL)) != NULL) &&
|
||||
(!(fmt.matchsel & WMATCH_MODES)) &&
|
||||
(!(fmt.matchsel & WMATCH_OPER) || IsOper(acptr)))
|
||||
{
|
||||
int isinvis = 0;
|
||||
int i = 0;
|
||||
Hook *h;
|
||||
|
||||
isinvis = IsInvisible(acptr);
|
||||
for (lp = acptr->user->channel; lp; lp = lp->next)
|
||||
{
|
||||
member = IsMember(client, lp->channel);
|
||||
|
||||
if (isinvis && !member)
|
||||
continue;
|
||||
|
||||
for (h = Hooks[HOOKTYPE_VISIBLE_IN_CHANNEL]; h; h = h->next)
|
||||
{
|
||||
i = (*(h->func.intfunc))(acptr,lp->channel);
|
||||
if (i != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i != 0 && !(is_skochanop(client, lp->channel)) && !(is_skochanop(acptr, lp->channel) || has_voice(acptr,lp->channel)))
|
||||
continue;
|
||||
|
||||
if (member || (!isinvis && PubChannel(lp->channel)))
|
||||
break;
|
||||
}
|
||||
if (lp != NULL)
|
||||
do_who(client, acptr, lp->channel, &fmt);
|
||||
else
|
||||
do_who(client, acptr, NULL, &fmt);
|
||||
|
||||
sendnumeric(client, RPL_ENDOFWHO, orig_mask);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ValidatePermissionsForPath("channel:see:who:secret",client,NULL,NULL,NULL) ||
|
||||
ValidatePermissionsForPath("channel:see:whois",client,NULL,NULL,NULL))
|
||||
{
|
||||
@ -561,9 +522,14 @@ static void who_common_channel(Client *client, Channel *channel,
|
||||
|
||||
static void who_global(Client *client, char *mask, int operspy, struct who_format *fmt)
|
||||
{
|
||||
Client *hunted = NULL;
|
||||
Client *acptr;
|
||||
int maxmatches = IsOper(client) ? INT_MAX : WHOLIMIT;
|
||||
|
||||
/* If searching for a nick explicitly, then include it later on in the result: */
|
||||
if (mask && ((fmt->matchsel & WMATCH_NICK) || (fmt->matchsel == 0)))
|
||||
hunted = find_person(mask, NULL);
|
||||
|
||||
/* Initialize the markers to zero */
|
||||
list_for_each_entry(acptr, &client_list, client_node)
|
||||
ClearMark(acptr);
|
||||
@ -583,7 +549,7 @@ static void who_global(Client *client, char *mask, int operspy, struct who_forma
|
||||
if (!IsUser(acptr))
|
||||
continue;
|
||||
|
||||
if (IsInvisible(acptr) && !operspy && (client != acptr))
|
||||
if (IsInvisible(acptr) && !operspy && (client != acptr) && (acptr != hunted))
|
||||
continue;
|
||||
|
||||
if (IsMarked(acptr))
|
||||
|
@ -417,7 +417,10 @@ static void parse2(Client *cptr, Client **fromptr, MessageTag *mtags, char *ch)
|
||||
/* If you're a user, and this command does not permit users or opers, deny */
|
||||
if ((flags & CMD_USER) && !(cmptr->flags & CMD_USER) && !(cmptr->flags & CMD_OPER))
|
||||
{
|
||||
sendnumeric(cptr, ERR_NOTFORUSERS, cmptr->cmd);
|
||||
if (cmptr->flags & CMD_UNREGISTERED)
|
||||
sendnumeric(cptr, ERR_ALREADYREGISTRED); /* only for unregistered phase */
|
||||
else
|
||||
sendnumeric(cptr, ERR_NOTFORUSERS, cmptr->cmd); /* really never for users */
|
||||
return;
|
||||
}
|
||||
|
||||
|
399
src/send.c
399
src/send.c
@ -164,11 +164,29 @@ void mark_data_to_send(Client *to)
|
||||
}
|
||||
}
|
||||
|
||||
/** Send data to clients, servers, channels, IRCOps, etc.
|
||||
* There are a lot of send functions. The most commonly functions
|
||||
* are: sendto_one() to send to an individual user,
|
||||
* sendnumeric() to send a numeric to an individual user
|
||||
* and sendto_channel() to send a message to a channel.
|
||||
* @defgroup SendFunctions Send functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Send a message to a single client.
|
||||
* This function is used quite a lot, after sendnumeric() it is the most-used send function.
|
||||
* @param to The client to send to
|
||||
* @param mtags Any message tags associated with this message (can be NULL)
|
||||
* @param pattern The format string / pattern to use.
|
||||
* @param ... Format string parameters.
|
||||
* @section sendto_one_examples Examples
|
||||
* @subsection sendto_one_mode_r Send "MODE -r"
|
||||
* This will send the `:serv.er.name MODE yournick -r` message.
|
||||
* Note that it will send only this message to illustrate the sendto_one() function.
|
||||
* It does *not* set anyone actually -r.
|
||||
* @code
|
||||
* sendto_one(client, NULL, ":%s MODE %s :-r", me.name, client->name);
|
||||
* @endcode
|
||||
*/
|
||||
void sendto_one(Client *to, MessageTag *mtags, FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
@ -180,8 +198,8 @@ void sendto_one(Client *to, MessageTag *mtags, FORMAT_STRING(const char *pattern
|
||||
|
||||
/** Send a message to a single client - va_list variant.
|
||||
* This function is similar to sendto_one() except that it
|
||||
* doesn't use varargs but a va_list instead.
|
||||
* Generally this is NOT used outside send.c, so not by modules.
|
||||
* doesn't use varargs but uses a va_list instead.
|
||||
* Generally this function is NOT used outside send.c, so not by modules.
|
||||
* @param to The client to send to
|
||||
* @param mtags Any message tags associated with this message (can be NULL)
|
||||
* @param pattern The format string / pattern to use.
|
||||
@ -363,9 +381,9 @@ void sendbufto_one(Client *to, char *msg, unsigned int quick)
|
||||
}
|
||||
|
||||
/** A single function to send data to a channel.
|
||||
* Previously there were 6, now there is 1. This means there
|
||||
* are likely some parameters that you will pass as NULL or 0
|
||||
* but at least we can all use one single function.
|
||||
* Previously there were 6 different functions to send channel data,
|
||||
* now there is 1 single function. This also means that you most
|
||||
* likely will pass NULL or 0 as some parameters.
|
||||
* @param channel The channel to send to
|
||||
* @param from The source of the message
|
||||
* @param skip The client to skip (can be NULL).
|
||||
@ -380,6 +398,36 @@ void sendbufto_one(Client *to, char *msg, unsigned int quick)
|
||||
* @param mtags The message tags to attach to this message
|
||||
* @param pattern The pattern (eg: ":%s PRIVMSG %s :%s")
|
||||
* @param ... The parameters for the pattern.
|
||||
* @note For all channel messages, it is important to attach the correct
|
||||
* message tags (mtags) via a new_message() call, as can be seen
|
||||
* in the example.
|
||||
* @section sendto_channel_examples Examples
|
||||
* @subsection sendto_channel_privmsg Send a PRIVMSG to a channel
|
||||
* This command will send the message "Hello everyone!!!" to the channel when executed.
|
||||
* @code
|
||||
* CMD_FUNC(cmd_sayhello)
|
||||
* {
|
||||
* MessageTag *mtags = NULL;
|
||||
* Channel *channel = NULL;
|
||||
* if ((parc < 2) || BadPtr(parv[1]))
|
||||
* {
|
||||
* sendnumeric(client, ERR_NEEDMOREPARAMS, "SAYHELLO");
|
||||
* return;
|
||||
* }
|
||||
* channel = find_channel(parv[1], NULL);
|
||||
* if (!channel)
|
||||
* {
|
||||
* sendnumeric(client, ERR_NOSUCHCHANNEL, parv[1]);
|
||||
* return;
|
||||
* }
|
||||
* new_message(client, recv_mtags, &mtags);
|
||||
* sendto_channel(channel, client, client->direction, 0, 0,
|
||||
* SEND_LOCAL|SEND_REMOTE, mtags,
|
||||
* ":%s PRIVMSG %s :Hello everyone!!!",
|
||||
* client->name, channel->name);
|
||||
* free_message_tags(mtags);
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
void sendto_channel(Channel *channel, Client *from, Client *skip,
|
||||
int prefix, long clicap, int sendflags,
|
||||
@ -593,11 +641,15 @@ static int match_it(Client *one, char *mask, int what)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sendto_match_butone
|
||||
*
|
||||
* Send to all clients which match the mask in a way defined on 'what';
|
||||
* either by user hostname or user servername.
|
||||
/** Send to all clients which match the mask.
|
||||
* This function is rarely used.
|
||||
* @param one The client to skip
|
||||
* @param from The sender
|
||||
* @param mask The mask
|
||||
* @param what One of MATCH_HOST or MATCH_SERVER
|
||||
* @param mtags Message tags associated with the message
|
||||
* @param pattern Format string
|
||||
* @param ... Parameters to the format string
|
||||
*/
|
||||
void sendto_match_butone(Client *one, Client *from, char *mask, int what,
|
||||
MessageTag *mtags, FORMAT_STRING(const char *pattern), ...)
|
||||
@ -641,10 +693,9 @@ void sendto_match_butone(Client *one, Client *from, char *mask, int what,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sendto_ops
|
||||
*
|
||||
* Send to *local* ops only.
|
||||
/** Send a message to all locally connected IRCOps
|
||||
* @param pattern The format string / pattern to use.
|
||||
* @param ... Format string parameters.
|
||||
*/
|
||||
void sendto_ops(FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
@ -664,10 +715,98 @@ void sendto_ops(FORMAT_STRING(const char *pattern), ...)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sendto_umode
|
||||
*
|
||||
* Send to specified umode
|
||||
/* Hmm.. so local sending is called sendto_ops() and local+remote is sendto_ops_butone(),
|
||||
* that is weird naming... (TODO fix some day in a new major series)
|
||||
*/
|
||||
|
||||
/** Send a message to all IRCOps (local and remote), except one.
|
||||
* @param one Skip sending the message to this client/direction
|
||||
* @param from The sender (can not be NULL)
|
||||
* @param pattern The format string / pattern to use.
|
||||
* @param ... Format string parameters.
|
||||
*/
|
||||
void sendto_ops_butone(Client *one, Client *from, FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
va_list vl;
|
||||
Client *acptr;
|
||||
|
||||
++current_serial;
|
||||
list_for_each_entry(acptr, &client_list, client_node)
|
||||
{
|
||||
if (!SendWallops(acptr))
|
||||
continue;
|
||||
if (acptr->direction->local->serial == current_serial) /* sent message along it already ? */
|
||||
continue;
|
||||
if (acptr->direction == one)
|
||||
continue; /* ...was the one I should skip */
|
||||
acptr->direction->local->serial = current_serial;
|
||||
|
||||
va_start(vl, pattern);
|
||||
vsendto_prefix_one(acptr->direction, from, NULL, pattern, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
}
|
||||
|
||||
/** This function does exactly the same as sendto_ops() in practice in 5.x.
|
||||
* There used to be a difference between sendto_ops() and sendto_realops()
|
||||
* with regards to user-settable snomasks, but this is no longer the case.
|
||||
* TODO: remove this function in some future cleanup
|
||||
*/
|
||||
void sendto_realops(FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
va_list vl;
|
||||
Client *acptr;
|
||||
char nbuf[1024];
|
||||
|
||||
list_for_each_entry(acptr, &oper_list, special_node)
|
||||
{
|
||||
ircsnprintf(nbuf, sizeof(nbuf), ":%s NOTICE %s :*** ", me.name, acptr->name);
|
||||
strlcat(nbuf, pattern, sizeof nbuf);
|
||||
|
||||
va_start(vl, pattern);
|
||||
vsendto_one(acptr, NULL, nbuf, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
}
|
||||
|
||||
/** Send a message to all locally connected IRCOps and also log the error.
|
||||
* @param pattern The format string / pattern to use.
|
||||
* @param ... Format string parameters.
|
||||
*/
|
||||
void sendto_ops_and_log(FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
va_list vl;
|
||||
char buf[1024];
|
||||
|
||||
va_start(vl, pattern);
|
||||
ircvsnprintf(buf, sizeof(buf), pattern, vl);
|
||||
va_end(vl);
|
||||
|
||||
ircd_log(LOG_ERROR, "%s", buf);
|
||||
sendto_umode(UMODE_OPER, "%s", buf);
|
||||
}
|
||||
|
||||
/** This function does exactly the same as sendto_ops_and_log()
|
||||
* TODO: remove this function in some future cleanup
|
||||
*/
|
||||
void sendto_realops_and_log(FORMAT_STRING(const char *fmt), ...)
|
||||
{
|
||||
va_list vl;
|
||||
static char buf[2048];
|
||||
|
||||
va_start(vl, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, vl);
|
||||
va_end(vl);
|
||||
|
||||
sendto_realops("%s", buf);
|
||||
ircd_log(LOG_ERROR, "%s", buf);
|
||||
}
|
||||
|
||||
|
||||
/** Send a message to all locally connected users with specified user mode.
|
||||
* @param umodes The umode that the recipient should have set (one of UMODE_)
|
||||
* @param pattern The format string / pattern to use.
|
||||
* @param ... Format string parameters.
|
||||
*/
|
||||
void sendto_umode(int umodes, FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
@ -687,10 +826,10 @@ void sendto_umode(int umodes, FORMAT_STRING(const char *pattern), ...)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sendto_umode_global
|
||||
*
|
||||
* Send to specified umode *GLOBALLY* (on all servers)
|
||||
/** Send a message to all users with specified user mode (local & remote users).
|
||||
* @param umodes The umode that the recipient should have set (one of UMODE_*)
|
||||
* @param pattern The format string / pattern to use.
|
||||
* @param ... Format string parameters.
|
||||
*/
|
||||
void sendto_umode_global(int umodes, FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
@ -734,10 +873,10 @@ void sendto_umode_global(int umodes, FORMAT_STRING(const char *pattern), ...)
|
||||
}
|
||||
}
|
||||
|
||||
/** Send to specified snomask - local / operonly.
|
||||
* @param snomask Snomask to send to (can be a bitmask [AND])
|
||||
* @param pattern printf-style pattern, followed by parameters.
|
||||
* This function does not send snomasks to non-opers.
|
||||
/** Send a message to all locally connected users with specified snomask.
|
||||
* @param snomask The snomask that the recipient should have set (one of SNO_*)
|
||||
* @param pattern The format string / pattern to use.
|
||||
* @param ... Format string parameters.
|
||||
*/
|
||||
void sendto_snomask(int snomask, FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
@ -756,10 +895,10 @@ void sendto_snomask(int snomask, FORMAT_STRING(const char *pattern), ...)
|
||||
}
|
||||
}
|
||||
|
||||
/** Send to specified snomask - global / operonly.
|
||||
* @param snomask Snomask to send to (can be a bitmask [AND])
|
||||
* @param pattern printf-style pattern, followed by parameters
|
||||
* This function does not send snomasks to non-opers.
|
||||
/** Send a message to all users with specified snomask (local and remote users).
|
||||
* @param snomask The snomask that the recipient should have set (one of SNO_*)
|
||||
* @param pattern The format string / pattern to use.
|
||||
* @param ... Format string parameters.
|
||||
*/
|
||||
void sendto_snomask_global(int snomask, FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
@ -788,10 +927,10 @@ void sendto_snomask_global(int snomask, FORMAT_STRING(const char *pattern), ...)
|
||||
sendto_server(NULL, 0, 0, NULL, ":%s SENDSNO %s :%s", me.id, snobuf, nbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* send_cap_notify
|
||||
*
|
||||
* Send CAP DEL or CAP NEW to clients supporting this.
|
||||
/** Send CAP DEL and CAP NEW notification to clients supporting it.
|
||||
* This function is mostly meant to be used by the CAP and SASL modules.
|
||||
* @param add Whether the CAP token is added (1) or removed (0)
|
||||
* @param token The CAP token
|
||||
*/
|
||||
void send_cap_notify(int add, char *token)
|
||||
{
|
||||
@ -829,33 +968,6 @@ void send_cap_notify(int add, char *token)
|
||||
}
|
||||
}
|
||||
|
||||
/* ** sendto_ops_butone
|
||||
** Send message to all operators.
|
||||
** one - client not to send message to
|
||||
** from- client which message is from *NEVER* NULL!!
|
||||
*/
|
||||
void sendto_ops_butone(Client *one, Client *from, FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
va_list vl;
|
||||
Client *acptr;
|
||||
|
||||
++current_serial;
|
||||
list_for_each_entry(acptr, &client_list, client_node)
|
||||
{
|
||||
if (!SendWallops(acptr))
|
||||
continue;
|
||||
if (acptr->direction->local->serial == current_serial) /* sent message along it already ? */
|
||||
continue;
|
||||
if (acptr->direction == one)
|
||||
continue; /* ...was the one I should skip */
|
||||
acptr->direction->local->serial = current_serial;
|
||||
|
||||
va_start(vl, pattern);
|
||||
vsendto_prefix_one(acptr->direction, from, NULL, pattern, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare buffer based on format string and 'from' for LOCAL delivery.
|
||||
* The prefix (:<something>) will be expanded to :nick!user@host if 'from'
|
||||
* is a person, taking into account the rules for hidden/cloaked host.
|
||||
@ -908,6 +1020,32 @@ static int vmakebuf_local_withprefix(char *buf, size_t buflen, Client *from, con
|
||||
return len;
|
||||
}
|
||||
|
||||
/** Send a message to a client, expand the sender prefix.
|
||||
* This is similar to sendto_one() except that it will expand the source part :%s
|
||||
* to :nick!user@host if needed, while with sendto_one() it will be :nick.
|
||||
* @param to The client to send to
|
||||
* @param mtags Any message tags associated with this message (can be NULL)
|
||||
* @param pattern The format string / pattern to use.
|
||||
* @param ... Format string parameters.
|
||||
*/
|
||||
void sendto_prefix_one(Client *to, Client *from, MessageTag *mtags, FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl, pattern);
|
||||
vsendto_prefix_one(to, from, mtags, pattern, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
/** Send a message to a single client, expand the sender prefix - va_list variant.
|
||||
* This is similar to vsendto_one() except that it will expand the source part :%s
|
||||
* to :nick!user@host if needed, while with sendto_one() it will be :nick.
|
||||
* This function is also similar to sendto_prefix_one(), but this is the va_list
|
||||
* variant.
|
||||
* @param to The client to send to
|
||||
* @param mtags Any message tags associated with this message (can be NULL)
|
||||
* @param pattern The format string / pattern to use.
|
||||
* @param ... Format string parameters.
|
||||
*/
|
||||
void vsendto_prefix_one(Client *to, Client *from, MessageTag *mtags, const char *pattern, va_list vl)
|
||||
{
|
||||
char *mtags_str = mtags ? mtags_to_string(mtags, to) : NULL;
|
||||
@ -928,60 +1066,6 @@ void vsendto_prefix_one(Client *to, Client *from, MessageTag *mtags, const char
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sendto_prefix_one
|
||||
*
|
||||
* to - destination client
|
||||
* from - client which message is from
|
||||
*
|
||||
* NOTE: NEITHER OF THESE SHOULD *EVER* BE NULL!!
|
||||
* -avalon
|
||||
*/
|
||||
|
||||
void sendto_prefix_one(Client *to, Client *from, MessageTag *mtags, FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl, pattern);
|
||||
vsendto_prefix_one(to, from, mtags, pattern, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
/*
|
||||
* sendto_realops
|
||||
*
|
||||
* Send to *local* ops only but NOT +s nonopers.
|
||||
*/
|
||||
void sendto_realops(FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
va_list vl;
|
||||
Client *acptr;
|
||||
char nbuf[1024];
|
||||
|
||||
list_for_each_entry(acptr, &oper_list, special_node)
|
||||
{
|
||||
ircsnprintf(nbuf, sizeof(nbuf), ":%s NOTICE %s :*** ", me.name, acptr->name);
|
||||
strlcat(nbuf, pattern, sizeof nbuf);
|
||||
|
||||
va_start(vl, pattern);
|
||||
vsendto_one(acptr, NULL, nbuf, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Sends a message to all (local) opers AND logs to the ircdlog (as LOG_ERROR) */
|
||||
void sendto_realops_and_log(FORMAT_STRING(const char *fmt), ...)
|
||||
{
|
||||
va_list vl;
|
||||
static char buf[2048];
|
||||
|
||||
va_start(vl, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, vl);
|
||||
va_end(vl);
|
||||
|
||||
sendto_realops("%s", buf);
|
||||
ircd_log(LOG_ERROR, "%s", buf);
|
||||
}
|
||||
|
||||
void sendto_connectnotice(Client *newuser, int disconnect, char *comment)
|
||||
{
|
||||
Client *acptr;
|
||||
@ -1102,6 +1186,11 @@ void sendto_one_nickcmd(Client *server, Client *client, char *umodes)
|
||||
* has a % in their nick, which is a safe assumption since % is illegal.
|
||||
*/
|
||||
|
||||
/** Send a server notice to a client.
|
||||
* @param to The client to send to
|
||||
* @param pattern The format string / pattern to use.
|
||||
* @param ... Format string parameters.
|
||||
*/
|
||||
void sendnotice(Client *to, FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
static char realpattern[1024];
|
||||
@ -1115,25 +1204,34 @@ void sendnotice(Client *to, FORMAT_STRING(const char *pattern), ...)
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
/** Send MultiLine list as a notice, one for each line */
|
||||
/** Send MultiLine list as a notice, one for each line.
|
||||
* @param client The client to send to
|
||||
* @param m The MultiLine list.
|
||||
*/
|
||||
void sendnotice_multiline(Client *client, MultiLine *m)
|
||||
{
|
||||
for (; m; m = m->next)
|
||||
sendnotice(client, "%s", m->line);
|
||||
}
|
||||
void sendtxtnumeric(Client *to, FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
static char realpattern[1024];
|
||||
va_list vl;
|
||||
|
||||
ircsnprintf(realpattern, sizeof(realpattern), ":%s %d %s :%s", me.name, RPL_TEXT, to->name, pattern);
|
||||
|
||||
va_start(vl, pattern);
|
||||
vsendto_one(to, NULL, realpattern, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
/** Send numeric to IRC client */
|
||||
/** Send numeric message to a client.
|
||||
* @param to The recipient
|
||||
* @param numeric The numeric, one of RPL_* or ERR_*, see src/numeric.c
|
||||
* @param ... The parameters for the numeric
|
||||
* @note Be sure to provide the correct number and type of parameters that belong to the numeric. Check src/numeric.c when in doubt!
|
||||
* @section sendnumeric_examples Examples
|
||||
* @subsection sendnumeric_permission_denied Send "Permission Denied" numeric
|
||||
* This numeric has no parameter, so is simple:
|
||||
* @code
|
||||
* sendnumeric(client, ERR_NOPRIVILEGES);
|
||||
* @endcode
|
||||
* @subsection sendnumeric_notenoughparameters Send "Not enough parameters" numeric
|
||||
* This numeric requires 1 parameter: the name of the command.
|
||||
* @code
|
||||
* sendnumeric(client, ERR_NEEDMOREPARAMS, "SOMECOMMAND");
|
||||
* @endcode
|
||||
*/
|
||||
void sendnumeric(Client *to, int numeric, ...)
|
||||
{
|
||||
va_list vl;
|
||||
@ -1146,7 +1244,15 @@ void sendnumeric(Client *to, int numeric, ...)
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
/** Send numeric to IRC client */
|
||||
/** Send numeric message to a client - format to user specific needs.
|
||||
* This will ignore the numeric definition of src/numeric.c and always send ":me.name numeric clientname "
|
||||
* followed by the pattern and format string you choose.
|
||||
* @param to The recipient
|
||||
* @param numeric The numeric, one of RPL_* or ERR_*, see src/numeric.c
|
||||
* @param pattern The format string / pattern to use.
|
||||
* @param ... Format string parameters.
|
||||
* @note Don't forget to add a colon if you need it (eg `:%%s`), this is a common mistake.
|
||||
*/
|
||||
void sendnumericfmt(Client *to, int numeric, FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
va_list vl;
|
||||
@ -1159,7 +1265,27 @@ void sendnumericfmt(Client *to, int numeric, FORMAT_STRING(const char *pattern),
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
/** Send raw data directly to socket, bypassing everything.
|
||||
/** Send text numeric message to a client (RPL_TEXT).
|
||||
* Because this generic output numeric is commonly used it got a special function for it.
|
||||
* @param to The recipient
|
||||
* @param numeric The numeric, one of RPL_* or ERR_*, see src/numeric.c
|
||||
* @param pattern The format string / pattern to use.
|
||||
* @param ... Format string parameters.
|
||||
* @note Don't forget to add a colon if you need it (eg `:%%s`), this is a common mistake.
|
||||
*/
|
||||
void sendtxtnumeric(Client *to, FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
static char realpattern[1024];
|
||||
va_list vl;
|
||||
|
||||
ircsnprintf(realpattern, sizeof(realpattern), ":%s %d %s :%s", me.name, RPL_TEXT, to->name, pattern);
|
||||
|
||||
va_start(vl, pattern);
|
||||
vsendto_one(to, NULL, realpattern, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
/* Send raw data directly to socket, bypassing everything.
|
||||
* Looks like an interesting function to call? NO! STOP!
|
||||
* Don't use this function. It may only be used by the initial
|
||||
* Z-Line check via the codepath to banned_client().
|
||||
@ -1186,17 +1312,4 @@ void send_raw_direct(Client *user, FORMAT_STRING(FORMAT_STRING(const char *patte
|
||||
(void)send(user->local->fd, sendbuf, sendlen, 0);
|
||||
}
|
||||
|
||||
/** Send a message to all locally connected IRCOps and log the error.
|
||||
*/
|
||||
void sendto_ops_and_log(FORMAT_STRING(const char *pattern), ...)
|
||||
{
|
||||
va_list vl;
|
||||
char buf[1024];
|
||||
|
||||
va_start(vl, pattern);
|
||||
ircvsnprintf(buf, sizeof(buf), pattern, vl);
|
||||
va_end(vl);
|
||||
|
||||
ircd_log(LOG_ERROR, "%s", buf);
|
||||
sendto_umode(UMODE_OPER, "%s", buf);
|
||||
}
|
||||
/** @} */
|
||||
|
@ -32,7 +32,6 @@
|
||||
/* for uname(), is POSIX so should be OK... */
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
extern void s_die();
|
||||
|
||||
MODVAR int max_connection_count = 1, max_client_count = 1;
|
||||
extern int do_garbage_collect;
|
||||
|
@ -724,17 +724,6 @@ void outofmemory(size_t bytes)
|
||||
exit(7);
|
||||
}
|
||||
|
||||
/** Check if the specified file exists */
|
||||
int file_exists(char *file)
|
||||
{
|
||||
FILE *fd;
|
||||
fd = fopen(file, "r");
|
||||
if (!fd)
|
||||
return 0;
|
||||
fclose(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Returns a unique filename in the specified directory
|
||||
* using the specified suffix. The returned value will
|
||||
* be of the form <dir>/<random-hex>.<suffix>
|
||||
|
104
src/tls.c
104
src/tls.c
@ -36,9 +36,10 @@ extern HWND hwIRCDWnd;
|
||||
#define SAFE_SSL_ACCEPT 3
|
||||
#define SAFE_SSL_CONNECT 4
|
||||
|
||||
/* Forward declarations */
|
||||
static int fatal_ssl_error(int ssl_error, int where, int my_errno, Client *client);
|
||||
extern int cipher_check(SSL_CTX *ctx, char **errstr);
|
||||
extern int certificate_quality_check(SSL_CTX *ctx, char **errstr);
|
||||
int cipher_check(SSL_CTX *ctx, char **errstr);
|
||||
int certificate_quality_check(SSL_CTX *ctx, char **errstr);
|
||||
|
||||
/* The SSL structures */
|
||||
SSL_CTX *ctx_server;
|
||||
@ -1040,6 +1041,8 @@ int verify_certificate(SSL *ssl, char *hostname, char **errstr)
|
||||
|
||||
if (SSL_get_verify_result(ssl) != X509_V_OK)
|
||||
{
|
||||
// FIXME: there are actually about 25+ different possible errors,
|
||||
// this is only the most common one:
|
||||
strlcpy(buf, "Certificate is not issued by a trusted Certificate Authority", sizeof(buf));
|
||||
if (errstr)
|
||||
*errstr = buf;
|
||||
@ -1333,3 +1336,100 @@ char *outdated_tls_client_build_string(char *pattern, Client *client)
|
||||
buildvarstring(pattern, buf, sizeof(buf), name, value);
|
||||
return buf;
|
||||
}
|
||||
|
||||
int check_certificate_expiry_ctx(SSL_CTX *ctx, char **errstr)
|
||||
{
|
||||
#if !defined(HAS_ASN1_TIME_diff) || !defined(HAS_X509_get0_notAfter)
|
||||
return 0;
|
||||
#else
|
||||
static char errbuf[512];
|
||||
SSL *ssl;
|
||||
X509 *cert;
|
||||
const ASN1_TIME *cert_expiry_time;
|
||||
int days_expiry = 0, seconds_expiry = 0;
|
||||
long duration;
|
||||
|
||||
*errstr = NULL;
|
||||
|
||||
ssl = SSL_new(ctx);
|
||||
if (!ssl)
|
||||
return 0;
|
||||
|
||||
cert = SSL_get_certificate(ssl);
|
||||
if (!cert)
|
||||
{
|
||||
SSL_free(ssl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get certificate time */
|
||||
cert_expiry_time = X509_get0_notAfter(cert);
|
||||
|
||||
/* calculate difference */
|
||||
ASN1_TIME_diff(&days_expiry, &seconds_expiry, cert_expiry_time, NULL);
|
||||
duration = (days_expiry * 86400) + seconds_expiry;
|
||||
|
||||
/* certificate expiry? */
|
||||
if ((days_expiry > 0) || (seconds_expiry > 0))
|
||||
{
|
||||
snprintf(errbuf, sizeof(errbuf), "certificate expired %s ago", pretty_time_val(duration));
|
||||
SSL_free(ssl);
|
||||
*errstr = errbuf;
|
||||
return 1;
|
||||
} else
|
||||
/* or near-expiry? */
|
||||
if (((days_expiry < 0) || (seconds_expiry < 0)) && (days_expiry > -7))
|
||||
{
|
||||
snprintf(errbuf, sizeof(errbuf), "certificate will expire in %s", pretty_time_val(0 - duration));
|
||||
SSL_free(ssl);
|
||||
*errstr = errbuf;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* All good */
|
||||
SSL_free(ssl);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void check_certificate_expiry_tlsoptions_and_warn(TLSOptions *tlsoptions)
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
int ret;
|
||||
char *errstr = NULL;
|
||||
|
||||
ctx = init_ctx(tlsoptions, 1);
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
if (check_certificate_expiry_ctx(ctx, &errstr))
|
||||
{
|
||||
sendto_umode_global(UMODE_OPER, "Warning: TLS certificate '%s': %s", tlsoptions->certificate_file, errstr);
|
||||
ircd_log(LOG_ERROR, "[warning] TLS certificate '%s': %s", tlsoptions->certificate_file, errstr);
|
||||
}
|
||||
SSL_CTX_free(ctx);
|
||||
}
|
||||
|
||||
EVENT(tls_check_expiry)
|
||||
{
|
||||
ConfigItem_listen *listen;
|
||||
ConfigItem_sni *sni;
|
||||
ConfigItem_link *link;
|
||||
|
||||
/* set block */
|
||||
check_certificate_expiry_tlsoptions_and_warn(iConf.tls_options);
|
||||
|
||||
for (listen = conf_listen; listen; listen = listen->next)
|
||||
if (listen->tls_options)
|
||||
check_certificate_expiry_tlsoptions_and_warn(listen->tls_options);
|
||||
|
||||
/* sni::tls-options.... */
|
||||
for (sni = conf_sni; sni; sni = sni->next)
|
||||
if (sni->tls_options)
|
||||
check_certificate_expiry_tlsoptions_and_warn(sni->tls_options);
|
||||
|
||||
/* link::outgoing::tls-options.... */
|
||||
for (link = conf_link; link; link = link->next)
|
||||
if (link->tls_options)
|
||||
check_certificate_expiry_tlsoptions_and_warn(link->tls_options);
|
||||
}
|
||||
|
146
src/user.c
146
src/user.c
@ -726,3 +726,149 @@ int hide_idle_time(Client *client, Client *target)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Check if the name of the security-group contains only valid characters.
|
||||
* @param name The name of the group
|
||||
* @returns 1 if name is valid, 0 if not (eg: illegal characters)
|
||||
*/
|
||||
int security_group_valid_name(char *name)
|
||||
{
|
||||
char *p;
|
||||
if (strlen(name) > SECURITYGROUPLEN)
|
||||
return 0; /* Too long */
|
||||
for (p = name; *p; p++)
|
||||
{
|
||||
if (!isalnum(*p) && !strchr("_-", *p))
|
||||
return 0; /* Character not allowed */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Find a security-group.
|
||||
* @param name The name of the security group
|
||||
* @returns A SecurityGroup struct, or NULL if not found.
|
||||
*/
|
||||
SecurityGroup *find_security_group(char *name)
|
||||
{
|
||||
SecurityGroup *s;
|
||||
for (s = securitygroups; s; s = s->next)
|
||||
if (!strcasecmp(name, s->name))
|
||||
return s;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Checks if a security-group exists.
|
||||
* This function takes the 'unknown-users' magic group into account as well.
|
||||
* @param name The name of the security group
|
||||
* @returns 1 if it exists, 0 if not
|
||||
*/
|
||||
int security_group_exists(char *name)
|
||||
{
|
||||
if (!strcmp(name, "unknown-users") || find_security_group(name))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Add a new security-group and add it to the list, but search for existing one first.
|
||||
* @param name The name of the security group
|
||||
* @returns A SecurityGroup struct (already added to the 'securitygroups' linked list)
|
||||
*/
|
||||
SecurityGroup *add_security_group(char *name, int priority)
|
||||
{
|
||||
SecurityGroup *s = find_security_group(name);
|
||||
|
||||
/* Existing? */
|
||||
if (s)
|
||||
return s;
|
||||
|
||||
/* Otherwise, create a new entry */
|
||||
s = safe_alloc(sizeof(SecurityGroup));
|
||||
strlcpy(s->name, name, sizeof(s->name));
|
||||
s->priority = priority;
|
||||
AddListItemPrio(s, securitygroups, priority);
|
||||
return s;
|
||||
}
|
||||
|
||||
/** Free a SecurityGroup struct */
|
||||
void free_security_group(SecurityGroup *s)
|
||||
{
|
||||
/* atm there is nothing else to free,
|
||||
* but who knows this may change in the future
|
||||
*/
|
||||
safe_free(s);
|
||||
}
|
||||
|
||||
/** Initialize the default security-group blocks */
|
||||
void set_security_group_defaults(void)
|
||||
{
|
||||
SecurityGroup *s, *s_next;
|
||||
|
||||
/* First free all security groups */
|
||||
for (s = securitygroups; s; s = s_next)
|
||||
{
|
||||
s_next = s->next;
|
||||
free_security_group(s);
|
||||
}
|
||||
securitygroups = NULL;
|
||||
|
||||
/* Default group: known-users */
|
||||
s = add_security_group("known-users", 100);
|
||||
s->identified = 1;
|
||||
s->reputation_score = 25;
|
||||
s->webirc = 0;
|
||||
|
||||
/* Default group: tls-and-known-users */
|
||||
s = add_security_group("tls-and-known-users", 200);
|
||||
s->identified = 1;
|
||||
s->reputation_score = 25;
|
||||
s->webirc = 0;
|
||||
s->tls = 1;
|
||||
|
||||
/* Default group: tls-users */
|
||||
s = add_security_group("tls-users", 300);
|
||||
s->tls = 1;
|
||||
}
|
||||
|
||||
/** Returns 1 if the user is OK as far as the security-group is concerned.
|
||||
* @param client The client to check
|
||||
* @param s The security-group to check against
|
||||
* @retval 1 if user is allowed by security-group, 0 if not.
|
||||
*/
|
||||
int user_allowed_by_security_group(Client *client, SecurityGroup *s)
|
||||
{
|
||||
if (s->identified && IsLoggedIn(client))
|
||||
return 1;
|
||||
if (s->webirc && moddata_client_get(client, "webirc"))
|
||||
return 1;
|
||||
if (s->reputation_score && (GetReputation(client) >= s->reputation_score))
|
||||
return 1;
|
||||
if (s->tls && (IsSecureConnect(client) || IsSecure(client)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Returns 1 if the user is OK as far as the security-group is concerned - "by name" version.
|
||||
* @param client The client to check
|
||||
* @param secgroupname The name of the security-group to check against
|
||||
* @retval 1 if user is allowed by security-group, 0 if not.
|
||||
*/
|
||||
int user_allowed_by_security_group_name(Client *client, char *secgroupname)
|
||||
{
|
||||
SecurityGroup *s;
|
||||
|
||||
/* Handle the magical 'unknown-users' case. */
|
||||
if (!strcmp(secgroupname, "unknown-users"))
|
||||
{
|
||||
/* This is simply the inverse of 'known-users' */
|
||||
s = find_security_group("known-users");
|
||||
if (!s)
|
||||
return 0; /* that's weird!? pretty impossible. */
|
||||
return !user_allowed_by_security_group(client, s);
|
||||
}
|
||||
|
||||
/* Find the group and evaluate it */
|
||||
s = find_security_group(secgroupname);
|
||||
if (!s)
|
||||
return 0; /* security group not found: no match */
|
||||
return user_allowed_by_security_group(client, s);
|
||||
}
|
||||
|
@ -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.7"
|
||||
id="5.0.8"
|
||||
echo "$id"
|
||||
|
||||
if test -r version.c
|
||||
|
@ -3,7 +3,7 @@
|
||||
<assemblyIdentity
|
||||
processorArchitecture="amd64"
|
||||
name="UnrealIRCd.UnrealIRCd.5"
|
||||
version="5.0.7.0"
|
||||
version="5.0.8.0"
|
||||
type="win32"
|
||||
/>
|
||||
<description>Internet Relay Chat Daemon</description>
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
[Setup]
|
||||
AppName=UnrealIRCd 5
|
||||
AppVerName=UnrealIRCd 5.0.7
|
||||
AppVerName=UnrealIRCd 5.0.8
|
||||
AppPublisher=UnrealIRCd Team
|
||||
AppPublisherURL=https://www.unrealircd.org
|
||||
AppSupportURL=https://www.unrealircd.org
|
||||
@ -68,6 +68,7 @@ Source: "src\modules\chanmodes\*.dll"; DestDir: "{app}\modules\chanmodes"; Flags
|
||||
Source: "src\modules\usermodes\*.dll"; DestDir: "{app}\modules\usermodes"; Flags: ignoreversion
|
||||
Source: "src\modules\snomasks\*.dll"; DestDir: "{app}\modules\snomasks"; Flags: ignoreversion
|
||||
Source: "src\modules\extbans\*.dll"; DestDir: "{app}\modules\extbans"; Flags: ignoreversion
|
||||
Source: "src\modules\third\*.dll"; DestDir: "{app}\modules\third"; Flags: ignoreversion skipifsourcedoesntexist
|
||||
|
||||
Source: "c:\dev\unrealircd-5-libs\pcre2\bin\pcre*.dll"; DestDir: "{app}\bin"; Flags: ignoreversion
|
||||
Source: "c:\dev\unrealircd-5-libs\argon2\vs2015\build\*.dll"; DestDir: "{app}\bin"; Flags: ignoreversion
|
||||
|
Loading…
Reference in New Issue
Block a user