Merge branch 'solanum' into merging-solanum-into-hackint

This commit is contained in:
9pfs 2024-06-06 00:33:19 +00:00
commit c7da812303
Signed by: 9pfs
SSH key fingerprint: SHA256:TOcGxMQCfy4VvRM8AzgXErKXdkAtaTcpGXgYMpyoJoY
540 changed files with 78646 additions and 130219 deletions

82
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,82 @@
name: CI
on:
push:
branches:
- main
paths-ignore:
- 'doc/oper-guide/**'
- 'CREDITS'
- 'LICENSE'
- 'NEWS.md'
- 'README.md'
pull_request:
branches:
- main
paths-ignore:
- 'doc/oper-guide/**'
- 'CREDITS'
- 'LICENSE'
- 'NEWS.md'
- 'README.md'
jobs:
linux:
name: Linux
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
# Debian 10 Buster
- os: ubuntu-20.04
compiler: gcc-8
- os: ubuntu-20.04
compiler: clang-7
# Ubuntu 20.04 Focal
- os: ubuntu-20.04
compiler: gcc-9
- os: ubuntu-20.04
compiler: clang-10
# Debian 11 Bullseye
- os: ubuntu-22.04
compiler: gcc-10
- os: ubuntu-22.04
compiler: clang-11
# Ubuntu 22.04 Jammy
- os: ubuntu-22.04
compiler: gcc-11
- os: ubuntu-22.04
compiler: clang-14
# next
- os: ubuntu-22.04
compiler: gcc-12
env:
CC: ${{ matrix.compiler }}
steps:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
${CC} \
automake \
autoconf \
libtool \
libsqlite3-dev \
libhyperscan-dev \
# EOF
- uses: actions/checkout@v2
- name: autogen.sh
run: bash autogen.sh
- name: configure
run: CFLAGS="-Werror -Wno-unused-value -Wno-unused-parameter" ./configure --enable-assert=hard --enable-warnings
- name: make
run: make -j2
- name: make check
run: make check
- name: make install
run: make install

29
.github/workflows/docs.yaml vendored Normal file
View file

@ -0,0 +1,29 @@
name: Oper Guide
on:
push:
branches:
- main
paths:
- 'doc/oper-guide/**'
pull_request:
branches:
- main
paths:
- 'doc/oper-guide/**'
jobs:
build:
runs-on: ubuntu-18.04
steps:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
python-sphinx \
texinfo \
# EOF
- uses: actions/checkout@v2
- name: Build
run: make -C doc/oper-guide html man info

77
.gitignore vendored
View file

@ -1,6 +1,7 @@
tags
Makefile
*~
*.a
*.o
*.so
*.lo
@ -9,31 +10,71 @@ Makefile
*.log
*.sw?
.deps
.dirstamp
.libs
autom4te.cache
authd/authd
bandb/bandb
bandb/bantool
bandb/solanum-bantool
autom4te.cache
aclocal.m4
compile
confdefs.h
config.guess
config.sub
depcomp
ltmain.sh
missing
config.log
config.status
configure
stamp-h1
libltdl/
librb/configure
librb/compile
librb/depcomp
librb/aclocal.m4
librb/include/librb_config.h
librb/include/librb_config.h.in
librb/include/librb-config.h
librb/include/serno.h
librb/librb.pc
librb/ltmain.sh
librb/missing
librb/libratbox.pc
librb/libtool
librb/src/version.c
librb/src/version.c.last
scripts/*.tar.bz2
scripts/*.tar.gz
include/setup.h
libratbox/include/libratbox_config.h
libratbox/include/librb-config.h
libratbox/include/stamp-h1
libratbox/libratbox.pc
libratbox/libtool
libratbox/src/version.c
libratbox/src/version.c.last
scripts/*.tbz2
scripts/*.tgz
servlink/servlink
src/ircd
src/lex.yy.c
src/version.c
src/version.c.last
src/y.tab.h
src/y.tab.c
include/setup.h.in
ircd/solanum
ircd/ircd_parser.c
ircd/ircd_parser.h
ircd/ircd_lexer.c
ircd/version.c
ircd/version.c.last
ssld/ssld
wsockd/wsockd
testsuite/ircd.pid.*
tools/solanum-mkpasswd
tools/solanum-mkfingerprint
tools/genssl
tools/mkpasswd
tools/viconf
include/serno.h
ircd/solanum
ircd/version.c
ircd/version.c.last
/libtool
Makefile.in
m4/argz.m4
m4/libtool.m4
m4/ltargz.m4
m4/ltdl.m4
m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4
*.dSYM/
*.exe

49
.indent.pro vendored
View file

@ -1,49 +0,0 @@
/* $Id: .indent.pro 238 2005-09-21 05:26:03Z nenolod $ */
/* copy this file to the source dir then run indent file.c */
--gnu-style
/* This is the indent before the brace not inside the block. */
--brace-indent0
/* Indent case: by 2 and braces inside case by 0(then by 0)... */
--case-brace-indentation0
--case-indentation2
--indent-level8
/* Put while() on the brace from do... */
--cuddle-do-while
/* Disable an annoying format... */
--no-space-after-function-call-names
/* Disable an annoying format... */
--dont-break-procedure-type
/* Disable an annoying format... */
--no-space-after-casts
--line-length200
/* typedefs */
-T boolean_t
-T node_t
-T list_t
-T tld_t
-T kline_t
-T EVH
-T sra_t
-T server_t
-T user_t
-T channel_t
-T chanuser_t
-T myuser_t
-T mychan_t
-T chanacs_t
-T CONFIGENTRY
-T CONFIGFILE
-T Block
-T MemBlock
-T BlockHeap

View file

@ -1,9 +1,14 @@
Aaron Sethman <androsyn@ratbox.org> androsyn <devnull@localhost>
Alexander Færøy <ahf@0x90.dk> Alexander F?r?y <ahf@0x90.dk>
Ariadne Conill <ariadne@dereferenced.org> <nenolod@atheme.org>
Ariadne Conill <ariadne@dereferenced.org> <nenolod@dereferenced.org>
Ariadne Conill <ariadne@dereferenced.org> nenolod <devnull@localhost>
Brett Greenham <taros@shadowircd.net> B.Greenham <taros@shadowircd.net>
Chris Mills <chris@chrisam.net> TheChrisAM <chris@chrisam.net>
Chris Mills <chris@chrisam.net> freenode!ChrisAM <chris@chrisam.net>
Elizabeth Jennifer Myers <elizabeth@sporksmoo.net> <elizabeth@sporksirc.net>
Elizabeth Myers <elizabeth@interlinked.me> <elizabeth@sporksirc.net>
Elizabeth Myers <elizabeth@interlinked.me> <elizabeth@sporksmoo.net>
Elizabeth Myers <elizabeth@interlinked.me> <spaz@whotookspaz.org>
Elly Fong-Jones <elly@leptoquark.net> Elly <elly@leptoquark.net>
Jilles Tjoelker <jilles@stack.nl> jilles <devnull@localhost>
Nathan Phillip Brink <binki@gentoo.org> <ohnobinki@ohnopublishing.net>
@ -13,5 +18,5 @@ Valeriy Yatsko <dwr@shadowircd.net> <darkwire@darkwire.ru>
Valeriy Yatsko <dwr@shadowircd.net> <darkwire@ircd-charybdis.ru>
Valeriy Yatsko <dwr@shadowircd.net> <darkwire@sellcenter.ru>
Valeriy Yatsko <dwr@shadowircd.net> <dwr@it-penza.org>
William Pitcock <nenolod@dereferenced.org> <nenolod@atheme.org>
William Pitcock <nenolod@dereferenced.org> nenolod <devnull@localhost>
Christine Dodrill <shadow.h511@gmail.com> <quora@lavabit.com>
Christine Dodrill <shadow.h511@gmail.com> <quorawings@gmail.com>

31
CREDITS
View file

@ -1,3 +1,4 @@
<<<<<<< .merge_file_qEvahK
Charybdis started as an evolution from ircd-ratbox. Its development
is led by a team of dedicated developers who have put a lot of time
into the project, and it has seen use on a variety of different
@ -38,3 +39,33 @@ w00t, Robin Burchell <surreal.w00t -at- gmail.com>
Visit the Charybdis website at: http://www.charybdis.io/
Visit us on IRC at: irc.charybdis.io #charybdis
=======
Solanum is based on Charybdis, which was based on ircd-ratbox.
Development is led by a group of representatives from Libera Chat
and OFTC:
amdj, Aaron Jones <amdj@libera.chat>
dwfreed, Doug Freed <dwfreed@mtu.edu>
ilbelkyr, Nicole Kleinhoff <ilbelkyr@libera.chat>
mcintosh, Richie McIntosh <richiemcintosh@gmail.com>
Myon, Christoph Berg <myon@oftc.net>
spb, Stephen Bennet <spb@libera.chat>
tomaw, Tom Wesley <tom@tomaw.net>
The Charybdis team was:
amdj, Aaron Jones <aaronmdjones -at- gmail.com>
Ariadne, Ariadne Conill <ariadne -at- dereferenced.org>
Elizafox, Elizabeth Myers <elizabeth -at- interlinked.me>
jdhore, JD Horelick <jdhore1 -at- gmail.com>
jilles, Jilles Tjoelker <jilles -at- stack.nl>
mr_flea, Keith Buck <mr_flea -at- esper.net>
viatsko, Valerii Iatsko <dwr -at- codingbox.io>
A full list of contributors to Charybdis and its predecessors
is in doc/credits-past.txt.
Visit the Solanum website at: https://solanum.chat/
Visit us on IRC at: irc.libera.chat #solanum
>>>>>>> .merge_file_gXRYUC

View file

@ -1,6 +0,0 @@
The Charybdis GIT repository can be checked out using the following command:
git clone git://github.com/charybdis-ircd/charybdis.git charybdis-devel
Charybdis's GIT repository depot can be browsed over the internet at
the following address:
http://github.com/charybdis-ircd/charybdis

186
INSTALL
View file

@ -1,186 +0,0 @@
Charybdis INSTALL Document
$Id: INSTALL 3384 2007-04-03 22:45:04Z jilles $
Copyright (c) 2001 by ircd-hybrid team
Copyright (c) 2002-2004 ircd-ratbox development team
Copyright (c) 2005-2008 charybdis development team
----------------------------------------------------------------------
HOW TO BUILD
As of hybrid-4, the distribution uses GNU autoconf instead of the old
Config script. The Makefile has also been updated to include CFLAGS
defines for popular modern OSes.
1.
Read the NEWS file to find out about the exciting new features in
this version. Other good reads are BUGS, doc/ircd.conf.example, and
README.FIRST.
2.
Run the configure script. It will create include/setup.h and the
Makefiles to match your system. In ircd-ratbox, the paths are now handled
with the --prefix option to configure, not in config.h.
/usr/local/ircd is the default if no prefix is specified.
./configure --prefix="/usr/local/ircd"
Note: There are some special optional parameters to the configure
script that some admins may wish to use.
*
--enable-kqueue - Use the superior kqueue(2) system call as
opposed to the default poll(2). This is currently only available
on FreeBSD 4.1 or higher.
*
--enable-devpoll - Enable the superior /dev/poll support on
Solaris. Linux /dev/poll is broken and will not work with this
option.
*
--enable-epoll - Enable the superior Linux Edge-Triggered Polling
system. This is currently only available on 2.5 Linux kernel
versions or later.
*
--enable-openssl - Enable the openssl dependent crypto functions.
This will allow CHALLENGE to work and encrypted links. On systems
where the configure script can automatically detect OpenSSL, this
option is not necessary. If configure cannot find OpenSSL, you
must specify a path with this option
(--enable-openssl=/path/to/openssl)
*
--enable-ipv6 - Enable IPv6 support.
*
--enable-assert[=OPTION] - Enable some debugging code. OPTION is
either 'soft' or 'hard' (default: hard). 'hard' should never be
used on production servers as it may generate unnecessary cores.
'soft' prevents cores from being generated but still imposes some
additional load.
*
--enable-small-net - Tunes the server for smaller networks by
reducing the startup memory footprint. This should really only be
used for *small* networks, as this tends to be a performance hit
on larger networks.
*
--with-nicklen=LENGTH - Sets the maximum NICK length. Note that
this must be consistent across your entire network.
3.
make should build ircd.
4.
make install will install the server, modules, and tools in the
the prefix specified when configure was run.
5.
If you wish to enable the user log, oper log, and failed oper log,
issue these commands at the shell prompt (in the prefix directory)
$ touch logs/userlog
$ touch logs/operlog
$ touch logs/foperlog
Note: If you use different names in ircd.conf, you must 'touch' the
specific names.
----------------------------------------------------------------------
HOW TO GET HELP
Send Check or Money Order to... just kidding! You're on your own for
support. Try asking other ircd-ratbox admins on EFnet if you can't fix it
yourself. If you do fix anything, however, please send context or unified
diffs to ircd-ratbox@lists.ratbox.org so the fixes can be incorporated into
the next release of ircd-hybrid. If ratbox crashes on you, PLEASE contact
ircd-ratbox@lists.ratbox.org ASAP with a backtrace of the core.
DISCUSSION: There is a mailing list for discussion of ratbox issues,
To subscribe, visit:
http://lists.ratbox.org/cgi-bin/mailman/listinfo/ircd-ratbox
----------------------------------------------------------------------
NOTES
The best way to get a backtrace of the core is to follow this sequence of
instructions:
1.
Change to the directory containing the core file
2.
Run gdb on the binary and the core file. With an unmodified ircd-ratbox
installation, an example command line is below (in the /usr/local/ircd
directory)
$ gdb bin/ircd ircd.core
3.
At the "(gdb)" prompt, enter the command "bt"
4.
Save the output of the backtrace command and send it to
ircd-ratbox@lists.ratbox.org
5.
Be sure to save the ircd binary, the modules, and the core file in a
safe place in case the developers need to look deeper than a backtrace
provides.
----------------------------------------------------------------------
OPENSSL NOTES
Older FreeBSD machines sometimes have the obsolete ports version of
OpenSSL libcrypto in /usr/local/lib. When configure is used with
--enable-openssl, and libintl is detected in /usr/local/lib, the
/usr/local/lib directory will be searched BEFORE the system /usr/lib for
libraries by the linker. The linker may try to link to the old
/usr/local/lib libcrypto instead of the system /usr/lib libcrypto. Some
older versions may cause error messages similar to the following:
gcc -g -O2 -DIRCD_PREFIX=\"/home/wcampbel/ircd\" -Wl,-export-dynamic
-L/usr/local/lib -o ircd blalloc.o channel.o vchannel.o class.o client.o
dline_conf.o event.o fdlist.o fileio.o hash.o irc_string.o ircd.o ircdauth.o
ircd_signal.o linebuf.o list.o listener.o m_error.o match.o memdebug.o
modules.o motd.o mtrie_conf.o oldparse.o numeric.o packet.o parse.o res.o rsa.o
restart.o s_auth.o s_bsd.o s_bsd_kqueue.o s_conf.o s_debug.o s_gline.o s_log.o
s_misc.o s_serv.o s_stats.o s_user.o scache.o send.o sprintf_irc.o tools.o
whowas.o lex.yy.o y.tab.o version.o -lintl -ldescrypt -lcrypto -lfl
rsa.o: In function `get_randomness':
/home/wcampbel/dev/ircd-ratbox/src/rsa.c(.text+0x60): undefined reference to
`RAND_pseudo_bytes'
/usr/local/lib/libcrypto.so: undefined reference to `ERR_load_RSAREF_strings'
/usr/local/lib/libcrypto.so: undefined reference to `RSA_PKCS1_RSAref'
*** Error code 1
If this is the case, you may need to rerun configure without the
--enable-openssl option, manually edit src/Makefile and modules/Makefile
to put -L/usr/lib before the -L/usr/local/lib in LDFLAGS, or remove the
old OpenSSL from /usr/local, and recompile all applications that use
libcrypto to use the system one.

View file

@ -1,4 +1,3 @@
# $Id: LICENSE 6 2005-09-10 01:02:21Z nenolod $
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991

60
Makefile.am Normal file
View file

@ -0,0 +1,60 @@
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = librb
if BUILD_LTDL
SUBDIRS += libltdl
endif
SUBDIRS += ircd \
ssld \
wsockd \
authd \
bandb \
tests \
tools \
modules \
extensions \
help \
doc
BUILT_SOURCES = include/serno.h
include/serno.h:
@if [ -d .git ]; then \
revh=`git log -1 --date=format:%Y%m%d --pretty=format:%cd-%h`; \
datecode=`git log -1 --pretty=format:%ct`; \
if [ -n "$$revh" ]; then \
echo '#define SERNO "'$$revh'"' >include/serno.h ; \
echo "#define DATECODE $${datecode}UL" >>include/serno.h; \
fi \
fi
@if [ ! -f include/serno.h ]; then \
echo '#define SERNO "unknown"' >include/serno.h; \
echo '#define DATECODE 0UL' >>include/serno.h; \
fi
install-data-hook:
test -d ${DESTDIR}${logdir} || mkdir -p ${DESTDIR}${logdir}
install-exec-hook:
rm -f ${DESTDIR}${libdir}/*.la
rm -f ${DESTDIR}${moduledir}/*.la
rm -f ${DESTDIR}${moduledir}/autoload/*.la
rm -f ${DESTDIR}${moduledir}/extensions/*.la
rm -f ${DESTDIR}${libdir}/*.dll.a
rm -f ${DESTDIR}${moduledir}/*.dll.a
rm -f ${DESTDIR}${moduledir}/autoload/*.dll.a
rm -f ${DESTDIR}${moduledir}/extensions/*.dll.a
distclean-local:
rm -f librb/include/librb-config.h
clean-local:
rm -f include/serno.h
rm -f ircd/ircd_lexer.c
rm -f ircd/ircd_parser.c
rm -f ircd/ircd_parser.h
rm -f ircd/version.c
rm -f ircd/version.c.last

View file

@ -1,162 +0,0 @@
#************************************************************************
#* IRC - Internet Relay Chat, Makefile
#* Copyright (C) 1990, Jarkko Oikarinen
#*
#* This program is free software; you can redistribute it and/or modify
#* it under the terms of the GNU General Public License as published by
#* the Free Software Foundation; either version 1, or (at your option)
#* any later version.
#*
#* This program is distributed in the hope that it will be useful,
#* but WITHOUT ANY WARRANTY; without even the implied warranty of
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#* GNU General Public License for more details.
#*
#* You should have received a copy of the GNU General Public License
#* along with this program; if not, write to the Free Software
#* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#*
#* $Id: Makefile.in 1347 2006-05-17 14:49:13Z nenolod $
#*/
RM=@RM@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
mandir = @mandir@
libdir = @libdir@
pkglibdir = @pkglibdir@
moduledir = @moduledir@
helpdir = @helpdir@
sysconfdir = @sysconfdir@
logdir = @logdir@
rundir = @rundir@
pkgrundir = @pkgrundir@
localstatedir = @localstatedir@
pkglocalstatedir= @pkglocalstatedir@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
# Default CFLAGS
# CFLAGS = -g -O2 -DNDEBUG
CFLAGS = @CFLAGS@
# Developers CFLAGS
#CFLAGS= -g -O2 -Wunused -Wall -ggdb -pedantic -Wshadow -Wmissing-declarations
# Default make flags - you may want to uncomment this on a multicpu machine
#MFLAGS = -j 4
#
# For developers
#CFLAGS= -g -O2 -Wall
# You may need to define the FD_SETSIZE in order to overrule
# the system one.
#CFLAGS= -DNDEBUG -g -O2 -D"FD_SETSIZE=1024"
SHELL=/bin/sh
# `extensions' must be after `modules' for proper creation of $(moduledir).
SUBDIRS=libratbox modules extensions src tools ssld bandb doc help
CLEANDIRS = ${SUBDIRS}
RSA_FILES=rsa_respond/README rsa_respond/respond.c rsa_respond/Makefile
all: build
autoconf: configure.ac
autoconf
autoheader
${RM} -f config.cache
build:
-@if [ ! -f include/setup.h ] ; then \
echo "Hmm...doesn't look like you've run configure..."; \
echo "Doing so now."; \
sh configure; \
fi
@if [ -d .git ] ; then \
revh=`git log -1 --date=short --pretty=format:%cd_%h 2>/dev/null | sed -e s/-//g -e s/_/-/`;\
[ -z "$$revh" ] || echo '#define SERNO "'$$revh'"' >include/serno.h ; \
elif [ -d .hg ] ; then \
revh=`hg parents --template '{date|shortdate}_{node|short}' 2>/dev/null | sed -e s/-//g -e s/_/-/`;\
[ -z "$$revh" ] || echo '#define SERNO "'$$revh'"' >include/serno.h ; \
fi
@[ -f include/serno.h ] || echo '#define SERNO "unknown"' >include/serno.h
@for i in $(SUBDIRS); do \
echo "build ==> $$i";\
cd $$i;\
${MAKE} || exit; cd ..;\
done
clean:
${RM} -f *~ core rsa_respond.tar rsa_respond.tar.gz
@for i in $(CLEANDIRS); do \
echo "clean ==> $$i";\
cd $$i;\
${MAKE} clean; cd ..;\
done
-@if [ -f include/setup.h ] ; then \
echo "To really restart installation, make distclean" ; \
fi
distclean:
${RM} -f Makefile *~ *.rej *.orig core ircd.core
${RM} -f config.status config.cache config.log
cd include; ${RM} -f setup.h *~ *.rej *.orig ; cd ..
@for i in $(CLEANDIRS); do \
echo "distclean ==> $$i";\
cd $$i;\
${MAKE} distclean; cd ..;\
done
depend:
@[ -f include/serno.h ] || echo '#define SERNO "unknown"' >include/serno.h
@for i in $(SUBDIRS); do \
echo "depend ==> $$i";\
cd $$i;\
${MAKE} depend; cd ..;\
done
lint:
@for i in $(SUBDIRS); do \
echo "lint ==> $$i";\
cd $$i;\
${MAKE} lint; cd ..;\
done
install-mkdirs:
@echo "ircd: setting up ircd directory structure"
-@if test ! -d $(DESTDIR)$(prefix); then \
mkdir -p -m 755 $(DESTDIR)$(prefix); \
fi
-@if test ! -d $(DESTDIR)$(bindir); then \
mkdir -p -m 755 $(DESTDIR)$(bindir); \
fi
-@if test ! -d $(DESTDIR)$(sysconfdir); then \
mkdir -p -m 755 $(DESTDIR)$(sysconfdir); \
fi
-@if test ! -d $(DESTDIR)$(mandir); then \
mkdir -p -m 755 $(DESTDIR)$(mandir); \
fi
-@if test ! -d $(DESTDIR)$(logdir); then \
mkdir -p -m 755 $(DESTDIR)$(logdir); \
fi
-@if test ! -d '$(DESTDIR)$(pkgrundir)'; then \
mkdir -p -m 755 '$(DESTDIR)$(pkgrundir)'; \
fi
-@if test ! -d '$(DESTDIR)$(pkglocalstatedir)'; then \
mkdir -p -m 755 '$(DESTDIR)$(pkglocalstatedir)'; \
fi
install: install-mkdirs all
@for i in $(SUBDIRS); do \
echo "install ==> $$i";\
cd $$i;\
${MAKE} install; \
cd ..; \
done
rsa_respond:
@cd tools;\
echo "Creating rsa_respond.tar.gz";\
tar cf ../rsa_respond.tar $(RSA_FILES);\
cd ..;\
gzip rsa_respond.tar

202
NEWS.md
View file

@ -1,5 +1,6 @@
# News
<<<<<<< .merge_file_h36DbE
This is charybdis 3.5.7, Copyright (c) 2005-2019 Charybdis team.
See LICENSE for licensing details (GPL v2).
@ -107,6 +108,205 @@ This is a minor bugfix release only
### misc
- Backport various ssld IPC improvements from master.
=======
This is solanum 1.0-dev.
See LICENSE for licensing details (GPL v2).
## solanum-1.0
Includes changes from charybdis-4.1.3-dev.
**This release includes breaking changes from charybdis 4.x.** Please pay close attention to
bolded warnings in the full release notes below.
### build
- Add `--with-asan` to configure to produce an ASan instrumented build
### server protocol
- **Breaking:** Don't implicitly abort SASL when connection registration handshake completes;
requires updating atheme to include https://github.com/atheme/atheme/pull/833.
- OPER is now propagated globally, as :operator OPER opername privset
### user
- **Breaking:** invite-notify is now enabled by loading the invite-notify extension
- Prioritise older, more important client capabilities for clients that can only accept
one line of CAP LS
- Add the solanum.chat/realhost vendor capability (provided by extensions/cap\_realhost)
- Add the solanum.chat/identify-msg vendor capability (provided by extensions/identify\_msg)
- Server-side aliases preserve protocol framing characters
- Add the +G user mode for soft callerid (implicitly allow users with a common channel)
- /invite no longer punches through callerid
- invite-notify now works
- Rejectcached users are now sent the reason of the ban that caused their reject in most cases
- Rejectcache entries expire when their corresponding K-lines do
- One-argument /stats and zero-argument /motd are no longer ratelimited
- Channel bans don't see through IP spoofs
- Global /names now respects userhost-in-names
- The `$j` extban is no longer usable inside ban exceptions
- TLSv1 connections are accepted. They can still be disabled using OpenSSL config if you don't
want them. TLSv1 existing is not thought to be a threat to up-to-date clients.
### oper
- **Breaking:** Kick immunity for override is now its own extension, override\_kick\_immunity
- **Breaking:** /stats A output now follows the same format as other stats letters
- **Breaking:** helpops now uses +h instead of +H
- **Breaking:** sno\_whois and the spy\_ extensions have been removed
- **Breaking:** Using /wallops now requires the oper:wallops privilege instead of oper:massnotice
- Opers now have their privset (identified by name) on remote servers
- Oper-only umodes are refreshed after rehash and /grant
- Extension modules can be reloaded
- Override no longer spams about being enabled/disabled. It continues to spam on each use.
- Add /testkline, which has the same syntax as /testline but doesn't check if the mask is ilined
- /privs is now remote-capable and can respond with more than one line
- Most commands now respect oper hiding
- Massnotice (notice/privmsg to $$.../$#...) now alerts opers
- Massnotice no longer imposes any restrictions on the target mask
- /kline and /dline are hardened to invalid inputs
- K/D-lines are more consistent about checking for encoded ipv4-in-ipv6 addresses
- Add extensions/drain to reject new connections
- Add extensions/filter to filter messages, parts and quits with a Hyperscan database
- Add extensions/sasl\_usercloak to interpolate SASL account names into I-line spoofs
### conf
- **Breaking:** Completely overhaul oper privs. All privset configs will need to be rewritten.
See reference.conf for details.
- Add the `kline_spoof_ip` I-line flag to make any spoof opaque to K-line matching
- Add general::hide\_tkline\_duration to remove durations from user-visible ban reasons
- Add general::hide\_opers, which behaves as if all opers have oper:hidden
- Add general::post\_registration\_delay
- Add general::tls\_ciphers\_oper\_only to hide TLS cipher details in /whois
- Add channel::opmod\_send\_statusmsg to send messages allowed by +z to @#channel
- Add class::max\_autoconn, with the behaviour of class::max\_number for servers prior to
charybdis 4
- Add `secure {}` blocks. Networks listed in a secure block gain +Z and can match `need_ssl` I-
and O-lines.
- Remove general::kline\_delay
- If m\_webirc is loaded, connections that try to use a webirc auth block as their I-line will
be disconnected on registration
### misc
- **Breaking:** WEBIRC now processes the "secure" option as specified by IRCv3. Web gateways that
do not set this option will need to be updated or their connections will show as insecure.
- Successfully changing IP with WEBIRC now drops an identd username
### code
- Channel lists are now kept sorted. A for-loop macro, `ITER_COMM_CHANNELS`, is introduced to
efficiently compare two such lists.
## charybdis-4.1.2
### user
- src/s\_user.c: don't corrupt usermodes on module unload/reload
## charybdis-4.1.1
### security
- Fix an issue with the PASS command and duplicate server instances.
### misc
- Fix connection hang with blacklist/opm when ident is disabled.
- Improve SASL CAP notification when the services server disconnects.
- MbedTLS: Support ChaCha20-Poly1305 in default cipher suites.
## charybdis-4.1
### misc
- SCTP is now supported for server connections (and optionally, user connections)
## charybdis-4.0.1
### server protocol
- SJOIN messages were being constructed in a 1024 byte buffer and truncated to 512 bytes
when sending. This caused channels with more than 50 users to fail to propagate all of
them during a net join.
## charybdis-4.0
### build
- Build system has been converted to libtool + automake for sanity reasons.
- The compile date is now set at configure time rather than build time, allowing for
reproducible builds. (#148, #149)
- Support for GNUTLS 3.4 has been added.
### user
- Import the ability to exceed MAXCHANNELS from ircd-seven.
- Implement IRCv3.2 enhanced capability negotiation (`CAP LS 302`).
- Implement support for receiving and sending IRCv3 message tags.
- Implement IRCv3.2 capabilities: (#141)
- account-tag
- echo-message
- invite-notify
- sasl
- server-time
- SASL: certificate fingerprints are now always sent to the SASL agent, allowing for
the certificate to be used as a second authentication factor.
### oper
- Merge several features from ircd-seven:
- Implement support for remote DIE/RESTART.
- Implement support for remote MODLOAD et al commands.
- Add the GRANT command which allows for temporarily opering a client.
- Implement the hidden oper-only channel modes framework.
- Implement a channel mode that disallows kicking IRC operators (+M).
- Enhance the oper override system, allowing more flexibility and detail
in network-wide notices.
- DNS, ident, and blacklist lookups have been moved to a dedicated daemon known
as authd. Some cosmetic changes to blacklist statistics and rejection notices
have resulted.
- An experimental OPM scanner has been added to authd. Plaintext SOCKS4,
SOCKS5, and HTTP CONNECT proxies can be checked for.
- The LOCOPS command has been moved from core to an extension.
- All core modules in charybdis have descriptions, which are shown in MODLIST.
- Suffixes should not be used when doing /MODLOAD, /MODUNLOAD, /MODRELOAD, etc.
### misc
- Support for WebSocket has been added, use the listen::wsock option to switch
a listener into websocket mode.
### conf
- Add the ability to strip color codes from topics unconditionally.
- The obsolete hub option from server info has been removed.
### docs
- The documentation has been cleaned up; obsolete files have been purged, and
files have been renamed and shuffled around to be more consistent.
### code
- `common.h` is gone. Everything useful in it was moved to `ircd_defs.h`.
- `config.h` is gone; the few remaining knobs in it were not for configuration
by mere mortals, and mostly existed as a 2.8 relic. Most of the knobs live in
`defaults.h`, but one is well-advised to stay away unless they know exactly
what they are doing.
- A new module API has been introduced, known as AV2. It includes things such as
module datecodes (to ensure modules don't fall out of sync with the code),
module descriptions, and other fun things.
- Alias and module commands are now in m_alias and m_modules, respectively, and
can be reloaded if need be. For sanity reasons, m_modules is a core module,
and cannot be unloaded.
- irc_dictionary and irc_radixtree related functions are now in librb, and
prefixed accordingly. Typedefs have been added for consistency with existing
data structures. For example, now you would write `rb_dictionary *foo` and
`RB_DICTIONARY_FOREACH`.
- C99 bools are now included and used in the code. Don't use ints as simple true
or false flags anymore. In accordance with this change, the `YES`/`NO` and
`TRUE`/`FALSE` macros have been removed.
- Return types from command handlers have been axed, as they have been useless
for years.
- libratbox has been renamed to librb, as we have diverged from upstream long
ago.
- Almost all 2.8-style hashtable structures have been moved to dictionaries or
radix trees, resulting in significant memory savings.
- The block allocator has been disabled and is no longer used.
- The ratbox client capabilities have been ported to use the ircd capabilities
framework, allowing for modules to provide capabilities.
- Support for restarting ssld has been added. ssld processes which are still
servicing clients will remain in use, but not service new connections, and
are garbage collected when they are no longer servicing connections.
- Support for ratbox-style 'iodebug' hooks has been removed.
- New channel types may be added by modules, see `extensions/chantype_dummy.c`
for a very simple example.
>>>>>>> .merge_file_4c8glm
## charybdis-3.5.0
@ -757,7 +957,7 @@ This is a minor bugfix release only
## charybdis-1.0
- Implement channel mode +L for channel list limit exemptions.
- Implement channel mode +P primarily as a status mode, permanant
- Implement channel mode +P primarily as a status mode, permanant
channel -- this is usually enforced via services registrations.
- Change behaviour of /stats p: now displays all staff members instead
of local ones only.

109
README.md
View file

@ -1,30 +1,82 @@
# charybdis
# solanum ![Build Status](https://github.com/solanum-ircd/solanum/workflows/CI/badge.svg)
Charybdis is a reference implementation of the IRCv3.1 server component. It is meant to be
used with an IRCv3-capable services implementation such as [Atheme][atheme] or [Anope][anope].
Solanum is an IRCv3 server designed to be highly scalable. It implements IRCv3.1 and some parts of IRCv3.2.
[atheme]: http://www.atheme.net/
It is meant to be used with an IRCv3-capable services implementation such as [Atheme][atheme] or [Anope][anope].
[atheme]: https://atheme.github.io/
[anope]: http://www.anope.org/
# necessary requirements
* A supported platform
* A working dynamic load library.
* A working lex. Solaris /usr/ccs/bin/lex appears to be broken, on this system flex should be used.
* A working dynamic library system
* A working lex and yacc - flex and bison should work
# platforms
Solanum is developed on Linux with glibc, but is currently portable to most POSIX-compatible operating systems.
However, this portability is likely to be removed unless someone is willing to maintain it. If you'd like to be that
person, please let us know on IRC.
# platform specific errata
These are known issues and workarounds for various platforms.
* **macOS**: you must set the `LIBTOOLIZE` environment variable to point to glibtoolize before running autogen.sh:
```bash
brew install libtool
export LIBTOOLIZE="/usr/local/bin/glibtoolize"
./autogen.sh
```
* **FreeBSD**: 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`
* **Solaris**: you may have to set your `PATH` to include `/usr/gnu/bin` and `/usr/gnu/sbin` before `/usr/bin`
and `/usr/sbin`. Solaris's default tools don't seem to play nicely with the configure script. When running
as a 32-bit binary, it should be started as:
```bash
ulimit -n 4095 ; LD_PRELOAD_32=/usr/lib/extendedFILE.so.1 ./solanum
```
# building
```bash
sudo apt install build-essential pkg-config automake libtool libsqlite3-dev # or equivalent for your distribution
./autogen.sh
./configure --prefix=/path/to/installation
make
make check # run tests
make install
```
See `./configure --help` for build options.
# feature specific requirements
* For SSL/TLS client and server connections, one of:
<<<<<<< .merge_file_7Huc5m
* OpenSSL 1.0.0 or newer (--enable-openssl)
* LibreSSL (--enable-openssl)
* MbedTLS (--enable-mbedtls)
* GnuTLS (--enable-gnutls)
=======
* OpenSSL 1.0.0 or newer (`--enable-openssl`)
* LibreSSL (`--enable-openssl`)
* mbedTLS (`--enable-mbedtls`)
* GnuTLS (`--enable-gnutls`)
>>>>>>> .merge_file_dqpn0B
* For certificate-based oper CHALLENGE, OpenSSL 1.0.0 or newer.
(Using CHALLENGE is not recommended for new deployments, so if you want to use a different TLS library,
feel free.)
<<<<<<< .merge_file_7Huc5m
* For ECDHE under OpenSSL, on Solaris and RHEL/Fedora (and its derivatives such as CentOS) you will
need to compile your own OpenSSL on these systems, as they have removed support for ECC/ECDHE.
Alternatively, consider using another library (see above).
@ -32,35 +84,28 @@ used with an IRCv3-capable services implementation such as [Atheme][atheme] or [
# tips
* To report bugs in charybdis, visit us on IRC at chat.freenode.net #charybdis
=======
* For ECDHE under OpenSSL, on Solaris you will need to compile your own OpenSSL on these systems, as they
have removed support for ECC/ECDHE. Alternatively, consider using another library (see above).
* Please read doc/index.txt to get an overview of the current documentation.
# tips
* The files, /etc/services, /etc/protocols, and /etc/resolv.conf, SHOULD be
* To report bugs in Solanum, visit us at `#solanum` on [Libera Chat](https://libera.chat)
>>>>>>> .merge_file_dqpn0B
* Please read [doc/readme.txt](doc/readme.txt) to get an overview of the current documentation.
* Read the [NEWS.md](NEWS.md) file for what's new in this release.
* The files, `/etc/services`, `/etc/protocols`, and `/etc/resolv.conf`, SHOULD be
readable by the user running the server in order for ircd to start with
the correct settings. If these files are wrong, charybdis will try to use
127.0.0.1 for a resolver as a last-ditch effort.
the correct settings. If these files are wrong, Solanum will try to use
`127.0.0.1` for a resolver as a last-ditch effort.
* 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"
# git access
* SOLARIS USERS: this code appears to tickle a bug in older gcc and
egcs ONLY on 64-bit Solaris7. gcc-2.95 and SunPro C on 64bit should
work fine, and any gcc or SunPro compiled on 32bit.
* The Solanum git repository can be checked out using the following command:
`git clone https://github.com/solanum-ircd/solanum`
* SUPPORTED PLATFORMS: this code should compile without any warnings on:
* FreeBSD 10
* Gentoo & Gentoo Hardened ~x86/~amd64/~fbsd
* RHEL 6 / 7
* Debian Jessie
* OpenSuSE 11/12
* 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.
* Please read NEWS for information about what is in this release.
* Other files recommended for reading: BUGS, INSTALL
* Solanum's git repository can be browsed over the Internet at the following address:
https://github.com/solanum-ircd/solanum

61
TODO
View file

@ -1,61 +0,0 @@
/ = in progress, x = done, ? = to be discussed, F = charybdis3.1 or next releases
[/] finish legacy code removal
[x] remove 2.8 report_error() in ratbox imported stuff
[F] client.c, channel.c is very 2.8 style still. it'd be nice to pack them into their own
namespace and such. moreover, the other 2.8 code needs similar rewriting/reworking too...
[x] merge m_join.c and m_sjoin.c in one module (same functions, done in ratbox3)
[ ] rewrite s_auth.c
[ ] authentication state/lock manager
[ ] move resolver/auth checker code into separated modules
[x] port to libratbox
[x] get it running
[x] clean up maxconnections kludges &c
[x] in-process SSL
[x] port and use ratbox ssld for server links
[x] merge with libratbox SVN
[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)
[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)
[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)
[ ] kline/xline/resv sync (what about spb's extension?)
[x] drop non-TS6 (legacy protocol) support
[?] Patch or core-feature - libguess on-fly any-charset-to-utf8 translation
[x] module engine rework
[?] MODULE_DEPEND and MODULE_CONFLICT for building extension dependencies (backport from shadowircd)
[x] more beautiful way of adding new channel modes by module
[x] basic functionality
[x] some example modules
[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
[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
[?] mingw support
[R] win32 native support - VS doesn't follow C99, this will require us switching back to C89 with libratbox and (future) core
[x] Bug fixes
[x] Compilation without zlib headers fails - fixed
[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
[?] internally split out +o/+v "ranks" into a series of permissions. this could allow for configure-defined
special access levels, halfops, etc. (would need to match globally, somehow. extra SVINFO param?)
might be backported from shadowircd in future (chanroles planned)
[?] somehow hide channel operators like ircnet can do?
couldn't be done via extension currently - compilation-time option acceptable?
[x] create chmode.h and put there all declarations of chm_* - this will make some modules clean
[?] Move oper override server WALLOPS to global server notices?

17
authd/Makefile.am Normal file
View file

@ -0,0 +1,17 @@
pkglibexec_PROGRAMS = authd
AM_CFLAGS=$(WARNFLAGS)
AM_CPPFLAGS = -I../include -I../librb/include
authd_SOURCES = \
authd.c \
dns.c \
notice.c \
provider.c \
res.c \
reslib.c \
providers/dnsbl.c \
providers/ident.c \
providers/rdns.c \
providers/opm.c
authd_LDADD = ../librb/src/librb.la

216
authd/authd.c Normal file
View file

@ -0,0 +1,216 @@
/* authd/authd.c - main code for authd
* Copyright (c) 2016 Ariadne Conill <ariadne@dereferenced.org>
*
* 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 "authd.h"
#include "dns.h"
#include "provider.h"
#include "notice.h"
#define MAXPARA 10
static void error_cb(rb_helper *helper) __attribute__((noreturn));
static void handle_reload(int parc, char *parv[]);
static void handle_stat(int parc, char *parv[]);
static void handle_options(int parc, char *parv[]);
rb_helper *authd_helper = NULL;
authd_cmd_handler authd_cmd_handlers[256] = {
['C'] = handle_new_connection,
['D'] = handle_resolve_dns,
['E'] = handle_cancel_connection,
['O'] = handle_options,
['R'] = handle_reload,
['S'] = handle_stat,
};
authd_stat_handler authd_stat_handlers[256] = {
['D'] = enumerate_nameservers,
};
authd_reload_handler authd_reload_handlers[256] = {
['D'] = reload_nameservers,
};
rb_dictionary *authd_option_handlers;
static void
handle_stat(int parc, char *parv[])
{
authd_stat_handler handler;
unsigned long long rid;
if(parc < 3)
{
warn_opers(L_CRIT, "BUG: handle_stat received too few parameters (at least 3 expected, got %d)", parc);
return;
}
if((rid = strtoull(parv[1], NULL, 16)) > UINT32_MAX)
{
warn_opers(L_CRIT, "BUG: handle_stat got a rid that was too large: %s", parv[1]);
return;
}
if (!(handler = authd_stat_handlers[(unsigned char)parv[2][0]]))
return;
handler((uint32_t)rid, parv[2][0]);
}
static void
handle_options(int parc, char *parv[])
{
struct auth_opts_handler *handler;
if(parc < 2)
{
warn_opers(L_CRIT, "BUG: handle_options received too few parameters (at least 2 expected, got %d)", parc);
return;
}
if((handler = rb_dictionary_retrieve(authd_option_handlers, parv[1])) == NULL)
{
warn_opers(L_CRIT, "BUG: handle_options got a bad option type %s", parv[1]);
return;
}
if((parc - 2) < handler->min_parc)
{
warn_opers(L_CRIT, "BUG: handle_options received too few parameters (at least %d expected, got %d)", handler->min_parc, parc);
return;
}
handler->handler(parv[1], parc - 2, (const char **)&parv[2]);
}
static void
handle_reload(int parc, char *parv[])
{
authd_reload_handler handler;
if(parc <= 2)
{
/* Reload all handlers */
for(size_t i = 0; i < 256; i++)
{
if ((handler = authd_reload_handlers[(unsigned char) i]) != NULL)
handler('\0');
}
return;
}
if (!(handler = authd_reload_handlers[(unsigned char)parv[1][0]]))
return;
handler(parv[1][0]);
}
static void
parse_request(rb_helper *helper)
{
static char *parv[MAXPARA + 1];
static char readbuf[READBUF_SIZE];
int parc;
int len;
authd_cmd_handler handler;
while((len = rb_helper_read(helper, readbuf, sizeof(readbuf))) > 0)
{
parc = rb_string_to_array(readbuf, parv, MAXPARA);
if(parc < 1)
continue;
handler = authd_cmd_handlers[(unsigned char)parv[0][0]];
if (handler != NULL)
handler(parc, parv);
}
}
static void
error_cb(rb_helper *helper)
{
exit(EX_ERROR);
}
static void
dummy_handler(int sig)
{
return;
}
static void
setup_signals(void)
{
struct sigaction act;
act.sa_flags = 0;
act.sa_handler = SIG_IGN;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGPIPE);
sigaddset(&act.sa_mask, SIGALRM);
#ifdef SIGTRAP
sigaddset(&act.sa_mask, SIGTRAP);
#endif
#ifdef SIGWINCH
sigaddset(&act.sa_mask, SIGWINCH);
sigaction(SIGWINCH, &act, 0);
#endif
sigaction(SIGPIPE, &act, 0);
#ifdef SIGTRAP
sigaction(SIGTRAP, &act, 0);
#endif
act.sa_handler = dummy_handler;
sigaction(SIGALRM, &act, 0);
}
int
main(int argc, char *argv[])
{
setup_signals();
authd_helper = rb_helper_child(parse_request, error_cb, NULL, NULL, NULL, 256, 256, 256); /* XXX fix me */
if(authd_helper == NULL)
{
fprintf(stderr, "authd is not meant to be invoked by end users\n");
exit(EX_ERROR);
}
rb_set_time();
setup_signals();
authd_option_handlers = rb_dictionary_create("authd options handlers", rb_strcasecmp);
init_resolver();
init_providers();
rb_init_prng(NULL, RB_PRNG_DEFAULT);
rb_helper_loop(authd_helper, 0);
/*
* XXX this function will never be called from here -- is it necessary?
*/
destroy_providers();
return 0;
}

59
authd/authd.h Normal file
View file

@ -0,0 +1,59 @@
/* authd/dns.h - header for authd DNS functions
* Copyright (c) 2016 Ariadne Conill <ariadne@dereferenced.org>
*
* 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 _AUTHD_H
#define _AUTHD_H
#include "stdinc.h"
#include "rb_lib.h"
#include "rb_dictionary.h"
#include "setup.h"
#include "ircd_defs.h"
typedef enum exit_reasons
{
EX_ERROR = 1,
EX_DNS_ERROR = 2,
EX_PROVIDER_ERROR = 3,
} exit_reasons;
typedef void (*provider_opts_handler_t)(const char *, int, const char **);
struct auth_opts_handler
{
const char *option;
int min_parc;
provider_opts_handler_t handler;
};
extern rb_helper *authd_helper;
typedef void (*authd_cmd_handler)(int parc, char *parv[]);
typedef void (*authd_stat_handler)(uint32_t rid, const char letter);
typedef void (*authd_reload_handler)(const char letter);
extern authd_cmd_handler authd_cmd_handlers[256];
extern authd_stat_handler authd_stat_handlers[256];
extern authd_reload_handler authd_reload_handlers[256];
extern rb_dictionary *authd_option_handlers;
#endif

303
authd/dns.c Normal file
View file

@ -0,0 +1,303 @@
/* authd/dns.c - authd DNS functions
* Copyright (c) 2016 Ariadne Conill <ariadne@dereferenced.org>
*
* 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 "authd.h"
#include "dns.h"
#include "notice.h"
#include "res.h"
static void handle_lookup_ip_reply(void *data, struct DNSReply *reply);
static void handle_lookup_hostname_reply(void *data, struct DNSReply *reply);
uint64_t query_count = 0;
/* A bit different from ircd... you just get a dns_query object.
*
* It gets freed whenever the res code gets back to us.
*/
struct dns_query *
lookup_ip(const char *host, int aftype, DNSCB callback, void *data)
{
struct dns_query *query = rb_malloc(sizeof(struct dns_query));
int g_type;
if(aftype == AF_INET)
{
query->type = QUERY_A;
g_type = T_A;
}
else if(aftype == AF_INET6)
{
query->type = QUERY_AAAA;
g_type = T_AAAA;
}
else
{
rb_free(query);
return NULL;
}
query->id = query_count++;
query->callback = callback;
query->data = data;
query->query.ptr = query;
query->query.callback = handle_lookup_ip_reply;
gethost_byname_type(host, &query->query, g_type);
return query;
}
/* See lookup_ip's comment */
struct dns_query *
lookup_hostname(const char *ip, DNSCB callback, void *data)
{
struct dns_query *query = rb_malloc(sizeof(struct dns_query));
int aftype;
if(!rb_inet_pton_sock(ip, &query->addr))
{
rb_free(query);
return NULL;
}
aftype = GET_SS_FAMILY(&query->addr);
if(aftype == AF_INET)
query->type = QUERY_PTR_A;
else if(aftype == AF_INET6)
query->type = QUERY_PTR_AAAA;
else
{
rb_free(query);
return NULL;
}
query->id = query_count++;
query->callback = callback;
query->data = data;
query->query.ptr = query;
query->query.callback = handle_lookup_hostname_reply;
gethost_byaddr(&query->addr, &query->query);
return query;
}
/* Cancel a pending query */
void
cancel_query(struct dns_query *query)
{
query->callback = query->data = NULL;
}
/* Callback from gethost_byname_type */
static void
handle_lookup_ip_reply(void *data, struct DNSReply *reply)
{
struct dns_query *query = data;
char ip[HOSTIPLEN] = "*";
if(query == NULL)
{
/* Shouldn't happen */
warn_opers(L_CRIT, "DNS: handle_lookup_ip_reply: query == NULL!");
exit(EX_DNS_ERROR);
}
if(reply == NULL)
goto end;
switch(query->type)
{
case QUERY_A:
if(GET_SS_FAMILY(&reply->addr) == AF_INET)
rb_inet_ntop_sock((struct sockaddr *)&reply->addr, ip, sizeof(ip));
break;
case QUERY_AAAA:
if(GET_SS_FAMILY(&reply->addr) == AF_INET6)
{
rb_inet_ntop_sock((struct sockaddr *)&reply->addr, ip, sizeof(ip));
if(ip[0] == ':')
{
memmove(&ip[1], ip, strlen(ip));
ip[0] = '0';
}
}
break;
default:
warn_opers(L_CRIT, "DNS: handle_lookup_ip_reply: unknown query type %d",
query->type);
exit(EX_DNS_ERROR);
}
end:
if(query->callback)
query->callback(ip, ip[0] != '*', query->type, query->data);
rb_free(query);
}
/* Callback from gethost_byaddr */
static void
handle_lookup_hostname_reply(void *data, struct DNSReply *reply)
{
struct dns_query *query = data;
char *hostname = NULL;
if(query == NULL)
{
/* Shouldn't happen */
warn_opers(L_CRIT, "DNS: handle_lookup_hostname_reply: query == NULL!");
exit(EX_DNS_ERROR);
}
if(reply == NULL)
goto end;
if(query->type == QUERY_PTR_A)
{
struct sockaddr_in *ip, *ip_fwd;
ip = (struct sockaddr_in *) &query->addr;
ip_fwd = (struct sockaddr_in *) &reply->addr;
if(ip->sin_addr.s_addr == ip_fwd->sin_addr.s_addr)
hostname = reply->h_name;
}
else if(query->type == QUERY_PTR_AAAA)
{
struct sockaddr_in6 *ip, *ip_fwd;
ip = (struct sockaddr_in6 *) &query->addr;
ip_fwd = (struct sockaddr_in6 *) &reply->addr;
if(memcmp(&ip->sin6_addr, &ip_fwd->sin6_addr, sizeof(struct in6_addr)) == 0)
hostname = reply->h_name;
}
else
{
/* Shouldn't happen */
warn_opers(L_CRIT, "DNS: handle_lookup_hostname_reply: unknown query type %d",
query->type);
exit(EX_DNS_ERROR);
}
end:
if(query->callback)
query->callback(hostname, hostname != NULL, query->type, query->data);
rb_free(query);
}
static void
submit_dns_answer(const char *reply, bool status, query_type type, void *data)
{
char *id = data;
if(!id || type == QUERY_INVALID)
{
warn_opers(L_CRIT, "DNS: submit_dns_answer gave us a bad query");
exit(EX_DNS_ERROR);
}
if(reply == NULL || status == false)
{
rb_helper_write(authd_helper, "E %s E %c *", id, type);
rb_free(id);
return;
}
rb_helper_write(authd_helper, "E %s O %c %s", id, type, reply);
rb_free(id);
}
void
handle_resolve_dns(int parc, char *parv[])
{
char *id = rb_strdup(parv[1]);
char qtype = *parv[2];
char *record = parv[3];
int aftype = AF_INET;
switch(qtype)
{
case '6':
aftype = AF_INET6;
case '4':
if(!lookup_ip(record, aftype, submit_dns_answer, id))
submit_dns_answer(NULL, false, qtype, NULL);
break;
case 'S':
case 'R':
if(!lookup_hostname(record, submit_dns_answer, id))
submit_dns_answer(NULL, false, qtype, NULL);
break;
default:
warn_opers(L_CRIT, "DNS: handle_resolve_dns got an unknown query: %c", qtype);
exit(EX_DNS_ERROR);
}
}
void
enumerate_nameservers(uint32_t rid, const char letter)
{
char buf[(HOSTIPLEN + 1) * IRCD_MAXNS];
size_t s = 0;
if (!irc_nscount)
{
/* Shouldn't happen */
warn_opers(L_CRIT, "DNS: no name servers!");
stats_error(rid, letter, "NONAMESERVERS");
exit(EX_DNS_ERROR);
}
for(int i = 0; i < irc_nscount; i++)
{
char addr[HOSTIPLEN];
size_t addrlen;
rb_inet_ntop_sock((struct sockaddr *)&irc_nsaddr_list[i], addr, sizeof(addr));
if (!addr[0])
{
/* Shouldn't happen */
warn_opers(L_CRIT, "DNS: bad nameserver!");
stats_error(rid, letter, "INVALIDNAMESERVER");
exit(EX_DNS_ERROR);
}
addrlen = strlen(addr) + 1;
(void)snprintf(&buf[s], sizeof(buf) - s, "%s ", addr);
s += addrlen;
}
if(s > 0)
buf[--s] = '\0';
stats_result(rid, letter, "%s", buf);
}
void
reload_nameservers(const char letter)
{
/* Not a whole lot to it */
restart_resolver();
}

61
authd/dns.h Normal file
View file

@ -0,0 +1,61 @@
/* authd/dns.h - header for authd DNS functions
* Copyright (c) 2016 Ariadne Conill <ariadne@dereferenced.org>
*
* 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 _AUTHD_DNS_H
#define _AUTHD_DNS_H
#define DNS_REQ_IDLEN 10
#include "stdinc.h"
#include "res.h"
#include "reslib.h"
typedef enum
{
QUERY_INVALID = 0,
QUERY_A = '4',
QUERY_AAAA = '6',
QUERY_PTR_A = 'R',
QUERY_PTR_AAAA = 'S',
} query_type;
/* Similar to that in ircd */
typedef void (*DNSCB)(const char *res, bool status, query_type type, void *data);
struct dns_query
{
struct DNSQuery query;
query_type type;
struct rb_sockaddr_storage addr;
uint64_t id;
DNSCB callback;
void *data;
};
extern struct dns_query *lookup_hostname(const char *ip, DNSCB callback, void *data);
extern struct dns_query *lookup_ip(const char *host, int aftype, DNSCB callback, void *data);
extern void cancel_query(struct dns_query *query);
extern void handle_resolve_dns(int parc, char *parv[]);
extern void enumerate_nameservers(uint32_t rid, const char letter);
extern void reload_nameservers(const char letter);
#endif

84
authd/notice.c Normal file
View file

@ -0,0 +1,84 @@
/* authd/notice.c - send notices back to the ircd and to clients
* Copyright (c) 2016 Elizabeth Myers <elizabeth@interlinked.me>
*
* 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 "authd.h"
#include "notice.h"
/* Send a notice to a client */
void
notice_client(uint32_t cid, const char *fmt, ...)
{
char buf[BUFSIZE];
va_list args;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
rb_helper_write(authd_helper, "N %x :%s", cid, buf);
}
/* Send a warning to the IRC daemon for logging, etc. */
void
warn_opers(notice_level_t level, const char *fmt, ...)
{
char buf[BUFSIZE];
va_list args;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
rb_helper_write(authd_helper, "W %c :%s", level, buf);
}
/* Send a stats result */
void
stats_result(uint32_t cid, char letter, const char *fmt, ...)
{
char buf[BUFSIZE];
va_list args;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
rb_helper_write(authd_helper, "Y %x %c %s", cid, letter, buf);
}
/* Send a stats error */
void
stats_error(uint32_t cid, char letter, const char *fmt, ...)
{
char buf[BUFSIZE];
va_list args;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
rb_helper_write(authd_helper, "X %x %c %s", cid, letter, buf);
}
void
stats_done(uint32_t cid, char letter)
{
rb_helper_write(authd_helper, "Z %x %c", cid, letter);
}

38
authd/notice.h Normal file
View file

@ -0,0 +1,38 @@
/* authd/notice.h - send notices back to the ircd and to clients
* Copyright (c) 2016 Elizabeth Myers <elizabeth@interlinked.me>
*
* 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 __SOLANUM_AUTHD_NOTICE_H__
#define __SOLANUM_AUTHD_NOTICE_H__
typedef enum
{
L_DEBUG = 'D',
L_INFO = 'I',
L_WARN = 'W',
L_CRIT ='C',
} notice_level_t;
void notice_client(uint32_t cid, const char *fmt, ...);
void warn_opers(notice_level_t level, const char *fmt, ...);
void stats_result(uint32_t cid, char letter, const char *fmt, ...);
void stats_error(uint32_t cid, char letter, const char *fmt, ...);
void stats_done(uint32_t cid, char letter);
#endif /* __SOLANUM_AUTHD_NOTICE_H__ */

433
authd/provider.c Normal file
View file

@ -0,0 +1,433 @@
/* authd/provider.c - authentication provider framework
* Copyright (c) 2016 Elizabeth Myers <elizabeth@interlinked.me>
*
* 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.
*/
/* The basic design here is to have "authentication providers" that do things
* like query ident and DNSBLs and even open proxies.
*
* Providers are registered in the auth_providers linked list. It is planned to
* use a bitmap to store provider ID's later.
*
* Providers can either return failure immediately, immediate acceptance, or do
* work in the background (calling set_provider to signal this).
*
* Provider-specific data for each client can be kept in an index of the data
* struct member (using the provider's ID).
*
* All providers must implement at a minimum a perform_provider function. You
* don't have to implement the others if you don't need them.
*
* Providers may kick clients off by rejecting them. Upon rejection, all
* providers are cancelled. They can also unconditionally accept them.
*
* When a provider is done and is neutral on accepting/rejecting a client, it
* should call provider_done. Do NOT call this if you have accepted or rejected
* the client.
*
* Eventually, stuff like *:line handling will be moved here, but that means we
* have to talk to bandb directly first.
*
* --Elizafox, 9 March 2016
*/
#include "stdinc.h"
#include "rb_dictionary.h"
#include "rb_lib.h"
#include "authd.h"
#include "provider.h"
#include "notice.h"
static EVH provider_timeout_event;
rb_dictionary *auth_clients;
rb_dlink_list auth_providers;
static rb_dlink_list free_pids;
static uint32_t allocated_pids;
static struct ev_entry *timeout_ev;
/* Set a provider's raw status */
static inline void
set_provider_status(struct auth_client *auth, uint32_t provider, provider_status_t status)
{
auth->data[provider].status = status;
}
/* Set the provider as running */
static inline void
set_provider_running(struct auth_client *auth, uint32_t provider)
{
auth->providers_active++;
set_provider_status(auth, provider, PROVIDER_STATUS_RUNNING);
}
/* Provider is no longer operating on this auth client */
static inline void
set_provider_done(struct auth_client *auth, uint32_t provider)
{
set_provider_status(auth, provider, PROVIDER_STATUS_DONE);
auth->providers_active--;
}
/* Initalise all providers */
void
init_providers(void)
{
auth_clients = rb_dictionary_create("pending auth clients", rb_uint32cmp);
timeout_ev = rb_event_addish("provider_timeout_event", provider_timeout_event, NULL, 1);
/* FIXME must be started before rdns/ident to receive completion notification from them */
load_provider(&dnsbl_provider);
load_provider(&opm_provider);
/* FIXME must be started after dnsbl/opm in case of early completion notifications */
load_provider(&rdns_provider);
load_provider(&ident_provider);
}
/* Terminate all providers */
void
destroy_providers(void)
{
rb_dlink_node *ptr, *nptr;
rb_dictionary_iter iter;
struct auth_client *auth;
/* Cancel outstanding connections */
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
{
auth_client_ref(auth);
/* TBD - is this the right thing? */
reject_client(auth, UINT32_MAX, "destroy",
"Authentication system is down... try reconnecting in a few seconds");
auth_client_unref(auth);
}
RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_providers.head)
{
struct auth_provider *provider = ptr->data;
if(provider->destroy)
provider->destroy();
rb_dlinkDelete(ptr, &auth_providers);
}
rb_dictionary_destroy(auth_clients, NULL, NULL);
rb_event_delete(timeout_ev);
}
/* Load a provider */
void
load_provider(struct auth_provider *provider)
{
/* Assign a PID */
if(rb_dlink_list_length(&free_pids) > 0)
{
/* use the free list */
provider->id = RB_POINTER_TO_UINT(free_pids.head->data);
rb_dlinkDestroy(free_pids.head, &free_pids);
}
else
{
if(allocated_pids == MAX_PROVIDERS || allocated_pids == UINT32_MAX)
{
warn_opers(L_WARN, "Cannot load additional provider, max reached!");
return;
}
provider->id = allocated_pids++;
}
if(provider->opt_handlers != NULL)
{
struct auth_opts_handler *handler;
for(handler = provider->opt_handlers; handler->option != NULL; handler++)
rb_dictionary_add(authd_option_handlers, handler->option, handler);
}
if(provider->stats_handler.letter != '\0')
authd_stat_handlers[(unsigned char)provider->stats_handler.letter] = provider->stats_handler.handler;
if(provider->init != NULL)
provider->init();
rb_dlinkAdd(provider, &provider->node, &auth_providers);
}
void
unload_provider(struct auth_provider *provider)
{
if(provider->opt_handlers != NULL)
{
struct auth_opts_handler *handler;
for(handler = provider->opt_handlers; handler->option != NULL; handler++)
rb_dictionary_delete(authd_option_handlers, handler->option);
}
if(provider->stats_handler.letter != '\0')
authd_stat_handlers[(unsigned char)provider->stats_handler.letter] = NULL;
if(provider->destroy != NULL)
provider->destroy();
rb_dlinkDelete(&provider->node, &auth_providers);
/* Reclaim ID */
rb_dlinkAddAlloc(RB_UINT_TO_POINTER(provider->id), &free_pids);
}
void
auth_client_free(struct auth_client *auth)
{
rb_dictionary_delete(auth_clients, RB_UINT_TO_POINTER(auth->cid));
rb_free(auth->data);
rb_free(auth);
}
/* Cancel outstanding providers for a client (if any). */
void
cancel_providers(struct auth_client *auth)
{
if(auth->providers_cancelled)
return;
auth->providers_cancelled = true;
if(auth->providers_active > 0)
{
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, auth_providers.head)
{
struct auth_provider *provider = ptr->data;
if(provider->cancel != NULL && is_provider_running(auth, provider->id))
/* Cancel if required */
provider->cancel(auth);
}
}
}
/* Provider is done */
void
provider_done(struct auth_client *auth, uint32_t id)
{
rb_dlink_node *ptr;
lrb_assert(is_provider_running(auth, id));
lrb_assert(id != UINT32_MAX);
lrb_assert(id < allocated_pids);
set_provider_done(auth, id);
if(auth->providers_active == 0 && !auth->providers_starting)
{
/* All done */
accept_client(auth);
return;
}
RB_DLINK_FOREACH(ptr, auth_providers.head)
{
struct auth_provider *provider = ptr->data;
if(provider->completed != NULL && is_provider_running(auth, provider->id))
/* Notify pending clients who asked for it */
provider->completed(auth, id);
}
}
/* Reject a client and cancel any outstanding providers */
void
reject_client(struct auth_client *auth, uint32_t id, const char *data, const char *fmt, ...)
{
char buf[BUFSIZE];
va_list args;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
/* We send back username and hostname in case ircd wants to overrule our decision.
* In the future this may not be the case.
* --Elizafox
*/
rb_helper_write(authd_helper, "R %x %c %s %s %s :%s",
auth->cid, id != UINT32_MAX ? auth->data[id].provider->letter : '*',
auth->username, auth->hostname,
data == NULL ? "*" : data, buf);
if(id != UINT32_MAX)
set_provider_done(auth, id);
cancel_providers(auth);
}
/* Accept a client and cancel outstanding providers if any */
void
accept_client(struct auth_client *auth)
{
rb_helper_write(authd_helper, "A %x %s %s", auth->cid, auth->username, auth->hostname);
cancel_providers(auth);
}
/* Begin authenticating user */
static void
start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ip, const char *c_port, const char *protocol)
{
struct auth_client *auth;
unsigned long long lcid = strtoull(cid, NULL, 16);
rb_dlink_node *ptr;
if(lcid == 0 || lcid > UINT32_MAX)
return;
auth = rb_malloc(sizeof(struct auth_client));
auth_client_ref(auth);
auth->cid = (uint32_t)lcid;
if(rb_dictionary_find(auth_clients, RB_UINT_TO_POINTER(auth->cid)) == NULL)
rb_dictionary_add(auth_clients, RB_UINT_TO_POINTER(auth->cid), auth);
else
{
warn_opers(L_CRIT, "provider: duplicate client added via start_auth: %s", cid);
exit(EX_PROVIDER_ERROR);
}
auth->protocol = strtoull(protocol, NULL, 16);
rb_strlcpy(auth->l_ip, l_ip, sizeof(auth->l_ip));
auth->l_port = (uint16_t)atoi(l_port); /* should be safe */
(void) rb_inet_pton_sock(l_ip, &auth->l_addr);
SET_SS_PORT(&auth->l_addr, htons(auth->l_port));
rb_strlcpy(auth->c_ip, c_ip, sizeof(auth->c_ip));
auth->c_port = (uint16_t)atoi(c_port);
(void) rb_inet_pton_sock(c_ip, &auth->c_addr);
SET_SS_PORT(&auth->c_addr, htons(auth->c_port));
rb_strlcpy(auth->hostname, "*", sizeof(auth->hostname));
rb_strlcpy(auth->username, "*", sizeof(auth->username));
auth->data = rb_malloc(allocated_pids * sizeof(struct auth_client_data));
auth->providers_starting = true;
RB_DLINK_FOREACH(ptr, auth_providers.head)
{
struct auth_provider *provider = ptr->data;
auth->data[provider->id].provider = provider;
lrb_assert(provider->start != NULL);
/* Execute providers */
set_provider_running(auth, provider->id);
if(!provider->start(auth))
/* Rejected immediately */
goto done;
if(auth->providers_cancelled)
break;
}
auth->providers_starting = false;
/* If no providers are running, accept the client */
if(auth->providers_active == 0)
accept_client(auth);
done:
auth_client_unref(auth);
}
/* Callback for the initiation */
void
handle_new_connection(int parc, char *parv[])
{
if (parc < 6) {
warn_opers(L_CRIT, "provider: received too few params for new connection (6 expected, got %d)", parc);
exit(EX_PROVIDER_ERROR);
}
start_auth(parv[1], parv[2], parv[3], parv[4], parv[5], parc > 6 ? parv[6] : "0");
}
void
handle_cancel_connection(int parc, char *parv[])
{
struct auth_client *auth;
unsigned long long lcid;
if(parc < 2)
{
warn_opers(L_CRIT, "provider: received too few params for new connection (2 expected, got %d)", parc);
exit(EX_PROVIDER_ERROR);
}
lcid = strtoull(parv[1], NULL, 16);
if(lcid == 0 || lcid > UINT32_MAX)
{
warn_opers(L_CRIT, "provider: got a request to cancel a connection that can't exist: %s", parv[1]);
exit(EX_PROVIDER_ERROR);
}
if((auth = rb_dictionary_retrieve(auth_clients, RB_UINT_TO_POINTER((uint32_t)lcid))) == NULL)
{
/* This could happen as a race if we've accepted/rejected but they cancel, so don't die here.
* --Elizafox */
return;
}
auth_client_ref(auth);
cancel_providers(auth);
auth_client_unref(auth);
}
static void
provider_timeout_event(void *notused __unused)
{
struct auth_client *auth;
rb_dictionary_iter iter;
const time_t curtime = rb_current_time();
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
{
rb_dlink_node *ptr;
auth_client_ref(auth);
RB_DLINK_FOREACH(ptr, auth_providers.head)
{
struct auth_provider *provider = ptr->data;
const time_t timeout = get_provider_timeout(auth, provider->id);
if(is_provider_running(auth, provider->id) && provider->timeout != NULL &&
timeout > 0 && timeout < curtime)
{
provider->timeout(auth);
}
}
auth_client_unref(auth);
}
}

246
authd/provider.h Normal file
View file

@ -0,0 +1,246 @@
/* authd/provider.h - authentication provider framework
* Copyright (c) 2016 Elizabeth Myers <elizabeth@interlinked.me>
*
* 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 __SOLANUM_AUTHD_PROVIDER_H__
#define __SOLANUM_AUTHD_PROVIDER_H__
#include "stdinc.h"
#include "authd.h"
#include "rb_dictionary.h"
#define MAX_PROVIDERS 32 /* This should be enough */
typedef enum
{
PROVIDER_STATUS_NOTRUN = 0,
PROVIDER_STATUS_RUNNING,
PROVIDER_STATUS_DONE,
} provider_status_t;
struct auth_client_data
{
struct auth_provider *provider; /* Pointer back */
time_t timeout; /* Provider timeout */
void *data; /* Provider data */
provider_status_t status; /* Provider status */
};
struct auth_client
{
uint32_t cid; /* Client ID */
int protocol; /* IP protocol (TCP/SCTP) */
char l_ip[HOSTIPLEN + 1]; /* Listener IP address */
uint16_t l_port; /* Listener port */
struct rb_sockaddr_storage l_addr; /* Listener address/port */
char c_ip[HOSTIPLEN + 1]; /* Client IP address */
uint16_t c_port; /* Client port */
struct rb_sockaddr_storage c_addr; /* Client address/port */
char hostname[HOSTLEN + 1]; /* Used for DNS lookup */
char username[USERLEN + 1]; /* Used for ident lookup */
bool providers_starting; /* Providers are still warming up */
bool providers_cancelled; /* Providers are being cancelled */
unsigned int providers_active; /* Number of active providers */
unsigned int refcount; /* Held references */
struct auth_client_data *data; /* Provider-specific data */
};
typedef bool (*provider_init_t)(void);
typedef void (*provider_destroy_t)(void);
typedef bool (*provider_start_t)(struct auth_client *);
typedef void (*provider_cancel_t)(struct auth_client *);
typedef void (*uint32_timeout_t)(struct auth_client *);
typedef void (*provider_complete_t)(struct auth_client *, uint32_t);
struct auth_stats_handler
{
const char letter;
authd_stat_handler handler;
};
struct auth_provider
{
rb_dlink_node node;
uint32_t id; /* Provider ID */
const char *name; /* Name of the provider */
char letter; /* Letter used on reject, etc. */
provider_init_t init; /* Initalise the provider */
provider_destroy_t destroy; /* Terminate the provider */
provider_start_t start; /* Perform authentication */
provider_cancel_t cancel; /* Authentication cancelled */
uint32_timeout_t timeout; /* Timeout callback */
provider_complete_t completed; /* Callback for when other performers complete (think dependency chains) */
struct auth_stats_handler stats_handler;
struct auth_opts_handler *opt_handlers;
};
extern struct auth_provider rdns_provider;
extern struct auth_provider ident_provider;
extern struct auth_provider dnsbl_provider;
extern struct auth_provider opm_provider;
extern rb_dlink_list auth_providers;
extern rb_dictionary *auth_clients;
void load_provider(struct auth_provider *provider);
void unload_provider(struct auth_provider *provider);
void init_providers(void);
void destroy_providers(void);
void cancel_providers(struct auth_client *auth);
void provider_done(struct auth_client *auth, uint32_t id);
void accept_client(struct auth_client *auth);
void reject_client(struct auth_client *auth, uint32_t id, const char *data, const char *fmt, ...);
void handle_new_connection(int parc, char *parv[]);
void handle_cancel_connection(int parc, char *parv[]);
void auth_client_free(struct auth_client *auth);
static inline void
auth_client_ref(struct auth_client *auth)
{
auth->refcount++;
}
static inline void
auth_client_unref(struct auth_client *auth)
{
auth->refcount--;
if (auth->refcount == 0)
auth_client_free(auth);
}
/* Get a provider by name */
static inline struct auth_provider *
find_provider(const char *name)
{
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, auth_providers.head)
{
struct auth_provider *provider = ptr->data;
if(strcasecmp(provider->name, name) == 0)
return provider;
}
return NULL;
}
/* Get a provider's id by name */
static inline bool
get_provider_id(const char *name, uint32_t *id)
{
struct auth_provider *provider = find_provider(name);
if(provider != NULL)
{
*id = provider->id;
return true;
}
else
return false;
}
/* Get a provider's raw status */
static inline provider_status_t
get_provider_status(struct auth_client *auth, uint32_t provider)
{
return auth->data[provider].status;
}
/* Check if provider is operating on this auth client */
static inline bool
is_provider_running(struct auth_client *auth, uint32_t provider)
{
return get_provider_status(auth, provider) == PROVIDER_STATUS_RUNNING;
}
/* Check if provider has finished on this client */
static inline bool
is_provider_done(struct auth_client *auth, uint32_t provider)
{
return get_provider_status(auth, provider) == PROVIDER_STATUS_DONE;
}
/* Check if provider doesn't exist or has finished on this client */
static inline bool
run_after_provider(struct auth_client *auth, const char *name)
{
uint32_t id;
if (get_provider_id(name, &id)) {
return get_provider_status(auth, id) == PROVIDER_STATUS_DONE;
} else {
return true;
}
}
/* Get provider auth client data */
static inline void *
get_provider_data(struct auth_client *auth, uint32_t id)
{
return auth->data[id].data;
}
/* Set provider auth client data */
static inline void
set_provider_data(struct auth_client *auth, uint32_t id, void *data)
{
auth->data[id].data = data;
}
/* Set timeout relative to current time on provider
* When the timeout lapses, the provider's timeout call will execute */
static inline void
set_provider_timeout_relative(struct auth_client *auth, uint32_t id, time_t timeout)
{
auth->data[id].timeout = timeout + rb_current_time();
}
/* Set timeout value in absolute time (Unix timestamp)
* When the timeout lapses, the provider's timeout call will execute */
static inline void
set_provider_timeout_absolute(struct auth_client *auth, uint32_t id, time_t timeout)
{
auth->data[id].timeout = timeout;
}
/* Get the timeout value for the provider */
static inline time_t
get_provider_timeout(struct auth_client *auth, uint32_t id)
{
return auth->data[id].timeout;
}
#endif /* __SOLANUM_AUTHD_PROVIDER_H__ */

608
authd/providers/dnsbl.c Normal file
View file

@ -0,0 +1,608 @@
/*
* Solanum: a slightly advanced ircd
* dnsbl.c: Manages DNSBL entries and lookups
*
* Copyright (C) 2006-2011 charybdis development team
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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.
*/
/* Originally written for charybdis circa 2006 (by nenolod?).
* Tweaked for authd. Some functions and structs renamed. Public/private
* interfaces have been shifted around. Some code has been cleaned up too.
* -- Elizafox 24 March 2016
*/
#include "authd.h"
#include "defaults.h"
#include "provider.h"
#include "notice.h"
#include "stdinc.h"
#include "dns.h"
#define SELF_PID (dnsbl_provider.id)
typedef enum filter_t
{
FILTER_ALL = 1,
FILTER_LAST = 2,
} filter_t;
/* dnsbl accepted IP types */
#define IPTYPE_IPV4 1
#define IPTYPE_IPV6 2
/* A configured DNSBL */
struct dnsbl
{
char host[IRCD_RES_HOSTLEN + 1];
char reason[BUFSIZE]; /* Reason template (ircd fills in the blanks) */
uint8_t iptype; /* IP types supported */
rb_dlink_list filters; /* Filters for queries */
bool delete; /* If true delete when no clients */
int refcount; /* When 0 and delete is set, remove this dnsbl */
unsigned int hits;
time_t lastwarning; /* Last warning about garbage replies sent */
};
/* A lookup in progress for a particular DNSBL for a particular client */
struct dnsbl_lookup
{
struct dnsbl *bl; /* dnsbl we're checking */
struct auth_client *auth; /* Client */
struct dns_query *query; /* DNS query pointer */
rb_dlink_node node;
};
/* A dnsbl filter */
struct dnsbl_filter
{
filter_t type; /* Type of filter */
char filter[HOSTIPLEN]; /* The filter itself */
rb_dlink_node node;
};
/* dnsbl user data attached to auth_client instance */
struct dnsbl_user
{
bool started;
rb_dlink_list queries; /* dnsbl queries in flight */
};
/* public interfaces */
static void dnsbls_destroy(void);
static bool dnsbls_start(struct auth_client *);
static inline void dnsbls_generic_cancel(struct auth_client *, const char *);
static void dnsbls_timeout(struct auth_client *);
static void dnsbls_cancel(struct auth_client *);
static void dnsbls_cancel_none(struct auth_client *);
/* private interfaces */
static void unref_dnsbl(struct dnsbl *);
static struct dnsbl *new_dnsbl(const char *, const char *, uint8_t, rb_dlink_list *);
static struct dnsbl *find_dnsbl(const char *);
static bool dnsbl_check_reply(struct dnsbl_lookup *, const char *);
static void dnsbl_dns_callback(const char *, bool, query_type, void *);
static void initiate_dnsbl_dnsquery(struct dnsbl *, struct auth_client *);
/* Variables */
static rb_dlink_list dnsbl_list = { NULL, NULL, 0 };
static int dnsbl_timeout = DNSBL_TIMEOUT_DEFAULT;
/* private interfaces */
static void
unref_dnsbl(struct dnsbl *bl)
{
rb_dlink_node *ptr, *nptr;
bl->refcount--;
if (bl->delete && bl->refcount <= 0)
{
RB_DLINK_FOREACH_SAFE(ptr, nptr, bl->filters.head)
{
rb_dlinkDelete(ptr, &bl->filters);
rb_free(ptr);
}
rb_dlinkFindDestroy(bl, &dnsbl_list);
rb_free(bl);
}
}
static struct dnsbl *
new_dnsbl(const char *name, const char *reason, uint8_t iptype, rb_dlink_list *filters)
{
struct dnsbl *bl;
if (name == NULL || reason == NULL || iptype == 0)
return NULL;
if((bl = find_dnsbl(name)) == NULL)
{
bl = rb_malloc(sizeof(struct dnsbl));
rb_dlinkAddAlloc(bl, &dnsbl_list);
}
else
bl->delete = false;
rb_strlcpy(bl->host, name, IRCD_RES_HOSTLEN + 1);
rb_strlcpy(bl->reason, reason, BUFSIZE);
bl->iptype = iptype;
rb_dlinkMoveList(filters, &bl->filters);
bl->lastwarning = 0;
return bl;
}
static struct dnsbl *
find_dnsbl(const char *name)
{
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, dnsbl_list.head)
{
struct dnsbl *bl = (struct dnsbl *)ptr->data;
if (!strcasecmp(bl->host, name))
return bl;
}
return NULL;
}
static inline bool
dnsbl_check_reply(struct dnsbl_lookup *bllookup, const char *ipaddr)
{
struct dnsbl *bl = bllookup->bl;
const char *lastoctet;
rb_dlink_node *ptr;
/* No filters and entry found - thus positive match */
if (!rb_dlink_list_length(&bl->filters))
return true;
/* Below will prolly have to change if IPv6 address replies are sent back */
if ((lastoctet = strrchr(ipaddr, '.')) == NULL || *(++lastoctet) == '\0')
goto blwarn;
RB_DLINK_FOREACH(ptr, bl->filters.head)
{
struct dnsbl_filter *filter = ptr->data;
const char *cmpstr;
if (filter->type == FILTER_ALL)
cmpstr = ipaddr;
else if (filter->type == FILTER_LAST)
cmpstr = lastoctet;
else
{
warn_opers(L_CRIT, "dnsbl: Unknown dnsbl filter type (host %s): %d",
bl->host, filter->type);
exit(EX_PROVIDER_ERROR);
}
if (strcmp(cmpstr, filter->filter) == 0)
/* Match! */
return true;
}
return false;
blwarn:
if (bl->lastwarning + 3600 < rb_current_time())
{
warn_opers(L_WARN, "Garbage/undecipherable reply received from dnsbl %s (reply %s)",
bl->host, ipaddr);
bl->lastwarning = rb_current_time();
}
return false;
}
static void
dnsbl_dns_callback(const char *result, bool status, query_type type, void *data)
{
struct dnsbl_lookup *bllookup = (struct dnsbl_lookup *)data;
struct dnsbl_user *bluser;
struct dnsbl *bl;
struct auth_client *auth;
lrb_assert(bllookup != NULL);
lrb_assert(bllookup->auth != NULL);
bl = bllookup->bl;
auth = bllookup->auth;
if((bluser = get_provider_data(auth, SELF_PID)) == NULL)
return;
if (result != NULL && status && dnsbl_check_reply(bllookup, result))
{
/* Match found, so proceed no further */
bl->hits++;
reject_client(auth, SELF_PID, bl->host, bl->reason);
dnsbls_cancel(auth);
return;
}
unref_dnsbl(bl);
cancel_query(bllookup->query); /* Ignore future responses */
rb_dlinkDelete(&bllookup->node, &bluser->queries);
rb_free(bllookup);
if(!rb_dlink_list_length(&bluser->queries))
{
/* Done here */
notice_client(auth->cid, "*** No DNSBL entry found for this IP");
rb_free(bluser);
set_provider_data(auth, SELF_PID, NULL);
set_provider_timeout_absolute(auth, SELF_PID, 0);
provider_done(auth, SELF_PID);
auth_client_unref(auth);
}
}
static void
initiate_dnsbl_dnsquery(struct dnsbl *bl, struct auth_client *auth)
{
struct dnsbl_lookup *bllookup = rb_malloc(sizeof(struct dnsbl_lookup));
struct dnsbl_user *bluser = get_provider_data(auth, SELF_PID);
char buf[IRCD_RES_HOSTLEN + 1];
int aftype;
bllookup->bl = bl;
bllookup->auth = auth;
aftype = GET_SS_FAMILY(&auth->c_addr);
if((aftype == AF_INET && (bl->iptype & IPTYPE_IPV4) == 0) ||
(aftype == AF_INET6 && (bl->iptype & IPTYPE_IPV6) == 0))
/* Incorrect dnsbl type for this IP... */
{
rb_free(bllookup);
return;
}
build_rdns(buf, sizeof(buf), &auth->c_addr, bl->host);
bllookup->query = lookup_ip(buf, AF_INET, dnsbl_dns_callback, bllookup);
rb_dlinkAdd(bllookup, &bllookup->node, &bluser->queries);
bl->refcount++;
}
static inline bool
lookup_all_dnsbls(struct auth_client *auth)
{
struct dnsbl_user *bluser = get_provider_data(auth, SELF_PID);
rb_dlink_node *ptr;
int iptype;
if(GET_SS_FAMILY(&auth->c_addr) == AF_INET)
iptype = IPTYPE_IPV4;
else if(GET_SS_FAMILY(&auth->c_addr) == AF_INET6)
iptype = IPTYPE_IPV6;
else
return false;
bluser->started = true;
notice_client(auth->cid, "*** Checking your IP against DNSBLs");
RB_DLINK_FOREACH(ptr, dnsbl_list.head)
{
struct dnsbl *bl = (struct dnsbl *)ptr->data;
if (!bl->delete && (bl->iptype & iptype))
initiate_dnsbl_dnsquery(bl, auth);
}
if(!rb_dlink_list_length(&bluser->queries))
/* None checked. */
return false;
set_provider_timeout_relative(auth, SELF_PID, dnsbl_timeout);
return true;
}
static inline void
delete_dnsbl(struct dnsbl *bl)
{
if (bl->refcount > 0)
bl->delete = true;
else
{
rb_dlinkFindDestroy(bl, &dnsbl_list);
rb_free(bl);
}
}
static void
delete_all_dnsbls(void)
{
rb_dlink_node *ptr, *nptr;
RB_DLINK_FOREACH_SAFE(ptr, nptr, dnsbl_list.head)
{
delete_dnsbl(ptr->data);
}
}
/* public interfaces */
static bool
dnsbls_start(struct auth_client *auth)
{
lrb_assert(get_provider_data(auth, SELF_PID) == NULL);
if (!rb_dlink_list_length(&dnsbl_list)) {
/* Nothing to do... */
provider_done(auth, SELF_PID);
return true;
}
auth_client_ref(auth);
set_provider_data(auth, SELF_PID, rb_malloc(sizeof(struct dnsbl_user)));
if (run_after_provider(auth, "rdns") && run_after_provider(auth, "ident")) {
/* Start the lookup if ident and rdns are finished, or not loaded. */
if (!lookup_all_dnsbls(auth)) {
dnsbls_cancel_none(auth);
return true;
}
}
return true;
}
/* This is called every time a provider is completed as long as we are marked not done */
static void
dnsbls_initiate(struct auth_client *auth, uint32_t provider)
{
struct dnsbl_user *bluser = get_provider_data(auth, SELF_PID);
lrb_assert(provider != SELF_PID);
lrb_assert(!is_provider_done(auth, SELF_PID));
lrb_assert(rb_dlink_list_length(&dnsbl_list) > 0);
if (bluser == NULL || bluser->started) {
/* Nothing to do */
return;
} else if (run_after_provider(auth, "rdns") && run_after_provider(auth, "ident")) {
/* Start the lookup if ident and rdns are finished, or not loaded. */
if (!lookup_all_dnsbls(auth)) {
dnsbls_cancel_none(auth);
}
}
}
static inline void
dnsbls_generic_cancel(struct auth_client *auth, const char *message)
{
rb_dlink_node *ptr, *nptr;
struct dnsbl_user *bluser = get_provider_data(auth, SELF_PID);
if(bluser == NULL)
return;
if(rb_dlink_list_length(&bluser->queries))
{
notice_client(auth->cid, message);
RB_DLINK_FOREACH_SAFE(ptr, nptr, bluser->queries.head)
{
struct dnsbl_lookup *bllookup = ptr->data;
cancel_query(bllookup->query);
unref_dnsbl(bllookup->bl);
rb_dlinkDelete(&bllookup->node, &bluser->queries);
rb_free(bllookup);
}
}
rb_free(bluser);
set_provider_data(auth, SELF_PID, NULL);
set_provider_timeout_absolute(auth, SELF_PID, 0);
provider_done(auth, SELF_PID);
auth_client_unref(auth);
}
static void
dnsbls_timeout(struct auth_client *auth)
{
dnsbls_generic_cancel(auth, "*** No response from DNSBLs");
}
static void
dnsbls_cancel(struct auth_client *auth)
{
dnsbls_generic_cancel(auth, "*** Aborting DNSBL checks");
}
static void
dnsbls_cancel_none(struct auth_client *auth)
{
dnsbls_generic_cancel(auth, "*** Could not check DNSBLs");
}
static void
dnsbls_destroy(void)
{
rb_dictionary_iter iter;
struct auth_client *auth;
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
{
dnsbls_cancel(auth);
/* auth is now invalid as we have no reference */
}
delete_all_dnsbls();
}
static void
add_conf_dnsbl(const char *key, int parc, const char **parv)
{
rb_dlink_list filters = { NULL, NULL, 0 };
char *tmp, *elemlist = rb_strdup(parv[2]);
uint8_t iptype;
if(*elemlist == '*')
goto end;
for(char *elem = rb_strtok_r(elemlist, ",", &tmp); elem; elem = rb_strtok_r(NULL, ",", &tmp))
{
struct dnsbl_filter *filter = rb_malloc(sizeof(struct dnsbl_filter));
int dot_c = 0;
filter_t type = FILTER_LAST;
/* Check dnsbl filter type and for validity */
for(char *c = elem; *c != '\0'; c++)
{
if(*c == '.')
{
if(++dot_c > 3)
{
warn_opers(L_CRIT, "dnsbl: addr_conf_dnsbl got a bad filter (too many octets)");
exit(EX_PROVIDER_ERROR);
}
type = FILTER_ALL;
}
else if(!isdigit(*c))
{
warn_opers(L_CRIT, "dnsbl: addr_conf_dnsbl got a bad filter (invalid character in dnsbl filter: %c)",
*c);
exit(EX_PROVIDER_ERROR);
}
}
if(dot_c > 0 && dot_c < 3)
{
warn_opers(L_CRIT, "dnsbl: addr_conf_dnsbl got a bad filter (insufficient octets)");
exit(EX_PROVIDER_ERROR);
}
filter->type = type;
rb_strlcpy(filter->filter, elem, sizeof(filter->filter));
rb_dlinkAdd(filter, &filter->node, &filters);
}
end:
rb_free(elemlist);
iptype = atoi(parv[1]) & 0x3;
if(new_dnsbl(parv[0], parv[3], iptype, &filters) == NULL)
{
warn_opers(L_CRIT, "dnsbl: addr_conf_dnsbl got a malformed dnsbl");
exit(EX_PROVIDER_ERROR);
}
}
static void
del_conf_dnsbl(const char *key, int parc, const char **parv)
{
struct dnsbl *bl = find_dnsbl(parv[0]);
if(bl == NULL)
{
/* Not fatal for now... */
warn_opers(L_WARN, "dnsbl: tried to remove nonexistent dnsbl %s", parv[0]);
return;
}
delete_dnsbl(bl);
}
static void
del_conf_dnsbl_all(const char *key, int parc, const char **parv)
{
delete_all_dnsbls();
}
static void
add_conf_dnsbl_timeout(const char *key, int parc, const char **parv)
{
int timeout = atoi(parv[0]);
if(timeout < 0)
{
warn_opers(L_CRIT, "dnsbl: dnsbl timeout < 0 (value: %d)", timeout);
exit(EX_PROVIDER_ERROR);
}
dnsbl_timeout = timeout;
}
#if 0
static void
dnsbl_stats(uint32_t rid, char letter)
{
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, dnsbl_list.head)
{
struct dnsbl *bl = ptr->data;
if(bl->delete)
continue;
stats_result(rid, letter, "%s %hhu %u", bl->host, bl->iptype, bl->hits);
}
stats_done(rid, letter);
}
#endif
struct auth_opts_handler dnsbl_options[] =
{
{ "rbl", 4, add_conf_dnsbl },
{ "rbl_del", 1, del_conf_dnsbl },
{ "rbl_del_all", 0, del_conf_dnsbl_all },
{ "rbl_timeout", 1, add_conf_dnsbl_timeout },
{ NULL, 0, NULL },
};
struct auth_provider dnsbl_provider =
{
.name = "dnsbl",
.letter = 'B',
.destroy = dnsbls_destroy,
.start = dnsbls_start,
.cancel = dnsbls_cancel,
.timeout = dnsbls_timeout,
.completed = dnsbls_initiate,
.opt_handlers = dnsbl_options,
/* .stats_handler = { 'B', dnsbl_stats }, */
};

387
authd/providers/ident.c Normal file
View file

@ -0,0 +1,387 @@
/* authd/providers/ident.c - ident lookup provider for authd
* Copyright (c) 2016 Elizabeth Myers <elizabeth@interlinked.me>
*
* 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.
*/
/* Largely adapted from old s_auth.c, but reworked for authd. rDNS code
* moved to its own provider.
*
* --Elizafox 13 March 2016
*/
#include "stdinc.h"
#include "defaults.h"
#include "match.h"
#include "authd.h"
#include "notice.h"
#include "provider.h"
#include "res.h"
#define SELF_PID (ident_provider.id)
#define IDENT_BUFSIZE 128
struct ident_query
{
rb_fde_t *F; /* Our FD */
};
/* Goinked from old s_auth.c --Elizafox */
static const char *messages[] =
{
"*** Checking Ident",
"*** Got Ident response",
"*** No Ident response",
"*** Cannot verify ident validity, ignoring ident",
"*** Ident disabled, not checking ident",
};
typedef enum
{
REPORT_LOOKUP,
REPORT_FOUND,
REPORT_FAIL,
REPORT_INVALID,
REPORT_DISABLED,
} ident_message;
static CNCB ident_connected;
static PF read_ident_reply;
static void client_fail(struct auth_client *auth, ident_message message);
static void client_success(struct auth_client *auth);
static char * get_valid_ident(char *buf);
static int ident_timeout = IDENT_TIMEOUT_DEFAULT;
static bool ident_enable = true;
/*
* ident_connected() - deal with the result of rb_connect_tcp()
*
* If the connection failed, we simply close the auth fd and report
* a failure. If the connection suceeded send the ident server a query
* giving "theirport , ourport". The write is only attempted *once* so
* it is deemed to be a fail if the entire write doesn't write all the
* data given. This shouldnt be a problem since the socket should have
* a write buffer far greater than this message to store it in should
* problems arise. -avalon
*/
static void
ident_connected(rb_fde_t *F __unused, int error, void *data)
{
struct auth_client *auth = data;
struct ident_query *query;
char authbuf[32];
int authlen;
lrb_assert(auth != NULL);
query = get_provider_data(auth, SELF_PID);
lrb_assert(query != NULL);
/* Check the error */
if(error != RB_OK)
{
/* We had an error during connection :( */
client_fail(auth, REPORT_FAIL);
return;
}
snprintf(authbuf, sizeof(authbuf), "%u , %u\r\n",
auth->c_port, auth->l_port);
authlen = strlen(authbuf);
if(rb_write(query->F, authbuf, authlen) != authlen)
{
client_fail(auth, REPORT_FAIL);
return;
}
read_ident_reply(query->F, auth);
}
static void
read_ident_reply(rb_fde_t *F, void *data)
{
struct auth_client *auth = data;
char buf[IDENT_BUFSIZE + 1] = { 0 }; /* buffer to read auth reply into */
ident_message message = REPORT_FAIL;
char *s = NULL;
char *t = NULL;
ssize_t len;
int count;
len = rb_read(F, buf, IDENT_BUFSIZE);
if(len < 0 && rb_ignore_errno(errno))
{
rb_setselect(F, RB_SELECT_READ, read_ident_reply, auth);
return;
}
if(len > 0)
{
if((s = get_valid_ident(buf)) != NULL)
{
t = auth->username;
while (*s == '~' || *s == '^')
s++;
for (count = USERLEN; *s && count; s++)
{
if(*s == '@' || *s == '\r' || *s == '\n')
break;
if(*s != ' ' && *s != ':' && *s != '[')
{
*t++ = *s;
count--;
}
}
*t = '\0';
}
else
message = REPORT_INVALID;
}
if (*auth->username == '\0')
{
auth->username[0] = '*';
auth->username[1] = '\0';
}
if(s == NULL)
client_fail(auth, message);
else
client_success(auth);
}
static void
client_fail(struct auth_client *auth, ident_message report)
{
struct ident_query *query = get_provider_data(auth, SELF_PID);
lrb_assert(query != NULL);
rb_strlcpy(auth->username, "*", sizeof(auth->username));
if(query->F != NULL)
rb_close(query->F);
rb_free(query);
set_provider_data(auth, SELF_PID, NULL);
set_provider_timeout_absolute(auth, SELF_PID, 0);
notice_client(auth->cid, messages[report]);
provider_done(auth, SELF_PID);
auth_client_unref(auth);
}
static void
client_success(struct auth_client *auth)
{
struct ident_query *query = get_provider_data(auth, SELF_PID);
lrb_assert(query != NULL);
if(query->F != NULL)
rb_close(query->F);
rb_free(query);
set_provider_data(auth, SELF_PID, NULL);
set_provider_timeout_absolute(auth, SELF_PID, 0);
notice_client(auth->cid, messages[REPORT_FOUND]);
provider_done(auth, SELF_PID);
auth_client_unref(auth);
}
/* get_valid_ident
* parse ident query reply from identd server
*
* Taken from old s_auth.c --Elizafox
*
* Inputs - pointer to ident buf
* Outputs - NULL if no valid ident found, otherwise pointer to name
* Side effects - None
*/
static char *
get_valid_ident(char *buf)
{
int remp = 0;
int locp = 0;
char *colon1Ptr;
char *colon2Ptr;
char *colon3Ptr;
char *commaPtr;
char *remotePortString;
/* All this to get rid of a sscanf() fun. */
remotePortString = buf;
colon1Ptr = strchr(remotePortString, ':');
if(!colon1Ptr)
return NULL;
*colon1Ptr = '\0';
colon1Ptr++;
colon2Ptr = strchr(colon1Ptr, ':');
if(!colon2Ptr)
return NULL;
*colon2Ptr = '\0';
colon2Ptr++;
commaPtr = strchr(remotePortString, ',');
if(!commaPtr)
return NULL;
*commaPtr = '\0';
commaPtr++;
remp = atoi(remotePortString);
if(!remp)
return NULL;
locp = atoi(commaPtr);
if(!locp)
return NULL;
/* look for USERID bordered by first pair of colons */
if(!strstr(colon1Ptr, "USERID"))
return NULL;
colon3Ptr = strchr(colon2Ptr, ':');
if(!colon3Ptr)
return NULL;
*colon3Ptr = '\0';
colon3Ptr++;
return (colon3Ptr);
}
static void
ident_destroy(void)
{
struct auth_client *auth;
rb_dictionary_iter iter;
/* Nuke all ident queries */
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
{
if(get_provider_data(auth, SELF_PID) != NULL)
client_fail(auth, REPORT_FAIL);
/* auth is now invalid as we have no reference */
}
}
static bool
ident_start(struct auth_client *auth)
{
struct ident_query *query = rb_malloc(sizeof(struct ident_query));
struct rb_sockaddr_storage l_addr, c_addr;
int family = GET_SS_FAMILY(&auth->c_addr);
lrb_assert(get_provider_data(auth, SELF_PID) == NULL);
if(!ident_enable)
{
rb_free(query);
notice_client(auth->cid, messages[REPORT_DISABLED]);
provider_done(auth, SELF_PID);
return true;
}
auth_client_ref(auth);
notice_client(auth->cid, messages[REPORT_LOOKUP]);
set_provider_data(auth, SELF_PID, query);
set_provider_timeout_relative(auth, SELF_PID, ident_timeout);
if((query->F = rb_socket(family, SOCK_STREAM, auth->protocol, "ident")) == NULL)
{
warn_opers(L_WARN, "Could not create ident socket: %s", strerror(errno));
client_fail(auth, REPORT_FAIL);
return true; /* Not a fatal error */
}
/* Build sockaddr_storages for rb_connect_tcp below */
l_addr = auth->l_addr;
c_addr = auth->c_addr;
SET_SS_PORT(&l_addr, 0);
SET_SS_PORT(&c_addr, htons(113));
rb_connect_tcp(query->F, (struct sockaddr *)&c_addr,
(struct sockaddr *)&l_addr,
ident_connected,
auth, ident_timeout);
return true;
}
static void
ident_cancel(struct auth_client *auth)
{
struct ident_query *query = get_provider_data(auth, SELF_PID);
if(query != NULL)
client_fail(auth, REPORT_FAIL);
}
static void
add_conf_ident_timeout(const char *key __unused, int parc __unused, const char **parv)
{
int timeout = atoi(parv[0]);
if(timeout < 0)
{
warn_opers(L_CRIT, "Ident: ident timeout < 0 (value: %d)", timeout);
exit(EX_PROVIDER_ERROR);
}
ident_timeout = timeout;
}
static void
set_ident_enabled(const char *key __unused, int parc __unused, const char **parv)
{
ident_enable = (*parv[0] == '1');
}
struct auth_opts_handler ident_options[] =
{
{ "ident_timeout", 1, add_conf_ident_timeout },
{ "ident_enabled", 1, set_ident_enabled },
{ NULL, 0, NULL },
};
struct auth_provider ident_provider =
{
.name = "ident",
.letter = 'I',
.start = ident_start,
.destroy = ident_destroy,
.cancel = ident_cancel,
.timeout = ident_cancel,
.opt_handlers = ident_options,
};

921
authd/providers/opm.c Normal file
View file

@ -0,0 +1,921 @@
/* authd/providers/opm.c - small open proxy monitor
* Copyright (c) 2016 Elizabeth Myers <elizabeth@interlinked.me>
*
* 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 "stdinc.h"
#include "rb_lib.h"
#include "defaults.h"
#include "setup.h"
#include "authd.h"
#include "notice.h"
#include "provider.h"
#include <netinet/tcp.h> // TCP_NODELAY
#define SELF_PID (opm_provider.id)
#define OPM_READSIZE 128
typedef enum protocol_t
{
PROTO_NONE,
PROTO_SOCKS4,
PROTO_SOCKS5,
PROTO_HTTP_CONNECT,
PROTO_HTTPS_CONNECT,
} protocol_t;
/* Lookup data associated with auth client */
struct opm_lookup
{
rb_dlink_list scans; /* List of scans */
bool in_progress;
};
struct opm_scan;
typedef void (*opm_callback_t)(struct opm_scan *);
/* A proxy scanner */
struct opm_proxy
{
char note[16];
protocol_t proto;
uint16_t port;
bool ssl; /* Connect to proxy with SSL */
bool ipv6; /* Proxy supports IPv6 */
opm_callback_t callback;
rb_dlink_node node;
};
/* A listener for proxy replies */
struct opm_listener
{
char ip[HOSTIPLEN];
uint16_t port;
struct rb_sockaddr_storage addr;
rb_fde_t *F;
};
/* An individual proxy scan */
struct opm_scan
{
struct auth_client *auth;
rb_fde_t *F; /* fd for scan */
struct opm_proxy *proxy; /* Associated proxy */
struct opm_listener *listener; /* Associated listener */
rb_dlink_node node;
};
/* Proxies that we scan for */
static rb_dlink_list proxy_scanners;
static ACCB accept_opm;
static PF read_opm_reply;
static CNCB opm_connected;
static void opm_cancel(struct auth_client *auth);
static bool create_listener(const char *ip, uint16_t port);
static int opm_timeout = OPM_TIMEOUT_DEFAULT;
static bool opm_enable = false;
enum
{
LISTEN_IPV4,
LISTEN_IPV6,
LISTEN_LAST,
};
/* IPv4 and IPv6 */
static struct opm_listener listeners[LISTEN_LAST];
static inline protocol_t
get_protocol_from_string(const char *str)
{
if(strcasecmp(str, "socks4") == 0)
return PROTO_SOCKS4;
else if(strcasecmp(str, "socks5") == 0)
return PROTO_SOCKS5;
else if(strcasecmp(str, "httpconnect") == 0)
return PROTO_HTTP_CONNECT;
else if(strcasecmp(str, "httpsconnect") == 0)
return PROTO_HTTPS_CONNECT;
else
return PROTO_NONE;
}
static inline struct opm_proxy *
find_proxy_scanner(protocol_t proto, uint16_t port)
{
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, proxy_scanners.head)
{
struct opm_proxy *proxy = ptr->data;
if(proxy->proto == proto && proxy->port == port)
return proxy;
}
return NULL;
}
/* This is called when an open proxy connects to us */
static void
read_opm_reply(rb_fde_t *F, void *data)
{
rb_dlink_node *ptr;
struct auth_client *auth = data;
struct opm_lookup *lookup;
char readbuf[OPM_READSIZE];
ssize_t len;
lrb_assert(auth != NULL);
lookup = get_provider_data(auth, SELF_PID);
lrb_assert(lookup != NULL);
if((len = rb_read(F, readbuf, sizeof(readbuf))) < 0 && rb_ignore_errno(errno))
{
rb_setselect(F, RB_SELECT_READ, read_opm_reply, auth);
return;
}
else if(len <= 0)
{
/* Dead */
rb_close(F);
return;
}
RB_DLINK_FOREACH(ptr, proxy_scanners.head)
{
struct opm_proxy *proxy = ptr->data;
if(strncmp(proxy->note, readbuf, strlen(proxy->note)) == 0)
{
rb_dlink_node *ptr, *nptr;
/* Cancel outstanding lookups */
RB_DLINK_FOREACH_SAFE(ptr, nptr, lookup->scans.head)
{
struct opm_scan *scan = ptr->data;
rb_close(scan->F);
rb_free(scan);
}
/* No longer needed, client is going away */
rb_free(lookup);
reject_client(auth, SELF_PID, readbuf, "Open proxy detected");
break;
}
}
rb_close(F);
}
static void
accept_opm(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t len, void *data)
{
struct auth_client *auth = NULL;
struct opm_listener *listener = data;
struct rb_sockaddr_storage localaddr;
unsigned int llen = sizeof(struct rb_sockaddr_storage);
rb_dictionary_iter iter;
if(status != 0 || listener == NULL)
{
rb_close(F);
return;
}
if(getsockname(rb_get_fd(F), (struct sockaddr *)&localaddr, &llen))
{
/* This can happen if the client goes away after accept */
rb_close(F);
return;
}
/* Correlate connection with client(s) */
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
{
if(GET_SS_FAMILY(&auth->c_addr) != GET_SS_FAMILY(&localaddr))
continue;
/* Compare the addresses */
switch(GET_SS_FAMILY(&localaddr))
{
case AF_INET:
{
struct sockaddr_in *s = (struct sockaddr_in *)&localaddr, *c = (struct sockaddr_in *)&auth->c_addr;
if(s->sin_addr.s_addr == c->sin_addr.s_addr)
{
/* Match... check if it's real */
rb_setselect(F, RB_SELECT_READ, read_opm_reply, auth);
return;
}
break;
}
case AF_INET6:
{
struct sockaddr_in6 *s = (struct sockaddr_in6 *)&localaddr, *c = (struct sockaddr_in6 *)&auth->c_addr;
if(IN6_ARE_ADDR_EQUAL(&s->sin6_addr, &c->sin6_addr))
{
rb_setselect(F, RB_SELECT_READ, read_opm_reply, auth);
return;
}
break;
}
default:
warn_opers(L_CRIT, "OPM: unknown address type in listen function");
exit(EX_PROVIDER_ERROR);
}
}
/* We don't care about the socket if we get here */
rb_close(F);
}
/* Scanners */
static void
opm_connected(rb_fde_t *F, int error, void *data)
{
struct opm_scan *scan = data;
struct opm_proxy *proxy = scan->proxy;
struct auth_client *auth = scan->auth;
struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
if(error || !opm_enable)
{
//notice_client(scan->auth->cid, "*** Scan not connected: %s", proxy->note);
goto end;
}
switch(GET_SS_FAMILY(&auth->c_addr))
{
case AF_INET:
if(listeners[LISTEN_IPV4].F == NULL)
/* They cannot respond to us */
goto end;
break;
case AF_INET6:
if(!proxy->ipv6)
/* Welp, too bad */
goto end;
if(listeners[LISTEN_IPV6].F == NULL)
/* They cannot respond to us */
goto end;
break;
default:
goto end;
}
proxy->callback(scan);
end:
rb_close(scan->F);
rb_dlinkDelete(&scan->node, &lookup->scans);
rb_free(scan);
}
static void
socks4_connected(struct opm_scan *scan)
{
uint8_t sendbuf[9]; /* Size we're building */
uint8_t *c = sendbuf;
memcpy(c, "\x04\x01", 2); c += 2; /* Socks version 4, connect command */
memcpy(c, &(((struct sockaddr_in *)&scan->listener->addr)->sin_port), 2); c += 2; /* Port */
memcpy(c, &(((struct sockaddr_in *)&scan->listener->addr)->sin_addr.s_addr), 4); c += 4; /* Address */
*c = '\x00'; /* No userid */
/* Send header */
if(rb_write(scan->F, sendbuf, sizeof(sendbuf)) < 0)
return;
/* Send note */
if(rb_write(scan->F, scan->proxy->note, strlen(scan->proxy->note) + 1) < 0)
return;
}
static void
socks5_connected(struct opm_scan *scan)
{
struct auth_client *auth = scan->auth;
uint8_t sendbuf[25]; /* Size we're building */
uint8_t *c = sendbuf;
/* Build the version header and socks request
* version header (3 bytes): version, number of auth methods, auth type (0 for none)
* connect req (3 bytes): version, command (1 = connect), reserved (0)
*/
memcpy(c, "\x05\x01\x00\x05\x01\x00", 6); c += 6;
switch(GET_SS_FAMILY(&auth->c_addr))
{
case AF_INET:
*(c++) = '\x01'; /* Address type (1 = IPv4) */
memcpy(c, &(((struct sockaddr_in *)&scan->listener->addr)->sin_addr.s_addr), 4); c += 4; /* Address */
memcpy(c, &(((struct sockaddr_in *)&scan->listener->addr)->sin_port), 2); c += 2; /* Port */
break;
case AF_INET6:
*(c++) = '\x04'; /* Address type (4 = IPv6) */
memcpy(c, ((struct sockaddr_in6 *)&scan->listener->addr)->sin6_addr.s6_addr, 16); c += 16; /* Address */
memcpy(c, &(((struct sockaddr_in6 *)&scan->listener->addr)->sin6_port), 2); c += 2; /* Port */
break;
default:
return;
}
/* Send header */
if(rb_write(scan->F, sendbuf, (size_t)(sendbuf - c)) <= 0)
return;
/* Now the note in a separate write */
if(rb_write(scan->F, scan->proxy->note, strlen(scan->proxy->note) + 1) <= 0)
return;
}
static void
http_connect_connected(struct opm_scan *scan)
{
char sendbuf[128]; /* A bit bigger than we need but better safe than sorry */
/* Simple enough to build */
snprintf(sendbuf, sizeof(sendbuf), "CONNECT %s:%hu HTTP/1.0\r\n\r\n", scan->listener->ip, scan->listener->port);
/* Send request */
if(rb_write(scan->F, sendbuf, strlen(sendbuf)) <= 0)
return;
/* Now the note in a separate write */
if(rb_write(scan->F, scan->proxy->note, strlen(scan->proxy->note) + 1) <= 0)
return;
/* MiroTik needs this, and as a separate write */
if(rb_write(scan->F, "\r\n", 2) <= 0)
return;
}
/* Establish connections */
static inline void
establish_connection(struct auth_client *auth, struct opm_proxy *proxy)
{
struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
struct opm_scan *scan = rb_malloc(sizeof(struct opm_scan));
struct opm_listener *listener;
struct rb_sockaddr_storage c_a, l_a;
int opt = 1;
lrb_assert(lookup != NULL);
if(GET_SS_FAMILY(&auth->c_addr) == AF_INET6)
{
if(proxy->proto == PROTO_SOCKS4)
{
/* SOCKS4 doesn't support IPv6 */
rb_free(scan);
return;
}
listener = &listeners[LISTEN_IPV6];
}
else
listener = &listeners[LISTEN_IPV4];
if(listener->F == NULL)
{
/* We can't respond */
rb_free(scan);
return;
}
c_a = auth->c_addr; /* Client */
l_a = listener->addr; /* Listener (connect using its IP) */
scan->auth = auth;
scan->proxy = proxy;
scan->listener = listener;
if((scan->F = rb_socket(GET_SS_FAMILY(&auth->c_addr), SOCK_STREAM, 0, proxy->note)) == NULL)
{
warn_opers(L_WARN, "OPM: could not create OPM socket (proto %s): %s", proxy->note, strerror(errno));
rb_free(scan);
return;
}
/* Disable Nagle's algorithim - buffering could affect scans */
(void)setsockopt(rb_get_fd(scan->F), IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(opt));
SET_SS_PORT(&l_a, 0);
SET_SS_PORT(&c_a, htons(proxy->port));
rb_dlinkAdd(scan, &scan->node, &lookup->scans);
if(!proxy->ssl)
rb_connect_tcp(scan->F,
(struct sockaddr *)&c_a,
(struct sockaddr *)&l_a,
opm_connected, scan, opm_timeout);
else
rb_connect_tcp_ssl(scan->F,
(struct sockaddr *)&c_a,
(struct sockaddr *)&l_a,
opm_connected, scan, opm_timeout);
}
static bool
create_listener(const char *ip, uint16_t port)
{
struct auth_client *auth;
struct opm_listener *listener;
struct rb_sockaddr_storage addr;
rb_dictionary_iter iter;
rb_fde_t *F;
int opt = 1;
if(!rb_inet_pton_sock(ip, &addr))
{
warn_opers(L_CRIT, "OPM: got a bad listener: %s:%hu", ip, port);
exit(EX_PROVIDER_ERROR);
}
SET_SS_PORT(&addr, htons(port));
if(GET_SS_FAMILY(&addr) == AF_INET6)
{
struct sockaddr_in6 *a1, *a2;
listener = &listeners[LISTEN_IPV6];
a1 = (struct sockaddr_in6 *)&addr;
a2 = (struct sockaddr_in6 *)&listener->addr;
if(IN6_ARE_ADDR_EQUAL(&a1->sin6_addr, &a2->sin6_addr) &&
GET_SS_PORT(&addr) == GET_SS_PORT(&listener->addr) &&
listener->F != NULL)
{
/* Listener already exists */
return false;
}
}
else
{
struct sockaddr_in *a1, *a2;
listener = &listeners[LISTEN_IPV4];
a1 = (struct sockaddr_in *)&addr;
a2 = (struct sockaddr_in *)&listener->addr;
if(a1->sin_addr.s_addr == a2->sin_addr.s_addr &&
GET_SS_PORT(&addr) == GET_SS_PORT(&listener->addr) &&
listener->F != NULL)
{
/* Listener already exists */
return false;
}
}
if((F = rb_socket(GET_SS_FAMILY(&addr), SOCK_STREAM, 0, "OPM listener socket")) == NULL)
{
/* This shouldn't fail, or we have big problems... */
warn_opers(L_CRIT, "OPM: cannot create socket: %s", strerror(errno));
exit(EX_PROVIDER_ERROR);
}
if(setsockopt(rb_get_fd(F), SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)))
{
/* This shouldn't fail either... */
warn_opers(L_CRIT, "OPM: cannot set options on socket: %s", strerror(errno));
exit(EX_PROVIDER_ERROR);
}
if(bind(rb_get_fd(F), (struct sockaddr *)&addr, GET_SS_LEN(&addr)))
{
/* Shit happens, let's not cripple authd over /this/ since it could be user error */
warn_opers(L_WARN, "OPM: cannot bind on socket: %s", strerror(errno));
rb_close(F);
return false;
}
if(rb_listen(F, SOMAXCONN, false)) /* deferred accept could interfere with detection */
{
/* Again, could be user error */
warn_opers(L_WARN, "OPM: cannot listen on socket: %s", strerror(errno));
rb_close(F);
return false;
}
/* From this point forward we assume we have a listener */
if(listener->F != NULL)
/* Close old listener */
rb_close(listener->F);
listener->F = F;
/* Cancel clients that may be on old listener
* XXX - should rescan clients that need it
*/
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
{
opm_cancel(auth);
/* auth is now invalid as we have no reference */
}
/* Copy data */
rb_strlcpy(listener->ip, ip, sizeof(listener->ip));
listener->port = port;
listener->addr = addr;
opm_enable = true; /* Implicitly set this to true for now if we have a listener */
rb_accept_tcp(listener->F, NULL, accept_opm, listener);
return true;
}
static void
opm_scan(struct auth_client *auth)
{
rb_dlink_node *ptr;
struct opm_lookup *lookup;
lrb_assert(auth != NULL);
lookup = get_provider_data(auth, SELF_PID);
set_provider_timeout_relative(auth, SELF_PID, opm_timeout);
lookup->in_progress = true;
RB_DLINK_FOREACH(ptr, proxy_scanners.head)
{
struct opm_proxy *proxy = ptr->data;
//notice_client(auth->cid, "*** Scanning for proxy type %s", proxy->note);
establish_connection(auth, proxy);
}
notice_client(auth->cid, "*** Scanning for open proxies...");
}
/* This is called every time a provider is completed as long as we are marked not done */
static void
opm_initiate(struct auth_client *auth, uint32_t provider)
{
struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
lrb_assert(provider != SELF_PID);
lrb_assert(!is_provider_done(auth, SELF_PID));
lrb_assert(rb_dlink_list_length(&proxy_scanners) > 0);
if (lookup == NULL || lookup->in_progress) {
/* Nothing to do */
return;
} else if (run_after_provider(auth, "rdns") && run_after_provider(auth,"ident")) {
/* Start scanning if ident and rdns are finished, or not loaded. */
opm_scan(auth);
}
}
static bool
opm_start(struct auth_client *auth)
{
lrb_assert(get_provider_data(auth, SELF_PID) == NULL);
if (!opm_enable || rb_dlink_list_length(&proxy_scanners) == 0) {
/* Nothing to do... */
provider_done(auth, SELF_PID);
return true;
}
auth_client_ref(auth);
set_provider_data(auth, SELF_PID, rb_malloc(sizeof(struct opm_lookup)));
if (run_after_provider(auth, "rdns") && run_after_provider(auth, "ident")) {
/* Start scanning if ident and rdns are finished, or not loaded. */
opm_scan(auth);
}
return true;
}
static void
opm_cancel(struct auth_client *auth)
{
struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
if(lookup != NULL)
{
rb_dlink_node *ptr, *nptr;
notice_client(auth->cid, "*** Did not detect open proxies");
RB_DLINK_FOREACH_SAFE(ptr, nptr, lookup->scans.head)
{
struct opm_scan *scan = ptr->data;
rb_close(scan->F);
rb_free(scan);
}
rb_free(lookup);
set_provider_data(auth, SELF_PID, NULL);
set_provider_timeout_absolute(auth, SELF_PID, 0);
provider_done(auth, SELF_PID);
auth_client_unref(auth);
}
}
static void
opm_destroy(void)
{
struct auth_client *auth;
rb_dictionary_iter iter;
/* Nuke all opm lookups */
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
{
opm_cancel(auth);
/* auth is now invalid as we have no reference */
}
}
static void
add_conf_opm_timeout(const char *key __unused, int parc __unused, const char **parv)
{
int timeout = atoi(parv[0]);
if(timeout < 0)
{
warn_opers(L_CRIT, "opm: opm timeout < 0 (value: %d)", timeout);
return;
}
opm_timeout = timeout;
}
static void
set_opm_enabled(const char *key __unused, int parc __unused, const char **parv)
{
bool enable = (*parv[0] == '1');
if(!enable)
{
if(listeners[LISTEN_IPV4].F != NULL || listeners[LISTEN_IPV6].F != NULL)
{
struct auth_client *auth;
rb_dictionary_iter iter;
/* Close the listening socket */
if(listeners[LISTEN_IPV4].F != NULL)
rb_close(listeners[LISTEN_IPV4].F);
if(listeners[LISTEN_IPV6].F != NULL)
rb_close(listeners[LISTEN_IPV6].F);
listeners[LISTEN_IPV4].F = listeners[LISTEN_IPV6].F = NULL;
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
{
opm_cancel(auth);
/* auth is now invalid as we have no reference */
}
}
}
else
{
if(listeners[LISTEN_IPV4].ip[0] != '\0' && listeners[LISTEN_IPV4].port != 0)
{
if(listeners[LISTEN_IPV4].F == NULL)
/* Pre-configured IP/port, just re-establish */
create_listener(listeners[LISTEN_IPV4].ip, listeners[LISTEN_IPV4].port);
}
if(listeners[LISTEN_IPV6].ip[0] != '\0' && listeners[LISTEN_IPV6].port != 0)
{
if(listeners[LISTEN_IPV6].F == NULL)
/* Pre-configured IP/port, just re-establish */
create_listener(listeners[LISTEN_IPV6].ip, listeners[LISTEN_IPV6].port);
}
}
opm_enable = enable;
}
static void
set_opm_listener(const char *key __unused, int parc __unused, const char **parv)
{
const char *ip = parv[0];
int iport = atoi(parv[1]);
if(iport > 65535 || iport <= 0)
{
warn_opers(L_CRIT, "OPM: got a bad listener: %s:%s", parv[0], parv[1]);
exit(EX_PROVIDER_ERROR);
}
create_listener(ip, (uint16_t)iport);
}
static void
create_opm_scanner(const char *key __unused, int parc __unused, const char **parv)
{
int iport = atoi(parv[1]);
struct opm_proxy *proxy = rb_malloc(sizeof(struct opm_proxy));
if(iport <= 0 || iport > 65535)
{
warn_opers(L_CRIT, "OPM: got a bad scanner: %s (port %s)", parv[0], parv[1]);
exit(EX_PROVIDER_ERROR);
}
proxy->port = (uint16_t)iport;
switch((proxy->proto = get_protocol_from_string(parv[0])))
{
case PROTO_SOCKS4:
snprintf(proxy->note, sizeof(proxy->note), "socks4:%hu", proxy->port);
proxy->ssl = false;
proxy->callback = socks4_connected;
break;
case PROTO_SOCKS5:
snprintf(proxy->note, sizeof(proxy->note), "socks5:%hu", proxy->port);
proxy->ssl = false;
proxy->callback = socks5_connected;
break;
case PROTO_HTTP_CONNECT:
snprintf(proxy->note, sizeof(proxy->note), "httpconnect:%hu", proxy->port);
proxy->ssl = false;
proxy->callback = http_connect_connected;
break;
case PROTO_HTTPS_CONNECT:
snprintf(proxy->note, sizeof(proxy->note), "httpsconnect:%hu", proxy->port);
proxy->callback = http_connect_connected;
proxy->ssl = true;
break;
default:
warn_opers(L_CRIT, "OPM: got an unknown proxy type: %s (port %hu)", parv[0], proxy->port);
exit(EX_PROVIDER_ERROR);
}
if(find_proxy_scanner(proxy->proto, proxy->port) != NULL)
{
warn_opers(L_CRIT, "OPM: got a duplicate scanner: %s (port %hu)", parv[0], proxy->port);
rb_free(proxy);
return;
}
rb_dlinkAdd(proxy, &proxy->node, &proxy_scanners);
}
static void
delete_opm_scanner(const char *key __unused, int parc __unused, const char **parv)
{
struct auth_client *auth;
struct opm_proxy *proxy;
protocol_t proto = get_protocol_from_string(parv[0]);
int iport = atoi(parv[1]);
rb_dictionary_iter iter;
if(iport <= 0 || iport > 65535)
{
warn_opers(L_CRIT, "OPM: got a bad scanner to delete: %s (port %s)", parv[0], parv[1]);
exit(EX_PROVIDER_ERROR);
}
if(proto == PROTO_NONE)
{
warn_opers(L_CRIT, "OPM: got an unknown proxy type to delete: %s (port %d)", parv[0], iport);
exit(EX_PROVIDER_ERROR);
}
if((proxy = find_proxy_scanner(proto, (uint16_t)iport)) == NULL)
{
warn_opers(L_CRIT, "OPM: cannot find proxy to delete: %s (port %d)", parv[0], iport);
exit(EX_PROVIDER_ERROR);
}
/* Abort remaining clients on this scanner */
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
{
rb_dlink_node *ptr;
struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
if(lookup == NULL)
continue;
auth_client_ref(auth);
RB_DLINK_FOREACH(ptr, lookup->scans.head)
{
struct opm_scan *scan = ptr->data;
if(scan->proxy->port == proxy->port && scan->proxy->proto == proxy->proto)
{
/* Match */
rb_dlinkDelete(&scan->node, &lookup->scans);
rb_free(scan);
if(rb_dlink_list_length(&lookup->scans) == 0)
opm_cancel(auth);
break;
}
}
auth_client_unref(auth);
}
rb_dlinkDelete(&proxy->node, &proxy_scanners);
rb_free(proxy);
if(rb_dlink_list_length(&proxy_scanners) == 0)
opm_enable = false;
}
static void
delete_opm_scanner_all(const char *key __unused, int parc __unused, const char **parv __unused)
{
struct auth_client *auth;
rb_dlink_node *ptr, *nptr;
rb_dictionary_iter iter;
RB_DLINK_FOREACH_SAFE(ptr, nptr, proxy_scanners.head)
{
rb_free(ptr->data);
rb_dlinkDelete(ptr, &proxy_scanners);
}
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
{
opm_cancel(auth);
/* auth is now invalid as we have no reference */
}
opm_enable = false;
}
static void
delete_opm_listener_all(const char *key __unused, int parc __unused, const char **parv __unused)
{
if(listeners[LISTEN_IPV4].F != NULL)
rb_close(listeners[LISTEN_IPV4].F);
if(listeners[LISTEN_IPV6].F != NULL)
rb_close(listeners[LISTEN_IPV6].F);
memset(&listeners, 0, sizeof(listeners));
}
struct auth_opts_handler opm_options[] =
{
{ "opm_timeout", 1, add_conf_opm_timeout },
{ "opm_enabled", 1, set_opm_enabled },
{ "opm_listener", 2, set_opm_listener },
{ "opm_listener_del_all", 0, delete_opm_listener_all },
{ "opm_scanner", 2, create_opm_scanner },
{ "opm_scanner_del", 2, delete_opm_scanner },
{ "opm_scanner_del_all", 0, delete_opm_scanner_all },
{ NULL, 0, NULL },
};
struct auth_provider opm_provider =
{
.name = "opm",
.letter = 'O',
.destroy = opm_destroy,
.start = opm_start,
.cancel = opm_cancel,
.timeout = opm_cancel,
.completed = opm_initiate,
.opt_handlers = opm_options,
};

181
authd/providers/rdns.c Normal file
View file

@ -0,0 +1,181 @@
/* authd/providers/rdns.c - rDNS lookup provider for authd
* Copyright (c) 2016 Elizabeth Myers <elizabeth@interlinked.me>
*
* 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 "stdinc.h"
#include "rb_commio.h"
#include "authd.h"
#include "provider.h"
#include "notice.h"
#include "res.h"
#include "dns.h"
#define SELF_PID (rdns_provider.id)
struct user_query
{
struct dns_query *query; /* Pending DNS query */
};
/* Goinked from old s_auth.c --Elizabeth */
static const char *messages[] =
{
"*** Looking up your hostname...",
"*** Couldn't look up your hostname",
"*** Your hostname is too long, ignoring hostname",
};
typedef enum
{
REPORT_LOOKUP,
REPORT_FAIL,
REPORT_TOOLONG,
} dns_message;
static void client_fail(struct auth_client *auth, dns_message message);
static void client_success(struct auth_client *auth);
static void dns_answer_callback(const char *res, bool status, query_type type, void *data);
static int rdns_timeout = RDNS_TIMEOUT_DEFAULT;
static void
dns_answer_callback(const char *res, bool status, query_type type, void *data)
{
struct auth_client *auth = data;
if(res == NULL || status == false)
client_fail(auth, REPORT_FAIL);
else if(strlen(res) > HOSTLEN)
client_fail(auth, REPORT_TOOLONG);
else
{
rb_strlcpy(auth->hostname, res, HOSTLEN + 1);
client_success(auth);
}
}
static void
client_fail(struct auth_client *auth, dns_message report)
{
struct user_query *query = get_provider_data(auth, SELF_PID);
lrb_assert(query != NULL);
rb_strlcpy(auth->hostname, "*", sizeof(auth->hostname));
notice_client(auth->cid, messages[report]);
cancel_query(query->query);
rb_free(query);
set_provider_data(auth, SELF_PID, NULL);
set_provider_timeout_absolute(auth, SELF_PID, 0);
provider_done(auth, SELF_PID);
auth_client_unref(auth);
}
static void
client_success(struct auth_client *auth)
{
struct user_query *query = get_provider_data(auth, SELF_PID);
lrb_assert(query != NULL);
notice_client(auth->cid, "*** Found your hostname: %s", auth->hostname);
cancel_query(query->query);
rb_free(query);
set_provider_data(auth, SELF_PID, NULL);
set_provider_timeout_absolute(auth, SELF_PID, 0);
provider_done(auth, SELF_PID);
auth_client_unref(auth);
}
static void
rdns_destroy(void)
{
struct auth_client *auth;
rb_dictionary_iter iter;
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
{
if(get_provider_data(auth, SELF_PID) != NULL)
client_fail(auth, REPORT_FAIL);
/* auth is now invalid as we have no reference */
}
}
static bool
rdns_start(struct auth_client *auth)
{
struct user_query *query = rb_malloc(sizeof(struct user_query));
auth_client_ref(auth);
set_provider_data(auth, SELF_PID, query);
set_provider_timeout_relative(auth, SELF_PID, rdns_timeout);
query->query = lookup_hostname(auth->c_ip, dns_answer_callback, auth);
notice_client(auth->cid, messages[REPORT_LOOKUP]);
return true;
}
static void
rdns_cancel(struct auth_client *auth)
{
struct user_query *query = get_provider_data(auth, SELF_PID);
if(query != NULL)
client_fail(auth, REPORT_FAIL);
}
static void
add_conf_dns_timeout(const char *key, int parc, const char **parv)
{
int timeout = atoi(parv[0]);
if(timeout < 0)
{
warn_opers(L_CRIT, "rDNS: DNS timeout < 0 (value: %d)", timeout);
exit(EX_PROVIDER_ERROR);
}
rdns_timeout = timeout;
}
struct auth_opts_handler rdns_options[] =
{
{ "rdns_timeout", 1, add_conf_dns_timeout },
{ NULL, 0, NULL },
};
struct auth_provider rdns_provider =
{
.name = "rdns",
.letter = 'R',
.destroy = rdns_destroy,
.start = rdns_start,
.cancel = rdns_cancel,
.timeout = rdns_cancel,
.opt_handlers = rdns_options,
};

885
authd/res.c Normal file
View file

@ -0,0 +1,885 @@
/*
* A rewrite of Darren Reeds original res.c As there is nothing
* left of Darrens original code, this is now licensed by the hybrid group.
* (Well, some of the function names are the same, and bits of the structs..)
* You can use it where it is useful, free even. Buy us a beer and stuff.
*
* The authors takes no responsibility for any damage or loss
* of property which results from the use of this software.
*
* July 1999 - Rewrote a bunch of stuff here. Change hostent builder code,
* added callbacks and reference counting of returned hostents.
* --Bleep (Thomas Helvey <tomh@inxpress.net>)
*
* This was all needlessly complicated for irc. Simplified. No more hostent
* All we really care about is the IP -> hostname mappings. Thats all.
*
* Apr 28, 2003 --cryogen and Dianora
*
* DNS server flooding lessened, AAAA-or-A lookup removed, ip6.int support
* removed, various robustness fixes
*
* 2006 --jilles and nenolod
*
* Resend queries to other servers if the DNS server replies with an error or
* an invalid response. Also, avoid servers that return errors or invalid
* responses.
*
* October 2012 --mr_flea
*
* ircd-ratbox changes for random IDs merged back in.
*
* January 2016 --kaniini
*/
#include <rb_lib.h>
#include "setup.h"
#include "res.h"
#include "reslib.h"
#if (CHAR_BIT != 8)
#error this code needs to be able to address individual octets
#endif
static PF res_readreply;
#define MAXPACKET 1024 /* rfc sez 512 but we expand names so ... */
#define AR_TTL 600 /* TTL in seconds for dns cache entries */
/* RFC 1104/1105 wasn't very helpful about what these fields
* should be named, so for now, we'll just name them this way.
* we probably should look at what named calls them or something.
*/
#define TYPE_SIZE (size_t)2
#define CLASS_SIZE (size_t)2
#define TTL_SIZE (size_t)4
#define RDLENGTH_SIZE (size_t)2
#define ANSWER_FIXED_SIZE (TYPE_SIZE + CLASS_SIZE + TTL_SIZE + RDLENGTH_SIZE)
struct in6_addr ipv6_addr;
struct in_addr ipv4_addr;
struct reslist
{
rb_dlink_node node;
int id;
time_t ttl;
char type;
char queryname[IRCD_RES_HOSTLEN + 1]; /* name currently being queried */
char retries; /* retry counter */
char sends; /* number of sends (>1 means resent) */
time_t sentat;
time_t timeout;
int lastns; /* index of last server sent to */
struct rb_sockaddr_storage addr;
char *name;
struct DNSQuery *query; /* query callback for this request */
};
static rb_fde_t *res_fd;
static rb_dlink_list request_list = { NULL, NULL, 0 };
static int ns_failure_count[IRCD_MAXNS]; /* timeouts and invalid/failed replies */
static void rem_request(struct reslist *request);
static struct reslist *make_request(struct DNSQuery *query);
static void gethost_byname_type_fqdn(const char *name, struct DNSQuery *query,
int type);
static void do_query_name(struct DNSQuery *query, const char *name, struct reslist *request, int);
static void do_query_number(struct DNSQuery *query, const struct rb_sockaddr_storage *,
struct reslist *request);
static void query_name(struct reslist *request);
static int send_res_msg(const char *buf, int len, int count);
static void resend_query(struct reslist *request);
static int check_question(struct reslist *request, HEADER * header, char *buf, char *eob);
static int proc_answer(struct reslist *request, HEADER * header, char *, char *);
static struct reslist *find_id(int id);
static struct DNSReply *make_dnsreply(struct reslist *request);
static uint16_t generate_random_id(void);
/*
* int
* res_ourserver(inp)
* looks up "inp" in irc_nsaddr_list[]
* returns:
* server ID or -1 for not found
* author:
* paul vixie, 29may94
* revised for ircd, cryogen(stu) may03
* slightly modified for charybdis, mr_flea oct12
*/
static int
res_ourserver(const struct rb_sockaddr_storage *inp)
{
const struct sockaddr_in6 *v6;
const struct sockaddr_in6 *v6in = (const struct sockaddr_in6 *)inp;
const struct sockaddr_in *v4;
const struct sockaddr_in *v4in = (const struct sockaddr_in *)inp;
int ns;
for(ns = 0; ns < irc_nscount; ns++)
{
const struct rb_sockaddr_storage *srv = &irc_nsaddr_list[ns];
v6 = (const struct sockaddr_in6 *)srv;
v4 = (const struct sockaddr_in *)srv;
/* could probably just memcmp(srv, inp, srv.ss_len) here
* but we'll air on the side of caution - stu
*/
switch (GET_SS_FAMILY(srv))
{
case AF_INET6:
if(GET_SS_FAMILY(srv) == GET_SS_FAMILY(inp))
if(v6->sin6_port == v6in->sin6_port)
if((memcmp(&v6->sin6_addr.s6_addr, &v6in->sin6_addr.s6_addr,
sizeof(struct in6_addr)) == 0) ||
(memcmp(&v6->sin6_addr.s6_addr, &in6addr_any,
sizeof(struct in6_addr)) == 0))
return 1;
break;
case AF_INET:
if(GET_SS_FAMILY(srv) == GET_SS_FAMILY(inp))
if(v4->sin_port == v4in->sin_port)
if((v4->sin_addr.s_addr == INADDR_ANY)
|| (v4->sin_addr.s_addr == v4in->sin_addr.s_addr))
return 1;
break;
default:
break;
}
}
return 0;
}
/*
* timeout_query_list - Remove queries from the list which have been
* there too long without being resolved.
*/
static time_t timeout_query_list(time_t now)
{
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
struct reslist *request;
time_t next_time = 0;
time_t timeout = 0;
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, request_list.head)
{
request = ptr->data;
timeout = request->sentat + request->timeout;
if (now >= timeout)
{
ns_failure_count[request->lastns]++;
request->sentat = now;
request->timeout += request->timeout;
resend_query(request);
}
if ((next_time == 0) || timeout < next_time)
{
next_time = timeout;
}
}
return (next_time > now) ? next_time : (now + AR_TTL);
}
/*
* timeout_resolver - check request list
*/
static void timeout_resolver(void *notused)
{
timeout_query_list(rb_current_time());
}
static struct ev_entry *timeout_resolver_ev = NULL;
/*
* start_resolver - do everything we need to read the resolv.conf file
* and initialize the resolver file descriptor if needed
*/
static void start_resolver(void)
{
int i;
irc_res_init();
for (i = 0; i < irc_nscount; i++)
ns_failure_count[i] = 0;
if (res_fd == NULL)
{
if ((res_fd = rb_socket(GET_SS_FAMILY(&irc_nsaddr_list[0]), SOCK_DGRAM, 0,
"UDP resolver socket")) == NULL)
return;
/* At the moment, the resolver FD data is global .. */
rb_setselect(res_fd, RB_SELECT_READ, res_readreply, NULL);
timeout_resolver_ev = rb_event_add("timeout_resolver", timeout_resolver, NULL, 1);
}
}
/*
* init_resolver - initialize resolver and resolver library
*/
void init_resolver(void)
{
#ifdef HAVE_SRAND48
srand48(rb_current_time());
#endif
start_resolver();
}
/*
* restart_resolver - reread resolv.conf, reopen socket
*/
void restart_resolver(void)
{
rb_close(res_fd);
res_fd = NULL;
rb_event_delete(timeout_resolver_ev); /* -ddosen */
start_resolver();
}
/*
* add_local_domain - Add the domain to hostname, if it is missing
* (as suggested by eps@TOASTER.SFSU.EDU)
*/
static void add_local_domain(char *hname, size_t size)
{
/* try to fix up unqualified names */
if (strchr(hname, '.') == NULL)
{
if (irc_domain[0])
{
size_t len = strlen(hname);
if ((strlen(irc_domain) + len + 2) < size)
{
hname[len++] = '.';
strcpy(hname + len, irc_domain);
}
}
}
}
/*
* rem_request - remove a request from the list.
* This must also free any memory that has been allocated for
* temporary storage of DNS results.
*/
static void rem_request(struct reslist *request)
{
rb_dlinkDelete(&request->node, &request_list);
rb_free(request->name);
rb_free(request);
}
/*
* make_request - Create a DNS request record for the server.
*/
static struct reslist *make_request(struct DNSQuery *query)
{
struct reslist *request = rb_malloc(sizeof(struct reslist));
request->sentat = rb_current_time();
request->retries = 3;
request->timeout = 4; /* start at 4 and exponential inc. */
request->query = query;
/*
* generate a unique id
* NOTE: we don't have to worry about converting this to and from
* network byte order, the nameserver does not interpret this value
* and returns it unchanged
*
* we generate an id per request now (instead of per send) to allow
* late replies to be used.
*/
request->id = generate_random_id();
rb_dlinkAdd(request, &request->node, &request_list);
return request;
}
/*
* retryfreq - determine how many queries to wait before resending
* if there have been that many consecutive timeouts
*
* This is a cubic backoff btw, if anyone didn't pick up on it. --Elizafox
*/
static int retryfreq(int timeouts)
{
switch (timeouts)
{
case 1:
return 3;
case 2:
return 9;
case 3:
return 27;
case 4:
return 81;
default:
return 243;
}
}
/*
* send_res_msg - sends msg to a nameserver.
* This should reflect /etc/resolv.conf.
* Returns number of nameserver successfully sent to
* or -1 if no successful sends.
*/
static int send_res_msg(const char *msg, int len, int rcount)
{
int i;
int ns;
static int retrycnt;
retrycnt++;
/* First try a nameserver that seems to work.
* Every once in a while, try a possibly broken one to check
* if it is working again.
*/
for (i = 0; i < irc_nscount; i++)
{
ns = (i + rcount - 1) % irc_nscount;
if (ns_failure_count[ns] && retrycnt % retryfreq(ns_failure_count[ns]))
continue;
if (sendto(rb_get_fd(res_fd), msg, len, 0,
(struct sockaddr *)&(irc_nsaddr_list[ns]),
GET_SS_LEN(&irc_nsaddr_list[ns])) == len)
return ns;
}
/* No known working nameservers, try some broken one. */
for (i = 0; i < irc_nscount; i++)
{
ns = (i + rcount - 1) % irc_nscount;
if (!ns_failure_count[ns])
continue;
if (sendto(rb_get_fd(res_fd), msg, len, 0,
(struct sockaddr *)&(irc_nsaddr_list[ns]),
GET_SS_LEN(&irc_nsaddr_list[ns])) == len)
return ns;
}
return -1;
}
/*
* find_id - find a dns request id (id is determined by dn_mkquery)
*/
static struct reslist *find_id(int id)
{
rb_dlink_node *ptr;
struct reslist *request;
RB_DLINK_FOREACH(ptr, request_list.head)
{
request = ptr->data;
if (request->id == id)
return (request);
}
return (NULL);
}
static uint16_t
generate_random_id(void)
{
uint16_t id;
do
{
rb_get_random(&id, sizeof(id));
if(id == 0xffff)
continue;
}
while(find_id(id));
return id;
}
/*
* gethost_byname_type - get host address from name, adding domain if needed
*/
void gethost_byname_type(const char *name, struct DNSQuery *query, int type)
{
char fqdn[IRCD_RES_HOSTLEN + 1];
assert(name != 0);
rb_strlcpy(fqdn, name, sizeof fqdn);
add_local_domain(fqdn, IRCD_RES_HOSTLEN);
gethost_byname_type_fqdn(fqdn, query, type);
}
/*
* gethost_byname_type_fqdn - get host address from fqdn
*/
static void gethost_byname_type_fqdn(const char *name, struct DNSQuery *query,
int type)
{
assert(name != 0);
do_query_name(query, name, NULL, type);
}
/*
* gethost_byaddr - get host name from address
*/
void gethost_byaddr(const struct rb_sockaddr_storage *addr, struct DNSQuery *query)
{
do_query_number(query, addr, NULL);
}
/*
* do_query_name - nameserver lookup name
*/
static void do_query_name(struct DNSQuery *query, const char *name, struct reslist *request,
int type)
{
if (request == NULL)
{
request = make_request(query);
request->name = rb_strdup(name);
}
rb_strlcpy(request->queryname, name, sizeof(request->queryname));
request->type = type;
query_name(request);
}
/* Build an rDNS style query - if suffix is NULL, use the appropriate .arpa zone */
void build_rdns(char *buf, size_t size, const struct rb_sockaddr_storage *addr, const char *suffix)
{
const unsigned char *cp;
if (GET_SS_FAMILY(addr) == AF_INET)
{
const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
cp = (const unsigned char *)&v4->sin_addr.s_addr;
(void) snprintf(buf, size, "%u.%u.%u.%u.%s",
(unsigned int)(cp[3]),
(unsigned int)(cp[2]),
(unsigned int)(cp[1]),
(unsigned int)(cp[0]),
suffix == NULL ? "in-addr.arpa" : suffix);
}
else if (GET_SS_FAMILY(addr) == AF_INET6)
{
const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
cp = (const unsigned char *)&v6->sin6_addr.s6_addr;
#define HI_NIBBLE(x) (unsigned int)((x) >> 4)
#define LO_NIBBLE(x) (unsigned int)((x) & 0xf)
(void) snprintf(buf, size,
"%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%s",
LO_NIBBLE(cp[15]), HI_NIBBLE(cp[15]),
LO_NIBBLE(cp[14]), HI_NIBBLE(cp[14]),
LO_NIBBLE(cp[13]), HI_NIBBLE(cp[13]),
LO_NIBBLE(cp[12]), HI_NIBBLE(cp[12]),
LO_NIBBLE(cp[11]), HI_NIBBLE(cp[11]),
LO_NIBBLE(cp[10]), HI_NIBBLE(cp[10]),
LO_NIBBLE(cp[9]), HI_NIBBLE(cp[9]),
LO_NIBBLE(cp[8]), HI_NIBBLE(cp[8]),
LO_NIBBLE(cp[7]), HI_NIBBLE(cp[7]),
LO_NIBBLE(cp[6]), HI_NIBBLE(cp[6]),
LO_NIBBLE(cp[5]), HI_NIBBLE(cp[5]),
LO_NIBBLE(cp[4]), HI_NIBBLE(cp[4]),
LO_NIBBLE(cp[3]), HI_NIBBLE(cp[3]),
LO_NIBBLE(cp[2]), HI_NIBBLE(cp[2]),
LO_NIBBLE(cp[1]), HI_NIBBLE(cp[1]),
LO_NIBBLE(cp[0]), HI_NIBBLE(cp[0]),
suffix == NULL ? "ip6.arpa" : suffix);
}
#undef HI_NIBBLE
#undef LO_NIBBLE
}
/*
* do_query_number - Use this to do reverse IP# lookups.
*/
static void do_query_number(struct DNSQuery *query, const struct rb_sockaddr_storage *addr,
struct reslist *request)
{
if (request == NULL)
{
request = make_request(query);
memcpy(&request->addr, addr, sizeof(struct rb_sockaddr_storage));
request->name = (char *)rb_malloc(IRCD_RES_HOSTLEN + 1);
}
build_rdns(request->queryname, sizeof request->queryname, addr, NULL);
request->type = T_PTR;
query_name(request);
}
/*
* query_name - generate a query based on class, type and name.
*/
static void query_name(struct reslist *request)
{
char buf[MAXPACKET];
int request_len = 0;
int ns;
memset(buf, 0, sizeof(buf));
if ((request_len =
irc_res_mkquery(request->queryname, C_IN, request->type, (unsigned char *)buf, sizeof(buf))) > 0)
{
HEADER *header = (HEADER *)(void *)buf;
header->id = request->id;
++request->sends;
ns = send_res_msg(buf, request_len, request->sends);
if (ns != -1)
request->lastns = ns;
}
}
static void resend_query(struct reslist *request)
{
if (--request->retries <= 0)
{
(*request->query->callback) (request->query->ptr, NULL);
rem_request(request);
return;
}
switch (request->type)
{
case T_PTR:
do_query_number(NULL, &request->addr, request);
break;
case T_A:
case T_AAAA:
do_query_name(NULL, request->name, request, request->type);
break;
default:
break;
}
}
/*
* check_question - check if the reply really belongs to the
* name we queried (to guard against late replies from previous
* queries with the same id).
*/
static int check_question(struct reslist *request, HEADER * header, char *buf, char *eob)
{
char hostbuf[IRCD_RES_HOSTLEN + 1]; /* working buffer */
unsigned char *current; /* current position in buf */
int n; /* temp count */
current = (unsigned char *)buf + sizeof(HEADER);
if (header->qdcount != 1)
return 0;
n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob, current, hostbuf,
sizeof(hostbuf));
if (n <= 0)
return 0;
if (rb_strcasecmp(hostbuf, request->queryname))
return 0;
return 1;
}
/*
* proc_answer - process name server reply
*/
static int proc_answer(struct reslist *request, HEADER * header, char *buf, char *eob)
{
char hostbuf[IRCD_RES_HOSTLEN + 100]; /* working buffer */
unsigned char *current; /* current position in buf */
int type; /* answer type */
int n; /* temp count */
int rd_length;
struct sockaddr_in *v4; /* conversion */
struct sockaddr_in6 *v6;
current = (unsigned char *)buf + sizeof(HEADER);
for (; header->qdcount > 0; --header->qdcount)
{
if ((n = irc_dn_skipname(current, (unsigned char *)eob)) < 0)
return 0;
current += (size_t) n + QFIXEDSZ;
}
/*
* process each answer sent to us blech.
*/
while (header->ancount > 0 && (char *)current < eob)
{
header->ancount--;
n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob, current, hostbuf,
sizeof(hostbuf));
if (n < 0)
{
/*
* broken message
*/
return (0);
}
else if (n == 0)
{
/*
* no more answers left
*/
return (0);
}
hostbuf[IRCD_RES_HOSTLEN] = '\0';
/* With Address arithmetic you have to be very anal
* this code was not working on alpha due to that
* (spotted by rodder/jailbird/dianora)
*/
current += (size_t) n;
if (!(((char *)current + ANSWER_FIXED_SIZE) < eob))
break;
type = irc_ns_get16(current);
current += TYPE_SIZE;
(void) irc_ns_get16(current);
current += CLASS_SIZE;
request->ttl = irc_ns_get32(current);
current += TTL_SIZE;
rd_length = irc_ns_get16(current);
current += RDLENGTH_SIZE;
/*
* Wait to set request->type until we verify this structure
*/
switch (type)
{
case T_A:
if (request->type != T_A)
return (0);
/*
* check for invalid rd_length or too many addresses
*/
if (rd_length != sizeof(struct in_addr))
return (0);
v4 = (struct sockaddr_in *)&request->addr;
SET_SS_LEN(&request->addr, sizeof(struct sockaddr_in));
v4->sin_family = AF_INET;
memcpy(&v4->sin_addr, current, sizeof(struct in_addr));
return (1);
case T_AAAA:
if (request->type != T_AAAA)
return (0);
if (rd_length != sizeof(struct in6_addr))
return (0);
SET_SS_LEN(&request->addr, sizeof(struct sockaddr_in6));
v6 = (struct sockaddr_in6 *)&request->addr;
v6->sin6_family = AF_INET6;
memcpy(&v6->sin6_addr, current, sizeof(struct in6_addr));
return (1);
case T_PTR:
if (request->type != T_PTR)
return (0);
n = irc_dn_expand((unsigned char *)buf, (unsigned char *)eob, current,
hostbuf, sizeof(hostbuf));
if (n < 0)
return (0); /* broken message */
else if (n == 0)
return (0); /* no more answers left */
rb_strlcpy(request->name, hostbuf, IRCD_RES_HOSTLEN + 1);
return (1);
}
/* skip any other record type e.g. CNAME, DNAME; real answer should follow */
current += rd_length;
}
return (1);
}
/*
* res_read_single_reply - read a dns reply from the nameserver and process it.
* Return value: 1 if a packet was read, 0 otherwise
*/
static int res_read_single_reply(rb_fde_t *F, void *data)
{
char buf[sizeof(HEADER) + MAXPACKET]
/* Sparc and alpha need 16bit-alignment for accessing header->id
* (which is uint16_t). Because of the header = (HEADER*) buf;
* lateron, this is neeeded. --FaUl
*/
#if defined(__sparc__) || defined(__alpha__)
__attribute__ ((aligned(16)))
#endif
;
HEADER *header;
struct reslist *request = NULL;
struct DNSReply *reply = NULL;
int rc;
int answer_count;
socklen_t len = sizeof(struct rb_sockaddr_storage);
struct rb_sockaddr_storage lsin;
int ns;
rc = recvfrom(rb_get_fd(F), buf, sizeof(buf), 0, (struct sockaddr *)&lsin, &len);
/* No packet */
if (rc == 0 || rc == -1)
return 0;
/* Too small */
if (rc <= (int)(sizeof(HEADER)))
return 1;
/*
* convert DNS reply reader from Network byte order to CPU byte order.
*/
header = (HEADER *)(void *)buf;
header->ancount = ntohs(header->ancount);
header->qdcount = ntohs(header->qdcount);
header->nscount = ntohs(header->nscount);
header->arcount = ntohs(header->arcount);
/*
* response for an id which we have already received an answer for
* just ignore this response.
*/
if (0 == (request = find_id(header->id)))
return 1;
/*
* check against possibly fake replies
*/
ns = res_ourserver(&lsin);
if (ns == -1)
return 1;
if (ns != request->lastns)
{
/*
* We'll accept the late reply, but penalize it a little more to make
* sure a laggy server doesn't end up favored.
*/
ns_failure_count[ns] += 3;
}
if (!check_question(request, header, buf, buf + rc))
return 1;
if ((header->rcode != NO_ERRORS) || (header->ancount == 0))
{
/*
* RFC 2136 states that in the event of a server returning SERVFAIL
* or NOTIMP, the request should be resent to the next server.
* Additionally, if the server refuses our query, resend it as well.
* -- mr_flea
*/
if (SERVFAIL == header->rcode || NOTIMP == header->rcode ||
REFUSED == header->rcode)
{
ns_failure_count[ns]++;
resend_query(request);
}
else
{
/*
* Either a fatal error was returned or no answer. Cancel the
* request.
*/
if (NXDOMAIN == header->rcode)
{
/* If the rcode is NXDOMAIN, treat it as a good response. */
ns_failure_count[ns] /= 4;
}
(*request->query->callback) (request->query->ptr, NULL);
rem_request(request);
}
return 1;
}
/*
* If this fails there was an error decoding the received packet.
* -- jilles
*/
answer_count = proc_answer(request, header, buf, buf + rc);
if (answer_count)
{
if (request->type == T_PTR)
{
if (request->name == NULL)
{
/*
* Got a PTR response with no name, something strange is
* happening. Try another DNS server.
*/
ns_failure_count[ns]++;
resend_query(request);
return 1;
}
/*
* Lookup the 'authoritative' name that we were given for the
* ip#.
*/
if (GET_SS_FAMILY(&request->addr) == AF_INET6)
gethost_byname_type_fqdn(request->name, request->query, T_AAAA);
else
gethost_byname_type_fqdn(request->name, request->query, T_A);
rem_request(request);
}
else
{
/*
* got a name and address response, client resolved
*/
reply = make_dnsreply(request);
(*request->query->callback) (request->query->ptr, reply);
rb_free(reply);
rem_request(request);
}
ns_failure_count[ns] /= 4;
}
else
{
/* Invalid or corrupt reply - try another resolver. */
ns_failure_count[ns]++;
resend_query(request);
}
return 1;
}
static void
res_readreply(rb_fde_t *F, void *data)
{
while (res_read_single_reply(F, data))
;
rb_setselect(F, RB_SELECT_READ, res_readreply, NULL);
}
static struct DNSReply *
make_dnsreply(struct reslist *request)
{
struct DNSReply *cp;
lrb_assert(request != 0);
cp = (struct DNSReply *)rb_malloc(sizeof(struct DNSReply));
cp->h_name = request->name;
memcpy(&cp->addr, &request->addr, sizeof(cp->addr));
return (cp);
}

View file

@ -1,23 +1,17 @@
/*
* res.h for referencing functions in res.c, reslib.c
*
* $Id: res.h 2023 2006-09-02 23:47:27Z jilles $
*/
#ifndef _CHARYBDIS_RES_H
#define _CHARYBDIS_RES_H
#include "ircd_defs.h"
#include "common.h"
#include "reslib.h"
#include "match.h"
#include "ircd.h"
#ifndef _SOLANUM_RES_H
#define _SOLANUM_RES_H
/* Maximum number of nameservers in /etc/resolv.conf we care about
* In hybrid, this was 2 -- but in Charybdis, we want to track
* In hybrid, this was 2 -- but in Solanum, we want to track
* a few more than that ;) --nenolod
*/
#define IRCD_MAXNS 10
#define RESOLVER_HOSTLEN 255
struct DNSReply
{
@ -36,10 +30,8 @@ extern int irc_nscount;
extern void init_resolver(void);
extern void restart_resolver(void);
extern void delete_resolver_queries(const struct DNSQuery *);
extern void gethost_byname_type(const char *, struct DNSQuery *, int);
extern void gethost_byaddr(const struct rb_sockaddr_storage *, struct DNSQuery *);
extern void add_local_domain(char *, size_t);
extern void report_dns_servers(struct Client *);
extern void build_rdns(char *, size_t, const struct rb_sockaddr_storage *, const char *);
#endif

View file

@ -76,9 +76,10 @@
* - Dianora
*/
#include <rb_lib.h>
#include <netdb.h>
#include "stdinc.h"
#include "ircd_defs.h"
#include "common.h"
#include "ircd.h"
#include "res.h"
#include "reslib.h"
@ -89,9 +90,6 @@
#define DNS_LABELTYPE_BITSTRING 0x41
#define DNS_MAXLINE 128
/* $Id: reslib.c 1695 2006-06-27 15:11:23Z jilles $ */
/* from Hybrid Id: reslib.c 177 2005-10-22 09:05:05Z michael $ */
struct rb_sockaddr_storage irc_nsaddr_list[IRCD_MAXNS];
int irc_nscount = 0;
char irc_domain[IRCD_RES_HOSTLEN + 1];
@ -115,10 +113,10 @@ static const char digitvalue[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
};
static const char digits[] = "0123456789";
static int parse_resvconf(void);
static void add_nameserver(const char *);
static const char digits[] = "0123456789";
static int labellen(const unsigned char *lp);
static int special(int ch);
static int printable(int ch);
@ -163,9 +161,6 @@ parse_resvconf(void)
char input[DNS_MAXLINE];
FILE *file;
/* XXX "/etc/resolv.conf" should be from a define in setup.h perhaps
* for cygwin support etc. this hardcodes it to unix for now -db
*/
if ((file = fopen("/etc/resolv.conf", "r")) == NULL)
return -1;
@ -177,7 +172,7 @@ parse_resvconf(void)
p = input;
/* skip until something thats not a space is seen */
while (IsSpace(*p))
while (isspace(*p))
p++;
/* if at this point, have a '\0' then continue */
if (*p == '\0')
@ -189,7 +184,7 @@ parse_resvconf(void)
/* skip until a space is found */
opt = p;
while (!IsSpace(*p) && *p != '\0')
while (!isspace(*p) && *p != '\0')
p++;
if (*p == '\0')
continue; /* no arguments?.. ignore this line */
@ -197,16 +192,16 @@ parse_resvconf(void)
*p++ = '\0';
/* skip these spaces that are before the argument */
while (IsSpace(*p))
while (isspace(*p))
p++;
/* Now arg should be right where p is pointing */
arg = p;
if ((p = strpbrk(arg, " \t")) != NULL)
*p = '\0'; /* take the first word */
if (irccmp(opt, "domain") == 0)
if (rb_strcasecmp(opt, "domain") == 0)
rb_strlcpy(irc_domain, arg, sizeof(irc_domain));
else if (irccmp(opt, "nameserver") == 0)
else if (rb_strcasecmp(opt, "nameserver") == 0)
add_nameserver(arg);
}
@ -228,10 +223,7 @@ add_nameserver(const char *arg)
/* Done max number of nameservers? */
if (irc_nscount >= IRCD_MAXNS)
{
ilog (L_MAIN, "Too many nameservers, ignoring %s", arg);
return;
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
@ -1117,9 +1109,9 @@ irc_dn_find(const unsigned char *domain, const unsigned char *msg,
}
/*
* * Thinking in noninternationalized USASCII (per the DNS spec),
* * convert this character to lower case if it's upper case.
* */
* Thinking in noninternationalized USASCII (per the DNS spec),
* convert this character to lower case if it's upper case.
*/
static int
mklower(int ch)
{

View file

@ -1,11 +1,10 @@
/*
* include/irc_reslib.h
*
* $Id: reslib.h 446 2006-02-12 02:46:54Z db $
*/
#ifndef _CHARYBDIS_RESLIB_H
#define _CHARYBDIS_RESLIB_H
#ifndef _SOLANUM_RESLIB_H
#define _SOLANUM_RESLIB_H
/* Longest hostname we're willing to work with.
* Due to DNSBLs this is more than HOSTLEN.
@ -79,24 +78,24 @@ typedef struct
*/
#define IRC_NS_GET16(s, cp) { \
const unsigned char *t_cp = (const unsigned char *)(cp); \
(s) = ((u_int16_t)t_cp[0] << 8) \
| ((u_int16_t)t_cp[1]) \
(s) = ((uint16_t)t_cp[0] << 8) \
| ((uint16_t)t_cp[1]) \
; \
(cp) += NS_INT16SZ; \
}
#define IRC_NS_GET32(l, cp) { \
const unsigned char *t_cp = (const unsigned char *)(cp); \
(l) = ((u_int32_t)t_cp[0] << 24) \
| ((u_int32_t)t_cp[1] << 16) \
| ((u_int32_t)t_cp[2] << 8) \
| ((u_int32_t)t_cp[3]) \
(l) = ((uint32_t)t_cp[0] << 24) \
| ((uint32_t)t_cp[1] << 16) \
| ((uint32_t)t_cp[2] << 8) \
| ((uint32_t)t_cp[3]) \
; \
(cp) += NS_INT32SZ; \
}
#define IRC_NS_PUT16(s, cp) { \
u_int16_t t_s = (u_int16_t)(s); \
uint16_t t_s = (uint16_t)(s); \
unsigned char *t_cp = (unsigned char *)(cp); \
*t_cp++ = t_s >> 8; \
*t_cp = t_s; \
@ -104,7 +103,7 @@ typedef struct
}
#define IRC_NS_PUT32(l, cp) { \
u_int32_t t_l = (u_int32_t)(l); \
uint32_t t_l = (uint32_t)(l); \
unsigned char *t_cp = (unsigned char *)(cp); \
*t_cp++ = t_l >> 24; \
*t_cp++ = t_l >> 16; \

96
autogen.sh Executable file
View file

@ -0,0 +1,96 @@
#! /bin/sh
TOP_DIR=$(dirname $0)
LAST_DIR=$PWD
if test ! -f $TOP_DIR/configure.ac ; then
echo "You must execute this script from the top level directory."
exit 1
fi
AUTOCONF=${AUTOCONF:-autoconf}
ACLOCAL=${ACLOCAL:-aclocal}
AUTOMAKE=${AUTOMAKE:-automake}
AUTOHEADER=${AUTOHEADER:-autoheader}
LIBTOOLIZE=${LIBTOOLIZE:-libtoolize}
#SHTOOLIZE=${SHTOOLIZE:-shtoolize}
dump_help_screen ()
{
echo "Usage: $0 [options]"
echo
echo "options:"
echo " -n skip CVS changelog creation"
echo " -h,--help show this help screen"
echo
exit 0
}
parse_options ()
{
while test "$1" != "" ; do
case $1 in
-h|--help)
dump_help_screen
;;
-n)
SKIP_CVS_CHANGELOG=yes
;;
*)
echo Invalid argument - $1
dump_help_screen
;;
esac
shift
done
}
run_or_die ()
{
COMMAND=$1
# check for empty commands
if test -z "$COMMAND" ; then
echo "*warning* no command specified"
return 1
fi
shift;
OPTIONS="$@"
# print a message
echo -n "*info* running $COMMAND"
if test -n "$OPTIONS" ; then
echo " ($OPTIONS)"
else
echo
fi
# run or die
$COMMAND $OPTIONS ; RESULT=$?
if test $RESULT -ne 0 ; then
echo "*error* $COMMAND failed. (exit code = $RESULT)"
exit 1
fi
return 0
}
parse_options "$@"
echo "Building librb autotools files."
cd "$TOP_DIR"/librb
sh autogen.sh
echo "Building main autotools files."
cd "$LAST_DIR"
run_or_die $ACLOCAL -I m4
run_or_die $LIBTOOLIZE --force --copy
run_or_die $AUTOHEADER
run_or_die $AUTOCONF
run_or_die $AUTOMAKE --add-missing --copy
#run_or_die $SHTOOLIZE all

11
bandb/Makefile.am Normal file
View file

@ -0,0 +1,11 @@
pkglibexec_PROGRAMS = bandb
bin_PROGRAMS = solanum-bantool
AM_CFLAGS=$(WARNFLAGS)
AM_CPPFLAGS = -I../include -I../librb/include @SQLITE_INCLUDES@
bandb_SOURCES = bandb.c rsdb_sqlite3.c rsdb_snprintf.c
bandb_LDADD = ../librb/src/librb.la @SQLITE_LD@
solanum_bantool_SOURCES = bantool.c rsdb_sqlite3.c rsdb_snprintf.c
solanum_bantool_LDADD = ../librb/src/librb.la @SQLITE_LD@

View file

@ -1,110 +0,0 @@
#
# Makefile.in for bandb/src
#
# $Id: Makefile.in 1285 2006-05-05 15:03:53Z nenolod $
#
CC = @CC@
INSTALL = @INSTALL@
INSTALL_BIN = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SUID = @INSTALL_PROGRAM@ -o root -m 4755
RM = @RM@
LEX = @LEX@
LEXLIB = @LEXLIB@
CFLAGS = @IRC_CFLAGS@ -DIRCD_PREFIX=\"@prefix@\"
LDFLAGS = @LDFLAGS@
MKDEP = @MKDEP@ -DIRCD_PREFIX=\"@prefix@\"
MV = @MV@
RM = @RM@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
libdir = @libdir@
libexecdir = @libexecdir@
pkglibexecdir = @pkglibexecdir@
sysconfdir = @sysconfdir@
localstatedir = @localstatedir@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PROGRAM_PREFIX = @PROGRAM_PREFIX@
SQLITE_LIBS = @SQLITE_LD@
SQLITE_INCLUDES = @SQLITE_INCLUDES@
ZIP_LIB = @ZLIB_LD@
IRCDLIBS = @MODULES_LIBS@ -L../libratbox/src/.libs -lratbox @LIBS@ $(SSL_LIBS) $(ZIP_LIB) $(SQLITE_LIBS)
INCLUDES = -I. -I../include -I../libratbox/include $(SSL_INCLUDES) $(SQLITE_INCLUDES)
CPPFLAGS = ${INCLUDES} @CPPFLAGS@
CFLAGS += -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION=1
pkglibexec_PROGS = bandb
bin_PROGS = bantool
PROGS = $(pkglibexec_PROGS) $(bin_PROGS)
BANDB_SOURCES = \
bandb.c \
rsdb_snprintf.c \
rsdb_sqlite3.c \
@SQLITE_SRC@
BANDB_OBJECTS = ${BANDB_SOURCES:.c=.o}
BANTOOL_SOURCES = \
bantool.c \
rsdb_snprintf.c \
rsdb_sqlite3.c \
@SQLITE_SRC@
BANTOOL_OBJECTS = ${BANTOOL_SOURCES:.c=.o}
all: bandb bantool
build: all
bandb: ${BANDB_OBJECTS}
${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${BANDB_OBJECTS} ${IRCDLIBS}
bantool: ${BANTOOL_OBJECTS}
${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${BANTOOL_OBJECTS} ${IRCDLIBS}
install: build
@echo "ircd: installing bandb ($(PROGS))"
@for i in $(bin_PROGS); do \
if test -f $(DESTDIR)$(bindir)/$(PROGRAM_PREFIX)$$i; then \
$(MV) $(DESTDIR)$(bindir)/$(PROGRAM_PREFIX)$$i $(DESTDIR)$(bindir)/$(PROGRAM_PREFIX)$$i.old; \
fi; \
$(INSTALL_BIN) $$i $(DESTDIR)$(bindir)/$(PROGRAM_PREFIX)$$i; \
done
@for i in $(pkglibexec_PROGS); do \
if test -f '$(DESTDIR)$(pkglibexecdir)/'$$i; then \
$(MV) '$(DESTDIR)$(pkglibexecdir)/'$$i '$(DESTDIR)$(pkglibexecdir)/'$$i.old; \
fi; \
$(INSTALL_BIN) $$i '$(DESTDIR)$(pkglibexecdir)/'$$i; \
done
.c.o:
${CC} ${CPPFLAGS} ${CFLAGS} -c $<
.PHONY: depend clean distclean
depend:
@${MKDEP} ${CPPFLAGS} ${SOURCES} > .depend.tmp
@sed -e '/^# DO NOT DELETE THIS LINE/,$$d' <Makefile >Makefile.depend
@echo '# DO NOT DELETE THIS LINE!!!' >>Makefile.depend
@echo '# make depend needs it.' >>Makefile.depend
@cat .depend.tmp >>Makefile.depend
@mv Makefile.depend Makefile
@rm -f .depend.tmp
clean:
${RM} -f *.o *~ *.core core bandb bantool
lint:
lint -aacgprxhH $(CPPFLAGS) -DIRCD_PREFIX=\"@prefix@\" $(SOURCES) >>../lint.out
distclean: clean
${RM} -f Makefile
# End of Makefile

View file

@ -26,14 +26,12 @@
* 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.
*
* $Id: bandb.c 26094 2008-09-19 15:33:46Z androsyn $
*/
#include "setup.h"
#include <ratbox_lib.h>
#include <rb_lib.h>
#include <stdio.h>
#include "rsdb.h"
#include "common.h"
#include "ircd_defs.h"
#define MAXPARA 10
@ -161,11 +159,11 @@ list_bans(void)
for(j = 0; j < table.row_count; j++)
{
if(i == BANDB_KLINE)
rb_snprintf(buf, sizeof(buf), "%c %s %s %s :%s",
snprintf(buf, sizeof(buf), "%c %s %s %s :%s",
bandb_letter[i], table.row[j][0],
table.row[j][1], table.row[j][2], table.row[j][3]);
else
rb_snprintf(buf, sizeof(buf), "%c %s %s :%s",
snprintf(buf, sizeof(buf), "%c %s %s :%s",
bandb_letter[i], table.row[j][0],
table.row[j][2], table.row[j][3]);
@ -238,7 +236,14 @@ parse_request(rb_helper *helper)
}
<<<<<<< .merge_file_OcfD4C
static void __attribute__((noreturn))
=======
static void
error_cb(rb_helper *helper) __attribute__((noreturn));
static void
>>>>>>> .merge_file_OF4zx2
error_cb(rb_helper *helper)
{
if(in_transaction)
@ -246,18 +251,15 @@ error_cb(rb_helper *helper)
exit(1);
}
#ifndef WINDOWS
static void
dummy_handler(int sig)
{
return;
}
#endif
static void
setup_signals(void)
{
#ifndef WINDOWS
struct sigaction act;
act.sa_flags = 0;
@ -280,15 +282,21 @@ setup_signals(void)
act.sa_handler = dummy_handler;
sigaction(SIGALRM, &act, 0);
#endif
}
<<<<<<< .merge_file_OcfD4C
static void __attribute__((noreturn))
=======
static void
db_error_cb(const char *errstr) __attribute__((noreturn));
static void
>>>>>>> .merge_file_OF4zx2
db_error_cb(const char *errstr)
{
char buf[256];
rb_snprintf(buf, sizeof(buf), "! :%s", errstr);
snprintf(buf, sizeof(buf), "! :%s", errstr);
rb_helper_write(bandb_helper, "%s", buf);
rb_sleep(1 << 30, 0);
exit(1);
@ -302,10 +310,9 @@ main(int argc, char *argv[])
if(bandb_helper == NULL)
{
fprintf(stderr,
"This is ircd-ratbox bandb. You aren't supposed to run me directly. Maybe you want bantool?\n");
"This is the solanum bandb for internal ircd use.\n");
fprintf(stderr,
"However I will print my Id tag $Id: bandb.c 26094 2008-09-19 15:33:46Z androsyn $\n");
fprintf(stderr, "Have a nice day\n");
"You aren't supposed to run me directly (did you want solanum-bantool?). Exiting.\n");
exit(1);
}
rsdb_init(db_error_cb);

View file

@ -22,9 +22,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* $Id: bantool.c 26164 2008-10-26 19:52:43Z androsyn $
*
*
* The following server admins have either contributed various configs to test against,
* or helped with debugging and feature requests. Many thanks to them.
* stevoo / efnet.port80.se
@ -43,11 +40,9 @@
#include <time.h>
#include "stdinc.h"
#include "common.h"
#include "rsdb.h"
#define EmptyString(x) ((x == NULL) || (*(x) == '\0'))
#define CheckEmpty(x) EmptyString(x) ? "" : x
#define BT_VERSION "0.4.1"
@ -96,16 +91,16 @@ struct counter
/* flags set by command line options */
struct flags
{
int none;
int export;
int import;
int verify;
int vacuum;
int pretend;
int verbose;
int wipe;
int dupes_ok;
} flag = {YES, NO, NO, NO, NO, NO, NO, NO, NO};
bool none;
bool export;
bool import;
bool verify;
bool vacuum;
bool pretend;
bool verbose;
bool wipe;
bool dupes_ok;
} flag = {true, false, false, false, false, false, false, false, false};
/* *INDENT-ON* */
static int table_has_rows(const char *table);
@ -148,32 +143,32 @@ main(int argc, char *argv[])
print_help(EXIT_SUCCESS);
/* noreturn call above, this is unreachable */
case 'i':
flag.none = NO;
flag.import = YES;
flag.none = false;
flag.import = true;
break;
case 'e':
flag.none = NO;
flag.export = YES;
flag.none = false;
flag.export = true;
break;
case 'u':
flag.none = NO;
flag.verify = YES;
flag.none = false;
flag.verify = true;
break;
case 's':
flag.none = NO;
flag.vacuum = YES;
flag.none = false;
flag.vacuum = true;
break;
case 'p':
flag.pretend = YES;
flag.pretend = true;
break;
case 'v':
flag.verbose = YES;
flag.verbose = true;
break;
case 'w':
flag.wipe = YES;
flag.wipe = true;
break;
case 'd':
flag.dupes_ok = YES;
flag.dupes_ok = true;
break;
default: /* '?' */
print_help(EXIT_FAILURE);
@ -201,10 +196,9 @@ main(int argc, char *argv[])
rb_strlcpy(etc, ETCPATH, sizeof(ETCPATH));
fprintf(stdout,
"* ircd-ratbox bantool v.%s ($Id: bantool.c 26164 2008-10-26 19:52:43Z androsyn $)\n",
BT_VERSION);
"* solanum bantool v.%s\n", BT_VERSION);
if(flag.pretend == NO)
if(flag.pretend == false)
{
if(rsdb_init(db_error_cb) == -1)
{
@ -218,7 +212,7 @@ main(int argc, char *argv[])
if(flag.import && flag.wipe)
{
flag.dupes_ok = YES; /* dont check for dupes if we are wiping the db clean */
flag.dupes_ok = true; /* dont check for dupes if we are wiping the db clean */
for(i = 0; i < 3; i++)
fprintf(stdout,
"* WARNING: YOU ARE ABOUT TO WIPE YOUR DATABASE!\n");
@ -230,16 +224,19 @@ main(int argc, char *argv[])
wipe_schema();
}
}
if(flag.verbose && flag.dupes_ok == YES)
if(flag.verbose && flag.dupes_ok == true)
fprintf(stdout, "* Allowing duplicate bans...\n");
/* checking for our files to import or export */
for(i = 0; i < LAST_BANDB_TYPE; i++)
{
rb_snprintf(conf, sizeof(conf), "%s/%s.conf%s",
etc, bandb_table[i], bandb_suffix[i]);
if (snprintf(conf, sizeof(conf), "%s/%s.conf%s",
etc, bandb_table[i], bandb_suffix[i]) >= sizeof(conf)) {
fprintf(stderr, "* Error: Config filename too long\n");
exit(EXIT_FAILURE);
}
if(flag.import && flag.pretend == NO)
if(flag.import && flag.pretend == false)
rsdb_transaction(RSDB_TRANS_START);
if(flag.import)
@ -248,7 +245,7 @@ main(int argc, char *argv[])
if(flag.export)
export_config(conf, i);
if(flag.import && flag.pretend == NO)
if(flag.import && flag.pretend == false)
rsdb_transaction(RSDB_TRANS_END);
}
@ -297,11 +294,11 @@ export_config(const char *conf, int id)
return;
if(strstr(conf, ".perm") != 0)
rb_snprintf(sql, sizeof(sql),
snprintf(sql, sizeof(sql),
"SELECT DISTINCT mask1,mask2,reason,oper,time FROM %s WHERE perm = 1 ORDER BY time",
bandb_table[id]);
else
rb_snprintf(sql, sizeof(sql),
snprintf(sql, sizeof(sql),
"SELECT DISTINCT mask1,mask2,reason,oper,time FROM %s WHERE perm = 0 ORDER BY time",
bandb_table[id]);
@ -330,7 +327,7 @@ export_config(const char *conf, int id)
{
case BANDB_DLINE:
case BANDB_DLINE_PERM:
rb_snprintf(buf, sizeof(buf),
snprintf(buf, sizeof(buf),
"\"%s\",\"%s\",\"\",\"%s\",\"%s\",%s\n",
table.row[j][mask1],
mangle_reason(table.row[j][reason]),
@ -340,7 +337,7 @@ export_config(const char *conf, int id)
case BANDB_XLINE:
case BANDB_XLINE_PERM:
rb_snprintf(buf, sizeof(buf),
snprintf(buf, sizeof(buf),
"\"%s\",\"0\",\"%s\",\"%s\",%s\n",
escape_quotes(table.row[j][mask1]),
mangle_reason(table.row[j][reason]),
@ -349,7 +346,7 @@ export_config(const char *conf, int id)
case BANDB_RESV:
case BANDB_RESV_PERM:
rb_snprintf(buf, sizeof(buf),
snprintf(buf, sizeof(buf),
"\"%s\",\"%s\",\"%s\",%s\n",
table.row[j][mask1],
mangle_reason(table.row[j][reason]),
@ -358,7 +355,7 @@ export_config(const char *conf, int id)
default: /* Klines */
rb_snprintf(buf, sizeof(buf),
snprintf(buf, sizeof(buf),
"\"%s\",\"%s\",\"%s\",\"\",\"%s\",\"%s\",%s\n",
table.row[j][mask1], table.row[j][mask2],
mangle_reason(table.row[j][reason]),
@ -497,13 +494,13 @@ import_config(const char *conf, int id)
/* append operreason_field to reason_field */
if(!EmptyString(f_oreason))
rb_snprintf(newreason, sizeof(newreason), "%s | %s", f_reason, f_oreason);
snprintf(newreason, sizeof(newreason), "%s | %s", f_reason, f_oreason);
else
rb_snprintf(newreason, sizeof(newreason), "%s", f_reason);
snprintf(newreason, sizeof(newreason), "%s", f_reason);
if(flag.pretend == NO)
if(flag.pretend == false)
{
if(flag.dupes_ok == NO)
if(flag.dupes_ok == false)
drop_dupes(f_mask1, f_mask2, bandb_table[id]);
rsdb_exec(NULL,
@ -746,7 +743,7 @@ check_schema(void)
NULL
};
for(i = 0; i < LAST_BANDB_TYPE; i++)
for(i = 0; i < LAST_BANDB_TYPE; i += 2 /* skip over _PERM */)
{
if(!table_exists(bandb_table[i]))
{
@ -773,8 +770,6 @@ check_schema(void)
columns[j], type);
}
}
i++; /* skip over .perm */
}
}
@ -812,17 +807,16 @@ table_has_rows(const char *dbtab)
}
/**
* completly wipes out an existing ban.db of all entries.
* completely wipes out an existing ban.db of all entries.
*/
static void
wipe_schema(void)
{
int i;
rsdb_transaction(RSDB_TRANS_START);
for(i = 0; i < LAST_BANDB_TYPE; i++)
for(i = 0; i < LAST_BANDB_TYPE; i += 2 /* double increment to skip over _PERM */)
{
rsdb_exec(NULL, "DROP TABLE %s", bandb_table[i]);
i++; /* double increment to skip over .perm */
}
rsdb_transaction(RSDB_TRANS_END);
@ -859,7 +853,7 @@ bt_smalldate(const char *string)
lt = gmtime(&t);
if(lt == NULL)
return NULL;
rb_snprintf(buf, sizeof(buf), "%d/%d/%d %02d.%02d",
snprintf(buf, sizeof(buf), "%d/%d/%d %02d.%02d",
lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min);
return buf;
}
@ -870,9 +864,8 @@ bt_smalldate(const char *string)
static void
print_help(const int i_exit)
{
fprintf(stderr, "bantool v.%s - the ircd-ratbox database tool.\n", BT_VERSION);
fprintf(stderr, "bantool v.%s - the solanum database tool.\n", BT_VERSION);
fprintf(stderr, "Copyright (C) 2008 Daniel J Reidy <dubkat@gmail.com>\n");
fprintf(stderr, "$Id: bantool.c 26164 2008-10-26 19:52:43Z androsyn $\n\n");
fprintf(stderr, "This program is distributed in the hope that it will be useful,\n"
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
@ -887,15 +880,15 @@ print_help(const int i_exit)
fprintf(stderr, " -s : Reclaim empty slack space the database may be taking up.\n");
fprintf(stderr, " -u : Update the database tables to support any new features.\n");
fprintf(stderr,
" This is automaticlly done if you are importing or exporting\n");
" This is automatically done if you are importing or exporting\n");
fprintf(stderr, " but should be run whenever you upgrade the ircd.\n");
fprintf(stderr,
" -p : pretend, checks for the configs, and parses them, then tells you some data...\n");
fprintf(stderr, " but does not touch your database.\n");
fprintf(stderr,
" -v : Be verbose... and it *is* very verbose! (intended for debugging)\n");
fprintf(stderr, " -d : Enable checking for redunant entries.\n");
fprintf(stderr, " -w : Completly wipe your database clean. May be used with -i \n");
fprintf(stderr, " -d : Enable checking for redundant entries.\n");
fprintf(stderr, " -w : Completely wipe your database clean. May be used with -i \n");
fprintf(stderr,
" path : An optional directory containing old ratbox configs for import, or export.\n");
fprintf(stderr, " If not specified, it looks in PREFIX/etc.\n");

View file

@ -1,4 +1,3 @@
/* $Id: rsdb.h 26164 2008-10-26 19:52:43Z androsyn $ */
#ifndef INCLUDED_rsdb_h
#define INCLUDED_rsdb_h

View file

@ -5,8 +5,6 @@
* Should you choose to use and/or modify this source code, please
* do so under the terms of the GNU General Public License under which
* this library is distributed.
*
* $Id: rsdb_snprintf.c 26094 2008-09-19 15:33:46Z androsyn $
*/
#include "stdinc.h"
#include "rsdb.h"

View file

@ -27,8 +27,6 @@
* 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.
*
* $Id: rsdb_sqlite3.c 26182 2008-11-11 02:52:41Z androsyn $
*/
#include "stdinc.h"
#include "rsdb.h"
@ -47,7 +45,7 @@ mlog(const char *errstr, ...)
char buf[256];
va_list ap;
va_start(ap, errstr);
rb_vsnprintf(buf, sizeof(buf), errstr, ap);
vsnprintf(buf, sizeof(buf), errstr, ap);
va_end(ap);
error_cb(buf);
}
@ -73,14 +71,14 @@ rsdb_init(rsdb_error_cb * ecb)
if(sqlite3_open(dbpath, &rb_bandb) != SQLITE_OK)
{
rb_snprintf(errbuf, sizeof(errbuf), "Unable to open sqlite database: %s",
snprintf(errbuf, sizeof(errbuf), "Unable to open sqlite database: %s",
sqlite3_errmsg(rb_bandb));
mlog(errbuf);
return -1;
}
if(access(dbpath, W_OK))
{
rb_snprintf(errbuf, sizeof(errbuf), "Unable to open sqlite database for write: %s", strerror(errno));
snprintf(errbuf, sizeof(errbuf), "Unable to open sqlite database for write: %s", strerror(errno));
mlog(errbuf);
return -1;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,316 +0,0 @@
$Id: CIDR.txt 6 2005-09-10 01:02:21Z nenolod $
CIDR Information
----------------
Presently, we all use IPv4. The format of IPv4 is the following:
A.B.C.D
Where letters 'A' through 'D' are 8-bit values. In English, this
means each digit can have a value of 0 to 255. Example:
129.56.4.234
Digits are called octets. Oct meaning 8, hence 8-bit values. An
octet cannot be greater than 255, and cannot be less than 0 (eg. a
negative number).
CIDR stands for "classless inter domain routing", details covered
in RFC's 1518 and 1519. It was introduced mainly due to waste within
A and B classes space. The goal was to make it possible to use
smaller nets than it would seem from (above) IP classes, for instance
by dividing one B class into 256 "C like" classes. The other goal was
to allow aggregation of routing information, so that routers could use
one aggregated route (like 194.145.96.0/20) instead of
advertising 16 C classes.
Class A are all these addresses which first bit is "0",
bitmap: 0nnnnnnn.hhhhhhhh.hhhhhhhh.hhhhhhhh (n=net, h=host)
IP range is 0.0.0.0 - 127.255.255.255
Class B are all these addresses which first two bits are "10",
bitmap: 10nnnnnn.nnnnnnnn.hhhhhhhh.hhhhhhhh (n=net, h=host)
IP range is 128.0.0.0 - 191.255.255.255
Class C are all these addresses which first three bits are "110",
bitmap: 110nnnnn.nnnnnnnn.nnnnnnnn.hhhhhhhh (n=net, h=host)
IP range is 192.0.0.0 - 223.255.255.255
Class D are all these addresses which first four bits are "1110",
this is multicast class and net/host bitmap doesn't apply here
IP range is 224.0.0.0 - 239.255.255.255
I bet they will never IRC, unless someone creates multicast IRC :)
Class E are all these addresses which first five bits are "11110",
this class is reserved for future use
IP range is 240.0.0.0 - 247.255.255.255
So, here is how CIDR notation comes into play.
For those of you who have real basic exposure to how networks are
set up, you should be aware of the term "netmask." Basically, this
is a IPv4 value which specifies the "size" of a network. You can
assume the word "size" means "range" if you want.
A chart describing the different classes in CIDR format and their
wildcard equivalents would probably help at this point:
CIDR version dot notation (netmask) Wildcard equivalent
-----------------------------------------------------------------
A.0.0.0/8 A.0.0.0/255.0.0.0 A.*.*.* or A.*
A.B.0.0/16 A.B.0.0/255.255.0.0 A.B.*.* or A.B.*
A.B.C.0/24 A.B.C.0/255.255.255.0 A.B.C.* or A.B.C.*
A.B.C.D/32 A.B.C.D/255.255.255.255 A.B.C.D
The question on any newbies mind at this point is "So what do all
of those values & numbers actually mean?"
Everything relating to computers is based on binary values (1s and
zeros). Binary plays a *tremendous* role in CIDR notation. Let's
break it down to the following table:
A B C D
-------- -------- -------- --------
/8 == 11111111 . 00000000 . 00000000 . 00000000 == 255.0.0.0
/16 == 11111111 . 11111111 . 00000000 . 00000000 == 255.255.0.0
/24 == 11111111 . 11111111 . 11111111 . 00000000 == 255.255.255.0
/32 == 11111111 . 11111111 . 11111111 . 11111111 == 255.255.255.255
The above is basically a binary table for the most common netblock
sizes. The "1"s you see above are the 8-bit values for each octet.
If you split an 8-bit value into each of it's bits, you find the
following:
00000000
^^^^^^^^_ 1sts place (1)
|||||||__ 2nds place (2)
||||||___ 3rds place (4)
|||||____ 4ths place (8)
||||_____ 5ths place (16)
|||______ 6ths place (32)
||_______ 7ths place (64)
|________ 8ths place (128)
Now, since computers consider zero a number, you pretty much have
to subtract one (so-to-speak; this is not really how its done, but
just assume it's -1 :-) ) from all the values possible. Some
examples of decimal values in binary:
15 == 00001111 (from left to right: 8+4+2+1)
16 == 00010000 (from left to right: 16)
53 == 00110101 (from left to right: 32+16+4+1)
79 == 01001111 (from left to right: 64+8+4+1)
254 == 11111110 (from left to right: 128+64+32+16+8+4+2)
So, with 8 bits, the range (as I said before) is zero to 255.
If none of this is making sense to you at this point, you should
back up and re-read all of the above. I realize it's a lot, but
it'll do you some good to re-read it until you understand :-).
So, let's modify the original table a bit by providing CIDR info
for /1 through /8:
A B C D
-------- -------- -------- --------
/1 == 10000000 . 00000000 . 00000000 . 00000000 == 128.0.0.0
/2 == 11000000 . 00000000 . 00000000 . 00000000 == 192.0.0.0
/3 == 11100000 . 00000000 . 00000000 . 00000000 == 224.0.0.0
/4 == 11110000 . 00000000 . 00000000 . 00000000 == 240.0.0.0
/5 == 11111000 . 00000000 . 00000000 . 00000000 == 248.0.0.0
/6 == 11111100 . 00000000 . 00000000 . 00000000 == 252.0.0.0
/7 == 11111110 . 00000000 . 00000000 . 00000000 == 254.0.0.0
/8 == 11111111 . 00000000 . 00000000 . 00000000 == 255.0.0.0
At this point, all of this should making a lot of sense, and you
should be able to see the precision that you can get by using CIDR
at this point. If not, well, I guess the best way to put it would
be that wildcards always assume /8, /16, or /24 (yes hello Piotr,
we can argue this later: I am referring to IPs *ONLY*, not domains
or FQDNs :-) ).
This table will provide a reference to all of the IPv4 CIDR values
cidr|netmask (dot notation)
----+---------------------
/1 | 128.0.0.0
/2 | 192.0.0.0
/3 | 224.0.0.0
/4 | 240.0.0.0
/5 | 248.0.0.0
/6 | 252.0.0.0
/7 | 254.0.0.0
/8 | 255.0.0.0
/9 | 255.128.0.0
/10 | 255.192.0.0
/11 | 255.224.0.0
/12 | 255.240.0.0
/13 | 255.248.0.0
/14 | 255.252.0.0
/15 | 255.254.0.0
/16 | 255.255.0.0
/17 | 255.255.128.0
/18 | 255.255.192.0
/19 | 255.255.224.0
/20 | 255.255.240.0
/21 | 255.255.248.0
/22 | 255.255.252.0
/23 | 255.255.254.0
/24 | 255.255.255.0
/25 | 255.255.255.128
/26 | 255.255.255.192
/27 | 255.255.255.224
/28 | 255.255.255.240
/29 | 255.255.255.248
/30 | 255.255.255.252
/31 | 255.255.255.254
/32 | 255.255.255.255
So, let's take all of the information above, and apply it to a
present-day situation on IRC.
Let's say you have a set of flooding clients who all show up from
the following hosts. For lack-of a better example, I'll use a
subnet here at Best:
nick1 (xyz@shell9.ba.best.com) [206.184.139.140]
nick2 (abc@shell8.ba.best.com) [206.184.139.139]
nick3 (foo@shell12.ba.best.com) [206.184.139.143]
Most people will assume the they were all in the same class C
(206.184.139.0/24 or 206.184.139.*).
This, as a matter of fact, is not true. Now, the reason *I* know
this is solely because I work on the network here; those IPs are
not delegated to a class C, but two portions of a class C (128 IPs
each). That means the class C is actually split into these two
portions:
Netblock IP range
-------- --------
206.184.139.0/25 206.184.139.0 to 206.184.139.127
206.184.139.128/25 206.184.139.128 to 206.184.139.255
For the record, 206.184.139.0 and 206.184.139.128 are both known as
"network addresses" (not to be confused with "netblocks" or "Ethernet
hardware addresses" or "MAC addresses"). Network addresses are
*ALWAYS EVEN*.
206.184.139.127 and 206.184.139.255 are what are known as broadcast
addresses. Broadcast addresses are *ALWAYS ODD*.
Now, the aforementioned list of clients are in the 2nd subnet shown
above, not the first. The reason for this should be obvious.
The remaining question is, "Well that's nice, you know what the netblock
is for Best. What about us? We don't know that!"
Believe it or not, you can find out the network block size by using
whois -h WHOIS.ARIN.NET on the IP in question. ARIN keeps a list of
all network blocks and who owns them -- quite useful, trust me. I
think I use ARIN 5 or 6 times a day, especially when dealing with
D-lines. Example:
$ whois -h whois.arin.net 206.184.139.140
Best Internet Communications, Inc. (NETBLK-NBN-206-184-BEST)
345 East Middlefield Road
Mountain View, CA 94043
Netname: NBN-206-184-BEST
Netblock: 206.184.0.0 - 206.184.255.255
Maintainer: BEST
Does this mean you should D-line 206.184.0.0/16? Probably not.
That's an entire class B-sized block, while you're only trying
to deny access to a subnetted class C.
So then how do you get the *real* info? Well, truth is, you don't.
You have to pretty much take a guess at what it is, if ARIN reports
something that's overly vague. Best, for example, was assigned the
above class B-sized block. We can subnet it however we want without
reporting back to ARIN how we have it subnetted. We own the block,
and that's all that matters (to ARIN).
Not all subnets are like this, however. Smaller subnets you may
find partitioned and listed on ARIN; I've seen /29 blocks for DSL
customers show up in ARIN before.
So, use ARIN any chance you get. The more precision the better!
Now, there is a small issue I want to address regarding use of CIDR
notation. Let's say you D-line the following in CIDR format (hi
sion ;-) ):
205.100.132.18/24
Entries like this really makes my blood boil, solely because it adds
excessive confusion and is just basically pointless. If you
examine the above, you'll see the /24 is specifying an entire
class C -- so then what's the purpose of using .18 versus .0?
There IS no purpose. The netmask itself will mask out the .18 and
continue to successfully use 205.100.132.0/24.
Doing things this way just adds confusion, especially on non-octet-
aligned subnets (such as /8, /16, /24, or /32). Seeing that on a
/27 or a /19 might make people go "wtf?"
I know for a fact this doc lacks a lot of necessary information,
like how the actual netmask/CIDR value play a role in "masking out"
the correct size, and what to do is WHOIS.ARIN.NET returns no
netblock information but instead a few different company names with
NIC handles. I'm sure you can figure this stuff out on your own,
or just ask an administrator friend of yours who DOES know. A lot
of us admins are BOFH types, but if you ask us the right questions,
you'll benefit from the answer quite thoroughly.
Oh, I almost forgot. Most Linux systems use a different version of
"whois" than FreeBSD does. The syntax for whois on Linux is
"whois <INFO>@whois.arin.net", while under FreeBSD it is
"whois -h whois.arin.net <INFO>" Debian uses yet another version
of whois that is incompatible with the above syntax options.
Note that the FreeBSD whois client has shortcuts for the most commonly
used whois servers. "whois -a <INFO>" is the shortcut for ARIN.
Also note that ARIN is not authoritative for all IP blocks on the
Internet. Take for example 212.158.123.66. A whois query to ARIN
will return the following information:
$ whois -h whois.arin.net 212.158.123.66
European Regional Internet Registry/RIPE NCC (NET-RIPE-NCC-)
These addresses have been further assigned to European users.
Contact information can be found in the RIPE database, via the
WHOIS and TELNET servers at whois.ripe.net, and at
http://www.ripe.net/db/whois.html
Netname: RIPE-NCC-212
Netblock: 212.0.0.0 - 212.255.255.255
Maintainer: RIPE
This query tells us that it is a European IP block, and is further
handled by RIPE's whois server. We must then query whois.ripe.net
to get more information.
$ whois -h whois.ripe.net 212.158.123.66
% Rights restricted by copyright. See
http://www.ripe.net/ripencc/pub-services/db/copyright.html
inetnum: 212.158.120.0 - 212.158.123.255
netname: INSNET-P2P
descr: Point to Point Links for for London Nodes
country: GB
--snip--
This tells us the actual IP block that the query was a part of.
Other whois servers that you may see blocks referred to are:
whois.ripn.net for Russia, whois.apnic.net for Asia, Australia, and
the Pacific, and whois.6bone.net for IPv6 blocks.
Contributed by Jeremy Chadwick <jdc@best.net>
Piotr Kucharski <chopin@sgh.waw.pl>
W. Campbell <wcampbel@botbay.net> and
Ariel Biener <ariel@fireball.tau.ac.il>

View file

@ -1,61 +0,0 @@
$Id: Hybrid-team 54 2005-09-10 05:12:55Z nenolod $
The hybrid team is a group of ircd coders who were frustrated
with the instability and all-out "dirtiness" of the EFnet ircd's
available. "hybrid" is the name for the collective efforts of a group
of people, all of us.
Anyone is welcome to contribute to this effort. You are encouraged
to participate in the Hybrid mailing list. To subscribe to the
Hybrid List, use this link:
https://lists.ircd-hybrid.org/mailman/listinfo/hybrid
The core team as, of this major release:
adx, Piotr Nizynski <adx@irc7.pl>
billy-jon, William Bierman III <bill@mu.org>
cryogen, Stuart Walsh <stu@ipng.org.uk>
Dianora, Diane Bruce <db@db.net>
joshk, Joshua Kwan <joshk@triplehelix.org>
kire, Erik Small <smalle@hawaii.edu>
knight, Alan LeVee <alan.levee@prometheus-designs.net>
metalrock, Jack Low <jclow@csupomona.edu>
Michael, Michael Wobst <michael.wobst@gmail.com>
Rodder, Jon Lusky <lusky@blown.net>
Wohali, Joan Touzet <joant@ieee.org>
The following people have contributed blood, sweat, and/or code to
recent releases of Hybrid, in nick alphabetical order:
A1kmm, Andrew Miller <a1kmm@mware.virtualave.net>
AndroSyn, Aaron Sethman <androsyn@ratbox.org>
bane, Dragan Dosen <bane@idolnet.org>
bysin, Ben Kittridge <bkittridge@cfl.rr.com>
cosine, Patrick Alken <wnder@uwns.underworld.net>
David-T, David Taylor <davidt@yadt.co.uk>
fl, Lee Hardy <lee@leeh.co.uk>
Garion, Joost Vunderink <garion@efnet.nl>
Habeeb, David Supuran <habeeb@cfl.rr.com>
Hwy101, W. Campbell <wcampbel@botbay.net>
jmallett, Juli Mallett <jmallett@FreeBSD.org>
jv, Jakub Vlasek <jv@pilsedu.cz>
k9, Jeremy Chadwick <ircd@jdc.parodius.com>
kre, Dinko Korunic <kreator@fly.srk.fer.hr>
madmax, Paul Lomax <madmax@efnet.org>
nenolod, William Pitcock <nenolod@nenolod.net>
Riedel, Dennis Vink, <riedel@chaotic.nl>
scuzzy, David Todd <scuzzy@aniverse.net>
spookey, David Colburn <spookey@spookey.org>
TimeMr14C, Yusuf Iskenderoglu <uhc0@stud.uni-karlsruhe.de>
toot, Toby Verrall <to7@antipope.fsnet.co.uk>
vx0, Mark Miller <mark@oc768.net>
wiz, Jason Dambrosio <jason@wiz.cx>
Xride, Søren Straarup <xride@x12.dk>
zb^3, Alfred Perlstein <alfred@freebsd.org>
Others are welcome. Always. And if we left anyone off the above list,
be sure to let us know that too. Many others have contributed to
previous versions of this ircd and its ancestors, too many to list
here.
Send bug fixes/complaints/rotten tomatoes to bugs@ircd-hybrid.org.

36
doc/Makefile.am Normal file
View file

@ -0,0 +1,36 @@
prefix = @prefix@
exec_prefix = @exec_prefix@
exec_suffix = @exec_suffix@
bindir = @bindir@
libexecdir = @libexecdir@
sysconfdir = @sysconfdir@
localstatedir = @localstatedir@
# Local to the etc Makefile
CONFS = ircd.conf.example reference.conf
install-mkdirs:
-@if test ! -d $(DESTDIR)$(sysconfdir); then \
echo "mkdir -p $(sysconfdir)"; \
mkdir -p $(DESTDIR)$(sysconfdir); \
fi
install: install-mkdirs
@echo "ircd: installing example config files ($(CONFS))"
@for i in $(CONFS); do \
if test -f $(DESTDIR)$(sysconfdir)/$$i; then \
$(MV) $(DESTDIR)$(sysconfdir)/$$i $(DESTDIR)$(sysconfdir)/$$i.old; \
fi; \
$(INSTALL_DATA) $$i $(DESTDIR)$(sysconfdir); \
done
-@if test ! -f $(DESTDIR)$(sysconfdir)/ircd.motd; then \
echo "ircd: installing motd file (ircd.motd)"; \
$(INSTALL_DATA) ircd.motd $(DESTDIR)$(sysconfdir); \
fi
-@if test -f $(DESTDIR)$(sysconfdir)/links.txt; then \
$(RM) $(DESTDIR)$(sysconfdir)/links.txt; \
fi

View file

@ -1,92 +0,0 @@
# $Id: Makefile.in 3376 2007-04-03 11:37:39Z nenolod $
CC = @CC@
INSTALL = @INSTALL@
INSTALL_BIN = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SUID = @INSTALL_PROGRAM@ -o root -m 4755
RM = @RM@
LEX = @LEX@
LEXLIB = @LEXLIB@
CFLAGS = @IRC_CFLAGS@ -DIRCD_PREFIX=\"@prefix@\"
LDFLAGS = @LDFLAGS@
MKDEP = ${CC} -MM
MV = @MV@
RM = @RM@
CP = @CP@
TOUCH = @TOUCH@
PROGRAM_PREFIX = @PROGRAM_PREFIX@
prefix = @prefix@
exec_prefix = @exec_prefix@
exec_suffix = @exec_suffix@
bindir = @bindir@
libexecdir = @libexecdir@
sysconfdir = @sysconfdir@
localstatedir = @localstatedir@
# Change this later! -- adrian
moduledir = @moduledir@
automoduledir = @moduledir@/autoload
# Local to the etc Makefile
mandir = @mandir@/man8
MANPAGES = ircd.8
CONFS = ircd.conf.example reference.conf
SSL_LIBS = @SSL_LIBS@
SSL_INCLUDES = @SSL_INCLUDES@
IRCDLIBS = @LIBS@ $(SSL_LIBS)
INCLUDES = -I../include $(SSL_INCLUDES)
CPPFLAGS = ${INCLUDES} @CPPFLAGS@
all: build
install-mkdirs:
-@if test ! -d $(DESTDIR)$(sysconfdir); then \
echo "mkdir -p $(sysconfdir)"; \
mkdir -p $(DESTDIR)$(sysconfdir); \
fi
-@if test ! -d $(DESTDIR)$(mandir); then \
echo "mkdir -p $(mandir)"; \
mkdir -p $(DESTDIR)$(mandir); \
fi
install: install-mkdirs build
@echo "ircd: installing example config files ($(CONFS))"
@for i in $(CONFS); do \
if test -f $(DESTDIR)$(sysconfdir)/$$i; then \
$(MV) $(DESTDIR)$(sysconfdir)/$$i $(DESTDIR)$(sysconfdir)/$$i.old; \
fi; \
$(INSTALL_DATA) $$i $(DESTDIR)$(sysconfdir); \
done
-@if test ! -f $(DESTDIR)$(sysconfdir)/ircd.motd; then \
echo "ircd: installing motd file (ircd.motd)"; \
$(INSTALL_DATA) ircd.motd $(DESTDIR)$(sysconfdir); \
fi
-@if test -f $(DESTDIR)$(sysconfdir)/links.txt; then \
$(RM) $(DESTDIR)$(sysconfdir)/links.txt; \
fi
@echo "ircd: installing manpage"
@for i in $(MANPAGES); do \
if test ! -f $(DESTDIR)$(mandir)/$(PROGRAM_PREFIX)$$i; then \
$(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/$(PROGRAM_PREFIX)$$i; \
fi; \
done
build:
clean:
depend:
lint:
distclean:
${RM} -f Makefile

View file

@ -1,17 +0,0 @@
$Id: README.cidr_bans 6 2005-09-10 01:02:21Z nenolod $
Basically what this patch does is allow for users to use cidr masks when
setting bans, exceptions, and invite invex(modes beI respectively). This
works for both IPv4 and IPv6 addresses.
I won't go into details of how cidr works here, but to use them, you could
do something like:
/mode #foo +b *!*@10.0.0.0/8
/mode #foo +e *!*@10.0.10.0/24
Aaron Sethman <androsyn@ratbox.org>
August 06, 2002

View file

@ -1,18 +0,0 @@
$Id: Ratbox-team 1640 2006-06-05 00:02:19Z jilles $
ircd-ratbox is an evolution where ircd-hybrid left off around version 7-rc1.
Currently the ircd-ratbox team consists of the following developers:
AndroSyn, Aaron Sethman <androsyn -at- ratbox.org>
anfl, Lee Hardy <lee -at- leeh.co.uk>
Special thanks for support, code and ideas to:
Hwy, W. Campbell <wcampbel -at- botbay.net>
jilles, Jilles Tjoelker <jilles -at- stack.nl>
larne, Edward Brocklesby <ejb -at- sdf.lonestar.org>
Of course our work is based on the work of many, many others over the past
10 or so years since irc has existed, including the work done by the Hybrid
team, our thanks goes to them.

View file

@ -1,272 +0,0 @@
The Tao of Internet Relay Chat
Copyright (C) Ove Ruben R Olsen 1994
Version of 940110
Contributing masters: Master ScottM
-----
Something is formed by the electrons, born in the silent cable. Shaping
and growing and ungrowing. It is there yet not there. It is the source of
Internet Relay Chat. I do not know the name, thus I will call it the Tao
of Internet Relay Chat.
If the Tao is great, then the IRC is running ceaselessly. If the IRC is
great then the server is running without ever stoping. If the server is
great then the client will always be the server. The luser is then pleased
and there is Chat in the world.
The Tao of IRC squits far away and connects on returning.
-----
The genetic potential of birth, a lot to know, yet unknown.
In the begining there was nothing.
Out of nothing the Tao gave birth to tolsun.oulu.fi. tolsun gave birth to
OuluBox.
OuluBox gave birth to rmsg.
rmsg was not Tao, so MUT gave birth to IRC.
No one knows when IRC came into existance, the mighty master WiZ have it
to be at the end of the eight month in the year of the Dragon.
-----
Each channel has its purpose, however humble. Each channel is the Yin and
Yang of IRC. Each channels has it's place within the IRC.
In the beginning there was only channel 0, thus channel 0 is the soil of
IRC.
Channel 1 to channel 10 then was open as the sea. Channel 11 to 999 was the
trees and forests of IRC. Channels above 999 should not be mentioned, and
channels below 0 were unborn and contained many secrets.
This was not the right Tao, so IRC gave birth to +channels.
+channels had the yin and yang. Mode does not.
This was not the right Tao still, so IRC gave birth to #channels.
#channels have the yin and yang.
Only channel 0 is the right path to Tao, but avoid speaking on channel 0.
-----
There was a great dispute among the Broom-Walkers of the Relay. Some of them
wanted neither yin nor yang. Out of this Eris came into existance. Some of the
Broom-Walkers then created Eris Free-net.
This was the right Tao.
Kind Gentle and Boring Net was another wrong path to the Tao of Internet Relay
Chat.
Some time later there was a quantity of some lusers who wanted to be
Broom-Walkers also. The Eris Free Broom-Walkers did not agree with them,
thus a new IRC was born. This IRC is called the Undernet.
But this is not the right Tao, either.
-----
There will always be disputes among the Broom-Walkers of Internet Relay Chat.
This is the very nature of the IRC.
-----
Lusers that do not understand the Tao is always using the yang of Mode on
their channels. Lusers that do understand the Tao are always using Ignore
on their channels.
How could this not be so ?
-----
The wise sage luser is told about the Chat and uses it. The luser is told
about the IRC and is looking for it. The flock are told about the Tao and
make a fool of the IRC.
If there was no laughter, there would be no Tao.
-----
The master says:
"Without the Tao of Internet Relay Chat, life becomes meaningless."
The Relay of the old time was mysterious and sacred. We can neither imagine
its thoughts nor path; we are left but to describe.
-----
The sage luser must be aware like a frog crossing the highway.
-----
The great master Wumpus once dreamed that he was an automaton. When he awoke
he exclaimed:
"I don't know whether I am Wumpus dreaming that I am a client,
or a client dreaming that I am Wumpus!"
So was the first Automata born.
The master Nap then said:
"Any automata should not speak unless spoken to.
Any automata shall only whisper when spoken to."
Thus replied the master Gnarfer:
"The lusers shall keep in mind that a automata can be either good or
bad. Create good automata, and the IRC will hail you and you will
gain fame and fortune. Create bad automata and people will start to
hate you, and finaly you will be /KILLed to ethernal damnation"
Many lusers have fallen into the clutches of ethernal damnation. They where
not following the Tao.
-----
There once was a luser who went to #BotSex. Each day he saw the automatons.
The luser decided that he also would have such a automata.
He asked another luser for his automata. The other luser gave his automata
away.
The luser was not within the Tao, so he just started the automata. The automata
had only Yang inside so all the lusers files where deleted.
Some moons laither the same luser then had become a sage luser, and did create
his automata from the very grounds with materials found inside the IRC.
The luser was now within the Tao and his automata lived happily ever after.
-----
There once was a master who wrote automatons without the help of master Phone.
A novice luser, seeking to imitate him, began with the help of master Phone.
When the novice luser asked the master to evaluate his automata the master
replied: "What is a working automata for the master is not for the luser.
You must must BE the IRC before automating."
-----
Master BigCheese gave birth to master Troy; his duty clear. Master Troy gave
birth to master Phone, for the Tao of Irc must be eternal and must flow as the
ceaseless river of Time itself.
-----
Master Phone once said about the ircII client:
"public_msg is for a message from someone NOT on the channel
public_other is for a message on a channel that doesn't belong to
a window. public is for a message on a channel that belongs to a
window!"
Out of this raised the mighty chaos.
-----
The sage luser came to the master who wrote automata without the help of
master Phone. The sage luser asked the master who wrote automata: "Which is
easiest to make. A automata with the help of master Phone or an automata
made with the help of a language ?"
The master who wrote automata then replied:
"With the help of a language."
The sage luser was disapointed and exclaimed: "But, with master Phone you
do not need to know anything about the soil of IRC. Is not that the easiet
way ?"
"Not really" said the master who wrote automata, "when using master Phone
you are closed inside a box. For sure, it is a great box for the lusers,
but the master will need more power, thus a language is the only path to go.
With the language the master will never have to limit himself. When using
such a language the master will seek the best between the need and the
availibility."
"I see", said the sage luser.
This is the essence of Tao of IRC automatas.
-----
A client should be light and be used for communication. The spirit of a good
client is that it should be very convinient for the luser to use, but hard
for the luser who want to create automata.
There should never ever be too many functions or too few functions.
There should always be a ignore.
Without ignore the client is not within the Tao of Chating.
The client should always respond the luser with messages that will not
astnonish him too much. The server likewise. If the server does not, then it
is the clients job to explain what the server says.
A client which fails this, will be useless and cause confusion for the lusers.
The only way to correct this is to use another client or to write a new one.
-----
A luser asked the masters on #IrcHelp: "My client does not work".
The masters replied: "Upgrade your client".
The luser then wondered why the master knew. The master then told him about
the Protocol.
"Your client does not work beaucse it does not understand the server. Why
should it always work ? Only a fool would expect such. But, clients are made
by humans, and humans are not perfect. Only Tao is.
The IRC is solid. The IRC is floating, and will always be dynamic. Live with
that or /quit."
-----
The luser came to the masters of #IrcHelp, asking about the Tao of IRC within
the client.
The masters then said that the Tao of IRC always lies inside the client
regardless of how the client connects to the server.
"Is the Tao in irc ?" asked the luser.
"It so is" replied the masters of #IrcHelp.
"Is the Tao in the ircII, Kiwi, rxirc, vms, rockers and msa ?" asked the
luser.
"In all of them and in the TPC, irchat, zenirc, zircon X11-irc and even the
dos irc has the Tao" said the master quietly.
"Is the Tao in a telnet connection directly to the server ?"
The master then was quiet for a long time and said. "Please leave, such
questions are not within the Tao of IRC".
-----
The master says: "Without the Protocol of TCP the messages will not travel.
Without the client, the server is useless."
-----
There once was a luser who used the ircII client. "ircII can do anything I
ever need for using IRC" said the emacs client user, "I have /ON's, I have
assignments, I have aliasing. Why don't you use this instead of the huge
emacs client, which also has a messy screen?"
The emacs client user then replied by saying that "it is better to have a
scripting language that is the client instead of have a client that has
a scripting language." Upon hearing this, the ircII client luser fell silent.
-----
The master Wumpus said: "Time for you to leave. I did, now I'm happy."
The master Gnarfer replied: "Use, but never overuse IRC, then you will also
be happy within IRC"
-----
A luser came unto the masters of #EU-Opers and asked, "How can I be, yet not
be, a user@host within the IRC?"
The masters of #EU-Opers replied: "To be Tao is to be ones true self. To hide
ones self is not Tao, and is not IRC, you have much to learn before you shall
be at rest within the Flow of Irc. Please leave"

129
doc/connecting-servers.rst Normal file
View file

@ -0,0 +1,129 @@
Connecting servers
==================
Servers can be connected together to improve redundancy, distribute bandwidth,
lower latency, and connect network services.
This document is an introduction to connecting servers. It assumes you are
already somewhat familiar with Solanum's configuration (if not, read
:file:`ircd.conf.example`, and set up your own server by editing it
and running Solanum).
Solanum uses the TS6 protocol, and can only be connected with other servers
using this protocol. We recommend you only connect Solanum with other Solanum
instances.
Unlike some other IRCd implementations, all connections are reciprocal in
Solanum, which means a single configuration block is used for both incoming
and outgoing connections.
Additionally, the same ports are used for server and client connections.
Creating servers
----------------
If you already have a server running, copy its configuration to a new machine,
and edit ``serverinfo`` for the new server. In particular, you must change the
``name`` and ``sid``, but keep the same ``network_name``.
We recommend you keep both configurations in sync using some external
configuration management systems, so server configurations do not drift apart
over time, as you change them.
For each of the two servers, you must create a ``connect`` block to represent
the connection with the other server. For example, if you have servers A and B
respectively at a.example.org and b.example.org, use respectively::
serverinfo {
name = "a.example.org";
// ...
};
connect "b.example.org" {
host = "203.0.113.2";
port = 6666;
send_password = "password";
accept_password = "anotherpassword";
flags = topicburst, autoconn;
class = "server";
};
and::
serverinfo {
name = "b.example.org";
// ...
};
connect "a.example.org" {
host = "203.0.113.1";
port = 6666;
send_password = "anotherpassword";
accept_password = "password";
flags = topicburst, autoconn;
class = "server";
};
Note the reversed passwords.
The ports should be any of the ports defined in a ``listen {}`` block of the
other server.
The ``autoconn`` flag indicates a server should automatically connect using
this ``connect {}`` block. At least one of the two servers should have it,
or the servers won't try to connect.
If you are connecting servers over an unencrypted link, you should use SSL/TLS
for the connection; see :file:`reference.conf`.
Connecting services
-------------------
In addition to regular servers, you can also connect service packages such
as atheme-services.
These services typically do not accept incoming connections, and connect to
one of the existing servers of the network.
To allow connections from such a service server, you should create
a new ``connect {}`` block for this package, on the server the services
will connect to::
connect "services.example.org" {
host = "localhost";
port = 6666;
send_password = "password";
accept_password = "anotherpassword";
flags = topicburst; // No autoconn, services don't accept incoming connections
class = "server";
};
And create the appropriate config in your services' configuration so that
they connect to your server on the configured port, and from the configured
hostname.
For example, with atheme::
loadmodule "modules/protocol/solanum";
uplink "a.example.org" {
host = "localhost";
port = 6666;
send_password = "anotherpassword";
receive_password = "password"
};
Finally, you must configure all servers in your network to recognize the
services server::
service {
name = "services.example.org";
};

276
doc/credits-past.txt Normal file
View file

@ -0,0 +1,276 @@
===============================================================================
IRCD 2.8 CREDITS
===============================================================================
/************************************************************************
* IRC - Internet Relay Chat, doc/AUTHORS
* Copyright (C) 1990
*
* AUTHORS FILE:
* This file attempts to remember all contributors to the IRC
* developement. Names can be only added this file, no name
* should never be removed. This file must be included into all
* distributions of IRC and derived works.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
IRC was conceived of and written by Jarkko Oikarinen <jto@tolsun.oulu.fi>.
IRC was originally written in University of Oulu, Computing Center.
Jan 1991 - IRC 2.6 jto@tolsun.oulu.fi
- Multiple Channels and protocol changes
Contributions were made by a cast of dozens, including the following:
Markku Jarvinen <mta@tut.fi>: Emacs-like editing facility for the client
Kimmo Suominen <kim@kannel.lut.fi>: HP-UX port
Jeff Trim <jtrim@orion.cair.du.edu>: enhancements and advice
Vijay Subramaniam <vijay@lll-winken.llnl.gov>: advice and ruthless publicity
Karl Kleinpaste <karl@cis.ohio-state.edu>: user's manual
Greg Lindahl <gl8f@virginia.edu>: AUTOMATON code, the Wumpus GM automaton,
myriad bug fixes
Bill Wisner <wisner@hayes.fai.alaska.edu>: numerous bug fixes and code
enhancements
Tom Davis <conslt16@zeus.unl.edu> and Tim Russell <russell@zeus.unl.edu>:
VMS modifications
Markku Savela <msa@tel4.tel.vtt.fi>: advice, support, and being the
incentive to do some of our *own* coding. :)
Tom Hopkins <hoppie@buengf.bu.edu>: bug fixes, quarantine lines,
consolidation of various patches.
Christopher Davis <ckd@cs.bu.edu>: EFnet/Anet gateway coding,
many automata ;), documentation fixing.
Helen Rose <hrose@cs.bu.edu>: documentation updating, and fixing.
Tom Hinds <rocker@bucsf.bu.edu>: emacs client updating.
Tim Miller <cerebus@bu-pub.bu.edu>: various server and client-breaking
features.
Darren Reed <avalon@coombs.anu.edu.au>: various bug fixes and enhancements.
Introduced nickname and channelname hash tables into the server.
The version 2.2 release was coordinated by Mike Bolotski
<mikeb@salmon.ee.ubc.ca>.
The version 2.4 release was coordinated by Markku Savela and
Chelsea Ashley Dyerman
The version 2.5.2 release was coordinated by Christopher Davis, Helen Rose,
and Tom Hopkins.
The versions 2.6.2, 2.7 and 2.8 releases were coordinated by Darren Reed.
Contributions for the 2.8 release from the following people:
Matthew Green <phone@coombs.anu.edu.au>
Chuck Kane <ckane@ece.uiuc.edu>
Matt Lyle <matt@oc.com>
Vesa Ruokonen <ruokonen@lut.fi>
Markku Savela <Markku.Savela@vtt.fi> / April 1990
Fixed various bugs in 2.2PL1 release server (2.2msa.4) and changed
sockets to use non-blocking mode (2.2msa.9). [I have absolutely
nothing to do with clients :-]
Chelsea Ashley Dyerman <chelsea@earth.cchem.berkeley.edu> / April 1990
Rewrote the Makefiles, restructuring of source tree. Added libIrcd.a to
the Makefile macros, numerous reformatting of server text messages, and
added mkversion.sh to keep track of compilation statistics. Numerous
bug fixes and enhancements, and co-coordinator of the 2.4 release.
jarlek@ifi.uio.no added mail functions to irc.
Armin Gruner <gruner@informatik.tu-muenchen.de> / May, June 1990:
* Patched KILL-line feature for ircd.conf, works now.
Enhancement: Time intervals can be specified in passwd-field.
Result: KILL-Line is only active during these intervals
* Patched PRIVMSG handling, now OPER can specify masks for sending
private messages, advantage: msg to all at a specified server or host.
* Little tests on irc 2.5 alpha, fixed some little typos in client code.
Change: common/debug.c has been moved to ircd/s_debug.c, and a
irc/c_debug.c has been created, for the benefit that wrong server msg
are displayed if client does not recognize them. (strange, if a server
sends an 'unknown command', isn't it?)
Tom Hopkins <hoppie@buengf.bu.edu> / September, October 1990:
* Patched msa's K lines for servers (Q lines).
* Consolidated several patches, including Stealth's logging patch.
* Fixed several minor bugs.
* Has done lots of other stuff that I can't seem to remember, but he
always works on code, so he has to have done alot more than three
lines worth. :)
Thanks go to those persons not mentioned here who have added their advice,
opinions, and code to IRC.
Various modifications, bugreports, cleanups and testing by:
Hugo Calendar <hugo@ucscb.ucsc.edu>
Bo Adler <adler@csvax.cs.caltech.edu>
Michael Sandrof <ms5n+@andrew.cmu.edu>
Jon Solomon <jsol@cs.bu.edu>
Jan Peterson <jlp@hamblin.math.byu.edu>
Nathan Glasser <nathan@brokaw.lcs.mit.edu>
Helen Rose <hrose@eff.org>
Mike Pelletier <stealth@caen.engin.umich.edu>
Basalat Ali Raja <gwydion@tavi.rice.edu>
Eric P. Scott <eps@toaster.sfsu.edu>
Dan Goodwin <fornax@wpi.wpi.edu>
Noah Friedman <friedman@ai.mit.edu>
===============================================================================
IRCD-HYBRID CREDITS
===============================================================================
The hybrid team is a group of ircd coders who were frustrated
with the instability and all-out "dirtiness" of the EFnet ircd's
available. "hybrid" is the name for the collective efforts of a group
of people, all of us.
Anyone is welcome to contribute to this effort. You are encouraged
to participate in the Hybrid mailing list. To subscribe to the
Hybrid List, use this link:
https://lists.ircd-hybrid.org/mailman/listinfo/hybrid
The core team as, of this major release:
adx, Piotr Nizynski <adx@irc7.pl>
billy-jon, William Bierman III <bill@mu.org>
cryogen, Stuart Walsh <stu@ipng.org.uk>
Dianora, Diane Bruce <db@db.net>
joshk, Joshua Kwan <joshk@triplehelix.org>
kire, Erik Small <smalle@hawaii.edu>
knight, Alan LeVee <alan.levee@prometheus-designs.net>
metalrock, Jack Low <jclow@csupomona.edu>
Michael, Michael Wobst <michael.wobst@gmail.com>
Rodder, Jon Lusky <lusky@blown.net>
Wohali, Joan Touzet <joant@ieee.org>
The following people have contributed blood, sweat, and/or code to
recent releases of Hybrid, in nick alphabetical order:
A1kmm, Andrew Miller <a1kmm@mware.virtualave.net>
AndroSyn, Aaron Sethman <androsyn@ratbox.org>
Ariadne, Ariadne Conill <ariadne@dereferenced.org>
bane, Dragan Dosen <bane@idolnet.org>
bysin, Ben Kittridge <bkittridge@cfl.rr.com>
cosine, Patrick Alken <wnder@uwns.underworld.net>
David-T, David Taylor <davidt@yadt.co.uk>
fl, Lee Hardy <lee@leeh.co.uk>
Garion, Joost Vunderink <garion@efnet.nl>
Habeeb, David Supuran <habeeb@cfl.rr.com>
Hwy101, W. Campbell <wcampbel@botbay.net>
jmallett, Juli Mallett <jmallett@FreeBSD.org>
jv, Jakub Vlasek <jv@pilsedu.cz>
k9, Jeremy Chadwick <ircd@jdc.parodius.com>
kre, Dinko Korunic <kreator@fly.srk.fer.hr>
madmax, Paul Lomax <madmax@efnet.org>
Riedel, Dennis Vink, <riedel@chaotic.nl>
scuzzy, David Todd <scuzzy@aniverse.net>
spookey, David Colburn <spookey@spookey.org>
TimeMr14C, Yusuf Iskenderoglu <uhc0@stud.uni-karlsruhe.de>
toot, Toby Verrall <to7@antipope.fsnet.co.uk>
vx0, Mark Miller <mark@oc768.net>
wiz, Jason Dambrosio <jason@wiz.cx>
Xride, Søren Straarup <xride@x12.dk>
zb^3, Alfred Perlstein <alfred@freebsd.org>
Others are welcome. Always. And if we left anyone off the above list,
be sure to let us know that too. Many others have contributed to
previous versions of this ircd and its ancestors, too many to list
here.
Send bug fixes/complaints/rotten tomatoes to bugs@ircd-hybrid.org.
===============================================================================
IRCD-RATBOX CREDITS
===============================================================================
ircd-ratbox is an evolution where ircd-hybrid left off around version 7-rc1.
Currently the ircd-ratbox team consists of the following developers:
AndroSyn, Aaron Sethman <androsyn -at- ratbox.org>
anfl, Lee Hardy <lee -at- leeh.co.uk>
Special thanks for support, code and ideas to:
Hwy, W. Campbell <wcampbel -at- botbay.net>
jilles, Jilles Tjoelker <jilles -at- stack.nl>
larne, Edward Brocklesby <ejb -at- sdf.lonestar.org>
Of course our work is based on the work of many, many others over the past
10 or so years since irc has existed, including the work done by the Hybrid
team, our thanks goes to them.
===============================================================================
CHARYBDIS CREDITS
===============================================================================
Charybdis started as an evolution from ircd-ratbox. Its development
is led by a team of dedicated developers who have put a lot of time
into the project and it has seen use on a variety of different
network configurations.
The Charybdis core team, listed in nick-alphabetical order:
amdj, Aaron Jones <aaronmdjones -at- gmail.com>
Ariadne, Ariadne Conill <ariadne -at- dereferenced.org>
Elizafox, Elizabeth Myers <elizabeth -at- interlinked.me>
jilles, Jilles Tjoelker <jilles -at- stack.nl>
mr_flea, Keith Buck <mr_flea -at- esper.net>
The following people are also project members, listed in nick-alphabetical
order:
jdhore, JD Horelick <jdhore1 -at- gmail.com>
viatsko, Valerii Iatsko <dwr -at- codingbox.io>
The following people have made contributions to the Charybdis releases,
in nick-alphabetical order:
AndroSyn, Aaron Sethman <androsyn -at- ratbox.org>
anfl, Lee Hardy <lee -at- leeh.co.uk>
beu, Elfyn McBratney <elfyn.mcbratney -at- gmail.com>
BlindSight, Matt Ullman <matt -at- airraidsirens.com>
Entrope, Michael Poole <mdpoole -at- trolius.org>
grawity, Mantas Mikulėnas <grawity -at- gmail.com>
gxti, Michael Tharp <gxti -at- partiallystapled.com>
mniip <mniip -at- mniip.com>
Simon, Simon Arlott
spb, Stephen Bennett <spb -at- attenuate.org>
Taros, Brett Greenham <taros -at- shadowircd.net>
ThaPrince, Jon Christopherson <jon -at- vile.com>
twincest, River Tarnell <river -at- attenuate.org>
w00t, Robin Burchell <surreal.w00t -at- gmail.com>
For a list of contributors to ircd-ratbox, ircd-hybrid, and ircd2.8 (the
predecessors to Charybdis), see the doc/credits-past.txt file in the Charybdis
distribution.
Visit the Charybdis website at: http://www.charybdis.io/
Visit us on IRC at: irc.charybdis.io #charybdis

View file

@ -1,7 +1,7 @@
account-notify client capability specification
----------------------------------------------
Copyright (c) 2010 William Pitcock <nenolod@atheme.org>.
Copyright (c) 2010 Ariadne Conill <ariadne@dereferenced.org>.
Unlimited redistribution and modification of this document is allowed
provided that the above copyright notice and this permission notice

View file

@ -51,9 +51,6 @@ If aes256 is not available, the following is used instead:
- Building ratbox-respond -
---------------------------
If you are using the unix based ratbox-respond this must be built. For the
windows version, ratbox-winrespond, please see http://respond.ircd-ratbox.org
ratbox-respond takes the challenge from the server, and together with your
private key file generates a response to be sent back. ratbox-respond
requires the openssl headers (ie, development files) and openssl libraries
@ -82,5 +79,3 @@ ratbox-respond/README for more information.
A number of scripts for clients have already been written to automate this
process, see client-scripts/README for more information.
--
$Id: challenge.txt 678 2006-02-03 20:25:01Z jilles $

View file

@ -43,5 +43,3 @@ the same on all servers for each nick-user pair, also if a user with a UID
nick changes their nick but is collided again (the server detecting the
collision will not propagate the nick change further).
--
$Id: collision_fnc.txt 3422 2007-04-22 14:35:28Z jilles $

View file

@ -42,6 +42,10 @@ exists and is not +s or +p. (The ops of the channel the ban is on cannot
necessarily see whether the user is in the target channel, so it should not
influence whether they can join either.)
extb_canjoin.so
$j:<channel>
matches users who are or are not banned from a specified channel
extb_oper.so
$o
matches opers (most useful with +I)
@ -56,6 +60,14 @@ extb_server.so
matches users connected to a server matching the mask (* and ? wildcards);
this can only be used with +b and +q
extb_extgecos.so
$x:<mask>
bans all users with matching nick!user@host#gecos
extb_ssl.so
$z
matches all SSL users
Comparisons:
+b $~a is similar to +r but also prevents not logged in users talking or
@ -88,5 +100,3 @@ The function is called whenever a (local) client needs to be checked against
a +bqeI entry of the given extban type, and whenever a local client tries to
add such an entry. (Clients are allowed to add bans matching themselves.)
--
$Id: extban.txt 1639 2006-06-04 23:26:47Z jilles $

59
doc/features/filter.txt Normal file
View file

@ -0,0 +1,59 @@
extensions/filter module documentation
--------------------------------------
The filter extension implements message content filtering using
solanum's hook framework and Intel's Hyperscan regular expression
matching library.
It requires an x86_64 processor with SSSE3 extensions.
To operate, the filter requires a database of regular expessions
that have been compiled using the Hyperscan library's
hs_compile_multi() or hs_compile_ext_multi() functions.
The command SETFILTER is used to manage operation of the filter and to
load compiled Hyperscan databases.
General documenation of SETFILTER is available using the 'HELP SETFILTER'
command.
For each expression in the database, the three least significant bits
of the expression ID are used to indicate which action the ircd should
take in the event of a match:
001 (1) DROP - The message will be dropped and the client will be sent
an ERR_CANNOTSENDTOCHAN message.
010 (2) KILL - The connection from which the message was recevied will
be closed.
100 (4) ALARM - A Server Notice will be generated indicating that an
expression was matched. The nick, user, hostname and
IP address will be reported. For privacy, the expression
that has been matched will not be disclosed.
Messages are passed to the filter module in a format similar to an
IRC messages:
0:nick!user@host#1 PRIVMSG #help :hello!
The number at the start of the line indicates the scanning pass:
Messages are scanned twice, once as they were received (0), and once
with any formatting or unprintable characters stripped (1).
By default, 'nick', 'user' and 'host' will contain *. This behaviour
can be changed at build time if filtering on these fields is required.
The number after the # will be 0 or 1 depending on whether the sending
client was identified to a NickServ account.
The process for loading filters is as follows:
1. The Hyperscan database is serialized using hs_serialize_database().
2. A 'SETFILTER NEW' command is sent.
3. The serialized data is split into chunks and base64 encoded.
The chunk size needs to be chosen to ensure that the resuliting
strings are short enough to fit into a 510 byte IRC line, taking
into account space needed for the 'SETFILTER +' command, check field,
server mask, and base64 overhead.
4. The encoded chunks are sent using 'SETFILTER +' commands
5. Once the entire database has been sent, a 'SETFILTER APPLY' command
is sent to commit it.

15
doc/features/index.txt Normal file
View file

@ -0,0 +1,15 @@
Here is an overview of the docs in the doc/features directory.
account-notify.txt - Description of the account-notify system
away-notify.txt - Description of the away-notify system
challenge.txt - Overview of the challenge/response system for
obtaining operator status
collision_fnc.txt - Overview of the SAVE nick collision method
extban.txt - Description of extended bans
extended-join.txt - Description of the extended-join system
modeg.txt - Description of UMODE +g, the caller ID system
monitor.txt - Description of the MONITOR system
sasl.txt - Description of the SASL services authentication
system
services.txt - Overview of features added by services
tgchange.txt - Overview of the target change system

View file

@ -78,7 +78,7 @@ Note that some clients may have to use /quote ACCEPT instead of /accept.
--
Client Hwy101: /msg Hwy-LL hi
Hwy101 will see: -!- Hwy-LL is in +g mode (server-side ignore.)
Hwy101 will see: -!- Hwy-LL is in +g mode and must manually allow you to message them.
-!- Hwy-LL has been informed that you messaged them.
Hwy-LL will see: -!- Hwy101 wcampbel@admin.irc.monkie.org is messaging you, and you have umode +g.
@ -86,7 +86,7 @@ Hwy-LL will see: -!- Hwy101 wcampbel@admin.irc.monkie.org is messaging you, and
--
If Hwy101 sends another message to Hwy-LL (before the minute expires), he will
see: -!- Hwy-LL is in +g mode (server-side ignore.)
see: -!- Hwy-LL is in +g mode and must manually allow you to message them.
and will not receive the second notice
Hwy-LL will NOT see any notice. This also applies if the second message comes
@ -189,7 +189,7 @@ their accept list.
716 - ERR_TARGUMODEG
--------------------
:<server> 716 <nick> <target> :is in +g mode (server-side ignore.)
:<server> 716 <nick> <target> :is in +g mode and must manually allow you to message them.
This numeric is used to indicate that a message (PRIVMSG) the client sent
could not be delivered because of CallerID restrictions. The <target>
@ -215,4 +215,3 @@ which is ambiguous if the user may contain a [ and in the author's opinion ugly.
--
W. Campbell
updated by J. Tjoelker
$Id: modeg.txt 3556 2007-08-18 14:45:10Z jilles $

View file

@ -1,6 +1,5 @@
MONITOR - Protocol for notification of when clients become online/offline
Lee Hardy <lee -at- leeh.co.uk>
$Id: monitor.txt 3520 2007-06-30 22:15:35Z jilles $
-------------------------------------------------------------------------
Currently, ISON requests by clients use a large amount of bandwidth. It is

View file

@ -127,4 +127,3 @@ Kucharski (IRCnet), IRC Client Capabilities Extension. March 2005.
This internet-draft has expired; it can still be found on
http://www.leeh.co.uk/draft-mitchell-irc-capabilities-02.html
$Id: sasl.txt 3169 2007-01-28 22:13:18Z jilles $

View file

@ -1,9 +1,12 @@
ratbox-services compatibility documentation - Lee H <lee -at- leeh.co.uk>
-------------------------------------------------------------------------
Services compatibility documentation
------------------------------------
Compatibility with ratbox-services is always enabled. Note that some or
all of this is also used by atheme-services and anope. It will add the
following features to ircd:
Originally written by Lee Hardy for ircd-ratbox. Minor changes by Elizabeth
Myers for modern services.
Compatibility with services is always enabled. Supported services include
atheme and anope. They add the following features to Charybdis:
1. Channel mode +r
@ -17,8 +20,8 @@ following features to ircd:
Ability to specify the names of services servers in ircd.conf:
service {
name = "services.ircd-ratbox.org";
name = "backup-services.ircd-ratbox.org";
name = "services.charybdis.io";
name = "backup-services.charybdis.io";
};
These must be specified for certain features to work. You may specify as
@ -60,4 +63,3 @@ following features to ircd:
Gives numeric 486 to users sending a PRIVMSG who are not logged in:
:<server> 486 <nick> <targetnick> :You must log in with services to message this user
# $Id: services.txt 6 2005-09-10 01:02:21Z nenolod $

View file

@ -41,6 +41,3 @@ you are messaging that channel or a client within that channel. The latter
can be done explicitly using the CNOTICE and CPRIVMSG commands, see
/quote help cnotice and /quote help cprivmsg, but is also implicit in a
normal /msg, /notice or /invite.
--
$Id: tgchange.txt 6 2005-09-10 01:02:21Z nenolod $

View file

@ -1,29 +0,0 @@
# $Id: index.txt 6 2005-09-10 01:02:21Z nenolod $
Here is the overview of the documents in the doc/ directory.
CIDR.txt - Description of CIDR in IPv4
Tao-of-IRC.940110 - No comment...
challenge.txt - Overview of the challenge/response system for
obtaining operator status
ircd.conf.example - An example ircd.conf file describing most of the
user settable options
guidelines.txt - Documentation guidelines
hooks.txt - Overview of the hooks available
index.txt - This file
ircd.8 - The new revised manpage, read with the following
commands in the prefix directory:
man -M . ircd
ircd.motd - A default ircd.motd used by make install
logfiles.txt - Description of formatting of some logfiles
modeg.txt - An in depth description of the server side silence
user mode (+g)
modes.txt - A list of all user and channel modes
operguide.txt - EFnet operator's guide
opermyth.txt - Oper myth's, describes what opers can and cannot do
server-version-info - Overview of the flags shown in /version
whats-new.txt - What new features are available
Also in the contrib/ directory you will find:
example_module.c - An example module, detailing what the code in a module
does. Useful for building your own modules.

View file

@ -1,120 +0,0 @@
.\" @(#)ircd.8 2.0 22 April 2004
.\" $Id: ircd.8 6 2005-09-10 01:02:21Z nenolod $
.TH IRCD 8 "ircd-ratbox" 22 April 2004
.SH NAME
ircd \- The Internet Relay Chat Program Server
.SH SYNOPSIS
.hy 0
.IP \fBircd\fP
[-dlinefile filename] [-configfile filename] [-klinefile filename]
[-logfile filename] [-pidfile filename] [-resvfile filename]
[-xlinefile filename] [-conftest] [-foreground] [-version]
.SH DESCRIPTION
.LP
\fIircd\fP is the server (daemon) program for the Internet Relay Chat
Program. The \fIircd\fP is a server in that its function is to "serve"
the client program \fIirc(1)\fP with messages and commands. All commands
and user messages are passed directly to the \fIircd\fP for processing
and relaying to other ircd sites.
.SH OPTIONS
.TP
.B \-dlinefile filename
Specifies the D-line file to be used. This file is used for both reading
D-lines at startup, and writing to while \fIircd\fP is running.
.TP
.B \-configfile filename
Specifies the ircd.conf file to be used for this ircdaemon. The option
is used to override the default ircd.conf given at compile time.
.TP
.B \-klinefile filename
Specifies the K-line file to be used. This file is used for both reading
K-lines at startup, and writing to while \fIircd\fP is running.
.TP
.B \-logfile filename
Specifies an alternative logfile to be used than that specified in config.h
.TP
.B \-pidfile filename
Specifies the ircd.pid used. The option is used to override the default
ircd.pid given at compile time.
.TP
.B \-resvfile filename
Specifies the resv.conf file to be used for this ircdaemon. The option
is used to override the default resv.conf given at compile time.
.TP
.B \-xlinefile filename
Specifies the xline.conf file to be used for this ircdaemon. The option
is used to override the default xline.conf given at compile time.
.TP
.B \-conftest
Makes \fIircd\fP check the ircd.conf for errors
.TP
.B \-foreground
Makes \fIircd\fP run in the foreground
.TP
.B \-version
Makes \fIircd\fP print its version, and exit.
.SH USAGE
If you plan to connect your \fIircd\fP server to an existing Irc-Network,
you will need to alter your local IRC configuration file (typically named
"ircd.conf") so that it will accept and make connections to other \fIircd\fP
servers. This file contains the hostnames, Network Addresses, and sometimes
passwords for connections to other ircds around the world. Because
description of the actual file format of the "ircd.conf" file is beyond the
scope of this document, please refer to the file INSTALL in the IRC source
files documentation directory.
.LP
.SH BOOTING THE SERVER
The \fIircd\fP server can be started as part of the
Unix boot procedure or just by placing the server into Unix Background.
Keep in mind that if it is \fBnot\fP part of your Unix's boot-up procedure
then you will have to manually start the \fIircd\fP server each time your
Unix is rebooted. This means if your Unix is prone to crashing
or going for for repairs a lot it would make sense to start the \fIircd\fP
server as part of your UNIX bootup procedure.
.SH EXAMPLE
.RS
.nf
tolsun% \fBbin/ircd\fP
.fi
.RE
.LP
Places \fIircd\fP into Unix background and starts up the server for use.
Note: You do not have to add the "&" to this command, the program will
automatically detach itself from tty.
.RS
.nf
leguin% \fBbin/ircd -foreground\fP
.fi
.RE
.LP
Runs ircd in the foreground.
.RS
.nf
.SH COPYRIGHT
(c) 1988,1989 University of Oulu, Computing Center, Finland,
.LP
(c) 1988,1989 Department of Information Processing Science,
University of Oulu, Finland
.LP
(c) 1988,1989,1990,1991 Jarkko Oikarinen
.LP
(c) 1997,1998,1999,2000,2001 The IRCD-Hybrid project.
.LP
For full COPYRIGHT see LICENSE file with IRC package.
.LP
.RE
.SH FILES
"ircd.conf"
.SH BUGS
None... ;-) if somebody finds one, please inform author
.SH AUTHOR
irc2.8 and earlier: Jarkko Oikarinen, currently jto@tolsun.oulu.fi.
.LP
ircd-hybrid-7: IRCD-Hybrid Project, ircd-hybrid@the-project.org.
.LP
manual page written by Jeff Trim, jtrim@orion.cair.du.edu,
later modified by jto@tolsun.oulu.fi.
.LP
modified for ircd-hybrid-7 by Edward Brocklesby, ejb@klamath.uucp.leguin.org.uk.
.LP
updated by W. Campbell, wcampbel@botbay.net

View file

@ -4,12 +4,11 @@
* Copyright (C) 2002-2005 ircd-ratbox development team
* Copyright (C) 2005-2006 charybdis development team
*
* $Id: example.conf 3582 2007-11-17 21:55:48Z jilles $
*
* See reference.conf for more information.
*/
/* Extensions */
<<<<<<< .merge_file_MAZNsP
#loadmodule "extensions/chm_operonly_compat.so";
#loadmodule "extensions/chm_quietunreg_compat.so";
#loadmodule "extensions/chm_sslonly_compat.so";
@ -35,23 +34,49 @@
#loadmodule "extensions/sno_whois.so";
#loadmodule "extensions/override.so";
#loadmodule "extensions/no_kill_services.so";
=======
#loadmodule "extensions/chm_nonotice";
#loadmodule "extensions/chm_operpeace";
#loadmodule "extensions/createauthonly";
#loadmodule "extensions/extb_account";
#loadmodule "extensions/extb_canjoin";
#loadmodule "extensions/extb_channel";
#loadmodule "extensions/extb_combi";
#loadmodule "extensions/extb_extgecos";
#loadmodule "extensions/extb_hostmask";
#loadmodule "extensions/extb_oper";
#loadmodule "extensions/extb_realname";
#loadmodule "extensions/extb_server";
#loadmodule "extensions/extb_ssl";
#loadmodule "extensions/extb_usermode";
#loadmodule "extensions/hurt";
#loadmodule "extensions/m_extendchans";
#loadmodule "extensions/m_findforwards";
#loadmodule "extensions/m_identify";
#loadmodule "extensions/m_locops";
#loadmodule "extensions/no_oper_invis";
#loadmodule "extensions/sno_farconnect";
#loadmodule "extensions/sno_globalnickchange";
#loadmodule "extensions/sno_globaloper";
#loadmodule "extensions/override";
#loadmodule "extensions/no_kill_services";
>>>>>>> .merge_file_DV7Blq
/*
* IP cloaking extensions: use ip_cloaking_4.0
* if you're linking 3.2 and later, otherwise use
* ip_cloaking.so, for compatibility with older 3.x
* ip_cloaking, for compatibility with older 3.x
* releases.
*/
#loadmodule "extensions/ip_cloaking_4.0.so";
#loadmodule "extensions/ip_cloaking.so";
#loadmodule "extensions/ip_cloaking_4.0";
#loadmodule "extensions/ip_cloaking";
serverinfo {
name = "hades.arpa";
sid = "42X";
description = "charybdis test server";
description = "solanum test server";
network_name = "StaticBox";
hub = yes;
/* On multi-homed hosts you may need the following. These define
* the addresses we connect from to other servers. */
@ -59,19 +84,21 @@ serverinfo {
#vhost = "192.0.2.6";
/* for IPv6 */
#vhost6 = "2001:db8:2::6";
/* ssl_private_key: our ssl private key */
ssl_private_key = "etc/ssl.key";
/* ssl_cert: certificate for our ssl server */
/* ssl_cert: certificate (and optionally key) for our ssl server */
ssl_cert = "etc/ssl.pem";
/* ssl_private_key: our ssl private key (if not contained in ssl_cert file) */
#ssl_private_key = "etc/ssl.key";
/* ssl_dh_params: DH parameters, generate with openssl dhparam -out dh.pem 2048
* In general, the DH parameters size should be the same as your key's size.
* However it has been reported that some clients have broken TLS implementations which may
* choke on keysizes larger than 2048-bit, so we would recommend using 2048-bit DH parameters
* for now if your keys are larger than 2048-bit.
*/
*
* If you do not provide parameters, some TLS backends will fail on DHE- ciphers,
* and some will succeed but use weak, common DH groups! */
ssl_dh_params = "etc/dh.pem";
/* ssld_count: number of ssld processes you want to start, if you
@ -160,7 +187,13 @@ listen {
/* Listen on IPv6 (if you used host= above). */
#host = "2001:db8:2::6";
#port = 5000, 6665 .. 6669;
#sslport = 9999;
#sslport = 6697;
/* wsock: listeners defined with this option enabled will be websocket listeners,
* and will not accept normal clients.
*/
wsock = yes;
sslport = 9999;
};
/* auth {}: allow users to connect to the ircd (OLD I:)
@ -183,7 +216,7 @@ auth {
* flags = ...; below if it is.
*/
password = "letmein";
/* spoof: fake the users user@host to be be this. You may either
* specify a host or a user@host to spoof to. This is free-form,
* just do everyone a favour and dont abuse it. (OLD I: = flag)
@ -191,26 +224,28 @@ auth {
spoof = "I.still.hate.packets";
/* Possible flags in auth:
*
*
* encrypted | password is encrypted with mkpasswd
* spoof_notice | give a notice when spoofing hosts
* exceed_limit (old > flag) | allow user to exceed class user limits
* kline_exempt (old ^ flag) | exempt this user from k/g/xlines&dnsbls
* dnsbl_exempt | exempt this user from dnsbls
* spambot_exempt | exempt this user from spambot checks
* shide_exempt | exempt this user from serverhiding
* kline_exempt (old ^ flag) | exempt this user from k/g/xlines,
* | dnsbls, and proxies
* proxy_exempt | exempt this user from proxies
* dnsbl_exempt | exempt this user from dnsbls
* spambot_exempt | exempt this user from spambot checks
* shide_exempt | exempt this user from serverhiding
* jupe_exempt | exempt this user from generating
* warnings joining juped channels
* resv_exempt | exempt this user from resvs
* resv_exempt | exempt this user from resvs
* flood_exempt | exempt this user from flood limits
* USE WITH CAUTION.
* 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;
/* class: the class the user is placed in */
class = "opers";
};
@ -224,7 +259,8 @@ auth {
* means they must be defined before operator {}.
*/
privset "local_op" {
privs = oper:local_kill, oper:operwall;
privs = oper:general, oper:privs, oper:testline, oper:kill, oper:operwall, oper:message,
usermode:servnotice, auspex:oper, auspex:hostname, auspex:umodes, auspex:cmodes;
};
privset "server_bot" {
@ -234,13 +270,14 @@ privset "server_bot" {
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;
privs = oper:routing, oper:kline, oper:unkline, oper:xline,
oper:resv, oper:cmodes, oper:mass_notice, oper:wallops,
oper:remoteban;
};
privset "admin" {
extends = "global_op";
privs = oper:admin, oper:die, oper:rehash, oper:spy;
privs = oper:admin, oper:die, oper:rehash, oper:spy, oper:grant;
};
operator "god" {
@ -253,13 +290,13 @@ operator "god" {
user = "*god@127.0.0.1";
/* password: the password required to oper. Unless ~encrypted is
* contained in flags = ...; this will need to be encrypted using
* contained in flags = ...; this will need to be encrypted using
* mkpasswd, MD5 is supported
*/
password = "etcnjl8juSU1E";
/* rsa key: the public key for this oper when using Challenge.
* A password should not be defined when this is used, see
* A password should not be defined when this is used, see
* doc/challenge.txt for more information.
*/
#rsa_public_key_file = "/usr/local/ircd/etc/oper.pub";
@ -297,20 +334,17 @@ operator "god" {
privset = "admin";
};
/* See connecting-servers.rst for an introduction to using these files. */
connect "irc.uplink.com" {
host = "203.0.113.3";
send_password = "password";
accept_password = "anotherpassword";
port = 6666;
hub_mask = "*";
class = "server";
flags = compressed, topicburst;
flags = topicburst;
#fingerprint = "c77106576abf7f9f90cca0f63874a60f2e40a64b";
/* If the connection is IPv6, uncomment below.
* Use 0::1, not ::1, for IPv6 localhost. */
#aftype = ipv6;
};
connect "ssl.uplink.com" {
@ -318,7 +352,6 @@ connect "ssl.uplink.com" {
send_password = "password";
accept_password = "anotherpassword";
port = 9999;
hub_mask = "*";
class = "server";
flags = ssl, topicburst;
};
@ -332,9 +365,8 @@ cluster {
flags = kline, tkline, unkline, xline, txline, unxline, resv, tresv, unresv;
};
shared {
oper = "*@*", "*";
flags = all, rehash;
secure {
ip = "127.0.0.1";
};
/* exempt {}: IPs that are exempt from Dlines and rejectcache. (OLD d:) */
@ -350,6 +382,7 @@ channel {
knock_delay = 5 minutes;
knock_delay_channel = 1 minute;
max_chans_per_user = 15;
max_chans_per_user_large = 60;
max_bans = 100;
max_bans_large = 500;
default_split_user_count = 0;
@ -364,6 +397,9 @@ channel {
disable_local_channels = no;
autochanmodes = "+nt";
displayed_usercount = 3;
strip_topic_colors = no;
opmod_send_statusmsg = no;
invite_notify_notice = yes;
};
serverhide {
@ -373,15 +409,14 @@ serverhide {
disable_hidden = no;
};
/* These are the blacklist settings.
/* These are the DNSBL settings.
* You can have multiple combinations of host and rejection reasons.
* They are used in pairs of one host/rejection reason.
*
* These settings should be adequate for most networks, and are (presently)
* required for use on StaticBox.
* The default settings should be adequate for most networks.
*
* Word to the wise: Do not use blacklists like SPEWS for blocking IRC
* connections.
* It is not recommended to use DNSBL services designed for e-mail spam
* prevention, such as SPEWS for blocking IRC connections.
*
* As of charybdis 2.2, you can do some keyword substitution on the rejection
* reason. The available keyword substitutions are:
@ -398,16 +433,16 @@ serverhide {
* as of this writing.
*
* As of charybdis 3.5, a matches parameter is allowed; if omitted, any result
* is considered a match. If included, a comma-separated list of *quoted*
* is considered a match. If included, a comma-separated list of *quoted*
* strings is allowed to match queries. They may be of the format "0" to "255"
* to match the final octet (e.g. 127.0.0.1) or "127.x.y.z" to explicitly match
* an A record. The blacklist is only applied if it matches anything in the
* an A record. The DNSBL match is only applied if it matches anything in the
* list. You may freely mix full IP's and final octets.
*
* Consult your blacklist provider for the meaning of these parameters; they
* are usually used to denote different ban types.
* Consult your DNSBL provider for the meaning of these parameters; they
* are usually used to denote different block reasons.
*/
blacklist {
dnsbl {
host = "rbl.efnetrbl.org";
type = ipv4;
reject_reason = "${nick}, your IP (${ip}) is listed in EFnet's RBL. For assistance, see http://efnetrbl.org/?i=${ip}";
@ -419,6 +454,78 @@ blacklist {
# reject_reason = "${nick}, your IP (${ip}) is listed in ${dnsbl-host} for some reason. In order to protect ${network-name} from abuse, we are not allowing connections listed in ${dnsbl-host} to connect";
};
/* These are the OPM settings.
* This is similar to the functionality provided by BOPM. It will scan incoming
* connections for open proxies by connecting to clients and attempting several
* different open proxy handshakes. If they connect back to us (via a dedicated
* listening port), and send back the data we send them, they are considered
* an open proxy. For politeness reasons (users may be confused by the incoming
* connection attempts if they are logging incoming connections), the user is
* notified upon connect if they are being scanned.
*
* WARNING:
* These settings are considered experimental. Only the most common proxy types
* are checked for (Charybdis is immune from POST and GET proxies). If you are
* not comfortable with experimental code, do not use this feature.
*/
#opm {
/* IPv4 address to listen on. This must be a publicly facing IP address
* to be effective.
* If omitted, it defaults to serverinfo::vhost.
*/
#listen_ipv4 = "127.0.0.1";
/* IPv4 port to listen on.
* This should not be the same as any existing listeners.
*/
#port_v4 = 32000;
/* IPv6 address to listen on. This must be a publicly facing IP address
* to be effective.
* If omitted, it defaults to serverinfo::vhost6.
*/
#listen_ipv6 = "::1";
/* IPv6 port to listen on.
* This should not be the same as any existing listeners.
*/
#port_v6 = 32000;
/* You can also set the listen_port directive which will set both the
* IPv4 and IPv6 ports at once.
*/
#listen_port = 32000;
/* This sets the timeout in seconds before ending open proxy scans.
* Values less than 1 or greater than 60 are ignored.
* It is advisable to keep it as short as feasible, so clients do not
* get held up by excessively long scan times.
*/
#timeout = 5;
/* These are the ports to scan for SOCKS4 proxies on. They may overlap
* with other scan types. Sensible defaults are given below.
*/
#socks4_ports = 1080, 10800, 443, 80, 8080, 8000;
/* These are the ports to scan for SOCKS5 proxies on. They may overlap
* with other scan types. Sensible defaults are given below.
*/
#socks5_ports = 1080, 10800, 443, 80, 8080, 8000;
/* These are the ports to scan for HTTP connect proxies on (plaintext).
* They may overlap with other scan types. Sensible defaults are given
* below.
*/
#httpconnect_ports = 80, 8080, 8000;
/* These are the ports to scan for HTTPS CONNECT proxies on (SSL).
* They may overlap with other scan types. Sensible defaults are given
* below.
*/
#httpsconnect_ports = 443, 4443;
#};
alias "NickServ" {
target = "NickServ";
};
@ -490,7 +597,7 @@ general {
tkline_expire_notices = no;
default_floodcount = 10;
failed_oper_notice = yes;
dots_in_ident=2;
dots_in_ident = 2;
min_nonwildcard = 4;
min_nonwildcard_simple = 3;
max_accept = 100;
@ -506,22 +613,30 @@ general {
resv_fnc = yes;
global_snotices = yes;
dline_with_reason = yes;
kline_delay = 0 seconds;
kline_with_reason = yes;
hide_tkdline_duration = no;
kline_reason = "K-Lined";
sasl_only_client_message = "You need to identify via SASL to use this server.";
identd_only_client_message = "You need to install identd to use this server.";
sctp_forbidden_client_message = "You are not allowed to use SCTP on this server.";
ssltls_only_client_message = "You need to use SSL/TLS to use this server.";
not_authorised_client_message = "You are not authorised to access this server.";
illegal_hostname_client_message = "You have an illegal character in your hostname.";
server_full_client_message = "Sorry, server is full - try later";
illegal_name_long_client_message = "Your username is invalid. Please make sure that your username contains only alphanumeric characters.";
illegal_name_short_client_message = "Invalid username";
identify_service = "NickServ@services.int";
identify_command = "IDENTIFY";
non_redundant_klines = yes;
warn_no_nline = yes;
use_propagated_bans = yes;
stats_e_disabled = no;
stats_c_oper_only=no;
stats_h_oper_only=no;
stats_y_oper_only=no;
stats_o_oper_only=yes;
stats_P_oper_only=no;
stats_i_oper_only=masked;
stats_k_oper_only=masked;
stats_c_oper_only = no;
stats_y_oper_only = no;
stats_o_oper_only = yes;
stats_P_oper_only = no;
stats_i_oper_only = masked;
stats_k_oper_only = masked;
map_oper_only = no;
operspy_admin_only = no;
operspy_dont_care_user_info = no;
@ -537,6 +652,7 @@ general {
no_oper_flood = yes;
max_targets = 4;
client_flood_max_lines = 20;
post_registration_delay = 0 seconds;
use_whois_actually = no;
oper_only_umodes = operwall, locops, servnotice;
oper_umodes = locops, servnotice, operwall, wallop;
@ -550,7 +666,9 @@ general {
throttle_count = 4;
max_ratelimit_tokens = 30;
away_interval = 30;
certfp_method = sha1;
certfp_method = spki_sha256;
hide_opers_in_whois = no;
tls_ciphers_oper_only = no;
};
modules {

View file

@ -1,2 +1,2 @@
This is charybdis MOTD you might replace it, but if not your friends will
This is solanum MOTD you might replace it, but if not your friends will
laugh at you.

View file

@ -1,5 +1,4 @@
ircd-ratbox logfiles - Lee H <lee -at- leeh.co.uk>
$Id: logfiles.txt 6 2005-09-10 01:02:21Z nenolod $
Charybdis logfiles - Lee H <lee -at- leeh.co.uk>
---------------------------
fname_killlog

View file

@ -4,7 +4,6 @@ Standard channel modes are listed in help/opers/cmode
The sgml docs have more detailed descriptions.
User mode +h (hide hostname) is provided by contrib/ip_cloaking.so
User mode +x (hide hostname) is provided by contrib/ip_cloaking.so
Server notice mask +F (far connects) is provided by contrib/sno_farconnect.so
# $Id: modes.txt 996 2006-03-09 01:14:34Z jilles $
Information on the caller ID system can be found in doc/features/modeg.txt

View file

@ -1,137 +0,0 @@
/************************************************************************
* IRC - Internet Relay Chat, doc/AUTHORS
* Copyright (C) 1990
*
* AUTHORS FILE:
* This file attempts to remember all contributors to the IRC
* developement. Names can be only added this file, no name
* should never be removed. This file must be included into all
* distributions of IRC and derived works.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
IRC was conceived of and written by Jarkko Oikarinen <jto@tolsun.oulu.fi>.
IRC was originally written in University of Oulu, Computing Center.
Jan 1991 - IRC 2.6 jto@tolsun.oulu.fi
- Multiple Channels and protocol changes
Contributions were made by a cast of dozens, including the following:
Markku Jarvinen <mta@tut.fi>: Emacs-like editing facility for the client
Kimmo Suominen <kim@kannel.lut.fi>: HP-UX port
Jeff Trim <jtrim@orion.cair.du.edu>: enhancements and advice
Vijay Subramaniam <vijay@lll-winken.llnl.gov>: advice and ruthless publicity
Karl Kleinpaste <karl@cis.ohio-state.edu>: user's manual
Greg Lindahl <gl8f@virginia.edu>: AUTOMATON code, the Wumpus GM automaton,
myriad bug fixes
Bill Wisner <wisner@hayes.fai.alaska.edu>: numerous bug fixes and code
enhancements
Tom Davis <conslt16@zeus.unl.edu> and Tim Russell <russell@zeus.unl.edu>:
VMS modifications
Markku Savela <msa@tel4.tel.vtt.fi>: advice, support, and being the
incentive to do some of our *own* coding. :)
Tom Hopkins <hoppie@buengf.bu.edu>: bug fixes, quarantine lines,
consolidation of various patches.
Christopher Davis <ckd@cs.bu.edu>: EFnet/Anet gateway coding,
many automata ;), documentation fixing.
Helen Rose <hrose@cs.bu.edu>: documentation updating, and fixing.
Tom Hinds <rocker@bucsf.bu.edu>: emacs client updating.
Tim Miller <cerebus@bu-pub.bu.edu>: various server and client-breaking
features.
Darren Reed <avalon@coombs.anu.edu.au>: various bug fixes and enhancements.
Introduced nickname and channelname hash tables into the server.
The version 2.2 release was coordinated by Mike Bolotski
<mikeb@salmon.ee.ubc.ca>.
The version 2.4 release was coordinated by Markku Savela and
Chelsea Ashley Dyerman
The version 2.5.2 release was coordinated by Christopher Davis, Helen Rose,
and Tom Hopkins.
The versions 2.6.2, 2.7 and 2.8 releases were coordinated by Darren Reed.
Contributions for the 2.8 release from the following people:
Matthew Green <phone@coombs.anu.edu.au>
Chuck Kane <ckane@ece.uiuc.edu>
Matt Lyle <matt@oc.com>
Vesa Ruokonen <ruokonen@lut.fi>
Markku Savela <Markku.Savela@vtt.fi> / April 1990
Fixed various bugs in 2.2PL1 release server (2.2msa.4) and changed
sockets to use non-blocking mode (2.2msa.9). [I have absolutely
nothing to do with clients :-]
Chelsea Ashley Dyerman <chelsea@earth.cchem.berkeley.edu> / April 1990
Rewrote the Makefiles, restructuring of source tree. Added libIrcd.a to
the Makefile macros, numerous reformatting of server text messages, and
added mkversion.sh to keep track of compilation statistics. Numerous
bug fixes and enhancements, and co-coordinator of the 2.4 release.
jarlek@ifi.uio.no added mail functions to irc.
Armin Gruner <gruner@informatik.tu-muenchen.de> / May, June 1990:
* Patched KILL-line feature for ircd.conf, works now.
Enhancement: Time intervals can be specified in passwd-field.
Result: KILL-Line is only active during these intervals
* Patched PRIVMSG handling, now OPER can specify masks for sending
private messages, advantage: msg to all at a specified server or host.
* Little tests on irc 2.5 alpha, fixed some little typos in client code.
Change: common/debug.c has been moved to ircd/s_debug.c, and a
irc/c_debug.c has been created, for the benefit that wrong server msg
are displayed if client does not recognize them. (strange, if a server
sends an 'unknown command', isn't it?)
Tom Hopkins <hoppie@buengf.bu.edu> / September, October 1990:
* Patched msa's K lines for servers (Q lines).
* Consolidated several patches, including Stealth's logging patch.
* Fixed several minor bugs.
* Has done lots of other stuff that I can't seem to remember, but he
always works on code, so he has to have done alot more than three
lines worth. :)
Thanks go to those persons not mentioned here who have added their advice,
opinions, and code to IRC.
Various modifications, bugreports, cleanups and testing by:
Hugo Calendar <hugo@ucscb.ucsc.edu>
Bo Adler <adler@csvax.cs.caltech.edu>
Michael Sandrof <ms5n+@andrew.cmu.edu>
Jon Solomon <jsol@cs.bu.edu>
Jan Peterson <jlp@hamblin.math.byu.edu>
Nathan Glasser <nathan@brokaw.lcs.mit.edu>
Helen Rose <hrose@eff.org>
Mike Pelletier <stealth@caen.engin.umich.edu>
Basalat Ali Raja <gwydion@tavi.rice.edu>
Eric P. Scott <eps@toaster.sfsu.edu>
Dan Goodwin <fornax@wpi.wpi.edu>
Noah Friedman <friedman@ai.mit.edu>

View file

@ -87,12 +87,21 @@ hub
serving as a hub, i.e. have multiple servers connected to it.
vhost
<<<<<<< .merge_file_cTfvge
An optional text field which defines an IP from which to connect
outward to other IRC servers.
vhost6
An optional text field which defines an IPv6 IP from which to
connect outward to other IRC servers.
=======
An optional text field which defines an IPv4 address from which
to connect outward to other IRC servers.
vhost6
An optional text field which defines an IPv6 address from which
to connect outward to other IRC servers.
>>>>>>> .merge_file_3UzJEV
admin {} block
--------------
@ -255,6 +264,12 @@ flags
class
A name of a class to put users matching this auth{} block into.
<<<<<<< .merge_file_cTfvge
=======
umodes
Additional umodes to apply to the default_umodes upon connect.
>>>>>>> .merge_file_3UzJEV
auth {} flags
~~~~~~~~~~~~~
@ -446,10 +461,13 @@ host
``A`` or ``AAAA`` record (no ``CNAME``) and it must be
the primary hostname for inbound connections to work.
<<<<<<< .merge_file_cTfvge
IPv6 addresses must be in ``::`` shortened form; addresses which
then start with a colon must be prepended with a zero, for
example ``0::1``.
=======
>>>>>>> .merge_file_3UzJEV
send\_password
The password to send to the other server.
@ -478,7 +496,12 @@ flags
aftype
The protocol that should be used to connect with, either ipv4 or
<<<<<<< .merge_file_cTfvge
ipv6. This defaults to ipv4 unless host is a numeric IPv6 address.
=======
ipv6. This defaults to neither, allowing connection using either
address family.
>>>>>>> .merge_file_3UzJEV
**connect {} flags**

View file

@ -1,368 +0,0 @@
EFnet Oper Guide
Last update: 02-21-2002
Written and maintained by Riedel
E-Mail: dennisv@vuurwerk.nl
1. Commands you should know about
2. The client of your choice
3. Your primary responsibilities
4. Re-routing
4.1 Re-routing other servers and remote connects
5. Kills and klines
6. Kill and K-Line requests
7. Happy birthday!
8. Security
9. Know who your friends are
10. The TCM bot
11. Services
12. G-Lines
1. Commands you should know about
This is no longer covered here. IRCD-hybrid is changing too rapidly, so
this section would be outdated in no time ;) For an up-to-date version,
please download the latest hybrid at www.ircd-hybrid.org.
2. The client of your choice
There are many IRC clients around for a wide variety of operating systems.
Being an IRC Operator doesn't *require* you to use a UNIX client, however
I personally prefer UNIX-based clients. If you're familiar with UNIX and
use UNIX for opering, I suggest ircII / epic. There are a lot of scripts
available for those two clients, and it's not that hard to write scripts
yourself to suite your needs. It is important that you know how to operate
your client, and familiarize yourself with the options and features. For
whatever client you chose this goes for any of them: You should be in
control of your client, instead of the client being in control of you.
Resources :
www.mirc.co.uk - mIRC (MS-Windows)
www.irchelp.org - a variety of clients and scripts
ftp.blackened.com - several UNIX based clients available
3. Your primary responsibilities
As an IRC Operator, you're responsible for maintaining the server on a
real-time basis. You represent your server, and you represent the network.
Irresponsible / rude / offensive / stupid behavior may discredit your server
and the network. You should focus on the task you were chosen for...
maintainance. Sounds simple, no? It means getting rid of users that abuse
the service, enforcing the server's policy and keeping the server linked.
Users will ask you questions, and expect you to know all the answers.. after
all, you're the oper!
Be prepared for users trying to fool you, sweet talk you into things you
don't want, lie and deceive. Most users are handling in good faith...
however, the abusers have learned how to manipulate opers. They have studied
the alien creature 'oper' for ages like biologists study animals. Be
paranoid, be curious and be suspicious. I can't stress the importancy of that
often enough.
Second priority has the network. You were not chosen to maintain the network
but you were chosen to maintain the server. However, you may want to be able
to reroute servers. If you see something broken, don't be afraid to fix it.
If you do, be sure you fix things and don't make it worse. Before you
step into routing, be sure you've familiarized yourself with the network's
topology, and be confident enough to perform such actions. (re)routing is
covered in the next chapter.
Opers on the network depend on a trusting relationship. You can usually take
the word from an oper. Other opers are considered -trusted-, however, there
are exceptions. Sometimes even opers lie to opers to get things done. Don't
be afraid to ask for proof of a certain statement, such as logs.
This doesn't mean you distrust the oper in question, but -you- and you alone
are responsible for your actions. You call the shots on your server, unless
your admin says otherwise.
4. Re-routing
Re-routing is not hard, and it's not scary but it is important that you do it
right. The commands you'll use are SQUIT and CONNECT. First, a very simple
example. Let's say your server, irc.yourserver.com is lagged to it's uplink,
irc.uplink.com and you want to reroute your server. You have to think about
where you want your server to be linked, and you have to time your reroute.
An example topology :
irc.yourserver.com ---- irc.uplink.com
| | \
B C D
/ \
E F
/ \
G H --- O
/ | \ | \
I J K L M
\
N
In this case, you're uplinked by irc.uplink.com
irc.uplink.com also hubs B, C and D. Server B functions as hub for E and F;
F hubs G and H; H hubs L, M and O. G hubs I, J and K. M hubs N.
Your server is allowed to connect to server B, F and G. So you consider the
servers you're able to connect to. Is the lag caused by a server that uplinks
irc.uplink.com ? Use /stats ? irc.uplink.com to determine lag to the other
servers. If irc.uplink.com does not respond, the lag is to your uplink. If
so, you cannot be sure about the state of the other uplinks, so you'd have to
get on a remote server and determine lag by using /stats ? and /trace. For
example, you could connect to server N, and /trace yournick. Yournick, being
the nick on your server. You'll see which route it takes, and what the
problem server is. Example /trace output :
S:[SERVER-N ] V:[2.8/hybrid] U:[SERVER-M ]
S:[SERVER-M ] V:[2.8/hybrid] U:[SERVER-H ]
S:[SERVER-H ] V:[2.8/hybrid] U:[SERVER-F ]
S:[SERVER-F ] V:[2.8/hybrid] U:[SERVER-B ]
S:[SERVER-B ] V:[2.8/hybrid] U:[irc.uplink.com ]
S:[irc.uplink.com ] V:[2.8/hybrid] U:[irc.yourserver.com ]
The trace doesn't complete... server-b announces irc.uplink.com, and
irc.uplink.com announces your server. Your server should return something
like :
S:[irc.yourserver.] OPER [yournick!user@yourhost]
If it doesn't, we know the lag is only between yourserver and uplink.
Usually if there is lag between your server and your uplink, the send-queue
rises. This is not always the case. Sometimes your server can write perfectly
to your uplink, but not reverse. That is called one sided lag.
We pick server B to link to. It means we have to SQUIT and CONNECT.
To unlink from irc.uplink.com and connect to SERVER_B we'd type:
/quote SQUIT irc.uplink.com :reroute
/connect SERVER_B
we *DON'T* SQUIT irc.yourserver.com... and I'll try to explain why:
If we wanted to remove hub M from the network, and with it N, we'd issue
a SQUIT M. An SQUIT follows a path, relays the SQUIT request to each server
in that path. Finally it reaches server H, which is the hub for M. Server H
sees the SQUIT and drops the link to M.
Now a different situation, we want to separate yourserver, uplink, C and D
from the rest of the network, in order to reroute. We'd have to SQUIT server
B, since we want the -uplink- of server B (being irc.uplink.com) to drop the
link to server B.
If you'd SQUIT irc.yourserver.com, you ask yourserver.com to drop the link to
itself, which is impossible. If you SQUIT irc.uplink.com, you ask yourserver
to drop the link to uplink, which is what we want to do.
After the SQUIT and CONNECT, the new situation looks like this :
irc.uplink.com
| | \
irc.yourserver.com -- B C D
/ \
E F
/ \
G H --- O
/ | \ | \
I J K L M
\
N
If yourserver is a Hub, it makes the situation more complex, since your
actions have more impact.
4.1 - Re-routing other servers and remote connects
Example topology :
irc.uplink.com
| | \
irc.yourserver.com -- B C D
/ \
E F
/ \
G H --- O
/ | \ | \
I J K L M
\
N
Let's say, hub H is way lagged to F, but G to F is fine... we want to reroute
H, and stick H to G.
We'd do :
/quote SQUIT serverh :re-routing you babe
/connect serverh 6667 serverg
A global wallops will be sent :
!serverg! Remote CONNECT serverh 6667 from ItsMe
When re-routing, always give the server some time to prevent nick collides.
When there is lag, people will connect to another server. When you SQUIT and
CONNECT to fast, a lot of those clients will be collided. Also, stick to your
territory. How enthusiastic you may be, you cannot route the world. If you're
an oper on the US side, stick to the US side when re-routing. Needless to
say, if you're EU, keep it to EU ;)
5. Kills and klines
As an oper, you're given the incredible power *cough* of KILL and KLINE.
/kill nick reason disconnects a client from IRC with the specified reason.
A /quote kline *evil@*.dude.org :reason here bans the user from your server.
Abusive kills and klines may draw attacks to your server, so always consider
if a kline or kill is deserved. If the server gets attacked after a valid
kill or kline, well.. tough luck. You should never be 'afraid' to kline
anyone on your server. If it's a good reason, make it so. Even if you know
it may cause the server to be attacked. Maybe good to think about is this:
- if /ignore solves the problem rather than a kick, /ignore
- kick if a ban is unneeded
- ban if a /kill is unwarranted for
- kill rather than kline if that solves the problem
- kline when a server ban is really needed.
You kline a user when you absolutely don't want this user to use the service
your server is providing.
Crosskills (killing users on another server) are another issue. Some admins
don't care if users get /kill'ed off their server, for any reason or no
reason at all... and other admins are very anal about it. A good way to go
(IMO) is to issue a KILL if there is an absolute need for the target user to
be disconnected. If there are active opers on that server, let them handle
it. They'll be upset if you /kill a user off their server, without
contacting them. /stats p irc.server.here shows the active opers on a
particular server. Some opers have multiple o-lines and are not watching all
sessions. If you can't find an active oper on a server, you can
/quote operwall a request for opers from that server.
Ghost KILLs are another story, an often misunderstood one.
When you see a /KILL from an oper with the reason 'ghosted' they usually
KILL a client that's about to ping timeout. That is not what a ghost is!
To quote Dianora: "a ghost happens because a client misses being killed when
it should be. Its a race condition due to nick chasing". In other words,
Server X thinks client A has been KILLed, while server Y missed the KILL
for that client.
6. Kill and K-Line requests
As previously mentioned, if an oper from another server contacts you and
requests a kill or a kline for a local client with a good reason, you can
usually trust this request. Opers depend on a trusting relationship. However,
since you're responsible for the kill or kline, it is not rude to ask for
proof. It depends on the oper making the request how thats interpreted, but
the way they respond to asking for proof tells more about them than about
you.
The more and longer you oper, how better you get to know the other opers.
You know who is honest, you'll know who are lying and deceiving. Before
you acquire this knowledge, you can merely rely on common sense and
instincts. You'll probably make mistakes occasionally, and thats nothing to
be ashamed of. Opers are - despite contrary believes - human.
Users occasionally will ask you to kill or kline a user/bot too. Some
requests are straight-forward and clear, others require you to be cautious. I
recommend to always investigate such requests, and when you're confident the
request is valid, issue the kill or kline.
7. Happy birthday!
It is a custom on EFnet to birthday /kill opers of whom it is his/her
birthday. Not all opers like this, but typically those opers don't let
others know about their birthday. You'll notice that the KILLS say a lot
about who likes who and who is friends with who. Whether you want to
participate, is entirely up to you.
8. Security
As with any privilege, you have to handle it cautiously and responsibly.
Be sure that your o/O line doesn't get compromised! Oper only from secure
hosts. You and only you should know your password. Don't share your oper
account, and make your oper password a UNIQUE one. If your o/O line gets
compromised, nasty things may/will happen. Imagine an oper with crosskill
capabilities who's operline gets 'hacked'... the results are often
disastrous and you will lose respect and trust from others. It can cause
your oper privileges to be revoked, or even the server to be (temporarily)
delinked.
9. Know who your friends are
As an oper you will get a lot of users that want to be 'friends' with you.
Users offer you free* access to their *nix servers, ops in channels,
unlimited leech access to the biggest and fastest warez sites *gasp* and
more. They want favors in return. They say they don't but they truly want
something in return. They -expect- something in return. You could either
don't respond to such offers, or use them. The last option creates an even
more distorted image of opers and doesn't do any good for the user <-> oper
relationship. Your *real* friends are usually the persons who were your
friends _before_ you acquired the extra privileges.
10. The TCM Bot
A TCM bot can be a valuable tool for opers. It keeps record of all connected
clients, flags clients with multiple connections and has all sorts of other
useful commands. There are three different kind of TCM's in use on EFnet,
being OOMon, TCM-Dianora and TCM-Hybrid. Every one of them requires you to
log in to be able to access the privileged commands. On OOMon you DCC chat
the TCM bot and do '.auth yournick yourpass' where yournick is your oper
name in your o/O line. In TCM-Dianora and TCM-Hybrid you register with:
'.register yourpass', where yourpass is your password ;)
All TCM commands start with a period. If you forget the period, the text goes
into the 'partyline', where it is echoed to all connected opers.
Resources : http://toast.blackened.com/oomon/help
http://www.db.net/~db/tcm.html
11. Services
A recent addition to EFNet is Channel Fixer, aka ChanFix. This is an
automated service that re-ops clients on opless channels. There are a few
restrictions. First, the channel has to be of significant size for ChanFix
to store it in its database. Second, it only logs static addresses.
How does it work? Periodically it stores information about the channel state
in its database, for every channel in there. On every 'run', a channel
operator gets one point. These scores make a top-5 of 'most frequent opped
clients'. When a channel becomes opless, ChanFix will join and op the top-5
opped clients CURRENTLY IN THE CHANNEL.
Chanfix can be invoked manually by server administrators. /msg ChanFix
chanfix #channel is the command to do it. ChanFix will join, and treat the
channel as if it were opless. It lowers TS by one (resulting in a deop of
the entire channel) and re-ops the top-5 clients currently in the channel.
The Channel Fixer won't log or actively fix channels when there's a split of
significant size. Needless to say, the chanfix command must be used with
caution.
12. G-Lines
Oh yes! A G-Line section. Currently, a part of EFNet (EU-EFnet) has G-Lines
enabled. This was decided by the EU admin community and is now mandatory
within EU-EFnet. In order for a G-Line to be activated, three opers from
three different servers need to issue the _exact_ same G-Line. The reason
is not counted.
G-Lines work best when the EU side of EFNet is not fragmented. G-Lines
will, however, propogate through a Hybrid 6 hub (but not a CSr hub) even
if the hub server has G-Lines disabled. This propogation allows two halves
of EU-EFnet to have concurrent G-Lines set even when split by US hub servers.
Questions / Comments / Suggestions are welcome.
You can e-mail me: dennisv@vuurwerk.nl
Best regards,
--
Dennis "Riedel" Vink ___~___ Email - dennisv@vuurwerk.nl
Unix System Administrator \ | / Phone - +31 23 5111111
Vuurwerk Internet '|.|' PGP - 0xD68A7AAB
And on the seventh day, He exited from append mode.
# $Id: operguide.txt 6 2005-09-10 01:02:21Z nenolod $

View file

@ -1,137 +0,0 @@
Date: Thu, 30 Jul 1998 16:21:40-0700 (MST)
To: operlist@the-project.org
From: rayp@primenet.com (Ray Powers)
Subject: The myths of opers....
I've always wanted to write something like this.. Its half rant, half
fact, so bear with it. Hopefully it will be worth reading.
There's a lot of hate for opers for a lot of reasons. Some are directly
oper related (i.e. 99% of us are colossal assholes), some are directly
user related (i.e. 99% of you are raving lunatics), and some is just plain
misconceptions. I'd like to take a minute to talk about part three in
hopes of clearing a few things up. This will kind of be in a FAQ form,
maybe you'll like it, maybe not, but its worth a shot.
Q: What can an oper on EFnet do.
A: This is an EXACT list of what we can do:
1) /squit a server, separating it from the rest of the net
2) /die our server
3) /kill a user, this disconnects them from the server they are on
4) /kline a hostmask, this bans them from our server
5) /dline an ip, this bans them from our server, regardless of
hostmask
6) See all invisible users on our server
7) Mass Msg/CTCP/notice a hostmask
8) Mass Msg/CTCP/notice a server
9) See and send Operwall/wallops notices
That's it. We can see more server messages than you, but that's not the
point.. The point to be shown here is very simple, *none* of these things
have anything to do with channels. Which leads us to our next question.
Q: What can opers *NOT* do, but keep being asked to anyways?
A: We can *NOT*:
1) Enter a channel that is +i or +k without being invited or
having the key
2) See who is inside a +s channel
3) Op ourselves or op you on a channel (unless of course we are a
channel op for that channel)
4) Tell you what XXXX's new nick is since they changed it to hide
from you.
5) Deop someone for you on a channel (unless of course we are a
channel op for that channel)
Notice a trend, with the exception of 4, all of these are 100% channel
related. EFnet is made so that opers have *NO* power of channels, for
better or worse. If we don't help you with these requests, its not because
we won't, its because we are completely incapable doing so. On the other
hand....
Q: What can opers do, but won't?
A: This will be a bit differently done, because I figure I should explain
why opers don't do these things, when they may normally make sense.
1) Why won't they kill somebody who has stolen your nick.
EFnet has gone on the basis of nicks not being owned, which is
why there is no nickserv on EFnet. Of course we see opers kill
all the time for nicks, though, so it seems rather hypocrital,
doesn't it?
An oper who kills for his nick will tell you its because the
other person was a bot, was juping his nick, or was imitating an
oper. It may be true, but it really comes down to the same
feeling you get when your nick is taken "Hey! that's my name! I
don't want that person using my name!"
I personally, do not kill for nicks. If someone takes my nick,
they can have it. Let them get my several hundred messages a day.
:P But the problem with the oper is this: How does an oper know
that you are really the person that uses that nick, or are you
the guy that wants to nick jupe that nick out from the real guy?
Unless the oper knows you well, they don't.. And saying that
people generally tell the truth means you haven't been on EFnet
very long.
I would prefer to think I am one of the more well respected
people on the net and people still lie to me on a regular basis.
So, the oper is stuck refusing to help because he can't tell who
is who. Remember this line of reasoning, its going to be coming
up a lot. :P
2) Why won't they kill that guy nuking/smurfing/ping -f'ing me?
This one is simple. There is no way to prove that somebody is
doing any of these things to you from an opers point of view. All
logs are fakeable, and the oper has no way to firsthand prove its
happening. Your best bet in this situation is to log what you can
and complain loud and long to their ISPs.
3) Why won't they help me take my channel back?
There's a bunch of answers to this. First, it is popular
opinion at EFnet that channels are not owned, and therefore, if
you lose a channel, you should go make another one. Notice I
say popular instead of official, because EFnet has never had an
"official" policy on much of anything.
But more and more you see opers killing for takeovers, so why
are they helping their channels and not yours.
Well, first, let's say your channel was taken over, and is now
+smtinlk. How exactly is the oper supposed to find out who is
oped in the channel right now to mass kill them? Even if they do get
all the nicks, they have to somehow manage to kill them all in
one hit, or they'll all just op each other again and it will be
fruitless. Or worse, they could have it all set up, and some
other oper could kill them halfway through because they don't
like mass-kills and it would be all ruined.
Or, let's say the mass-kill goes off, then the channel is
opless and generally speaking, chaos begins. People start
mass-nuking or flooding the channel to clear it out, or just to
be annoying. And there's still a 50/50 chance that takeover
people will get the channel back on a split and we'll have to try
to do it all over again.
If you're about to ask why they don't split their server,
the answer is very simple: We are not about to screw up roughly
30,000 peoples chatting for your channel. Its rude. This of
course is all based on the fact that we can prove its taken over,
as per the conversation about nicks, we often can't.
4) But.. its obvious they took it from me! The topic says
"Ha ha, we took your channel Rick!" for Pete's sake! And
there's only One op, so you can kill him and get the channel
back immediately!
This one is a bit more complex, but its really a personal
call. That one op could be a rampant smurfpup with a penis so
tiny he has no choice but to rampantly smurf and synflood anyone
that gets in his way. This is popularly known on irc as SPS, or
Small Penis Syndrome. In this case, if the oper does help you
out, they could end up with their server being downed for a day
or two, and it really isn't worth it for your channel, no
offense.
Keep in mind that this is all spoken from the perspective of someone who
*DOES* help with channels when possible, but understands greatly the
reasons not to, and judges each situation very carefully.
That's the gist of the information I was trying to get across. If you
were cluefull enough to get on operlist, a lot of this may be common
knowledge to you, but sometimes its good to step back and see why opers do
what they do a lot of the time.
Hoping this is of value to SOMEONE....
Ray Powers
Monkster/MimePunk/PrimeMonk/PacMonk/MtgMonk/Ihavefartoomanynickstonickjupe

23
doc/readme.txt Normal file
View file

@ -0,0 +1,23 @@
Here is the overview of the documents in the doc/ directory.
Subdirectories:
features/ - Documents about features and standards
technical/ - Technical documents about ircd internals and
protocol information
sgml/ - SGML documentation
Files:
ircd.conf.example - An example ircd.conf file describing most of the
user settable options
ircd.motd - A default ircd.motd used by make install
reference.conf - A complete example showing all possible config
options
credits-past.txt - Credits for the predecessors to Charybdis
logfiles.txt - Description of formatting of some logfiles
server-version-info.txt - Overview of the flags shown in /version
Also in the contrib/ directory you will find:
example_module.c - An example module, detailing what the code in a module
does. Useful for building your own modules.

View file

@ -1,4 +1,4 @@
/* doc/reference.conf - charybdis Example configuration file
/* doc/reference.conf - solanum example configuration file
*
* Copyright (C) 2000-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
@ -6,7 +6,6 @@
*
* Written by ejb, wcampbel, db, leeh and others
*
* $Id: reference.conf 3582 2007-11-17 21:55:48Z jilles $
*/
/* IMPORTANT NOTES:
@ -27,23 +26,28 @@
* .include "filename"
* .include <filename>
*
* Flags variables are comma-separated sets of predefined values,
* specific to each block. For example in operator {} blocks:
* flags = encrypted, encrypted;
*
* Times/durations are written as:
* 12 hours 30 minutes 1 second
*
*
* Valid units of time:
* month, week, day, hour, minute, second
*
* Valid units of size:
* megabyte/mbyte/mb, kilobyte/kbyte/kb, byte
*
* Sizes and times may be singular or plural.
*/
* Sizes and times may be singular or plural.
*/
/* Extensions:
*
* Charybdis contains several extensions that are not enabled by default.
* To use them, uncomment the lines below.
*
<<<<<<< .merge_file_UmjhEh
* Channel mode +-A (admin only) -- chm_adminonly.so
* Channel mode +-O (oper only) -- chm_operonly.so
* Channel mode +-S (ssl only) -- chm_sslonly.so
@ -105,6 +109,73 @@
#loadmodule "extensions/sno_whois.so";
#loadmodule "extensions/override.so";
#loadmodule "extensions/no_kill_services.so";
=======
* Channel mode +-A (admin only) -- chm_adminonly
* Channel mode +-T (blocks notices) -- chm_nonotice
* Channel mode +-O (oper only) -- chm_operonly
* Channel mode +-S (ssl only) -- chm_sslonly
* Channel mode +-M (disallow KICK on IRC ops) -- chm_operpeace
* Restrict channel creation to logged in users -- createauthonly
* Account bans (+b $a[:mask]) -- extb_account
* Banned from another channel (+b $j:mask) -- extb_canjoin
* Other-channel bans (+b $c:mask) -- extb_channel
* Combination extbans -- extb_combi
* Extended ban (+b $x:mask) -- extb_extgecos
* Hostmask bans (for combination extbans) -- extb_hostmask
* Oper bans (+b $o) -- extb_oper
* Realname (gecos) bans (+b $r:mask) -- extb_realname
* Server bans (+b $s:mask) -- extb_server
* SSL bans (+b $z) -- extb_ssl
* User mode bans (+b $u:modes) -- extb_usermode
* Helpops system (umode +h) -- helpops
* HURT system -- hurt
* New host mangling (umode +x) -- ip_cloaking_4.0
* Old host mangling (umode +h) -- ip_cloaking
* Dynamically extend channel limits -- m_extendchans
* Find channel forwards -- m_findforwards
* /identify support -- m_identify
* /locops support -- m_locops
* Opers cannot be invisible (umode +i) -- no_oper_invis
* Far connection notices (snomask +F) -- sno_farconnect
* Remote oper up notices -- sno_globaloper
* Global nick-change notices -- sno_globalnickchange
* Oper-override (modehacking only) -- override
* Stop services kills -- no_kill_services
* Allows you to hide your idle time (umode +I) -- umode_hide_idle_time
*/
#loadmodule "extensions/chm_adminonly";
#loadmodule "extensions/chm_nonotice";
#loadmodule "extensions/chm_operonly";
#loadmodule "extensions/chm_sslonly";
#loadmodule "extensions/chm_operpeace";
#loadmodule "extensions/createauthonly";
#loadmodule "extensions/extb_account";
#loadmodule "extensions/extb_canjoin";
#loadmodule "extensions/extb_channel";
#loadmodule "extensions/extb_combi";
#loadmodule "extensions/extb_extgecos";
#loadmodule "extensions/extb_hostmask";
#loadmodule "extensions/extb_oper";
#loadmodule "extensions/extb_realname";
#loadmodule "extensions/extb_server";
#loadmodule "extensions/extb_ssl";
#loadmodule "extensions/extb_usermode";
#loadmodule "extensions/helpops";
#loadmodule "extensions/hurt";
#loadmodule "extensions/ip_cloaking_4.0";
#loadmodule "extensions/ip_cloaking";
#loadmodule "extensions/m_extendchans";
#loadmodule "extensions/m_findforwards";
#loadmodule "extensions/m_identify";
#loadmodule "extensions/m_locops";
#loadmodule "extensions/no_oper_invis";
#loadmodule "extensions/sno_farconnect";
#loadmodule "extensions/sno_globalnickchange";
#loadmodule "extensions/sno_globaloper";
#loadmodule "extensions/override";
#loadmodule "extensions/no_kill_services";
#loadmodule "extensions/umode_hide_idle_time";
>>>>>>> .merge_file_Mh5Whq
/* serverinfo {}: Contains information about the server. (OLD M:) */
serverinfo {
@ -129,11 +200,6 @@ serverinfo {
*/
network_name = "MyNet";
/* hub: allow this server to act as a hub and have multiple servers
* connected to it.
*/
hub = no;
/* vhost: the IP to bind to when we connect outward to ipv4 servers.
* This should be an ipv4 IP only.
*/
@ -143,18 +209,26 @@ serverinfo {
* This should be an ipv6 IP only.
*/
#vhost6 = "2001:db8:2::6";
<<<<<<< .merge_file_UmjhEh
/* ssl_private_key: our ssl private key */
ssl_private_key = "etc/ssl.key";
=======
>>>>>>> .merge_file_Mh5Whq
/* ssl_cert: certificate for our ssl server */
/* ssl_cert: certificate (and optionally key) for our ssl server */
ssl_cert = "etc/ssl.pem";
/* ssl_dh_params: DH parameters, generate with openssl dhparam -out dh.pem 1024 */
/* ssl_private_key: our ssl private key (if not contained in ssl_cert file) */
#ssl_private_key = "etc/ssl.key";
/* ssl_dh_params: DH parameters, generate with openssl dhparam -out dh.pem 2048 */
/* If you do not provide parameters, some TLS backends will fail on DHE- ciphers,
and some will succeed but use weak, common DH groups! */
ssl_dh_params = "etc/dh.pem";
/* ssl_cipher_list: A list of ciphers, dependent on your TLS backend */
#ssl_cipher_list = "EECDH+HIGH:EDH+HIGH:HIGH:!aNULL";
#ssl_cipher_list = "TLS_CHACHA20_POLY1305_SHA256:EECDH+HIGH:EDH+HIGH:HIGH:!aNULL";
/* ssld_count: number of ssld processes you want to start, if you
* have a really busy server, using N-1 where N is the number of
@ -245,7 +319,7 @@ class "users" {
*/
cidr_ipv6_bitlen = 64;
/* number_per_cidr: Number of connections to allow from a subnet of the
/* number_per_cidr: Number of connections to allow from a subnet of the
* size given in cidr_ipv4_bitlen/cidr_ipv6_bitlen.
* 4 seems to be a good default to me.
*/
@ -282,17 +356,20 @@ class "server" {
*/
connectfreq = 5 minutes;
/* max number: the amount of servers to autoconnect to. if the number
/* max_autoconn: the amount of servers to autoconnect to. if the number
* of servers in the class is or exceeds this, no more servers in the
* class are autoconnected. oper initiated connects are unaffected.
* this should usually be set to either 0 or 1. (autoconnecting from
* hubs to leaves may cause leaves to function as hubs by having
* multiple servers connected to them.)
*/
max_number = 1;
max_autoconn = 1;
/* max_number: the maximum number of servers allowed in this class */
max_number = 100;
/* sendq: servers need a higher sendq as they are sent more data */
sendq=2 megabytes;
sendq = 2 megabytes;
};
/* listen {}: contain information about the ports ircd listens on (OLD P:) */
@ -307,19 +384,19 @@ listen {
/* port: the specific port to listen on. if no host is specified
* before, it will listen on all available IPs.
*
* sslport: the specific port to listen ssl connections on. if no
* sslport: the specific port to listen ssl connections on. if no
* host is specified before, it will listen on all available IPs.
*
* ports are seperated via a comma, a range may be specified using ".."
*/
/* port: listen on all available IPs, ports 5000 and 6665 to 6669 */
port = 5000, 6665 .. 6669;
/* sslport: listen for ssl connections on all available IPs, port 9999 */
sslport = 9999;
/* host: set a specific IP/host the ports after the line will listen
/* sslport: listen for ssl connections on all available IPs, port 6697 */
sslport = 6697;
/* host: set a specific IP/host the ports after the line will listen
* on. This may be ipv4 or ipv6.
*/
host = "192.0.2.6";
@ -329,10 +406,21 @@ listen {
host = "2001:db8:2::6";
port = 7002;
sslport = 9002;
/* wsock: listeners defined with this option enabled will be websocket listeners,
* and will not accept normal clients.
*/
wsock = yes;
sslport = 9999;
};
/* auth {}: allow users to connect to the ircd (OLD I:) */
auth {
/* description: descriptive text to help recognize this auth block in
* stats i output.
*/
description = "example oper";
/* user: the user@host allowed to connect. Multiple IPv4/IPv6 user
* lines are permitted per auth block. This is matched against the
* hostname and IP address (using :: shortening for IPv6 and
@ -342,6 +430,11 @@ auth {
user = "*@198.51.100.0/24";
user = "*test@2001:db8:1:*";
/* umodes; the user mode character string to apply to users
* when they get placed into this auth block.
*/
#umodes = "+w";
/* auth_user: This allows specifying a username:password instead of
* just a password in PASS, so that a fixed user@host is not
* necessary for a specific auth{} block.
@ -353,7 +446,7 @@ auth {
* flags = ...; below if it is.
*/
password = "letmein";
/* spoof: fake the users user@host to be be this. You may either
* specify a host or a user@host to spoof to. This is free-form,
* just do everyone a favour and dont abuse it. (OLD I: = flag)
@ -361,26 +454,31 @@ auth {
spoof = "I.still.hate.packets";
/* Possible flags in auth:
*
*
* encrypted | password is encrypted with mkpasswd
* spoof_notice | give a notice when spoofing hosts
* exceed_limit (old > flag) | allow user to exceed class user limits
* kline_exempt (old ^ flag) | exempt this user from k/g/xlines&dnsbls
* dnsbl_exempt | exempt this user from dnsbls
* spambot_exempt | exempt this user from spambot checks
* shide_exempt | exempt this user from serverhiding
* kline_exempt (old ^ flag) | exempt this user from k/g/xlines,
* | dnsbls, and proxies
* dnsbl_exempt | exempt this user from dnsbls
* proxy_exempt | exempt this user from proxies
* spambot_exempt | exempt this user from spambot checks
* shide_exempt | exempt this user from serverhiding
* jupe_exempt | exempt this user from generating
* warnings joining juped channels
* resv_exempt | exempt this user from resvs
* resv_exempt | exempt this user from resvs
* flood_exempt | exempt this user from flood limits
* 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
* extend_chans | allow this user to join more channels than normal
* kline_spoof_ip | if this block has a spoof host, klines match only
* | the spoof and not the underlying IP
*/
flags = kline_exempt, exceed_limit;
/* class: the class the user is placed in */
class = "opers";
};
@ -392,7 +490,7 @@ auth {
*/
redirserv = "irc.example.net";
redirport = 6667;
user = "*.example.com";
/* class: a class is required even though it is not used */
@ -411,8 +509,15 @@ privset "local_op" {
*
* 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:general: enable most general oper privileges that came
* with +o in older releases
* auspex:oper: allows the oper to see through oper hiding
* auspex:umodes: allows viewing other users' modes
* auspex:cmodes: shows privileged cmodes
* auspex:hostname: shows hidden hostnames/ips
* oper:privs: allows /stats o/O and seeing privset in /whois
* oper:testline: allows /testline and /testgecos
* oper: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
@ -423,18 +528,36 @@ privset "local_op" {
* 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
* will not have the admin lines in
* whois.
* oper:xline: allows use of /quote xline/unxline
* oper:resv: allows /quote resv/unresv
* oper:cmodes: allows 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: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
* oper:mass_notice: allows sending mass notices
* oper:wallops: allows sending wallops messages
* oper:grant: allows using the GRANT command
* usermode:servnotice: allows setting +s
* oper:message: allows opers to bypass CALLERID (usermode +g)
* oper:free_target: messages to the oper bypass flood controls
*
* Privileges provided by extensions include:
*
* oper:dehelper: allows the DEHELPER command (from extensions/helpops)
* oper:override: enables oper override via umode +p (from extensions/override)
* oper:receive_immunity:
* confers the benefits of chmode +M (operpeace) (from extensions/chm_operpeace)
* usermode:helpops allows setting +h (from extensions/helpops)
* auspex:usertimes:
* allows viewing user idle/connect times even when +I is set (from extensions/umode_hide_idle_time)
* oper:shedding: allows the SHEDDING command (from extensions/m_shedding)
*/
privs = oper:local_kill, oper:operwall;
privs = oper:general, oper:privs, oper:testline, oper:kill, oper:operwall, oper:message,
usermode:servnotice, auspex:oper, auspex:hostname, auspex:umodes, auspex:cmodes;
};
privset "server_bot" {
@ -445,13 +568,14 @@ privset "server_bot" {
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;
privs = oper:routing, oper:kline, oper:unkline, oper:xline,
oper:resv, oper:cmodes, oper:mass_notice, oper:wallops,
oper:remoteban;
};
privset "admin" {
extends = "global_op";
privs = oper:admin, oper:die, oper:rehash, oper:spy;
privs = oper:admin, oper:die, oper:rehash, oper:spy, oper:grant;
};
/* operator {}: defines ircd operators. (OLD O:) */
@ -466,13 +590,13 @@ operator "god" {
user = "*@127.0.0.1";
/* password: the password required to oper. Unless ~encrypted is
* contained in flags = ...; this will need to be encrypted using
* contained in flags = ...; this will need to be encrypted using
* mkpasswd, MD5 is supported
*/
password = "etcnjl8juSU1E";
/* rsa key: the public key for this oper when using Challenge.
* A password should not be defined when this is used, see
* A password should not be defined when this is used, see
* doc/challenge.txt for more information.
*/
#rsa_public_key_file = "/usr/local/ircd/etc/oper.pub";
@ -510,12 +634,21 @@ operator "god" {
privset = "admin";
};
/* connect {}: controls servers we connect to (OLD C:, N:, H:, L:) */
/* connect {}: controls servers we connect with (OLD C:, N:, H:, L:).
*
* This configuration is used whether connections are incoming or
* outgoing.
*/
connect "irc.uplink.com" {
/* the name must go above */
/* the name of the other server must go above. It should match the
* other server's name in its serverinfo {} block, and does not
* need to be an actual hostname.
*/
/* host: the host or IP to connect to. If a hostname is used it
* must match the reverse dns of the server.
/* host: the host or IP to connect to.
*
* It is also used to validate incoming connections. If a hostname
* is used, it must match the reverse dns of the server.
*/
host = "203.0.113.3";
@ -539,65 +672,44 @@ connect "irc.uplink.com" {
/* port: the port to connect to this server on */
port = 6666;
/* hub mask: the mask of servers that this server may hub. Multiple
* entries are permitted
*/
hub_mask = "*";
/* leaf mask: the mask of servers this server may not hub. Multiple
* entries are permitted. Useful for forbidding EU -> US -> EU routes.
*/
#leaf_mask = "*.uk";
/* class: the class this server is in */
class = "server";
/* flags: controls special options for this server
* encrypted - marks the accept_password as being crypt()'d
* autoconn - automatically connect to this server
* compressed - compress traffic via ziplinks
* topicburst - burst topics between servers
* ssl - ssl/tls encrypted server connections
* encrypted - marks the accept_password as being crypt()'d
* autoconn - automatically connect to this server
* topicburst - burst topics between servers
* ssl - ssl/tls encrypted server connections
* sctp - use SCTP instead of TCP to connect to the server
* no-export - marks the link as a no-export link (not exported to other links)
*/
flags = compressed, topicburst;
flags = topicburst;
};
connect "ipv6.some.server" {
/* Hosts that are IPv6 addresses must be in :: shortened form
* if applicable. Addresses starting with a colon get an extra
* zero prepended, for example: 0::1
*/
connect "ipv6.lame.server" {
host = "192.0.2.1";
host = "2001:db8:3::8";
send_password = "password";
accept_password = "password";
port = 6666;
/* aftype: controls whether the connection uses "ipv4" or "ipv6".
* Default is ipv4.
/* aftype: controls whether the outgoing connection uses "ipv4" or "ipv6".
* Default is to try either at random.
*/
aftype = ipv6;
class = "server";
};
connect "ssl.uplink.com" {
/* Example of ssl server-to-server connection, ssl flag doesn't need
* compressed flag, 'cause it uses own compression
*/
host = "203.0.113.129";
send_password = "password";
accept_password = "anotherpassword";
port = 9999;
hub_mask = "*";
class = "server";
flags = ssl, topicburst;
};
/* cluster {}; servers that we propagate things to automatically.
* NOTE: This does NOT grant them privileges to apply anything locally,
* you must add a seperate shared block for that. Clustering will
* only be done for actions by LOCAL opers, that arent directed
* remotely.
*/
/* cluster {}; servers that we propagate things to automatically. */
cluster {
/* name: the server to share with, this can be a wildcard and may be
* stacked.
@ -630,8 +742,7 @@ cluster {
/* service{}: privileged servers (services). These servers have extra
* privileges such as setting login names on users and introducing clients
* with umode +S (unkickable, hide channels, etc). This does not allow them
* to set bans, you need a separate shared{} for that.
* with umode +S (unkickable, hide channels, etc).
* Do not place normal servers here.
* There may be only one service{} block.
*/
@ -640,56 +751,6 @@ service {
name = "services.int";
};
/* shared {}: users that are allowed to place remote bans on our server.
* NOTE: These are ordered top down. The first one the user@host and server
* matches will be used. Their access will then be decided on that
* block and will not fall back to another block that matches.
*/
shared {
/* oper: the user@host and server the user must be on to set klines.
* The first field must be a user@host, the second field is an
* optional server. These may be stacked.
*/
/* flags: list of what to allow them to place, all the oper lines
* above this (up until another flags entry) will receive these
* flags. This *must* be present.
*
* kline - allow setting perm/temp klines
* tkline - allow setting temp klines
* unkline - allow removing klines
* xline - allow setting perm/temp xlines
* txline - allow setting temp xlines
* unxline - allow removing xlines
* resv - allow setting perm/temp resvs
* tresv - allow setting temp resvs
* unresv - allow removing xlines
* all - allow oper/server to do all of above.
* locops - allow locops - only used for servers who cluster
* rehash - allow rehashing
* dline - allow setting perm/temp dlines
* tdline - allow setting temp dlines
* undline - allow removing dlines
* none - disallow everything
*/
/* allow flame@*.leeh.co.uk on server irc.ircd-ratbox.org and
* allow leeh@*.leeh.co.uk on server ircd.ircd-ratbox.org to kline
*/
oper = "flame@*.leeh.co.uk", "irc.ircd-ratbox.org";
oper = "leeh@*.leeh.co.uk", "ircd.ircd-ratbox.org";
flags = kline;
/* you may forbid certain opers/servers from doing anything */
oper = "irc@vanity.oper", "*";
oper = "*@*", "irc.vanity.server";
oper = "irc@another.vanity.oper", "bigger.vanity.server";
flags = none;
/* or allow everyone to place temp klines */
oper = "*@*";
flags = tkline;
};
/* exempt {}: IPs that are exempt from Dlines and rejectcache. (OLD d:) */
exempt {
ip = "192.0.2.0/24";
@ -698,6 +759,12 @@ exempt {
ip = "127.0.0.1";
};
/* secure {}: IPs that are considered to be secure networks, and get
* +Z without using TLS */
secure {
ip = "127.0.0.1";
};
/* The channel block contains options pertaining to channels */
channel {
/* invex: Enable/disable channel mode +I, a n!u@h list of masks
@ -735,6 +802,9 @@ channel {
/* max chans: The maximum number of channels a user can join/be on. */
max_chans_per_user = 15;
/* max chans (large): The extended maximum number of channels a user can join. */
max_chans_per_user_large = 60;
/* max bans: maximum number of +b/e/I/q modes in a channel */
max_bans = 100;
@ -755,7 +825,7 @@ channel {
default_split_user_count = 0;
/* split servers: when the amount of servers that have acknowledged
* theyve finished bursting is lower than this, consider ourselves
* theyve finished bursting is lower than this, consider ourselves
* split. this must be set for automatic splitmode
*/
default_split_server_count = 0;
@ -810,6 +880,22 @@ channel {
* such as LIST >0.
*/
displayed_usercount = 3;
/* strip_topic_colors: whether or not color codes in TOPIC should be stripped. */
strip_topic_colors = no;
/* opmod_send_statusmsg: format messages sent to ops due to +z
* as PRIVMSG @#channel when sent to clients.
*/
opmod_send_statusmsg = no;
/* ip_bans_through_vhost: should channel IP bans see through dynamic spoofed hosts? */
ip_bans_through_vhost = yes;
/* invite_notify_notice: when using extensions/invite_notify, should
* we send a NOTICE to clients that don't support IRCv3 invite-notify
*/
invite_notify_notice = yes;
};
@ -841,8 +927,7 @@ serverhide {
* You can have multiple combinations of host and rejection reasons.
* They are used in pairs of one host/rejection reason.
*
* These settings should be adequate for most networks, and are (presently)
* required for use on StaticBox.
* These settings should be adequate for most networks.
*
* Word to the wise: Do not use blacklists like SPEWS for blocking IRC
* connections.
@ -867,7 +952,7 @@ serverhide {
* to match the final octet (e.g. 127.0.0.1) or "127.x.y.z" to explicitly match
* an A record. The blacklist is only applied if it matches anything in the
* list. You may freely mix full IP's and final octets.
*
*
* Consult your blacklist provider for the meaning of these parameters; they
* are usually used to denote different ban types.
*/
@ -883,6 +968,78 @@ blacklist {
# reject_reason = "${nick}, your IP (${ip}) is listed in ${dnsbl-host} for some reason. In order to protect ${network-name} from abuse, we are not allowing connections listed in ${dnsbl-host} to connect";
};
/* These are the OPM settings.
* This is similar to the functionality provided by BOPM. It will scan incoming
* connections for open proxies by connecting to clients and attempting several
* different open proxy handshakes. If they connect back to us (via a dedicated
* listening port), and send back the data we send them, they are considered
* an open proxy. For politeness reasons (users may be confused by the incoming
* connection attempts if they are logging incoming connections), the user is
* notified upon connect if they are being scanned.
*
* WARNING:
* These settings are considered experimental. Only the most common proxy types
* are checked for (Charybdis is immune from POST and GET proxies). If you are
* not comfortable with experimental code, do not use this feature.
*/
#opm {
/* IPv4 address to listen on. This must be a publicly facing IP address
* to be effective.
* If omitted, it defaults to serverinfo::vhost.
*/
#listen_ipv4 = "127.0.0.1";
/* IPv4 port to listen on.
* This should not be the same as any existing listeners.
*/
#port_v4 = 32000;
/* IPv6 address to listen on. This must be a publicly facing IP address
* to be effective.
* If omitted, it defaults to serverinfo::vhost6.
*/
#listen_ipv6 = "::1";
/* IPv6 port to listen on.
* This should not be the same as any existing listeners.
*/
#port_v6 = 32000;
/* You can also set the listen_port directive which will set both the
* IPv4 and IPv6 ports at once.
*/
#listen_port = 32000;
/* This sets the timeout in seconds before ending open proxy scans.
* Values less than 1 or greater than 60 are ignored.
* It is advisable to keep it as short as feasible, so clients do not
* get held up by excessively long scan times.
*/
#timeout = 5;
/* These are the ports to scan for SOCKS4 proxies on. They may overlap
* with other scan types. Sensible defaults are given below.
*/
#socks4_ports = 80, 443, 1080, 8000, 8080, 10800;
/* These are the ports to scan for SOCKS5 proxies on. They may overlap
* with other scan types. Sensible defaults are given below.
*/
#socks5_ports = 80, 443, 1080, 8000, 8080, 10800;
/* These are the ports to scan for HTTP CONNECT proxies on (plaintext).
* They may overlap with other scan types. Sensible defaults are given
* below.
*/
#httpconnect_ports = 80, 8080, 8000;
/* These are the ports to scan for HTTPS CONNECT proxies on (SSL).
* They may overlap with other scan types. Sensible defaults are given
* below.
*/
#httpsconnect_ports = 443, 4443;
#};
/*
* Alias blocks allow you to define custom commands. (Old m_sshortcut.c)
* They send PRIVMSG to the given target. A real command takes
@ -1007,7 +1164,7 @@ general {
*/
default_floodcount = 10;
/* failed oper notice: send a notice to all opers on the server when
/* failed oper notice: send a notice to all opers on the server when
* someone tries to OPER and uses the wrong password, host or ident.
*/
failed_oper_notice = yes;
@ -1015,7 +1172,7 @@ general {
/* dots in ident: the amount of '.' characters permitted in an ident
* reply before the user is rejected.
*/
dots_in_ident=2;
dots_in_ident = 2;
/* min nonwildcard: the minimum non wildcard characters in k/d/g lines
* placed via the server. klines hand placed are exempt from limits.
@ -1079,28 +1236,72 @@ general {
* displayed unconditionally.
*/
global_snotices = yes;
/* dline reason: show the user the dline reason when they connect
/* dline reason: show the user the dline reason when they connect
* and are dlined.
*/
dline_with_reason = yes;
/* kline delay: delay the checking of klines until a specified time.
* Useful if large kline lists are applied often to prevent the
* server eating CPU.
*/
kline_delay = 0 seconds;
/* kline reason: show the user the reason why they are k/dlined
/* kline reason: show the user the reason why they are k/dlined
* on exit. may give away who set k/dline when set via tcm.
*/
kline_with_reason = yes;
/* tkline duration: when showing users their k/dline reason (see
* kline_with_reason), don't add "Temporary K-line 123 min."
*/
hide_tkdline_duration = no;
/* kline reason: make the users quit message on channels this
* reason instead of the oper's reason.
*/
kline_reason = "Connection closed";
/* SASL access only client message: give users a message that
* informs them
*/
sasl_only_client_message = "You need to identify via SASL to use this server.";
/* Identd access only client message: give users a message that
* informs them
*/
identd_only_client_message = "You need to install identd to use this server.";
/* SCTP forbidden client message: give users a message that
* informs them
*/
sctp_forbidden_client_message = "You are not allowed to use SCTP on this server.";
/* SSL/TLS access only client message: give users a message that
* informs them
*/
ssltls_only_client_message = "You need to use SSL/TLS to use this server.";
/* Not authorised client message: tell users that they are not
* authorised
*/
not_authorised_client_message = "You are not authorised to access this server.";
/* Illegal hostname client message: tell users that they have illegal
* chars in their hostname
*/
illegal_hostname_client_message = "You have an illegal character in your hostname.";
/* Server full client message: tell users that the server they're connecting
* to is full
*/
server_full_client_message = "Sorry, server is full - try later";
/* illegal name long client message: long-form explanation that their username
* contains illegal characters
*/
illegal_name_long_client_message = "Your username is invalid. Please make sure that your username contains only alphanumeric characters.";
/* illegal name short client message: short-form notification that their username
* contains illegal characters; will be followed by ": their_username"
*/
illegal_name_short_client_message = "Invalid username";
/* identify to services via server password
* if auth{} block had no password but the user specified a
* server password anyway, send a PRIVMSG to <identify_service>
@ -1113,7 +1314,7 @@ general {
non_redundant_klines = yes;
/* warn no nline: warn opers about servers that try to connect but
* we dont have a connect {} block for. Twits with misconfigured
* we dont have a connect {} block for. Twits with misconfigured
* servers can get really annoying with this enabled.
*/
warn_no_nline = yes;
@ -1131,36 +1332,40 @@ general {
stats_e_disabled = no;
/* stats c oper only: make stats c (connect {}) oper only */
stats_c_oper_only=no;
/* stats h oper only: make stats h (hub_mask/leaf_mask) oper only */
stats_h_oper_only=no;
stats_c_oper_only = no;
/* stats y oper only: make stats y (class {}) oper only */
stats_y_oper_only=no;
stats_y_oper_only = no;
/* stats o oper only: make stats o (opers) oper only */
stats_o_oper_only=yes;
stats_o_oper_only = yes;
/* stats P oper only: make stats P (ports) oper only
* NOTE: users doing stats P will never be given the ips that the
* NOTE: users doing stats P will never be given the ips that the
* server listens on, simply the ports.
*/
stats_P_oper_only=no;
stats_P_oper_only = no;
/* stats i oper only: make stats i (auth {}) oper only. set to:
* yes: show users no auth blocks, made oper only.
* masked: show users first matching auth block
* no: show users all auth blocks.
*/
stats_i_oper_only=masked;
stats_i_oper_only = masked;
/* stats k/K oper only: make stats k/K (klines) oper only. set to:
* yes: show users no auth blocks, made oper only
* masked: show users first matching auth block
* no: show users all auth blocks.
*/
stats_k_oper_only=masked;
stats_k_oper_only = masked;
/* stats l/L oper only:
* yes: non-opers can't use this at all
* self: non-opers see only themselves
* no: show targeted users or non-hidden opers to everyone
*/
stats_l_oper_only = self;
/* map oper only: make /map oper only */
map_oper_only = no;
@ -1202,6 +1407,13 @@ general {
*/
ping_cookie = no;
/* ping warn time: how long to wait after pinging a server before starting
* to complain it is unresponsive. Note that the ping check interval is 30
* seconds, so the first complaint will come at the next check after this
* time has passed.
*/
ping_warn_time = 15 seconds;
/* connect timeout: sets how long we should wait for a connection
* request to succeed
*/
@ -1220,12 +1432,18 @@ general {
/* REMOVE ME. The following line checks you've been reading. */
havent_read_conf = yes;
/* max targets: the maximum amount of targets in a single
/* max targets: the maximum amount of targets in a single
* PRIVMSG/NOTICE. set to 999 NOT 0 for unlimited.
*/
max_targets = 4;
/* post-registration delay: wait this long before processing commands from a newly
* registered user. Used to allow network utility bots to perform any actions
* (such as host changes or proxy scanning) before the user can join channels.
*/
post_registration_delay = 2 seconds;
/* use_whois_actually: send clients requesting a whois a numeric
* giving the real IP of non-spoofed clients to prevent DNS abuse.
*/
@ -1233,9 +1451,9 @@ general {
/* usermodes configurable: a list of usermodes for the options below
*
* +g - callerid - Server Side Ignore
* +g - callerid - Server-side private message allow list
* +D - deaf - Don't see channel messages
* +i - invisible - Not shown in NAMES or WHO unless you share a
* +i - invisible - Not shown in NAMES or WHO unless you share a
* a channel
* +l - locops - See LOCOPS messages
* +Q - noforward - Unaffected by channel forwarding
@ -1244,7 +1462,7 @@ general {
* +w - wallop - See oper and server generated WALLOPS
* +z - operwall - See operwalls
*/
/* oper only umodes: usermodes only opers may set */
oper_only_umodes = operwall, locops, servnotice;
@ -1255,14 +1473,6 @@ general {
* provided they have umode +s set */
oper_snomask = "+s";
/* compression level: level of compression for compressed links between
* servers.
*
* values are between: 1 (least compression, fastest)
* and: 9 (most compression, slowest).
*/
#compression_level = 6;
/* burst_away: This enables bursting away messages to servers.
* With this disabled, we will only propogate AWAY messages
* as users send them, but never burst them. Be warned though
@ -1336,6 +1546,7 @@ general {
* "SPKI:SHA2-256:" or "SPKI:SHA2-512:" depending on the hash type. These fingerprints
* are not supported on servers running charybdis 3.5.3 or earlier.
*
<<<<<<< .merge_file_UmjhEh
* To generate a fingerprint from a certificate file, run the following:
* $ openssl x509 -outform DER -in your.crt | sha1sum (or sha256sum, or sha512sum)
*
@ -1348,17 +1559,44 @@ general {
* sha512sum | sed -r -e 's/^/SPKI:SHA2-512:/'
*/
certfp_method = sha256;
=======
* To generate a fingerprint from a certificate file, please use the mkfingerprint utility
* program located in the bin/ subdirectory of your IRCd installation. Running it with no
* arguments will give you a brief usage message; it takes method and filename arguments.
*/
certfp_method = spki_sha256;
/* hide_opers_in_whois: if set to YES, then oper status will be hidden in /WHOIS output. */
hide_opers_in_whois = no;
/* hide_opers: Hide all opers from unprivileged users */
hide_opers = no;
/* tls_ciphers_oper_only: show the TLS cipher string in /WHOIS only to opers and self */
tls_ciphers_oper_only = no;
/* hidden_caps: client capabilities we'll pretend we don't support until they're requested */
#hidden_caps = "userhost-in-names";
/* oper_secure_only: require TLS on any connection trying to oper up */
oper_secure_only = no;
/* drain_reason: Message shown to users when they are rejected from a draining server.
* requires extensions/drain to be loaded.
*/
drain_reason = "This server is not accepting connections.";
>>>>>>> .merge_file_Mh5Whq
};
modules {
/* module path: paths to search for modules specified below and
/* module path: paths to search for modules specified below and
* in /modload.
*/
path = "/usr/local/ircd/modules";
path = "/usr/local/ircd/modules/autoload";
/* module: the name of a module to load on startup/rehash */
#module = "some_module.so";
#module = "some_module";
};
/*

View file

@ -1,15 +1,15 @@
Server VERSION Info
$Id: server-version-info 1851 2006-08-24 17:16:53Z jilles $
Copyright (c) 2001 by ircd-hybrid team
Copyright (c) 2002 ircd-ratbox development team
Copyright (c) 2016 Charybdis development team
----------------------------------------------------------------------
When you type /version, you will often see something like this:
ircd-ratbox-1.0rc7(20021120_0). embers.lan egGHIKMpZ6 TS5ow
charybdis-3.5.0-rc1(20151011-d09bde1). joestar.interlinked.me :eIKMpSZ6 TS6ow 1US
Ever wondered what those funny chars mean after the version number? Well
here they are:
@ -17,12 +17,6 @@
+----------------------------+
| 'e' | USE_EXCEPT |
|------+---------------------|
| 'g' | NO_FAKE_GLINES |
|------+---------------------|
| 'G' | GLINES |
|------+---------------------|
| 'H' | HUB |
|------+---------------------|
| 'I' | USE_INVEX |
|------+---------------------|
| 'K' | USE_KNOCK |
@ -33,8 +27,6 @@
|------+---------------------|
| 'S' | OPERS_SEE_ALL_USERS |
|------+---------------------|
| 'T' | IGNORE_BOGUS_TS |
|------+---------------------|
| 'Z' | ZIPLINKS |
|------+---------------------|
| '6' | IPv6 |
@ -43,7 +35,7 @@
|------+---------------------|
| 'TS' | Supports TS |
|------+---------------------|
| '5' | TS Version 5 |
| '6' | TS Version 6 |
|------+---------------------|
| 'o' | TS Only |
|------+---------------------|

View file

@ -1,330 +0,0 @@
Protocol changes for +TSora
---------------------------
Note:
The protocols described here implement TimeStamps on IRC channels and
nicks. The idea of IRC TimeStamps was started on Undernet, and first
implemented by Run <carlo@runaway.xs4all.nl>. The protocols used here
are not exactly the same as the ones used on Undernet; the nick-kill
handling is very similar and must be credited to Run, while the
"TimeStamped channel description" protocol is quite different.
TSora servers keep track of which version of the TS protocol (if any)
their neighboring servers are using, and take it into account when
sending messages to them. This allows for seamless integration of TS
servers into a non-TS net, and for upgrades of the protocol.
Each server knows which is the lowest and the highest version of the
TS protocol it can interact with; currently both of these are set to 1:
#define TS_CURRENT 1 /* the highest TS ver we can do */
#define TS_MIN 1 /* the lowest TS ver we can do */
Timings and TS versions:
========================
. Keep a 'delta' value to be added to the result of all calls to time(),
initially 0.
. Send a second argument to the PASS command, ending in the 'TS' string.
. Send a
SVINFO <TS_CURRENT> <TS_MIN> <STANDALONE> :<UTC-TIME>
just after "SERVER", where <STANDALONE> is 1 if we're connected to
more TSora servers, and 0 if not, and <UTC-TIME> is our idea of the
current UTC time, fixed with the delta.
. When we receive a "SVINFO <x> <y> <z> :<t>" line from a connecting
server, we ignore it if TS_CURRENT<y or x<TS_MIN, otherwise we
set a flag remembering that that server is TS-aware, remember the TS
version to use with it (min(TS_CURRENT, x)). Additionally, if this is
our first connected TS server, we set our delta to t-<OUR_UTC> if
z==0, and to (t-<OUR_UTC>)/2 if z!=0. The SVINFO data is kept around
until the server has effectively registered with SERVER, and used
*after* sending our own SVINFO to that server.
Explanations:
Servers will always know which of their directly-linked servers can do
TS, and will use the TS protocol only with servers that do understand
it. This makes it possible to switch to full TS in just one
code-replacement step, without incompatibilities.
As long as not all servers are TS-aware, the net will be divided into
"zones" of linked TS-aware servers. Channel modes will be kept
synchronized at least within the zone in which the channel was
created, and nick collisions between servers in the same zone will
result in only one client being killed.
Time synchronization ensures that servers have the same idea of the
current time, and achieves this purpose as long as TS servers are
introduced one by one within the same 'zone'. The merging of two zones
cannot synchronize them completely, but it is to be expected that
within each zone the effective time will be very close to the real
time.
By sending TSINFO after SERVER rather than before, we avoid the extra
lag created by the identd check on the server. To be able to send
immediately a connect burst of either type (TS or not), we need to
know before that if the server does TS or not, so we send that
information with PASS as an extra argument. And to avoid being
incompatible with 2.9 servers, which check that this second argument
begins with "2.9", we check that it *ends* with "TS".
The current time is only used when setting a TS on a new channel or
nick, and once such a TS is set, it is never modified because of
synchronization, as it is much more important that the TS for a
channel or nick stays the same across all servers than that it is
accurate to the second.
Note that Undernet's 2.8.x servers have no time synchronization at
all, and have had no problems because of it - all of this is more to
catch the occasional server with a way-off clock than anything.
NICK handling patches (anti-nick-collide + shorter connect burst):
==================================================================
. For each nick, store a TS value = the TS value received if any, or our
UTC+delta at the time we first heard of the nick. TS's are propagated
to TS-aware servers whenever sending a NICK command.
. Nick changes reset the TS to the current time.
. When sending a connect burst to another TS server, replace the
NICK/USER pair with only one NICK command containing the nick, the
hopcount, the TS, the umode, and all the USER information.
The format for a full NICK line is:
NICK <nick> <hops> <TS> <umode> <user> <host> <server> :<ircname>
The umode is a + followed by any applying usermodes.
The format for a nick-change NICK line is:
:<oldnick> NICK <newnick> :<TS>
. When a NICK is received from a TS server, that conflicts with an
existing nick:
+ if the userhosts differ or one is not known:
* if the timestamps are equal, kill ours and the old one if it
was a nick change
* if the incoming timestamp is older than ours, kill ours and
propagate the new one
* if the incoming timestamp is younger, ignore the line, but kill
the old nick if it was a nick change
+ if the userhosts are the same:
* if the timestamps are equal, kill ours and the old one if it
was a nick change
* if the incoming timestamp is younger, kill ours and propagate
the new one
* if the incoming timestamp is older, ignore the line but kill
the old nick if it was a nick change
. When a NICK is received from a non-TS server that conflicts with
an existing nick, kill both.
. Do not send "Fake Prefix" kills in response to lines coming from TS
servers; the sanitization works anyway, and this allows the "newer
nick overruled" case to work.
Explanations:
The modified nick-introduction syntax allows for a slightly shorter
connect-burst, and most importantly lets the server compare
user@host's when determining which nick to kill: if the user@host
is the same, then the older nick must be killed rather than the
newer.
When talking to a non-TS server, we need to behave exactly like one
because it expects us to. When talkign to a TS server, we don't kill
the nicks it's introducing, as we know it'll be smart enough to do it
itself when seeing our own introduced nick.
When we see a nick arriving from a non-TS server, it won't have a TS,
but it's safe enough to give it the current time rather than keeping
it 0; such TS's won't be the same all across the network (as long as
there is more than one TS zone), and when there's a collision, the TS
used will be the one in the zone the collision occurs in.
Also, it is important to note that by the time a server sees (and
chooses to ignore) a nick introduction, the introducing server has
also had the time to put umode changes for that nick on its queue, so
we must ignore them too... so we need to ignore fake-prefix lines
rather than sending kills for them. This is safe enough, as the rest
of the protocol ensures that they'll get killed anyway (and the
Undernet does it too, so it's been more than enough tested). Just for
an extra bit of compatibility, we still kill fake prefixes coming from
non-TS servers.
This part of the TS protocol is almost exactly the same as the
Undernet's .anc (anti-nick-collide) patches, except that Undernet
servers don't add usermodes to the NICK line.
TimeStamped channel descriptions (avoiding hacked ops and desynchs):
====================================================================
. For each channel, keep a timestamp, set to the current time when the
channel is created by a client on the local server, or to the received
value if the channel has been propagated from a TS server, or to 0
otherwise. This value will have the semantics of "the time of creation
of the current ops on the channel", and 0 will mean that the channel
is in non-TS mode.
A new server protocol command is introduced, SJOIN, which introduces
a full channel description: a timestamp, all the modes (except bans),
and the list of channel members with their ops and voices. This
command will be used instead of JOIN and of (most) MODEs both in
connect bursts and when propagating channel creations among TS
servers. SJOIN will never be accepted from or sent to users.
The syntax for the command is:
SJOIN <TS> #<channel> <modes> :[@][+]<nick_1> ... [@][+]<nick_n>
The fields have the following meanings:
* <TS> is the timestamp for the channel
* <modes> is the list of global channel modes, starting with a +
and a letter for each of the active modes (spmntkil), followed
by an argument for +l if there is a limit, and an argument for
+k if there's a key (in the same order they were mentioned in
the string of letters).
A channel with no modes will have a "+" in that field.
A special value of "0" means that the server does not specify the
modes, and will be used when more than one SJOIN line is needed
to completely describe a channel, or when propagating a SJOIN
the modes of which were rejected.
* Each nick is preceded by a "@" if the user has ops, and a "+" if
the user has a voice. For mode +ov, both flags are used.
SJOINs will be propagated (when appropriate) to neighboring TS
servers, and converted to JOINs and MODEs for neighboring non-TS
servers.
To propagate channels for which not all users fit in one
SJOIN line, several SJOINs will be sent consecutively, only the first
one including actual information in the <mode> field.
An extra ad-hoc restriction is imposed on SJOIN messages, to simplify
processing: if a channel has ops, then the first <nick> of the first
SJOIN sent to propagate that channel must be one of the ops.
Servers will never attempt to reconstruct a SJOIN from JOIN/MODE
information being received at the moment from other servers.
. For each user on a channel, keep an extra flag (like ops and voice)
that is set when the user has received channel ops from another
server (in a SJOIN channel description), which we rejected (ignored).
Mode changes (but NOT kicks) coming from a TS server and from someone
with this flag set will be ignored. The flag will be reset when the
user gets ops from another user or server.
. On deops done by non-local users, coming from TS servers, on channels
with a non-zero TS, do not check that the user has ops but check that
their 'deopped' flag is not set. For kicks coming from a TS server, do
not check either. This will avoid desynchs, and 'bad' modechanges are
avoided anyway. Other mode changes will still only be taken into
account and propagated when done by users that are seen as having ops.
. When a MODE change that ops someone is received from a server for a
channel, that channel's TS is set to 0, and the mode change is
propagated.
. When a SJOIN is received for a channel, deal with it in this way:
* received-TS = 0:
+ if we have ops or the SJOIN doesn't op anyone, SJOIN propagated
with our own TS.
+ otherwise, TS set to 0 and SJOIN propagated with 0.
* received-TS > 0, own-TS = 0:
+ if the SJOIN ops someone or we don't have ops, set our TS to the
received TS and propagate.
+ otherwise, propagate with TS = 0.
* received-TS = own-TS: propagate.
* received-TS < own-TS:
+ if the SJOIN ops someone, remove *all* modes (except bans) from
the channel and propagate these mode changes to all neighboring
non-TS servers, and copy the received TS and propagate the SJOIN.
+ if the SJOIN does not op anyone and we have ops, propagate
with our own TS.
+ otherwise, copy the received TS and propagate the SJOIN.
* received-TS > own-TS:
+ if the SJOIN does not introduce any ops, process and propagate
with our own TS.
+ if we have ops: for each person the mode change would op, set the
'deopped' flag; process all the JOINs ignoring the '@' and '+'
flags; propagate without the flags and with our TS.
+ if we don't have ops: set our TS to the received one, propagate
with the flags.
Explanations:
This part of the protocol is the one that is most different (and
incompatible) with the Undernet's: we never timestamp MODE changes,
but instead we introduce the concept of time-stamped channel
descriptions. This way each server can determine, based on its state
and the received description, what the correct modes for a channel
are, and deop its own users if necessary. With this protocol, there is
*never* the need to reverse and bounce back a mode change. This is
both faster and more bandwith-effective.
The end goal is to have a protocol will eventually protect channels
against hacked ops, while minimizing the impact on a mixed-server net.
In order to do this, whenever there is a conflict between a TS server
and a non-TS one, the non-TS one's idea of the whole situation
prevails. This means that channels will only have a TS when they have
been created on a TS-aware server, and will lose it whenever a server
op comes from a non-TS server. Also, at most one 'zone' will have a TS
for any given channel at any given time, ensuring that there won't be
any deops when zones are merged. However, when TS zones are merged, if
the side that has a TS also has ops, then the TS is kept across the
whole new zone. Effective protection will only be ensured once all
servers run TS patches and channels have been re-created, as there is
no way servers can assign a TS to a channel they are not creating
(like they do with nicks) without having unwanted deops later.
The visible effects of this timestamped channel-description protocol
are that when a split rejoins, and one side has hacked ops, the other
side doesn't see any server mode changes (just like with Undernet's
TS), but the side that has hacked ops sees:
* first the first server on the other side deopping and devoicing
everyone, and fixing the +spmntkli modes
* then other users joining, and getting server ops and voices
The less obvious part of this protocol is its behavior in the case
that the younger side of a rejoin has servers that are lagged with
each other. In such a situation, a SJOIN that clears all modes and
sets the legitimate ones is being propagated from one server, and
lagged illegitimate mode changes and kicks are being propagated in the
opposite direction. In this case, a kick done by someone who is being
deopped by the SJOIN must be taken into account to keep the name list
in sync (and since it can only be kicking someone who also was on the
younger side), while a deop does not matter (and will be ignored by
the first server on the other side), and an opping *needs* to be
discareded to avoid hacked ops.
The main property of timestamped channel descriptions that makes them
a very stable protocol even with lag and splits, is that they leave a
server in the same final state, independently of the order in which
channel descriptions coming from different servers are received. Even
when SJOINs and MODEs for the same channel are being propagated in
different direction because of several splits rejoining, the final
state will be the same, independently of the exact order in which each
server received the SJOINs, and will be the same across all the
servers in the same zone.

View file

@ -1,5 +1,5 @@
Server capabilities
William Pitcock <nenolod -at- nenolod.net>
Ariadne Conill <ariadne -at- dereferenced.org>
-------------------
Not all TSora IRCd's support these.

View file

@ -1,5 +1,3 @@
$Id: cluster.txt 6 2005-09-10 01:02:21Z nenolod $
Short description of how remote kline and friends are propagated under
the old hyb7 style (CAP_KLN etc) and under the new style over ENCAP.

View file

@ -1,5 +1,3 @@
$Id: euid.txt 1863 2006-08-27 13:40:37Z jilles $
Extended UID command proposal
Jilles Tjoelker <jilles@stack.nl>

View file

@ -1,8 +1,6 @@
Overview of the event subsystem
Adrian Chadd <adrian@creative.net.au>
$Id: event.txt 6 2005-09-10 01:02:21Z nenolod $
One of the things that immediately struck me whilst first looking at the
code was that the ircd periodically scheduled things in io_loop() but

View file

@ -1,47 +0,0 @@
Overview of the filedescriptor subsystem
Adrian Chadd <adrian@creative.net.au>
$Id: fd-management.txt 6 2005-09-10 01:02:21Z nenolod $
Filedescriptor lists
--------------------
The filedescriptor list is managed through the routines in fdlist.c .
These include:
fd_open() - tag an FD as "open" and active
fd_close() - tag an FD as "closed" and close() the filedescriptor
fd_note() - update the filedescriptor tag
You can get the current list of open filedescriptors through /stats F as
an oper.
FD lists
--------
The FD list support is very alpha. There are a few lists defined:
typedef enum fdlist_t {
FDLIST_NONE,
FDLIST_SERVICE,
FDLIST_SERVER,
FDLIST_IDLECLIENT,
FDLIST_BUSYCLIENT,
FDLIST_MAX
} fdlist_t;
FDLIST_NONE Not on any list (ie close()d)
FDLIST_SERVICE A service - listen() sockets, resolver, etc
FDLIST_SERVER Server connections
FDLIST_IDLECLIENT An idle client
FDLIST_BUSYCLIENT A busy client
FDLIST_MAX Used for bounds checking
The idea is that the SERVICE sockets need polling frequently, the SERVER
sockets also need polling frequently, BUSYCLIENT is for busy clients
which need frequent polling (eg we're trying to write to them), and
IDLECLIENT is for clients which we don't need to poll frequently.
THIS hasn't been decided upon yet.

View file

@ -6,7 +6,7 @@ contrib/example_module.c, this document simply describes which hooks are
available.
There are various hook structures available that may be passed to hooks:
hook_data - struct Client *client; const void *arg1;
hook_data - struct Client *client; const void *arg1;
const void *arg2;
hook_data_int - struct Client *client; const void *arg1; int arg2;
hook_data_client - struct Client *client; struct Client *target;
@ -114,11 +114,27 @@ The following hooks are called during various events related to clients.
oldsnomask = new snomask field
The following are for debugging and take struct hook_io_data for arguments.
Channel Hooks
-------------
"can_invite" - Called before deciding whether to allow the
/invite command
hdata->chptr = channel being invited to
hdata->msptr = membership of inviter
hdata->client = inviter
hdata->target = invite target
hdata->approved = zero to allow
hdata->error = NULL, or error message
if non-null, `approved` is the numeric
"invite" - Called just before effecting an invite on the
target's server
hdata = as above
The following are for debugging and take struct hook_io_data for arguments.
These can be used for a variety of purposes, but are aimed at the developer
community.
"iosend"
"iorecv"
"iorecvctrl"
$Id: hooks.txt 3414 2007-04-15 16:54:50Z jilles $

View file

@ -1,6 +1,5 @@
The hostmask/netmask system.
Copyright(C) 2001 by Andrew Miller(A1kmm)<a1kmm@mware.virtualave.net>
$Id: hostmask.txt 6 2005-09-10 01:02:21Z nenolod $
Contents
========
@ -95,7 +94,7 @@ Section 3.3: Initialising and rehashing
To initialise, call init_host_hash(). This only needs to be done once on
startup.
On rehash, to wipe out the old unwanted conf, and free them if there are
no references to them, call clear_out_address_conf().
no references to them, call clear_out_address_conf().
Section 3.4: Finding IP/host confs
----------------------------------

View file

@ -1,19 +1,10 @@
Technical Documentation for ircd-hybrid-7
Technical Documentation for Charybdis
Persistent_Clients.txt - A global UID and Persistent client (with cookies)
proposal
README.TSora - Description of the TS3 protocol
README.openssl - Information for users who have problems with
Hybrid, OpenSSL, and their operating system
cryptlink.txt - Outline of CRYPTLINK protocol
capab.txt - Description of server capabilities
cluster.txt - Technical description of the cluster system
euid.txt - Description of TS6 EUIDs
event.txt - Outline of the event system
fd-management.txt - Outline of the file descriptor management system
file-management.txt - Outline of the disk file management system
hooks.txt - Internal IRC daemon hoks
hostmask.txt - Outline of hostmask handling
linebuf.txt - Outline of the linebuf system (dbuf replacement)
network.txt - Outline of the network traffic subsystem
rfc1459.txt - The IRC RFC
send.txt - Document on all of the send_to functions
whats-new-code.txt - Whats changed in the code
# $Id: index.txt 6 2005-09-10 01:02:21Z nenolod $
ts6-protocol.txt - Description of the TS6 protocol

View file

@ -1,10 +1,7 @@
linebuf - a dbuf replacement for the New World Order(tm)
By Adrian Chadd <adrian@creative.net.au>
$Id: linebuf.txt 6 2005-09-10 01:02:21Z nenolod $
History
-------

View file

@ -1,105 +0,0 @@
Overview of the network subsystem
Adrian Chadd <adrian@creative.net.au>
$Id: network.txt 6 2005-09-10 01:02:21Z nenolod $
This document is an overview of the new and hopefully improved network
subsystem.
The code is based loosely upon the network core found in the Squid web cache
server, with some optimizations for ircd-specific IO patterns.
Filedescriptor IO
-----------------
Filedescriptor IO is initiated using comm_setselect(). comm_setselect()
registers interest in reading from or writing to a file descriptor.
When a filedescriptor is ready for the required IO a callback is called
from the IO loop.
The comm_setselect() usage is:
void
comm_setselect(int fd, fdlist_t list, int type, PF *callback, void *cbdata,
int timeout)
where:
fd filedescriptor
list Which list the FD should be put on
type IO type. Can currently include:
COMM_SELECT_READ - register for read
COMM_SELECT_WRITE - register for write
callback Function to call when the FD is ready
cbdata Data to be passed to above function
timeout Update the timeout value. 0 is "don't update".
A typical use is:
..
/* Register interest in the FD for a read event */
comm_setselect(fd, FDLIST_SERVICE, COMM_SELECT_READ, read_callback, read_data,
0);
..
(FD becomes ready for read in the IO loop)
void
read_callback(int fd, void *data)
{
/* called when the FD becomes ready for read */
retval = read(fd, buf, len);
..
/* Ok, we need to read some more when its ready */
comm_setselect(fd, FDLIST_SERVICE, COMM_SELECT_READ, read_callback, data,
0);
}
Socket timeouts
---------------
A "socket timeout" is a callback registered to be called when a certain
amount of time has elapsed. Think of it as an event, but against a FD.
A good example of socket timeouts is in the comm_connect_tcp() code.
When the connect() begins, comm_settimeout() is called to call
comm_connect_timeout() if the timeout occurs. Once the connect() completes,
comm_settimeout() is called with a timeout of 0 and callback of NULL
to deregister the timeout. If the timeout occurs, comm_connect_timeout()
is called and the connection attempt is aborted.
Functions
---------
comm_open() - a socket() wrapper, enforcing fd limitations and tagging the
file descriptor with a note
comm_accept() - an accept() wrapper, enforcing fd limitations and tagging
the file descriptor with a note
comm_connect_tcp() - attempt an async connect(). Handles DNS lookups if
required, and will call the given callback at completion or error
comm_settimeout() - set a callback to be called after a given time period.
This is good to implement things like PING checks and connect() timeouts.
Notes:
* All socket creation should go through comm_open() / comm_accept().
* All socket closing should go through fd_close(). comm_close() isn't
implemented yet.
* comm_connect_tcp() is your best friend. :-)
* *ALL* network sockets should be non-blocking. If your OS doesn't support
non-blocking sockets, you shouldn't be here.

View file

@ -1,253 +0,0 @@
send.c re-work
PREFIXES
========
Server prefixes are the ":%s" strings at the beginning of messages.
They are used by servers to route the message properly and by servers to
local clients to update their idea of who is whom.
":nick!user@host" is a prefix ":name" where name is either a nick
or name of a server is another valid prefix.
Typical prefix for a local client to a channel:
":Dianora!db@irc.db.net"
for a prefix to a remote server:
":Dianora"
e.g. as seen locally on a channel:
":Dianora!db@irc.db.net PRIVMSG #us-opers :ON TOP OF ...\r\n"
e.g. as seen sent to a remote server:
":Dianora PRIVMSG #us-opers :ON TOP OF ...\r\n"
It has been argued that full prefixes sent locally are a waste of bandwidth
(Isomer from Undernet has argued this). i.e. instead of sending:
":nick!user@host" for a local prefix, one could just send ":nick"..
Unfortunately, this breaks many clients badly. Personally I feel that
until clients are updated to understand that a full prefix isn't always
going to be sent, that this should be held off on.
As much as possible, prefix generation is now moved "upstairs" as
much as possible. i.e. if its known its a local client only, then the
onus of the prefix generation, is the users, not hidden in send.c
This allows somewhat faster code to be written, as the prefix doesn't
have to be regenerated over and over again.
Prefixes aren't sent in all cases, such as a new user using NICK
A prefix is needed when it must be routed.
i.e.
NICK newnick
There is obviously no prefix needed from a locally connected client.
FUNCTIONS
=========
sendto_one() - Should be used for _local_ clients only
it expects the prefix to be pre-built by user.
usage - sendto_one(struct Client *to, char *pattern, ...);
typical use:
sendto_one(acptr,":%s NOTICE %s :I'm tired", me.name,
acptr->name);
Note: This was from a server "me" hence only one
name in prefix.
This would be an example of a client sptr, noticing
acptr IF acptr is known to be a local client:
sendto_one(acptr,":%s!%s@%s NOTICE %s :You there?",
sptr->name,
sptr->username,
sptr->host,
acptr->name);
sendto_one_prefix()
- Sends a message to a remote client, with proper
prefix and target (name or UID).
usage - sendto_one_prefix(struct Client *target_p,
struct Client *source_p,
const char *command,
const char *pattern, ...)
typical use:
sendto_one_prefix(target_p, source_p, "INVITE", ":%s",
chptr->chname);
sendto_one_notice()
- Sends a notice from this server to target. Target may
be a local or remote client.
Prefix and target are chosen based on TS6 capability.
typical use:
sendto_one_notice(source_p, ":You suck. Yes, really.");
sendto_one_numeric()
- Sends a numeric from this server to target. Target may
be a local or remote client.
Prefix and target are chosen based on TS6 capability.
typical use:
sendto_one_numeric(source_p, RPL_STATSDEBUG,
"p :%u staff members", count);
sendto_channel_flags()
- This function sends a var args message to a channel globally,
except to the client specified as "one", the prefix
is built by this function on the fly as it has to
be sent both to local clients on this server and to
remote servers.
For type use one of:
ONLY_SERVERS ALL_MEMBERS ONLY_CHANOPS ONLY_CHANOPSVOICED
If type is not ALL_MEMBERS it's not sent to not-CHW-capable
servers.
Deaf (umode +D) clients are always skipped.
usage - sendto_channel_flags(struct Client *one,
int type,
struct Client *from,
struct Channel *chptr,
const char *pattern, ... );
sendto_channel_butone(cptr, ALL_MEMBERS, sptr, chptr
"PRIVMSG %s :HI!",
chptr->chname);
e.g. if channel message is coming from "cptr"
it must not be sent back to cptr.
sendto_server()
- This function sends specified var args message
to all connected servers except the client "one"
which have all of "caps" capabilities but none
of "nocaps" capabilities.
If "chptr" is not NULL and is a local channel,
nothing is sent.
usage - sendto_server(struct Client *one,
struct Channel *chptr,
unsigned long caps,
unsigned long nocaps,
const char *format, ... );
sendto_common_channels_local()
- This function is used only by m_nick and exit_one_client
its used to propagate nick changes to all channels user
is in, and QUIT messages to all channels user is in.
As it only sends to local clients, prefix generation
is left to the user. It also sends the message to the
user if the user isn't on any channels.
usage - sendto_common_channels_local(struct Client *user,
const char *pattern,
...);
sendto_channel_local()
- This function is used to send only locally, never
to remote servers. This is useful when removing
local chanops, or adding a local chanop. MODE/SJOIN
sent to remote server allows that server to propagate
mode changes to its clients locally.
The message is also sent to deaf (umode +D) clients.
usage - sendto_channel_local(int type,
struct Channel *chptr,
const char *pattern, ... );
prefix must be pre-built. type is a flag
denoting ONE of
ALL_MEMBERS - all members locally are sent to
ONLY_CHANOPS_VOICED - only chanops and voiced see this
ONLY_CHANOPS - only chanops see this
sendto_match_butone()
- only used for the old style oper masking
i.e. /msg #hostmask which in hyb7 is /msg $#hostmask
or /msg $servermask in hyb7 /msg $$servermask
usage - sendto_match_butone(struct Client *one,
struct Client *source_p,
char *mask,
int what,
const char *pattern, ... );
one is the client not to send to
mask is the actual mask
what is either MATCH_HOST or MATCH_SERVER
sendto_match_servs()
- Allows sending a message to servers whose names match
the given mask. A message is also sent to non-matching
servers which have matching servers behind them.
Used for ENCAP, remote kline, etc.
No message is sent to source_p->from.
usage - sendto_match_servs(struct Client *source_p,
const char *mask,
int cap, int nocap,
const char *pattern, ...);
sendto_anywhere()
- Allows the sending of a message to any client on the net
without knowing whether its local or remote. The penalty
is the calculation of a run-time prefix.
It is less efficient then sendto_one()
usage - sendto_anywhere(struct Client *to,
struct Client *from,
const char *command,
const char *pattern, ...);
e.g.
sendto_anywhere(target_p, source_p,
"PRIVMSG", ":Hi, Where ever you are");
sendto_realops_flags()
- combines old sendto_realops and sendto_realops_flags
sends specified message to opers locally only
depending on umodes. UMODE_ALL is UMODE_SERVNOTICE.
the message is sent as a server notice, prefixed with
"*** Notice -- ".
usage - sendto_realops_flags(int flags,
const char *pattern, ... );
e.g.
sendto_realops_flags(UMODE_ALL,
"Don't eat the yellow snow");
sendto_wallops_flags()
- sends specified message to opers/users locally,
depending on umodes. used for messages that need
to be in wallops form
- some policy decisions about who gets what live in here
usage - sendto_wallops_flags(int flags,
struct Client *, const char *patterm ...);
e.g.
sendto_wallops_flags(UMODE_LOCOPS,
sptr, "Message");
-- Diane Bruce
Updated Jan 2006 by jilles with ratbox and late hybrid7 changes
$Id: send.txt 587 2006-01-27 19:45:11Z jilles $

View file

@ -1,5 +1,6 @@
TS6 protocol description
Written by Jilles Tjoelker
Edits by Elizabeth Myers to add TS rules described by Lee Harvey.
General format: much like rfc1459
Maximum parameters for a command: 15 (this does not include the prefix
@ -18,6 +19,7 @@ nicknames and server names are accepted, possibly with wildcards; from servers,
UIDs/SIDs (sending names or even wildcards is deprecated). This is done with
the function hunt_server(). Any rate limiting should be done locally.
duration: a parameter type used for ban durations. It is a duration in seconds.
A value of 0 means a permanent ban.
@ -112,6 +114,75 @@ type D
+g (allow any member to /invite)
+z (send messages blocked by +m to chanops)
Nick TS rules:
A server receiving a command that requires nick TS rules must check for a
collision between an existing user, and the nick in the received message.
(the "new user"). The collisions must obey the rules specified in Nick TS
collisions.
If the TS received is lower than the TS of the existing user the server will
collide the existing user if the clients user@host are different, if the
clients user@hosts are identical it will collide the new user.
If the TS received is equal to the TS of the existing user both clients are
collided.
If the TS received is higher than the TS of the existing user, the server
will collide the existing user if the user@hosts are identical, if the
clients user@host are different it will collide the new user and drop the
message.
Nick TS collisions:
If both users are to be collided, we must issue a KILL for the existing
user to all servers. If the new user has a UID then we must also issue a
KILL for that UID back to the server sending us data causing the collision.
If only the existing user is being collided, we must issue a KILL for the
existing user to all servers except the server sending us data. If the
existing user has a UID and the server sending us data supports TS6 then
we must also issue a KILL for the existing users UID to the server sending
us data.
If only the new user is being collided, we must issue a KILL for the new user
back to the server sending us data if the new user has a UID.
Channel TS rules:
A server receiving a command that requires normal channel TS rules must
apply the following rules to the command.
If the TS received is lower than our TS of the channel a TS6 server must
remove status modes (+ov etc) and channel modes (+nt etc). If the
originating server is TS6 capable (ie, it has a SID), the server must
also remove any ban modes (+b etc). The new modes and statuses are then
accepted.
If any bans are removed, the server must send to non-TS6, directly connected
servers mode changes removing the bans after the command is propagated.
This prevents desync with banlists, and has to be sent after as clients are
still able to send mode changes before the triggering command arrives.
If the TS received is equal to our TS of the channel the server should keep
its current modes and accept the received modes and statuses.
If the TS received is higher than our TS of the channel the server should keep
its current modes and ignore the received modes and statuses. Any statuses
given in the received message will be removed. A server must mark clients
losing their op (+o) status who do not have a UID as 'deopped'. A server must
ignore any "MODE" commands from a user marked as 'deopped'.
Simple channel TS rules:
A server receiving a command that requires simple channel TS rules must
apply the following rules to the command.
If the TS received is lower, or equal to our TS of the channel the modes are
accepted. If the TS received is higher than our TS of the channel the modes
are ignored and dropped.
Simple channel TS rules do not affect current modes in the channel except
for the modes we are accepting.
<numeric>
source: server
parameters: target, any...
@ -248,6 +319,28 @@ Sets a D:line (IP ban checked directly after accepting connection).
The mask must be an IP address or CIDR mask.
EBMASK
source: server
propagation: broadcast
parameters: channelTS, channel, type, space separated "masks ts hostmask" chunks
If the channelTS in the message is greater (newer) than the current TS of
the channel, drop the message and do not propagate it.
Type is the mode letter of a ban-like mode. In efnet TS6 this is 'b', 'e' or
'I'. In charybdis TS6 additionally 'q' is possible.
Add all the masks and their set at/by to the given list of the channel.
All ban-like modes must be bursted using this command, not using MODE or TMODE.
ECHO
source: user
parameters: "P"/"N", target, text
As PRIVMSG, but delivers an echo-message echo to the target; they will see
a PRIVMSG or NOTICE from themselves to the source.
ENCAP
source: any
parameters: target server mask, subcommand, opt. parameters...
@ -599,6 +692,13 @@ and most error messages are suppressed.
Servers may not send '$$', '$#' and opers@server notices. Older servers may
not allow servers to send to specific statuses on a channel.
OPER
source: user
parameters: opername, privset
Sets the source user's oper name and privset. Sent after the +o mode change, or
during burst, to inform other servers of an oper's privileges.
OPERSPY
encap only
encap target: *
@ -1137,8 +1237,6 @@ CAP
CHALLENGE
CHANTRACE
CLOSE
CNOTICE
CPRIVMSG
DIE
GET
HELP
@ -1153,7 +1251,6 @@ MODRESTART
MODUNLOAD
MONITOR
NAMES
OPER
POST
PUT
RESTART

View file

@ -1,299 +0,0 @@
$Id: ts6.txt 3211 2007-02-20 00:34:28Z jilles $
TS6 Proposal (v8)
Written by Lee H <lee@leeh.co.uk>
Ideas borrowed heavily from ircnet (Beeth, jv, Q)
- Changes between v7 and v8 -
-----------------------------
In the v7 specification, the JOIN command included the channel modes of a
channel, and acted on them following TS rules. In the v8 specification,
JOIN will never send modes.
Desyncs can occur both when they are sent and when they are not. If they
are sent, then you can have a situation where a user on one side of the
network issues "MODE #channel -l", and a user on another side of the network
issues "JOIN #channel" whilst the +l still exists. As the JOIN string sent
server<->server includes the full modes at the time of the user joining,
this will propagate the +l, but there is a -l crossing in the other
direction. Desync will occur beyond where they intersect.
If the modes are not sent, then a lower TS JOIN command, or a JOIN command
that creates a channel will cause a desync.
It is judged that the desync with sending the modes is worse than the desync
by not sending them, as such the v8 specification dictates modes are not
sent with a JOIN command server<->server.
The v8 specification also clarifies that servers may issue TMODE.
- Introduction -
----------------
This document aims to fix some of the flaws that are still present in the
current TS system.
Whilst only one person may use a nickname at any one time, they are not
a reliable method of directing commands between servers. Clients can change
their nicknames, which can create desyncs. A reliable method of directing
messages between servers is required so that a message will always reach the
intended destination, even if the client changes nicks in between.
UID solves this problem by ensuring that a client has a unique ID for the
duration of his connection.
This document also aims to solve the lack of TS rules to channel 'bans' on
a netburst. Bans from both sides of a TS war (losing/winning) are kept.
Bursting the bans with a TS solves this problem.
There is also a race condition in the current TS system, where a user can
issue a mode during a netburst and the mode will be set on the server
we are bursting to.
- Definitions -
---------------
Throughout this document, the following terms are used:
SID - A servers unique ID. This is three characters long and must be in
the form [0-9][A-Z0-9][A-Z0-9]
ID - A clients unique ID. This is six characters long and must be in
the form [A-Z][A-Z0-9][A-Z0-9][A-Z0-9][A-Z0-9][A-Z0-9]. The
numbers [0-9] at the beginning of an ID are legal characters, but
reserved for future use.
UID - An ID concateneted to a SID. This forms the clients UID.
TS6 - The TS version 6.
- Support -
-----------
Support for this document is given by the TS version 6.
Wherever a destination parameter or source parameter is used, it must use
the SID or UID if the server/client has one. A TS6 capable server must
translate any SIDs/UIDs back into the server/clients name when communicating
with a server that does not support TS6.
A TS6 server must also support the QS (quitstorm) system, and the encap
specification found here:
http://www.leeh.co.uk/ircd/encap.txt
The TS6 protocol does not supports masked entities.
- Nick TS rules -
-----------------
A server receiving a command that requires nick TS rules must check for a
collision between an existing user, and the nick in the received message.
(the "new user"). The collisions must obey the rules specified in Nick TS
collisions.
If the TS received is lower than the TS of the existing user the server will
collide the existing user if the clients user@host are different, if the
clients user@hosts are identical it will collide the new user.
If the TS received is equal to the TS of the existing user both clients are
collided.
If the TS received is higher than the TS of the existing user, the server
will collide the existing user if the user@hosts are identical, if the
clients user@host are different it will collide the new user and drop the
message.
- Nick TS collisions -
----------------------
If both users are to be collided, we must issue a KILL for the existing
user to all servers. If the new user has a UID then we must also issue a
KILL for that UID back to the server sending us data causing the collision.
If only the existing user is being collided, we must issue a KILL for the
existing user to all servers except the server sending us data. If the
existing user has a UID and the server sending us data supports TS6 then
we must also issue a KILL for the existing users UID to the server sending
us data.
If only the new user is being collided, we must issue a KILL for the new user
back to the server sending us data if the new user has a UID.
- Channel TS rules -
--------------------
A server receiving a command that requires normal channel TS rules must
apply the following rules to the command.
If the TS received is lower than our TS of the channel a TS6 server must
remove status modes (+ov etc) and channel modes (+nt etc). If the
originating server is TS6 capable (ie, it has a SID), the server must
also remove any ban modes (+b etc). The new modes and statuses are then
accepted.
If any bans are removed, the server must send to non-TS6, directly connected
servers mode changes removing the bans after the command is propagated.
This prevents desync with banlists, and has to be sent after as clients are
still able to send mode changes before the triggering command arrives.
If the TS received is equal to our TS of the channel the server should keep
its current modes and accept the received modes and statuses.
If the TS received is higher than our TS of the channel the server should keep
its current modes and ignore the received modes and statuses. Any statuses
given in the received message will be removed. A server must mark clients
losing their op (+o) status who do not have a UID as 'deopped'. A server must
ignore any "MODE" commands from a user marked as 'deopped'.
- Simple channel TS rules -
---------------------------
A server receiving a command that requires simple channel TS rules must
apply the following rules to the command.
If the TS received is lower, or equal to our TS of the channel the modes are
accepted. If the TS received is higher than our TS of the channel the modes
are ignored and dropped.
Simple channel TS rules do not affect current modes in the channel except
for the modes we are accepting.
- The following commands are defined here as the TS6 protocol -
---------------------------------------------------------------
- PASS -
PASS <PASSWORD> TS <TS_CURRENT> :<SID>
This command is used for password verification with the server we are
connecting to.
Due to the burst being sent on verification of the "SERVER" command, and
"SVINFO" being sent after "SERVER", we need to be aware of the TS version
earlier to decide whether to send a TS6 burst or not.
The <PASSWORD> field is the password we have stored for this server,
<TS_CURRENT> is our current TS version. If this field is not present then
the server does not support TS6. <SID> is the SID of the server.
- UID -
:<SID> UID <NICK> <HOPS> <TS> +<UMODE> <USERNAME> <HOSTNAME> <IP> <UID> :<GECOS>
This command is used for introducing clients to the network.
The <SID> field is the SID of the server the client is connected to.
The <NICK> field is the nick of the client being introduced. The <HOPS>
field is the amount of server hops between the server being burst to and
the server the client is on. The <TS> field is the TS of the client, either
the time they connected or the time they last changed nick. The <UMODE>
field contains the clients usermodes that need to be transmitted between
servers. The <USERNAME> field contains the clients username/ident. The
<HOSTNAME> field contains the clients host.
The <IP> field contains the clients IP. If the IP is not to be sent
(due to a spoof etc), the field must be sent as "0". The <UID> field is the
clients UID. The <GECOS> field is the clients gecos.
A server receiving a UID command must apply nick TS rules to the nick.
- SID -
:<SID> SID <SERVERNAME> <HOPS> <SID> :<GECOS>
This command is used for introducing servers to the network.
The first <SID> field is the SID of the new servers uplink. The
<SERVERNAME> field is the new servers name. The <HOPS> field is the hops
between the server being introduced nd the server being burst to.
The second <SID> field is the SID of the new server. The <GECOS> field i
is the new servers gecos.
Upon receiving the SID command servers must check for a SID collision.
Two servers must not be allowed to link to the network with the same SID.
If a server detects a SID collision it must drop the link to the directly
connected server through which the command was received.
Client and servers which do not have a UID/SID must be introduced by old
methods.
- SJOIN -
:<SID> SJOIN <TS> <CHANNAME> +<CHANMODES> :<UIDS>
This command is used for introducing users to channels.
The <SID> field is the SID of the server introducing users to the channel.
The <TS> field is the channels current TS, <CHANNAME> is the channels
current name, <CHANMODES> are the channels current modes. <UIDS> is a
space delimited list of clients UIDs to join to the channel. Each clients
UID is prefixed with their status on the channel, ie "@UID" for an opped
user. Multiple prefixes are allowed, "peons" (clients without a status) are
not prefixed.
A server receiving an SJOIN must apply normal channel TS rules to the SJOIN.
A TS6 server must not use the SJOIN command outside of a netburst
to introduce a single user to an existing channel. It must instead
use the "JOIN" command defined in this specification. A TS6 server must
still use SJOIN for creating channels.
- JOIN -
:<UID> JOIN <TS> <CHANNAME> +
This command is used for introducing one user unopped to an existing channel.
The <UID> field is the UID of the client joining the channel. The
<TS> field is the channels current TS, <CHANNAME> is the channels
current name.
A server receiving a JOIN must apply normal channel TS rules to the JOIN.
No channel modes are sent with the JOIN command. In previous versions of
this specification, the "+" parameter contained the channels current modes.
A server following this version of the specification must not interpret this
argument and must not propagate any value other than "+" for this parameter.
It should be noted that whilst JOIN would not normally create a
channel or lower the timestamp, during specific conditions it can. This
can create a desync that this specification does not rectify.
- BMASK -
:<SID> BMASK <TS> <CHANNAME> <TYPE> :<MASKS>
This command is used for bursting channel bans to a network.
The <SID> field is the SID of the server bursting the bans. The
<TS> field is the channels current TS, <CHANNAME> is the channels
name. <TYPE> is a single character identifying the mode type (ie,
for a ban 'b'). <MASKS> is a space delimited list of masks of the
given mode,limited only in length to the size of the buffer as defined
by RFC1459.
A server receiving a BMASK must apply simple channel TS rules to the BMASK.
A TS6 server must translate BMASKs into raw modes for non-TS6
capable servers. This command must be used only after SJOIN has
been sent for the given channel.
It should be noted however, that a BMASK with a lower TS should
not be possible without a desync, due to it being sent after
SJOIN.
- TMODE -
:<SID|UID> TMODE <TS> <CHANNAME> <MODESTRING>
This command is used for clients issuing modes on a channel.
<SID|UID> is either the UID of the client setting the mode, or the SID of
the server setting the mode. <TS> is the current TS of the channel,
<CHANNAME> is the channels name. <MODESTRING> is the raw mode the client is
setting.
A server receiving a TMODE must apply simple channel TS rules to the TMODE.
A TS6 server must translate MODEs issued by a local client, or received from
a server into TMODE to send to other TS6 capable servers.

View file

@ -1 +0,0 @@
-i8 -bli0 -cs -ut -nsai -nsaw -nsaf -npcs -nprs -l100

77
extensions/Makefile.am Normal file
View file

@ -0,0 +1,77 @@
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/librb/include $(LTDLINCL)
AM_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined -shared
AM_LDFLAGS += -export-symbols-regex _mheader
LIBS += $(top_srcdir)/ircd/libircd.la
extensiondir=@moduledir@/extensions
extension_LTLIBRARIES = \
chantype_dummy.la \
chm_adminonly.la \
chm_operonly.la \
chm_insecure.la \
chm_nonotice.la \
chm_operpeace.la \
chm_regmsg.la \
chm_sslonly.la \
createauthonly.la \
createoperonly.la \
extb_account.la \
extb_canjoin.la \
extb_channel.la \
extb_guest.la \
extb_hostmask.la \
extb_oper.la \
extb_server.la \
extb_ssl.la \
extb_realname.la \
extb_usermode.la \
extb_extgecos.la \
extb_combi.la \
force_user_invis.la \
helpops.la \
hurt.la \
invite_notify.la \
ip_cloaking.la \
ip_cloaking_old.la \
ip_cloaking_3.0.la \
ip_cloaking_4.0.la \
override.la \
override_kick_immunity.la \
restrict-unauthenticated.la \
sno_channelcreate.la \
sno_farconnect.la \
sno_globalnickchange.la \
sno_globaloper.la \
umode_noctcp.la \
m_adminwall.la \
m_echotags.la \
m_extendchans.la \
m_findforwards.la \
m_identify.la \
m_locops.la \
m_mkpasswd.la \
m_ojoin.la \
m_okick.la \
m_omode.la \
m_opme.la \
m_sendbans.la \
m_shedding.la \
m_webirc.la \
m_remove.la \
hide_uncommon_channels.la \
no_kill_services.la \
no_locops.la \
no_oper_invis.la \
sasl_usercloak.la \
drain.la \
identify_msg.la \
cap_realhost.la \
invex_regonly.la \
umode_hide_idle_time.la \
cap_oper.la \
example_module.la
if HAVE_HYPERSCAN
extension_LTLIBRARIES += filter.la
endif

View file

@ -1,131 +0,0 @@
#
# Makefile.in for ircd/contrib
#
# $Id: Makefile.in 3522 2007-07-06 07:48:28Z nenolod $
#
CC = @CC@
RM = @RM@
SED = @SED@
LEX = @LEX@
LEXLIB = @LEXLIB@
CFLAGS = @IRC_CFLAGS@ -DIRCD_PREFIX=\"@prefix@\"
PICFLAGS = @PICFLAGS@
MKDEP = @MKDEP@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SUID = @INSTALL_PROGRAM@ -o root -m 4755
SHELL = /bin/sh
prefix = @prefix@
exec_prefix = @exec_prefix@
libdir = @libdir@
pkglibdir = @pkglibdir@
moduledir = @moduledir@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
AUTOMODULEDIR = $(moduledir)/extensions
SSL_LIBS = @SSL_LIBS@
SSL_INCLUDES = @SSL_INCLUDES@
IRCDLIBS = @LIBS@ $(SSL_LIBS)
INCLUDES = -I. -I../include -I../libratbox/include $(SSL_INCLUDES)
CPPFLAGS = ${INCLUDES} @CPPFLAGS@
SRCS = \
chm_adminonly.c \
chm_operonly.c \
chm_operonly_compat.c \
chm_nonotice.c \
chm_quietunreg_compat.c \
chm_sslonly.c \
chm_sslonly_compat.c \
createauthonly.c \
createoperonly.c \
extb_account.c \
extb_canjoin.c \
extb_channel.c \
extb_hostmask.c \
extb_oper.c \
extb_server.c \
extb_ssl.c \
extb_realname.c \
extb_usermode.c \
extb_extgecos.c \
extb_combi.c \
force_user_invis.c \
hurt.c \
ip_cloaking.c \
ip_cloaking_old.c \
ip_cloaking_3.0.c \
ip_cloaking_4.0.c \
override.c \
restrict-unauthenticated.c \
sno_farconnect.c \
sno_globalkline.c \
sno_globaloper.c \
sno_whois.c \
m_42.c \
m_adminwall.c \
m_findforwards.c \
m_identify.c \
m_mkpasswd.c \
m_ojoin.c \
m_okick.c \
m_omode.c \
m_opme.c \
m_sendbans.c \
m_webirc.c \
m_remove.c \
m_roleplay.c \
hide_uncommon_channels.c \
no_kill_services.c \
no_locops.c \
no_oper_invis.c \
spy_admin_notice.c \
spy_info_notice.c \
spy_links_notice.c \
spy_motd_notice.c \
spy_stats_notice.c \
spy_stats_p_notice.c \
spy_trace_notice.c \
example_module.c
OBJS = ${SRCS:.c=.so}
default: build
build: all
all: $(OBJS)
install: all
-@if test ! -d $(DESTDIR)$(AUTOMODULEDIR); then \
mkdir $(DESTDIR)$(AUTOMODULEDIR); \
fi
@echo "Installing modules into $(DESTDIR)$(AUTOMODULEDIR) .."
@for file in $(OBJS); do \
$(INSTALL_DATA) $$file $(DESTDIR)$(AUTOMODULEDIR); \
done
.SUFFIXES: .so
.c.so:
${CC} ${PICFLAGS} ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} $< -o $@
.PHONY: depend clean distclean
depend:
@${MKDEP} ${CPPFLAGS} ${SRCS} > .depend
@sed s/\\\.o/\\\.so/ < .depend > .depend.tmp
@sed -e '/^# DO NOT DELETE THIS LINE/,$$d' <Makefile >Makefile.depend
@echo '# DO NOT DELETE THIS LINE!!!' >>Makefile.depend
@echo '# make depend needs it.' >>Makefile.depend
@cat .depend.tmp >>Makefile.depend
@mv Makefile.depend Makefile
@rm -f .depend.tmp .depend
clean:
${RM} -f *.so *~
distclean: clean
${RM} -f Makefile

View file

@ -1,8 +1,6 @@
$Id: README 1622 2006-06-04 03:01:05Z beu $
This directory contains extensions (modules) to charybdis ircd that
This directory contains extensions (modules) to solanum ircd that
have been contributed by other people, or written by our development
team. Unsupported extensions live under unsupported/.
team.
Modules
@ -13,9 +11,6 @@ createauthonly.c - Only allow authenticated (identified) users to create
ip_cloaking.c - Cloak (spoof) the host for users that have umode +h.
m_42.c - The Answer to Life, the Universe, and Everything.
Syntax: 42
m_adminwall.c - Sends a message to all admins network-wide (umode +a)
Syntax: ADMINWALL :<message>
@ -84,6 +79,7 @@ extb_account.so - Account bans (+b $a[:mask])
extb_canjoin.so - Banned from another channel (+b $j:mask)
extb_channel.so - Other-channel bans (+b $c:mask)
extb_extgecos.so - Extended ban (+b $x:mask)
extb_guest.so - Unidentified bans (+b $g:mask)
extb_oper.so - Oper bans (+b $o)
extb_realname.so - Realname (gecos) bans (+b $r:mask)
extb_server.so - Server bans (+b $s:mask)

147
extensions/cap_oper.c Normal file
View file

@ -0,0 +1,147 @@
/*
* Copyright (C) 2021 David Schultz <me@zpld.me>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <stdinc.h>
#include <modules.h>
#include <capability.h>
#include <s_conf.h>
#include <s_serv.h>
#include <s_newconf.h>
#include <client.h>
#include <msgbuf.h>
static char cap_oper_desc[] = "Provides the solanum.chat/oper capability";
static bool cap_oper_oper_visible(struct Client *);
static void cap_oper_outbound_msgbuf(void *);
static void cap_oper_umode_changed(void *);
static void cap_oper_cap_change(void *);
static unsigned CLICAP_OPER;
static unsigned CLICAP_OPER_AUSPEX;
static unsigned CLICAP_OPER_JUSTOPER;
static unsigned CLICAP_OPER_NORMAL;
static struct ClientCapability capdata_oper_oper = {
.visible = cap_oper_oper_visible,
};
mapi_cap_list_av2 cap_oper_caps[] = {
{ MAPI_CAP_CLIENT, "solanum.chat/oper", NULL, &CLICAP_OPER },
{ MAPI_CAP_CLIENT, "?oper_auspex", &capdata_oper_oper, &CLICAP_OPER_AUSPEX },
{ MAPI_CAP_CLIENT, "?oper_justoper", &capdata_oper_oper, &CLICAP_OPER_JUSTOPER },
{ MAPI_CAP_CLIENT, "?oper_normal", &capdata_oper_oper, &CLICAP_OPER_NORMAL },
{ 0, NULL, NULL, NULL },
};
mapi_hfn_list_av1 cap_oper_hfnlist[] = {
{ "outbound_msgbuf", cap_oper_outbound_msgbuf, HOOK_NORMAL },
{ "umode_changed", cap_oper_umode_changed, HOOK_MONITOR },
{ "cap_change", cap_oper_cap_change, HOOK_MONITOR },
{ NULL, NULL, 0 },
};
static bool
cap_oper_oper_visible(struct Client *client)
{
return false;
}
static void
cap_oper_outbound_msgbuf(void *data_)
{
hook_data *data = data_;
struct MsgBuf *msgbuf = data->arg1;
if (data->client == NULL || !IsPerson(data->client))
return;
if (IsOper(data->client))
{
/* send all oper data to auspex */
msgbuf_append_tag(msgbuf, "solanum.chat/oper", data->client->user->opername, CLICAP_OPER_AUSPEX);
if (HasPrivilege(data->client, "oper:hidden") || ConfigFileEntry.hide_opers)
/* these people aren't allowed to see hidden opers */
return;
msgbuf_append_tag(msgbuf, "solanum.chat/oper", data->client->user->opername, CLICAP_OPER_JUSTOPER);
msgbuf_append_tag(msgbuf, "solanum.chat/oper", NULL, CLICAP_OPER_NORMAL);
}
}
static inline void
update_clicap_oper(struct Client *client)
{
/* clear out old caps */
client->localClient->caps &= ~CLICAP_OPER_AUSPEX;
client->localClient->caps &= ~CLICAP_OPER_JUSTOPER;
client->localClient->caps &= ~CLICAP_OPER_NORMAL;
if (client->localClient->caps & CLICAP_OPER && HasPrivilege(client, "auspex:oper"))
{
/* if the client is an oper with auspex, let them see everything */
client->localClient->caps |= CLICAP_OPER_AUSPEX;
}
else if (client->localClient->caps & CLICAP_OPER && IsOper(client))
{
/* if the client is an oper, let them see other opers */
client->localClient->caps |= CLICAP_OPER_JUSTOPER;
}
else if (client->localClient->caps & CLICAP_OPER)
{
/* if the client is a normal user, let them see opers
provided that server wide oper hiding is not enabled */
client->localClient->caps |= CLICAP_OPER_NORMAL;
}
}
static void
cap_oper_umode_changed(void *data_)
{
hook_data_umode_changed *data = data_;
if (!MyClient(data->client))
return;
update_clicap_oper(data->client);
}
static void
cap_oper_cap_change(void *data_)
{
hook_data_cap_change *data = data_;
update_clicap_oper(data->client);
}
static int
modinit(void)
{
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, lclient_list.head)
{
struct Client *client = ptr->data;
update_clicap_oper(client);
}
return 0;
}
DECLARE_MODULE_AV2(cap_oper, modinit, NULL, NULL, NULL, cap_oper_hfnlist, cap_oper_caps, NULL, cap_oper_desc);

124
extensions/cap_realhost.c Normal file
View file

@ -0,0 +1,124 @@
/*
* Copyright (C) 2020 Ed Kellett
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <stdinc.h>
#include <modules.h>
#include <capability.h>
#include <s_serv.h>
#include <s_newconf.h>
#include <client.h>
#include <msgbuf.h>
static char cap_realhost_desc[] = "Provides the solanum.chat/realhost oper-only capability";
static bool cap_oper_realhost_visible(struct Client *);
static void cap_realhost_outbound_msgbuf(void *);
static void cap_realhost_umode_changed(void *);
static void cap_realhost_cap_change(void *);
static unsigned CLICAP_REALHOST;
static unsigned CLICAP_OPER_REALHOST;
static struct ClientCapability capdata_oper_realhost = {
.visible = cap_oper_realhost_visible,
};
mapi_cap_list_av2 cap_realhost_caps[] = {
{ MAPI_CAP_CLIENT, "solanum.chat/realhost", NULL, &CLICAP_REALHOST },
{ MAPI_CAP_CLIENT, "?oper_realhost", &capdata_oper_realhost, &CLICAP_OPER_REALHOST },
{ 0, NULL, NULL, NULL },
};
mapi_hfn_list_av1 cap_realhost_hfnlist[] = {
{ "outbound_msgbuf", cap_realhost_outbound_msgbuf, HOOK_NORMAL },
{ "umode_changed", cap_realhost_umode_changed, HOOK_MONITOR },
{ "cap_change", cap_realhost_cap_change, HOOK_MONITOR },
{ NULL, NULL, 0 },
};
static bool
cap_oper_realhost_visible(struct Client *client)
{
return false;
}
static void
cap_realhost_outbound_msgbuf(void *data_)
{
hook_data *data = data_;
struct MsgBuf *msgbuf = data->arg1;
if (data->client == NULL || !IsPerson(data->client))
return;
if (!IsIPSpoof(data->client) && !EmptyString(data->client->sockhost) && strcmp(data->client->sockhost, "0"))
{
msgbuf_append_tag(msgbuf, "solanum.chat/ip", data->client->sockhost,
IsDynSpoof(data->client) ? CLICAP_OPER_REALHOST : CLICAP_REALHOST);
}
if (!EmptyString(data->client->orighost))
msgbuf_append_tag(msgbuf, "solanum.chat/realhost", data->client->orighost, CLICAP_OPER_REALHOST);
}
static inline void
update_clicap_oper_realhost(struct Client *client)
{
client->localClient->caps &= ~CLICAP_OPER_REALHOST;
if (client->localClient->caps & CLICAP_REALHOST && HasPrivilege(client, "auspex:hostname"))
{
client->localClient->caps |= CLICAP_OPER_REALHOST;
}
}
static void
cap_realhost_umode_changed(void *data_)
{
hook_data_umode_changed *data = data_;
if (!MyClient(data->client))
return;
update_clicap_oper_realhost(data->client);
}
static void
cap_realhost_cap_change(void *data_)
{
hook_data_cap_change *data = data_;
update_clicap_oper_realhost(data->client);
}
static int
modinit(void)
{
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, lclient_list.head)
{
struct Client *client = ptr->data;
update_clicap_oper_realhost(client);
}
return 0;
}
DECLARE_MODULE_AV2(cap_realhost, modinit, NULL, NULL, NULL, cap_realhost_hfnlist, cap_realhost_caps, NULL, cap_realhost_desc);

View file

@ -0,0 +1,30 @@
/* dummy channel type (>): just a global channel type */
#include "stdinc.h"
#include "modules.h"
#include "client.h"
#include "ircd.h"
#include "supported.h"
static const char chantype_desc[] = "Secondary global channel type (>)";
static int _modinit(void);
static void _moddeinit(void);
DECLARE_MODULE_AV2(chantype_dummy, _modinit, _moddeinit, NULL, NULL, NULL, NULL, NULL, chantype_desc);
static int
_modinit(void)
{
CharAttrs['>'] |= CHANPFX_C;
chantypes_update();
return 0;
}
static void
_moddeinit(void)
{
CharAttrs['>'] &= ~CHANPFX_C;
chantypes_update();
}

View file

@ -10,10 +10,13 @@
#include "numeric.h"
#include "chmode.h"
static void h_can_join(hook_data_channel *);
static const char chm_adminonly_desc[] =
"Enables channel mode +A that blocks non-admins from joining a channel";
static void h_can_join(void *);
mapi_hfn_list_av1 adminonly_hfnlist[] = {
{ "can_join", (hookfn) h_can_join },
{ "can_join", h_can_join },
{ NULL, NULL }
};
@ -35,11 +38,12 @@ _moddeinit(void)
cflag_orphan('A');
}
DECLARE_MODULE_AV1(chm_adminonly, _modinit, _moddeinit, NULL, NULL, adminonly_hfnlist, "$Revision$");
DECLARE_MODULE_AV2(chm_adminonly, _modinit, _moddeinit, NULL, NULL, adminonly_hfnlist, NULL, NULL, chm_adminonly_desc);
static void
h_can_join(hook_data_channel *data)
h_can_join(void *data_)
{
hook_data_channel *data = data_;
struct Client *source_p = data->client;
struct Channel *chptr = data->chptr;

58
extensions/chm_insecure.c Normal file
View file

@ -0,0 +1,58 @@
#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 const char chm_insecure_desc[] =
"Adds channel mode +U that allows non-SSL users to join a channel, "
"disallowing them by default";
static void h_can_join(void *);
mapi_hfn_list_av1 sslonly_hfnlist[] = {
{ "can_join", h_can_join },
{ NULL, NULL }
};
static unsigned int mymode;
static int
_modinit(void)
{
mymode = cflag_add('U', chm_simple);
if (mymode == 0)
return -1;
return 0;
}
static void
_moddeinit(void)
{
cflag_orphan('U');
}
DECLARE_MODULE_AV2(chm_insecure, _modinit, _moddeinit, NULL, NULL, sslonly_hfnlist, NULL, NULL, chm_insecure_desc);
static void
h_can_join(void *data_)
{
hook_data_channel *data = data_;
struct Client *source_p = data->client;
struct Channel *chptr = data->chptr;
if(!(chptr->mode.mode & mymode) && !IsSecureClient(source_p)) {
/* XXX This is equal to ERR_THROTTLE */
sendto_one_numeric(source_p, 480, "%s :Cannot join channel (-U) - SSL/TLS required", chptr->chname);
data->approved = ERR_CUSTOM;
}
}

Some files were not shown because too many files have changed in this diff Show more