diff --git a/Config b/Config index 28ccb7f..7ddfe86 100755 --- a/Config +++ b/Config @@ -255,25 +255,19 @@ fi #parse arguments -NOCACHE="" IMPORTEDSETTINGS="" NOINTRO="" QUICK="" -CLEAN="" ADVANCED="" while [ $# -ge 1 ] ; do if [ $1 = "--help" ] ; then echo "Config utility for UnrealIRCd" echo "-----------------------------" echo "Syntax: ./Config [options]" - echo "-nocache Ignore settings saved in config.settings" echo "-nointro Skip intro (release notes, etc)" echo "-quick Skip questions, go straight to configure" echo "-advanced Include additional advanced questions" - echo "-clean Clean ./configure cache" exit 0 - elif [ $1 = "-nocache" ] ; then - NOCACHE="1" elif [ $1 = "-nointro" ] ; then NOINTRO="1" elif [ $1 = "-quick" -o $1 = "-q" ] ; then @@ -285,8 +279,6 @@ while [ $# -ge 1 ] ; do RUN_CONFIGURE cd "$UNREALCWD" exit 0 - elif [ $1 = "-clean" -o $1 = "-C" ] ; then - CLEAN="1" elif [ $1 = "-advanced" ] ; then PREADVANCED="1" fi @@ -299,10 +291,6 @@ elif [ "$ADVANCED" = "1" ]; then ADVANCED="" fi -if [ -n "$CLEAN" ] ; then - rm -f config.cache -fi - if [ "`id -u`" = "0" ]; then echo "ERROR: You cannot build or run UnrealIRCd as root" echo "" @@ -324,77 +312,75 @@ clear echo "We will now ask you a number of questions. You can just press ENTER to accept the defaults!" echo "" -if [ -z "$NOCACHE" ] ; then - # This needs to be updated each release so auto-upgrading works for settings, modules, etc!!: - UNREALRELEASES="unrealircd-5.0.2 unrealircd-5.0.1 unrealircd-5.0.0 unrealircd-5.0.0-rc2 unrealircd-5.0.0-rc1" - if [ -f "config.settings" ]; then - . ./config.settings +# This needs to be updated each release so auto-upgrading works for settings, modules, etc!!: +UNREALRELEASES="unrealircd-5.0.3.1 unrealircd-5.0.3 unrealircd-5.0.2 unrealircd-5.0.1 unrealircd-5.0.0 unrealircd-5.0.0-rc2 unrealircd-5.0.0-rc1" +if [ -f "config.settings" ]; then + . ./config.settings +else + # Try to load a previous config.settings + for x in $UNREALRELEASES + do + if [ -f ../$x/config.settings ]; then + IMPORTEDSETTINGS="../$x" + break + fi + done + echo "If you have previously installed UnrealIRCd on this shell then you can specify a" + echo "directory here so I can import the build settings and third party modules" + echo "to make your life a little easier." + if [ ! -z "$IMPORTEDSETTINGS" ]; then + echo "Found previous installation in: $IMPORTEDSETTINGS." + echo "You can enter a different path or type 'none' if you don't want to use it." + echo "Just press Enter to accept the default settings." else - # Try to load a previous config.settings - for x in $UNREALRELEASES - do - if [ -f ../$x/config.settings ]; then - IMPORTEDSETTINGS="../$x" - break - fi - done - echo "If you have previously installed UnrealIRCd on this shell then you can specify a" - echo "directory here so I can import the build settings and third party modules" - echo "to make your life a little easier." - if [ ! -z "$IMPORTEDSETTINGS" ]; then - echo "Found previous installation in: $IMPORTEDSETTINGS." - echo "You can enter a different path or type 'none' if you don't want to use it." - echo "Just press Enter to accept the default settings." - else - echo "If you install UnrealIRCd for the first time on this shell, then just hit Enter"; - fi + echo "If you install UnrealIRCd for the first time on this shell, then just hit Enter"; + fi - TEST="$IMPORTEDSETTINGS" - echo $n "[$TEST] -> $c" - read cc - if [ -z "$cc" ]; then - IMPORTEDSETTINGS="$TEST" - else - IMPORTEDSETTINGS="$cc" + TEST="$IMPORTEDSETTINGS" + echo $n "[$TEST] -> $c" + read cc + if [ -z "$cc" ]; then + IMPORTEDSETTINGS="$TEST" + else + IMPORTEDSETTINGS="$cc" + fi + if [ "$IMPORTEDSETTINGS" = "none" ]; then + IMPORTEDSETTINGS="" + fi + if [ "$IMPORTEDSETTINGS" != "" ]; then + if [ -d $IMPORTEDSETTINGS/conf ]; then + echo "ERROR: Directory $IMPORTEDSETTINGS is an INSTALLATION directory (eg /home/irc/unrealircd)." + echo "This question was about a SOURCE directory (eg /home/irc/unrealircd-5.0.0)." + exit fi - if [ "$IMPORTEDSETTINGS" = "none" ]; then - IMPORTEDSETTINGS="" + if [ ! -f $IMPORTEDSETTINGS/config.settings ]; then + echo "Directory $IMPORTEDSETTINGS does not exist or does not contain a config.settings file" + exit fi - if [ "$IMPORTEDSETTINGS" != "" ]; then - if [ -d $IMPORTEDSETTINGS/conf ]; then - echo "ERROR: Directory $IMPORTEDSETTINGS is an INSTALLATION directory (eg /home/irc/unrealircd)." - echo "This question was about a SOURCE directory (eg /home/irc/unrealircd-5.0.0)." - exit - fi - if [ ! -f $IMPORTEDSETTINGS/config.settings ]; then - echo "Directory $IMPORTEDSETTINGS does not exist or does not contain a config.settings file" - exit - fi - COPYMODULES="1" - if grep -q TOPICNICKISNUH $IMPORTEDSETTINGS/config.settings; then - echo "Directory $IMPORTEDSETTINGS seems to be UnrealIRCd 4.x (or older)." - echo "I will copy the settings but not any 3rd party modules, as they are incompatible with 5.x." - COPYMODULES="0" - fi - # Actually load the settings - . $IMPORTEDSETTINGS/config.settings - if [ "$COPYMODULES" = "1" ]; then - # Copy over 3rd party modules (also deals with 0 file cases, hence the silly looking code) - for f in $IMPORTEDSETTINGS/src/modules/third/*.c - do - [ -e "$f" ] && cp $f src/modules/third/ - done - fi + COPYMODULES="1" + if grep -q TOPICNICKISNUH $IMPORTEDSETTINGS/config.settings; then + echo "Directory $IMPORTEDSETTINGS seems to be UnrealIRCd 4.x (or older)." + echo "I will copy the settings but not any 3rd party modules, as they are incompatible with 5.x." + COPYMODULES="0" + fi + # Actually load the settings + . $IMPORTEDSETTINGS/config.settings + if [ "$COPYMODULES" = "1" ]; then + # Copy over 3rd party modules (also deals with 0 file cases, hence the silly looking code) + for f in $IMPORTEDSETTINGS/src/modules/third/*.c + do + [ -e "$f" ] && cp $f src/modules/third/ + done fi fi - # If we just imported settings and the curl dir is set to - # something like /home/xxx/unrealircd-5.x.y/extras/curl/ - # (what we call 'local-curl') then remove this setting as - # it would refer to the old UnrealIRCd installation. - if [ ! -z "$IMPORTEDSETTINGS" ]; then - if echo "$CURLDIR"|grep -qi unrealircd; then - CURLDIR="" - fi +fi +# If we just imported settings and the curl dir is set to +# something like /home/xxx/unrealircd-5.x.y/extras/curl/ +# (what we call 'local-curl') then remove this setting as +# it would refer to the old UnrealIRCd installation. +if [ ! -z "$IMPORTEDSETTINGS" ]; then + if echo "$CURLDIR"|grep -qi unrealircd; then + CURLDIR="" fi fi diff --git a/autoconf/m4/unreal.m4 b/autoconf/m4/unreal.m4 index a77b095..ec2c85d 100644 --- a/autoconf/m4/unreal.m4 +++ b/autoconf/m4/unreal.m4 @@ -252,3 +252,23 @@ else AC_MSG_RESULT([no]) fi ]) + +AC_DEFUN([CHECK_SSL_CTX_SET_SECURITY_LEVEL], +[ +AC_MSG_CHECKING([for SSL_CTX_set_security_level in SSL library]) +AC_LANG_PUSH(C) +SAVE_LIBS="$LIBS" +LIBS="$LIBS $CRYPTOLIB" +AC_TRY_LINK([#include ], + [SSL_CTX *ctx = NULL; SSL_CTX_set_security_level(ctx, 1);], + 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_SSL_CTX_SET_SECURITY_LEVEL], [], [Define if ssl library has SSL_CTX_set_security_level]) +else + AC_MSG_RESULT([no]) +fi +]) diff --git a/configure b/configure index 125017a..4936473 100755 --- a/configure +++ b/configure @@ -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.3.1. +# Generated by GNU Autoconf 2.69 for unrealircd 5.0.4. # # Report bugs to . # @@ -580,8 +580,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='unrealircd' PACKAGE_TARNAME='unrealircd' -PACKAGE_VERSION='5.0.3.1' -PACKAGE_STRING='unrealircd 5.0.3.1' +PACKAGE_VERSION='5.0.4' +PACKAGE_STRING='unrealircd 5.0.4' PACKAGE_BUGREPORT='https://bugs.unrealircd.org/' PACKAGE_URL='https://unrealircd.org/' @@ -670,6 +670,8 @@ HARDEN_BINLDFLAGS HARDEN_BINCFLAGS HARDEN_LDFLAGS HARDEN_CFLAGS +GMAKE +MAKER OBJEXT EXEEXT ac_ct_CC @@ -679,8 +681,6 @@ CFLAGS CC PKGCONFIG GUNZIP -GMAKE -MAKER INSTALL OPENSSLPATH TOUCH @@ -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.3.1 to adapt to many kinds of systems. +\`configure' configures unrealircd 5.0.4 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.3.1:";; + short | recursive ) echo "Configuration of unrealircd 5.0.4:";; 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.3.1 +unrealircd configure 5.0.4 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.3.1, which was +It was created by unrealircd $as_me 5.0.4, 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="3" +UNREAL_VERSION_MINOR="4" cat >>confdefs.h <<_ACEOF #define UNREAL_VERSION_MINOR $UNREAL_VERSION_MINOR @@ -2331,7 +2331,7 @@ _ACEOF # The version suffix such as a beta marker or release candidate # marker. (e.g.: -rcX for unrealircd-3.2.9-rcX). This macro is a # string instead of an integer because it contains arbitrary data. -UNREAL_VERSION_SUFFIX=".1" +UNREAL_VERSION_SUFFIX="" cat >>confdefs.h <<_ACEOF #define UNREAL_VERSION_SUFFIX "$UNREAL_VERSION_SUFFIX" @@ -2551,91 +2551,6 @@ $as_echo "no" >&6; } fi -# Extract the first word of "gmake", so it can be a program name with args. -set dummy gmake; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_MAKER+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$MAKER"; then - ac_cv_prog_MAKER="$MAKER" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_MAKER="gmake" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - test -z "$ac_cv_prog_MAKER" && ac_cv_prog_MAKER="make" -fi -fi -MAKER=$ac_cv_prog_MAKER -if test -n "$MAKER"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKER" >&5 -$as_echo "$MAKER" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -# Extract the first word of "gmake", so it can be a program name with args. -set dummy gmake; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_GMAKE+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $GMAKE in - [\\/]* | ?:[\\/]*) - ac_cv_path_GMAKE="$GMAKE" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_GMAKE="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -GMAKE=$ac_cv_path_GMAKE -if test -n "$GMAKE"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMAKE" >&5 -$as_echo "$GMAKE" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - -if $MAKER --version | grep -q "GNU Make"; then : - GNUMAKE="0" -else - as_fn_error $? "It seems your system does not have gmake installed. Please install gmake." "$LINENO" 5 -fi - # Extract the first word of "gunzip", so it can be a program name with args. set dummy gunzip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -3687,6 +3602,90 @@ if test "$ac_cv_prog_cc_c99" = "no"; then : as_fn_error $? "No C99 compiler was found. Please install gcc or clang and other build tools. Eg, on Debian/Ubuntu you probably want to run the following as root: apt-get install build-essential " "$LINENO" 5 fi +# Extract the first word of "gmake", so it can be a program name with args. +set dummy gmake; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MAKER+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MAKER"; then + ac_cv_prog_MAKER="$MAKER" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MAKER="gmake" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_MAKER" && ac_cv_prog_MAKER="make" +fi +fi +MAKER=$ac_cv_prog_MAKER +if test -n "$MAKER"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKER" >&5 +$as_echo "$MAKER" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "gmake", so it can be a program name with args. +set dummy gmake; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GMAKE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GMAKE in + [\\/]* | ?:[\\/]*) + ac_cv_path_GMAKE="$GMAKE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GMAKE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GMAKE=$ac_cv_path_GMAKE +if test -n "$GMAKE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMAKE" >&5 +$as_echo "$GMAKE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if $MAKER --version | grep -q "GNU Make"; then : + GNUMAKE="0" +else + as_fn_error $? "It seems your system does not have make/gmake installed. If you are on Linux then install make, otherwise install gmake." "$LINENO" 5 +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt in -ldescrypt" >&5 $as_echo_n "checking for crypt in -ldescrypt... " >&6; } @@ -6384,6 +6383,53 @@ else $as_echo "no" >&6; } fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_CTX_set_security_level in SSL library" >&5 +$as_echo_n "checking for SSL_CTX_set_security_level 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 +int +main () +{ +SSL_CTX *ctx = NULL; SSL_CTX_set_security_level(ctx, 1); + ; + 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_SSL_CTX_SET_SECURITY_LEVEL /**/" >>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 @@ -6948,6 +6994,11 @@ $as_echo "installing Argon2 library" >&6; } $ac_cv_prog_MAKER install PREFIX=$cur_dir/extras/argon2 || exit 1 # We need to manually copy the libs to PRIVATELIBDIR because # there is no way to tell make install in libargon2 to do so. +# BUT FIRST, delete the old library so it becomes an unlink+create +# operation rather than overwriting the existing file which would +# lead to a crash of the currently running IRCd. +rm -f "$PRIVATELIBDIR/"libargon2* +# Now copy the new library files: cp -av $cur_dir/extras/argon2/lib/* $PRIVATELIBDIR/ ARGON2_CFLAGS="-I$cur_dir/extras/argon2/include" @@ -8249,7 +8300,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.3.1, which was +This file was extended by unrealircd $as_me 5.0.4, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -8312,7 +8363,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.3.1 +unrealircd config.status 5.0.4 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 983b6dd..92720c8 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ dnl src/windows/unrealinst.iss dnl doc/Config.header dnl src/version.c.SH -AC_INIT([unrealircd], [5.0.3.1], [https://bugs.unrealircd.org/], [], [https://unrealircd.org/]) +AC_INIT([unrealircd], [5.0.4], [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,13 +34,13 @@ 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=["3"] +UNREAL_VERSION_MINOR=["4"] 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 # marker. (e.g.: -rcX for unrealircd-3.2.9-rcX). This macro is a # string instead of an integer because it contains arbitrary data. -UNREAL_VERSION_SUFFIX=[".1"] +UNREAL_VERSION_SUFFIX=[""] AC_DEFINE_UNQUOTED([UNREAL_VERSION_SUFFIX], ["$UNREAL_VERSION_SUFFIX"], [Version suffix such as a beta marker or release candidate marker. (e.g.: -rcX for unrealircd-3.2.9-rcX)]) AC_PATH_PROG(RM,rm) @@ -60,13 +60,6 @@ exit 1 ]) AC_PATH_PROG(INSTALL,install) -AC_CHECK_PROG(MAKER, gmake, gmake, make) -AC_PATH_PROG(GMAKE,gmake) - -AS_IF([$MAKER --version | grep -q "GNU Make"], - [GNUMAKE="0"], - [AC_MSG_ERROR([It seems your system does not have gmake installed. Please install gmake.])]) - AC_PATH_PROG(GUNZIP, gunzip) AC_PATH_PROG(PKGCONFIG, pkg-config) @@ -75,6 +68,13 @@ AC_PROG_CC_C99 AS_IF([test "$ac_cv_prog_cc_c99" = "no"], [AC_MSG_ERROR([No C99 compiler was found. Please install gcc or clang and other build tools. Eg, on Debian/Ubuntu you probably want to run the following as root: apt-get install build-essential ])]) +dnl Check for make moved down, so the above compiler check takes precedence. +AC_CHECK_PROG(MAKER, gmake, gmake, make) +AC_PATH_PROG(GMAKE,gmake) +AS_IF([$MAKER --version | grep -q "GNU Make"], + [GNUMAKE="0"], + [AC_MSG_ERROR([It seems your system does not have make/gmake installed. If you are on Linux then install make, otherwise install gmake.])]) + dnl Checks for libraries. AC_CHECK_LIB(descrypt, crypt, [AC_DEFINE([HAVE_CRYPT], [], [Define if you have crypt]) @@ -497,6 +497,7 @@ AC_ARG_WITH(system-cares, [AS_HELP_STRING([--without-system-cares], [Use bundled CHECK_SSL CHECK_SSL_CTX_SET1_CURVES_LIST CHECK_SSL_CTX_SET_MIN_PROTO_VERSION +CHECK_SSL_CTX_SET_SECURITY_LEVEL 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"], @@ -603,6 +604,11 @@ AC_MSG_RESULT(installing Argon2 library) $ac_cv_prog_MAKER install PREFIX=$cur_dir/extras/argon2 || exit 1 # We need to manually copy the libs to PRIVATELIBDIR because # there is no way to tell make install in libargon2 to do so. +# BUT FIRST, delete the old library so it becomes an unlink+create +# operation rather than overwriting the existing file which would +# lead to a crash of the currently running IRCd. +rm -f "$PRIVATELIBDIR/"libargon2* +# Now copy the new library files: cp -av $cur_dir/extras/argon2/lib/* $PRIVATELIBDIR/ ARGON2_CFLAGS="-I$cur_dir/extras/argon2/include" AC_SUBST(ARGON2_CFLAGS) diff --git a/doc/Config.header b/doc/Config.header index caeeb18..dcddc86 100644 --- a/doc/Config.header +++ b/doc/Config.header @@ -7,11 +7,10 @@ \___/|_| |_|_| \___|\__,_|_|\___/\_| \_| \____/\__,_| Configuration Program - for UnrealIRCd 5.0.3.1 + for UnrealIRCd 5.0.4 This program will help you to compile your IRC server, and ask you questions regarding the compile-time settings of it during the process. -regarding the setup of it, during the process. A short installation guide is available online at: https://www.unrealircd.org/docs/Installing_from_source diff --git a/doc/RELEASE-NOTES.md b/doc/RELEASE-NOTES.md index b7625dc..d030e13 100644 --- a/doc/RELEASE-NOTES.md +++ b/doc/RELEASE-NOTES.md @@ -1,5 +1,46 @@ -UnrealIRCd 5.0.3.1 Release Notes -================================= +UnrealIRCd 5.0.4 Release Notes +=============================== + +This new 5.0.4 version fixes quite a number of bugs. It contains only two small feature improvements. + +Fixes: +* When placing a SHUN on an online user it was not always effective. +* Channeldb was not properly restoring all channel modes, such as +P. +* When upgrading UnrealIRCd it could sometimes crash the currently + running IRC server (rare), or trigger a crash report on + ```./unrealircd restart``` (quite common). +* UnrealIRCd was giving up too easily on ident lookups. +* Crash when unloading a module with moddata. +* Crash if an authenticated server sends wrong information (rare). +* Removing a TEMPSHUN did not work if the user was on another server. +* SAJOIN to 0 (part all channels) resulted in a desync when used on remote users. +* Forced nick change from services was not showing up if the user + was not in any channels. + +Enhancements: +* New option [set::hide-idle-time::policy](https://www.unrealircd.org/docs/Set_block#set%3A%3Ahide-idle-time) + by which you can change usermode +I (hide idle time in WHOIS) from + oper-only to settable by users. More options will follow in a future + release. +* In WHOIS you can now see if a user is currently (temp)shunned. + This only works for locally connected users for technical reasons, + so use ```/WHOIS Nick Nick``` to see it for remote users. + +Changes: +* The oper notices and logging with regards to server linking have changed + a little. They are more consistent and log more now. +* When an IRCOp tries to oper up from an insecure connection we will now + mention the https://www.unrealircd.org/docs/FAQ#oper-requires-tls page. + This message is customizable through + [set::plaintext-policy::oper-message](https://www.unrealircd.org/docs/Set_block#set::plaintext-policy). +* The French HELPOP text was updated. + +Upgrading from UnrealIRCd 4? +----------------------------- + +Are you upgrading from UnrealIRCd 4.x to UnrealIRCd 5? +Then check out the *UnrealIRCd 5* release notes [further down](#unrealircd-5). At the +very least, check out [Upgrading from 4.x](https://www.unrealircd.org/docs/Upgrading_from_4.x). UnrealIRCd 5.0.3.1 ------------------- diff --git a/doc/conf/except.conf b/doc/conf/except.conf index 14a9be5..562fbd5 100644 --- a/doc/conf/except.conf +++ b/doc/conf/except.conf @@ -33,3 +33,4 @@ except ban { mask *@2600:3c03::f03c:91ff:fe96:c1fa; } # bot.search.mibbit.com # Netsplit except ban { mask *@85.25.137.63; } # eagle.netsplit.de +except ban { mask *@85.25.10.40; } # anaconda.netsplit.de \ No newline at end of file diff --git a/doc/conf/ircd.motd b/doc/conf/ircd.motd index 1113ad7..7fc0ae0 100644 --- a/doc/conf/ircd.motd +++ b/doc/conf/ircd.motd @@ -36,12 +36,9 @@ 0,0 0║ ╚0,0 0║ 0,0 0╗ 0,0 0║ ╚0,0 0╔╝ 0╚═╝ ╚════╝ ╚══════╝ ╚═╝ ╚════╝ +4─────────┤ 0THE WILD WILD WEST OF IRC4├───────── +14• 7Do not disrupt the orderly operation of the network +14• 7No distribution of child pornography -4──────────────────┤ 0RULES 4├─────────────────── - -14• 7Do not disrupt or compromise our security. -14• 7No malicious abuse of network services. -14• 7No distribution of child pornography. - -4────────────────────────────────────────────── \ No newline at end of file +8,4 E N T E R T H E V O I D  \ No newline at end of file diff --git a/doc/conf/unrealircd.remote.conf b/doc/conf/unrealircd.remote.conf deleted file mode 100644 index e745785..0000000 --- a/doc/conf/unrealircd.remote.conf +++ /dev/null @@ -1,185 +0,0 @@ -admin { ""; } - -alias botserv { type services; } -alias bs { target botserv; type services; } -alias chanserv { type services; } -alias cs { target chanserv; type services; } -alias hostserv { type services; } -alias hs { target hostserv; type services; } -alias nickserv { type services; } -alias ns { target nickserv; type services; } -alias operserv { type services; } -alias os { target operserv; type services; } - -class clients { pingfreq 120; maxclients 100; sendq 1M; options { nofakelag; } } -class servers { pingfreq 120; maxclients 10; sendq 1M; connfreq 30; } - -allow { ip *; class clients; maxperip 2; } - -listen { ip *; port 6667; options { clientsonly; } } -listen { ip *; port 6697; options { clientsonly; tls; } } -listen { ip *; port REDACTED; options { serversonly; tls; } } - -link irc.supernets.org { - incoming { mask REDACTED; } - outgoing { - bind-ip *; - hostname REDACTED; - port REDACTED; - options { tls; autoconnect; } - } - password "REDACTED" { spkifp; } - class servers; -} - -log "errors.log" { flags { errors; } maxsize 10K; } - -tld { mask *@*; motd remote.motd; rules remote.motd; options { remote; } } - -ulines { services.supernets.org; } - -blacklist dronebl { - dns { - name dnsbl.dronebl.org; - type record; - reply { 3; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; } - } - action gzline; - ban-time 1d; - reason "8,4 E N T E R T H E V O I D "; -} - -blacklist efnetrbl { - dns { - name rbl.efnetrbl.org; - type record; - reply { 1; 4; 5; } - } - action gzline; - ban-time 1d; - reason "8,4 E N T E R T H E V O I D "; -} - -blacklist torbl { - dns { - name torexit.dan.me.uk; - type record; - reply { 100; } - } - action gzline; - ban-time 1d; - reason "8,4 E N T E R T H E V O I D "; -} - -webirc { mask 107.161.19.53; password "REDACTED"; } # KiwiIRC -webirc { mask 107.161.19.109; password "REDACTED"; } -webirc { mask 107.161.31.4; password "REDACTED"; } - -webirc { mask 207.192.75.252; password "REDACTED"; } # Mibbit -webirc { mask 64.62.228.82; password "REDACTED"; } -webirc { mask 78.129.202.38; password "REDACTED"; } -webirc { mask 109.169.29.95 ; password "REDACTED"; } - -set { - kline-address "banned@supernets.org"; - gline-address "banned@supernets.org"; - modes-on-connect "+ipTx"; - modes-on-oper "+HIq"; - snomask-on-oper "+bcFfkGsSo"; - modes-on-join "+ns"; - level-on-join "op"; - restrict-channelmodes "CnLpPs"; - restrict-commands { - invite { connect-delay 3600; exempt-identified yes; } - list { connect-delay 120; exempt-identified yes; } - private-message { connect-delay 300; exempt-identified yes; } - private-notice { connect-delay 3600; exempt-identified yes; } - } - auto-join "#superbowl"; - oper-auto-join "#help"; - static-quit "EMO-QUIT"; - static-part "EMO-PART"; - who-limit 100; - nick-length 20; - maxchannelsperuser 10; - channel-command-prefix "`!@$."; - options { hide-ulines; flat-map; identd-check; } - network-name "SuperNETs"; - default-server "irc.supernets.org"; - services-server "services.supernets.org"; - sasl-server "services.supernets.org"; - help-channel "#help"; - cloak-method ip; - cloak-keys { - "REDACTED"; - "REDACTED"; - "REDACTED"; - } - hiddenhost-prefix "SUPER"; - plaintext-policy { - user warn; - oper deny; - server deny; - user-message "4WARNING: You are not using a secure connection with SSL/TLS"; - oper-message "Network operators must connect using SSL/TLS"; - } - outdated-tls-policy { - user warn; - oper deny; - server deny; - user-message "4WARNING: You are using an outdated SSL/TLS protocol or cipher"; - oper-message "Network operators must connect using an up-to-date SSL/TLS protocol or cipher"; - } - anti-flood { - away-flood 3:300; - connect-flood 3:300; - invite-flood 3:300; - join-flood 3:300; - knock-flood 3:300; - max-concurrent-conversations { users 5; new-user-every 60s; } - nick-flood 3:300; - unknown-flood-amount 2048; - unknown-flood-bantime 1h; - } - default-bantime 1d; - spamfilter { - ban-time 1d; - ban-reason "8,4 E N T E R T H E V O I D "; - except "#anythinggoes"; - } - max-targets-per-command { kick 1; part 1; privmsg 1; } - hide-ban-reason yes; - reject-message { - gline "8,4 E N T E R T H E V O I D "; - kline "8,4 E N T E R T H E V O I D "; - password-mismatch "8,4 E N T E R T H E V O I D "; - server-full "8,4 E N T E R T H E V O I D "; - too-many-connections "8,4 E N T E R T H E V O I D "; - unauthorized "8,4 E N T E R T H E V O I D "; - } - antimixedutf8 { - score 10; - ban-action block; - ban-reason "8,4 E N T E R T H E V O I D "; - ban-time 1h; - } - connthrottle { - known-users { minimum-reputation-score 24; sasl-bypass yes; } - new-users { local-throttle 20:60; global-throttle 30:60; } - disabled-when { reputation-gathering 1w; start-delay 3m; } - } - history { - channel { - playback-on-join { lines 100; time 1d; } - max-storage-per-channel { lines 100; time 1d; } - } - } - manual-ban-target ip; -} - -hideserver { - disable-map yes; - disable-links yes; - map-deny-message "Denied"; - links-deny-message "Denied"; -} \ No newline at end of file diff --git a/extras/doxygen/Doxyfile b/extras/doxygen/Doxyfile index 7e3d7d7..06500ed 100644 --- a/extras/doxygen/Doxyfile +++ b/extras/doxygen/Doxyfile @@ -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.3 +PROJECT_NUMBER = 5.0.4 # 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 diff --git a/extras/tests/tls/cipherscan_profiles/openssl-102-ubuntu16.txt b/extras/tests/tls/cipherscan_profiles/openssl-102-ubuntu16.txt new file mode 100644 index 0000000..347ee63 --- /dev/null +++ b/extras/tests/tls/cipherscan_profiles/openssl-102-ubuntu16.txt @@ -0,0 +1,27 @@ +Target: 127.0.0.1:5901 + +prio ciphersuite protocols pfs curves +1 ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1 +2 ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1 +3 ECDHE-ECDSA-AES256-SHA384 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1 +4 ECDHE-ECDSA-AES256-SHA TLSv1,TLSv1.1,TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1 +5 ECDHE-ECDSA-AES128-SHA256 TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1 +6 ECDHE-ECDSA-AES128-SHA TLSv1,TLSv1.1,TLSv1.2 ECDH,P-521,521bits secp521r1,secp384r1 + +Certificate: untrusted, 384 bits, ecdsa-with-SHA256 signature +TLS ticket lifetime hint: None +NPN protocols: None +OCSP stapling: not supported +Cipher ordering: server +Curves ordering: server - fallback: no +Server supports secure renegotiation +Server supported compression methods: NONE +TLS Tolerance: yes + +Intolerance to: + SSL 3.254 : absent + TLS 1.0 : absent + TLS 1.1 : absent + TLS 1.2 : absent + TLS 1.3 : absent + TLS 1.4 : absent diff --git a/extras/tls.cnf b/extras/tls.cnf index 7a04a4a..46a9611 100644 --- a/extras/tls.cnf +++ b/extras/tls.cnf @@ -18,7 +18,7 @@ stateOrProvinceName_default = New York localityName = Locality Name (eg, city) 0.organizationName = Organization Name (eg, company) -0.organizationName_default = SuperNETs +0.organizationName_default = IRC geeks organizationalUnitName = Organizational Unit Name (eg, section) organizationalUnitName_default = IRCd diff --git a/include/dynconf.h b/include/dynconf.h index 07f9698..5276e07 100644 --- a/include/dynconf.h +++ b/include/dynconf.h @@ -55,6 +55,8 @@ typedef enum AllowedChannelChars { ALLOWED_CHANNELCHARS_ANY=1, ALLOWED_CHANNELCH typedef enum BanTarget { BAN_TARGET_IP=1, BAN_TARGET_USERIP=2, BAN_TARGET_HOST=3, BAN_TARGET_USERHOST=4, BAN_TARGET_ACCOUNT=5, BAN_TARGET_CERTFP=6 } BanTarget; +typedef enum HideIdleTimePolicy { HIDE_IDLE_TIME_NEVER=1, HIDE_IDLE_TIME_ALWAYS=2, HIDE_IDLE_TIME_USERMODE=3, HIDE_IDLE_TIME_OPER_USERMODE=4 } HideIdleTimePolicy; + /** The set { } block configuration */ typedef struct Configuration Configuration; struct Configuration { @@ -97,9 +99,9 @@ struct Configuration { char *static_part; TLSOptions *tls_options; Policy plaintext_policy_user; - char *plaintext_policy_user_message; + MultiLine *plaintext_policy_user_message; Policy plaintext_policy_oper; - char *plaintext_policy_oper_message; + MultiLine *plaintext_policy_oper_message; Policy plaintext_policy_server; Policy outdated_tls_policy_user; char *outdated_tls_policy_user_message; @@ -171,6 +173,7 @@ struct Configuration { int part_instead_of_quit_on_comment_change; BroadcastChannelMessagesOption broadcast_channel_messages; AllowedChannelChars allowed_channelchars; + HideIdleTimePolicy hide_idle_time; }; extern MODVAR Configuration iConf; diff --git a/include/h.h b/include/h.h index a31729d..2d4cfc0 100644 --- a/include/h.h +++ b/include/h.h @@ -911,6 +911,8 @@ extern void badword_config_free(ConfigItem_badword *ca); extern char *badword_config_check_regex(char *s, int fastsupport, int check_broadness); extern AllowedChannelChars allowed_channelchars_strtoval(char *str); extern char *allowed_channelchars_valtostr(AllowedChannelChars v); +extern HideIdleTimePolicy hideidletime_strtoval(char *str); +extern char *hideidletime_valtostr(HideIdleTimePolicy v); extern long ClientCapabilityBit(const char *token); extern int is_handshake_finished(Client *client); extern void SetCapability(Client *acptr, const char *token); @@ -958,6 +960,7 @@ extern char *filename_add_suffix(const char *fname, const char *suffix); extern int filename_has_suffix(const char *fname, const char *suffix); extern void addmultiline(MultiLine **l, char *line); extern void freemultiline(MultiLine *l); +#define safe_free_multiline(x) do { if (x) freemultiline(x); x = NULL; } while(0) extern void sendnotice_multiline(Client *client, MultiLine *m); extern void unreal_del_quotes(char *i); extern char *unreal_add_quotes(char *str); @@ -965,3 +968,5 @@ extern int unreal_add_quotes_r(char *i, char *o, size_t len); extern void user_account_login(MessageTag *recv_mtags, Client *client); extern void link_generator(void); extern void update_throttling_timer_settings(void); +extern int hide_idle_time(Client *client, Client *target); +extern void lost_server_link(Client *serv, FORMAT_STRING(const char *fmt), ...); diff --git a/include/modules.h b/include/modules.h index dad5f0a..5dfaceb 100644 --- a/include/modules.h +++ b/include/modules.h @@ -650,6 +650,7 @@ struct Event { vFP event; /**< Actual function to call */ void *data; /**< The data to pass in the function call */ struct timeval last_run; /**< Last time this event ran */ + char deleted; /**< Set to 1 if this event is marked for deletion */ Module *owner; /**< To which module this event belongs */ }; @@ -676,7 +677,7 @@ extern MODVAR Callback *Callbacks[MAXCALLBACKS], *RCallbacks[MAXCALLBACKS]; extern MODVAR ClientCapability *clicaps; extern Event *EventAdd(Module *module, char *name, vFP event, void *data, long every_msec, int count); -extern Event *EventDel(Event *event); +extern void EventDel(Event *event); extern Event *EventMarkDel(Event *event); extern Event *EventFind(char *name); extern int EventMod(Event *event, EventInfo *mods); diff --git a/include/setup.h.in b/include/setup.h.in index 492bf43..071688f 100644 --- a/include/setup.h.in +++ b/include/setup.h.in @@ -34,6 +34,9 @@ /* Define if ssl library has SSL_CTX_set_min_proto_version */ #undef HAS_SSL_CTX_SET_MIN_PROTO_VERSION +/* Define if ssl library has SSL_CTX_set_security_level */ +#undef HAS_SSL_CTX_SET_SECURITY_LEVEL + /* Define if you have crypt */ #undef HAVE_CRYPT diff --git a/include/windows/setup.h b/include/windows/setup.h index 0b86df7..e7394c8 100644 --- a/include/windows/setup.h +++ b/include/windows/setup.h @@ -63,10 +63,10 @@ #define UNREAL_VERSION_MAJOR 0 /* Minor version number (e.g.: 1 for Unreal3.2.1) */ -#define UNREAL_VERSION_MINOR 3 +#define UNREAL_VERSION_MINOR 4 /* Version suffix such as a beta marker or release candidate marker. (e.g.: -rcX for unrealircd-3.2.9-rcX) */ -#define UNREAL_VERSION_SUFFIX ".1" +#define UNREAL_VERSION_SUFFIX "" #endif diff --git a/src/api-event.c b/src/api-event.c index 6dcb888..2044e5b 100644 --- a/src/api-event.c +++ b/src/api-event.c @@ -87,40 +87,69 @@ Event *EventAdd(Module *module, char *name, vFP event, void *data, long every_ms } -Event *EventMarkDel(Event *event) +/** Mark the Event for deletion. + * The actual deletion of the event happens later on + * (which is of no concern to the caller). + */ +void EventDel(Event *e) { - event->count = -1; - return event; + char buf[128]; + + /* Mark for deletion */ + e->deleted = 1; + + /* Replace the name so deleted events are clearly labeled */ + if (e->name) + { + snprintf(buf, sizeof(buf), "deleted:%s", e->name); + safe_strdup(e->name, buf); + } + + /* Remove the event from the module, that is something we can safely do straight away */ + if (e->owner) + { + ModuleObject *eventobjs; + for (eventobjs = e->owner->objects; eventobjs; eventobjs = eventobjs->next) + { + if (eventobjs->type == MOBJ_EVENT && eventobjs->object.event == e) + { + DelListItem(eventobjs, e->owner->objects); + safe_free(eventobjs); + break; + } + } + e->owner = NULL; + } } -Event *EventDel(Event *event) +/** Remove the event for real, used only via CleanupEvents(), not for end-users. */ +static void EventDelReal(Event *e) { - Event *p, *q; - for (p = events; p; p = p->next) + if (!e->deleted) { - if (p == event) - { - q = p->next; - safe_free(p->name); - DelListItem(p, events); - if (p->owner) - { - ModuleObject *eventobjs; - for (eventobjs = p->owner->objects; eventobjs; eventobjs = eventobjs->next) - { - if (eventobjs->type == MOBJ_EVENT && eventobjs->object.event == p) - { - DelListItem(eventobjs, p->owner->objects); - safe_free(eventobjs); - break; - } - } - } - safe_free(p); - return q; - } + ircd_log(LOG_ERROR, "EventDelReal called while e->deleted is 0. This cannot happen. Event name: %s.", e->name); + abort(); + } + if (e->owner) + { + ircd_log(LOG_ERROR, "EventDelReal called while e->owner is non-NULL. This cannot happen. Event name: %s.", e->name); + abort(); + } + safe_free(e->name); + DelListItem(e, events); + safe_free(e); +} + +/** Remove any events that were previously marked for deletion */ +static void CleanupEvents(void) +{ + Event *e, *e_next; + for (e = events; e; e = e_next) + { + e_next = e->next; + if (e->deleted) + EventDelReal(e); } - return NULL; } Event *EventFind(char *name) @@ -171,11 +200,12 @@ int EventMod(Event *event, EventInfo *mods) void DoEvents(void) { - Event *e, *e_next; + Event *e; - for (e = events; e; e = e_next) + for (e = events; e; e = e->next) { - e_next = e->next; + if (e->deleted) + continue; if (e->count == -1) { EventDel(e); @@ -195,6 +225,8 @@ void DoEvents(void) } } } + + CleanupEvents(); } void SetupEvents(void) diff --git a/src/api-usermode.c b/src/api-usermode.c index cdecac5..b195c4f 100644 --- a/src/api-usermode.c +++ b/src/api-usermode.c @@ -61,6 +61,9 @@ long SNO_OPER = 0L; long AllUmodes; /* All umodes */ long SendUmodes; /* All umodes which are sent to other servers (global umodes) */ +/* Forward declarations */ +int umode_hidle_allow(Client *client, int what); + void umode_init(void) { long val = 1; @@ -93,7 +96,7 @@ void umode_init(void) UmodeAdd(NULL, 'd', UMODE_GLOBAL, 0, umode_allow_all, &UMODE_DEAF); UmodeAdd(NULL, 'H', UMODE_GLOBAL, 1, umode_allow_opers, &UMODE_HIDEOPER); UmodeAdd(NULL, 't', UMODE_GLOBAL, 0, umode_allow_unset, &UMODE_SETHOST); - UmodeAdd(NULL, 'I', UMODE_GLOBAL, 1, umode_allow_opers, &UMODE_HIDLE); + UmodeAdd(NULL, 'I', UMODE_GLOBAL, 0, umode_hidle_allow, &UMODE_HIDLE); SnomaskAdd(NULL, 'k', umode_allow_opers, &SNO_KILLS); SnomaskAdd(NULL, 'c', umode_allow_opers, &SNO_CLIENT); SnomaskAdd(NULL, 'f', umode_allow_opers, &SNO_FLOOD); @@ -378,6 +381,17 @@ int umode_allow_opers(Client *client, int what) return 1; } +int umode_hidle_allow(Client *client, int what) +{ + if (!MyUser(client)) + return 1; + if (iConf.hide_idle_time == HIDE_IDLE_TIME_OPER_USERMODE) + return IsOper(client) ? 1 : 0; + if (iConf.hide_idle_time == HIDE_IDLE_TIME_USERMODE) + return 1; + return 0; /* if set::hide-idle-time is 'never' or 'always' then +I makes no sense */ +} + void unload_all_unused_umodes(void) { long removed_umode = 0; @@ -469,6 +483,10 @@ int i; if (Usermode_Table[i].unset_on_deoper) client->umodes &= ~Usermode_Table[i].mode; } + + /* Bit of a hack, since this is a dynamic permission umode */ + if (iConf.hide_idle_time == HIDE_IDLE_TIME_OPER_USERMODE) + client->umodes &= ~UMODE_HIDLE; } void remove_oper_privileges(Client *client, int broadcast_mode_change) diff --git a/src/conf.c b/src/conf.c index e65ebee..97ca505 100644 --- a/src/conf.c +++ b/src/conf.c @@ -787,6 +787,36 @@ char *ban_target_valtostr(BanTarget v) } } +HideIdleTimePolicy hideidletime_strtoval(char *str) +{ + if (!strcmp(str, "never")) + return HIDE_IDLE_TIME_NEVER; + else if (!strcmp(str, "always")) + return HIDE_IDLE_TIME_ALWAYS; + else if (!strcmp(str, "usermode")) + return HIDE_IDLE_TIME_USERMODE; + else if (!strcmp(str, "oper-usermode")) + return HIDE_IDLE_TIME_OPER_USERMODE; + return 0; +} + +char *hideidletime_valtostr(HideIdleTimePolicy v) +{ + switch(v) + { + case HIDE_IDLE_TIME_NEVER: + return "never"; + case HIDE_IDLE_TIME_ALWAYS: + return "always"; + case HIDE_IDLE_TIME_USERMODE: + return "usermode"; + case HIDE_IDLE_TIME_OPER_USERMODE: + return "oper-usermode"; + default: + return "INVALID"; + } +} + ConfigFile *config_load(char *filename, char *displayname) { struct stat sb; @@ -1586,8 +1616,8 @@ void free_iConf(Configuration *i) free_tls_options(i->tls_options); i->tls_options = NULL; safe_free(i->tls_options); - safe_free(i->plaintext_policy_user_message); - safe_free(i->plaintext_policy_oper_message); + safe_free_multiline(i->plaintext_policy_user_message); + safe_free_multiline(i->plaintext_policy_oper_message); safe_free(i->outdated_tls_policy_user_message); safe_free(i->outdated_tls_policy_oper_message); safe_free(i->restrict_usermodes); @@ -1714,6 +1744,8 @@ void config_setdefaultsettings(Configuration *i) i->automatic_ban_target = BAN_TARGET_IP; i->manual_ban_target = BAN_TARGET_HOST; + + i->hide_idle_time = HIDE_IDLE_TIME_OPER_USERMODE; } static void make_default_logblock(void) @@ -1742,18 +1774,21 @@ void postconf_defaults(void) { /* The message depends on whether it's reject or warn.. */ if (iConf.plaintext_policy_user == POLICY_DENY) - safe_strdup(iConf.plaintext_policy_user_message, "Insecure connection. Please reconnect using SSL/TLS."); + addmultiline(&iConf.plaintext_policy_user_message, "Insecure connection. Please reconnect using SSL/TLS."); else if (iConf.plaintext_policy_user == POLICY_WARN) - safe_strdup(iConf.plaintext_policy_user_message, "WARNING: Insecure connection. Please consider using SSL/TLS."); + addmultiline(&iConf.plaintext_policy_user_message, "WARNING: Insecure connection. Please consider using SSL/TLS."); } if (!iConf.plaintext_policy_oper_message) { /* The message depends on whether it's reject or warn.. */ if (iConf.plaintext_policy_oper == POLICY_DENY) - safe_strdup(iConf.plaintext_policy_oper_message, "You need to use a secure connection (SSL/TLS) in order to /OPER."); + { + addmultiline(&iConf.plaintext_policy_oper_message, "You need to use a secure connection (SSL/TLS) in order to /OPER."); + addmultiline(&iConf.plaintext_policy_oper_message, "See https://www.unrealircd.org/docs/FAQ#oper-requires-tls"); + } else if (iConf.plaintext_policy_oper == POLICY_WARN) - safe_strdup(iConf.plaintext_policy_oper_message, "WARNING: You /OPER'ed up from an insecure connection. Please consider using SSL/TLS."); + addmultiline(&iConf.plaintext_policy_oper_message, "WARNING: You /OPER'ed up from an insecure connection. Please consider using SSL/TLS."); } if (!iConf.outdated_tls_policy_user_message) @@ -7674,9 +7709,9 @@ int _conf_set(ConfigFile *conf, ConfigEntry *ce) else if (!strcmp(cepp->ce_varname, "server")) tempiConf.plaintext_policy_server = policy_strtoval(cepp->ce_vardata); else if (!strcmp(cepp->ce_varname, "user-message")) - safe_strdup(tempiConf.plaintext_policy_user_message, cepp->ce_vardata); + addmultiline(&tempiConf.plaintext_policy_user_message, cepp->ce_vardata); else if (!strcmp(cepp->ce_varname, "oper-message")) - safe_strdup(tempiConf.plaintext_policy_oper_message, cepp->ce_vardata); + addmultiline(&tempiConf.plaintext_policy_oper_message, cepp->ce_vardata); } } else if (!strcmp(cep->ce_varname, "outdated-tls-policy")) @@ -7782,12 +7817,15 @@ int _conf_set(ConfigFile *conf, ConfigEntry *ce) } else if (!strcmp(cep->ce_varname, "allowed-channelchars")) { - if (!strcmp(cep->ce_vardata, "ascii")) - tempiConf.allowed_channelchars = ALLOWED_CHANNELCHARS_ASCII; - else if (!strcmp(cep->ce_vardata, "utf8")) - tempiConf.allowed_channelchars = ALLOWED_CHANNELCHARS_UTF8; - else if (!strcmp(cep->ce_vardata, "any")) - tempiConf.allowed_channelchars = ALLOWED_CHANNELCHARS_ANY; + tempiConf.allowed_channelchars = allowed_channelchars_strtoval(cep->ce_vardata); + } + else if (!strcmp(cep->ce_varname, "hide-idle-time")) + { + for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) + { + if (!strcmp(cepp->ce_varname, "policy")) + tempiConf.hide_idle_time = hideidletime_strtoval(cepp->ce_vardata); + } } else { @@ -8976,15 +9014,37 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce) else if (!strcmp(cep->ce_varname, "allowed-channelchars")) { CheckNull(cep); - if (strcmp(cep->ce_vardata, "ascii") && - strcmp(cep->ce_vardata, "utf8") && - strcmp(cep->ce_vardata, "any")) + if (!allowed_channelchars_strtoval(cep->ce_vardata)) { config_error("%s:%i: set::allowed-channelchars: value should be one of: 'ascii', 'utf8' or 'any'", cep->ce_fileptr->cf_filename, cep->ce_varlinenum); errors++; } } + else if (!strcmp(cep->ce_varname, "hide-idle-time")) + { + for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) + { + CheckNull(cepp); + if (!strcmp(cepp->ce_varname, "policy")) + { + if (!hideidletime_strtoval(cepp->ce_vardata)) + { + config_error("%s:%i: set::hide-idle-time::policy: value should be one of: 'never', 'always', 'usermode' or 'oper-usermode'", + cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum); + errors++; + } + } + else + { + config_error_unknown(cepp->ce_fileptr->cf_filename, + cepp->ce_varlinenum, "set::hide-idle-time", + cepp->ce_varname); + errors++; + continue; + } + } + } else { int used = 0; diff --git a/src/dns.c b/src/dns.c index 4fe8a80..edaa674 100644 --- a/src/dns.c +++ b/src/dns.c @@ -420,7 +420,7 @@ void unrealdns_cb_nametoip_link(void *arg, int status, int timeouts, struct host switch ((n = connect_server(r->linkblock, r->client, he2))) { case 0: - sendto_ops_and_log("Connecting to server %s[%s].", r->linkblock->servername, ip); + sendto_ops_and_log("Trying to activate link with server %s[%s]...", r->linkblock->servername, ip); break; case -1: sendto_ops_and_log("Couldn't connect to server %s[%s].", r->linkblock->servername, ip); diff --git a/src/ircd.c b/src/ircd.c index 60fef06..6a8b972 100644 --- a/src/ircd.c +++ b/src/ircd.c @@ -312,7 +312,7 @@ EVENT(try_connections) break; if (!deny && connect_server(aconf, NULL, NULL) == 0) - sendto_realops("Connection to %s[%s] activated.", + sendto_ops_and_log("Trying to activate link with server %s[%s]...", aconf->servername, aconf->outgoing.hostname); } @@ -393,7 +393,7 @@ EVENT(handshake_timeout) if (client->serv && *client->serv->by) { /* If this is a handshake timeout to an outgoing server then notify ops & log it */ - sendto_ops_and_log("Connection handshake timeout while connecting to server '%s' (%s)", + sendto_ops_and_log("Connection handshake timeout while trying to link to server '%s' (%s)", client->name, client->ip?client->ip:""); } @@ -534,9 +534,6 @@ EVENT(check_deadsockets) { if (!IsDead(client)) abort(); /* impossible */ -#ifdef DEBUGMODE - ircd_log(LOG_ERROR, "Closing deadsock2: %s", client->name); -#endif list_del(&client->client_node); free_client(client); } diff --git a/src/modules/channeldb.c b/src/modules/channeldb.c index 51a77ae..882fbd6 100644 --- a/src/modules/channeldb.c +++ b/src/modules/channeldb.c @@ -84,6 +84,12 @@ MOD_INIT() setcfg(); + HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, channeldb_configrun); + return MOD_SUCCESS; +} + +MOD_LOAD() +{ if (!channeldb_loaded) { /* If this is the first time that our module is loaded, then read the database. */ @@ -98,12 +104,6 @@ MOD_INIT() } channeldb_loaded = 1; } - HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, channeldb_configrun); - return MOD_SUCCESS; -} - -MOD_LOAD() -{ EventAdd(modinfo->handle, "channeldb_write_channeldb", write_channeldb_evt, NULL, CHANNELDB_SAVE_EVERY*1000, 0); if (ModuleGetError(modinfo->handle) != MODERR_NOERROR) { diff --git a/src/modules/connect.c b/src/modules/connect.c index 306998e..e5c47bd 100644 --- a/src/modules/connect.c +++ b/src/modules/connect.c @@ -137,7 +137,7 @@ CMD_FUNC(cmd_connect) switch (retval = connect_server(aconf, client, NULL)) { case 0: - sendnotice(client, "*** Connecting to %s[%s].", + sendnotice(client, "*** Trying to activate link with server %s[%s]...", aconf->servername, aconf->outgoing.hostname); break; case -1: diff --git a/src/modules/ident_lookup.c b/src/modules/ident_lookup.c index dd6712d..884af33 100644 --- a/src/modules/ident_lookup.c +++ b/src/modules/ident_lookup.c @@ -63,8 +63,20 @@ static EVENT(check_ident_timeout) list_for_each_entry_safe(client, next, &unknown_list, lclient_node) { - if (IsIdentLookup(client) && ((TStime() - client->local->firsttime) > IDENT_CONNECT_TIMEOUT)) - ident_lookup_failed(client); + if (IsIdentLookup(client)) + { + if (IsIdentLookupSent(client)) + { + /* set::ident::connect-timeout */ + if ((TStime() - client->local->firsttime) > IDENT_CONNECT_TIMEOUT) + ident_lookup_failed(client); + } else + { + /* set::ident::read-timeout */ + if ((TStime() - client->local->firsttime) > IDENT_READ_TIMEOUT) + ident_lookup_failed(client); + } + } } } diff --git a/src/modules/join.c b/src/modules/join.c index 2ac292e..f89bc18 100644 --- a/src/modules/join.c +++ b/src/modules/join.c @@ -441,7 +441,7 @@ void _do_join(Client *client, int parc, char *parv[]) new_message(client, NULL, &mtags); - sendto_channel(channel, client, NULL, 0, 0, SEND_LOCAL, NULL, + sendto_channel(channel, client, NULL, 0, 0, SEND_LOCAL, mtags, ":%s PART %s :%s", client->name, channel->chname, "Left all channels"); sendto_server(client, 0, 0, mtags, ":%s PART %s :Left all channels", client->name, channel->chname); diff --git a/src/modules/nick.c b/src/modules/nick.c index daf1e9d..9cf9704 100644 --- a/src/modules/nick.c +++ b/src/modules/nick.c @@ -1085,7 +1085,7 @@ int _register_user(Client *client, char *nick, char *username, char *umode, char sendnumeric(client, RPL_SNOMASK, get_snomask_string_raw(user->snomask)); if (!IsSecure(client) && !IsLocalhost(client) && (iConf.plaintext_policy_user == POLICY_WARN)) - sendnotice(client, "%s", iConf.plaintext_policy_user_message); + sendnotice_multiline(client, iConf.plaintext_policy_user_message); if (IsSecure(client) && (iConf.outdated_tls_policy_user == POLICY_WARN) && outdated_tls_client(client)) sendnotice(client, "%s", outdated_tls_client_build_string(iConf.outdated_tls_policy_user_message, client)); @@ -1300,7 +1300,7 @@ int AllowClient(Client *client, char *username) if (!IsSecure(client) && !IsLocalhost(client) && (iConf.plaintext_policy_user == POLICY_DENY)) { - exit_client(client, NULL, iConf.plaintext_policy_user_message); + exit_client(client, NULL, iConf.plaintext_policy_user_message->line); return 0; } diff --git a/src/modules/oper.c b/src/modules/oper.c index f9776cf..ee7d89a 100644 --- a/src/modules/oper.c +++ b/src/modules/oper.c @@ -114,7 +114,7 @@ CMD_FUNC(cmd_oper) /* set::plaintext-policy::oper 'deny' */ if (!IsSecure(client) && !IsLocalhost(client) && (iConf.plaintext_policy_oper == POLICY_DENY)) { - sendnotice(client, "%s", iConf.plaintext_policy_oper_message); + sendnotice_multiline(client, iConf.plaintext_policy_oper_message); sendto_snomask_global (SNO_OPER, "Failed OPER attempt by %s (%s@%s) [not using SSL/TLS]", client->name, client->user->username, client->local->sockhost); @@ -315,7 +315,7 @@ CMD_FUNC(cmd_oper) /* set::plaintext-policy::oper 'warn' */ if (!IsSecure(client) && !IsLocalhost(client) && (iConf.plaintext_policy_oper == POLICY_WARN)) { - sendnotice(client, "%s", iConf.plaintext_policy_oper_message); + sendnotice_multiline(client, iConf.plaintext_policy_oper_message); sendto_snomask_global (SNO_OPER, "OPER %s [%s] used an insecure (non-SSL/TLS) connection to /OPER.", client->name, name); diff --git a/src/modules/sajoin.c b/src/modules/sajoin.c index ea3496a..9388c5a 100644 --- a/src/modules/sajoin.c +++ b/src/modules/sajoin.c @@ -221,10 +221,10 @@ CMD_FUNC(cmd_sajoin) channel = lp->channel; new_message(target, NULL, &mtags); - sendto_channel(channel, target, NULL, 0, 0, SEND_LOCAL, NULL, + sendto_channel(channel, target, NULL, 0, 0, SEND_LOCAL, mtags, ":%s PART %s :%s", target->name, channel->chname, "Left all channels"); - sendto_server(client, 0, 0, mtags, ":%s PART %s :Left all channels", target->name, channel->chname); + sendto_server(NULL, 0, 0, mtags, ":%s PART %s :Left all channels", target->name, channel->chname); if (MyConnect(target)) RunHook4(HOOKTYPE_LOCAL_PART, target, channel, mtags, "Left all channels"); free_message_tags(mtags); @@ -275,5 +275,22 @@ CMD_FUNC(cmd_sajoin) strlcat(jbuf, ",", sizeof jbuf); strlcat(jbuf, name, sizeof jbuf); } + if (did_anything) + { + if (!sjmode) + { + //sendnotice(target, "*** You were forced to join %s", jbuf); + sendto_umode_global(UMODE_OPER, "%s used SAJOIN to make %s join %s", client->name, target->name, jbuf); + ircd_log(LOG_SACMDS,"SAJOIN: %s used SAJOIN to make %s join %s", + client->name, target->name, jbuf); + } + else + { + //sendnotice(target, "*** You were forced to join %s with '%c'", jbuf, sjmode); + sendto_umode_global(UMODE_OPER, "%s used SAJOIN to make %s join %c%s", client->name, target->name, sjmode, jbuf); + ircd_log(LOG_SACMDS,"SAJOIN: %s used SAJOIN to make %s join %c%s", + client->name, target->name, sjmode, jbuf); + } + } } } diff --git a/src/modules/sapart.c b/src/modules/sapart.c index d783fdd..b981e30 100644 --- a/src/modules/sapart.c +++ b/src/modules/sapart.c @@ -159,6 +159,22 @@ CMD_FUNC(cmd_sapart) parv[0] = target->name; // nick parv[1] = parv[2]; // chan parv[2] = comment ? commentx : NULL; // comment + if (comment) + { + //sendnotice(target, "*** You were forced to part %s (%s)", parv[1], commentx); + sendto_umode_global(UMODE_OPER, "%s used SAPART to make %s part %s (%s)", + client->name, target->name, parv[1], comment); + ircd_log(LOG_SACMDS,"SAPART: %s used SAPART to make %s part %s (%s)", + client->name, target->name, parv[1], comment); + } + else + { + //sendnotice(target, "*** You were forced to part %s", parv[1]); + sendto_umode_global(UMODE_OPER, "%s used SAPART to make %s part %s", + client->name, target->name, parv[1]); + ircd_log(LOG_SACMDS,"SAPART: %s used SAPART to make %s part %s", + client->name, target->name, parv[1]); + } do_cmd(target, NULL, "PART", comment ? 3 : 2, parv); /* target may be killed now due to the part reason @ spamfilter */ } diff --git a/src/modules/server.c b/src/modules/server.c index 9722a3e..4e7d0d4 100644 --- a/src/modules/server.c +++ b/src/modules/server.c @@ -547,6 +547,7 @@ CMD_FUNC(cmd_server) sendto_umode_global(UMODE_OPER, "Directly linked server %s provided a hopcount of %d, while 1 was expected", servername, hop); exit_client(client, NULL, "Invalid SERVER message, hop count must be 1"); + return; } client->hopcount = hop; diff --git a/src/modules/svsmode.c b/src/modules/svsmode.c index 4772abc..fd9f04f 100644 --- a/src/modules/svsmode.c +++ b/src/modules/svsmode.c @@ -407,6 +407,13 @@ void do_svsmode(Client *client, MessageTag *recv_mtags, int parc, char *parv[], if (parv[3]) { strlcpy(target->user->svid, parv[3], sizeof(target->user->svid)); + if(MyConnect(target)) + /* Notify user */ + sendnumeric(target, RPL_LOGGEDIN, + BadPtr(target->name) ? "*" : target->name, + BadPtr(target->user->username) ? "*" : target->user->username, + BadPtr(target->user->realhost) ? "*" : target->user->realhost, + target->user->svid, target->user->svid); user_account_login(recv_mtags, target); } else diff --git a/src/modules/tkl.c b/src/modules/tkl.c index 30a4ffe..a69a347 100644 --- a/src/modules/tkl.c +++ b/src/modules/tkl.c @@ -1028,8 +1028,8 @@ CMD_FUNC(cmd_tempshun) } if (!MyUser(target)) { - sendto_one(target->direction, NULL, ":%s TEMPSHUN %s :%s", - client->id, target->id, comment); + sendto_one(target, NULL, ":%s TEMPSHUN %c%s :%s", + client->id, remove ? '-' : '+', target->id, comment); } else { char buf[1024]; if (!remove) @@ -1747,7 +1747,7 @@ CMD_FUNC(cmd_eline) /** Helper function for cmd_spamfilter, explaining usage. */ void spamfilter_usage(Client *client) { - sendnotice(client, "Use: /spamfilter [add|del|remove|+|-] [-simple|-regex|-posix] [type] [action] [tkltime] [tklreason] [regex]"); + sendnotice(client, "Use: /spamfilter [add|del|remove|+|-] [-simple|-regex] [type] [action] [tkltime] [tklreason] [regex]"); sendnotice(client, "See '/helpop ?spamfilter' for more information."); sendnotice(client, "For an easy way to remove an existing spamfilter, use '/spamfilter del' without additional parameters"); } @@ -1755,13 +1755,12 @@ void spamfilter_usage(Client *client) /** Helper function for cmd_spamfilter, explaining usage has changed. */ void spamfilter_new_usage(Client *client, char *parv[]) { - sendnotice(client, "Unknown match-type '%s'. Must be one of: -regex (new fast PCRE regexes), " - "-posix (old unreal 3.2.x posix regexes) or " + sendnotice(client, "Unknown match-type '%s'. Must be one of: -regex (new fast PCRE regexes) or " "-simple (simple text with ? and * wildcards)", parv[2]); if (*parv[2] != '-') - sendnotice(client, "Using the old 3.2.x /SPAMFILTER syntax? Note the new -regex/-posix/-simple field!!"); + sendnotice(client, "Using the old 3.2.x /SPAMFILTER syntax? Note the new -regex/-simple field!!"); spamfilter_usage(client); } @@ -4209,8 +4208,11 @@ CMD_FUNC(cmd_tkl_del) RunHook2(HOOKTYPE_TKL_DEL, client, tkl); if (type & TKL_GLOBAL) + { + /* This is a bit of a hack for #5629. Will consider real fix post-release. */ + safe_strdup(tkl->set_by, removed_by); tkl_broadcast_entry(0, client, client, tkl); - + } if (TKLIsBanException(tkl)) { @@ -4252,7 +4254,7 @@ CMD_FUNC(cmd_tkl_del) * * [A] tkl reason field must be escaped by caller [eg: use unreal_encodespace() * if cmd_tkl is called internally]. - * [B] match-type must be one of: regex, simple, posix. + * [B] match-type must be one of: regex, simple. * [C] Could be a regex or a regular string with wildcards, depending on [B] */ CMD_FUNC(_cmd_tkl) diff --git a/src/modules/whois.c b/src/modules/whois.c index b739327..c4ec3cc 100644 --- a/src/modules/whois.c +++ b/src/modules/whois.c @@ -315,6 +315,12 @@ CMD_FUNC(cmd_whois) RunHook2(HOOKTYPE_WHOIS, client, target); + if (IsOper(client) && MyUser(target) && IsShunned(target)) + { + sendto_one(client, NULL, ":%s %d %s %s :is shunned", + me.name, RPL_WHOISSPECIAL, client->name, target->name); + } + if (target->user->swhois && !hideoper) { SWhois *s; @@ -336,7 +342,7 @@ CMD_FUNC(cmd_whois) * Umode +I hides an oper's idle time from regular users. * -Nath. */ - if (MyConnect(target) && (IsOper(client) || !(target->umodes & UMODE_HIDLE))) + if (MyConnect(target) && !hide_idle_time(client, target)) { sendnumeric(client, RPL_WHOISIDLE, name, TStime() - target->local->last, target->local->firsttime); diff --git a/src/modules/whox.c b/src/modules/whox.c index 3e34e96..23767af 100644 --- a/src/modules/whox.c +++ b/src/modules/whox.c @@ -8,10 +8,18 @@ #include "unrealircd.h" -#define MSG_WHO "WHO" +/* Module header */ +ModuleHeader MOD_HEADER + = { + "whox", + "5.0", + "command /who", + "UnrealIRCd Team", + "unrealircd-5", + }; -#define FLAGS_MARK 0x400000 /* marked client (was hybnotice) */ +/* Defines */ #define FIELD_CHANNEL 0x0001 #define FIELD_HOP 0x0002 #define FIELD_FLAGS 0x0004 @@ -43,13 +51,14 @@ #define WHO_ADD 1 #define WHO_DEL 0 -#define SetMark(x) ((x)->flags |= FLAGS_MARK) -#define ClearMark(x) ((x)->flags &= ~FLAGS_MARK) -#define IsMarked(x) ((x)->flags & FLAGS_MARK) - #define HasField(x, y) ((x)->fields & (y)) #define IsMatch(x, y) ((x)->matchsel & (y)) +#define IsMarked(x) (moddata_client(x, whox_md).l) +#define SetMark(x) do { moddata_client(x, whox_md).l = 1; } while(0) +#define ClearMark(x) do { moddata_client(x, whox_md).l = 0; } while(0) + +/* Structs */ struct who_format { int fields; @@ -61,30 +70,46 @@ struct who_format int show_ip; }; +/* Global variables */ +ModDataInfo *whox_md = NULL; + +/* Forward declarations */ CMD_FUNC(cmd_whox); static void who_global(Client *client, char *mask, int operspy, struct who_format *fmt); static void do_who(Client *client, Client *acptr, Channel *channel, struct who_format *fmt); static void do_who_on_channel(Client *client, Channel *channel, int member, int operspy, struct who_format *fmt); static int convert_classical_who_request(Client *client, int *parc, char *parv[], char **orig_mask, struct who_format *fmt); - -ModuleHeader MOD_HEADER - = { - "whox", - "5.0", - "command /who", - "UnrealIRCd Team", - "unrealircd-5", - }; +char *whox_md_serialize(ModData *m); +void whox_md_unserialize(char *str, ModData *m); +void whox_md_free(ModData *md); MOD_INIT() { + ModDataInfo mreq; + MARK_AS_OFFICIAL_MODULE(modinfo); - if (!CommandAdd(modinfo->handle, MSG_WHO, cmd_whox, MAXPARA, CMD_USER)) + + if (!CommandAdd(modinfo->handle, "WHO", cmd_whox, MAXPARA, CMD_USER)) { config_warn("You cannot load both cmd_whox and cmd_who. You should ONLY load the cmd_whox module."); return MOD_FAILED; } + + memset(&mreq, 0, sizeof(mreq)); + mreq.name = "whox"; + mreq.type = MODDATATYPE_CLIENT; + mreq.serialize = whox_md_serialize; + mreq.unserialize = whox_md_unserialize; + mreq.free = whox_md_free; + mreq.sync = 0; + whox_md = ModDataAdd(modinfo->handle, mreq); + if (!whox_md) + { + config_error("could not register whox moddata"); + return MOD_FAILED; + } + ISupportAdd(modinfo->handle, "WHOX", NULL); return MOD_SUCCESS; } @@ -99,6 +124,29 @@ MOD_UNLOAD() return MOD_SUCCESS; } +/** whox module data operations: serialize (rare) */ +char *whox_md_serialize(ModData *m) +{ + static char buf[32]; + if (m->i == 0) + return NULL; /* not set */ + snprintf(buf, sizeof(buf), "%d", m->i); + return buf; +} + +/** whox module data operations: unserialize (rare) */ +void whox_md_unserialize(char *str, ModData *m) +{ + m->i = atoi(str); +} + +/** whox module data operations: free */ +void whox_md_free(ModData *md) +{ + /* we have nothing to free actually, but we must set to zero */ + md->l = 0; +} + /** cmd_whox: standardized "extended" version of WHO. * The good thing about WHOX is that it allows the client to define what * output they want to see. Another good thing is that it is standardized @@ -792,9 +840,10 @@ static void do_who(Client *client, Client *acptr, Channel *channel, struct who_f if (HasField(fmt, FIELD_HOP)) append_format(str, sizeof str, &pos, " %d", hide ? 0 : acptr->hopcount); if (HasField(fmt, FIELD_IDLE)) - append_format(str, sizeof str, &pos, " %d", (int)(MyUser(acptr) && - (!(acptr->umodes & UMODE_HIDLE) || IsOper(client) || - (client == acptr)) ? TStime() - acptr->local->last : 0)); + { + append_format(str, sizeof str, &pos, " %d", + (int)((MyUser(acptr) && !hide_idle_time(client, acptr)) ? (TStime() - acptr->local->last) : 0)); + } if (HasField(fmt, FIELD_ACCOUNT)) append_format(str, sizeof str, &pos, " %s", (!isdigit(*acptr->user->svid)) ? acptr->user->svid : "0"); if (HasField(fmt, FIELD_OPLEVEL)) diff --git a/src/random.c b/src/random.c index 00c8814..0fc33bc 100644 --- a/src/random.c +++ b/src/random.c @@ -438,18 +438,16 @@ void init_random() { struct { #ifndef _WIN32 - struct timeval nowt; /* time */ + struct timeval nowt; /* time */ char rnd[32]; /* /dev/urandom */ #else - MEMORYSTATUS mstat; /* memory status */ struct _timeb nowt; /* time */ + MEMORYSTATUS mstat; /* memory status */ #endif } rdat; #ifndef _WIN32 int fd; -#else - MEMORYSTATUS mstat; #endif _rs_stir(); diff --git a/src/serv.c b/src/serv.c index a6a2650..70aa904 100644 --- a/src/serv.c +++ b/src/serv.c @@ -405,9 +405,6 @@ CMD_FUNC(cmd_error) para = (parc > 1 && *parv[1] != '\0') ? parv[1] : "<>"; - Debug((DEBUG_ERROR, "Received ERROR message from %s: %s", - client->name, para)); - /* Errors from untrusted sources only go to the junk snomask * (which is only for debugging issues and such). * This to prevent flooding and confusing IRCOps by @@ -415,13 +412,15 @@ CMD_FUNC(cmd_error) */ if (!IsServer(client) && !client->serv) { - sendto_snomask(SNO_JUNK, "ERROR from %s -- %s", + sendto_snomask(SNO_JUNK, "ERROR from server %s: %s", get_client_name(client, FALSE), para); return; } - sendto_umode_global(UMODE_OPER, "ERROR from %s -- %s", - get_client_name(client, FALSE), para); + sendto_umode_global(UMODE_OPER, "ERROR from server %s: %s", + get_client_name(client, FALSE), para); + ircd_log(LOG_ERROR, "ERROR from server %s: %s", + get_client_name(client, FALSE), para); } /** Save the tunefile (such as: highest seen connection count) */ @@ -1279,3 +1278,32 @@ void tkl_init(void) memset(tklines, 0, sizeof(tklines)); memset(tklines_ip_hash, 0, sizeof(tklines_ip_hash)); } + +/** Called when a server link is lost. + * Used for logging only, API users can use the HOOKTYPE_SERVER_QUIT hook. + */ +void lost_server_link(Client *serv, FORMAT_STRING(const char *fmt), ...) +{ + va_list vl; + static char buf[1024], buf2[512]; + + va_start(vl, fmt); + vsnprintf(buf2, sizeof(buf2), fmt, vl); + va_end(vl); + + if (IsServer(serv)) + { + /* An already established link is now lost. Broadcast this to all opers. */ + snprintf(buf, sizeof(buf), "Lost server link to %s: %s", + get_client_name(serv, FALSE), buf2); + sendto_umode_global(UMODE_OPER, "%s", buf); + } else { + /* A link attempt failed. Only send this to local opers (can be noisy every xx seconds). */ + snprintf(buf, sizeof(buf), "Unable to link with server %s: %s", + get_client_name(serv, FALSE), buf2); + sendto_umode(UMODE_OPER, "%s", buf); + } + + /* Always log! */ + ircd_log(LOG_ERROR, "%s", buf); +} diff --git a/src/socket.c b/src/socket.c index d8b549a..bde1176 100644 --- a/src/socket.c +++ b/src/socket.c @@ -1086,12 +1086,7 @@ void read_packet(int fd, int revents, void *data) return; if (IsServer(client) || client->serv) /* server or outgoing connection */ - { - sendto_umode_global(UMODE_OPER, "Lost connection to %s: Read error", - get_client_name(client, FALSE)); - ircd_log(LOG_ERROR, "Lost connection to %s: Read error", - get_client_name(client, FALSE)); - } + lost_server_link(client, "Read error or connection closed."); exit_client(client, NULL, "Read error"); return; diff --git a/src/tls.c b/src/tls.c index 7da64df..f7e75c7 100644 --- a/src/tls.c +++ b/src/tls.c @@ -270,8 +270,25 @@ static int setup_dh_params(SSL_CTX *ctx) /** Disable SSL/TLS protocols as set by config */ void disable_ssl_protocols(SSL_CTX *ctx, TLSOptions *tlsoptions) { - /* OpenSSL has two mechanisms for protocol version control: - * + /* OpenSSL has three mechanisms for protocol version control... */ + +#ifdef HAS_SSL_CTX_SET_SECURITY_LEVEL + /* The first one is setting a "security level" as introduced + * by OpenSSL 1.1.0. Some Linux distro's like Ubuntu 20.04 + * seemingly compile with -DOPENSSL_TLS_SECURITY_LEVEL=2. + * This means the application (UnrealIRCd) is unable to allow + * TLSv1.0/1.1 even if the application is configured to do so. + * So here we set the level to 1, but -again- ONLY if we are + * configured to allow TLSv1.0 or v1.1, of course. + */ + if ((tlsoptions->protocols & TLS_PROTOCOL_TLSV1) || + (tlsoptions->protocols & TLS_PROTOCOL_TLSV1_1)) + { + SSL_CTX_set_security_level(ctx, 1); + } +#endif + + /* The remaining two mechanisms are: * The old way, which is most flexible, is to use: * SSL_CTX_set_options(... SSL_OP_NO_) which allows * you to disable each and every specific SSL/TLS version. @@ -937,18 +954,12 @@ static int fatal_ssl_error(int ssl_error, int where, int my_errno, Client *clien (client->serv && client->serv->conf) ? client->serv->conf->outgoing.port : -1, client->name); } - sendto_umode(UMODE_OPER, "Lost connection to %s: %s: %s%s%s", - get_client_name(client, FALSE), ssl_func, ssl_errstr, additional_info, extra); - /* This is a connect() that fails, we don't broadcast that for non-SSL either (noisy) */ + lost_server_link(client, "%s: %s%s%s", ssl_func, ssl_errstr, additional_info, extra); } else - if ((IsServer(client) || (client->serv && client->serv->conf)) && (where != SAFE_SSL_WRITE)) + if (IsServer(client) || (client->serv && client->serv->conf)) { - /* if server (either judged by IsServer() or clearly an outgoing connect), - * and not writing (since otherwise deliver_it will take care of the error), THEN - * send a closing link error... - */ - sendto_umode_global(UMODE_OPER, "Lost connection to %s: %s: %d (%s%s)", - get_client_name(client, FALSE), ssl_func, ssl_error, ssl_errstr, additional_info); + /* Either a trusted fully established server (incoming) or an outgoing server link (established or not) */ + lost_server_link(client, "%s: %s%s", ssl_func, ssl_errstr, additional_info); } if (errtmp) diff --git a/src/user.c b/src/user.c index 2d8016c..8baf29e 100644 --- a/src/user.c +++ b/src/user.c @@ -699,3 +699,29 @@ void user_account_login(MessageTag *recv_mtags, Client *client) { RunHook2(HOOKTYPE_ACCOUNT_LOGIN, client, recv_mtags); } + +/** Should we hide the idle time of 'target' to user 'client'? + * This depends on the set::hide-idle-time policy. + */ +int hide_idle_time(Client *client, Client *target) +{ + /* First of all, IRCOps bypass the restriction */ + if (IsOper(client)) + return 0; + + /* Other than that, it depends on the settings: */ + switch (iConf.hide_idle_time) + { + case HIDE_IDLE_TIME_NEVER: + return 0; + case HIDE_IDLE_TIME_ALWAYS: + return 1; + case HIDE_IDLE_TIME_USERMODE: + case HIDE_IDLE_TIME_OPER_USERMODE: + if (target->umodes & UMODE_HIDLE) + return 1; + return 0; + default: + return 0; + } +} diff --git a/src/version.c.SH b/src/version.c.SH index 19cc542..add7e10 100644 --- a/src/version.c.SH +++ b/src/version.c.SH @@ -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.3.1" +id="5.0.4" echo "$id" if test -r version.c diff --git a/src/windows/UnrealIRCd.exe.manifest b/src/windows/UnrealIRCd.exe.manifest index 37a8716..3052db8 100644 --- a/src/windows/UnrealIRCd.exe.manifest +++ b/src/windows/UnrealIRCd.exe.manifest @@ -3,7 +3,7 @@ Internet Relay Chat Daemon diff --git a/src/windows/unrealinst.iss b/src/windows/unrealinst.iss index 2fc4b82..1e25d54 100644 --- a/src/windows/unrealinst.iss +++ b/src/windows/unrealinst.iss @@ -6,7 +6,7 @@ [Setup] AppName=UnrealIRCd 5 -AppVerName=UnrealIRCd 5.0.3.1 +AppVerName=UnrealIRCd 5.0.4 AppPublisher=UnrealIRCd Team AppPublisherURL=https://www.unrealircd.org AppSupportURL=https://www.unrealircd.org diff --git a/unrealircd.in b/unrealircd.in index 31430b8..73dcaea 100644 --- a/unrealircd.in +++ b/unrealircd.in @@ -33,11 +33,8 @@ if [ "$1" = "start" ] ; then if [ ! -f @CONFDIR@/unrealircd.conf ]; then echo "" echo "The configuration file does not exist (@CONFDIR@/unrealircd.conf)." - echo "* Create one by following:" - echo " https://www.unrealircd.org/docs/Installing_from_source#Creating_a_configuration_file" - echo "* Or if you are upgrading from version 3.2.x then read:" - echo " https://www.unrealircd.org/docs/Upgrading_from_3.2.x and" - echo " https://www.unrealircd.org/docs/UnrealIRCd_files_and_directories" + echo "Create one using the example configuration file, see the documentation:" + echo "https://www.unrealircd.org/docs/Installing_from_source#Creating_a_configuration_file" exit 1 fi @BINDIR@/unrealircd