diff --git a/CREDITS b/CREDITS index 97d1e95e2..8e19badcc 100644 --- a/CREDITS +++ b/CREDITS @@ -7,7 +7,7 @@ network configurations. The charybdis core team is listed in nick-alphabetical order: -dwr, Valery Yatsko +dwr, Valery Yatsko gxti, Michael Tharp jilles, Jilles Tjoelker nenolod, William Pitcock diff --git a/README.FIRST b/README.FIRST index 6f581136e..266bde31a 100644 --- a/README.FIRST +++ b/README.FIRST @@ -7,8 +7,6 @@ If you don't read this first, we won't help you. * - Reading INSTALL is now a must, as the old DPATH is now specified * * when configure is run. * * You now need to ./configure --prefix="/path/to/install/it" * - * - The old config format WILL NOT WORK. Please see doc/example.conf ! * - * - The old kline format WILL NOT WORK. Please use convertklines which * * will be installed with your ircd! * ************************************************************************* @@ -18,6 +16,15 @@ If you don't read this first, we won't help you. ******************************* REQUIREMENTS ********************************** +New Features - A short introduction: +- charybdis-3.x now has several major changes over previous version that you + will notice right away. + o SSL Client support. + o Connection Throttling. + +- Please see NEWS for more detailed changes. + + Necessary Requirements: - A supported platform (look below) @@ -33,41 +40,27 @@ Necessary Requirements: Feature Specific Requirements: -- For the SSL Challenge controlled OPER feature and encrypted server links, +- For SSL Clients, SSL Challenge controlled OPER feature, and encrypted server links, a working OpenSSL library -- For encrypted oper and (optional) server passwords, a working DES and/or - MD5 library +- For encrypted oper and (optional) server passwords, a working DES, MD5, or SHA library. ******************************************************************************* -- To report bugs in ircd-ratbox, send the bug report to ircd-ratbox@lists.ratbox.org +- To report bugs in charybdis, visit us at irc.atheme.org #charybdis - Known bugs are listed in the BUGS file - See the INSTALL document for info on configuring and compiling - ircd-ratbox. + charybdis. - Please read doc/index.txt to get an overview of the current documentation. -- Old Hybrid 5/6 configuration files are no longer supported. All conf - files will have to be converted to the new format. A convertconf - utility is provided and installed into bin/. - -- If you are wondering why config.h is practically empty, its because many - things that were once in config.h are now specified in the 'general' - block of ircd.conf. Look at example.conf for more information about - these options. - - The files, /etc/services, /etc/protocols, and /etc/resolv.conf, MUST be readable by the user running the server in order for ircd to start. Errors from adns causing the ircd to refuse to start up are often related to permission problems on these files. -- There is a mailing list for ircd-ratbox. To subscribe to this list - visit http://lists.ratbox.org/cgi-bin/mailman/listinfo/ircd-ratbox - Note that this list also gets the commit emails from the CVS server. - - FREEBSD USERS: if you are compiling with ipv6 you may experience problems with ipv4 due to the way the socket code is written. To fix this you must: "sysctl net.inet6.ip6.v6only=0" @@ -77,26 +70,34 @@ Feature Specific Requirements: work fine, and any gcc or SunPro compiled on 32bit. - DARWIN AND MACOS X USERS: You must be using at least the December 2001 - Development Tools from Apple to build ircd-ratbox with shared modules. + Development Tools from Apple to build charybdis with shared modules. Before then you MUST disable shared modules, as we do not have the proper flags for cc(1) prior to that point to produce shared modules. -- SUPPORTED PLATFORMS: this code should compile without any warnings - on FreeBSD 3.x/4.x, RedHat 6.2, Debian Potato and Solaris 7/8 sparc. +- SUPPORTED PLATFORMS: this code should compile without any warnings on: + FreeBSD 6.x/7.x, + Gentoo & Gentoo Hardened ~x86/~amd64/~fbsd + Fedora 8/9 / CentOS 4/5 / Redhat Enterprise 5 + Debian Etch, + OpenSuSE 10/11, + OpenSolaris 2008.x? + Solaris 10 sparc. + Please let us know if you find otherwise. It probably does not compile on AIX, IRIX or libc5 Linux. - TESTED PLATFORMS: The code has been tested on the following platforms, and is known to run properly. - FreeBSD 3.x/4.x - Linux glibc + FreeBSD 6.x/7.x + Linux glibc-2.6, glibc-2.7 Solaris 2.6/7/8 OpenBSD 2.8 NetBSD 1.4 + OpenVMS/Alpha 7.2 (static modules, no ssld) -- Please read doc/whats-new.txt for information about what is in this release +- Please read NEWS for information about what is in this release - Other files recommended for reading: BUGS, INSTALL -------------------------------------------------------------------------------- -$Id: README.FIRST 1837 2006-08-22 14:05:58Z nenolod $ +$Id$ diff --git a/TODO b/TODO index 77198bfc7..76eb97c43 100644 --- a/TODO +++ b/TODO @@ -14,36 +14,54 @@ [x] in-process SSL [x] port and use ratbox ssld for server links [x] merge with libratbox SVN -[/] ssl stuff +[x] ssl stuff [x] client-to-client ssl [x] server-to-server ssl [x] ssl usermode (+Z) [x] ssl channelmode (done by extban and chm_compat) - [ ] acknowledgement message for SSL users like '* *** You are connected using SSL cipher "DHE RSA-AES 128 CBC-SHA"' [x] tool for generating ssl certificates and other stuff [x] gnutls backend for at least SSL connections (replacing libcrypto use in m_challenge would be nice too) -[/] merge some stuff from ircd-seven directly (to be determined what) +[x] merge some stuff from ircd-seven directly (to be determined what) [x] remote d:lines support [x] PASS selector:password for auth{} (useful for dynamic IPs) - [ ] +C (noctcp) channel/usermode [F] kline/xline/resv sync [F] make an ability of using bandb instead of .conf files as bans storage [x] drop non-TS6 (legacy protocol) support [F] Doxygen code documentation +[?] Patch or core-feature - libguess on-fly any-charset-to-utf8 translation [/] module engine rework [/] more beautiful way of adding new channel modes by module - [x] basic functionality - [x] some example modules - [ ] think on how could we append privilege checking for simple chmode - like chm_staff, but additionaly limited (e. g. IsOperResv etc); - possibly move the same code for all functions into separated one and make it extern? + [x] basic functionality + [x] some example modules + [ ] think on how could we append privilege checking for simple chmode - like chm_staff, but additionaly limited (e. g. IsOperResv etc); + possibly move the same code for all functions into separated one and make it extern? + [x] another idea is too make that work with privilege groups, like "serveradmins" or "ircops" [ ] make nick/user/host validation functions/match tables able to work in separated modules, this will help us making support for native characters sets/slashes in host etc [ ] auth checker module [ ] resolver module + [ ] hooks + [ ] can_kick + which modules could we add in charybdis distro? + [ ] can_send_channel + [?] +C (ctcp) + [ ] can_send_user + [?] +C (ctcp) + [x] privilege system for privilege groups, something like + in .conf: helper { kill_global, rehash, kline_local } + in modules: privilege_add("kill_global"), has_privilege(source_p, "kill_global") etc, should work the way dynamic cflags/umodes done + -- this is done kinda like this, but not really. See HasPrivilege() calls. privilege_add() was not needed ~nenolod [x] Remove glines entirely +[/] test suite as in ircu +[?] win32 + [?] cygwin support + [?] mingw support + [?] native win32 (VS2005/VS2008) [/] Bug fixes [x] Compilation without zlib headers fails - fixed - [ ] Compilation date and time in server welcome message is in OS locale - looks ugly 'cause often it's not match user's codepage + [x] Compilation date and time in server welcome message is in OS locale - looks ugly 'cause often it's not match user's codepage +[ ] Improvments + [ ] ircd shouldn't need bison/byacc/yacc or flex for compilation --- other stuff [ ] allow to set up configfiles path (etc/) instead of separated configfiles names (kline.conf, ircd.conf etc) like it is in ratbox3? [?] internally split out +o/+v "ranks" into a series of permissions. this could allow for configure-defined diff --git a/configure b/configure index 26e094a1d..0b455ab7d 100755 --- a/configure +++ b/configure @@ -2802,8 +2802,8 @@ esac fi -{ echo "$as_me:$LINENO: checking uname -s for Cygwin, Solaris, AIX or HPUX" >&5 -echo $ECHO_N "checking uname -s for Cygwin, Solaris, AIX or HPUX... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: checking uname -s for Solaris, AIX or HPUX" >&5 +echo $ECHO_N "checking uname -s for Solaris, AIX or HPUX... $ECHO_C" >&6; } OSNAME=`uname -s` case "$OSNAME" in HP-UX*) @@ -2818,11 +2818,6 @@ echo "${ECHO_T}assuming old HPUX with its own cc" >&6; } echo "${ECHO_T}already using newer HPUX" >&6; } fi ;; - CYGWIN*) - { echo "$as_me:$LINENO: result: Cygwin" >&5 -echo "${ECHO_T}Cygwin" >&6; } - CYGWIN=yes - ;; SunOS*) { echo "$as_me:$LINENO: result: SunOS or Solaris" >&5 echo "${ECHO_T}SunOS or Solaris" >&6; } @@ -7613,8 +7608,8 @@ fi if test $ac_cv_header_stdarg_h = yes; then : else - { { echo "$as_me:$LINENO: error: ** stdarg.h could not be found - ircd-ratbox will not compile without it **" >&5 -echo "$as_me: error: ** stdarg.h could not be found - ircd-ratbox will not compile without it **" >&2;} + { { echo "$as_me:$LINENO: error: ** stdarg.h could not be found - charybdis will not compile without it **" >&5 +echo "$as_me: error: ** stdarg.h could not be found - charybdis will not compile without it **" >&2;} { (exit 1); exit 1; }; } fi @@ -10833,13 +10828,6 @@ _ACEOF shared_modules="yes" if test "$shared_modules" = yes; then - - if test "$CYGWIN" = yes; then - { echo "$as_me:$LINENO: WARNING: disabling shared modules; Cygwin is at present unable to build them." >&5 -echo "$as_me: WARNING: disabling shared modules; Cygwin is at present unable to build them." >&2;} - shared_modules="no" - fi - if test "$CC" = tcc -a "$TenDRA" = "no"; then { echo "$as_me:$LINENO: WARNING: disabling shared modules: Tiny C Compiler can't create PIC" >&5 echo "$as_me: WARNING: disabling shared modules: Tiny C Compiler can't create PIC" >&2;} @@ -12079,7 +12067,7 @@ echo "${ECHO_T}no" >&6; } echo $ECHO_N "checking GCC flag(s) -Wwrite-strings... $ECHO_C" >&6; } if test "${GCC-no}" = yes then - if test "${charybdis_cv_c_gcc_w_float_equal+set}" = set; then + if test "${charybdis_cv_c_gcc_w_write_strings+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else @@ -12123,24 +12111,99 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then - charybdis_cv_c_gcc_w_float_equal=yes + charybdis_cv_c_gcc_w_write_strings=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - charybdis_cv_c_gcc_w_float_equal=no + charybdis_cv_c_gcc_w_write_strings=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="${oldcflags}" fi - if test "x$charybdis_cv_c_gcc_w_float_equal" = xyes; then + if test "x$charybdis_cv_c_gcc_w_write_strings" = xyes; then CWARNS="${CWARNS}-Wwrite-strings " { echo "$as_me:$LINENO: result: ok" >&5 echo "${ECHO_T}ok" >&6; } else - charybdis_cv_c_gcc_w_float_equal='' + charybdis_cv_c_gcc_w_write_strings='' + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + fi + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + fi + + + { echo "$as_me:$LINENO: checking GCC flag(s) -Werror-implicit-function-declaration" >&5 +echo $ECHO_N "checking GCC flag(s) -Werror-implicit-function-declaration... $ECHO_C" >&6; } + if test "${GCC-no}" = yes + then + if test "${charybdis_cv_c_gcc_w_error_implicit_function_declaration+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + oldcflags="${CFLAGS-}" + CFLAGS="${CFLAGS-} ${CWARNS} -Werror-implicit-function-declaration -Werror" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include +int main(void); + +int +main () +{ + + (void)strcmp("a","b"); fprintf(stdout,"test ok\n"); + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + charybdis_cv_c_gcc_w_error_implicit_function_declaration=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + charybdis_cv_c_gcc_w_error_implicit_function_declaration=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="${oldcflags}" +fi + + if test "x$charybdis_cv_c_gcc_w_error_implicit_function_declaration" = xyes; then + CWARNS="${CWARNS}-Werror-implicit-function-declaration " + { echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6; } + else + charybdis_cv_c_gcc_w_error_implicit_function_declaration='' { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi diff --git a/configure.ac b/configure.ac index efd1e79a9..910dc99c2 100644 --- a/configure.ac +++ b/configure.ac @@ -81,7 +81,7 @@ esac fi -AC_MSG_CHECKING([uname -s for Cygwin, Solaris, AIX or HPUX]) +AC_MSG_CHECKING([uname -s for Solaris, AIX or HPUX]) OSNAME=`uname -s` case "$OSNAME" in HP-UX*) @@ -96,10 +96,6 @@ case "$OSNAME" in AC_MSG_RESULT(already using newer HPUX) fi ;; - CYGWIN*) - AC_MSG_RESULT(Cygwin) - CYGWIN=yes - ;; SunOS*) AC_MSG_RESULT(SunOS or Solaris) AC_DEFINE(__EXTENSIONS__, 1, [This is needed to use strtok_r on Solaris.]) @@ -315,7 +311,7 @@ fi AC_C_BIGENDIAN dnl Check for stdarg.h - if we can't find it, halt configure -AC_CHECK_HEADER(stdarg.h, , [AC_MSG_ERROR([** stdarg.h could not be found - ircd-ratbox will not compile without it **])]) +AC_CHECK_HEADER(stdarg.h, , [AC_MSG_ERROR([** stdarg.h could not be found - charybdis will not compile without it **])]) dnl Checks for the existence of strlcat, strlcpy, basename... dnl This more reliable test only works with gcc though. @@ -893,12 +889,6 @@ AC_DEFINE_UNQUOTED(NICKLEN, (${NICKLEN}+1), [Nickname length]) shared_modules="yes" dnl Some first-stage sanity checks. if test "$shared_modules" = yes; then - - if test "$CYGWIN" = yes; then - AC_MSG_WARN([disabling shared modules; Cygwin is at present unable to build them.]) - shared_modules="no" - fi - dnl TenDRA's cc is called tcc too. if test "$CC" = tcc -a "$TenDRA" = "no"; then AC_MSG_WARN([disabling shared modules: Tiny C Compiler can't create PIC]) diff --git a/doc/example.conf b/doc/example.conf index 5e02e0dfa..688c2de49 100755 --- a/doc/example.conf +++ b/doc/example.conf @@ -172,6 +172,7 @@ auth { * USE WITH CAUTION. * no_tilde (old - flag) | don't prefix ~ to username if no ident * need_ident (old + flag) | require ident for user in this class + * need_ssl | require SSL/TLS for user in this class * need_sasl | require SASL id for user in this class */ flags = kline_exempt, exceed_limit; @@ -185,6 +186,29 @@ auth { class = "users"; }; +/* privset {} blocks MUST be specified before anything that uses them. That + * means they must be defined before operator {}. + */ +privset "local_op" { + privs = oper:local_kill, oper:operwall; +}; + +privset "server_bot" { + extends = "local_op"; + privs = oper:global_kill, oper:kline, oper:remoteban, snomask:nick_changes; +}; + +privset "global_op" { + extends = "local_op"; + privs = oper:global_kill, oper:routing, oper:kline, oper:unkline, oper:xline, + oper:resv, oper:mass_notice, oper:remoteban; +}; + +privset "admin" { + extends = "global_op"; + privs = oper:admin, oper:die, oper:rehash, oper:spy; +}; + operator "god" { /* name: the name of the oper must go above */ @@ -217,42 +241,20 @@ operator "god" { */ snomask = "+Zbfkrsuy"; - /* privileges: controls the activities and commands an oper is - * allowed to do on the server. You may prefix an option with ~ to - * disable it, ie ~operwall + /* flags: misc options for the operator. You may prefix an option + * with ~ to disable it, e.g. ~encrypted. * - * Default flags are operwall, remoteban and encrypted. + * Default flags are encrypted. * * Available options: * * encrypted: the password above is encrypted [DEFAULT] - * local_kill: allows local users to be /KILL'd - * global_kill: allows local and remote users to be - * /KILL'd (OLD 'O' flag) - * remote: allows remote SQUIT and CONNECT (OLD 'R' flag) - * kline: allows KLINE and DLINE (OLD 'K' flag) - * unkline: allows UNKLINE and UNDLINE (OLD 'U' flag) - * nick_changes: allows oper to see nickchanges (OLD 'N' flag) - * via snomask +n - * rehash: allows oper to REHASH config (OLD 'H' flag) - * die: allows DIE and RESTART (OLD 'D' flag) - * admin: gives admin privileges. admins - * may (un)load modules and see the - * real IPs of servers. - * hidden_admin: gives admin privileges except - * will not have the admin lines in - * stats p and whois. - * xline: allows use of /quote xline/unxline - * resv: allows /quote resv/unresv and cmode +LP [DEFAULT] - * operwall: allows the oper to send/receive operwalls [DEFAULT] - * oper_spy: allows 'operspy' features to see through +s - * channels etc. see /quote help operspy - * hidden_oper: hides the oper from /stats p (OLD UMODE +p) - * remoteban: allows remote kline etc [DEFAULT] - * mass_notice: allows sending wallops and mass notices [DEFAULT] + * need_ssl: must be using SSL/TLS to oper up */ - flags = global_kill, remote, kline, unkline, - die, rehash, admin, xline, operwall; + flags = encrypted; + + /* privset: privileges set to grant */ + privset = "admin"; }; connect "irc.uplink.com" { @@ -460,7 +462,8 @@ general { reject_ban_time = 1 minute; reject_after_count = 3; reject_duration = 5 minutes; - max_unknown_ip = 2; + throttle_duration = 60; + throttle_count = 4; }; modules { diff --git a/doc/reference.conf b/doc/reference.conf index 4d5448057..08d95088e 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -18,6 +18,9 @@ * that matches a user will be used. So place spoofs first, then specials, * then general access, then restricted. * + * privset {} blocks MUST be specified before anything that uses them. That + * means they must be defined before operator {}. + * * Both shell style (#) and C style comments are supported. * * Files may be included by either: @@ -41,6 +44,9 @@ * Charybdis contains several extensions that are not enabled by default. * To use them, uncomment the lines below. * + * Channel mode +-A (admin only) -- chm_adminonly.so + * Channel mode +-O (oper only) -- chm_operonly.so + * Channel mode +-S (ssl only) -- chm_sslonly.so * Emulates channel mode +-O (oper only) (+-iI $o) -- chm_operonly_compat.so * Emulates channel mode +-R (quiet unreg) (+-q $~a) -- chm_quietunreg_compat.so * Emulates channel mode +-S (ssl only) (+-b $~z) -- chm_sslonly_compat.so @@ -63,6 +69,9 @@ * Remote oper up notices -- sno_globaloper.so * /whois notifications (snomask +W) -- sno_whois.so */ +#loadmodule "extensions/chm_adminonly.so"; +#loadmodule "extensions/chm_operonly.so"; +#loadmodule "extensions/chm_sslonly.so"; #loadmodule "extensions/chm_operonly_compat.so"; #loadmodule "extensions/chm_quietunreg_compat.so"; #loadmodule "extensions/chm_sslonly_compat.so"; @@ -326,6 +335,7 @@ auth { * USE WITH CAUTION. * no_tilde (old - flag) | don't prefix ~ to username if no ident * need_ident (old + flag) | require ident for user in this class + * need_ssl | require SSL/TLS for user in this class * need_sasl | require SASL id for user in this class */ flags = kline_exempt, exceed_limit; @@ -355,10 +365,57 @@ auth { flags = need_ident; }; -/* operator {}: defines ircd operators. (OLD O:) - * charybdis no longer supports local operators, privileges are - * controlled via flags. - */ +/* privset{}: defines operator privilege sets. */ +privset "local_op" { + /* privs: controls the activities and commands an oper is + * allowed to do on the server + * + * Available options: + * + * oper:local_kill: allows local users to be /KILL'd + * oper:global_kill: allows local and remote users to be /KILL'd + * oper:routing: allows remote SQUIT and CONNECT + * oper:kline: allows KLINE and DLINE + * oper:unkline: allows UNKLINE and UNDLINE + * snomask:nick_changes: allows oper to see nickchanges via snomask +n + * oper:rehash: allows oper to REHASH config + * oper:die: allows DIE and RESTART + * oper:admin: gives admin privileges. admins + * may (un)load modules and see various + * additional information. + * oper:hidden_admin: gives admin privileges except + * will not have the admin lines in + * whois. + * oper:xline: allows use of /quote xline/unxline + * oper:resv: allows /quote resv/unresv and cmode +LP + * oper:operwall: allows the oper to send/receive operwalls + * oper:spy: allows 'operspy' features to see through +s + * channels etc. see /quote help operspy + * oper:hidden: hides the oper from /stats p + * oper:remoteban: allows remote kline etc + * oper:mass_notice: allows sending wallops and mass notices + */ + privs = oper:local_kill, oper:operwall; +}; + +privset "server_bot" { + /* extends: a privset to inherit in this privset */ + extends = "local_op"; + privs = oper:global_kill, oper:kline, oper:remoteban, snomask:nick_changes; +}; + +privset "global_op" { + extends = "local_op"; + privs = oper:global_kill, oper:routing, oper:kline, oper:unkline, oper:xline, + oper:resv, oper:mass_notice, oper:remoteban; +}; + +privset "admin" { + extends = "global_op"; + privs = oper:admin, oper:die, oper:rehash, oper:spy; +}; + +/* operator {}: defines ircd operators. (OLD O:) */ operator "god" { /* name: the name of the oper must go above */ @@ -392,42 +449,20 @@ operator "god" { */ snomask = "+Zbfkrsuy"; - /* privileges: controls the activities and commands an oper is - * allowed to do on the server. You may prefix an option with ~ to - * disable it, ie ~operwall + /* flags: misc options for the operator. You may prefix an option + * with ~ to disable it, e.g. ~encrypted. * - * Default flags are operwall, remoteban and encrypted. + * Default flags are encrypted. * * Available options: * * encrypted: the password above is encrypted [DEFAULT] - * local_kill: allows local users to be /KILL'd - * global_kill: allows local and remote users to be - * /KILL'd (OLD 'O' flag) - * remote: allows remote SQUIT and CONNECT (OLD 'R' flag) - * kline: allows KLINE and DLINE (OLD 'K' flag) - * unkline: allows UNKLINE and UNDLINE (OLD 'U' flag) - * nick_changes: allows oper to see nickchanges (OLD 'N' flag) - * via snomask +n - * rehash: allows oper to REHASH config (OLD 'H' flag) - * die: allows DIE and RESTART (OLD 'D' flag) - * admin: gives admin privileges. admins - * may (un)load modules and see the - * real IPs of servers. - * hidden_admin: gives admin privileges except - * will not have the admin lines in - * stats p and whois. - * xline: allows use of /quote xline/unxline - * resv: allows /quote resv/unresv and cmode +LP [DEFAULT] - * operwall: allows the oper to send/receive operwalls [DEFAULT] - * oper_spy: allows 'operspy' features to see through +s - * channels etc. see /quote help operspy - * hidden_oper: hides the oper from /stats p (OLD UMODE +p) - * remoteban: allows remote kline etc [DEFAULT] - * mass_notice: allows sending wallops and mass notices [DEFAULT] + * need_ssl: must be using SSL/TLS to oper up */ - flags = global_kill, remote, kline, unkline, - die, rehash, admin, xline, operwall; + flags = encrypted; + + /* privset: privileges set to grant */ + privset = "admin"; }; /* connect {}: controls servers we connect to (OLD C:, N:, H:, L:) */ @@ -1100,13 +1135,6 @@ general { * provided they have umode +s set */ oper_snomask = "+s"; - /* servlink path: path to 'servlink' program used by ircd to handle - * encrypted/compressed server <-> server links. - * - * only define if servlink is not in same directory as ircd itself. - */ - #servlink_path = "/usr/local/ircd/bin/servlink"; - /* use egd: if your system does not have *random devices yet you * want to use OpenSSL and encrypted links, enable this. Beware - * EGD is *very* CPU intensive when gathering data for its pool @@ -1153,10 +1181,14 @@ general { /* reject duration: the amount of time to cache the rejection */ reject_duration = 5 minutes; - /* max_unknown_ip: maximum number of pending connections to the server - * that are allowed per IP address + /* throttle_duration: Amount of time that throttling will be applied to an IP + * address. */ - max_unknown_ip = 2; + throttle_duration = 60; + + /* throttle_count: Number of connections within throttle_duration that it takes + * for throttling to take effect */ + throttle_count = 4; }; modules { diff --git a/doc/sgml/oper-guide/config.sgml b/doc/sgml/oper-guide/config.sgml index fc44fb73e..4c6207ffc 100644 --- a/doc/sgml/oper-guide/config.sgml +++ b/doc/sgml/oper-guide/config.sgml @@ -410,6 +410,12 @@ auth { Users in this auth{} block must have identd, otherwise they will be rejected. + + need_ssl + + Users in this auth{} block must be connected via SSL/TLS, otherwise they will be rejected. + + need_sasl @@ -442,6 +448,33 @@ exempt { + + privset {} block + +privset { + extends = "name"; + privs = list; +}; + + A privset (privilege set) block specifies a set of + operator privileges. + + + privset {} variables + + extends + + An optional privset to inherit. The new privset will have all privileges that the given privset has. + + + + privs + + Privileges to grant to this privset. These are described in the operator privileges section. + + + + operator {} block @@ -510,19 +543,35 @@ operator "name" { - flags + privset - A listing of privileges granted to operators using this block. - By default, the mass_notice, operwall, remoteban and resv privileges are granted; - use ~mass_notice, ~operwall, ~remoteban and ~resv to disable them if necessary. - - - In addition, a flag designating if the password is encrypted is here. - Privileges are documented elsewhere in this guide. + The privilege set granted to successfully opered clients. + This must be defined before this operator{} block. + + flags + + A list of flags to apply to this operator{} block. They are listed below. + + + + + operator {} flags + + encrypted + + The password used has been encrypted. This is enabled by default, use ~encrypted to disable it. + + + + need_ssl + + Restricts use of this operator{} block to SSL/TLS connections only. + + diff --git a/doc/sgml/oper-guide/oprivs.sgml b/doc/sgml/oper-guide/oprivs.sgml index fb5213e41..a35824008 100644 --- a/doc/sgml/oper-guide/oprivs.sgml +++ b/doc/sgml/oper-guide/oprivs.sgml @@ -3,12 +3,10 @@ Meanings of oper privileges - These are flags in operator{}. - The letter appears after opering up and in /stats o; an uppercase - letter means the privilege is possessed, lowercase means it is not. + These are specified in privset{}. - admin (A), server administrator + oper:admin, server administrator Various privileges intended for server administrators. Among other things, this automatically sets umode +a and allows @@ -16,7 +14,73 @@ - remoteban (B), set remote bans + oper:die, die and restart + + This grants permission to use DIE and RESTART, shutting down + or restarting the server. + + + + oper:global_kill, global kill + + Allows using KILL on users on any server. + + + + oper:hidden, hide from /stats p + + This privilege currently does nothing, but was designed + to hide bots from /stats p so users will not message them + for help. + + + + oper:hidden_admin, hidden administrator + + This grants everything granted to the oper:admin privilege, + except the ability to set umode +a. If both oper:admin and oper:hidden_admin + are possessed, umode +a can still not be used. + + + + oper:kline, kline and dline + + Allows using KLINE and DLINE, to ban users by user@host mask + or IP address. + + + + oper:local_kill, kill local users + + This grants permission to use KILL on users on the same server, + disconnecting them from the network. + + + + oper:mass_notice, global notices and wallops + + Allows using server name ($$mask) and hostname ($#mask) masks in + NOTICE and PRIVMSG to send a message to all matching users, and + allows using the WALLOPS command to send a message to all users + with umode +w set. + + + + oper:operwall, send/receive operwall + + Allows using the OPERWALL command and umode +z to send and + receive operwalls. + + + + oper:rehash, rehash + + Allows using the REHASH command, to rehash various configuration + files or clear certain lists. + + + + oper:remoteban, set remote bans This grants the ability to use the ON argument on DLINE/KLINE/XLINE/RESV and UNDLINE/UNKLINE/UNXLINE/UNRESV to set @@ -26,83 +90,18 @@ If a cluster{} block is present, bans are sent remotely even - if the oper does not have remoteban privilege. + if the oper does not have oper:remoteban privilege. - local_kill (C), kill local users - - This grants permission to use KILL on users on the same server, - disconnecting them from the network. - - - - die (D), die and restart - - This grants permission to use DIE and RESTART, shutting down - or restarting the server. - - - - rehash (H), rehash - - Allows using the REHASH command, to rehash various configuration - files or clear certain lists. - - - - kline (K), kline and dline - - Allows using KLINE and DLINE, to ban users by user@host mask - or IP address. - - - - operwall (L), send/receive operwall - - Allows using the OPERWALL command and umode +z to send and - receive operwalls. - - - - mass_notice (M), global notices and wallops - - Allows using server name ($$mask) and hostname ($#mask) masks in - NOTICE and PRIVMSG to send a message to all matching users, and - allows using the WALLOPS command to send a message to all users - with umode +w set. - - - - nick_changes (N), see nick changes - - Allows using snomask +n to see local client nick changes. - This is designed for monitor bots. - - - - global_kill (O), global kill - - Allows using KILL on users on any server. - - - - hidden_oper (P), hide from /stats p - - This privilege currently does nothing, but was designed - to hide bots from /stats p so users will not message them - for help. - - - - resv (Q), channel control + oper:resv, channel control This allows using /resv, /unresv and changing the channel modes +L and +P. - remote (R), remote routing + oper:routing, remote routing This allows using the third argument of the CONNECT command, to instruct another server to connect somewhere, and using SQUIT @@ -111,7 +110,7 @@ - oper_spy (S), use operspy + oper:spy, use operspy This allows using /mode !#channel, /whois !nick, /who !#channel, /chantrace !#channel, /who !mask, /masktrace !user@host :gecos @@ -133,27 +132,23 @@ - unkline (U), unkline and undline + oper:unkline, unkline and undline Allows using UNKLINE and UNDLINE. - xline (X), xline and unxline + oper:xline, xline and unxline Allows using XLINE and UNXLINE, to ban/unban users by realname. - hidden_admin, hidden administrator + snomask:nick_changes, see nick changes - This grants everything granted to the admin privilege, - except the ability to set umode +a. If both admin and hidden_admin - are possessed, umode +a can still not be used. + Allows using snomask +n to see local client nick changes. + This is designed for monitor bots. - - This privilege does not appear in /stats o or oper up notices. - diff --git a/doc/sgml/oper-guide/umodes.sgml b/doc/sgml/oper-guide/umodes.sgml index 6d64c546e..720e38a6b 100644 --- a/doc/sgml/oper-guide/umodes.sgml +++ b/doc/sgml/oper-guide/umodes.sgml @@ -147,8 +147,10 @@ This umode grants various features useful for services. For example, clients with this umode cannot be kicked or deopped on channels, - do not show channels the querying user is not on in WHOIS, - and do not appear in /stats p. + can send to any channel, do not show channels in WHOIS, + can be the target of services aliases and do not appear in /stats p. + No server notices are sent for hostname changes by services clients; + server notices about kills are sent to snomask +k instead of +s. The exact effects of this umode are variable; no user or oper on @@ -165,7 +167,8 @@ Users with the +w umode set will receive WALLOPS messages sent by opers. Opers with +w additionally receive WALLOPS sent by servers (e.g. - remote CONNECT, remote SQUIT, many services packages). + remote CONNECT, remote SQUIT, various severe misconfigurations, + many services packages). diff --git a/extensions/Makefile.in b/extensions/Makefile.in index ca7b80884..13c58db68 100644 --- a/extensions/Makefile.in +++ b/extensions/Makefile.in @@ -27,6 +27,7 @@ INCLUDES = -I. -I../include -I../libratbox/include $(SSL_INCLUDES) CPPFLAGS = ${INCLUDES} @CPPFLAGS@ SRCS = \ + chm_adminonly.c \ chm_operonly.c \ chm_operonly_compat.c \ chm_quietunreg_compat.c \ diff --git a/extensions/chm_adminonly.c b/extensions/chm_adminonly.c new file mode 100644 index 000000000..9380c3df7 --- /dev/null +++ b/extensions/chm_adminonly.c @@ -0,0 +1,52 @@ +#include "stdinc.h" +#include "modules.h" +#include "hook.h" +#include "client.h" +#include "ircd.h" +#include "send.h" +#include "s_conf.h" +#include "s_user.h" +#include "s_serv.h" +#include "numeric.h" +#include "chmode.h" + +static void h_can_join(hook_data_channel *); + +mapi_hfn_list_av1 adminonly_hfnlist[] = { + { "can_join", (hookfn) h_can_join }, + { NULL, NULL } +}; + +static int +_modinit(void) +{ + chmode_table['A'].mode_type = find_cflag_slot(); + chmode_table['A'].set_func = chm_staff; + + construct_noparam_modes(); + + return 0; +} + +static void +_moddeinit(void) +{ + chmode_table['A'].mode_type = 0; + + construct_noparam_modes(); +} + +DECLARE_MODULE_AV1(chm_adminonly, _modinit, _moddeinit, NULL, NULL, adminonly_hfnlist, "$Revision$"); + +static void +h_can_join(hook_data_channel *data) +{ + struct Client *source_p = data->client; + struct Channel *chptr = data->chptr; + + if((chptr->mode.mode & chmode_flags['A']) && !IsAdmin(source_p)) { + sendto_one_numeric(source_p, 519, "%s :Cannot join channel (+A) - you are not an IRC server administrator", chptr->chname); + data->approved = ERR_CUSTOM; + } +} + diff --git a/extensions/chm_operonly.c b/extensions/chm_operonly.c index b46fd8ac6..4912e5a74 100644 --- a/extensions/chm_operonly.c +++ b/extensions/chm_operonly.c @@ -28,7 +28,7 @@ _modinit(void) { /* add the channel mode to the available slot */ chmode_table['O'].mode_type = find_cflag_slot(); - chmode_table['O'].set_func = chm_simple; + chmode_table['O'].set_func = chm_staff; construct_noparam_modes(); @@ -58,7 +58,7 @@ h_can_join(hook_data_channel *data) struct Channel *chptr = data->chptr; if((chptr->mode.mode & chmode_flags['O']) && !IsOper(source_p)) { - sendto_one_notice(source_p, ":Only IRC Operators could join this channel!"); + sendto_one_numeric(source_p, 520, "%s :Cannot join channel (+O) - you are not an IRC operator", chptr->chname); data->approved = ERR_CUSTOM; } } diff --git a/extensions/ip_cloaking.c b/extensions/ip_cloaking.c index c85059b5b..09aabeb9f 100644 --- a/extensions/ip_cloaking.c +++ b/extensions/ip_cloaking.c @@ -94,11 +94,11 @@ do_host_cloak_ip(const char *inbuf, char *outbuf) if(ipv6) { - snprintf(outbuf, HOSTLEN, "%s:%x", buf, accum); + rb_snprintf(outbuf, HOSTLEN, "%s:%x", buf, accum); } else { - snprintf(outbuf, HOSTLEN, "%s.%x", buf, accum); + rb_snprintf(outbuf, HOSTLEN, "%s.%x", buf, accum); } } diff --git a/extensions/ip_cloaking_3.0.c b/extensions/ip_cloaking_3.0.c index e80a19a45..193939567 100644 --- a/extensions/ip_cloaking_3.0.c +++ b/extensions/ip_cloaking_3.0.c @@ -121,11 +121,11 @@ do_host_cloak_ip(const char *inbuf, char *outbuf) if(ipv6) { - snprintf(outbuf, HOSTLEN, "%s:%x", buf, accum); + rb_snprintf(outbuf, HOSTLEN, "%s:%x", buf, accum); } else { - snprintf(outbuf, HOSTLEN, "%s.%x", buf, accum); + rb_snprintf(outbuf, HOSTLEN, "%s.%x", buf, accum); } } diff --git a/extensions/m_mkpasswd.c b/extensions/m_mkpasswd.c index b59997b09..16b76f1c2 100644 --- a/extensions/m_mkpasswd.c +++ b/extensions/m_mkpasswd.c @@ -56,7 +56,7 @@ m_mkpasswd(struct Client *client_p, struct Client *source_p, int parc, const cha if((last_used + ConfigFileEntry.pace_wait) > rb_current_time()) { /* safe enough to give this on a local connect only */ - sendto_one(source_p, form_str(RPL_LOAD2HI), me.name, parv[0]); + sendto_one(source_p, form_str(RPL_LOAD2HI), me.name, parv[0], "MKPASSWD"); return 0; } else diff --git a/extensions/m_sendbans.c b/extensions/m_sendbans.c index f8829a08e..00ff7da8c 100644 --- a/extensions/m_sendbans.c +++ b/extensions/m_sendbans.c @@ -126,8 +126,9 @@ static int mo_sendbans(struct Client *client_p, struct Client *source_p, int par } sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, - "%s is sending resvs and xlines to %s", - get_oper_name(source_p), target); + "%s!%s@%s is sending resvs and xlines to %s", + source_p->name, source_p->username, source_p->host, + target); RB_DLINK_FOREACH(ptr, resv_conf_list.head) { diff --git a/extensions/m_webirc.c b/extensions/m_webirc.c index 735be1ed5..584de6738 100644 --- a/extensions/m_webirc.c +++ b/extensions/m_webirc.c @@ -125,7 +125,6 @@ mr_webirc(struct Client *client_p, struct Client *source_p, int parc, const char else rb_strlcpy(source_p->host, source_p->sockhost, sizeof(source_p->host)); - del_unknown_ip(source_p); rb_inet_pton_sock(parv[4], (struct sockaddr *)&source_p->localClient->ip); /* Check dlines now, klines will be checked on registration */ diff --git a/extensions/sno_globalkline.c b/extensions/sno_globalkline.c index 487044ec0..a654c4889 100644 --- a/extensions/sno_globalkline.c +++ b/extensions/sno_globalkline.c @@ -48,4 +48,16 @@ h_gla_client_exit(hook_data_client_exit *hdata) "K/DLINE active for %s[%s@%s]", source_p->name, source_p->username, source_p->host); } + else if (!strncmp(hdata->comment, "Temporary K-line ", 17)) + { + sendto_realops_snomask_from(SNO_GENERAL, L_ALL, source_p->servptr, + "K/DLINE active for %s[%s@%s]", + source_p->name, source_p->username, source_p->host); + } + else if (!strncmp(hdata->comment, "Temporary D-line ", 17)) + { + sendto_realops_snomask_from(SNO_GENERAL, L_ALL, source_p->servptr, + "K/DLINE active for %s[%s@%s]", + source_p->name, source_p->username, source_p->host); + } } diff --git a/include/channel.h b/include/channel.h index 236f49cf9..b4da1b6ed 100644 --- a/include/channel.h +++ b/include/channel.h @@ -255,8 +255,6 @@ extern void send_cap_mode_changes(struct Client *client_p, struct Client *source extern void set_channel_mode(struct Client *client_p, struct Client *source_p, struct Channel *chptr, struct membership *msptr, int parc, const char *parv[]); -extern int chmode_flags[256]; - extern struct ChannelMode chmode_table[256]; extern int add_id(struct Client *source_p, struct Channel *chptr, const char *banid, diff --git a/include/chmode.h b/include/chmode.h index e3b386b9c..a9c04a64e 100644 --- a/include/chmode.h +++ b/include/chmode.h @@ -34,6 +34,8 @@ */ #define ERR_CUSTOM 1000 +extern int chmode_flags[256]; + extern void chm_nosuch(struct Client *source_p, struct Channel *chptr, int alevel, int parc, int *parn, const char **parv, int *errors, int dir, char c, long mode_type); diff --git a/include/client.h b/include/client.h index 7027dde6d..33491442a 100644 --- a/include/client.h +++ b/include/client.h @@ -40,6 +40,7 @@ #include "snomask.h" #include "match.h" #include "ircd.h" +#include "privilege.h" /* other structs */ struct Blacklist; @@ -281,6 +282,8 @@ struct LocalUser struct ZipStats *zipstats; /* zipstats */ uint16_t cork_count; /* used for corking/uncorking connections */ struct ev_entry *event; /* used for associated events */ + + struct PrivilegeSet *privset; /* privset... */ }; struct PreClient @@ -295,6 +298,8 @@ struct PreClient rb_dlink_list dnsbl_queries; /* list of struct BlacklistClient * */ struct Blacklist *dnsbl_listed; /* first dnsbl where it's listed */ + + struct rb_sockaddr_storage lip; /* address of our side of the connection */ }; struct ListClient @@ -400,16 +405,15 @@ struct exit_client_hook #define FLAGS_FLOODDONE 0x0100 /* flood grace period over / reported */ #define FLAGS_NORMALEX 0x0400 /* Client exited normally */ #define FLAGS_SENDQEX 0x0800 /* Sendq exceeded */ -#define FLAGS_SERVLINK 0x10000 /* servlink has servlink process */ -#define FLAGS_MARK 0x20000 /* marked client */ -#define FLAGS_HIDDEN 0x40000 /* hidden server */ -#define FLAGS_EOB 0x80000 /* EOB */ -#define FLAGS_MYCONNECT 0x100000 /* MyConnect */ -#define FLAGS_IOERROR 0x200000 /* IO error */ -#define FLAGS_SERVICE 0x400000 /* network service */ -#define FLAGS_TGCHANGE 0x800000 /* we're allowed to clear something */ -#define FLAGS_DYNSPOOF 0x1000000 /* dynamic spoof, only opers see ip */ -#define FLAGS_EXUNKNOWN 0x2000000 /* too many unknowns exit.. */ +#define FLAGS_MARK 0x10000 /* marked client */ +#define FLAGS_HIDDEN 0x20000 /* hidden server */ +#define FLAGS_EOB 0x40000 /* EOB */ +#define FLAGS_MYCONNECT 0x80000 /* MyConnect */ +#define FLAGS_IOERROR 0x100000 /* IO error */ +#define FLAGS_SERVICE 0x200000 /* network service */ +#define FLAGS_TGCHANGE 0x400000 /* we're allowed to clear something */ +#define FLAGS_DYNSPOOF 0x800000 /* dynamic spoof, only opers see ip */ +#define FLAGS_EXUNKNOWN 0x1000000 /* too many unknowns exit.. */ /* flags for local clients, this needs stuff moved from above to here at some point */ #define LFLAGS_SSL 0x00000001 diff --git a/include/config.h b/include/config.h index daa8652a6..04fcfdb16 100644 --- a/include/config.h +++ b/include/config.h @@ -61,7 +61,6 @@ /* files */ #define SPATH BINPATH "/ircd" /* ircd executable */ #define LIPATH LIBPATH "/libircd" SHARED_SUFFIX /* ircd library */ -#define SLPATH BINPATH "/servlink" /* servlink executable */ #define CPATH ETCPATH "/ircd.conf" /* ircd.conf file */ #define KPATH ETCPATH "/kline.conf" /* kline file */ #define DLPATH ETCPATH "/dline.conf" /* dline file */ diff --git a/include/config.h.dist b/include/config.h.dist index daa8652a6..04fcfdb16 100644 --- a/include/config.h.dist +++ b/include/config.h.dist @@ -61,7 +61,6 @@ /* files */ #define SPATH BINPATH "/ircd" /* ircd executable */ #define LIPATH LIBPATH "/libircd" SHARED_SUFFIX /* ircd library */ -#define SLPATH BINPATH "/servlink" /* servlink executable */ #define CPATH ETCPATH "/ircd.conf" /* ircd.conf file */ #define KPATH ETCPATH "/kline.conf" /* kline file */ #define DLPATH ETCPATH "/dline.conf" /* dline file */ diff --git a/include/numeric.h b/include/numeric.h index af9435d05..b80c200d2 100644 --- a/include/numeric.h +++ b/include/numeric.h @@ -154,6 +154,8 @@ extern const char *form_str(int); #define RPL_LISTEND 323 #define RPL_CHANNELMODEIS 324 +#define RPL_CHANNELURL 328 /* to be sent by services */ + #define RPL_CREATIONTIME 329 #define RPL_WHOISLOGGEDIN 330 diff --git a/include/privilege.h b/include/privilege.h new file mode 100644 index 000000000..c454efca4 --- /dev/null +++ b/include/privilege.h @@ -0,0 +1,48 @@ +/* + * charybdis: an advanced ircd. + * privilege.h: Dynamic privileges API. + * + * Copyright (c) 2008 William Pitcock + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __CHARYBDIS_PRIVILEGE_H +#define __CHARYBDIS_PRIVILEGE_H + +#include "stdinc.h" + +typedef enum { + PRIV_NEEDOPER = 1 +} PrivilegeFlags; + +struct PrivilegeSet { + int refs; + char *name; + char *privs; + PrivilegeFlags flags; + rb_dlink_node node; +}; + +int privilegeset_in_set(struct PrivilegeSet *set, const char *priv); +struct PrivilegeSet *privilegeset_set_new(const char *name, const char *privs, PrivilegeFlags flags); +struct PrivilegeSet *privilegeset_extend(struct PrivilegeSet *parent, const char *name, const char *privs, PrivilegeFlags flags); +struct PrivilegeSet *privilegeset_get(const char *name); +struct PrivilegeSet *privilegeset_ref(struct PrivilegeSet *set); +void privilegeset_unref(struct PrivilegeSet *set); + +#endif diff --git a/include/reject.h b/include/reject.h index 2a36f9a36..0f559bc14 100644 --- a/include/reject.h +++ b/include/reject.h @@ -3,7 +3,7 @@ * reject.h: header to a file which rejects users with prejudice * * Copyright (C) 2003 Aaron Sethman - * Copyright (C) 2003-2004 ircd-ratbox development team + * Copyright (C) 2003-2005 ircd-ratbox development team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,11 +17,11 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA * * - * $Id: reject.h 3446 2007-05-14 22:21:16Z jilles $ + * $Id: reject.h 25056 2008-02-06 20:47:40Z androsyn $ */ #ifndef INCLUDED_reject_h #define INCLUDED_reject_h @@ -29,17 +29,16 @@ /* amount of time to delay a rejected clients exit */ #define DELAYED_EXIT_TIME 10 -extern rb_dlink_list delay_exit; - void init_reject(void); -int check_reject(struct Client *); +int check_reject(rb_fde_t *F, struct sockaddr *addr); void add_reject(struct Client *, const char *mask1, const char *mask2); void flush_reject(void); int remove_reject_ip(const char *ip); int remove_reject_mask(const char *mask1, const char *mask2); +unsigned long delay_exit_length(void); + +int throttle_add(struct sockaddr *addr); -int add_unknown_ip(struct Client *client_p); -void del_unknown_ip(struct Client *client_p); #endif diff --git a/include/s_conf.h b/include/s_conf.h index 8ce8f01df..bb2e162d7 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -89,6 +89,7 @@ struct ConfItem /* Generic flags... */ #define CONF_FLAGS_TEMPORARY 0x00800000 +#define CONF_FLAGS_NEED_SSL 0x00000002 /* auth{} flags... */ #define CONF_FLAGS_NO_TILDE 0x00000004 #define CONF_FLAGS_NEED_IDENTD 0x00000008 @@ -122,6 +123,7 @@ struct ConfItem #define IsConfEncrypted(x) ((x)->flags & CONF_FLAGS_ENCRYPTED) #define IsNeedSasl(x) ((x)->flags & CONF_FLAGS_NEED_SASL) #define IsConfExemptDNSBL(x) ((x)->flags & CONF_FLAGS_EXEMPTDNSBL) +#define IsConfSSLNeeded(x) ((x)->flags & CONF_FLAGS_NEED_SSL) /* flag definitions for opers now in client.h */ @@ -134,7 +136,6 @@ struct config_file_entry const char *xlinefile; const char *resvfile; - char *servlink_path; char *egdpool_path; char *default_operstring; @@ -210,12 +211,13 @@ struct config_file_entry int reject_ban_time; int reject_after_count; int reject_duration; + int throttle_count; + int throttle_duration; int target_change; int collision_fnc; int default_umodes; int global_snotices; int operspy_dont_care_user_info; - int max_unknown_ip; }; struct config_channel_entry diff --git a/include/s_newconf.h b/include/s_newconf.h index 402887e80..916cf77e3 100644 --- a/include/s_newconf.h +++ b/include/s_newconf.h @@ -36,6 +36,7 @@ #define INCLUDED_s_newconf_h #include "setup.h" +#include "privilege.h" #ifdef HAVE_LIBCRYPTO #include @@ -120,6 +121,8 @@ struct oper_conf unsigned int snomask; + struct PrivilegeSet *privset; + #ifdef HAVE_LIBCRYPTO char *rsa_pubkey_file; RSA *rsa_pubkey; @@ -137,51 +140,33 @@ extern void cluster_generic(struct Client *, const char *, int cltype, int cap, const char *format, ...); #define OPER_ENCRYPTED 0x00001 -#define OPER_KLINE 0x00002 -#define OPER_UNKLINE 0x00004 -#define OPER_LOCKILL 0x00008 -#define OPER_GLOBKILL 0x00010 -#define OPER_REMOTE 0x00020 -#define OPER_XLINE 0x00080 -#define OPER_RESV 0x00100 -#define OPER_NICKS 0x00200 -#define OPER_REHASH 0x00400 -#define OPER_DIE 0x00800 -#define OPER_ADMIN 0x01000 -#define OPER_HADMIN 0x02000 -#define OPER_OPERWALL 0x04000 -#define OPER_INVIS 0x08000 -#define OPER_SPY 0x10000 -#define OPER_REMOTEBAN 0x20000 -#define OPER_MASSNOTICE 0x40000 +#define OPER_NEEDSSL 0x80000 /* 0x400000 and above are in client.h */ -#define OPER_FLAGS (OPER_KLINE|OPER_UNKLINE|OPER_LOCKILL|OPER_GLOBKILL|\ - OPER_REMOTE|OPER_XLINE|OPER_RESV|\ - OPER_NICKS|OPER_REHASH|OPER_DIE|OPER_ADMIN|\ - OPER_HADMIN|OPER_OPERWALL|OPER_INVIS|OPER_SPY|\ - OPER_REMOTEBAN|OPER_MASSNOTICE) +#define OPER_FLAGS 0 /* no oper privs in Client.flags2/oper_conf.flags currently */ #define IsOperConfEncrypted(x) ((x)->flags & OPER_ENCRYPTED) +#define IsOperConfNeedSSL(x) ((x)->flags & OPER_NEEDSSL) -#define IsOperGlobalKill(x) ((x)->flags2 & OPER_GLOBKILL) -#define IsOperLocalKill(x) ((x)->flags2 & OPER_LOCKILL) -#define IsOperRemote(x) ((x)->flags2 & OPER_REMOTE) -#define IsOperUnkline(x) ((x)->flags2 & OPER_UNKLINE) -#define IsOperN(x) ((x)->flags2 & OPER_NICKS) -#define IsOperK(x) ((x)->flags2 & OPER_KLINE) -#define IsOperXline(x) ((x)->flags2 & OPER_XLINE) -#define IsOperResv(x) ((x)->flags2 & OPER_RESV) -#define IsOperDie(x) ((x)->flags2 & OPER_DIE) -#define IsOperRehash(x) ((x)->flags2 & OPER_REHASH) -#define IsOperHiddenAdmin(x) ((x)->flags2 & OPER_HADMIN) -#define IsOperAdmin(x) (((x)->flags2 & OPER_ADMIN) || \ - ((x)->flags2 & OPER_HADMIN)) -#define IsOperOperwall(x) ((x)->flags2 & OPER_OPERWALL) -#define IsOperSpy(x) ((x)->flags2 & OPER_SPY) -#define IsOperInvis(x) ((x)->flags2 & OPER_INVIS) -#define IsOperRemoteBan(x) ((x)->flags2 & OPER_REMOTEBAN) -#define IsOperMassNotice(x) ((x)->flags2 & OPER_MASSNOTICE) +#define HasPrivilege(x, y) ((x)->localClient != NULL && (x)->localClient->privset != NULL && privilegeset_in_set((x)->localClient->privset, (y))) + +#define IsOperGlobalKill(x) (HasPrivilege((x), "oper:global_kill")) +#define IsOperLocalKill(x) (HasPrivilege((x), "oper:local_kill")) +#define IsOperRemote(x) (HasPrivilege((x), "oper:routing")) +#define IsOperUnkline(x) (HasPrivilege((x), "oper:unkline")) +#define IsOperN(x) (HasPrivilege((x), "snomask:nick_changes")) +#define IsOperK(x) (HasPrivilege((x), "oper:kline")) +#define IsOperXline(x) (HasPrivilege((x), "oper:xline")) +#define IsOperResv(x) (HasPrivilege((x), "oper:resv")) +#define IsOperDie(x) (HasPrivilege((x), "oper:die")) +#define IsOperRehash(x) (HasPrivilege((x), "oper:rehash")) +#define IsOperHiddenAdmin(x) (HasPrivilege((x), "oper:hidden_admin")) +#define IsOperAdmin(x) (HasPrivilege((x), "oper:admin") || HasPrivilege((x), "oper:hidden_admin")) +#define IsOperOperwall(x) (HasPrivilege((x), "oper:operwall")) +#define IsOperSpy(x) (HasPrivilege((x), "oper:spy")) +#define IsOperInvis(x) (HasPrivilege((x), "oper:hidden")) +#define IsOperRemoteBan(x) (HasPrivilege((x), "oper:remoteban")) +#define IsOperMassNotice(x) (HasPrivilege((x), "oper:mass_notice")) extern struct oper_conf *make_oper_conf(void); extern void free_oper_conf(struct oper_conf *); diff --git a/include/supported.h b/include/supported.h index d92c9b1f3..1ed7c0d42 100644 --- a/include/supported.h +++ b/include/supported.h @@ -36,6 +36,7 @@ #define INCLUDED_supported_h extern void add_isupport(const char *, const char *(*)(const void *), const void *); +extern const void *change_isupport(const char *, const char *(*)(const void *), const void *); extern void delete_isupport(const char *); extern void show_isupport(struct Client *); extern void init_isupport(void); diff --git a/libratbox/ChangeLog b/libratbox/ChangeLog index a31a4e856..78a85b809 100644 --- a/libratbox/ChangeLog +++ b/libratbox/ChangeLog @@ -1,3 +1,48 @@ +androsyn 2008/08/06 19:51:44 UTC (25861) + Log: + put back in the pad to even pointer boundaries stuff + + Modified: + libratbox/trunk/src/balloc.c (File Modified) + + +androsyn 2008/08/06 19:30:25 UTC (25859) + Log: + fix the block heap free code + + Modified: + libratbox/trunk/src/balloc.c (File Modified) + + +androsyn 2008/08/06 19:14:38 UTC (25857) + Log: + Fix a bug where we would get SIGBUS crashes when trying to use a long long. + The problem was we were only aligning pointers to 4 bytes, which isn't good + enough for long long on sparc when using gcc 4.x. Apparently gcc 3.x was more + tolerant of this. This fixes it correctly. + + + + Modified: + libratbox/trunk/src/balloc.c (File Modified) + + +androsyn 2008/08/05 04:12:26 UTC (25853) + Log: + fix a buffer overrun in the nossl case + + Modified: + libratbox/trunk/src/nossl.c (File Modified) + + +androsyn 2008/08/04 22:04:38 UTC (25833) + Log: + make GET_SS_FAMILY use const and add a SET_SS_FAMILY macro. ircd fixes coming shortly + + Modified: + libratbox/trunk/include/ratbox_lib.h (File Modified) + + androsyn 2008/07/29 15:26:55 UTC (25795) Log: some sanity checks in the rb_open path diff --git a/libratbox/aclocal.m4 b/libratbox/aclocal.m4 index cce9fea95..083883edc 100644 --- a/libratbox/aclocal.m4 +++ b/libratbox/aclocal.m4 @@ -21,7 +21,7 @@ To do so, use the procedure documented by the package, typically `autoreconf'.]) # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- -# serial 52 Debian 1.5.26-1ubuntu1 AC_PROG_LIBTOOL +# serial 52 Debian 1.5.26-4 AC_PROG_LIBTOOL # AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) diff --git a/libratbox/configure b/libratbox/configure index af408af2f..c0875e3bc 100755 --- a/libratbox/configure +++ b/libratbox/configure @@ -21356,8 +21356,8 @@ fi *interix*) CPPFLAGS="$CFLAGS -D_ALL_SOURCE -D_XOPEN_SOURCE=500" ;; -*solaris*) - CPPFLAGS="$CFLAGS -D_POSIX_PTHREAD_SEMANTICS" +*solaris*|*sunos*) + CPPFLAGS="$CFLAGS -D_POSIX_PTHREAD_SEMANTICS -D_XPG4_2 -D__EXTENSIONS__" ;; *) ;; diff --git a/libratbox/configure.ac b/libratbox/configure.ac index 86588c896..b51ecb1b1 100644 --- a/libratbox/configure.ac +++ b/libratbox/configure.ac @@ -79,8 +79,8 @@ case "$host_os" in *interix*) CPPFLAGS="$CFLAGS -D_ALL_SOURCE -D_XOPEN_SOURCE=500" ;; -*solaris*) - CPPFLAGS="$CFLAGS -D_POSIX_PTHREAD_SEMANTICS" +*solaris*|*sunos*) + CPPFLAGS="$CFLAGS -D_POSIX_PTHREAD_SEMANTICS -D_XPG4_2 -D__EXTENSIONS__" ;; *) ;; diff --git a/libratbox/src/balloc.c b/libratbox/src/balloc.c index 19e9a256e..7c06e3070 100644 --- a/libratbox/src/balloc.c +++ b/libratbox/src/balloc.c @@ -28,7 +28,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA * - * $Id: balloc.c 25675 2008-07-06 04:13:05Z androsyn $ + * $Id: balloc.c 25861 2008-08-06 19:51:44Z androsyn $ */ /* @@ -69,6 +69,8 @@ #endif #endif +static uintptr_t offset_pad; + /* status information for an allocated block in heap */ struct rb_heap_block { @@ -79,17 +81,6 @@ struct rb_heap_block }; typedef struct rb_heap_block rb_heap_block; -struct rb_heap_memblock -{ - rb_heap_block *block; - union { - rb_dlink_node node; - char data[1]; /* stub pointer..this is ugly */ - } ndata; -}; - -typedef struct rb_heap_memblock rb_heap_memblock; - /* information for the root node of the heap */ struct rb_bh { @@ -155,6 +146,18 @@ void rb_init_bh(void) { heap_lists = rb_malloc(sizeof(rb_dlink_list)); + offset_pad = sizeof(void *); + /* XXX if you get SIGBUS when trying to use a long long..here is where you need to + * fix your shit + */ +#ifdef __sparc__ + if((offset_pad % __alignof__(long long)) != 0) + { + offset_pad += __alignof__(long long); + offset_pad &= ~(__alignof__(long long) - 1); + } +#endif + #ifndef NOBALLOC #ifdef WIN32 block_heap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0); @@ -226,11 +229,11 @@ newblock(rb_bh * bh) rb_heap_block *b; unsigned long i; uintptr_t offset; - + rb_dlink_node *node; /* Setup the initial data structure. */ b = rb_malloc(sizeof(rb_heap_block)); - b->alloc_size = bh->elemsPerBlock * (bh->elemSize + sizeof(rb_heap_block *)); + b->alloc_size = bh->elemsPerBlock * bh->elemSize; b->elems = get_block(b->alloc_size); if(rb_unlikely(b->elems == NULL)) @@ -239,11 +242,11 @@ newblock(rb_bh * bh) } offset = (uintptr_t)b->elems; /* Setup our blocks now */ - for (i = 0; i < bh->elemsPerBlock; i++, offset += (bh->elemSize + sizeof(rb_heap_block *))) + for (i = 0; i < bh->elemsPerBlock; i++, offset += bh->elemSize) { - rb_heap_memblock *memblock = (rb_heap_memblock *)offset; - memblock->block = b; - rb_dlinkAdd(memblock, &memblock->ndata.node, &bh->free_list); + *((void **)offset) = b; + node = (void *)(offset + offset_pad); + rb_dlinkAdd((void *)offset, node, &bh->free_list); } rb_dlinkAdd(b, &b->node, &bh->block_list); b->free_count = bh->elemsPerBlock; @@ -272,26 +275,27 @@ rb_bh_create(size_t elemsize, int elemsperblock, const char *desc) rb_bh *bh; lrb_assert(elemsize > 0 && elemsperblock > 0); lrb_assert(elemsize >= sizeof(rb_dlink_node)); + /* Catch idiotic requests up front */ if((elemsize == 0) || (elemsperblock <= 0)) { rb_bh_fail("Attempting to rb_bh_create idiotic sizes"); } - + if(elemsize < sizeof(rb_dlink_node)) rb_bh_fail("Attempt to rb_bh_create smaller than sizeof(rb_dlink_node)"); /* Allocate our new rb_bh */ bh = rb_malloc(sizeof(rb_bh)); - #ifndef NOBALLOC + elemsize += offset_pad; if((elemsize % sizeof(void *)) != 0) { /* Pad to even pointer boundary */ elemsize += sizeof(void *); elemsize &= ~(sizeof(void *) - 1); } -#endif /* !NOBALLOC */ +#endif bh->elemSize = elemsize; bh->elemsPerBlock = elemsperblock; @@ -334,7 +338,8 @@ rb_bh_alloc(rb_bh * bh) { #ifndef NOBALLOC rb_dlink_node *new_node; - rb_heap_memblock *memblock; + rb_heap_block *block; + void *ptr; #endif lrb_assert(bh != NULL); if(rb_unlikely(bh == NULL)) @@ -363,11 +368,11 @@ rb_bh_alloc(rb_bh * bh) } new_node = bh->free_list.head; - memblock = new_node->data; + block = new_node->data; + ptr = new_node->data + offset_pad; rb_dlinkDelete(new_node, &bh->free_list); - memblock->block->free_count--; - memset((void *)memblock->ndata.data, 0, bh->elemSize); - return((void *)memblock->ndata.data); + memset(ptr, 0, bh->elemSize - offset_pad); + return(ptr); #endif } @@ -387,7 +392,8 @@ int rb_bh_free(rb_bh * bh, void *ptr) { #ifndef NOBALLOC - rb_heap_memblock *memblock; + rb_heap_block *block; + void *data; #endif lrb_assert(bh != NULL); lrb_assert(ptr != NULL); @@ -407,14 +413,15 @@ rb_bh_free(rb_bh * bh, void *ptr) #ifdef NOBALLOC rb_free(ptr); #else - memblock = (rb_heap_memblock *) ((uintptr_t)ptr - sizeof(rb_heap_block *)); + data = (void *)(ptr - offset_pad); + block = *(rb_heap_block **)data; /* XXX */ - if(rb_unlikely(!((uintptr_t)ptr >= (uintptr_t)memblock->block->elems && (uintptr_t)ptr < (uintptr_t)memblock->block->elems + (uintptr_t)memblock->block->alloc_size))) + if(rb_unlikely(!((uintptr_t)ptr >= (uintptr_t)block->elems && (uintptr_t)ptr < (uintptr_t)block->elems + (uintptr_t)block->alloc_size))) { rb_bh_fail("rb_bh_free() bogus pointer"); } - memblock->block->free_count++; - rb_dlinkAdd(memblock, &memblock->ndata.node, &bh->free_list); + block->free_count++; + rb_dlinkAdd(data, (rb_dlink_node *)ptr, &bh->free_list); #endif /* !NOBALLOC */ return (0); } @@ -468,7 +475,7 @@ rb_bh_usage(rb_bh * bh, size_t * bused, size_t * bfree, size_t * bmemusage, cons freem = rb_dlink_list_length(&bh->free_list); used = (rb_dlink_list_length(&bh->block_list) * bh->elemsPerBlock) - freem; - memusage = used * (bh->elemSize + sizeof(void *)); + memusage = used * bh->elemSize; if(bused != NULL) *bused = used; if(bfree != NULL) @@ -495,8 +502,8 @@ void rb_bh_usage_all(rb_bh_usage_cb *cb, void *data) bh = (rb_bh *)ptr->data; freem = rb_dlink_list_length(&bh->free_list); used = (rb_dlink_list_length(&bh->block_list) * bh->elemsPerBlock) - freem; - memusage = used * (bh->elemSize + sizeof(void *)); - heapalloc = (freem + used) * (bh->elemSize + sizeof(void *)); + memusage = used * bh->elemSize; + heapalloc = (freem + used) * bh->elemSize; if(bh->desc != NULL) desc = bh->desc; cb(used, freem, memusage, heapalloc, desc, data); @@ -516,8 +523,8 @@ rb_bh_total_usage(size_t *total_alloc, size_t *total_used) bh = (rb_bh *)ptr->data; freem = rb_dlink_list_length(&bh->free_list); used = (rb_dlink_list_length(&bh->block_list) * bh->elemsPerBlock) - freem; - used_memory += used * (bh->elemSize + sizeof(void *)); - total_memory += (freem + used) * (bh->elemSize + sizeof(void *)); + used_memory += used * bh->elemSize; + total_memory += (freem + used) * bh->elemSize; } if(total_alloc != NULL) @@ -558,10 +565,9 @@ rb_bh_gc(rb_bh * bh) /* i'm seriously going to hell for this.. */ offset = (uintptr_t)b->elems; - for (i = 0; i < bh->elemsPerBlock; i++, offset += ((uintptr_t)bh->elemSize + sizeof(rb_heap_memblock *))) + for (i = 0; i < bh->elemsPerBlock; i++, offset += (uintptr_t)bh->elemSize) { - rb_heap_memblock *memblock = (rb_heap_memblock *)offset; - rb_dlinkDelete(&memblock->ndata.node, &bh->free_list); + rb_dlinkDelete(((rb_dlink_node *)offset), &bh->free_list); } rb_dlinkDelete(&b->node, &bh->block_list); free_block(b->elems, b->alloc_size); diff --git a/libratbox/src/ports.c b/libratbox/src/ports.c index 2bfcbbe1f..353b07b7f 100644 --- a/libratbox/src/ports.c +++ b/libratbox/src/ports.c @@ -45,7 +45,7 @@ static port_event_t *pelst; /* port buffer */ static int pemax; /* max structs to buffer */ int -rb_setup_fd_ports(int fd) +rb_setup_fd_ports(rb_fde_t *F) { return 0; } diff --git a/modules/core/m_error.c b/modules/core/m_error.c index 9659f11b2..5a5bd67a6 100644 --- a/modules/core/m_error.c +++ b/modules/core/m_error.c @@ -58,7 +58,7 @@ is_safe_error(const char *message) if (!strncmp(message, "Closing Link: 127.0.0.1 (", 25)) return 1; - snprintf(prefix2, sizeof prefix2, + rb_snprintf(prefix2, sizeof prefix2, "Closing Link: 127.0.0.1 %s (", me.name); if (!strncmp(message, prefix2, strlen(prefix2))) return 1; diff --git a/modules/core/m_join.c b/modules/core/m_join.c index ff4750f33..2f51663d2 100644 --- a/modules/core/m_join.c +++ b/modules/core/m_join.c @@ -137,6 +137,7 @@ m_join(struct Client *client_p, struct Client *source_p, int parc, const char *p struct ConfItem *aconf; char *name; char *key = NULL; + const char *modes; int i, flags = 0; char *p = NULL, *p2 = NULL; char *chanlist; @@ -341,17 +342,15 @@ m_join(struct Client *client_p, struct Client *source_p, int parc, const char *p chptr->channelts = rb_current_time(); chptr->mode.mode |= MODE_TOPICLIMIT; chptr->mode.mode |= MODE_NOPRIVMSGS; + modes = channel_modes(chptr, &me); - sendto_channel_local(ONLY_CHANOPS, chptr, ":%s MODE %s +nt", - me.name, chptr->chname); + sendto_channel_local(ONLY_CHANOPS, chptr, ":%s MODE %s %s", + me.name, chptr->chname, modes); - if(*chptr->chname == '#') - { - sendto_server(client_p, chptr, CAP_TS6, NOCAPS, - ":%s SJOIN %ld %s +nt :@%s", - me.id, (long) chptr->channelts, - chptr->chname, source_p->id); - } + sendto_server(client_p, chptr, CAP_TS6, NOCAPS, + ":%s SJOIN %ld %s %s :@%s", + me.id, (long) chptr->channelts, + chptr->chname, modes, source_p->id); } else { diff --git a/modules/core/m_message.c b/modules/core/m_message.c index fc0896ff3..658a2a309 100644 --- a/modules/core/m_message.c +++ b/modules/core/m_message.c @@ -916,7 +916,6 @@ handle_special(int p_or_n, const char *command, struct Client *client_p, struct Client *target_p; char *server; char *s; - int count; /* user[%host]@server addressed? * NOTE: users can send to user@server, but not user%host@server @@ -931,8 +930,6 @@ handle_special(int p_or_n, const char *command, struct Client *client_p, return; } - count = 0; - if(!IsOper(source_p)) { if(strchr(nick, '%') || (strncmp(nick, "opers", 5) == 0)) diff --git a/modules/core/m_nick.c b/modules/core/m_nick.c index 7d0996c65..9db4a7702 100644 --- a/modules/core/m_nick.c +++ b/modules/core/m_nick.c @@ -318,6 +318,7 @@ ms_nick(struct Client *client_p, struct Client *source_p, int parc, const char * { struct Client *target_p; time_t newts = 0; + char squitreason[100]; if(parc != 9) { @@ -326,7 +327,10 @@ ms_nick(struct Client *client_p, struct Client *source_p, int parc, const char * "with %d arguments (expecting 9)", client_p->name, parc); ilog(L_SERVER, "Excess parameters (%d) for command 'NICK' from %s.", parc, client_p->name); - exit_client(client_p, client_p, client_p, "Excess parameters to NICK command"); + rb_snprintf(squitreason, sizeof squitreason, + "Excess parameters (%d) to %s command, expecting %d", + parc, "NICK", 9); + exit_client(client_p, client_p, client_p, squitreason); return 0; } @@ -404,6 +408,7 @@ ms_uid(struct Client *client_p, struct Client *source_p, int parc, const char *p { struct Client *target_p; time_t newts = 0; + char squitreason[120]; newts = atol(parv[3]); @@ -414,7 +419,10 @@ ms_uid(struct Client *client_p, struct Client *source_p, int parc, const char *p "with %d arguments (expecting 10)", client_p->name, parc); ilog(L_SERVER, "Excess parameters (%d) for command 'UID' from %s.", parc, client_p->name); - exit_client(client_p, client_p, client_p, "Excess parameters to UID command"); + rb_snprintf(squitreason, sizeof squitreason, + "Excess parameters (%d) to %s command, expecting %d", + parc, "UID", 10); + exit_client(client_p, client_p, client_p, squitreason); return 0; } @@ -425,6 +433,15 @@ ms_uid(struct Client *client_p, struct Client *source_p, int parc, const char *p return 0; } + if(!clean_uid(parv[8])) + { + rb_snprintf(squitreason, sizeof squitreason, + "Invalid UID %s for nick %s on %s", + parv[8], parv[1], source_p->name); + exit_client(client_p, client_p, client_p, squitreason); + return 0; + } + if(!clean_username(parv[5]) || !clean_host(parv[6])) { ServerStats.is_kill++; @@ -435,16 +452,6 @@ ms_uid(struct Client *client_p, struct Client *source_p, int parc, const char *p return 0; } - if(!clean_uid(parv[8])) - { - ServerStats.is_kill++; - sendto_realops_snomask(SNO_DEBUG, L_ALL, - "Bad UID: %s From: %s(via %s)", - parv[8], source_p->name, client_p->name); - sendto_one(client_p, ":%s KILL %s :%s (Bad UID)", me.id, parv[8], me.name); - return 0; - } - /* check length of clients gecos */ if(strlen(parv[9]) > REALLEN) { @@ -492,6 +499,7 @@ ms_euid(struct Client *client_p, struct Client *source_p, int parc, const char * { struct Client *target_p; time_t newts = 0; + char squitreason[120]; newts = atol(parv[3]); @@ -502,7 +510,10 @@ ms_euid(struct Client *client_p, struct Client *source_p, int parc, const char * "with %d arguments (expecting 12)", client_p->name, parc); ilog(L_SERVER, "Excess parameters (%d) for command 'EUID' from %s.", parc, client_p->name); - exit_client(client_p, client_p, client_p, "Excess parameters to EUID command"); + rb_snprintf(squitreason, sizeof squitreason, + "Excess parameters (%d) to %s command, expecting %d", + parc, "EUID", 12); + exit_client(client_p, client_p, client_p, squitreason); return 0; } @@ -513,6 +524,15 @@ ms_euid(struct Client *client_p, struct Client *source_p, int parc, const char * return 0; } + if(!clean_uid(parv[8])) + { + rb_snprintf(squitreason, sizeof squitreason, + "Invalid UID %s for nick %s on %s", + parv[8], parv[1], source_p->name); + exit_client(client_p, client_p, client_p, squitreason); + return 0; + } + if(!clean_username(parv[5]) || !clean_host(parv[6])) { ServerStats.is_kill++; @@ -523,16 +543,6 @@ ms_euid(struct Client *client_p, struct Client *source_p, int parc, const char * return 0; } - if(!clean_uid(parv[8])) - { - ServerStats.is_kill++; - sendto_realops_snomask(SNO_DEBUG, L_ALL, - "Bad UID: %s From: %s(via %s)", - parv[8], source_p->name, client_p->name); - sendto_one(client_p, ":%s KILL %s :%s (Bad UID)", me.id, parv[8], me.name); - return 0; - } - if(strcmp(parv[9], "*") && !clean_host(parv[9])) { ServerStats.is_kill++; diff --git a/modules/core/m_server.c b/modules/core/m_server.c index 95926f10c..dc05c005b 100644 --- a/modules/core/m_server.c +++ b/modules/core/m_server.c @@ -119,7 +119,7 @@ mr_server(struct Client *client_p, struct Client *source_p, int parc, const char sendto_realops_snomask(SNO_GENERAL, L_ALL, "Unauthorised server connection attempt from %s: " "No entry for servername %s", - client_p->name, name); + "[@255.255.255.255]", name); ilog(L_SERVER, "Access denied, no connect block for server %s%s", EmptyString(client_p->name) ? name : "", @@ -135,7 +135,7 @@ mr_server(struct Client *client_p, struct Client *source_p, int parc, const char sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) ? L_NETWIDE : L_ALL, "Unauthorised server connection attempt from %s: " "Bad password for server %s", - client_p->name, name); + "[@255.255.255.255]", name); ilog(L_SERVER, "Access denied, invalid password for server %s%s", EmptyString(client_p->name) ? name : "", @@ -150,7 +150,7 @@ mr_server(struct Client *client_p, struct Client *source_p, int parc, const char sendto_realops_snomask(SNO_GENERAL, L_ALL, "Unauthorised server connection attempt from %s: " "Invalid host for server %s", - client_p->name, name); + "[@255.255.255.255]", name); ilog(L_SERVER, "Access denied, invalid host for server %s%s", EmptyString(client_p->name) ? name : "", @@ -165,7 +165,7 @@ mr_server(struct Client *client_p, struct Client *source_p, int parc, const char case -4: sendto_realops_snomask(SNO_GENERAL, L_ALL, "Invalid servername %s from %s", - name, client_p->name); + name, "[@255.255.255.255]"); ilog(L_SERVER, "Access denied, invalid servername from %s", log_client_name(client_p, SHOW_IP)); @@ -208,7 +208,7 @@ mr_server(struct Client *client_p, struct Client *source_p, int parc, const char */ sendto_realops_snomask(SNO_GENERAL, L_ALL, "Attempt to re-introduce server %s from %s", - name, client_p->name); + name, "[@255.255.255.255]"); ilog(L_SERVER, "Attempt to re-introduce server %s from %s", name, log_client_name(client_p, SHOW_IP)); @@ -220,14 +220,15 @@ mr_server(struct Client *client_p, struct Client *source_p, int parc, const char if(has_id(client_p) && (target_p = find_id(client_p->id)) != NULL) { sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) ? L_NETWIDE : L_ALL, - "Attempt to re-introduce SID %s from %s%s", + "Attempt to re-introduce SID %s from %s%s (already in use by %s)", client_p->id, EmptyString(client_p->name) ? name : "", - client_p->name); - ilog(L_SERVER, "Attempt to re-introduce SID %s from %s%s", + client_p->name, target_p->name); + ilog(L_SERVER, "Attempt to re-introduce SID %s from %s%s (already in use by %s)", client_p->id, EmptyString(client_p->name) ? name : "", - log_client_name(client_p, SHOW_IP)); + log_client_name(client_p, SHOW_IP), + target_p->name); sendto_one(client_p, "ERROR :SID already exists."); exit_client(client_p, client_p, client_p, "SID Exists"); @@ -267,6 +268,7 @@ ms_server(struct Client *client_p, struct Client *source_p, int parc, const char int hlined = 0; int llined = 0; rb_dlink_node *ptr; + char squitreason[160]; name = parv[1]; hop = atoi(parv[2]); @@ -292,21 +294,13 @@ ms_server(struct Client *client_p, struct Client *source_p, int parc, const char * doesnt exist, although ircd can handle it, its not a realistic * solution.. --fl_ */ - /* It is behind a host-masked server. Completely ignore the - * server message(don't propagate or we will delink from whoever - * we propagate to). -A1kmm */ - if(irccmp(target_p->name, name) && target_p->from == client_p) - return 0; - - sendto_one(client_p, "ERROR :Server %s already exists", name); - - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "Link %s cancelled, server %s already exists", - client_p->name, name); ilog(L_SERVER, "Link %s cancelled, server %s already exists", client_p->name, name); - exit_client(client_p, client_p, &me, "Server Exists"); + rb_snprintf(squitreason, sizeof squitreason, + "Server %s already exists", + name); + exit_client(client_p, client_p, &me, squitreason); return 0; } @@ -338,11 +332,6 @@ ms_server(struct Client *client_p, struct Client *source_p, int parc, const char * add it to list and propagate word to my other * server links... */ - if(parc == 1 || EmptyString(info)) - { - sendto_one(client_p, "ERROR :No server info specified for %s", name); - return 0; - } /* * See if the newly found server is behind a guaranteed @@ -385,7 +374,7 @@ ms_server(struct Client *client_p, struct Client *source_p, int parc, const char * .edu's */ - /* Ok, check client_p can hub the new server, and make sure it's not a LL */ + /* Ok, check client_p can hub the new server */ if(!hlined) { /* OOOPs nope can't HUB */ @@ -394,7 +383,10 @@ ms_server(struct Client *client_p, struct Client *source_p, int parc, const char ilog(L_SERVER, "Non-Hub link %s introduced %s.", client_p->name, name); - exit_client(NULL, client_p, &me, "No matching hub_mask."); + rb_snprintf(squitreason, sizeof squitreason, + "No matching hub_mask for %s", + name); + exit_client(NULL, client_p, &me, squitreason); return 0; } @@ -408,7 +400,10 @@ ms_server(struct Client *client_p, struct Client *source_p, int parc, const char ilog(L_SERVER, "Link %s introduced leafed server %s.", client_p->name, name); - exit_client(NULL, client_p, &me, "Leafed Server."); + rb_snprintf(squitreason, sizeof squitreason, + "Matching leaf_mask for %s", + name); + exit_client(NULL, client_p, &me, squitreason); return 0; } @@ -473,34 +468,39 @@ ms_sid(struct Client *client_p, struct Client *source_p, int parc, const char *p int hop; int hlined = 0; int llined = 0; + char squitreason[160]; hop = atoi(parv[2]); /* collision on the name? */ if((target_p = find_server(NULL, parv[1])) != NULL) { - sendto_one(client_p, "ERROR :Server %s already exists", parv[1]); - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "Link %s cancelled, server %s already exists", - client_p->name, parv[1]); ilog(L_SERVER, "Link %s cancelled, server %s already exists", client_p->name, parv[1]); - exit_client(NULL, client_p, &me, "Server Exists"); + rb_snprintf(squitreason, sizeof squitreason, + "Server %s already exists", + parv[1]); + exit_client(NULL, client_p, &me, squitreason); return 0; } /* collision on the SID? */ if((target_p = find_id(parv[3])) != NULL) { - sendto_one(client_p, "ERROR :SID %s already exists", parv[3]); - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "Link %s cancelled, SID %s already exists", - client_p->name, parv[3]); - ilog(L_SERVER, "Link %s cancelled, SID %s already exists", - client_p->name, parv[3]); + sendto_wallops_flags(UMODE_WALLOP, &me, + "Link %s cancelled, SID %s for server %s already in use by %s", + client_p->name, parv[3], parv[1], target_p->name); + sendto_server(NULL, NULL, CAP_TS6, NOCAPS, + ":%s WALLOPS :Link %s cancelled, SID %s for server %s already in use by %s", + me.id, client_p->name, parv[3], parv[1], target_p->name); + ilog(L_SERVER, "Link %s cancelled, SID %s for server %s already in use by %s", + client_p->name, parv[3], parv[1], target_p->name); - exit_client(NULL, client_p, &me, "SID Exists"); + rb_snprintf(squitreason, sizeof squitreason, + "SID %s for %s already in use by %s", + parv[3], parv[1], target_p->name); + exit_client(NULL, client_p, &me, squitreason); return 0; } @@ -551,26 +551,32 @@ ms_sid(struct Client *client_p, struct Client *source_p, int parc, const char *p /* no matching hub_mask */ if(!hlined) { - sendto_one(client_p, "ERROR :No matching hub_mask"); sendto_realops_snomask(SNO_GENERAL, L_ALL, "Non-Hub link %s introduced %s.", client_p->name, parv[1]); ilog(L_SERVER, "Non-Hub link %s introduced %s.", client_p->name, parv[1]); - exit_client(NULL, client_p, &me, "No matching hub_mask."); + + rb_snprintf(squitreason, sizeof squitreason, + "No matching hub_mask for %s", + parv[1]); + exit_client(NULL, client_p, &me, squitreason); return 0; } /* matching leaf_mask */ if(llined) { - sendto_one(client_p, "ERROR :Matching leaf_mask"); sendto_realops_snomask(SNO_GENERAL, L_ALL, "Link %s introduced leafed server %s.", client_p->name, parv[1]); ilog(L_SERVER, "Link %s introduced leafed server %s.", client_p->name, parv[1]); - exit_client(NULL, client_p, &me, "Leafed Server."); + + rb_snprintf(squitreason, sizeof squitreason, + "Matching leaf_mask for %s", + parv[1]); + exit_client(NULL, client_p, &me, squitreason); return 0; } diff --git a/modules/m_challenge.c b/modules/m_challenge.c index ea7c1280e..e0b9dbe05 100644 --- a/modules/m_challenge.c +++ b/modules/m_challenge.c @@ -223,6 +223,22 @@ m_challenge(struct Client *client_p, struct Client *source_p, int parc, const ch return 0; } + if(IsOperConfNeedSSL(oper_p) && !IsSSLClient(source_p)) + { + sendto_one(source_p, form_str(ERR_NOOPERHOST), me.name, source_p->name); + ilog(L_FOPER, "FAILED CHALLENGE (%s) by (%s!%s@%s) (%s) -- requires SSL/TLS", + parv[1], source_p->name, source_p->username, source_p->host, + source_p->sockhost); + + if(ConfigFileEntry.failed_oper_notice) + { + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "Failed CHALLENGE attempt - missing SSL/TLS by %s (%s@%s)", + source_p->name, source_p->username, source_p->host); + } + return 0; + } + if(!generate_challenge(&challenge, &(source_p->localClient->challenge), oper_p->rsa_pubkey)) { char *chal = challenge; diff --git a/modules/m_info.c b/modules/m_info.c index 870fe1219..03671b43f 100644 --- a/modules/m_info.c +++ b/modules/m_info.c @@ -446,6 +446,18 @@ static struct InfoStruct info_table[] = { &ConfigFileEntry.stats_y_oper_only, "STATS Y is only shown to operators", }, + { + "throttle_count", + OUTPUT_DECIMAL, + &ConfigFileEntry.throttle_count, + "Connection throttle threshold", + }, + { + "throttle_duration", + OUTPUT_DECIMAL, + &ConfigFileEntry.throttle_duration, + "Connection throttle duration", + }, { "tkline_expire_notices", OUTPUT_BOOLEAN, diff --git a/modules/m_list.c b/modules/m_list.c index db397a2b7..ab05e405f 100644 --- a/modules/m_list.c +++ b/modules/m_list.c @@ -324,7 +324,7 @@ static void safelist_channel_named(struct Client *source_p, const char *name) return; } - if (ShowChannel(source_p, chptr)) + if (!SecretChannel(chptr) || IsMember(source_p, chptr)) sendto_one(source_p, form_str(RPL_LIST), me.name, source_p->name, chptr->chname, rb_dlink_list_length(&chptr->members), chptr->topic == NULL ? "" : chptr->topic); diff --git a/modules/m_monitor.c b/modules/m_monitor.c index 1193c69e2..a6ce57551 100644 --- a/modules/m_monitor.c +++ b/modules/m_monitor.c @@ -89,9 +89,9 @@ add_monitor(struct Client *client_p, const char *nicks) sendto_one(client_p, "%s", offbuf); if(p) - snprintf(buf, sizeof(buf), "%s,%s", name, p); + rb_snprintf(buf, sizeof(buf), "%s,%s", name, p); else - snprintf(buf, sizeof(buf), "%s", name); + rb_snprintf(buf, sizeof(buf), "%s", name); sendto_one(client_p, form_str(ERR_MONLISTFULL), me.name, client_p->name, diff --git a/modules/m_oper.c b/modules/m_oper.c index 2a8a2f0e7..1b0b7c928 100644 --- a/modules/m_oper.c +++ b/modules/m_oper.c @@ -100,6 +100,22 @@ m_oper(struct Client *client_p, struct Client *source_p, int parc, const char *p return 0; } + if(IsOperConfNeedSSL(oper_p) && !IsSSLClient(source_p)) + { + sendto_one(source_p, form_str(ERR_NOOPERHOST), me.name, source_p->name); + ilog(L_FOPER, "FAILED OPER (%s) by (%s!%s@%s) (%s) -- requires SSL/TLS", + name, source_p->name, + source_p->username, source_p->host, source_p->sockhost); + + if(ConfigFileEntry.failed_oper_notice) + { + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "Failed OPER attempt - missing SSL/TLS by %s (%s@%s)", + source_p->name, source_p->username, source_p->host); + } + return 0; + } + if(match_oper_password(password, oper_p)) { oper_up(source_p, oper_p); diff --git a/modules/m_pass.c b/modules/m_pass.c index 0cc0747ba..b66de738f 100644 --- a/modules/m_pass.c +++ b/modules/m_pass.c @@ -83,9 +83,9 @@ mr_pass(struct Client *client_p, struct Client *source_p, int parc, const char * auth_user = NULL; } - client_p->localClient->passwd = rb_strndup(pass, PASSWDLEN); + client_p->localClient->passwd = *pass ? rb_strndup(pass, PASSWDLEN) : NULL; - if(auth_user) + if(auth_user && *auth_user) client_p->localClient->auth_user = rb_strndup(auth_user, PASSWDLEN); /* These are for servers only */ diff --git a/modules/m_privs.c b/modules/m_privs.c index e4479f6de..1d24aad5a 100644 --- a/modules/m_privs.c +++ b/modules/m_privs.c @@ -60,28 +60,6 @@ struct mode_table int mode; }; -static struct mode_table oper_table[] = { - /*{"encrypted", OPER_ENCRYPTED },*/ - {"local_kill", OPER_LOCKILL }, - {"global_kill", OPER_GLOBKILL/*|OPER_LOCKILL*/ }, - {"remote", OPER_REMOTE }, - {"kline", OPER_KLINE }, - {"unkline", OPER_UNKLINE }, - {"nick_changes", OPER_NICKS }, - {"rehash", OPER_REHASH }, - {"die", OPER_DIE }, - {"admin", OPER_ADMIN }, - {"hidden_admin", OPER_HADMIN }, - {"xline", OPER_XLINE }, - {"resv", OPER_RESV }, - {"operwall", OPER_OPERWALL }, - {"oper_spy", OPER_SPY }, - {"hidden_oper", OPER_INVIS }, - {"remoteban", OPER_REMOTEBAN }, - {"mass_notice", OPER_MASSNOTICE }, - {NULL, 0} -}; - /* there is no such table like this anywhere else */ static struct mode_table auth_client_table[] = { {"resv_exempt", FLAGS2_EXEMPTRESV }, @@ -101,23 +79,22 @@ static void show_privs(struct Client *source_p, struct Client *target_p) struct mode_table *p; buf[0] = '\0'; - p = &oper_table[0]; - while (p->name != NULL) - { - if (target_p->flags2 & p->mode) - { - if (buf[0] != '\0') - rb_strlcat(buf, " ", sizeof buf); - rb_strlcat(buf, p->name, sizeof buf); - } - p++; - } + if (target_p->localClient->privset) + rb_strlcat(buf, target_p->localClient->privset->privs, sizeof buf); if (IsOper(target_p)) { if (buf[0] != '\0') rb_strlcat(buf, " ", sizeof buf); rb_strlcat(buf, "operator:", sizeof buf); rb_strlcat(buf, target_p->localClient->opername, sizeof buf); + + if (target_p->localClient->privset) + { + if (buf[0] != '\0') + rb_strlcat(buf, " ", sizeof buf); + rb_strlcat(buf, "privset:", sizeof buf); + rb_strlcat(buf, target_p->localClient->privset->name, sizeof buf); + } } p = &auth_client_table[0]; while (p->name != NULL) diff --git a/modules/m_services.c b/modules/m_services.c index a78cc7f25..ffc77cd5f 100644 --- a/modules/m_services.c +++ b/modules/m_services.c @@ -195,7 +195,7 @@ me_rsfnc(struct Client *client_p, struct Client *source_p, kill_client_serv_butone(NULL, exist_p, "%s (Nickname regained by services)", me.name); - snprintf(buf, sizeof(buf), "Killed (%s (Nickname regained by services))", + rb_snprintf(buf, sizeof(buf), "Killed (%s (Nickname regained by services))", me.name); exit_client(NULL, exist_p, &me, buf); } diff --git a/modules/m_signon.c b/modules/m_signon.c index d57d953a9..f28021ff0 100644 --- a/modules/m_signon.c +++ b/modules/m_signon.c @@ -214,7 +214,7 @@ me_svslogin(struct Client *client_p, struct Client *source_p, kill_client_serv_butone(NULL, exist_p, "%s (Nickname regained by services)", me.name); - snprintf(buf, sizeof(buf), "Killed (%s (Nickname regained by services))", + rb_snprintf(buf, sizeof(buf), "Killed (%s (Nickname regained by services))", me.name); exit_client(NULL, exist_p, &me, buf); }else if((exist_p = find_client(nick)) && IsUnknown(exist_p) && exist_p != target_p) { diff --git a/modules/m_stats.c b/modules/m_stats.c index 92fc3f24c..b1c68ec0a 100644 --- a/modules/m_stats.c +++ b/modules/m_stats.c @@ -674,7 +674,7 @@ stats_oper(struct Client *source_p) sendto_one_numeric(source_p, RPL_STATSOLINE, form_str(RPL_STATSOLINE), oper_p->username, oper_p->host, oper_p->name, - IsOper(source_p) ? get_oper_privs(oper_p->flags) : "0", "-1"); + IsOper(source_p) ? oper_p->privset->name : "0", "-1"); } } @@ -875,7 +875,7 @@ stats_tstats (struct Client *source_p) "T :accepts %u refused %u", sp.is_ac, sp.is_ref); sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :rejected %u delaying %lu", - sp.is_rej, rb_dlink_list_length(&delay_exit)); + sp.is_rej, delay_exit_length()); sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :nicks being delayed %lu", get_nd_count()); @@ -949,9 +949,9 @@ static struct shared_flags shared_flagtable[] = { SHARED_UNRESV, 'R' }, { SHARED_LOCOPS, 'L' }, { SHARED_REHASH, 'H' }, - { SHARED_TDLINE, 'd' }, - { SHARED_PDLINE, 'D' }, - { SHARED_UNDLINE, 'E' }, + { SHARED_TDLINE, 'd' }, + { SHARED_PDLINE, 'D' }, + { SHARED_UNDLINE, 'E' }, { 0, '\0'} }; @@ -961,7 +961,7 @@ stats_shared (struct Client *source_p) { struct remote_conf *shared_p; rb_dlink_node *ptr; - char buf[15]; + char buf[sizeof(shared_flagtable)/sizeof(shared_flagtable[0])]; char *p; int i; diff --git a/modules/m_svinfo.c b/modules/m_svinfo.c index 740f8d7df..27ff52570 100644 --- a/modules/m_svinfo.c +++ b/modules/m_svinfo.c @@ -71,7 +71,7 @@ ms_svinfo(struct Client *client_p, struct Client *source_p, int parc, const char sendto_realops_snomask(SNO_GENERAL, L_ALL, "Link %s dropped, wrong TS protocol version (%s,%s)", source_p->name, parv[1], parv[2]); - snprintf(squitreason, sizeof squitreason, "Incompatible TS version (%s,%s)", + rb_snprintf(squitreason, sizeof squitreason, "Incompatible TS version (%s,%s)", parv[1], parv[2]); exit_client(source_p, source_p, source_p, squitreason); return 0; @@ -95,7 +95,7 @@ ms_svinfo(struct Client *client_p, struct Client *source_p, int parc, const char "Link %s dropped, excessive TS delta" " (my TS=%ld, their TS=%ld, delta=%d)", log_client_name(source_p, SHOW_IP), (long) rb_current_time(), (long) theirtime, deltat); - snprintf(squitreason, sizeof squitreason, "Excessive TS delta (my TS=%ld, their TS=%ld, delta=%d)", + rb_snprintf(squitreason, sizeof squitreason, "Excessive TS delta (my TS=%ld, their TS=%ld, delta=%d)", (long) rb_current_time(), (long) theirtime, deltat); exit_client(source_p, source_p, source_p, squitreason); return 0; diff --git a/modules/m_testline.c b/modules/m_testline.c index 993e995d5..0bcba6ea3 100644 --- a/modules/m_testline.c +++ b/modules/m_testline.c @@ -193,7 +193,8 @@ mo_testline(struct Client *client_p, struct Client *source_p, int parc, const ch if(aconf && aconf->status & CONF_CLIENT) { sendto_one_numeric(source_p, RPL_STATSILINE, form_str(RPL_STATSILINE), - aconf->name, show_iline_prefix(source_p, aconf, aconf->user), + aconf->name, EmptyString(aconf->spasswd) ? "" : aconf->spasswd, + show_iline_prefix(source_p, aconf, aconf->user), aconf->host, aconf->port, aconf->className); return 0; } diff --git a/modules/m_whois.c b/modules/m_whois.c index 54c71a1d5..085e4d64d 100644 --- a/modules/m_whois.c +++ b/modules/m_whois.c @@ -200,7 +200,7 @@ do_whois(struct Client *client_p, struct Client *source_p, int parc, const char { char buffer[BUFSIZE]; - snprintf(buffer, sizeof(buffer), "%s!%s@%s %s", + rb_snprintf(buffer, sizeof(buffer), "%s!%s@%s %s", target_p->name, target_p->username, target_p->host, target_p->servptr->name); report_operspy(source_p, "WHOIS", buffer); @@ -239,16 +239,9 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy) char *t; int tlen; hook_data_client hdata; - char *name; - char quest[] = "?"; int visible; int extra_space = 0; - if(target_p->name[0] == '\0') - name = quest; - else - name = target_p->name; - if(target_p->user == NULL) { s_assert(0); diff --git a/scripts/application.sh b/scripts/application.sh index f3da0b7dd..203bb6406 100755 --- a/scripts/application.sh +++ b/scripts/application.sh @@ -26,7 +26,7 @@ fi # Charybdis wants the hg tip to be in include/serno.h, in its own format. MYTIP=`hg parents --template '#date|shortdate#_#node|short#' 2>/dev/null | sed -e s/-//g -e s/_/-/` -echo "[atheme-services] Generating include/serno.h for tip $MYTIP." +echo "[charybdis] Generating include/serno.h for tip $MYTIP." cat << _EOF_ > include/serno.h /* Generated automatically by makepackage. Any changes made here will be lost. */ #define SERNO "$MYTIP" diff --git a/src/Makefile.in b/src/Makefile.in index 5322b5a2c..be06853c0 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -78,6 +78,7 @@ SRCS = \ numeric.c \ packet.c \ parse.c \ + privilege.c \ res.c \ reslib.c \ reject.c \ diff --git a/src/channel.c b/src/channel.c index e3e2c060b..52e4b50de 100644 --- a/src/channel.c +++ b/src/channel.c @@ -26,6 +26,7 @@ #include "stdinc.h" #include "channel.h" +#include "chmode.h" #include "client.h" #include "common.h" #include "hash.h" diff --git a/src/client.c b/src/client.c index a1fd820f5..0f717bc77 100644 --- a/src/client.c +++ b/src/client.c @@ -1280,7 +1280,6 @@ exit_unknown_client(struct Client *client_p, struct Client *source_p, struct Cli delete_resolver_queries(source_p->localClient->dnsquery); rb_free(source_p->localClient->dnsquery); } - del_unknown_ip(source_p); rb_dlinkDelete(&source_p->localClient->tnode, &unknown_list); if(!IsIOError(source_p)) @@ -1362,15 +1361,12 @@ static int qs_server(struct Client *client_p, struct Client *source_p, struct Client *from, const char *comment) { - struct Client *target_p; - if(source_p->servptr && source_p->servptr->serv) rb_dlinkDelete(&source_p->lnode, &source_p->servptr->serv->servers); else s_assert(0); rb_dlinkFindDestroy(source_p, &global_serv_list); - target_p = source_p->from; if(has_id(source_p)) del_from_id_hash(source_p->id, source_p); diff --git a/src/extban.c b/src/extban.c index c8a04df98..8890fccaf 100644 --- a/src/extban.c +++ b/src/extban.c @@ -68,17 +68,14 @@ int valid_extban(const char *banstr, struct Client *client_p, struct Channel *chptr, long mode_type) { const char *p; - int invert = 0, result = EXTBAN_INVALID; + int result = EXTBAN_INVALID; ExtbanFunc f; if (*banstr != '$') return 0; p = banstr + 1; if (*p == '~') - { - invert = 1; p++; - } f = extban_table[(unsigned char) ToLower(*p)]; if (*p != '\0') { diff --git a/src/hostmask.c b/src/hostmask.c index a0a193d5c..d02404882 100644 --- a/src/hostmask.c +++ b/src/hostmask.c @@ -446,7 +446,6 @@ find_exact_conf_by_address(const char *address, int type, const char *username) if(address == NULL) address = "/NOMATCH!/"; - arec = rb_malloc(sizeof(struct AddressRec)); masktype = parse_netmask(address, (struct sockaddr *)&addr, &bits); #ifdef RB_IPV6 if(masktype == HM_IPV6) diff --git a/src/irc_dictionary.c b/src/irc_dictionary.c index 0de08b6d8..89a0a7bb7 100644 --- a/src/irc_dictionary.c +++ b/src/irc_dictionary.c @@ -850,15 +850,15 @@ void irc_dictionary_stats(struct Dictionary *dict, void (*cb)(const char *line, s_assert(dict != NULL); if (dict->id != NULL) - snprintf(str, sizeof str, "Dictionary stats for %s (%d)", + rb_snprintf(str, sizeof str, "Dictionary stats for %s (%d)", dict->id, dict->count); else - snprintf(str, sizeof str, "Dictionary stats for <%p> (%d)", + rb_snprintf(str, sizeof str, "Dictionary stats for <%p> (%d)", (void *)dict, dict->count); cb(str, privdata); maxdepth = 0; sum = stats_recurse(dict->root, 0, &maxdepth); - snprintf(str, sizeof str, "Depth sum %d Avg depth %d Max depth %d", sum, sum / dict->count, maxdepth); + rb_snprintf(str, sizeof str, "Depth sum %d Avg depth %d Max depth %d", sum, sum / dict->count, maxdepth); cb(str, privdata); return; } diff --git a/src/ircd.c b/src/ircd.c index cd20e7506..a5c7bcdbe 100644 --- a/src/ircd.c +++ b/src/ircd.c @@ -66,6 +66,7 @@ #include "serno.h" #include "sslproc.h" #include "chmode.h" +#include "privilege.h" /* /quote set variables */ struct SetOptions GlobalSetOptions; @@ -188,7 +189,7 @@ init_sys(void) if(maxconnections <= MAX_BUFFER) { fprintf(stderr, "ERROR: Shell FD limits are too low.\n"); - fprintf(stderr, "ERROR: ircd-ratbox reserves %d FDs, shell limits must be above this\n", MAX_BUFFER); + fprintf(stderr, "ERROR: charybdis reserves %d FDs, shell limits must be above this\n", MAX_BUFFER); exit(EXIT_FAILURE); } return; @@ -447,12 +448,13 @@ setup_corefile(void) static void ircd_log_cb(const char *str) { - ilog(L_MAIN, "%s", str); + ilog(L_MAIN, "libratbox reports: %s", str); } static void ircd_restart_cb(const char *str) { + inotice("libratbox has called the restart callback: %s", str); restart(str); } @@ -469,9 +471,11 @@ ircd_die_cb(const char *str) if(str != NULL) { /* Try to get the message out to currently logged in operators. */ - sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Server panic! %s", str); - inotice("server panic: %s", str); + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "libratbox has called the die callback..aborting: %s", str); + inotice("libratbox has called the die callback..aborting: %s", str); } + else + inotice("libratbox has called the die callback..aborting"); unlink(pidFileName); exit(EXIT_FAILURE); @@ -628,6 +632,14 @@ main(int argc, char *argv[]) rb_lib_init(ircd_log_cb, ircd_restart_cb, ircd_die_cb, !server_state_foreground, maxconnections, DNODE_HEAP_SIZE, FD_HEAP_SIZE); rb_linebuf_init(LINEBUF_HEAP_SIZE); + if(ConfigFileEntry.use_egd && (ConfigFileEntry.egdpool_path != NULL)) + { + rb_init_prng(ConfigFileEntry.egdpool_path, RB_PRNG_EGD); + } else + rb_init_prng(NULL, RB_PRNG_DEFAULT); + + seed_random(NULL); + init_main_logfile(); newconf_init(); init_s_conf(); @@ -651,6 +663,7 @@ main(int argc, char *argv[]) #endif init_auth(); /* Initialise the auth code */ init_resolver(); /* Needs to be setup before the io loop */ + privilegeset_set_new("default", "", 0); if (testing_conf) fprintf(stderr, "\nBeginning config test\n"); diff --git a/src/ircd_lexer.l b/src/ircd_lexer.l index 4770c3e77..e7df1da93 100644 --- a/src/ircd_lexer.l +++ b/src/ircd_lexer.l @@ -91,7 +91,7 @@ ws [ \t]* digit [0-9] comment #.* qstring \"[^\"\n]*[\"\n] -string [a-zA-Z_\~][a-zA-Z0-9_]* +string [a-zA-Z_\~\:][a-zA-Z0-9_\:]* include \.include{ws}(\<.*\>|\".*\") %% diff --git a/src/listener.c b/src/listener.c index 60289fb2c..7f270a153 100644 --- a/src/listener.c +++ b/src/listener.c @@ -435,7 +435,7 @@ close_listeners() * any client list yet. */ static void -add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, void *ssl_ctl, int exempt) +add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, struct sockaddr *lai, void *ssl_ctl) { struct Client *new_client; s_assert(NULL != listener); @@ -447,6 +447,7 @@ add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, voi new_client = make_client(NULL); memcpy(&new_client->localClient->ip, sai, sizeof(struct rb_sockaddr_storage)); + memcpy(&new_client->preClient->lip, lai, sizeof(struct rb_sockaddr_storage)); /* * copy address to 'sockhost' as a string, copy it to host too @@ -467,17 +468,11 @@ add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, voi ++listener->ref_count; - if(!exempt) - { - if(check_reject(new_client)) - return; - if(add_unknown_ip(new_client)) - return; - } - start_auth(new_client); } +static const char *toofast = "ERROR :Reconnecting too fast, throttled.\r\n"; + static int accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, void *data) { @@ -512,7 +507,7 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi return 0; } - aconf = find_dline(addr, AF_INET); + aconf = find_dline(addr, addr->sa_family); if(aconf != NULL && (aconf->status & CONF_EXEMPTDLINE)) return 1; @@ -539,6 +534,16 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi return 0; } + if(check_reject(F, addr)) + return 0; + + if(throttle_add(addr)) + { + rb_write(F, toofast, strlen(toofast)); + rb_close(F); + return 0; + } + return 1; } @@ -549,7 +554,7 @@ accept_ssld(rb_fde_t *F, struct sockaddr *addr, struct sockaddr *laddr, struct L rb_fde_t *xF[2]; rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF[0], &xF[1], "Incoming ssld Connection"); ctl = start_ssld_accept(F, xF[1], rb_get_fd(xF[0])); /* this will close F for us */ - add_connection(listener, xF[0], addr, ctl, 1); + add_connection(listener, xF[0], addr, laddr, ctl); } static void @@ -563,13 +568,13 @@ accept_callback(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t add if(getsockname(rb_get_fd(F), (struct sockaddr *) &lip, &locallen) < 0) { - /* this shouldn't fail so... */ - /* XXX add logging of this */ + /* this can fail if the connection disappeared in the meantime */ rb_close(F); + return; } if(listener->ssl) accept_ssld(F, addr, (struct sockaddr *)&lip, listener); else - add_connection(listener, F, addr, NULL, 1); + add_connection(listener, F, addr, (struct sockaddr *)&lip, NULL); } diff --git a/src/messages.tab b/src/messages.tab index 2166b6462..e1b95d9b8 100644 --- a/src/messages.tab +++ b/src/messages.tab @@ -349,7 +349,7 @@ static const char * replies[] = { /* 325 */ NULL, /* 326 */ NULL, /* 327 */ NULL, -/* 328 */ NULL, +/* 328 RPL_CHANNELURL */ NULL, /* 329 RPL_CREATIONTIME, */ ":%s 329 %s %s %lu", /* 330 RPL_WHOISLOGGEDIN */ ":%s 330 %s %s %s :is logged in as", /* 331 RPL_NOTOPIC, */ ":%s 331 %s %s :No topic is set.", @@ -402,7 +402,7 @@ static const char * replies[] = { /* 378 RPL_WHOISHOST, */ "%s :is connecting from *@%s %s", /* 379 */ NULL, /* 380 */ NULL, -/* 381 RPL_YOUREOPER, */ ":%s 381 %s :Congratulations! You are now an mIRC warrior.", +/* 381 RPL_YOUREOPER, */ ":%s 381 %s :I can't work under these conditions anymore! The charybdis developers' jokes are just too lame!!! I quit! Really!", /* 382 RPL_REHASHING, */ ":%s 382 %s %s :Rehashing", /* 383 */ NULL, /* 384 RPL_MYPORTIS, */ NULL, diff --git a/src/newconf.c b/src/newconf.c index 92671f393..6fe62dddd 100644 --- a/src/newconf.c +++ b/src/newconf.c @@ -28,6 +28,7 @@ #include "snomask.h" #include "blacklist.h" #include "sslproc.h" +#include "privilege.h" #define CF_TYPE(x) ((x) & CF_MTYPE) @@ -53,6 +54,7 @@ static struct alias_entry *yy_alias = NULL; static char *yy_blacklist_host = NULL; static char *yy_blacklist_reason = NULL; +static char *yy_privset_extends = NULL; static const char * conf_strtype(int type) @@ -306,23 +308,7 @@ static struct mode_table umode_table[] = { static struct mode_table oper_table[] = { {"encrypted", OPER_ENCRYPTED }, - {"local_kill", OPER_LOCKILL }, - {"global_kill", OPER_GLOBKILL|OPER_LOCKILL }, - {"remote", OPER_REMOTE }, - {"kline", OPER_KLINE }, - {"unkline", OPER_UNKLINE }, - {"nick_changes", OPER_NICKS }, - {"rehash", OPER_REHASH }, - {"die", OPER_DIE }, - {"admin", OPER_ADMIN }, - {"hidden_admin", OPER_HADMIN }, - {"xline", OPER_XLINE }, - {"resv", OPER_RESV }, - {"operwall", OPER_OPERWALL }, - {"oper_spy", OPER_SPY }, - {"hidden_oper", OPER_INVIS }, - {"remoteban", OPER_REMOTEBAN }, - {"mass_notice", OPER_MASSNOTICE }, + {"need_ssl", OPER_NEEDSSL }, {NULL, 0} }; @@ -340,6 +326,7 @@ static struct mode_table auth_table[] = { {"no_tilde", CONF_FLAGS_NO_TILDE }, {"need_ident", CONF_FLAGS_NEED_IDENTD }, {"have_ident", CONF_FLAGS_NEED_IDENTD }, + {"need_ssl", CONF_FLAGS_NEED_SSL }, {"need_sasl", CONF_FLAGS_NEED_SASL }, {NULL, 0} }; @@ -448,6 +435,60 @@ set_modes_from_table(int *modes, const char *whatis, struct mode_table *tab, con } } +static void +conf_set_privset_extends(void *data) +{ + yy_privset_extends = rb_strdup((char *) data); +} + +static void +conf_set_privset_privs(void *data) +{ + char *privs = NULL; + conf_parm_t *args = data; + + for (; args; args = args->next) + { + if (privs == NULL) + privs = rb_strdup(args->v.string); + else + { + char *privs_old = privs; + + privs = rb_malloc(strlen(privs_old) + 1 + strlen(args->v.string) + 1); + strcpy(privs, privs_old); + strcat(privs, " "); + strcat(privs, args->v.string); + + rb_free(privs_old); + } + } + + if (privs) + { + if (yy_privset_extends) + { + struct PrivilegeSet *set = privilegeset_get(yy_privset_extends); + + if (!set) + { + conf_report_error("Warning -- unknown parent privilege set %s for %s; assuming defaults", yy_privset_extends, conf_cur_block_name); + + set = privilegeset_get("default"); + } + + privilegeset_extend(set, conf_cur_block_name != NULL ? conf_cur_block_name : "", privs, 0); + + rb_free(yy_privset_extends); + yy_privset_extends = NULL; + } + else + privilegeset_set_new(conf_cur_block_name != NULL ? conf_cur_block_name : "", privs, 0); + + rb_free(privs); + } +} + static int conf_begin_oper(struct TopConf *tc) { @@ -467,7 +508,7 @@ conf_begin_oper(struct TopConf *tc) } yy_oper = make_oper_conf(); - yy_oper->flags |= OPER_ENCRYPTED|OPER_RESV|OPER_OPERWALL|OPER_REMOTEBAN|OPER_MASSNOTICE; + yy_oper->flags |= OPER_ENCRYPTED; return 0; } @@ -504,6 +545,10 @@ conf_end_oper(struct TopConf *tc) return 0; } + + if (!yy_oper->privset) + yy_oper->privset = privilegeset_get("default"); + /* now, yy_oper_list contains a stack of oper_conf's with just user * and host in, yy_oper contains the rest of the information which * we need to copy into each element in yy_oper_list @@ -521,6 +566,7 @@ conf_end_oper(struct TopConf *tc) yy_tmpoper->flags = yy_oper->flags; yy_tmpoper->umodes = yy_oper->umodes; yy_tmpoper->snomask = yy_oper->snomask; + yy_tmpoper->privset = yy_oper->privset; #ifdef HAVE_LIBCRYPTO if(yy_oper->rsa_pubkey_file) @@ -569,6 +615,12 @@ conf_set_oper_flags(void *data) set_modes_from_table(&yy_oper->flags, "flag", oper_table, args); } +static void +conf_set_oper_privset(void *data) +{ + yy_oper->privset = privilegeset_get((char *) data); +} + static void conf_set_oper_user(void *data) { @@ -1967,12 +2019,20 @@ static struct ConfEntry conf_operator_table[] = { "rsa_public_key_file", CF_QSTRING, conf_set_oper_rsa_public_key_file, 0, NULL }, { "flags", CF_STRING | CF_FLIST, conf_set_oper_flags, 0, NULL }, { "umodes", CF_STRING | CF_FLIST, conf_set_oper_umodes, 0, NULL }, + { "privset", CF_QSTRING, conf_set_oper_privset, 0, NULL }, { "snomask", CF_QSTRING, conf_set_oper_snomask, 0, NULL }, { "user", CF_QSTRING, conf_set_oper_user, 0, NULL }, { "password", CF_QSTRING, conf_set_oper_password, 0, NULL }, { "\0", 0, NULL, 0, NULL } }; +static struct ConfEntry conf_privset_table[] = +{ + { "extends", CF_QSTRING, conf_set_privset_extends, 0, NULL }, + { "privs", CF_STRING | CF_FLIST, conf_set_privset_privs, 0, NULL }, + { "\0", 0, NULL, 0, NULL } +}; + static struct ConfEntry conf_class_table[] = { { "ping_time", CF_TIME, conf_set_class_ping_time, 0, NULL }, @@ -2035,7 +2095,6 @@ static struct ConfEntry conf_general_table[] = { "kline_reason", CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.kline_reason }, { "identify_service", CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.identifyservice }, { "identify_command", CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.identifycommand }, - { "servlink_path", CF_QSTRING, NULL, MAXPATHLEN, &ConfigFileEntry.servlink_path }, { "anti_spam_exit_message_time", CF_TIME, NULL, 0, &ConfigFileEntry.anti_spam_exit_message_time }, { "disable_fake_channels", CF_YESNO, NULL, 0, &ConfigFileEntry.disable_fake_channels }, @@ -2064,7 +2123,6 @@ static struct ConfEntry conf_general_table[] = { "max_nick_time", CF_TIME, NULL, 0, &ConfigFileEntry.max_nick_time }, { "max_nick_changes", CF_INT, NULL, 0, &ConfigFileEntry.max_nick_changes }, { "max_targets", CF_INT, NULL, 0, &ConfigFileEntry.max_targets }, - { "max_unknown_ip", CF_INT, NULL, 0, &ConfigFileEntry.max_unknown_ip }, { "min_nonwildcard", CF_INT, NULL, 0, &ConfigFileEntry.min_nonwildcard }, { "nick_delay", CF_TIME, NULL, 0, &ConfigFileEntry.nick_delay }, { "no_oper_flood", CF_YESNO, NULL, 0, &ConfigFileEntry.no_oper_flood }, @@ -2076,6 +2134,8 @@ static struct ConfEntry conf_general_table[] = { "reject_after_count", CF_INT, NULL, 0, &ConfigFileEntry.reject_after_count }, { "reject_ban_time", CF_TIME, NULL, 0, &ConfigFileEntry.reject_ban_time }, { "reject_duration", CF_TIME, NULL, 0, &ConfigFileEntry.reject_duration }, + { "throttle_count", CF_INT, NULL, 0, &ConfigFileEntry.throttle_count }, + { "throttle_duration", CF_TIME, NULL, 0, &ConfigFileEntry.throttle_duration }, { "short_motd", CF_YESNO, NULL, 0, &ConfigFileEntry.short_motd }, { "stats_c_oper_only", CF_YESNO, NULL, 0, &ConfigFileEntry.stats_c_oper_only }, { "stats_e_disabled", CF_YESNO, NULL, 0, &ConfigFileEntry.stats_e_disabled }, @@ -2134,6 +2194,7 @@ newconf_init() add_top_conf("log", NULL, NULL, conf_log_table); add_top_conf("operator", conf_begin_oper, conf_end_oper, conf_operator_table); add_top_conf("class", conf_begin_class, conf_end_class, conf_class_table); + add_top_conf("privset", NULL, NULL, conf_privset_table); add_top_conf("listen", conf_begin_listen, conf_end_listen, NULL); add_conf_item("listen", "port", CF_INT | CF_FLIST, conf_set_listen_port); diff --git a/src/parse.c b/src/parse.c index 970ad7f63..5fe0585dc 100644 --- a/src/parse.c +++ b/src/parse.c @@ -364,7 +364,7 @@ handle_command(struct Message *mptr, struct Client *client_p, ilog(L_SERVER, "Insufficient parameters (%d < %d) for command '%s' from %s.", i, ehandler.min_para, mptr->cmd, client_p->name); - snprintf(squitreason, sizeof squitreason, + rb_snprintf(squitreason, sizeof squitreason, "Insufficient parameters (%d < %d) for command '%s'", i, ehandler.min_para, mptr->cmd); exit_client(client_p, client_p, client_p, squitreason); diff --git a/src/privilege.c b/src/privilege.c new file mode 100644 index 000000000..060cf4895 --- /dev/null +++ b/src/privilege.c @@ -0,0 +1,121 @@ +/* + * charybdis: an advanced ircd. + * privilege.c: Dynamic privileges API. + * + * Copyright (c) 2008 William Pitcock + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "privilege.h" + +static rb_dlink_list privilegeset_list = {}; + +int +privilegeset_in_set(struct PrivilegeSet *set, const char *priv) +{ + s_assert(set != NULL); + s_assert(priv != NULL); + + return strstr(set->privs, priv) != NULL; +} + +struct PrivilegeSet * +privilegeset_set_new(const char *name, const char *privs, PrivilegeFlags flags) +{ + struct PrivilegeSet *set; + + s_assert(privilegeset_get(name) == NULL); + + set = rb_malloc(sizeof(struct PrivilegeSet)); + set->refs = 1; + set->name = rb_strdup(name); + set->privs = rb_strdup(privs); + set->flags = flags; + + rb_dlinkAdd(set, &set->node, &privilegeset_list); + + return set; +} + +struct PrivilegeSet * +privilegeset_extend(struct PrivilegeSet *parent, const char *name, const char *privs, PrivilegeFlags flags) +{ + struct PrivilegeSet *set; + + s_assert(parent != NULL); + s_assert(name != NULL); + s_assert(privs != NULL); + s_assert(privilegeset_get(name) == NULL); + + set = rb_malloc(sizeof(struct PrivilegeSet)); + set->refs = 1; + set->name = rb_strdup(name); + set->flags = flags; + set->privs = rb_malloc(strlen(parent->privs) + 1 + strlen(privs) + 1); + strcpy(set->privs, parent->privs); + strcat(set->privs, " "); + strcat(set->privs, privs); + + rb_dlinkAdd(set, &set->node, &privilegeset_list); + + return set; +} + +struct PrivilegeSet * +privilegeset_get(const char *name) +{ + rb_dlink_node *iter; + + s_assert(name != NULL); + + RB_DLINK_FOREACH(iter, privilegeset_list.head) + { + struct PrivilegeSet *set = (struct PrivilegeSet *) iter->data; + + if (!strcasecmp(set->name, name)) + return set; + } + + return NULL; +} + +struct PrivilegeSet * +privilegeset_ref(struct PrivilegeSet *set) +{ + s_assert(set != NULL); + + set->refs++; + + return set; +} + +void +privilegeset_unref(struct PrivilegeSet *set) +{ + s_assert(set != NULL); + + if (--set->refs == 0) + { + rb_dlinkDelete(&set->node, &privilegeset_list); + + rb_free(set->name); + rb_free(set->privs); + rb_free(set); + } +} diff --git a/src/reject.c b/src/reject.c index d2422a4c7..b5035c656 100644 --- a/src/reject.c +++ b/src/reject.c @@ -17,70 +17,78 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA * - * $Id: reject.c 3456 2007-05-18 19:14:18Z jilles $ + * $Id: reject.c 25119 2008-03-13 16:57:05Z androsyn $ */ #include "stdinc.h" -#include "config.h" #include "client.h" #include "s_conf.h" #include "reject.h" #include "s_stats.h" -#include "msg.h" +#include "ircd.h" +#include "send.h" +#include "numeric.h" +#include "parse.h" +#include "hostmask.h" +#include "match.h" #include "hash.h" static rb_patricia_tree_t *reject_tree; -rb_dlink_list delay_exit; +static rb_dlink_list delay_exit; static rb_dlink_list reject_list; +static rb_dlink_list throttle_list; +static rb_patricia_tree_t *throttle_tree; +static void throttle_expires(void *unused); -static rb_patricia_tree_t *unknown_tree; -struct reject_data +typedef struct _reject_data { rb_dlink_node rnode; time_t time; unsigned int count; uint32_t mask_hashv; -}; +} reject_t; + +typedef struct _delay_data +{ + rb_dlink_node node; + rb_fde_t *F; +} delay_t; + +typedef struct _throttle +{ + rb_dlink_node node; + time_t last; + int count; +} throttle_t; + +unsigned long +delay_exit_length(void) +{ + return rb_dlink_list_length(&delay_exit); +} static void reject_exit(void *unused) { - struct Client *client_p; rb_dlink_node *ptr, *ptr_next; - + delay_t *ddata; + static const char *errbuf = "ERROR :Closing Link: (*** Banned (cache))\r\n"; + RB_DLINK_FOREACH_SAFE(ptr, ptr_next, delay_exit.head) { - client_p = ptr->data; - if(IsDead(client_p)) - continue; + ddata = ptr->data; - /* this MUST be here, to prevent the possibility - * sendto_one() generates a write error, and then a client - * ends up on the dead_list and the abort_list --fl - * - * new disconnect notice stolen from ircu --nenolod - * no, this only happens when someone's IP has some - * ban on it and rejects them rather longer than the - * ircu message suggests --jilles - */ - if(!IsIOError(client_p)) - { - if(IsExUnknown(client_p)) - sendto_one(client_p, "ERROR :Closing Link: %s (*** Too many unknown connections)", client_p->host); - else - sendto_one(client_p, "ERROR :Closing Link: %s (*** Banned (cache))", client_p->host); - } - close_connection(client_p); - SetDead(client_p); - rb_dlinkAddAlloc(client_p, &dead_list); + rb_write(ddata->F, errbuf, strlen(errbuf)); + rb_close(ddata->F); + rb_free(ddata); } - delay_exit.head = delay_exit.tail = NULL; - delay_exit.length = 0; + delay_exit.head = delay_exit.tail = NULL; + delay_exit.length = 0; } static void @@ -88,7 +96,7 @@ reject_expires(void *unused) { rb_dlink_node *ptr, *next; rb_patricia_node_t *pnode; - struct reject_data *rdata; + reject_t *rdata; RB_DLINK_FOREACH_SAFE(ptr, next, reject_list.head) { @@ -108,9 +116,10 @@ void init_reject(void) { reject_tree = rb_new_patricia(PATRICIA_BITS); - unknown_tree = rb_new_patricia(PATRICIA_BITS); + throttle_tree = rb_new_patricia(PATRICIA_BITS); rb_event_add("reject_exit", reject_exit, NULL, DELAYED_EXIT_TIME); rb_event_add("reject_expires", reject_expires, NULL, 60); + rb_event_add("throttle_expires", throttle_expires, NULL, 10); } @@ -118,18 +127,18 @@ void add_reject(struct Client *client_p, const char *mask1, const char *mask2) { rb_patricia_node_t *pnode; - struct reject_data *rdata; + reject_t *rdata; uint32_t hashv; /* Reject is disabled */ - if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_ban_time == 0) + if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0) return; hashv = 0; if (mask1 != NULL) - hashv ^= fnv_hash_upper(mask1, 32); + hashv ^= fnv_hash_upper((const unsigned char *)mask1, 32); if (mask2 != NULL) - hashv ^= fnv_hash_upper(mask2, 32); + hashv ^= fnv_hash_upper((const unsigned char *)mask2, 32); if((pnode = rb_match_ip(reject_tree, (struct sockaddr *)&client_p->localClient->ip)) != NULL) { @@ -141,11 +150,11 @@ add_reject(struct Client *client_p, const char *mask1, const char *mask2) { int bitlen = 32; #ifdef RB_IPV6 - if(client_p->localClient->ip.ss_family == AF_INET6) + if(GET_SS_FAMILY(&client_p->localClient->ip) == AF_INET6) bitlen = 128; #endif pnode = make_and_lookup_ip(reject_tree, (struct sockaddr *)&client_p->localClient->ip, bitlen); - pnode->data = rdata = rb_malloc(sizeof(struct reject_data)); + pnode->data = rdata = rb_malloc(sizeof(reject_t)); rb_dlinkAddTail(pnode, &rdata->rnode, &reject_list); rdata->time = rb_current_time(); rdata->count = 1; @@ -154,29 +163,28 @@ add_reject(struct Client *client_p, const char *mask1, const char *mask2) } int -check_reject(struct Client *client_p) +check_reject(rb_fde_t *F, struct sockaddr *addr) { rb_patricia_node_t *pnode; - struct reject_data *rdata; - + reject_t *rdata; + delay_t *ddata; /* Reject is disabled */ - if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_ban_time == 0 || - ConfigFileEntry.reject_duration == 0) + if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0) return 0; - pnode = rb_match_ip(reject_tree, (struct sockaddr *)&client_p->localClient->ip); + pnode = rb_match_ip(reject_tree, addr); if(pnode != NULL) { rdata = pnode->data; rdata->time = rb_current_time(); - if(rdata->count > ConfigFileEntry.reject_after_count) + if(rdata->count > (unsigned long)ConfigFileEntry.reject_after_count) { + ddata = rb_malloc(sizeof(delay_t)); ServerStats.is_rej++; - SetReject(client_p); - rb_setselect(client_p->localClient->F, RB_SELECT_WRITE | RB_SELECT_READ, NULL, NULL); - SetClosing(client_p); - rb_dlinkMoveNode(&client_p->localClient->tnode, &unknown_list, &delay_exit); + rb_setselect(F, RB_SELECT_WRITE | RB_SELECT_READ, NULL, NULL); + ddata->F = F; + rb_dlinkAdd(ddata, &ddata->node, &delay_exit); return 1; } } @@ -189,7 +197,7 @@ flush_reject(void) { rb_dlink_node *ptr, *next; rb_patricia_node_t *pnode; - struct reject_data *rdata; + reject_t *rdata; RB_DLINK_FOREACH_SAFE(ptr, next, reject_list.head) { @@ -207,13 +215,12 @@ remove_reject_ip(const char *ip) rb_patricia_node_t *pnode; /* Reject is disabled */ - if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_ban_time == 0 || - ConfigFileEntry.reject_duration == 0) + if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0) return -1; if((pnode = rb_match_string(reject_tree, ip)) != NULL) { - struct reject_data *rdata = pnode->data; + reject_t *rdata = pnode->data; rb_dlinkDelete(&rdata->rnode, &reject_list); rb_free(rdata); rb_patricia_remove(reject_tree, pnode); @@ -227,15 +234,15 @@ remove_reject_mask(const char *mask1, const char *mask2) { rb_dlink_node *ptr, *next; rb_patricia_node_t *pnode; - struct reject_data *rdata; + reject_t *rdata; uint32_t hashv; int n = 0; hashv = 0; if (mask1 != NULL) - hashv ^= fnv_hash_upper(mask1, 32); + hashv ^= fnv_hash_upper((const unsigned char *)mask1, 32); if (mask2 != NULL) - hashv ^= fnv_hash_upper(mask2, 32); + hashv ^= fnv_hash_upper((const unsigned char *)mask2, 32); RB_DLINK_FOREACH_SAFE(ptr, next, reject_list.head) { pnode = ptr->data; @@ -251,50 +258,57 @@ remove_reject_mask(const char *mask1, const char *mask2) return n; } - int -add_unknown_ip(struct Client *client_p) +throttle_add(struct sockaddr *addr) { + throttle_t *t; rb_patricia_node_t *pnode; - if((pnode = rb_match_ip(unknown_tree, (struct sockaddr *)&client_p->localClient->ip)) == NULL) + if((pnode = rb_match_ip(throttle_tree, addr)) != NULL) { + t = pnode->data; + + if(t->count > ConfigFileEntry.throttle_count) + return 1; + + /* Stop penalizing them after they've been throttled */ + t->last = rb_current_time(); + t->count++; + + } else { int bitlen = 32; #ifdef RB_IPV6 - if(client_p->localClient->ip.ss_family == AF_INET6) + if(GET_SS_FAMILY(addr) == AF_INET6) bitlen = 128; #endif - pnode = make_and_lookup_ip(unknown_tree, (struct sockaddr *)&client_p->localClient->ip, bitlen); - pnode->data = (void *)0; - } - - if((unsigned long)pnode->data >= ConfigFileEntry.max_unknown_ip) - { - SetExUnknown(client_p); - SetReject(client_p); - rb_setselect(client_p->localClient->F, RB_SELECT_WRITE | RB_SELECT_READ, NULL, NULL); - SetClosing(client_p); - rb_dlinkMoveNode(&client_p->localClient->tnode, &unknown_list, &delay_exit); - return 1; - } - - pnode->data = (void *)((unsigned long)pnode->data + 1); - + t = rb_malloc(sizeof(throttle_t)); + t->last = rb_current_time(); + t->count = 1; + pnode = make_and_lookup_ip(throttle_tree, addr, bitlen); + pnode->data = t; + rb_dlinkAdd(pnode, &t->node, &throttle_list); + } return 0; } -void -del_unknown_ip(struct Client *client_p) +static void +throttle_expires(void *unused) { + rb_dlink_node *ptr, *next; rb_patricia_node_t *pnode; - - if((pnode = rb_match_ip(unknown_tree, (struct sockaddr *)&client_p->localClient->ip)) != NULL) + throttle_t *t; + + RB_DLINK_FOREACH_SAFE(ptr, next, throttle_list.head) { - pnode->data = (void *)((unsigned long)pnode->data - 1); - if((unsigned long)pnode->data <= 0) - { - rb_patricia_remove(unknown_tree, pnode); - } + pnode = ptr->data; + t = pnode->data; + + if(t->last + ConfigFileEntry.throttle_duration > rb_current_time()) + continue; + + rb_dlinkDelete(ptr, &throttle_list); + rb_free(t); + rb_patricia_remove(throttle_tree, pnode); } - /* this can happen due to m_webirc.c's manipulations, for example */ } + diff --git a/src/s_auth.c b/src/s_auth.c index 83407b37b..a6143bb11 100644 --- a/src/s_auth.c +++ b/src/s_auth.c @@ -297,7 +297,6 @@ static int start_auth_query(struct AuthRequest *auth) { struct rb_sockaddr_storage localaddr, destaddr; - socklen_t locallen = sizeof(struct rb_sockaddr_storage); rb_fde_t *F; int family; @@ -333,14 +332,7 @@ start_auth_query(struct AuthRequest *auth) * since the ident request must originate from that same address-- * and machines with multiple IP addresses are common now */ - memset(&localaddr, 0, locallen); - if(getsockname(rb_get_fd(auth->client->localClient->F), - (struct sockaddr *) &localaddr, &locallen) == -1) - { - /* can happen if connection was just closed */ - rb_close(F); - return 0; - } + localaddr = auth->client->preClient->lip; /* XXX mangle_mapped_sockaddr((struct sockaddr *)&localaddr); */ #ifdef RB_IPV6 diff --git a/src/s_conf.c b/src/s_conf.c index f27c6aba9..11f6f2a9e 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -772,7 +772,6 @@ set_default_conf(void) ConfigFileEntry.hide_error_messages = 1; ConfigFileEntry.dots_in_ident = 0; ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT; - ConfigFileEntry.servlink_path = rb_strdup(SLPATH); ConfigFileEntry.egdpool_path = NULL; ConfigFileEntry.use_whois_actually = YES; ConfigFileEntry.burst_away = NO; @@ -820,7 +819,8 @@ set_default_conf(void) ConfigFileEntry.reject_after_count = 5; ConfigFileEntry.reject_ban_time = 300; ConfigFileEntry.reject_duration = 120; - ConfigFileEntry.max_unknown_ip = 2; + ConfigFileEntry.throttle_count = 4; + ConfigFileEntry.throttle_duration = 60; ServerInfo.default_max_clients = MAXCONNECTIONS; } @@ -857,9 +857,6 @@ validate_conf(void) if(ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN) ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT; - if(ConfigFileEntry.servlink_path == NULL) - ConfigFileEntry.servlink_path = rb_strdup(SLPATH); - if(ServerInfo.network_name == NULL) ServerInfo.network_name = rb_strdup(NETWORK_NAME_DEFAULT); @@ -1234,8 +1231,8 @@ clear_out_old_conf(void) */ /* clean out general */ - rb_free(ConfigFileEntry.servlink_path); - ConfigFileEntry.servlink_path = NULL; + rb_free(ConfigFileEntry.kline_reason); + ConfigFileEntry.kline_reason = NULL; RB_DLINK_FOREACH_SAFE(ptr, next_ptr, service_list.head) { diff --git a/src/s_newconf.c b/src/s_newconf.c index af8110100..93f589684 100644 --- a/src/s_newconf.c +++ b/src/s_newconf.c @@ -318,55 +318,6 @@ find_oper_conf(const char *username, const char *host, const char *locip, const return NULL; } -struct oper_flags -{ - int flag; - const char *name; -}; -static struct oper_flags oper_flagtable[] = -{ - { OPER_KLINE, "kline" }, - { OPER_XLINE, "xline" }, - { OPER_RESV, "resv" }, - { OPER_GLOBKILL, "global_kill" }, - { OPER_LOCKILL, "local_kill" }, - { OPER_REMOTE, "remote" }, - { OPER_UNKLINE, "unkline" }, - { OPER_REHASH, "rehash" }, - { OPER_DIE, "die" }, - { OPER_ADMIN, "admin" }, - { OPER_HADMIN, "hidden_admin" }, - { OPER_NICKS, "nick_changes" }, - { OPER_OPERWALL, "operwall" }, - { OPER_SPY, "spy" }, - { OPER_INVIS, "hidden_oper" }, - { OPER_REMOTEBAN, "remoteban" }, - { OPER_MASSNOTICE, "mass_notice" }, - { 0, NULL } -}; - -const char * -get_oper_privs(int flags) -{ - static char buf[BUFSIZE]; - char *p; - int i; - - p = buf; - *p = '\0'; - - for(i = 0; oper_flagtable[i].flag; i++) - if (flags & oper_flagtable[i].flag) - { - if(*buf != '\0') - rb_strlcat(buf, ", ", sizeof(buf)); - - rb_strlcat(buf, oper_flagtable[i].name, sizeof(buf)); - } - - return buf; -} - struct server_conf * make_server_conf(void) { diff --git a/src/s_serv.c b/src/s_serv.c index daff36c78..e29fdba03 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -760,7 +760,6 @@ server_estab(struct Client *client_p) set_chcap_usage_counts(client_p); rb_dlinkAdd(client_p, &client_p->lnode, &me.serv->servers); - del_unknown_ip(client_p); rb_dlinkMoveNode(&client_p->localClient->tnode, &unknown_list, &serv_list); rb_dlinkAddTailAlloc(client_p, &global_serv_list); diff --git a/src/s_user.c b/src/s_user.c index 6407c0512..740525605 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -314,6 +314,14 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char return (CLIENT_EXITED); } + if(IsConfSSLNeeded(aconf) && !IsSSL(source_p)) + { + ServerStats.is_ref++; + sendto_one_notice(source_p, ":*** Notice -- You need to use SSL/TLS to use this server"); + exit_client(client_p, source_p, &me, "Use SSL/TLS"); + return (CLIENT_EXITED); + } + if(!IsGotId(source_p)) { const char *p; @@ -527,7 +535,6 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char Count.invisi++; s_assert(!IsClient(source_p)); - del_unknown_ip(source_p); rb_dlinkMoveNode(&source_p->localClient->tnode, &unknown_list, &lclient_list); SetClient(source_p); @@ -650,11 +657,21 @@ introduce_client(struct Client *client_p, struct Client *source_p, struct User * else identifyservice_p = NULL; if (identifyservice_p != NULL) - sendto_one(identifyservice_p, ":%s PRIVMSG %s :%s %s", - get_id(source_p, identifyservice_p), - ConfigFileEntry.identifyservice, - ConfigFileEntry.identifycommand, - source_p->localClient->passwd); + { + if (!EmptyString(source_p->localClient->auth_user)) + sendto_one(identifyservice_p, ":%s PRIVMSG %s :%s %s %s", + get_id(source_p, identifyservice_p), + ConfigFileEntry.identifyservice, + ConfigFileEntry.identifycommand, + source_p->localClient->auth_user, + source_p->localClient->passwd); + else + sendto_one(identifyservice_p, ":%s PRIVMSG %s :%s %s", + get_id(source_p, identifyservice_p), + ConfigFileEntry.identifyservice, + ConfigFileEntry.identifycommand, + source_p->localClient->passwd); + } } memset(source_p->localClient->passwd, 0, strlen(source_p->localClient->passwd)); rb_free(source_p->localClient->passwd); @@ -966,6 +983,8 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char source_p->localClient->opername = NULL; rb_dlinkFindDestroy(source_p, &local_oper_list); + privilegeset_unref(source_p->localClient->privset); + source_p->localClient->privset = NULL; } rb_dlinkFindDestroy(source_p, &oper_list); @@ -1251,6 +1270,7 @@ oper_up(struct Client *source_p, struct oper_conf *oper_p) source_p->flags2 |= oper_p->flags; source_p->localClient->opername = rb_strdup(oper_p->name); + source_p->localClient->privset = privilegeset_ref(oper_p->privset); rb_dlinkAddAlloc(source_p, &local_oper_list); rb_dlinkAddAlloc(source_p, &oper_list); @@ -1277,7 +1297,8 @@ oper_up(struct Client *source_p, struct oper_conf *oper_p) sendto_one_numeric(source_p, RPL_SNOMASK, form_str(RPL_SNOMASK), construct_snobuf(source_p->snomask)); sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, source_p->name); - sendto_one_notice(source_p, ":*** Oper privs are %s", get_oper_privs(oper_p->flags)); + sendto_one_notice(source_p, ":*** Oper privilege set is %s", oper_p->privset->name); + sendto_one_notice(source_p, ":*** Oper privs are %s", oper_p->privset->privs); send_oper_motd(source_p); return (1); diff --git a/src/sslproc.c b/src/sslproc.c index 5c2b46630..4f9af8bb3 100644 --- a/src/sslproc.c +++ b/src/sslproc.c @@ -234,7 +234,7 @@ start_ssldaemon(int count, const char *ssl_cert, const char *ssl_private_key, co if(ssld_spin_count > 20 && (rb_current_time() - last_spin < 5)) { - ilog(L_MAIN, "ssld helper is spinning - will attempt to restart in 5 minutes"); + ilog(L_MAIN, "ssld helper is spinning - will attempt to restart in 1 minute"); sendto_realops_snomask(SNO_GENERAL, L_ALL, "ssld helper is spinning - will attempt to restart in 1 minute"); rb_event_add("restart_ssld_event", restart_ssld_event, NULL, 60); ssld_wait = 1; diff --git a/src/supported.c b/src/supported.c index e0f617e49..e788ad5e6 100644 --- a/src/supported.c +++ b/src/supported.c @@ -111,6 +111,32 @@ add_isupport(const char *name, const char *(*func)(const void *), const void *pa rb_dlinkAddTail(item, &item->node, &isupportlist); } +const void * +change_isupport(const char *name, const char *(*func)(const void *), const void *param) +{ + rb_dlink_node *ptr; + struct isupportitem *item; + void *oldvalue; + + RB_DLINK_FOREACH(ptr, isupportlist.head) + { + item = ptr->data; + + if (!strcmp(item->name, name)) + { + oldvalue = item->param; + + // item->name = name; + item->func = func; + item->param = param; + + break; + } + } + + return oldvalue; +} + void delete_isupport(const char *name) { diff --git a/src/version.c.SH b/src/version.c.SH index 769daf83e..59a5ee820 100644 --- a/src/version.c.SH +++ b/src/version.c.SH @@ -19,7 +19,7 @@ generation=`expr $generation + 1` uname=`uname -a` -creation=`date | \ +creation=`LC_ALL=C date | \ awk '{if (NF == 6) \ { print $1 " " $2 " " $3 " " $6 " at " $4 " " $5 } \ else \ diff --git a/ssld/ssld.c b/ssld/ssld.c index 58e1bd0f9..83ba7655e 100644 --- a/ssld/ssld.c +++ b/ssld/ssld.c @@ -1076,7 +1076,6 @@ main(int argc, char **argv) close(x); } -#if 0 x = open("/dev/null", O_RDWR); if(x >= 0) { @@ -1089,7 +1088,7 @@ main(int argc, char **argv) if(x > 2) close(x); } -#endif + setup_signals(); rb_lib_init(NULL, NULL, NULL, 0, maxfd, 1024, 4096); rb_init_rawbuffers(1024); diff --git a/testsuite/ircd.conf.1 b/testsuite/ircd.conf.1 new file mode 100644 index 000000000..a91ecd1e0 --- /dev/null +++ b/testsuite/ircd.conf.1 @@ -0,0 +1,92 @@ +loadmodule "extensions/extb_account.so"; +loadmodule "extensions/extb_channel.so"; +loadmodule "extensions/extb_oper.so"; +loadmodule "extensions/extb_realname.so"; +loadmodule "extensions/extb_server.so"; +#loadmodule "extensions/ip_cloaking.so"; +loadmodule "extensions/sno_farconnect.so"; +loadmodule "extensions/sno_globalkline.so"; +#loadmodule "extensions/sno_globaloper.so"; + +serverinfo { + name = "testsuite1."; + sid = "1TT"; + description = "Testsuite"; + network_name = "Testsuite"; + network_desc = "Testing"; + hub = yes; + vhost = "127.0.0.1"; +}; + +admin { + name = "Here"; + description = "Charybdis testsuite server"; + email = "root@localhost"; +}; + +class "users" { + ping_time = 5 minutes; + number_per_ip = 100; + max_number = 200; + sendq = 100kb; +}; + +class "server" { + ping_time = 5 minutes; + connectfreq = 5 minutes; + max_number = 3; + sendq = 5 megabytes; +}; + +listen { host = "127.0.0.1"; port = 7601; }; + +auth { user = "*@127.0.0.0/8"; class = "users"; }; + +operator "oper" { + user = "*@127.0.0.0/8"; + password = "oper"; + flags = global_kill, remote, kline, unkline, nick_changes, + die, rehash, admin, xline, operwall, oper_spy, ~encrypted; +}; + +connect "testsuite2." { + host = "127.0.0.1"; + port = 7602; + send_password = "testsuite"; + accept_password = "testsuite"; + hub_mask = "*"; + class = "server"; + flags = topicburst; +}; + +connect "testsuite3." { + host = "127.0.0.1"; + port = 7603; + send_password = "testsuite"; + accept_password = "testsuite"; + hub_mask = "*"; + class = "server"; + flags = topicburst; +}; + +shared { + oper = "*@*", "*"; + flags = all; +}; + +alias "NickServ" { + target = "NickServ"; +}; +alias "ChanServ" { + target = "ChanServ"; +}; +alias "OperServ" { + target = "OperServ"; +}; +alias "MemoServ" { + target = "MemoServ"; +}; + +service { + name = "services."; +}; diff --git a/testsuite/ircd.conf.2 b/testsuite/ircd.conf.2 new file mode 100644 index 000000000..184f0524e --- /dev/null +++ b/testsuite/ircd.conf.2 @@ -0,0 +1,92 @@ +loadmodule "extensions/extb_account.so"; +loadmodule "extensions/extb_channel.so"; +loadmodule "extensions/extb_oper.so"; +loadmodule "extensions/extb_realname.so"; +loadmodule "extensions/extb_server.so"; +#loadmodule "extensions/ip_cloaking.so"; +loadmodule "extensions/sno_farconnect.so"; +loadmodule "extensions/sno_globalkline.so"; +#loadmodule "extensions/sno_globaloper.so"; + +serverinfo { + name = "testsuite2."; + sid = "2TT"; + description = "Testsuite"; + network_name = "Testsuite"; + network_desc = "Testing"; + hub = yes; + vhost = "127.0.0.1"; +}; + +admin { + name = "Here"; + description = "Charybdis testsuite server"; + email = "root@localhost"; +}; + +class "users" { + ping_time = 5 minutes; + number_per_ip = 100; + max_number = 200; + sendq = 100kb; +}; + +class "server" { + ping_time = 5 minutes; + connectfreq = 5 minutes; + max_number = 3; + sendq = 5 megabytes; +}; + +listen { host = "127.0.0.1"; port = 7602; }; + +auth { user = "*@127.0.0.0/8"; class = "users"; }; + +operator "oper" { + user = "*@127.0.0.0/8"; + password = "oper"; + flags = global_kill, remote, kline, unkline, nick_changes, + die, rehash, admin, xline, operwall, oper_spy, ~encrypted; +}; + +connect "testsuite1." { + host = "127.0.0.1"; + port = 7601; + send_password = "testsuite"; + accept_password = "testsuite"; + hub_mask = "*"; + class = "server"; + flags = topicburst; +}; + +connect "testsuite3." { + host = "127.0.0.1"; + port = 7603; + send_password = "testsuite"; + accept_password = "testsuite"; + hub_mask = "*"; + class = "server"; + flags = topicburst; +}; + +shared { + oper = "*@*", "*"; + flags = all; +}; + +alias "NickServ" { + target = "NickServ"; +}; +alias "ChanServ" { + target = "ChanServ"; +}; +alias "OperServ" { + target = "OperServ"; +}; +alias "MemoServ" { + target = "MemoServ"; +}; + +service { + name = "services."; +}; diff --git a/testsuite/ircd.conf.3 b/testsuite/ircd.conf.3 new file mode 100644 index 000000000..cb8f379c6 --- /dev/null +++ b/testsuite/ircd.conf.3 @@ -0,0 +1,92 @@ +loadmodule "extensions/extb_account.so"; +loadmodule "extensions/extb_channel.so"; +loadmodule "extensions/extb_oper.so"; +loadmodule "extensions/extb_realname.so"; +loadmodule "extensions/extb_server.so"; +#loadmodule "extensions/ip_cloaking.so"; +loadmodule "extensions/sno_farconnect.so"; +loadmodule "extensions/sno_globalkline.so"; +#loadmodule "extensions/sno_globaloper.so"; + +serverinfo { + name = "testsuite3."; + sid = "3TT"; + description = "Testsuite"; + network_name = "Testsuite"; + network_desc = "Testing"; + hub = yes; + vhost = "127.0.0.1"; +}; + +admin { + name = "Here"; + description = "Charybdis testsuite server"; + email = "root@localhost"; +}; + +class "users" { + ping_time = 5 minutes; + number_per_ip = 100; + max_number = 200; + sendq = 100kb; +}; + +class "server" { + ping_time = 5 minutes; + connectfreq = 5 minutes; + max_number = 3; + sendq = 5 megabytes; +}; + +listen { host = "127.0.0.1"; port = 7603; }; + +auth { user = "*@127.0.0.0/8"; class = "users"; }; + +operator "oper" { + user = "*@127.0.0.0/8"; + password = "oper"; + flags = global_kill, remote, kline, unkline, nick_changes, + die, rehash, admin, xline, operwall, oper_spy, ~encrypted; +}; + +connect "testsuite1." { + host = "127.0.0.1"; + port = 7601; + send_password = "testsuite"; + accept_password = "testsuite"; + hub_mask = "*"; + class = "server"; + flags = topicburst; +}; + +connect "testsuite2." { + host = "127.0.0.1"; + port = 7602; + send_password = "testsuite"; + accept_password = "testsuite"; + hub_mask = "*"; + class = "server"; + flags = topicburst; +}; + +shared { + oper = "*@*", "*"; + flags = all; +}; + +alias "NickServ" { + target = "NickServ"; +}; +alias "ChanServ" { + target = "ChanServ"; +}; +alias "OperServ" { + target = "OperServ"; +}; +alias "MemoServ" { + target = "MemoServ"; +}; + +service { + name = "services."; +}; diff --git a/testsuite/startall.sh b/testsuite/startall.sh new file mode 100755 index 000000000..6f00e8c74 --- /dev/null +++ b/testsuite/startall.sh @@ -0,0 +1,8 @@ +#!/bin/sh +testdir=`pwd` +prefix=`sed -n -e 's/^#define IRCD_PREFIX "\(.*\)"/\1/p' "$testdir/../include/setup.h"` +[ -d $prefix ] || { echo Unable to find installation prefix; exit 1; } + +$prefix/bin/ircd -configfile $testdir/ircd.conf.1 -pidfile $testdir/ircd.pid.1 +$prefix/bin/ircd -configfile $testdir/ircd.conf.2 -pidfile $testdir/ircd.pid.2 +$prefix/bin/ircd -configfile $testdir/ircd.conf.3 -pidfile $testdir/ircd.pid.3 diff --git a/tools/genssl.sh b/tools/genssl.sh index a55ae97ae..5e435487d 100755 --- a/tools/genssl.sh +++ b/tools/genssl.sh @@ -1,9 +1,6 @@ #!/bin/sh -echo "Generating certificate request .. " -openssl req -new -nodes -out ../etc/req.pem - echo "Generating self-signed certificate .. " -openssl req -x509 -days 365 -in ../etc/req.pem -key ../etc/rsa.key -out ../etc/cert.pem +openssl req -x509 -nodes -newkey rsa:1024 -keyout ../etc/test.key -out ../etc/test.cert echo "Generating Diffie-Hellman file for secure SSL/TLS negotiation .. " openssl dhparam -out ../etc/dh.pem 1024 @@ -11,8 +8,8 @@ openssl dhparam -out ../etc/dh.pem 1024 echo " Now change these lines in the IRCd config file: - ssl_private_key = "etc/rsa.key"; - ssl_cert = "etc/cert.pem"; + ssl_private_key = "etc/test.key"; + ssl_cert = "etc/test.cert"; ssl_dh_params = "etc/dh.pem"; Enjoy using ssl.