Compare commits

...

315 commits

Author SHA1 Message Date
c7da812303
Merge branch 'solanum' into merging-solanum-into-hackint 2024-06-06 00:33:19 +00:00
Martin Weinelt
6b8d4cb307 default.nix: drop rb_setenv for BANDB_PATH
Fixes: "bandb - bandb failure: Unable to open sqlite database: unable to open database file"
2021-06-01 20:12:30 +02:00
Martin Weinelt
66225eb7ef default.nix: enable ziplinks 2021-06-01 20:12:24 +02:00
Martin Weinelt
f5f2190b40 add default.nix 2020-07-28 23:13:35 +02:00
ManiacTwister
529e8705c2 Merge remote-tracking branch 'upstream/release/3.5' into hackint/3.5 2020-03-01 18:15:35 +01:00
Aaron Jones
fca7f870c8
extensions/extb_ssl.c: make certfp parameter case-insensitive
I had the idea that maybe these should be case-sensitive because some
encodings (like Base-64) are. But it turns out it's better to
prioritise not breaking existing configurations / channel mode lists,
and just revisit this in future maybe.

[ci skip]
2020-01-28 20:47:04 +00:00
Aaron Jones
5572f43834
extensions/extb_ssl.c: clean up this logic
This should also be using strcmp(3), not irccmp().
No practical consequence (yet), it just makes more sense.
2020-01-28 20:35:42 +00:00
Aaron Jones
905508885b
Support ECDH X25519 for TLSv1.3 (OpenSSL 1.1.1) 2019-09-08 13:57:53 +00:00
Aaron Jones
88fbca25d0
Charybdis 3.5.7 2019-08-31 19:11:05 +00:00
Simon Arlott
a74ee5d2c7
Revert "ircd: Fix umode orphan scheme."
This reverts commit c1fc044c35.
2019-08-31 15:06:30 +01:00
Simon Arlott
24b8fd0063
m_sasl: Don't process authentication messages if SASL has been aborted 2019-06-08 22:07:36 +01:00
Aaron Jones
a589946b42
Revert "m_sasl: Don't process authentication messages if SASL has been aborted"
SASL does not work with this commit in the tree.

This reverts commit f44a0d7ea2.
2019-06-08 20:59:36 +00:00
Simon Arlott
f44a0d7ea2
m_sasl: Don't process authentication messages if SASL has been aborted 2019-02-23 13:19:13 +00:00
Aaron Jones
358a73c8d5
Merge branch fakelist into release/3.5 2018-11-26 21:24:34 +00:00
Aaron Jones
3c36726f83
src/newconf.c: fakechannel: guard against repeated config options
Also correct another minor memory leak
2018-11-26 21:23:51 +00:00
ManiacTwister
9a10251fd5 Fixed syntax error 2018-11-26 22:10:11 +01:00
ManiacTwister
d7aec4702a Initialize fakechan topic to NULL, allocate an empty string if not overridden 2018-11-26 22:03:42 +01:00
ManiacTwister
908f1c30c4 Proper range for fakechannel user count 2018-11-26 20:13:37 +01:00
ManiacTwister
cee332ab83 Use irccmp instead of strcasecmp for fakechannels 2018-11-26 20:13:20 +01:00
ManiacTwister
0ca3cf0d91 Disable fakechannels by default 2018-11-26 20:13:00 +01:00
ManiacTwister
590a46b165 Fixed fakechannel removal 2018-11-26 20:12:44 +01:00
ManiacTwister
23e6d4ed73 Check if users_max is less than users_min 2018-11-26 20:12:04 +01:00
ManiacTwister
6d01464fc5 Allow fakechannels with 0 users 2018-11-26 20:11:37 +01:00
ManiacTwister
a4e5c2fa61 Added fakechannels to /LIST 2018-11-21 20:19:41 +01:00
ManiacTwister
074e23e4e2 Added SNI support (OpenSSL) 2018-11-21 20:03:48 +01:00
ManiacTwister
0b79494ec9 Added fakechannels to /LIST 2018-10-27 21:47:25 +02:00
ManiacTwister
d89ff1897d Check if ssl_cipher_list is set 2018-10-27 20:59:42 +02:00
ManiacTwister
bec08a8364 Allow fd limit change when rehashing 2018-10-27 20:59:02 +02:00
ManiacTwister
ef70f680c5 Add commit sha1 to charybdis version 2018-10-27 20:53:52 +02:00
Aaron Jones
a034b14fbf
charybdis 3.5.6 2018-08-26 18:50:21 +00:00
Aaron Jones
cc34e7543a
libratbox/src/mbedtls_ratbox.h: remove unnecessary inclusion 2018-08-26 18:50:08 +00:00
Simon Arlott
3ea954da3a
m_nick/m_sasl/m_user: restore check for mixing of client and server protocol 2018-08-15 22:48:08 +01:00
Simon Arlott
28caceba33
m_pass: store unverified SID in preClient for use in m_server 2018-08-15 22:48:07 +01:00
Aaron Jones
4f8ad92ab4
MbedTLS: Support ChaCha20-Poly1305 in TLSv1.2+ 2018-08-13 22:34:16 +00:00
Simon Arlott
151c4614a0
authd: always use an empty buffer to read ident reply
Otherwise we could read uninitialised data beyond the actual reply
2018-08-12 18:57:15 +01:00
Simon Arlott
03f04cd80e
m_sasl: check if the agent is present after every client_exit
When a server disconnects the client_exit hook will only be called once
but there could be multiple servers and clients behind that server.

After any client exits, check if the agent is still present.
2018-08-12 13:06:20 +01:00
Simon Arlott
f515fa9382
doc: build with travis 2018-08-12 10:15:05 +01:00
Simon Arlott
8e02234970
doc: there is no _static directory 2018-08-12 09:42:10 +01:00
Simon Arlott
ccaf2012bd
Merge pull request #263 from anarcat/extban-doc
point users towards HELP EXTBAN for inline help
2018-08-12 09:25:56 +01:00
Antoine Beaupré
6e93b3b153
point users towards HELP EXTBAN for inline help 2018-07-26 16:39:58 -04:00
Aaron Jones
bfffef7436
modules/m_sasl.c: prevent abort_sasl() sending 906 twice 2018-04-06 20:05:48 +00:00
Aaron Jones
11d111c3fa
modules/m_sasl.c: abort session if we receive '*' as data
Otherwise we'd send the * on to services as actual data, which is likely
to fail to decode it (it's not valid Base-64) and reply with an SASL ...
D F which will result in us sending a 904 numeric instead of a 906.

cf. https://github.com/ircv3/ircv3-specifications/pull/298#issuecomment-271336287

Reported-By: James Wheare
2018-04-06 19:45:56 +00:00
Aaron Jones
6c00795284
libratbox/src/mbedtls.c: check public/private keys match 2018-01-06 15:58:30 +00:00
Aaron Jones
412263854f
src/s_user.c: don't send fake MODE for clients who have CHGHOST
Reported-by: Samuel Hoffman <samuelhoffman2@gmail.com>
2017-12-17 03:20:08 +00:00
Aaron Jones
9d80b087cd
doc/reference.conf: clarify that server link fingerprints aren't optional
[ci skip]
2017-11-04 07:42:21 +00:00
Aaron Jones
cf5b56b06b
Update configure from configure.ac 2017-10-23 11:44:04 +00:00
mniip
5ce1252007
configure.ac: Adjust dlopen/dlsym checks
In modern gcc/clang, libasan (the address sanitizer runtime) exports a
weak definition of `dlopen` so that it can intercept certain flags. If
one tried to `./configure` with address sanitizer enabled, this would
cause AC_SEARCH_LIBS to conclude that dlopen doesn't require any link
flags to use. However libasan does not export `dlsym` and this caused
AC_CHECK_FUNC to fail because it didn't try linking with `-ldl`.
2017-10-23 11:43:42 +00:00
Aaron Jones
e1d4ebda4d
modules/static_modules.c.SH: use correct header file
Commit 4016731b1c missed a file.

Reported-by: mniip (Freenode)

[ci skip]
2017-10-15 06:38:33 +00:00
Aaron Jones
c380c2336a Merge pull request #247 from anarcat/cmode-help-pointer
point to the CMODE help page for more modes
2017-08-29 18:21:56 +00:00
Antoine Beaupré
b018538406
point to the CMODE help page for more modes 2017-08-29 09:10:37 -04:00
Simon Arlott
55735d9d7e
exit_unknown_client: don't delete servers from the client hash
Outgoing servers are not added to the client hash until they reach
IsServer() status, so if they're unknown when they exit then don't
attempt to delete them.
2017-08-24 20:09:17 +01:00
Simon Arlott
754c1edf2e
m_sasl: indicate client connection type for SASL 2017-08-13 21:52:04 +01:00
Aaron Jones
a6485efda0
libratbox/src/commio.c: misc cleanups for compiler warnings
commio.c:2244:11: warning: variable length array used [-Wvla]
commio.c:2253:29: warning: comparison of integers of different signs:
                  'unsigned int' and 'int' [-Wsign-compare]

This use of alloca(3) is okay-ish considering the corresponding function
`rb_recv_fd_buf()` already uses it too, for much the same purpose. Also
remove a redundant return statement.
2017-08-04 12:32:58 +00:00
Simon Arlott
c41d0c0f5f
modules/core/m_join.c: remove global variable parabuf
Edit by @aaronmdjones: m_join() doesn't need it
2017-08-04 12:32:58 +00:00
Simon Arlott
75399a9334
modules/core/m_join.c: remove global variable modebuf 2017-08-04 12:32:58 +00:00
Simon Arlott
18823bcfca
modules/core/m_join.c: remove global variable para 2017-08-04 12:32:58 +00:00
Simon Arlott
1c2012f03b
modules/core/m_join.c: remove global variable pargs 2017-08-04 12:32:58 +00:00
Simon Arlott
6420b39ad0
modules/core/m_join.c: remove global variable mbuf 2017-08-04 12:32:58 +00:00
Simon Arlott
55ae03aee1
libratbox/src/ratbox_lib.c: avoid clang static analysis warning 2017-08-04 12:32:58 +00:00
Simon Arlott
ae6ce6100a
ssld: avoid clang static analysis warning
Don't set `x = 0` twice.

Edit by @aaronmdjones: fix for loop initialisation and inner condition
2017-08-04 12:32:58 +00:00
Simon Arlott
a21843a0a0
ssld: avoid clang static analysis warning 2017-08-04 12:32:58 +00:00
Simon Arlott
8fc0cea653
librb: rb_linebuf_copy_raw: remove unused assignment 2017-08-04 12:32:58 +00:00
Simon Arlott
ed78e97a96
ircd: hostmask: avoid clang static analysis warning
arec->Mask.ipa.bits is unused if arec->masktype == HM_HOST
2017-08-04 12:32:58 +00:00
Simon Arlott
ea3ca814f5
libratbox/src/commio.c: Must set addrlen before every call to accept()
If an IPv4 connection is dropped by the pre-callback, and there is a
pending IPv6 connection on the same listening socket then the retried
accept() will be unable to populate `st` because `addrlen` will be too
small. Also initialise `st` each time to avoid a clang static analysis
warning.
2017-08-04 12:32:58 +00:00
Aaron Jones
e09aeac9ed
src/hash.c: misc cleanup for compiler warnings
hash.c:714:36: warning: comparison of integers of different signs:
               'uint32_t' (aka 'unsigned int') and 'int'
               [-Wsign-compare]

    (... and 1 more of the same)
2017-08-04 12:32:58 +00:00
Aaron Jones
85f46bb59e
libratbox/src/crypt.c: misc cleanup for compiler warning
crypt.c:1979:7: warning: '_STRING_ARCH_unaligned' is not defined,
                evaluates to 0 [-Wundef]
2017-08-04 12:32:58 +00:00
Aaron Jones
e55c29ef11
include/s_user.h: convert raw attribute into already-existing macro call
I overlooked this existing macro when adding this attribute in an earlier
commit.
2017-08-04 12:32:57 +00:00
Aaron Jones
3109b8a636
modules/core/m_mode.c: misc cleanup for compiler warning
core/m_mode.c:378:11: warning: possible misuse of comma operator here
                      [-Wcomma]
2017-08-04 12:32:57 +00:00
Aaron Jones
c67c9451a1
extensions/hurt.c: misc cleanups for compiler warnings
hurt.c:196:16: warning: possible misuse of comma operator here [-Wcomma]

    (... and 3 more of the same)
2017-08-04 12:32:57 +00:00
Aaron Jones
daf1b4b9af
extensions/m_sendbans.c: misc cleanup for compiler warning
m_sendbans.c:76:15: warning: possible misuse of comma operator here
                    [-Wcomma]
2017-08-04 12:32:57 +00:00
Aaron Jones
8952f21843
modules/m_rehash.c: misc cleanups for compiler warnings
m_rehash.c:380:17: warning: possible misuse of comma operator here
                   [-Wcomma]

    (... and 3 more of the same)
2017-08-04 12:32:57 +00:00
Aaron Jones
ec5f6dc23b
src/supported.c: misc cleanups for compiler warnings
supported.c:172:22: warning: possible misuse of comma operator here
                    [-Wcomma]

    (... and 4 more of the same)
2017-08-04 12:32:57 +00:00
Aaron Jones
f21bac62f4
src/chmode.c: misc cleanups for compiler warnings
chmode.c:417:12: warning: possible misuse of comma operator here
                 [-Wcomma]

    (... and 12 more of the same)
2017-08-04 12:32:57 +00:00
Aaron Jones
f54e6c3558
libratbox/src/commio.c: misc cleanup for compiler warning
commio.c:1269:17: warning: possible misuse of comma operator here
                  [-Wcomma]

What an ugly way to use commas!
2017-08-04 12:32:57 +00:00
Aaron Jones
82e920102f
lots of misc cleanups for compiler warnings
ratbox_lib.c:159:1: warning: function 'rb_lib_restart' could be declared
                    with attribute 'noreturn' [-Wmissing-noreturn]

ratbox_lib.c:220:1: warning: function 'rb_lib_loop' could be declared
                    with attribute 'noreturn' [-Wmissing-noreturn]

restart.c:55:1: warning: function 'server_reboot' could be declared with
                attribute 'noreturn' [-Wmissing-noreturn]
2017-08-04 12:32:57 +00:00
Aaron Jones
6f1e0a6f47
src/ircd_signal.c: misc cleanup for compiler warning
ircd_signal.c:59:1: warning: function 'sigterm_handler' could be declared
                    with attribute 'noreturn' [-Wmissing-noreturn]
2017-08-04 12:32:57 +00:00
Aaron Jones
9ca4bd7e0c
rb_helper: misc cleanups for compiler warning
helper.c:291:1: warning: function 'rb_helper_loop' could be declared
                with attribute 'noreturn' [-Wmissing-noreturn]
2017-08-04 12:32:57 +00:00
Aaron Jones
7406d7acad
getopt: misc cleanups for compiler warning
getopt.c:124:1: warning: function 'usage' could be declared with
                attribute 'noreturn' [-Wmissing-noreturn]
2017-08-04 12:32:57 +00:00
Aaron Jones
8c8a219e71
src/bandbi.c: misc cleanup for compiler warning
bandbi.c:389:1: warning: function 'bandb_handle_failure' could be
                declared with attribute 'noreturn'
                [-Wmissing-noreturn]
2017-08-04 12:32:57 +00:00
Aaron Jones
bd62a802f9
libratbox/src/balloc.c: misc cleanup for compiler warning
balloc.c:111:1: warning: function '_rb_bh_fail' could be declared with
                attribute 'noreturn' [-Wmissing-noreturn]
2017-08-04 12:32:57 +00:00
Aaron Jones
efc60d52a3
modules/core/m_server.c: misc cleanup for compiler warnings
core/m_server.c:138:3: warning: 'break' will never be executed
                       [-Wunreachable-code-break]

    (... and 3 more of the same)

Why put an unreachable comment in the code *and then write a
statement following it* ? O_o
2017-08-04 12:32:57 +00:00
Aaron Jones
81e245be5b
modules/core/m_die.c: misc cleanup for compiler warning
core/m_die.c:76:9: warning: 'return' will never be executed
                   [-Wunreachable-code-return]
2017-08-04 12:32:57 +00:00
Aaron Jones
ee0a3970c8
modules/m_whois.c: misc cleanup for compiler warning
m_whois.c:331:8: warning: declaration shadows a local variable [-Wshadow]
2017-08-04 12:32:56 +00:00
Aaron Jones
72fd7c04ac
include/s_user.h: misc cleanup for compiler warning
s_user.c:1428:26: warning: format string is not a string literal
                  [-Wformat-nonliteral]

Adding the printf attribute to the function will make the compiler
assume that the 'format' argument to the function is a string
literal (by warning about the *callers* of the function *not* using
a string literal), thus avoiding the warning in the function.
2017-08-04 12:32:56 +00:00
Aaron Jones
eef58149c7
src/res.c: misc cleanup for compiler warnings
res.c:704:6: warning: 'break' will never be executed
             [-Wunreachable-code-break]

    (... and 2 more of the same)
2017-08-04 12:32:56 +00:00
Aaron Jones
e52356b21e
libratbox/src/commio.c: misc cleanup for compiler warnings
commio.c:1368:3: warning: 'break' will never be executed
                 [-Wunreachable-code-break]

    (... and 2 more of the same)
2017-08-04 12:32:56 +00:00
Aaron Jones
9c7e29bf66
src/chmode.c: misc cleanup for compiler warning
chmode.c:782:3: warning: 'break' will never be executed
                [-Wunreachable-code-break]
2017-08-04 12:32:56 +00:00
Aaron Jones
ef14b780b4
src/modules.c: misc cleanup for compiler warnings
modules.c:799:37: warning: cast from function call of type 'void *' to
                  non-matching type 'uintptr_t' (aka 'unsigned long')
                  [-Wbad-function-cast]

    (... and 1 more of the same)

Redundant double-cast removed.
2017-08-04 12:32:56 +00:00
Aaron Jones
fa2b7ab282
libratbox/src/openssl_ratbox.h: misc cleanup for compiler warning
openssl.c:459:47: warning: cast from 'const char *' to 'char *' drops
                  const qualifier [-Wcast-qual]

(I find it remarkable that SSL_CTX_set1_curves_list() does not accept a
 'const char *' argument...)
2017-08-04 12:32:56 +00:00
Aaron Jones
b253a53c51
modules/m_stats.c: misc cleanup for compiler warnings
m_stats.c:181:22: warning: this function declaration is not a prototype
                  [-Wstrict-prototypes]

m_stats.c:1502:24: warning: format string is not a string literal
                   [-Wformat-nonliteral]
    (... and 2 more of the same)
2017-08-04 12:32:56 +00:00
Aaron Jones
28541a0d96
tools/mkpasswd.c: misc cleanup for compiler warnings
mkpasswd.c:516:1: warning: function 'full_usage' could be declared with
                  attribute 'noreturn' [-Wmissing-noreturn]

mkpasswd.c:537:1: warning: function 'brief_usage' could be declared with
                  attribute 'noreturn' [-Wmissing-noreturn]
2017-08-04 12:32:56 +00:00
Aaron Jones
3f7ccca917
libratbox/src/crypt.c: misc cleanup for compiler warnings
crypt.c:49:4: warning: 'break' will never be executed
              [-Wunreachable-code-break]
    (... and 3 more of the same)

crypt.c:627:7: warning: variable 'f' may be uninitialized when used
               here [-Wconditional-uninitialized]

crypt.c:539:12: note: initialize the variable 'f' to silence this
                warning
2017-08-04 12:32:56 +00:00
Aaron Jones
9519919ff5
ssld/ssld.c: misc cleanup for compiler warning
ssld.c:1251:14: warning: signed shift result (0x80000000) sets the sign
                bit of the shift expression's type ('int') and becomes
                negative [-Wshift-sign-overflow]
2017-08-04 12:32:56 +00:00
Aaron Jones
846629b388
bandb/bantool.c: misc cleanup for compiler warning
bantool.c:149:4: warning: 'break' will never be executed
                 [-Wunreachable-code-break]
2017-08-04 12:32:56 +00:00
Aaron Jones
9b7cc82b90
ircd: misc cleanup for compiler warnings
ircd.c:125:1: warning: function 'ircd_shutdown' could be declared with
              attribute 'noreturn' [-Wmissing-noreturn]

ircd.c:437:1: warning: function 'ircd_die_cb' could be declared with
              attribute 'noreturn' [-Wmissing-noreturn]
2017-08-04 12:32:56 +00:00
Aaron Jones
a8517ee77c
bandb/bandb.c: misc cleanup for compiler warnings
bandb.c:243:1: warning: function 'error_cb' could be declared with
               attribute 'noreturn' [-Wmissing-noreturn]

bandb.c:289:1: warning: function 'db_error_cb' could be declared with
               attribute 'noreturn' [-Wmissing-noreturn]

bandb.c:293:13: warning: signed shift result (0x80000000) sets the sign
                bit of the shift expression's type ('int') and becomes
                negative [-Wshift-sign-overflow]
2017-08-04 12:32:56 +00:00
Aaron Jones
81ae0a7d1b
bandb/bantool.c: misc cleanup for compiler warning
bantool.c:872:1: warning: function 'print_help' could be declared with
                 attribute 'noreturn' [-Wmissing-noreturn]
2017-08-04 12:32:53 +00:00
Simon Arlott
9d7c65294f
m_webirc: set sockhost before potentially using it to set host
Remove extra IP check, it's not necessary.
2017-08-01 22:50:30 +01:00
Simon Arlott
ce15ac6c0b
sslproc: check number of arguments to zipstats command 2017-07-29 22:22:34 +01:00
Aaron Jones
705ca33e17
src/channel.c: don't use the bancache in is_banned()/is_quieted()
The bancache will be re-architected onto clients in future for easier
invalidation, but this is a good-enough temporary fix for issue #243

Fixes #243
2017-07-05 17:35:28 +00:00
Aaron Jones
167ca46a04
mbedtls.c: minor fixups
- Add (void) casts for unused function parameters
- Rearrange member in `struct rb_mbedtls_cfg_context' for data alignment
- Document a `clang-4.0 -Weverything' (-Wcast-qual) diagnostic
- Avoid pointless conversions between positive/negative error codes
- Use capital hexadecimals in error codes and properly cast to
  (unsigned int) for %x/%X
2017-07-03 00:21:43 +00:00
Simon Arlott
51d65d191a
m_webirc: use rb_inet_ntop_sock to populate sockhost 2017-06-27 21:15:14 +01:00
Simon Arlott
62c0ac4124
ircd: s_conf: fix use of strlcpy in strip_tabs
strlcpy should be called with the size of the destination buffer, not
the length of the source string.

When the source is an empty string, the destination buffer isn't
written at all, resulting in it trying to output uninitialised data.

This could also cause a buffer overflow on very long invalid config
lines.
2017-06-25 19:54:39 +01:00
Aaron Jones
789bb31c92
configure: allow exact PID file prefix to be specified 2017-06-23 05:55:48 +00:00
Aaron Jones
1b7c6aff1a
MbedTLS: Don't use a dummy CA certificate on new library (no longer required) 2017-06-22 11:12:21 +00:00
Ellenor Malik
e0f1c3b5bc
extensions/extb_ssl.c: add support for matching by certificate fingerprint 2017-06-16 01:51:38 +00:00
Aaron Jones
68ba8e8125
README.md: Update channel
The domain expired and then someone else seems to have reacquired it,
so point users back at Freenode for now as recovery is unlikely.
2017-06-12 17:00:14 +00:00
Aaron Jones
8b96afb67b Merge pull request #241 from anarcat/rst-guide 2017-03-25 16:49:08 +00:00
Antoine Beaupré
7e7107a6b7
fix more headings 2017-03-25 12:35:29 -04:00
Antoine Beaupré
5bc633fd77
fix two headings to be toplevel 2017-03-25 12:33:06 -04:00
Antoine Beaupré
c14e0b9523
do not hardcode theme 2017-03-25 12:29:27 -04:00
Antoine Beaupré
f41c25c0c1
config.rst review 2017-03-25 12:22:36 -04:00
Antoine Beaupré
ea56df54f7
review commands.rst style 2017-03-25 12:07:37 -04:00
Antoine Beaupré
194a960192
fix style in ucommands.rst 2017-03-25 11:49:30 -04:00
Antoine Beaupré
79a69a8e43
fix syntax warning 2017-03-25 11:47:58 -04:00
Antoine Beaupré
8bb743a695
fix ucommands.rst style 2017-03-25 11:47:23 -04:00
Antoine Beaupré
689137420b
review umodes.rst 2017-03-25 11:45:22 -04:00
Antoine Beaupré
2838bd22d6
review oprivs.rst style 2017-03-25 11:44:51 -04:00
Antoine Beaupré
932350e189
review cmodes.rst style 2017-03-25 11:42:51 -04:00
Antoine Beaupré
bdfadfcb99
some styling
turn all +flags into preformatted flags, fix admonitions
2017-03-25 11:33:06 -04:00
Antoine Beaupré
bc9cb138a4
ignore build results 2017-03-25 11:15:08 -04:00
Antoine Beaupré
c74b47583e
fix duplicate headings, remove duplicate ToC 2017-03-25 11:15:03 -04:00
Antoine Beaupré
0da7307521
merge two index pages 2017-03-25 11:09:44 -04:00
Antoine Beaupré
2874f74c81
convert SGML guide to RST
the rationale behind switching away from SGML/Docbook is the following:

 * SGML is hard to edit for humans
 * the output is not much prettier
 * the toolchain is not well supported and missing from the build
 * the build is not hooked into anywhere, no automation

the reason why RST was chosen:

 * it allows for a strong structure like Docbook
 * the theme from Read The Docs is pretty
 * it also supports mobile devices
 * sphinx can easily output to PDF and ePUB formats
 * RST is plaintext that can be easily edited and diff'd
 * RST can be automatically built by ReadTheDocs and the toolchain is
   readily available
 * the output is also parsed by Github so documentation can be read
   straight from GH

the reason why Markdown was not chosen:

 * the current strong structure would be hard to replicate
 * markdown is not standardized and output varies according to the
   implementation

the docs were converted with Pandoc, using the following commands:

    mkdir oper-guide
    for source in sgml/oper-guide/*.sgml; do
        pandoc --toc -s -f docbook -t rst $source -o oper-guide/$(basename $source .sgml).rst
    done
    cd oper-guide
    sphinx-quickstart
    git add *.rst make.bat conf.py
    git add -f Makefile
    git rm -r ../sgml
2017-03-25 10:51:01 -04:00
Aaron Jones
6fa52d140c
Charybdis 3.5.5 2017-03-01 01:08:58 +00:00
Aaron Jones
d8df3c90de
GNUTLS: Log why fingerprint generation fails
This is rudimentary but at least 1 other backend logs why too.
2017-03-01 01:06:57 +00:00
Aaron Jones
5d8a480305
GNUTLS: Don't use VERS-TLS-ALL
It causes problems with older versions of the library.
2017-02-28 22:51:51 +00:00
Aaron Jones
b012874243 Merge pull request #238 from anarcat/gnutls-cert-count
properly call gnutls_x509_crt_list_import
2017-02-28 22:44:35 +00:00
Antoine Beaupré
9f21f1b353
properly call gnutls_x509_crt_list_import
the [manpage][] says:

>  unsigned int * cert_max
>      Initially must hold the maximum number of certs. It will be updated
>      with the number of certs available.

ratbox doesn't actually initialize that variable, so gnutls naturally
fails. i would also recommend considering dynamically allocating the
cert list to deal with that error in other ways than failing to
configured SSL completely in GnuTLS. the apache gnutls module has a
similar problem and came up with a [patch][] to do exactly this which
you may want to consider.

but since our cert chain is only (!) 5 certs long, our itched is
scratch by this particular patch.

[manpage]: https://manpages.debian.org/jessie/gnutls-doc/gnutls_x509_crt_list_import.3.en.html
[patch]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=511573#35
2017-02-28 17:36:56 -05:00
Aaron Jones
9bd8c1c0dc
Charybdis 3.5.4 2017-02-28 21:28:20 +00:00
Simon Arlott
b04acc54ac
CREDITS: fix my nickname and update my email address 2017-01-06 21:51:05 +00:00
Aaron Jones
5633e89376
MbedTLS: Disable TLSv1.0 2016-12-30 18:00:45 +00:00
Aaron Jones
e140ba71d6
OpenSSL: Disable TLSv1.0 2016-12-30 18:00:43 +00:00
Aaron Jones
6bcfd29624
GNUTLS: Provide a default priority string, disable TLSv1.0 in it
The user can still override this choice with the ssl_cipher_list option
in ircd.conf -- this is the only backend that will allow you to do so.
2016-12-30 18:00:41 +00:00
Keith Buck
4574e77f43 extensions/extb_channel: Allow matching secret channels.
This change modifies extb_channel to allow matching users in secret
channels, which prevents trivial ban evasion by setting the target
channel +s. Information leak due to this change is unlikely since the
attacker would have to know that the target channel exists, the name of
the channel (or guess it), have a specific user they wanted to know
whether was in the channel (and not know already), and the target user
would need to have something like autojoin-on-invite enabled (or any of
the other various ways hostname cloaking is attacked).
2016-12-29 05:44:18 +00:00
Aaron Jones
db05a36210
MODRESTART: Defer restart to the event loop
When a remote MODRESTART command is received, it will pass through the
ENCAP module. The ms_encap function is responsible for dispatching the
command handler and then the modules will eventually be reloaded.

However, if the ENCAP module is reloaded to a different address, the
stack now contains the address of a function that no longer exists.

Return immediately from the command handler and have the event loop
call the function responsible for reloading the modules instead.

Reported-by: mniip (Freenode)
2016-12-28 20:15:39 +00:00
Aaron Jones
9cdd7270f9
mkpasswd: avoid strdup(NULL) and the like if rb_crypt() fails 2016-12-20 03:54:08 +00:00
Keith Buck
a91a4515c9 mr_server: Handle certificate validation errors.
When certificate validation fails, the certificate fingerprint won't be
calculated, resulting in an attempt to format NULL into a log line
showing the fingerprint. Instead, add a different error message for
missing fingerprint (i.e. validation failed).
2016-12-09 10:01:22 +00:00
Keith Buck
5fd7e2bb8c m_rehash: Require admin privileges for REHASH SSLD.
This change enforces admin privileges for the REHASH SSLD command, as
originally intended.
2016-12-04 22:03:34 +00:00
Simon Arlott
598a7d3b7e mr_server: Report certificate fingerprint mismatches
Log the received certificate fingerprint when it causes a server to be
rejected.
2016-12-04 21:49:59 +00:00
Simon Arlott
8d0153ff55 mr_server: Handle unknown error codes
As mr_server is a module, it could potentially receive an unknown
error code from check_server().
2016-12-04 21:45:16 +00:00
Simon Arlott
0264fe161f sslproc: don't send updated config to dead/shutdown sslds
They might be running older versions of the SSL library that
doesn't support the key type or ciphers being configured.
2016-12-04 21:40:08 +00:00
Simon Arlott
9c98c1f866 ircd: add missing sslproc function ssld_foreach_info()
Iterate through the ssl daemons and report their status.
2016-12-04 21:25:41 +00:00
Simon Arlott
d4b074a771 ircd: support restarting ssld processes
Add REHASH SSLD (admins only) that starts new sslds and marks the
existing ones as inactive until all their clients disconnect.

Very useful whenever the SSL library has a vulnerability because
new connections can use a new version of the library without
disconnecting existing clients/servers.

Add STATS S (admins only) to list ssld processes, status, and client
count.
2016-12-04 21:24:56 +00:00
Aaron Jones
e386d7f362
reference.conf: missed a line
(see previous commit) [ci skip]
2016-12-01 05:15:30 +00:00
Aaron Jones
2815967598
reference.conf: simplify SPKI fingerprint generation commands
[ci skip]
2016-12-01 05:08:15 +00:00
Aaron Jones
256e6fd251
reference.conf: Use proper IPv6 RFC Documentation Range Subnet
[ci skip]
2016-11-27 20:50:20 +00:00
Simon Arlott
65b9b1d06d
server_estab: don't try to send to a dead client
If the zlib setup fails the client will be exited, so don't send
to it before checking this.
2016-11-20 21:43:58 +00:00
Simon Arlott
aaf6039eea
listener: use exit_client instead of free_client
As well as leaking a connid and leaving the connection open,
these calls to free_client() leave the client in the unknown_list
causing check_unknowns_list() to crash when either ptr->data
(ptr being the freed client_p->localClient->tnode) is NULL or
when client_p->localClient is NULL.

Flag the client as an IO error so that we don't try to send it
any data (as this is not a normal plaintext connection).
2016-11-20 21:43:44 +00:00
Aaron Jones
785df805d7
reference.conf: bump the recommended digest algorithm from SHA-1 to SHA2-256
ircd.conf.example still has SHA-1 for the people who want to quickly deploy
by renaming that file and adjusting as appropriate.
2016-11-15 12:34:49 +00:00
Aaron Jones
2afd965b21
TLS: Partially backport the SubjectPublicKeyInfo digesting functionality
This backports the code responsible for SPKI digests from release/4.

It also adjusts doc/reference.conf to note that SPKI digests are now
supported, and how to generate them. It does NOT backport the mkfingerprint
program -- the instructions in reference.conf are sufficient. I am ofcourse
open to anyone else backporting the program, but I don't see the need.
2016-11-15 12:30:09 +00:00
Aaron Jones
0a9598655c
TLS backends: Move some library-dependent functions to the proper location
The comment incorrectly stated these were library-agnostic; infact, they
use library-dependent data types or macro names.
2016-11-15 12:11:12 +00:00
Simon Arlott
95bdc091b2
free cache emptyline rb_dlink_node, allocated automatically but never freed
==00:00:01:09.081 1762== 48 bytes in 2 blocks are definitely lost in loss record 545 of 991
==00:00:01:09.081 1762==    at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==00:00:01:09.081 1762==    by 0x56C14A2: rb_malloc (rb_memory.h:41)
==00:00:01:09.081 1762==    by 0x56C177C: rb_bh_alloc (balloc.c:189)
==00:00:01:09.081 1762==    by 0x56CA0A9: rb_make_rb_dlink_node (tools.c:65)
==00:00:01:09.081 1762==    by 0x4E52D85: cache_file (cache.c:146)
==00:00:01:09.081 1762==    by 0x4E52AC3: init_cache (cache.c:67)
==00:00:01:09.081 1762==    by 0x4E69530: charybdis_main (ircd.c:762)
==00:00:01:09.081 1762==    by 0x400815: main (main.c:8)

==00:00:01:09.100 1762== 2,808 bytes in 117 blocks are definitely lost in loss record 960 of 991
==00:00:01:09.100 1762==    at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==00:00:01:09.100 1762==    by 0x56C14A2: rb_malloc (rb_memory.h:41)
==00:00:01:09.100 1762==    by 0x56C177C: rb_bh_alloc (balloc.c:189)
==00:00:01:09.100 1762==    by 0x56CA0A9: rb_make_rb_dlink_node (tools.c:65)
==00:00:01:09.100 1762==    by 0x4E52D85: cache_file (cache.c:146)
==00:00:01:09.100 1762==    by 0x4E5337A: load_help (cache.c:301)
==00:00:01:09.100 1762==    by 0x4E698AA: charybdis_main (ircd.c:848)
==00:00:01:09.100 1762==    by 0x400815: main (main.c:8)

==00:00:01:09.100 1762== 5,328 (5,304 direct, 24 indirect) bytes in 221 blocks are definitely lost in loss record 971 of 991
==00:00:01:09.100 1762==    at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==00:00:01:09.100 1762==    by 0x56C14A2: rb_malloc (rb_memory.h:41)
==00:00:01:09.100 1762==    by 0x56C177C: rb_bh_alloc (balloc.c:189)
==00:00:01:09.100 1762==    by 0x56CA0A9: rb_make_rb_dlink_node (tools.c:65)
==00:00:01:09.100 1762==    by 0x4E52D85: cache_file (cache.c:146)
==00:00:01:09.100 1762==    by 0x4E53278: load_help (cache.c:266)
==00:00:01:09.100 1762==    by 0x4E698AA: charybdis_main (ircd.c:848)
==00:00:01:09.100 1762==    by 0x400815: main (main.c:8)
2016-10-30 12:08:13 +00:00
Simon Arlott
ccd9e858f3
free server_p->certfp, allocated in newconf.c
==01:17:20:36.920 5966== 429 bytes in 3 blocks are possibly lost in loss record 899 of 1,020
==01:17:20:36.920 5966==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==01:17:20:36.920 5966==    by 0x4E73867: rb_strdup (rb_memory.h:70)
==01:17:20:36.920 5966==    by 0x4E7674C: conf_set_connect_fingerprint (newconf.c:1421)
==01:17:20:36.920 5966==    by 0x4E78D55: conf_call_set (newconf.c:2562)
==01:17:20:36.920 5966==    by 0x4E6A33D: yyparse (ircd_parser.y:215)
==01:17:20:36.920 5966==    by 0x4E7FFC7: read_conf (s_conf.c:834)
==01:17:20:36.920 5966==    by 0x4E81718: read_conf_files (s_conf.c:1419)
==01:17:20:36.920 5966==    by 0x4E69567: charybdis_main (ircd.c:775)
==01:17:20:36.920 5966==    by 0x400815: main (main.c:8)
2016-10-30 11:48:23 +00:00
Simon Arlott
2b439b88fc
free localClient->cipher_string, allocated in sslproc.c
==01:17:20:36.919 5966== 280 bytes in 8 blocks are definitely lost in loss record 876 of 1,020
==01:17:20:36.919 5966==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==01:17:20:36.919 5966==    by 0x4E93F4F: rb_strdup (rb_memory.h:70)
==01:17:20:36.919 5966==    by 0x4E95280: ssl_process_cipher_string (sslproc.c:476)
==01:17:20:36.919 5966==    by 0x4E95540: ssl_process_cmd_recv (sslproc.c:561)
==01:17:20:36.919 5966==    by 0x4E9582A: ssl_read_ctl (sslproc.c:632)
==01:17:20:36.919 5966==    by 0x56CBAB6: rb_select_epoll (epoll.c:199)
==01:17:20:36.919 5966==    by 0x56C4EB5: rb_select (commio.c:2085)
==01:17:20:36.919 5966==    by 0x56C7FD6: rb_lib_loop (rb_lib.c:228)
==01:17:20:36.919 5966==    by 0x4E69987: charybdis_main (ircd.c:872)
==01:17:20:36.919 5966==    by 0x400815: main (main.c:8)
2016-10-30 11:29:15 +00:00
Simon Arlott
6f3d3cb6f5
free localClient->zipstats, allocated in sslproc.c
==01:17:20:36.906 5966== 48 bytes in 1 blocks are definitely lost in loss record 544 of 1,020
==01:17:20:36.906 5966==    at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==01:17:20:36.906 5966==    by 0x4E93F0C: rb_malloc (rb_memory.h:41)
==01:17:20:36.906 5966==    by 0x4E961E8: start_zlib_session (sslproc.c:901)
==01:17:20:36.906 5966==    by 0x4E86FAC: server_estab (s_serv.c:877)
==01:17:20:36.906 5966==    by 0x13B2921A: mr_server (m_server.c:304)
==01:17:20:36.906 5966==    by 0x4E7AF03: handle_command (parse.c:241)
==01:17:20:36.906 5966==    by 0x4E7A96A: parse (parse.c:157)
==01:17:20:36.906 5966==    by 0x4E7A3DC: client_dopacket (packet.c:354)
==01:17:20:36.906 5966==    by 0x4E798D6: parse_client_queued (packet.c:98)
==01:17:20:36.906 5966==    by 0x4E79FAC: read_packet (packet.c:282)
==01:17:20:36.906 5966==    by 0x56CBAB6: rb_select_epoll (epoll.c:199)
==01:17:20:36.906 5966==    by 0x56C4EB5: rb_select (commio.c:2085)
2016-10-30 11:26:37 +00:00
Aaron Jones
0508eea2ed
OpenSSL: Adjust ciphersuite order and update documentation 2016-10-18 11:14:47 +00:00
Aaron Jones
a3868e7141
MbedTLS: Adjust ciphersuite order and update documentation 2016-10-18 10:56:04 +00:00
Aaron Jones
866026ab70
whois: check target is an oper before assuming they have a privset
The CHALLENGE functionality will set opername but not privset --
if an oper performs a WHOIS on someone currently half-way through
a challenge we will perform a NULL dereference.

Related to ircd-seven commit d7b05f7583babf6
2016-09-20 13:46:40 +00:00
William Pitcock
5de892828f Merge pull request #220 from charybdis-ircd/gnutls220
Improvements to the GNUTLS backend
2016-09-16 22:50:27 -07:00
Aaron Jones
ecfdcb08e8
GNUTLS: Reorder all functions to match the other backends
No code was changed in this commit; just entire lines moved up or down.
Ofcourse, most git diff tools won't see it that way.

The diff between the MbedTLS backend and this one is now fairly
minimal.

Note to auditors importing this series of patches for review and
integration: This means you can skip this patch if you don't trust me.
2016-09-17 00:56:54 +00:00
Aaron Jones
fe9fba46cf
GNUTLS: Add some more misc checks to the start of functions 2016-09-17 00:56:54 +00:00
Aaron Jones
70bb2e24e0
GNUTLS: Cosmetic preprocessor cleanliness 2016-09-17 00:56:54 +00:00
Aaron Jones
1a75461594
GNUTLS: Minor fix to rb_ssl_accept_common()/rb_ssl_connect_common()
Properly check whether the library was interrupted by the kernel
before assuming that a nonzero errno was caused by the kernel.

Otherwise, a memory allocation failure in the library for example
would incorrectly be interpreted as a syscall error instead of a
library error.
2016-09-17 00:56:54 +00:00
Aaron Jones
0071c423d5
GNUTLS: Improve rb_ssl_read_or_write()
* Set errno to 0 before attempting any read/write operations as it may
  affect our tests otherwise.

* Properly check whether the gnutls_record_recv()/gnutls_record_send()
  call failed and distinguish between kernel and library errors.
2016-09-17 00:56:54 +00:00
Aaron Jones
d4e71871c0
GNUTLS: rb_ssl_read_or_write(): Use macro to refer to session context 2016-09-17 00:56:54 +00:00
Aaron Jones
939d7ec7fe
GNUTLS: Apply whole-file const correctness 2016-09-17 00:56:54 +00:00
Aaron Jones
9c7dda22e8
GNUTLS: Improve rb_ssl_get_cipher()
* Add debugging assertions.

* Reduce the buffer size in line with the other backends.

* Ask for the cipher name directly instead of constructing it ourselves
  from the key exchange / authentication algorithm, symmetric encryption
  algorithm, and message authentication code algorithm.
2016-09-17 00:56:54 +00:00
Aaron Jones
dd59642de1
GNUTLS: Improve rb_get_ssl_info()
Explicitly ignore the snprintf return value and properly indent
the following line.

Also add a 'v' before the version strings so it reads as e.g.:
  library (v3.3.8), compiled (v3.3.8)
2016-09-17 00:56:54 +00:00
Aaron Jones
67d31a2755
GNUTLS: Improve rb_get_ssl_certfp()
* Give function parameters const correctness.

* Use similar variable names as the other backends -- this will reduce
  the diff between them.

* Check for more kinds of errors in retrieving the peer's certificate.

* Log failure to generate fingerprints, like the MbedTLS backend does.
2016-09-17 00:56:54 +00:00
Aaron Jones
9986455edc
GNUTLS: Log PRNG initialisation 2016-09-17 00:56:53 +00:00
Aaron Jones
2b5bf0bada
GNUTLS: Improve rb_connect_tcp_ssl() and rb_ssl_start_connected()
Use the variable name instead of its type as an argument to a sizeof
allocation. This will prevent possible future errors being introduced
when the type of the variable is changed, but the sizeof argument is
not updated.
2016-09-17 00:56:53 +00:00
Aaron Jones
f4726edf7a
GNUTLS: Fix up rb_ssl_listen()
Declare and assign variables at the same time; give function
parameters const correctness.
2016-09-17 00:56:53 +00:00
Aaron Jones
4369f1fa55
GNUTLS: Improve rb_ssl_connect_common()
This is the same as the previous commit for rb_ssl_accept_common().
2016-09-17 00:56:53 +00:00
Aaron Jones
8ebebff4b4
GNUTLS: Improve rb_ssl_accept_common()
* Add more debugging assertions

* Cancel timeouts and callbacks when handshake succeeds or hard fails

* Differentiate between kernel and library errors

* Increase F->handshake_count on handshake success

  I'm still not exactly sure what this is even used for. It may be
  removed from all backends at a later time if I find it's not being
  used for anything important, as right now it can only have the values
  0 or 1.
2016-09-17 00:56:53 +00:00
Aaron Jones
8099d352c9
GNUTLS: Store error codes properly
This is similar to commit db12df5c16 for
the MbedTLS backend.

The difference is, GNUTLS will not accept positive values as input to
gnutls_strerror(), so we invert the sign bit after retrieving the value
too, not just when storing it.

Also add a forgotten ssl_errno assignment to rb_ssl_connect_common().
2016-09-17 00:56:53 +00:00
Aaron Jones
c6600fe290
GNUTLS: Add rb_ssl_strerror() function in line with other backends 2016-09-17 00:56:53 +00:00
Aaron Jones
d70129a0d6
GNUTLS: Rework rb_init_ssl() and rb_setup_ssl_server()
I did my best to remove all possible memory leaks in the latter.
It's ugly.
2016-09-17 00:56:53 +00:00
Aaron Jones
2d01971d05
GNUTLS: Send do_ssl_handshake() to the depths from whence it came 2016-09-17 00:56:53 +00:00
Aaron Jones
4fc76590b9
GNUTLS: Rework datum loading code 2016-09-17 00:56:53 +00:00
Aaron Jones
25ecd3cc86
GNUTLS: Raise minimum group size for Diffie-Hellman-Merkle key exchange
A 2048-bit long P should really be the minimum these days.
2016-09-17 00:56:53 +00:00
Aaron Jones
5797027e9f
GNUTLS: Add dedicated socket send/recv functions
This avoids a compiler warning regarding casting a file descriptor to a
pointer (as input to gnutls_transport_set_ptr()), and also ensures that
the pointer is valid for the lifetime of the session.
2016-09-17 00:56:53 +00:00
Aaron Jones
3f32d48dab
GNUTLS: Break off TLS setup from callbacks to a dedicated function
This is in line with the other backends; eventually those callbacks
will be moved to a library-agnostic section.
2016-09-17 00:56:52 +00:00
Aaron Jones
4618ec248e
GNUTLS: Improve the connect callback logic 2016-09-17 00:56:52 +00:00
Aaron Jones
77119a5031
GNUTLS: Improve the accept callback logic 2016-09-17 00:56:52 +00:00
Aaron Jones
a41a1d20db
GNUTLS: Fix the SSL_P(x) macro
It previously assumed there was an "F" variable in the scope it was
used in. It now uses its input "x" variable.
2016-09-17 00:56:52 +00:00
Aaron Jones
5103d939d0
GNUTLS: Rename the timeout callback in line with the other backends 2016-09-17 00:56:52 +00:00
Aaron Jones
992aa93b80
GNUTLS: Tidy up rb_init_ssl() and improve its error logging 2016-09-17 00:56:52 +00:00
Aaron Jones
6cc08ecf90
GNUTLS: Move `struct ssl_connect' definition to the top of the file 2016-09-17 00:56:52 +00:00
Aaron Jones
fde101b9b2
GNUTLS: Tidy up the cert authentication callback 2016-09-17 00:56:52 +00:00
Aaron Jones
75d7d47a7e
GNUTLS: Tidy up headers 2016-09-17 00:56:52 +00:00
Aaron Jones
d9e6ff7349
GNUTLS: Tidy up unit-scope variables and give them clearer names 2016-09-17 00:56:11 +00:00
Aaron Jones
4d89c83c32
GNUTLS: Shut down sessions properly
If gnutls_bye() fails with a fatal error, we would reattempt it again
and again, even though this may then go on to e.g. cause a segmentation
fault.

Now we just keep retrying if it was interrupted, in line with the other
backends, up to a maximum of 3 retries.
2016-09-17 00:55:40 +00:00
Aaron Jones
a3a25a4c8a
MbedTLS: A few more minor changes
Yeah, I know, I said I was happy with it and wouldn't be changing it.
However, the new GNUTLS backend I'm working on has prompted this.

E.g. MbedTLS error codes and GNUTLS error codes are both negative ints,
     but GNUTLS will not tolerate positive input values. Let's treat
     both backends the same.
2016-09-17 00:11:46 +00:00
Aaron Jones
159d901e71
MbedTLS & OpenSSL: Purely cosmetic changes.
This further reduces the diff between the backends.
It does not change any of the logic in either backend.
2016-09-16 11:17:29 +00:00
William Pitcock
de78e5906a Merge pull request #219 from aaronmdjones/openssl219
Improve the OpenSSL backend
2016-09-15 21:50:48 -07:00
Aaron Jones
92c04c6b9d
OpenSSL: Final round of const correctness
I'm happy with the state of this backend now.
I don't anticipate making any further changes.
2016-09-15 20:14:01 +00:00
Aaron Jones
5feb292aa9
OpenSSL: Indicate successful RNG initialisation 2016-09-15 20:12:22 +00:00
Aaron Jones
5bb5226edc
OpenSSL: Simplify the RNG code 2016-09-15 20:12:22 +00:00
Aaron Jones
15e2cab1e5
OpenSSL: Add another debugging assert 2016-09-15 20:12:22 +00:00
Aaron Jones
01ce1c508d
OpenSSL: Add a debugging assert for timeouts 2016-09-15 20:12:22 +00:00
Aaron Jones
b4a0b60dff
OpenSSL: Cast sockaddr len variable appropriately 2016-09-15 20:12:22 +00:00
Aaron Jones
d9c825c4de
OpenSSL: Correct closing comment
[ci skip]
2016-09-15 20:12:21 +00:00
Aaron Jones
06c588e535
OpenSSL: Apply consistent coding style
[ci skip]
2016-09-15 20:12:21 +00:00
Aaron Jones
767fad345f
OpenSSL: Properly wrap long lines.
[ci skip]
2016-09-15 20:12:21 +00:00
Aaron Jones
a8db009575
OpenSSL: Modify rb_ssl_strerror() in line with other backends 2016-09-15 20:12:21 +00:00
Aaron Jones
45d05d8882
OpenSSL: Improve error logging in rb_setup_ssl_server() 2016-09-15 20:12:21 +00:00
Aaron Jones
bd8097c459
OpenSSL: Tweak connection shutdown logic 2016-09-15 20:12:21 +00:00
Aaron Jones
485b5b8084
OpenSSL: Import the callback/handshake logic from the MbedTLS backend 2016-09-15 20:12:21 +00:00
Aaron Jones
9114e3a2dc
OpenSSL: Improve rb_setup_ssl_server()
* Move file/data assignments to the top of the function

* Don't attempt to set a hardcoded P-384 ECDH key if we have the new
  SSL_CTX_set1_curves_list() function (OpenSSL 1.0.2+)

* Rename variables consistent with other backends and wrap the function
  arguments.

* Disable OpenSSL's disabling of TLS 1/n-1 record splitting.
  In other words, enable TLS 1/n-1 record splitting.

* Other misc cleanups.
2016-09-15 20:12:21 +00:00
Aaron Jones
47d51fe3ac
OpenSSL: Use C99 __func__ declaration instead of writing function names 2016-09-15 20:12:21 +00:00
Aaron Jones
cc04fbe3f9
OpenSSL: Fix up rb_init_ssl() to use proper define from openssl_ratbox.h 2016-09-15 20:12:21 +00:00
Aaron Jones
62fc0eab03
OpenSSL: Rename error functions consistent with other backends. 2016-09-15 20:12:21 +00:00
Aaron Jones
4e9441a1cb
OpenSSL: Add generic direction enum for negotiation setup.
Also define an SSL_P(x) macro as in other backends and use that to refer
to the client session context.
2016-09-15 20:12:21 +00:00
Aaron Jones
e569720fe1
OpenSSL: Misc code cleanups
Make use of C99 for loop initialisers, declarations with immediate
rvalues, etc.
2016-09-15 20:12:20 +00:00
Aaron Jones
a61e06e1d1
OpenSSL: Add const-correctness to function and variable declarations. 2016-09-15 20:12:20 +00:00
Aaron Jones
1c39c519fe
OpenSSL: Reorder functions in line with the MbedTLS backend.
The diff for this commit will look like I have changed a lot of code;
in reality, nothing was changed, just whole functions moved up or down.
2016-09-15 20:12:20 +00:00
Aaron Jones
1c7d295320
OpenSSL: Move connect structure declaration to top of file 2016-09-15 20:12:20 +00:00
Aaron Jones
8a40573369
OpenSSL: Remove context duplication
OpenSSL is perfectly capable of having a single context that is shared
by both client and server sessions alike; one simply needs to call
SSL_set_accept_state (for server) or SSL_set_connect_state (for client)
before attempting handshaking.
2016-09-15 20:12:20 +00:00
Aaron Jones
2aec9b6d68
OpenSSL: Remove unnecessary handshake info callback 2016-09-15 20:12:20 +00:00
Aaron Jones
1f30c8943b
OpenSSL: Tidy up headers
Move all the header includes to a single header file, rename said file.
2016-09-15 20:12:20 +00:00
Aaron Jones
265dc4e53c
MbedTLS: Final round of const correctness
I'm happy with the state of this backend now.
I don't anticipate making any further changes.
2016-09-15 20:10:43 +00:00
Aaron Jones
f66a6390b0
MbedTLS: More const correctness 2016-09-15 13:24:29 +00:00
Aaron Jones
101c659117
MbedTLS: Cast addrlen rb_ssl_accept_setup to avoid compiler warnings 2016-09-15 13:24:29 +00:00
Aaron Jones
1083d8557b
MbedTLS: Cast return types for reading/writing only on success 2016-09-15 13:24:29 +00:00
Aaron Jones
f0ad82013c
MbedTLS: More const correctness 2016-09-15 13:24:28 +00:00
Aaron Jones
ac62792970
MbedTLS: Correct NULL checks for functions in line with other backends 2016-09-15 13:24:28 +00:00
Aaron Jones
988fedf212
MbedTLS: Move structure cert/key assignment to after cert/key loading 2016-09-15 13:24:28 +00:00
Aaron Jones
bef81a5d45
MbedTLS: Use C99 __func__ declaration instead of writing function names 2016-09-15 13:24:28 +00:00
Aaron Jones
8cd8b24ffb
MbedTLS: Make error string printing prettier. 2016-09-15 13:24:28 +00:00
Aaron Jones
db12df5c16
MbedTLS: Store error codes properly.
OpenSSL uses `unsigned long' type for its error codes, so that's
what (lib)ratbox used to store the error values.

Unfortunately, MbedTLS uses int, and its error codes are negative.
On machines where `int' and `long' are the same size, this could
result in storing a truncated error code.

This patch inverts the sign bit on error codes and then casts them
to unsigned long for storage.

MbedTLS itself (specifically, `mbedtls_strerror()') will function
properly with negative or positive input values. It even converts
negative input values to positive before checking them against the
list of known error codes!

See also: `library/error.c' in the MbedTLS 2.1+ distribution.
2016-09-15 13:24:28 +00:00
Aaron Jones
8668cb9b9d
MbedTLS: Const correctness in rb_ssl_init_fd
We shouldn't ever change this input variable.
Tell the compiler that we won't.
2016-09-15 13:24:28 +00:00
Aaron Jones
46c61dd478
MbedTLS: Set socket send/receive functions after initialising session 2016-09-15 13:24:28 +00:00
Aaron Jones
978c8ae828
MbedTLS: Move memory allocation to the beginning of rb_ssl_init_fd 2016-09-15 13:24:28 +00:00
Aaron Jones
163a4a9d06
MbedTLS: Remove default case in switch for an enum with all values
Having default here doesn't make sense (using something not in that
enum will generate a compile-time warning).
2016-09-15 13:24:28 +00:00
Aaron Jones
5b900411bf
MbedTLS: Rename error printing function
All 3 backends (MbedTLS, OpenSSL, GNUTLS) are going to have the same
function name for returning error strings. This will help to reduce the
diffs between them.
2016-09-15 13:24:28 +00:00
Aaron Jones
295c8f7d37
MbedTLS: Tidy up headers
Move all the header includes to a single header file, rename said file.
2016-09-15 13:24:25 +00:00
Aaron Jones
354e61b4c2
README: Update location of support channel
This was done on v4 and master already, 3.5 slipped between the cracks.

[ci skip]
2016-09-15 09:45:41 +00:00
Aaron Jones
566f46785f
MbedTLS: Misc backend cleanups
* Add generic direction enum for negotiation setup.

* Rename a rather long wrapper function to a shorter one consistent with
  what it does.

* Rework context setup function.

* Don't check for handshake state before beginning handshaking.

  The old backend began a handshake and then stepped into the callback
  function if it was interrupted; the current one just jumps right into
  it, so there is no need to check if it has previously succeeded,
  because it hasn't been attempted yet.

* Add missing errno assignment to one of the handshake wrappers.

* Don't bother checking if SSL_P(F) is NULL when we already checked if
  F->ssl is NULL -- this should be impossible.

* Don't bother checking if SSL_C(F) is NULL -- this was a no-op.

* Change the socket send and recv functions to not peer into a foreign
  ratbox structure -- use the correct function to get the socket fd.

* Rewrap some lines and function arguments.

Other backends will be brought into line with this backend soon.

This will enable easier maintenance of the backends, by reducing the
diffs between them, which should make different behaviour easier to
spot.
2016-09-10 08:42:04 +00:00
Aaron Jones
2a8ec58c15
MbedTLS: Treat 0 bytes read/written to socket properly
At the moment, if a link quits in just the right (wrong [1]) way,
the quit reason will resemble:

    <-- foo (~bar@baz) has quit (Read error: (-0x0) )

This should resolve that.

[1] Peers should send a close_notify alert before abruptly shutting
    down their socket. This will result in a sane quit message:

    <-- foo (~bar@baz) has quit (Read error: (-0x7880) SSL -
    The peer notified us that the connection is going to be closed)

[ci skip]
2016-09-09 01:47:08 +00:00
William Pitcock
ee10f6cdcc rebuild configure 2016-09-05 17:33:24 -05:00
William Pitcock
50851b0b55 update NEWS for charybdis 3.5.3. 2016-09-05 17:31:49 -05:00
William Pitcock
1bc097d1ec charybdis 3.5.3. 2016-09-05 17:09:30 -05:00
William Pitcock
89d4c468b6 Merge pull request #214 from aaronmdjones/release/3.5
Fix up the MbedTLS backend
2016-09-03 10:34:43 -07:00
Aaron Jones
818a3fda94
SASL: Disallow beginning : and space anywhere in AUTHENTICATE parameter
This is a FIX FOR A SECURITY VULNERABILITY. All Charybdis users must
apply this fix if you support SASL on your servers, or unload m_sasl.so
in the meantime.
2016-09-03 17:28:41 +00:00
Aaron Jones
be31ac33d5 MbedTLS: Use correct error code for failed socket writes
This should make writing more efficient.
2016-09-02 00:28:17 +00:00
Aaron Jones
0db0805ed5 MbedTLS: Don't include the sentinel in suites count calculation 2016-09-01 20:57:07 +00:00
Aaron Jones
df51e80717 MbedTLS: Provide default list of configured ciphersuites 2016-09-01 20:47:34 +00:00
Aaron Jones
f92b4d81d4
OpenSSL: Initialise if LibreSSL
LibreSSL's definition of OPENSSL_VERSION_NUMBER bites us in the ass,
*again*.
2016-09-01 19:28:18 +00:00
Aaron Jones
6df12e8169 MbedTLS: Cleaner iteration of ciphersuite list 2016-09-01 18:18:09 +00:00
Aaron Jones
ede25e0a8a MbedTLS: Log success or failure to parse ciphersuite list 2016-08-31 22:03:42 +00:00
Aaron Jones
6f3651f8ec MbedTLS: Remove pointless no-op cast 2016-08-31 18:34:21 +00:00
Aaron Jones
b21ed5c0aa MbedTLS: Ciphersuite configuration fixes 2016-08-31 17:06:51 +00:00
Aaron Jones
42b029d0d6 MbedTLS: Preliminary attempt at ciphersuite configuration 2016-08-31 17:03:02 +00:00
Aaron Jones
6008896554
Backport ffedad8d to release/3.5 2016-08-31 14:21:16 +00:00
Aaron Jones
865e70f529
Revert "Backport c1fc044c to release/3.5"
This reverts commit c9c2d6ea12.

This commit included some as yet untested and unrelated code by mistake.
2016-08-31 14:19:43 +00:00
Aaron Jones
c2af499d4d
Backport c1fc044c to release/3.5 2016-08-31 14:15:28 +00:00
Aaron Jones
c9c2d6ea12
Backport c1fc044c to release/3.5 2016-08-31 14:13:45 +00:00
Aaron Jones
531e6323d8 MbedTLS: Explicitly ignore rb_snprintf() return value 2016-08-31 01:01:42 +00:00
Aaron Jones
036419c344 MbedTLS: Misc security improvements
As a client, require all peers (i.e. other IRC servers) to support secure
renegotiation. Break handshakes with servers that don't. We do not
renegotiate our sessions, but this is the most secure option regardless.

As a client, disable TLS Session Tickets. The server side MbedTLS code
does not have any ticket callbacks configured, so an MbedTLS IRC Server
will not issue tickets -- however, others could. Server connections are
not expected to be short-lived enough to benefit from the usage of tickets,
and their issuance harms forward secrecy.
2016-08-31 00:13:56 +00:00
Aaron Jones
cfcd4615ed README: Fix more MbedTLS casing 2016-08-30 23:39:22 +00:00
Aaron Jones
19d9c417af MbedTLS: Fix casing on opening comment block 2016-08-30 23:38:25 +00:00
Aaron Jones
f2fbec4510 MbedTLS: More const-correctness 2016-08-30 23:31:47 +00:00
Aaron Jones
f89406ac72 MbedTLS: Misc sizeof prettiness 2016-08-30 23:22:41 +00:00
Aaron Jones
c1007a93d5 MbedTLS: Move more code to appropriate section 2016-08-30 23:16:33 +00:00
Aaron Jones
3ba0923c0e MbedTLS: Move some MbedTLS-specific code to the appropriate section 2016-08-30 23:13:53 +00:00
Aaron Jones
4c9ab80f6b MbedTLS: Major restructuring
I have removed all non-MbedTLS-specific code from this backend and
copied the non-OpenSSL-specific portions of the OpenSSL backend code
over; as it seems to be more reliable.
2016-08-30 22:57:25 +00:00
Aaron Jones
07b6e728b5
OpenSSL: Initialise one context at a time
If initialising the server context fails, but the client one succeeds,
we will not only leak memory, but the error message reported for
initialising the server context might not make sense, because we
initialise the client context after and that could erase or change the
list of queued errors.

This scenario is considered rare. Nevertheless, we now initialise the
client context after *successfully* initialising the server context.
2016-08-30 10:21:46 +00:00
Aaron Jones
545668de33
Print initialisation notice before forking 2016-08-24 16:43:45 +00:00
Aaron Jones
856ecd0011
startup: fork before initialising the event subsystem
On FreeBSD 4.8, fork(2) doesn't actually behave like fork(2).

Namely, kqueue(2) descriptors are not inherited by the child.
IOW, we can't fork(2) after we get the kqueue(2) descriptor.

So we'll just have to rely on people to actually read the
server log file if they want to understand why their server
is dying during startup.
2016-08-21 22:18:52 +00:00
Aaron Jones
24ba10b6b1
Tidy up daemonisation with regard to file descriptor mess
This moves daemonisation to the end of initialisation which
vastly simplifies the reporting logic and eliminates the need
for the child to communicate to the parent.

This is a backport from the release/4 branch.
2016-08-21 00:34:38 +00:00
Aaron Jones
f70b6f55f9
TLS Backends: Harmomise the rb_ssl_get_cipher() function
The GNUTLS backend reports the version in use for the client as well
as its ciphersuite -- do the same for the other 2 backends.
2016-08-20 04:08:30 +01:00
Aaron Jones
1554951205
Prod AppVeyor into (possible) inaction. Maybe. 2016-08-19 19:59:42 +00:00
Aaron Jones
36335ea3f2
Attempt to disable AppVeyor on this branch 2016-08-19 19:48:30 +00:00
Aaron Jones
3288fc4648
GNUTLS: Fixup fingerprint generation across library versions
Also remove some unnecessary variables, e.g. write directy to the
return buffer, in line with the other backends.
2016-08-19 19:05:22 +00:00
Aaron Jones
f15a30a16f
GNUTLS: I need to wake up. Fix more. 2016-08-17 17:37:03 +00:00
Aaron Jones
b24cfd7c50
GNUTLS: Fix typo on previous commit 2016-08-17 17:27:26 +00:00
Aaron Jones
06feeb244d
GNUTLS: Avoid null derefence in constructing ciphersuite 2016-08-17 16:58:40 +00:00
Aaron Jones
897c10749d
README: Clarify that OpenSSL is not required for ECDHE 2016-08-15 10:53:23 +00:00
Aaron Jones
e5afd80775
mkpasswd: use urandom for salts, cleanup
Using /dev/random for salt generation is pointless -- it can block, and
any extra randomness it would provide (which is debatable) is not needed,
as salts only need to be unique, not unpredictable.
2016-08-15 09:49:57 +00:00
Aaron Jones
0bd2f0b710
openssl: Avoid use-after-free when rehashing fails to load new files
Commit 5c8da48 introduced a fix for issue #186 by freeing the old SSL_CTX
structure before constructing a new one, which could disconnect existing
clients otherwise.

Unfortunately, the freeing is done first, which means that if setting up
a new structure fails for any reason, there will be no usable structures
left, but they are still referenced.

This fix moves the freeing to the end of the function, using intermediate
new variables in the meantime. This problem was discovered while testing
against OpenSSL 1.1.0 RC6.
2016-08-12 13:29:02 +00:00
Aaron Jones
419f0c6af7
reference.conf: Document fingerprint generation
[ci skip]
2016-07-16 05:42:00 +00:00
Aaron Jones
e719e46d27
mbedtls backend: indicate reason for TLS session termination
[ci skip]
2016-06-12 11:32:30 +00:00
William Pitcock
82ce2ab4da CREDITS: charybdis official channel will now be on irc.charybdis.io. 2016-06-04 23:54:14 -05:00
William Pitcock
cc3e763e26 CREDITS: adjust to reflect present situation 2016-06-04 23:50:10 -05:00
Aaron Jones
03e6030ed2
openssl: More LibreSSL compatibility
LibreSSL does not have the new version macros & functions that OpenSSL
1.1.0 implements. This causes a compile-time failure against LibreSSL.

Further, the runtime function for returning the library version returns
the wrong number (the hardcoded constant number SSLEAY_VERSION_NUMBER
aka OPENSSL_VERSION_NUMBER, instead of LIBRESSL_VERSION_NUMBER).

Add more ifdef soup to remedy the situation.
2016-06-01 17:45:36 +00:00
William Pitcock
bc2eeb0992
Do not shadow OpenSSL-internal symbol "ssl_ok".
This is a backport of commit bfc44622
2016-06-01 16:32:26 +00:00
Aaron Jones
82d827469c
openssl: change how we load DH parameters
The code already assumes the presence of fopen(3) and errno, and, by
extension, fclose(3) and strerror(3), so just use those instead of the
BIO wrappers.

Additionally, don't fail to initialise if the DH file does exist but
parsing it fails, as per the pre-existing comment about them being
optional.
2016-05-25 21:53:09 +00:00
Aaron Jones
828fe03888
ircd_lexer: fix another crash with the same cause 2016-05-15 00:54:26 +00:00
Aaron Jones
f55078bdc7
ircd_lexer: fix crash with very large config option strings 2016-05-14 23:58:07 +00:00
William Pitcock
96129f7d4d charybdis 3.5.2. 2016-05-14 17:00:59 -05:00
Aaron Jones
01fdef77e6
starttls: Allow command usage with backends other than OpenSSL 2016-05-14 00:27:27 +00:00
Aaron Jones
57d3cd1159
[mbedtls] Fix up backend to allow fingerprint generation
See the comments in the newly created file for an explanation.
2016-05-04 09:09:01 +00:00
Aaron Jones
fd5af836b7
[mbedtls] Various fixes and improvements
* Move certificate, key, DH parameters and configuration to heap
  (Documentation states that setting new configuration, e.g.
   during a rehash, is unsupported while connections using that
   configuration are active)

  This is the same approach as the fix for #186

  Refcount these structures so as to not introduce a memory leak

  On rehash, it will use new structures only if there are no
  errors in constructing them

* Add better error-reporting (strings in addition to numbers)
  where possible

* Coalesce several connection memory allocations into one function

* Reduce boilerplate where possible (Charybdis targets C99)

* Support private key being in certificate file, and having no
  DH parameters file

* Correct erroneous closing comment
2016-05-04 02:12:23 +00:00
Aaron Jones
d35caf56cb
[TLS backends] Make version strings more useful and consistent 2016-05-04 00:20:07 +00:00
Aaron Jones
2a1e5de8cb
Travis CI: Build against sqlite3 library, don't autogen 2016-05-03 23:29:27 +00:00
Aaron Jones
ddc6c9a922
Add Travis CI configuration for release/3.5 branch 2016-05-03 23:23:35 +00:00
Aaron Jones
b8cf4b3bf2
[sslproc] Various fixes
* Properly allow no DH parameters (some backends come with defaults)
* If no private key is given, assume it's in the certificate file
* Use correct length calculation in buffer for TLS options
* Fix compiler warnings regarding uint64_t stats counters
2016-05-03 23:19:06 +00:00
Aaron Jones
1ea72c8f86
[ssld] Fix possible crash when DH parameters are not provided
This has ssld calling strlen() on a NULL value

[ci skip]
2016-05-03 17:48:04 +00:00
Aaron Jones
5c8da48264
Backport more TLS backend and ssld fixes & improvements from 3.6
openssl:
 * Don't manually initialise libssl 1.1.0 -- it does this automatically
 * SSL_library_init() should be called first otherwise
 * Move SSL_CTX construction to rb_setup_ssl_server()
 * Test for all required files (certificate & key) before doing anything
 * Free the old CTX before constructing a new one (Fixes #186)
 * Properly abort rb_setup_ssl_server() on CTX construction failures
 * Support ECDHE on more than one curve on OpenSSL 1.0.2 and above
 * Clean up ifdef indentation
 * Fix DH parameters memory leak

mbedtls:
 * Fix certificate fingerprint generation
 * Fix library linking order
 * Fix incorrect printf()-esque argument count
 * Return digest length for fingerprints instead of 1, consistent
   with the other backends

sslproc / ssld:
 * Fingerprint methods have no assocated file descriptors
 * Send TLS information (cipher, fingerprint) before data
 * Use correct header length for fingerprint method

Authored-by: Aaron Jones <aaronmdjones@gmail.com>
Authored-by: William Pitcock <nenolod@dereferenced.org>
Authored-by: Simon Arlott <sa.me.uk>
2016-04-30 21:39:05 +00:00
William Pitcock
1d2ba176ea
ircd: Channel.bants is not a serial but a timestamp.
Previously, the IRCd would increment bants instead of resyncing the timestamp, causing the potential of
false negatives from the bancache system.
2016-04-30 00:14:06 +00:00
Valerii Iatsko
bf9e0a6ed5 Fixed compilation w/ gnutls v3 2016-04-02 17:28:37 -05:00
William Pitcock
558bca8608 news for 3.5.1. 2016-04-02 17:22:14 -05:00
William Pitcock
db1b744e41 charybdis 3.5.1. 2016-04-02 17:21:06 -05:00
William Pitcock
18244e32f3 more ssld ipc improvements from 3.6 2016-04-02 17:20:15 -05:00
William Pitcock
987fa43982 sslproc: partial backport of 3.6 connid changes 2016-04-02 17:16:09 -05:00
William Pitcock
f76b0cee90 s_serv: ensure we use the actual assigned connid on an outbound connection 2016-04-02 17:15:01 -05:00
William Pitcock
d5ff7a9c3c ssld: do not shadow openssl-internal symbol "ssl_ok" (yeah, i know) 2016-04-02 17:12:28 -05:00
William Pitcock
1533b40304 ssld: we use uint8_t for IPC buffers, not char 2016-04-02 17:11:21 -05:00
Simon Arlott
b7cca0143d ssld: change_connid may be called with an unknown ID
If change_connid is called with an unknown ID, conn will be
NULL, check this with an assert and then respond by reporting
the new ID as closed instead of dereferencing a NULL pointer.
2016-04-02 17:11:08 -05:00
Valerii Iatsko
b1f028e5d4 ssld: fix memleak
same as r29199 ircd-ratbox:
free zlib_stream_t with the rest of the conn_t
2016-04-02 17:10:42 -05:00
Aaron Jones
56f1d769bd
Document extb_usermode module in reference.conf
Also add it to the example configuration files

[ci skip]
2016-03-28 03:34:36 +01:00
Aaron Jones
604ab13778
extensions: Fix duplicate extban character usage
extb_usermode and extb_hostmask both use the same extban character
('m'), resulting in only one of the modules being usable (depending
on module load order) and neither one functioning if one of them
is unloaded.

This changes the character for extb_usermode from 'm' to 'u'.

[ci skip]
2016-03-28 03:33:24 +01:00
William Pitcock
e3af723d23 m_cap: ensure that CAP parameters are properly initialized to zero 2016-02-28 19:08:03 -06:00
William Pitcock
e253d010ed libratbox: gnutls: add gnutls 3.4 support (closes #123) 2016-01-24 14:52:40 -05:00
98 changed files with 93265 additions and 35 deletions

58
.travis.yml Normal file
View file

@ -0,0 +1,58 @@
# Travis-CI Build for charybdis-3.5
# see travis-ci.org for details
language: c
# Use the faster container-based infrastructure.
sudo: false
matrix:
include:
- os: linux
compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['gcc-4.8', 'automake', 'autoconf', 'libtool', 'shtool', 'libsqlite3-dev', 'python-sphinx', 'texinfo']
env: COMPILER=gcc-4.8
- os: linux
compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['gcc-4.9', 'automake', 'autoconf', 'libtool', 'shtool', 'libsqlite3-dev', 'python-sphinx', 'texinfo']
env: COMPILER=gcc-4.9
- os: linux
compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['gcc-5', 'automake', 'autoconf', 'libtool', 'shtool', 'libsqlite3-dev', 'python-sphinx', 'texinfo']
env: COMPILER=gcc-5
- os: linux
compiler: clang
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7']
packages: ['clang-3.7', 'automake', 'autoconf', 'libtool', 'shtool', 'libsqlite3-dev', 'python-sphinx', 'texinfo']
env: COMPILER=clang-3.7
- os: osx
compiler: clang
env: COMPILER=clang LIBTOOLIZE=glibtoolize
osx_image: xcode7.3
cache:
apt:
ccache:
script:
- CC=$COMPILER ./configure --with-shared-sqlite
- make -j4
- make install
- "if [ ${TRAVIS_OS_NAME} != 'osx' ]; then make -C doc/oper-guide html man info; fi"

43
CREDITS
View file

@ -1,3 +1,45 @@
<<<<<<< .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
network configurations.
The Charybdis core team, listed in nick-alphabetical order:
amdj, Aaron Jones <aaronmdjones -at- gmail.com>
Elizafox, Elizabeth Myers <elizabeth -at- interlinked.me>
jilles, Jilles Tjoelker <jilles -at- stack.nl>
kaniini, William Pitcock <nenolod -at- dereferenced.org>
mr_flea, Keith Buck <mr_flea -at- esper.net>
Simon, Simon Arlott <charybdis -at- uuid.uk>
The following people are also project members, listed in nick-alphabetical
order:
grawity, Mantas Mikulėnas <grawity -at- gmail.com>
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>
dwr, Valery Yatsko <dwr -at- shadowircd.net>
Elizacat, Elizabeth Myers <elizabeth -at- interlinked.me>
Entrope, Michael Poole <mdpoole -at- trolius.org>
gxti, Michael Tharp <gxti -at- partiallystapled.com>
mniip <mniip -at- mniip.com>
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>
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
@ -26,3 +68,4 @@ 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

110
NEWS.md
View file

@ -1,5 +1,114 @@
# News
<<<<<<< .merge_file_h36DbE
This is charybdis 3.5.7, Copyright (c) 2005-2019 Charybdis team.
See LICENSE for licensing details (GPL v2).
## charybdis-3.5.7
This is primarily a bugfix release.
### user
- modules/m_sasl.c: don't process messages if SASL has been aborted
- src/s_user.c: don't corrupt usermodes on module unload/reload
### misc
- modules/m_list.c: add fake /LIST reply output to help fight spambots
## charybdis-3.5.6
This is primarily a bugfix release.
### security
- doc/reference.conf: clarify: TLS server fingerprints are not optional
- extensions/extb_ssl.c: add support for matching fingerprints
- libratbox/src/mbedtls.c: check public/private keys match
- libratbox/src/mbedtls.c: support ChaCha20-Poly1305 by default
### user
- libratbox/src/commio.c: fix accept() for IPv6 after dropping IPv4
- src/client.c: don't delete servers from the client hash table
- src/s_user.c: don't send fake MODE for clients with CHGHOST support
- modules/m_sasl.c: abort session if we receive '*' as data
- modules/m_sasl.c: check agent is present after every client exit
### misc
- configure: adjust dlopen/dlsym checks to work under libasan
- configure: allow exact PID file prefix to be specified
- doc/: convert SGML oper guide to RST
- doc/: point users to HELP EXTBAN for inline help
- extensions/m_webirc.c: set sockhost before using it to set host
## charybdis-3.5.5
This is a minor bugfix release only
### misc
- GNUTLS: Initialise a variable before trying to load server certificates
- GNUTLS: Log why certificate fingerprint generation fails
- GNUTLS: Avoid using new tokens in the default priority string
## charybdis-3.5.4
### security
- Disable TLSv1.0 in all backends
- Fix possible NULL dereference in mkpasswd
- Backport SubjectPublicKeyInfo certificate digest methods from version 4
- Backport REHASH SSLD functionality from version 4
- This allows new ssld processes to be started (to inherit a new or upgraded TLS backend
library) without dropping any existing clients or active server links
### misc
- Various memory leak fixes in newconf, sslproc, zlib
- Fix crash bug when performing /whois on someone half-way through a CHALLENGE
- Fix crash bug when performing remote MODRESTART command
- Allow extban matching presence in secret (+s) channels
## charybdis-3.5.3
### security
- incorporate all relevant security patches for charybdis through 6th September 2016:
- fix issue allowing EXTERNAL authentications to be spoofed using a certificate not actually
held by the authenticating user
### misc
- mbedtls TLS backend improvements from charybdis 4 and 5:
- add support for configurable ciphersuites
- disable legacy (SSLv2) renegotiation support if possible
- disable session tickets if possible
- general robustness improvements
- gnutls TLS backend improvements from charybdis 4:
- make certfp support more reliable on newer gnutls versions
- avoid possible null dereference when constructing ciphersuites
- openssl TLS backend improvements from charybdis 4:
- avoid a possible use-after-free issue when newer openssl versions cannot load keypairs in a rehash
- improve compatibility with libressl
- more robustly load DH parameters files
- daemonization improvements from charybdis 4
## charybdis-3.5.2
### user
- Allow IRCv3.1 STARTTLS to work with other SSL backends besides OpenSSL.
- Fix an edge case regression involving channel ban cache that was introduced in 3.5.0.
### misc
- Ensure ssld does not crash when DH parameters are not provided.
- mbedtls TLS backend improvements from charybdis 4:
- add support for CertFP
- provide personalization data for the PRNG
- fix library linking order
- openssl TLS backend improvements from charybdis 4:
- do not manually initialise openssl when running with OpenSSL 1.1.0 or later
- support ECDHE on more than one curve on OpenSSL 1.0.2 and above
- fix DH parameters memory leak
- free the old TLS context before constructing a new one (#186)
## charybdis-3.5.1
### misc
- Backport various ssld IPC improvements from master.
=======
This is solanum 1.0-dev.
See LICENSE for licensing details (GPL v2).
@ -197,6 +306,7 @@ bolded warnings in the full release notes below.
- 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

View file

@ -60,21 +60,38 @@ See `./configure --help` for build options.
* 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).
# 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).
# tips
* 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.

16
aclocal.m4 vendored Normal file
View file

@ -0,0 +1,16 @@
# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
# Copyright (C) 1996-2017 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
m4_include([m4/charybdis.m4])
m4_include([m4/pkg.m4])

2
appveyor.yml Normal file
View file

@ -0,0 +1,2 @@
except:
- release/3.5

View file

@ -236,10 +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)
@ -281,10 +285,14 @@ setup_signals(void)
}
<<<<<<< .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];
@ -310,8 +318,7 @@ main(int argc, char *argv[])
rsdb_init(db_error_cb);
check_schema();
rb_helper_loop(bandb_helper, 0);
return 0;
/* UNREACHABLE */
}
static void

View file

@ -141,7 +141,7 @@ main(int argc, char *argv[])
{
case 'h':
print_help(EXIT_SUCCESS);
break;
/* noreturn call above, this is unreachable */
case 'i':
flag.none = false;
flag.import = true;
@ -861,8 +861,8 @@ bt_smalldate(const char *string)
/**
* you are here ->.
*/
void
print_help(int i_exit)
static void
print_help(const int i_exit)
{
fprintf(stderr, "bantool v.%s - the solanum database tool.\n", BT_VERSION);
fprintf(stderr, "Copyright (C) 2008 Daniel J Reidy <dubkat@gmail.com>\n");
@ -892,5 +892,6 @@ print_help(int i_exit)
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");
exit(i_exit);
}

11453
configure vendored Executable file

File diff suppressed because it is too large Load diff

View file

@ -12,9 +12,13 @@ AC_GNU_SOURCE
AC_PROG_CC_C99
<<<<<<< .merge_file_E9kQwr
AC_INIT([charybdis], [3.5.7])
=======
if test x"$ac_cv_prog_cc_c99" = "xno"; then
AC_ERROR([solanum requires a C99 capable compiler])
fi
>>>>>>> .merge_file_knjbyY
AC_PREFIX_DEFAULT($HOME/ircd)
AC_CONFIG_MACRO_DIR([m4])
@ -114,7 +118,6 @@ AS_IF([test "x$enable_fhs_paths" = "xyes"],
pkglibdir='${libdir}/${PACKAGE_TARNAME}'
AC_SUBST([pkglibdir])
AC_SUBST([rundir])
AC_SUBST([pkgrundir])
AC_SUBST([pkglocalstatedir])
AC_DEFINE_DIR([PKGLOCALSTATEDIR], [pkglocalstatedir], [[Directory in which to store state, such as ban database]])
AC_SUBST([pkglibexecdir])
@ -392,21 +395,40 @@ AC_ARG_WITH(moduledir,
AC_DEFINE_DIR(MODULE_DIR, moduledir, [Prefix where modules are installed.])
AC_SUBST_DIR([moduledir])
dnl **********************************************************************
dnl Check for --with-rundir
dnl **********************************************************************
AC_MSG_CHECKING([whether or modify rundir])
AC_MSG_CHECKING([whether to modify rundir])
AC_ARG_WITH([rundir],
[AC_HELP_STRING([--with-rundir=DIR],
[Directory in which to store pidfile.])],
[Directory to use as prefix for pidfile.])],
[AC_MSG_RESULT([yes])
rundir=`echo $withval | sed 's/\/$//'`],
[AC_MSG_RESULT([no])
AS_IF([test "x$enable_fhs_paths" = "xyes"],
[rundir='${prefix}/run'],
[rundir='${sysconfdir}'])])
AC_SUBST([rundir])
dnl **********************************************************************
dnl Check for --with-pkgrundir
dnl **********************************************************************
AC_MSG_CHECKING([whether to modify pkgrundir])
AC_ARG_WITH([pkgrundir],
[AC_HELP_STRING([--with-pkgrundir=DIR],
[Directory in which to store pidfile.])],
[AC_MSG_RESULT([yes])
pkgrundir=`echo $withval | sed 's/\/$//'`],
[AC_MSG_RESULT([no])])
AC_SUBST([pkgrundir])
AC_DEFINE_DIR([PKGRUNDIR], [pkgrundir], [Directory to store pidfile in.])
dnl **********************************************************************
dnl Check for --with-program-prefix
dnl **********************************************************************
dnl Installed utility program prefixes (does not affect binaries
dnl installed into pkglibexecdir)
AC_MSG_CHECKING([for program prefix])
@ -443,8 +465,16 @@ AC_HELP_STRING([--with-custom-version=NAME],
AC_MSG_RESULT([no])]
)
if git rev-parse --git-dir > /dev/null 2>&1; then
GITSHA=$(git rev-parse --short HEAD)
else
GITSHA="unknown"
fi
AC_DEFINE_UNQUOTED(BRANDING_NAME, ["$BRANDING_NAME"], [Custom branding name.])
AC_DEFINE_UNQUOTED(BRANDING_VERSION, ["$BRANDING_VERSION"], [Custom branding name.])
AC_DEFINE_UNQUOTED(BRANDING_VERSION, ["${BRANDING_VERSION}-${GITSHA}"], [Custom branding name.])
if test "x$BRANDING_NAME" != "x$PACKAGE_NAME"; then
AC_DEFINE(CUSTOM_BRANDING, 1, [Define if custom branding is enabled.])
@ -544,12 +574,135 @@ AC_DEFINE_UNQUOTED(TOPICLEN, ${TOPICLEN}, [Maximum topic length (<=390)])
AC_DEFINE_UNQUOTED(NICKLEN, (${NICKLEN}+1), [Nickname length])
<<<<<<< .merge_file_E9kQwr
dnl Second stage: check for functions and headers.
if test "$shared_modules" = yes; then
DYNLINK_C=dynlink.c
AC_CHECK_HEADERS(dlfcn.h)
AC_SEARCH_LIBS(shl_load, dld,
[
AC_DEFINE(HAVE_SHL_LOAD, 1, [Define if the shl_load function is available.])
SUFFIX=".sl"
MOD_TARGET=hpux_shared
SEDOBJ="s/\.o/.sl/g"
],
dnl !shl_load:
[
dnl standard dlopen
AC_SEARCH_LIBS(dlopen, [dl c_r],
[
AC_SEARCH_LIBS(dlsym, [dl c_r],
[
if
test "$ac_cv_search_dlopen" != "none required" &&
test "$ac_cv_search_dlsym" != "none required" &&
test "$ac_cv_search_dlopen" != "$ac_cv_search_dlsym"; then
AC_MSG_WARN([dlopen and dlsym from different sources])
fi
AC_DEFINE(HAVE_DLOPEN, 1, [Define if the dlopen function is available.])
SUFFIX=".so"
MOD_TARGET=shared_modules
SEDOBJ="s/\.o/.so/g"
if test "$AppleGCC" = yes; then
AC_CHECK_HEADERS([mach-o/dyld.h])
fi
AC_CHECK_FUNCS(dlfunc)
],
[
shared_modules=no
])
],
[
shared_modules=no
])
])
fi
AC_DEFINE_UNQUOTED(SHARED_SUFFIX, "$SUFFIX", [Suffix for shared libraries on this platform.])
dnl Third stage - wrangling the linker.
if test "$shared_modules" = yes; then
# The GNU linker requires the -export-dynamic option to make
# all symbols visible in the dynamic symbol table.
hold_ldflags=$LDFLAGS
AC_MSG_CHECKING(for the ld -export-dynamic flag)
LDFLAGS="${LDFLAGS} -Wl,-export-dynamic -Werror"
AC_LINK_IFELSE(AC_LANG_PROGRAM([],[int i;]), found=yes, found=no)
LDFLAGS=$hold_ldflags
if expr "`uname -s`" : ^IRIX >/dev/null 2>&1; then
found="no, IRIX ld uses -B,dynamic"
LDFLAGS="${LDFLAGS} -Wl,-B,dynamic"
fi
if expr "`uname -s`" : ^AIX >/dev/null 2>&1; then
found="no, AIX ld uses -G -brtl"
LDFLAGS="${LDFLAGS} -Wl,-G,-brtl"
fi
AC_MSG_RESULT($found)
if test "$found" = yes; then
LDFLAGS="${LDFLAGS} -Wl,-export-dynamic"
fi
AC_MSG_CHECKING(for compiler option to produce PIC)
dnl The order should be here to check for groups of compilers,
dnl then for odd compilers, then if no PICFLAGS were set up,
dnl check for GCC and set defaults, or else error. -jmallett
if test "$SGS" = "yes"; then
AC_MSG_RESULT([SVR4 SGS interfaces: -KPIC -DPIC -G])
PICFLAGS="-KPIC -DPIC -G"
fi
if test "$AppleGCC" = "yes"; then
AC_MSG_RESULT([Darwin Mach-O bundles: -fno-common -bundle -flat_namespace -undefined suppress])
PICFLAGS="-fno-common -bundle -flat_namespace -undefined suppress"
fi
dnl Please note, that on HPUX two different stages of module compilation occurs, since
dnl while compiling modules, the compiler does not allow you to give arguments
dnl to the linker. (I did not design this)
dnl So we need -c in the first stage of module compilation.
dnl In the second stage, we link the modules via ld -b.
dnl Additionally, HPUX does not like -export-dynamic, it likes -E instead.
dnl -TimeMr14C
if test "$HPUX" = "yes" -a "$CC" != gcc; then
AC_MSG_RESULT(HP-UX cc: +z -r -q -n)
PICFLAGS="+z -r -q -n -c"
AC_MSG_CHECKING([if +ESfic is required on this platform])
if expr "`$CC +ESfic 2>&1`" : ".*neither supported.*" >/dev/null; then
AC_MSG_RESULT(no)
else
AC_MSG_RESULT(yes)
PICFLAGS="$PICFLAGS +ESfic"
fi
LDFLAGS="${LDFLAGS} -Wl,-E"
fi
if test "$Tru" = yes -a "$CC" != gcc; then
AC_MSG_RESULT([Tru64: -shared -expect_unresolved '*'])
PICFLAGS="-shared -expect_unresolved '*' "
LDFLAGS="-call_shared"
fi
if test -z "$PICFLAGS"; then
if test "$ac_cv_c_compiler_gnu" = "yes"; then
AC_MSG_RESULT(gcc: -fPIC -DPIC -shared)
PICFLAGS="-fPIC -DPIC -shared"
else
AC_MSG_RESULT(no)
shared_modules=no
fi
fi
fi
=======
AC_ARG_WITH(asan,
AC_HELP_STRING([--with-asan],[Build with Address Sanitizer]),
[
CFLAGS="$CFLAGS -fsanitize=address"
LDFLAGS="$LDFLAGS -fsanitize=address"
])
>>>>>>> .merge_file_knjbyY
# rpath, for finding librb.so at run time
hold_ldflags=$LDFLAGS

26
default.nix Normal file
View file

@ -0,0 +1,26 @@
{ stdenv, bash
, flex, bison
, openssl, gnutls, zlib }:
stdenv.mkDerivation {
pname = "charybdis";
version = "3.5.7";
src = ./.;
patches = [
./patches/bandb-remove-setenv.patch
];
configureFlags = [
"--enable-epoll"
"--enable-ipv6"
"--with-zlib-path=${zlib.dev}/lib"
"--enable-openssl=${openssl.dev}"
"--with-program-prefix=charybdis-"
"--sysconfdir=/etc/charybdis"
];
nativeBuildInputs = [ bison flex ];
buildInputs = [ openssl gnutls zlib ];
}

51
doc/ircd.conf.example Normal file → Executable file
View file

@ -8,6 +8,33 @@
*/
/* Extensions */
<<<<<<< .merge_file_MAZNsP
#loadmodule "extensions/chm_operonly_compat.so";
#loadmodule "extensions/chm_quietunreg_compat.so";
#loadmodule "extensions/chm_sslonly_compat.so";
#loadmodule "extensions/createauthonly.so";
#loadmodule "extensions/extb_account.so";
#loadmodule "extensions/extb_canjoin.so";
#loadmodule "extensions/extb_channel.so";
#loadmodule "extensions/extb_combi.so";
#loadmodule "extensions/extb_extgecos.so";
#loadmodule "extensions/extb_hostmask.so";
#loadmodule "extensions/extb_oper.so";
#loadmodule "extensions/extb_realname.so";
#loadmodule "extensions/extb_server.so";
#loadmodule "extensions/extb_ssl.so";
#loadmodule "extensions/extb_usermode.so";
#loadmodule "extensions/hurt.so";
#loadmodule "extensions/m_findforwards.so";
#loadmodule "extensions/m_identify.so";
#loadmodule "extensions/no_oper_invis.so";
#loadmodule "extensions/sno_farconnect.so";
#loadmodule "extensions/sno_globalkline.so";
#loadmodule "extensions/sno_globaloper.so";
#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";
@ -33,6 +60,7 @@
#loadmodule "extensions/sno_globaloper";
#loadmodule "extensions/override";
#loadmodule "extensions/no_kill_services";
>>>>>>> .merge_file_DV7Blq
/*
* IP cloaking extensions: use ip_cloaking_4.0
@ -530,6 +558,14 @@ alias "MS" {
target = "MemoServ";
};
/*
fakechannel "#honeypot" {
topic = "Come in";
users_min = 50;
users_max = 300;
};
*/
general {
hide_error_messages = opers;
hide_spoof_ips = yes;
@ -607,6 +643,7 @@ general {
caller_id_wait = 1 minute;
pace_wait_simple = 1 second;
pace_wait = 10 seconds;
listfake_wait = 180 seconds;
short_motd = no;
ping_cookie = no;
connect_timeout = 30 seconds;
@ -638,3 +675,17 @@ modules {
path = "modules";
path = "modules/autoload";
};
/*
vhost "selfsigned.hades.arpa" {
ssl_private_key = "etc/selfssl.key";
ssl_cert = "etc/selfssl.pem";
};
vhost "oldca.hades.arpa" {
ssl_private_key = "etc/oldssl.key";
ssl_cert = "etc/oldssl2.pem";
ssl_dh_params = "etc/olddh.pem";
ssl_cipher_list = "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL";;
};
*/

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,9 +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
~~~~~~~~~~~~~
@ -449,6 +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.
@ -477,8 +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**

110
doc/reference.conf Normal file → Executable file
View file

@ -47,6 +47,69 @@
* 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
* Emulates channel mode +-O (oper only) (+-iI $o) -- chm_operonly_compat.so
* Emulates channel mode +-R (quiet unreg) (+-q $~a) -- chm_quietunreg_compat.so
* Emulates channel mode +-S (ssl only) (+-b $~z) -- chm_sslonly_compat.so
* Restrict channel creation to logged in users -- createauthonly.so
* Account bans (+b $a[:mask]) -- extb_account.so
* Banned from another channel (+b $j:mask) -- extb_canjoin.so
* Other-channel bans (+b $c:mask) -- extb_channel.so
* Combination extbans -- extb_combi.so
* Extended ban (+b $x:mask) -- extb_extgecos.so
* Hostmask bans (for combination extbans) -- extb_hostmask.so
* Oper bans (+b $o) -- extb_oper.so
* Realname (gecos) bans (+b $r:mask) -- extb_realname.so
* Server bans (+b $s:mask) -- extb_server.so
* SSL bans (+b $z) -- extb_ssl.so
* User mode bans (+b $u:modes) -- extb_usermode.so
* HURT system -- hurt.so
* New host mangling (umode +x) -- ip_cloaking_4.0.so
* Old host mangling (umode +h) -- ip_cloaking.so
* Find channel forwards -- m_findforwards.so
* /identify support -- m_identify.so
* Opers cannot be invisible (umode +i) -- no_oper_invis.so
* Far connection notices (snomask +F) -- sno_farconnect.so
* Remote k/d/x line active notices -- sno_globalkline.so
* Remote oper up notices -- sno_globaloper.so
* /whois notifications (snomask +W) -- sno_whois.so
* Oper-override (modehacking only) -- override.so
* Stop services kills -- no_kill_services.so
*/
#loadmodule "extensions/chm_adminonly.so";
#loadmodule "extensions/chm_operonly.so";
#loadmodule "extensions/chm_sslonly.so";
#loadmodule "extensions/chm_operonly_compat.so";
#loadmodule "extensions/chm_quietunreg_compat.so";
#loadmodule "extensions/chm_sslonly_compat.so";
#loadmodule "extensions/createauthonly.so";
#loadmodule "extensions/extb_account.so";
#loadmodule "extensions/extb_canjoin.so";
#loadmodule "extensions/extb_channel.so";
#loadmodule "extensions/extb_combi.so";
#loadmodule "extensions/extb_extgecos.so";
#loadmodule "extensions/extb_hostmask.so";
#loadmodule "extensions/extb_oper.so";
#loadmodule "extensions/extb_realname.so";
#loadmodule "extensions/extb_server.so";
#loadmodule "extensions/extb_ssl.so";
#loadmodule "extensions/extb_usermode.so";
#loadmodule "extensions/hurt.so";
#loadmodule "extensions/ip_cloaking_4.0.so";
#loadmodule "extensions/ip_cloaking.so";
#loadmodule "extensions/m_findforwards.so";
#loadmodule "extensions/m_identify.so";
#loadmodule "extensions/no_oper_invis.so";
#loadmodule "extensions/sno_farconnect.so";
#loadmodule "extensions/sno_globalkline.so";
#loadmodule "extensions/sno_globaloper.so";
#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
@ -112,6 +175,7 @@
#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 {
@ -145,6 +209,12 @@ 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 (and optionally key) for our ssl server */
ssl_cert = "etc/ssl.pem";
@ -1014,6 +1084,14 @@ alias "MS" {
target = "MemoServ";
};
/*
fakechannel "#honeypot" {
topic = "Come in";
users_min = 50;
users_max = 300;
};
*/
/* The general block contains many of the options that were once compiled
* in options in config.h. The general block is read at start time.
*/
@ -1316,6 +1394,9 @@ general {
*/
pace_wait = 10 seconds;
/* listfake_wait: time until real list command can be used */
listfake_wait = 180 seconds;
/* short motd: send clients a notice telling them to read the motd
* instead of forcing a motd to clients who may simply ignore it.
*/
@ -1465,6 +1546,20 @@ 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)
*
* To generate a SPKI SHA-256 fingerprint, run the following:
* $ openssl x509 -pubkey -noout -in your.crt | openssl pkey -pubin -outform DER | \
* sha256sum | sed -r -e 's/^/SPKI:SHA2-256:/'
*
* To generate a SPKI SHA-512 fingerprint, run the following:
* $ openssl x509 -pubkey -noout -in your.crt | openssl pkey -pubin -outform DER | \
* 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.
@ -1490,6 +1585,7 @@ general {
* requires extensions/drain to be loaded.
*/
drain_reason = "This server is not accepting connections.";
>>>>>>> .merge_file_Mh5Whq
};
modules {
@ -1502,3 +1598,17 @@ modules {
/* module: the name of a module to load on startup/rehash */
#module = "some_module";
};
/*
vhost "selfsigned.hades.arpa" {
ssl_private_key = "etc/selfssl.key";
ssl_cert = "etc/selfssl.pem";
};
vhost "oldca.hades.arpa" {
ssl_private_key = "etc/oldssl.key";
ssl_cert = "etc/oldssl2.pem";
ssl_dh_params = "etc/olddh.pem";
ssl_cipher_list = "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL";
};
*/

View file

@ -1,5 +1,9 @@
/* SSL extban type: matches ssl users */
/* This file is available under the same conditions as the rest of
https://github.com/asterIRC/ircd-chatd, and by extension, the rest
of Charybdis. */
#include "stdinc.h"
#include "modules.h"
#include "client.h"
@ -11,7 +15,11 @@ static int _modinit(void);
static void _moddeinit(void);
static int eb_ssl(const char *data, struct Client *client_p, struct Channel *chptr, long mode_type);
<<<<<<< .merge_file_utDAI3
DECLARE_MODULE_AV1(extb_ssl, _modinit, _moddeinit, NULL, NULL, NULL, "1.05");
=======
DECLARE_MODULE_AV2(extb_ssl, _modinit, _moddeinit, NULL, NULL, NULL, NULL, NULL, extb_desc);
>>>>>>> .merge_file_lvPLfm
static int
_modinit(void)
@ -28,13 +36,17 @@ _moddeinit(void)
}
static int eb_ssl(const char *data, struct Client *client_p,
struct Channel *chptr, long mode_type)
struct Channel *chptr, long mode_type)
{
(void)chptr;
(void)mode_type;
<<<<<<< .merge_file_utDAI3
if (! IsSSLClient(client_p))
=======
if (!IsSecureClient(client_p))
>>>>>>> .merge_file_lvPLfm
return EXTBAN_NOMATCH;
if (data != NULL)

View file

@ -197,9 +197,17 @@ mo_hurt(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
}
if (parc == 3)
expire = NULL, ip = parv[1], reason = parv[2];
{
expire = NULL;
ip = parv[1];
reason = parv[2];
}
else
expire = parv[1], ip = parv[2], reason = parv[3];
{
expire = parv[1];
ip = parv[2];
reason = parv[3];
}
if (!expire)
expire_time = HURT_DEFAULT_EXPIRE;

View file

@ -76,7 +76,10 @@ static const char *expand_xline(const char *mask)
while (*p != '\0')
{
if (*p == ' ')
*q++ = '\\', *q++ = 's';
{
*q++ = '\\';
*q++ = 's';
}
else
*q++ = *p;
p++;

View file

@ -87,6 +87,8 @@ mr_webirc(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
const char *encr;
struct rb_sockaddr_storage addr;
<<<<<<< .merge_file_65X4Nj
=======
int secure = 0;
if (source_p->flags & FLAGS_SENTUSER || !EmptyString(source_p->name))
@ -94,6 +96,7 @@ mr_webirc(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
exit_client(client_p, source_p, &me, "WEBIRC may not follow NICK/USER");
}
>>>>>>> .merge_file_ryG7XZ
aconf = find_address_conf(client_p->host, client_p->sockhost,
IsGotId(client_p) ? client_p->username : "webirc",
IsGotId(client_p) ? client_p->username : "webirc",
@ -140,6 +143,8 @@ mr_webirc(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
}
source_p->localClient->ip = addr;
<<<<<<< .merge_file_65X4Nj
=======
source_p->username[0] = '\0';
ClearGotId(source_p);
@ -163,6 +168,7 @@ mr_webirc(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
{
ClearSecure(source_p);
}
>>>>>>> .merge_file_ryG7XZ
rb_inet_ntop_sock((struct sockaddr *)&source_p->localClient->ip, source_p->sockhost, sizeof(source_p->sockhost));

View file

@ -19,7 +19,10 @@ Unless noted below, all types can be used with +b, +q, +e and +I.
$a:<mask> - Matches users logged in with a username matching the mask
(* and ? wildcards)
$c:<chan> - Matches users who are on the given channel
<<<<<<< .merge_file_IbT0MO
=======
$g:<mask> - Matches as a normal ban but excludes logged in users
>>>>>>> .merge_file_pGDMRH
$o - Matches opers (most useful with +I)
$r:<mask> - Matches users with a realname (gecos) matching the mask
(* and ? wildcards); this can only be used with +b and +q
@ -29,4 +32,5 @@ Unless noted below, all types can be used with +b, +q, +e and +I.
channel
$x:<mask> - Bans all users with matching nick!user@host#gecos
$z - Matches all SSL users
$z:<data> - Matches all SSL users with a fingerprint matching the data

View file

@ -31,7 +31,10 @@ X f - Shows File Descriptors
* q - Shows temporary and global resv'd nicks and channels
* Q - Shows resv'd nicks and channels
* r - Shows resource usage by ircd
<<<<<<< .merge_file_9l1jJa
=======
* s - Shows secure blocks
>>>>>>> .merge_file_OEoqTz
X S - Shows ssld processes
* t - Shows generic server stats
u - Shows server uptime

View file

@ -99,10 +99,18 @@ extern int testing_conf;
extern struct ev_entry *check_splitmode_ev;
<<<<<<< .merge_file_iW7mBk
extern int ircd_ssl_ok;
extern int ircd_zlib_ok;
extern int maxconnections;
extern void rehash_ulimit();
=======
extern bool ircd_ssl_ok;
extern bool ircd_zlib_ok;
extern int maxconnections;
>>>>>>> .merge_file_fQC2Ek
void ircd_shutdown(const char *reason) __attribute__((noreturn));
#endif

View file

@ -37,7 +37,11 @@ struct lgetopt
extern struct lgetopt myopts[];
<<<<<<< .merge_file_v0j8Uc
void parseargs(int *, char ***, struct lgetopt *);
=======
void usage(const char *) __attribute__((noreturn));
void parseargs(int *, char * const **, struct lgetopt *);
>>>>>>> .merge_file_OM6tzi
#endif /* __GETOPT_H_INCLUDED__ */

View file

@ -39,7 +39,12 @@ extern void mod_add_cmd(struct Message *msg);
extern void mod_del_cmd(struct Message *msg);
extern char *reconstruct_parv(int parc, const char *parv[]);
<<<<<<< .merge_file_8Ju36V
extern struct Dictionary *alias_dict;
extern struct Dictionary *fakechannel_dict;
=======
extern rb_dictionary *alias_dict;
extern rb_dictionary *cmd_dict;
>>>>>>> .merge_file_g15suK
#endif /* INCLUDED_parse_h_h */

View file

@ -204,7 +204,11 @@ struct config_file_entry
int operspy_admin_only;
int pace_wait;
int pace_wait_simple;
<<<<<<< .merge_file_Ey8dam
int listfake_wait;
=======
int ping_warn_time;
>>>>>>> .merge_file_WzePKN
int short_motd;
int no_oper_flood;
int hide_server;
@ -340,6 +344,16 @@ struct alias_entry
int flags; /* reserved for later use */
};
struct fakechannel_entry
{
char *name;
char *topic;
int users_min;
int users_max;
};
/* All variables are GLOBAL */
extern struct config_file_entry ConfigFileEntry; /* defined in ircd.c */
extern struct config_channel_entry ConfigChannel; /* defined in channel.c */

View file

@ -52,6 +52,7 @@ extern rb_dlink_list xline_conf_list;
extern rb_dlink_list resv_conf_list;
extern rb_dlink_list nd_list;
extern rb_dlink_list tgchange_list;
extern rb_dlink_list vhost_conf_list;
extern struct _rb_patricia_tree_t *tgchange_tree;
@ -255,5 +256,16 @@ extern void add_nd_entry(const char *name);
extern void free_nd_entry(struct nd_entry *);
extern unsigned long get_nd_count(void);
#endif
struct vhost_conf
{
char *hostname;
char *ssl_private_key;
char *ssl_cert;
char *ssl_dh_params;
char *ssl_cipher_list;
rb_dlink_node node;
};
extern struct vhost_conf *make_vhost_conf(void);
extern void free_vhost_conf(struct vhost_conf *);
#endif

View file

@ -25,7 +25,12 @@
#ifndef INCLUDED_s_user_h
#define INCLUDED_s_user_h
<<<<<<< .merge_file_TICs6q
#include "config.h"
#include "ircd_defs.h"
=======
#include "defaults.h"
>>>>>>> .merge_file_R44nIw
struct Client;
struct User;
@ -45,7 +50,8 @@ extern void introduce_client(struct Client *client_p, struct Client *source_p,
struct User *user, const char *nick, int use_euid);
extern void change_nick_user_host(struct Client *target_p, const char *nick, const char *user,
const char *host, int newts, const char *format, ...);
const char *host, int newts, const char *format, ...)
AFP(6, 7);
extern int user_modes[256];
extern unsigned int find_umode_slot(void);

View file

@ -33,6 +33,17 @@ enum ssld_status {
void init_ssld(void);
void restart_ssld(void);
<<<<<<< .merge_file_CConFf
int start_ssldaemon(int count, const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list);
ssl_ctl_t *start_ssld_accept(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
ssl_ctl_t *start_ssld_connect(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
void start_zlib_session(void *data);
void send_new_ssl_certs(const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list, const int method, const char *hostname);
void send_remove_ssl_vhost(const char *hostname);
void ssld_decrement_clicount(ssl_ctl_t *ctl);
int get_ssld_count(void);
void ssld_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum ssld_status status), void *data);
=======
int start_ssldaemon(int count);
ssl_ctl_t *start_ssld_accept(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
ssl_ctl_t *start_ssld_connect(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
@ -41,6 +52,6 @@ void ssld_update_config(void);
void ssld_decrement_clicount(ssl_ctl_t *ctl);
int get_ssld_count(void);
void ssld_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum ssld_status status, const char *version), void *data);
>>>>>>> .merge_file_pjqFeX
#endif

886
libratbox/Makefile.in Normal file
View file

@ -0,0 +1,886 @@
# Makefile.in generated by automake 1.15.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2017 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
$(am__configure_deps) $(am__DIST_COMMON)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno config.status.lineno
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/libratbox_config.h
CONFIG_CLEAN_FILES = libratbox.pc
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
ctags-recursive dvi-recursive html-recursive info-recursive \
install-data-recursive install-dvi-recursive \
install-exec-recursive install-html-recursive \
install-info-recursive install-pdf-recursive \
install-ps-recursive install-recursive installcheck-recursive \
installdirs-recursive pdf-recursive ps-recursive \
tags-recursive uninstall-recursive
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
test -z "$$files" \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
am__installdirs = "$(DESTDIR)$(pkgconfigdir)"
DATA = $(pkgconfig_DATA)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
am__recursive_targets = \
$(RECURSIVE_TARGETS) \
$(RECURSIVE_CLEAN_TARGETS) \
$(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
cscope distdir dist dist-all distcheck
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
CSCOPE = cscope
DIST_SUBDIRS = $(SUBDIRS)
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/libratbox.pc.in \
$(top_srcdir)/include/libratbox_config.h.in COPYING ChangeLog \
INSTALL README TODO compile config.guess config.sub install-sh \
ltmain.sh missing
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
am__remove_distdir = \
if test -d "$(distdir)"; then \
find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
&& rm -rf "$(distdir)" \
|| { sleep 5 && rm -rf "$(distdir)"; }; \
else :; fi
am__post_remove_distdir = $(am__remove_distdir)
am__relativize = \
dir0=`pwd`; \
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
sed_rest='s,^[^/]*/*,,'; \
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
sed_butlast='s,/*[^/]*$$,,'; \
while test -n "$$dir1"; do \
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
if test "$$first" != "."; then \
if test "$$first" = ".."; then \
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
else \
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
if test "$$first2" = "$$first"; then \
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
else \
dir2="../$$dir2"; \
fi; \
dir0="$$dir0"/"$$first"; \
fi; \
fi; \
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
done; \
reldir="$$dir2"
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best
DIST_TARGETS = dist-gzip
distuninstallcheck_listfiles = find . -type f -print
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
distcleancheck_listfiles = find . -type f -print
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AS = @AS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CP = @CP@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
GNUTLS_LIBS = @GNUTLS_LIBS@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN = @LN@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@
MBEDTLS_LIBS = @MBEDTLS_LIBS@
MKDIR_P = @MKDIR_P@
MV = @MV@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PICFLAGS = @PICFLAGS@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
RANLIB = @RANLIB@
RB_PREFIX = @RB_PREFIX@
RM = @RM@
SED = @SED@
SEDOBJ = @SEDOBJ@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SSL_CFLAGS = @SSL_CFLAGS@
SSL_LIBS = @SSL_LIBS@
STRIP = @STRIP@
TOUCH = @TOUCH@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = foreign
SUBDIRS = src
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libratbox.pc
all: all-recursive
.SUFFIXES:
am--refresh: Makefile
@:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
$(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
echo ' $(SHELL) ./config.status'; \
$(SHELL) ./config.status;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
$(am__cd) $(srcdir) && $(AUTOCONF)
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
$(am__aclocal_m4_deps):
include/libratbox_config.h: include/stamp-h1
@test -f $@ || rm -f include/stamp-h1
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) include/stamp-h1
include/stamp-h1: $(top_srcdir)/include/libratbox_config.h.in $(top_builddir)/config.status
@rm -f include/stamp-h1
cd $(top_builddir) && $(SHELL) ./config.status include/libratbox_config.h
$(top_srcdir)/include/libratbox_config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
rm -f include/stamp-h1
touch $@
distclean-hdr:
-rm -f include/libratbox_config.h include/stamp-h1
libratbox.pc: $(top_builddir)/config.status $(srcdir)/libratbox.pc.in
cd $(top_builddir) && $(SHELL) ./config.status $@
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool config.lt
install-pkgconfigDATA: $(pkgconfig_DATA)
@$(NORMAL_INSTALL)
@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \
$(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \
done
uninstall-pkgconfigDATA:
@$(NORMAL_UNINSTALL)
@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir)
# This directory's subdirectories are mostly independent; you can cd
# into them and run 'make' without going through this Makefile.
# To change the values of 'make' variables: instead of editing Makefiles,
# (1) if the variable is set in 'config.status', edit 'config.status'
# (which will cause the Makefiles to be regenerated when you run 'make');
# (2) otherwise, pass the desired values on the 'make' command line.
$(am__recursive_targets):
@fail=; \
if $(am__make_keepgoing); then \
failcom='fail=yes'; \
else \
failcom='exit 1'; \
fi; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-recursive
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-recursive
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscope: cscope.files
test ! -s cscope.files \
|| $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
clean-cscope:
-rm -f cscope.files
cscope.files: clean-cscope cscopelist
cscopelist: cscopelist-recursive
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
distdir: $(DISTFILES)
$(am__remove_distdir)
test -d "$(distdir)" || mkdir "$(distdir)"
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
$(am__make_dryrun) \
|| test -d "$(distdir)/$$subdir" \
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|| exit 1; \
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
$(am__relativize); \
new_distdir=$$reldir; \
dir1=$$subdir; dir2="$(top_distdir)"; \
$(am__relativize); \
new_top_distdir=$$reldir; \
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
($(am__cd) $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$$new_top_distdir" \
distdir="$$new_distdir" \
am__remove_distdir=: \
am__skip_length_check=: \
am__skip_mode_fix=: \
distdir) \
|| exit 1; \
fi; \
done
-test -n "$(am__skip_mode_fix)" \
|| find "$(distdir)" -type d ! -perm -755 \
-exec chmod u+rwx,go+rx {} \; -o \
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|| chmod -R a+r "$(distdir)"
dist-gzip: distdir
tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
$(am__post_remove_distdir)
dist-bzip2: distdir
tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
$(am__post_remove_distdir)
dist-lzip: distdir
tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
$(am__post_remove_distdir)
dist-xz: distdir
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
$(am__post_remove_distdir)
dist-tarZ: distdir
@echo WARNING: "Support for distribution archives compressed with" \
"legacy program 'compress' is deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
$(am__post_remove_distdir)
dist-shar: distdir
@echo WARNING: "Support for shar distribution archives is" \
"deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
$(am__post_remove_distdir)
dist-zip: distdir
-rm -f $(distdir).zip
zip -rq $(distdir).zip $(distdir)
$(am__post_remove_distdir)
dist dist-all:
$(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
$(am__post_remove_distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
case '$(DIST_ARCHIVES)' in \
*.tar.gz*) \
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.lz*) \
lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
*.tar.xz*) \
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
*.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
*.shar.gz*) \
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
esac
chmod -R a-w $(distdir)
chmod u+w $(distdir)
mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
chmod a-w $(distdir)
test -d $(distdir)/_build || exit 0; \
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
&& am__cwd=`pwd` \
&& $(am__cd) $(distdir)/_build/sub \
&& ../../configure \
$(AM_DISTCHECK_CONFIGURE_FLAGS) \
$(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=../.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
distuninstallcheck \
&& chmod -R a-w "$$dc_install_base" \
&& ({ \
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
} || { rm -rf "$$dc_destdir"; exit 1; }) \
&& rm -rf "$$dc_destdir" \
&& $(MAKE) $(AM_MAKEFLAGS) dist \
&& rm -rf $(DIST_ARCHIVES) \
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
&& cd "$$am__cwd" \
|| exit 1
$(am__post_remove_distdir)
@(echo "$(distdir) archives ready for distribution: "; \
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
distuninstallcheck:
@test -n '$(distuninstallcheck_dir)' || { \
echo 'ERROR: trying to run $@ with an empty' \
'$$(distuninstallcheck_dir)' >&2; \
exit 1; \
}; \
$(am__cd) '$(distuninstallcheck_dir)' || { \
echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
exit 1; \
}; \
test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left after uninstall:" ; \
if test -n "$(DESTDIR)"; then \
echo " (check DESTDIR support)"; \
fi ; \
$(distuninstallcheck_listfiles) ; \
exit 1; } >&2
distcleancheck: distclean
@if test '$(srcdir)' = . ; then \
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
exit 1 ; \
fi
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left in build directory after distclean:" ; \
$(distcleancheck_listfiles) ; \
exit 1; } >&2
check-am: all-am
check: check-recursive
all-am: Makefile $(DATA)
installdirs: installdirs-recursive
installdirs-am:
for dir in "$(DESTDIR)$(pkgconfigdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-hdr \
distclean-libtool distclean-tags
dvi: dvi-recursive
dvi-am:
html: html-recursive
html-am:
info: info-recursive
info-am:
install-data-am: install-pkgconfigDATA
install-dvi: install-dvi-recursive
install-dvi-am:
install-exec-am:
install-html: install-html-recursive
install-html-am:
install-info: install-info-recursive
install-info-am:
install-man:
install-pdf: install-pdf-recursive
install-pdf-am:
install-ps: install-ps-recursive
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am: uninstall-pkgconfigDATA
.MAKE: $(am__recursive_targets) install-am install-strip
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
am--refresh check check-am clean clean-cscope clean-generic \
clean-libtool cscope cscopelist-am ctags ctags-am dist \
dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \
dist-xz dist-zip distcheck distclean distclean-generic \
distclean-hdr distclean-libtool distclean-tags distcleancheck \
distdir distuninstallcheck dvi dvi-am html html-am info \
info-am install install-am install-data install-data-am \
install-dvi install-dvi-am install-exec install-exec-am \
install-html install-html-am install-info install-info-am \
install-man install-pdf install-pdf-am install-pkgconfigDATA \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs installdirs-am maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-generic \
mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
uninstall-am uninstall-pkgconfigDATA
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

10541
libratbox/aclocal.m4 vendored Normal file

File diff suppressed because it is too large Load diff

1480
libratbox/config.guess vendored Executable file

File diff suppressed because it is too large Load diff

1801
libratbox/config.sub vendored Executable file

File diff suppressed because it is too large Load diff

17916
libratbox/configure vendored Executable file

File diff suppressed because it is too large Load diff

698
libratbox/configure.ac Normal file
View file

@ -0,0 +1,698 @@
dnl $Id: configure.ac 26260 2008-12-10 04:08:39Z androsyn $
dnl Process this file with autoconf to produce a configure script.
dnl TODO: clean up all the OpenSSL and shared module checking stuff;
dnl the most major changes have already been made and it looks like
dnl said functions need to be just about as complex as they already are.
AC_PREREQ(2.63)
AUTOMAKE_OPTIONS = 1.10
dnl Sneaky way to get an Id tag into the configure script
AC_COPYRIGHT([$Id: configure.ac 26260 2008-12-10 04:08:39Z androsyn $])
AC_INIT([libratbox],[devel])
AM_INIT_AUTOMAKE(AC_PACKAGE_TARNAME, AC_PACKAGE_VERSION, -)
AM_CONFIG_HEADER(include/libratbox_config.h)
AC_PREFIX_DEFAULT(/usr/local/libratbox)
AC_GNU_SOURCE
dnl Checks for programs.
AC_PROG_CC_C99
if test x"$ac_cv_prog_cc_c99" = "xno"; then
AC_ERROR([ircd-ratbox requires a C99 capable compiler])
fi
AC_PROG_INSTALL
AC_PROG_EGREP
AC_PROG_SED
F77=no
CXX=no
GCJ=no
AM_DISABLE_STATIC
AM_ENABLE_SHARED
AM_MAINTAINER_MODE
AC_ISC_POSIX
AC_C_INLINE
AC_C_CONST
AC_C_BIGENDIAN
AC_PROG_MAKE_SET
AC_PROG_INSTALL
AC_PATH_PROG(AUTOMAKE, automake)
AC_PATH_PROG(ACLOCAL, aclocal)
AC_PATH_PROG(AUTOHEADER, autoheader)
AC_PATH_PROG(AS, as)
AC_PATH_PROG(RM, rm)
AC_PATH_PROG(CP, cp)
AC_PATH_PROG(MV, mv)
AC_PATH_PROG(LN, ln)
AC_PATH_PROG(TOUCH, touch)
AC_LANG(C)
AC_PROG_LIBTOOL
LIBTOOL="$LIBTOOL --silent"
case "$host_os" in
*cygwin*)
AC_DEFINE_UNQUOTED(CYGWIN,1,[This is a Cygwin system])
AC_DEFINE_UNQUOTED(WINDOWS,1,[This is a Windows system])
;;
*mingw*)
AC_DEFINE_UNQUOTED(MINGW,1,[This is a MinGW system])
AC_DEFINE_UNQUOTED(WINDOWS,1,[This is a Windows system])
AC_CHECK_HEADER(windows.h, , [AC_MSG_ERROR([** MinGW and no windows.h. I give up.])])
AC_CHECK_HEADER(winsock2.h, , [AC_MSG_ERROR([** MinGW and no winsock2.h. I give up.])])
AC_DEFINE_UNQUOTED(HAVE_WINSOCK2_H, 1, [Have WINSOCK2_H])
AC_DEFINE_UNQUOTED(HAVE_WINSOCK_H, 1, [Have WINSOCK_H])
LIBS="$LIBS -lws2_32 -liphlpapi"
is_mingw="yes"
;;
*interix*)
CPPFLAGS="$CFLAGS -D_ALL_SOURCE -D_XOPEN_SOURCE=500"
;;
*solaris*)
CPPFLAGS="$CFLAGS -D_POSIX_PTHREAD_SEMANTICS -D_XPG4_2"
;;
*)
;;
esac
AM_CONDITIONAL([MINGW], [test "$is_mingw" = "yes"])
# backwards support for IRC_CFLAGS
CFLAGS="$IRC_CFLAGS $CFLAGS -Wall"
dnl use directory structure of cached as default (hack)
if test "$libexecdir" = '${exec_prefix}/libexec' &&
test "$localstatedir" = '${prefix}/var'; then
libexecdir='${bindir}'
localstatedir='${prefix}'
fi
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
AC_TYPE_UID_T
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([crypt.h unistd.h sys/socket.h sys/stat.h sys/time.h time.h netinet/in.h arpa/inet.h errno.h sys/uio.h spawn.h sys/poll.h sys/epoll.h sys/select.h sys/devpoll.h sys/event.h port.h signal.h sys/signalfd.h sys/timerfd.h linux/tcp.h])
AC_HEADER_TIME
dnl Networking Functions
dnl ====================
AC_SEARCH_LIBS(socket, [socket],,)
AC_CHECK_MEMBER([struct sockaddr.sa_len], [AC_DEFINE(SOCKADDR_IN_HAS_LEN, 1, [Define to 1 if sockaddr has a 'sa_len'
member.])],,[[
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
]])
AC_CHECK_TYPE([socklen_t], rb_cv_socklen_t=socklen_t,[
AC_MSG_CHECKING([for socklen_t equivalent])
AC_CACHE_VAL([rb_cv_socklen_t],
[
# Systems have either "struct sockaddr *" or
# "void *" as the second argument to getpeername
rb_cv_socklen_t=
for arg2 in "struct sockaddr" void; do
for t in int size_t unsigned long "unsigned long"; do
AC_TRY_COMPILE([
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
int getpeername (int, $arg2 *, $t *);
],[
$t len;
getpeername(0,0,&len);
],[
rb_cv_socklen_t="$t"
break
])
done
done
if test "x$rb_cv_socklen_t" = x; then
AC_MSG_WARN([Cannot find a type to use in place of socklen_t using int])
rb_cv_socklen_t=int
fi
])
AC_MSG_RESULT($rb_cv_socklen_t)],
[#include <sys/types.h>
#include <sys/socket.h>])
rb_socklen_t=$rb_cv_socklen_t
AC_ARG_ENABLE(ipv6,AC_HELP_STRING([--disable-ipv6],[Disable IPv6 support]),[ipv6=$enableval],[ipv6=yes])
if test x$ipv6 != xyes; then
have_v6="no"
else
have_v6=yes
RB_PROTO_INET6([], [
AC_MSG_NOTICE([Disabling IPv6 support: PF_INET6 not found])
have_v6=no
])
if test "X$have_v6" = "Xyes"; then
RB_TYPE_STRUCT_SOCKADDR_IN6([], [
AC_MSG_NOTICE([Disabling IPv6 support: struct sockaddr_in6 not found])
have_v6=no
])
fi
fi
AC_CHECK_TYPES([struct sockaddr_storage],[
rb_have_sockaddr_storage=yes
],[], [
#include <sys/types.h>
#include <sys/socket.h>
])
dnl Check for stdarg.h - if we cant find it, halt configure
AC_CHECK_HEADER(stdarg.h, , [AC_MSG_ERROR([** stdarg.h could not be found - libratbox will not compile without it **])])
AC_CHECK_TYPE([sa_family_t], [],
[AC_DEFINE(sa_family_t, [u_int16_t], [If system does not define sa_family_t, define it here.])],
[[#include <sys/types.h>
#include <sys/socket.h>]])
dnl check for various functions...
AC_CHECK_FUNCS([socketpair gettimeofday writev sendmsg gmtime_r strtok_r usleep posix_spawn strlcpy strlcat strnlen fstat signalfd select poll kevent port_create epoll_ctl arc4random getrusage timerfd_create])
AC_SEARCH_LIBS(nanosleep, rt posix4, AC_DEFINE(HAVE_NANOSLEEP, 1, [Define if you have nanosleep]))
AC_SEARCH_LIBS(timer_create, rt, AC_DEFINE(HAVE_TIMER_CREATE, 1, [Define if you have timer_create]))
RB_CHECK_TIMER_CREATE
RB_CHECK_TIMERFD_CREATE
AC_FUNC_ALLOCA
AC_FUNC_VFORK
AC_FUNC_MMAP
AC_MSG_CHECKING(for /dev/poll)
if test -c "/dev/poll"; then
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_DEVPOLL, [1], [Define to 1 if you have devpoll])
else
AC_MSG_RESULT(no)
fi
if test "$is_mingw" = "yes"; then
AC_DEFINE(HAVE_WIN32, [1], [Define to 1 if you are on windows])
fi
dnl OpenSSL support
AC_MSG_CHECKING(for OpenSSL)
AC_ARG_ENABLE(openssl,
[AC_HELP_STRING([--enable-openssl[=DIR]],[Enable OpenSSL support (DIR optional).])
AC_HELP_STRING([--disable-openssl],[Disable OpenSSL support.])],
[cf_enable_openssl=$enableval],
[cf_enable_openssl="auto"])
if test "$cf_enable_openssl" != "no" ; then
cf_openssl_basedir=""
if test "$cf_enable_openssl" != "auto" &&
test "$cf_enable_openssl" != "yes" ; then
dnl Support for --enable-openssl=/some/place
cf_openssl_basedir="`echo ${cf_enable_openssl} | sed 's/\/$//'`"
else
dnl Do the auto-probe here. Check some common directory paths.
for dirs in /usr/local/ssl /usr/pkg /usr/local \
/usr/local/openssl ; do
if test -f "${dirs}/include/openssl/opensslv.h" ; then
cf_openssl_basedir="${dirs}"
break
fi
done
unset dirs
fi
dnl Now check cf_openssl_found to see if we found anything.
if test ! -z "$cf_openssl_basedir"; then
if test -f "${cf_openssl_basedir}/include/openssl/opensslv.h" ; then
SSL_CFLAGS="-I${cf_openssl_basedir}/include"
SSL_LIBS="-L${cf_openssl_basedir}/lib"
else
dnl OpenSSL wasn't found in the directory specified. Naughty
dnl administrator...
cf_openssl_basedir=""
fi
else
dnl Check for stock FreeBSD 4.x and 5.x systems, since their files
dnl are in /usr/include and /usr/lib. In this case, we don't want to
dnl change INCLUDES or LIBS, but still want to enable OpenSSL.
dnl We can't do this check above, because some people want two versions
dnl of OpenSSL installed (stock FreeBSD 4.x/5.x and /usr/local/ssl)
dnl and they want /usr/local/ssl to have preference.
if test -f "/usr/include/openssl/opensslv.h" ; then
cf_openssl_basedir="/usr"
fi
fi
dnl If we have a basedir defined, then everything is okay. Otherwise,
dnl we have a problem.
if test ! -z "$cf_openssl_basedir"; then
AC_MSG_RESULT($cf_openssl_basedir)
cf_enable_openssl="yes"
else
AC_MSG_RESULT([not found. Specify a correct path?])
cf_enable_openssl="no"
fi
unset cf_openssl_basedir
else
dnl If --disable-openssl was specified
AC_MSG_RESULT(disabled)
fi
save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $SSL_CFLAGS"
save_LIBS="$LIBS"
LIBS="$LIBS $SSL_LIBS"
if test "$cf_enable_openssl" != no; then
dnl Check OpenSSL version (must be 0.9.7 or above!)
AC_MSG_CHECKING(for OpenSSL 0.9.7 or above)
AC_RUN_IFELSE(
AC_LANG_PROGRAM(
[#include <openssl/opensslv.h>
#include <stdlib.h>],
[[if (OPENSSL_VERSION_NUMBER >= 0x00907000)
exit(0); else exit(1);]]),
cf_enable_openssl=yes,
cf_enable_openssl=no,
cf_enable_openssl=no)
if test "$cf_enable_openssl" != no; then
AC_MSG_RESULT(found)
else
AC_MSG_RESULT(no - OpenSSL support disabled)
fi
fi
if test "$cf_enable_openssl" != no; then
CPPFLAGS="$CPPFLAGS $SSL_LIBS"
AC_CHECK_LIB(crypto, RAND_status,
[cf_enable_openssl=yes],
[cf_enable_openssl=no])
fi
if test "$cf_enable_openssl" != no; then
CPPFLAGS="$CPPFLAGS $SSL_LIBS"
AC_CHECK_LIB(ssl, SSL_read,
[SSL_LIBS="$SSL_LIBS -lssl -lcrypto"],
[cf_enable_openssl=no], [-lcrypto])
fi
dnl mbedTLS support
AC_ARG_ENABLE(mbedtls,
[AC_HELP_STRING([--enable-mbedtls], [Enable mbedTLS support.])
AC_HELP_STRING([--disable-mbedtls], [Disable mbedTLS support.])],
[cf_enable_mbedtls=$enableval],
[cf_enable_mbedtls="auto"])
if test "$cf_enable_mbedtls" != no; then
save_CPPFLAGS="$CPPFLAGS"
save_LIBS="$LIBS"
LIBS="$LIBS $MBEDTLS_LIBS"
AC_CHECK_LIB(mbedtls, mbedtls_ssl_init, [
MBEDTLS_LIBS="$MBEDTLS_LIBS -lmbedtls -lmbedx509 -lmbedcrypto"
cf_enable_mbedtls=yes
], [cf_enable_mbedtls=no], [-lmbedx509 -lmbedcrypto])
fi
dnl GnuTLS support
AC_MSG_CHECKING(for GnuTLS)
AC_ARG_ENABLE(gnutls,
[AC_HELP_STRING([--enable-gnutls],[Enable GnuTLS support.])
AC_HELP_STRING([--disable-gnutls],[Disable GnuTLS support.])],
[cf_enable_gnutls=$enableval],
[cf_enable_gnutls="auto"])
if test "$cf_enable_gnutls" != no; then
PKG_CHECK_MODULES(GNUTLS, [gnutls], [
cf_enable_gnutls="yes"
], [cf_enable_gnutls="no"])
fi
dnl mbed TLS is given highest preference when no specified TLS library is provided
if test "$cf_enable_openssl" = "auto" -a "$cf_enable_mbedtls" = "yes"; then
cf_enable_openssl="no"
fi
if test "$cf_enable_gnutls" = "auto" -a "$cf_enable_openssl" = "yes" -a "$cf_enable_mbedtls" = "yes"; then
cf_enable_gnutls="no"
fi
if test x"$cf_enable_openssl" != xno; then
AC_DEFINE(HAVE_OPENSSL,1,[Has OpenSSL])
GNUTLS_CFLAGS=""
GNUTLS_LIBS=""
MBEDTLS_LIBS=""
MBEDTLS_CFLAGS=""
SSL_TYPE="openssl"
elif test x"$cf_enable_mbedtls" != xno; then
AC_DEFINE(HAVE_MBEDTLS, 1, [Has mbedTLS])
SSL_LIBS=""
SSL_CFLAGS=""
GNUTLS_CFLAGS=""
GNUTLS_LIBS=""
SSL_TYPE="mbedtls"
elif test x"$cf_enable_gnutls" != xno; then
AC_DEFINE(HAVE_GNUTLS, 1, [Has GnuTLS])
SSL_LIBS=""
SSL_CFLAGS=""
MBEDTLS_LIBS=""
MBEDTLS_CFLAGS=""
SSL_TYPE="gnutls"
fi
CPPFLAGS="$save_CPPFLAGS"
LIBS="$save_LIBS"
dnl End OpenSSL detection
dnl Debug-related options
dnl =====================
AC_ARG_ENABLE(assert,
AC_HELP_STRING([--enable-assert],[Enable assert(). Choose between soft(warnings) and hard(aborts the daemon)]),
[assert=$enableval], [assert=no])
if test "$assert" = no; then
AC_DEFINE(NDEBUG, 1, [Define this to disable debugging support.])
elif test "$assert" = soft; then
AC_DEFINE(SOFT_ASSERT, 1, [Define this to enable soft asserts.])
AC_DEFINE(NDEBUG, 1, [Define this to disable debugging support.])
elif test "$assert" = yes; then
assert = "hard";
fi
AC_MSG_CHECKING(if you want to do a profile build)
AC_ARG_ENABLE(profile,
AC_HELP_STRING([--enable-profile],[Enable profiling]),
[profile=$enableval], [profile=no])
if test "$profile" = yes; then
if test "$ac_cv_c_compiler_gnu" = yes; then
CFLAGS="$CFLAGS -pg -static"
AC_MSG_RESULT([yes, adding -pg -static])
AC_DEFINE(RATBOX_PROFILE, 1, [Defined to mark profiling is enabled])
else
AC_MSG_RESULT([no, profile builds only work with gcc])
fi
else
AC_MSG_RESULT(no)
fi
AC_ARG_ENABLE(balloc,
AC_HELP_STRING([--disable-balloc],[Disable the block allocator.]),
[balloc=$enableval], [balloc=yes])
if test "$balloc" = no; then
AC_DEFINE([NOBALLOC], 1, [Define to 1 if you wish to disable the block allocator.])
fi
AC_ARG_ENABLE(warnings,
AC_HELP_STRING([--enable-warnings],[Enable all sorts of warnings for debugging.]),
[CFLAGS="$CFLAGS -Wall -Werror -Wcast-qual -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wshadow -Wwrite-strings -W -Wno-unused -Wunused-function -Wunused-variable"],[])
AC_SUBST(LDFLAGS)
AC_SUBST(PICFLAGS)
AC_SUBST(CFLAGS)
AC_SUBST(SEDOBJ)
AC_SUBST(SSL_CFLAGS)
AC_SUBST(SSL_LIBS)
AC_SUBST(GNUTLS_CFLAGS)
AC_SUBST(GNUTLS_LIBS)
AC_SUBST(MBEDTLS_CFLAGS)
AC_SUBST(MBEDTLS_LIBS)
if test "$prefix" = "NONE"; then
AC_DEFINE_UNQUOTED(RB_PREFIX, "$ac_default_prefix", [Prefix where libratbox is installed.])
else
dnl Don't get bitten by Cygwin's stupidity if the user specified
dnl a custom prefix with a trailing slash
prefix=`echo $prefix | sed 's/\/$//'`
AC_DEFINE_UNQUOTED(RB_PREFIX, "$prefix", [Prefix where libratbox is installed.])
fi
AC_SUBST(RB_PREFIX)
AC_CONFIG_COMMANDS([include/librb-config.h],
[
outfile=include/librb-config.h.tmp
cat > $outfile <<\_______EOF
/*
* librb-config.h: libratbox config file. Please modify configure.ac
*/
#ifndef __LIBRB_CONFIG_H
#define __LIBRB_CONFIG_H
_______EOF
if test "x$rb_have_ipv6" = "xyes"; then
echo "#define RB_IPV6 1" >> $outfile
fi
if test "x$rb_windows_h" = "xyes"; then
echo '#define WIN32_LEAN_AND_MEAN 1' >> $outfile
echo '#include <windows.h>' >> $outfile
echo '#include <winsock2.h>' >> $outfile
echo '#include <iphlpapi.h>' >> $outfile
fi
if test "x$rb_alloca_h" = "xyes"; then
echo '#define RB_HAVE_ALLOCA_H 1' >> $outfile
fi
if test "x$rb_header_stdc" = "xyes"; then
echo '#include <stdlib.h>' >> $outfile
echo '#include <stddef.h>' >> $outfile
elif test "x$rb_header_stdlib" = "xyes"; then
echo '#include <stdlib.h>' >> $outfile
fi
if test "x$rb_header_string_h" = "xyes"; then
echo '#include <string.h>' >> $outfile
fi
if test "x$rb_stdint_h" = "xyes"; then
echo '#include <stdint.h>' >> $outfile
fi
if test "x$rb_inttypes_h" = "xyes"; then
echo '#include <inttypes.h>' >> $outfile
fi
if test "x$rb_sys_types_h" = "xyes"; then
echo '#include <sys/types.h>' >> $outfile
fi
if test "x$rb_sys_time_h" = "xyes"; then
echo '#include <sys/time.h>' >> $outfile
fi
if test "x$rb_sys_stat_h" = "xyes"; then
echo '#include <sys/stat.h>' >> $outfile
fi
if test "x$rb_time_h" = "xyes"; then
echo '#include <time.h>' >> $outfile
fi
if test "x$rb_sys_socket_h" = "xyes"; then
echo '#include <sys/socket.h>' >> $outfile
fi
if test "x$rb_netinet_in_h" = "xyes"; then
echo '#include <netinet/in.h>' >> $outfile
fi
if test "x$rb_arpa_inet_h" = "xyes"; then
echo '#include <arpa/inet.h>' >> $outfile
fi
if test "x$rb_unistd_h" = "xyes"; then
echo '#include <unistd.h>' >> $outfile
fi
if test "x$rb_crypt_h" = "xyes"; then
echo '#include <crypt.h>' >> $outfile
fi
if test "x$rb_errno_h" = "xyes"; then
echo '#include <errno.h>' >> $outfile
fi
echo "typedef $rb_socklen_t rb_socklen_t;" >> $outfile
if test "x$rb_sockaddr_sa_len" = "xyes"; then
echo '#define RB_SOCKADDR_HAS_SA_LEN 1' >> $outfile
fi
if test "x$rb_sockaddr_storage" = "xyes"; then
echo '#define rb_sockaddr_storage sockaddr_storage' >> $outfile
else
echo 'struct rb_sockaddr_storage { uint8_t _padding[[128]]; };' >> $outfile
fi
cat >> $outfile <<\_______EOF
#endif /* __LIBRB_CONFIG_H */
_______EOF
if cmp -s $outfile include/librb-config.h; then
AC_MSG_NOTICE([include/librb-config.h is unchanged])
${rb_rm} -f $outfile
else
${rb_mv} $outfile include/librb-config.h
fi
],[
if test x$ac_cv_header_stdc = xyes; then
rb_header_stdc=yes
fi
if test x$ac_cv_header_stdlib_h = xyes; then
rb_header_stdlib_h=yes
fi
if test x$ac_cv_header_string_h = xyes; then
rb_header_string_h=yes
fi
if test x$ac_cv_header_memory_h = xyes; then
rb_header_memory_h=yes
fi
if test "x${ac_cv_working_alloca_h+set}" = xset ; then
rb_alloca_h="$ac_cv_working_alloca_h"
else
rb_alloc_h="$ac_cv_header_alloca_h"
fi
if test x$ac_cv_member_struct_sockaddr_sa_len = xyes; then
rb_sockaddr_sa_len=yes
fi
if test x$ac_cv_header_sys_socket_h = xyes; then
rb_sys_socket_h=yes
fi
if test x$ac_cv_header_sys_types_h = xyes; then
rb_sys_types_h=yes
fi
if test x$ac_cv_header_sys_stat_h = xyes; then
rb_sys_stat_h=yes
fi
if test x$ac_cv_header_sys_time_h = xyes; then
rb_sys_time_h=yes
fi
if test x$ac_cv_header_time = xyes; then
rb_time_h=yes
fi
if test x$ac_cv_header_stdint_h = xyes; then
rb_stdint_h=yes
fi
if test x$ac_cv_header_inttypes_h = xyes; then
rb_inttypes_h=yes
fi
if test x$ac_cv_header_netinet_in_h = xyes; then
rb_netinet_in_h=yes
fi
if test x$ac_cv_header_crypt_h = xyes; then
rb_crypt_h=yes
fi
if test x$ac_cv_header_errno_h = xyes; then
rb_errno_h=yes
fi
if test x$ac_cv_header_unistd_h = xyes; then
rb_unistd_h=yes
fi
if test x$ac_cv_header_windows_h = xyes; then
rb_windows_h=yes
fi
if test x$ac_cv_header_winsock2_h = xyes; then
rb_winsock2_h=yes
fi
rb_socklen_t=$rb_socklen_t
if test "x$rb_have_sockaddr_storage" = "xyes"; then
rb_sockaddr_storage="yes"
else
rb_sockaddr_storage="no"
fi
rb_have_ipv6="$have_v6"
rb_mv="$MV"
rb_rm="$RM"
]
)
AC_CONFIG_FILES( \
src/Makefile \
Makefile \
libratbox.pc
)
AC_OUTPUT
dnl Make it look sexay!
echo
echo "Compiling $PACKAGE_NAME $PACKAGE_VERSION"
echo
echo "Installing into: $prefix"
echo "IPv6 support ................... $have_v6"
echo "Assert debugging ............... $assert"
echo "Block allocator ................ $balloc"
echo "SSL Type........................ $SSL_TYPE"
echo

791
libratbox/depcomp Executable file
View file

@ -0,0 +1,791 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2016-01-11.22; # UTC
# Copyright (C) 1999-2017 Free Software Foundation, Inc.
# 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, 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, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by 'PROGRAMS ARGS'.
object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
# Get the directory component of the given path, and save it in the
# global variables '$dir'. Note that this directory component will
# be either empty or ending with a '/' character. This is deliberate.
set_dir_from ()
{
case $1 in
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
*) dir=;;
esac
}
# Get the suffix-stripped basename of the given path, and save it the
# global variable '$base'.
set_base_from ()
{
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
}
# If no dependency file was actually created by the compiler invocation,
# we still have to create a dummy depfile, to avoid errors with the
# Makefile "include basename.Plo" scheme.
make_dummy_depfile ()
{
echo "#dummy" > "$depfile"
}
# Factor out some common post-processing of the generated depfile.
# Requires the auxiliary global variable '$tmpdepfile' to be set.
aix_post_process_depfile ()
{
# If the compiler actually managed to produce a dependency file,
# post-process it.
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependency.h'.
# Do two passes, one to just change these to
# $object: dependency.h
# and one to simply output
# dependency.h:
# which is needed to avoid the deleted-header problem.
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
} > "$depfile"
rm -f "$tmpdepfile"
else
make_dummy_depfile
fi
}
# A tabulation character.
tab=' '
# A newline character.
nl='
'
# Character ranges might be problematic outside the C locale.
# These definitions help.
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lower=abcdefghijklmnopqrstuvwxyz
digits=0123456789
alpha=${upper}${lower}
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Avoid interferences from the environment.
gccflag= dashmflag=
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
## (see the conditional assignment to $gccflag above).
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say). Also, it might not be
## supported by the other compilers which use the 'gcc' depmode.
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The second -e expression handles DOS-style file names with drive
# letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
| tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
xlc)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
aix_post_process_depfile
;;
tcc)
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
# FIXME: That version still under development at the moment of writing.
# Make that this statement remains true also for stable, released
# versions.
# It will wrap lines (doesn't matter whether long or short) with a
# trailing '\', as in:
#
# foo.o : \
# foo.c \
# foo.h \
#
# It will put a trailing '\' even on the last line, and will use leading
# spaces rather than leading tabs (at least since its commit 0394caf7
# "Emit spaces for -MD").
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
# We have to change lines of the first kind to '$object: \'.
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
# And for each line of the second kind, we have to emit a 'dep.h:'
# dummy dependency, to avoid the deleted-header problem.
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
## The order of this option in the case statement is important, since the
## shell code in configure will try each of these formats in the order
## listed in this file. A plain '-MD' option would be understood by many
## compilers, so we must ensure this comes after the gcc and icc options.
pgcc)
# Portland's C compiler understands '-MD'.
# Will always output deps to 'file.d' where file is the root name of the
# source file under compilation, even if file resides in a subdirectory.
# The object file name does not affect the name of the '.d' file.
# pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
set_dir_from "$object"
# Use the source, not the object, to determine the base name, since
# that's sadly what pgcc will do too.
set_base_from "$source"
tmpdepfile=$base.d
# For projects that build the same source file twice into different object
# files, the pgcc approach of using the *source* file root name can cause
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
trap "
echo '$0: caught signal, cleaning up...' >&2
rmdir '$lockdir'
exit 1
" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
# mkdir is a portable test-and-set.
if mkdir "$lockdir" 2>/dev/null; then
# This process acquired the lock.
"$@" -MD
stat=$?
# Release the lock.
rmdir "$lockdir"
break
else
# If the lock is being held by a different process, wait
# until the winning process is done or we timeout.
while test -d "$lockdir" && test $i -gt 0; do
sleep 1
i=`expr $i - 1`
done
fi
i=`expr $i - 1`
done
trap - 1 2 13 15
if test $i -le 0; then
echo "$0: failed to acquire lock after $numtries attempts" >&2
echo "$0: check lockdir '$lockdir'" >&2
exit 1
fi
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
# Libtool generates 2 separate objects for the 2 libraries. These
# two compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir$base.o.d # libtool 1.5
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
# Same post-processing that is required for AIX mode.
aix_post_process_depfile
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
msvc7msys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this sed invocation
# correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process the last invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed '1,2d' "$tmpdepfile" \
| tr ' ' "$nl" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E \
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
| sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

View file

@ -0,0 +1,46 @@
/*
* ircd-ratbox: A slightly useful ircd.
* commio-ssl.h: A header for the ssl code
*
* Copyright (C) 2008 ircd-ratbox development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
* $Id: commio-ssl.h 26280 2008-12-10 20:25:29Z androsyn $
*/
#ifndef _COMMIO_SSL_H
#define _COMMIO_SSL_H
int rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list, const char *hostname);
int rb_init_ssl(void);
int rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept);
int rb_init_prng(const char *path, prng_seed_t seed_type);
int rb_get_random(void *buf, size_t length);
const char *rb_get_ssl_strerror(rb_fde_t *F);
void rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout);
void rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout);
void rb_connect_tcp_ssl(rb_fde_t *F, struct sockaddr *dest, struct sockaddr *clocal, int socklen,
CNCB * callback, void *data, int timeout);
void rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, int addrlen);
void rb_ssl_shutdown(rb_fde_t *F);
ssize_t rb_ssl_read(rb_fde_t *F, void *buf, size_t count);
ssize_t rb_ssl_write(rb_fde_t *F, const void *buf, size_t count);
void rb_get_ssl_info(char *buf, size_t length);
#endif

View file

@ -0,0 +1,225 @@
/*
* $Id: ratbox_lib.h 26256 2008-12-10 04:05:26Z androsyn $
*/
#ifndef RB_LIB_H
#define RB_LIB_H 1
#include <librb-config.h>
#include <stdio.h>
#include <limits.h>
#include <stdarg.h>
#include <assert.h>
#include <fcntl.h>
#include <signal.h>
#include <ctype.h>
#ifdef HAVE_LINUX_TCP_H
# include <linux/tcp.h>
#endif
#ifdef __GNUC__
#undef alloca
#define alloca __builtin_alloca
#else
# ifdef _MSC_VER
# include <malloc.h>
# define alloca _alloca
# else
# if RB_HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
#pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca();
# endif
# endif
# endif
# endif
#endif /* __GNUC__ */
#ifdef __GNUC__
#ifdef rb_likely
#undef rb_likely
#endif
#ifdef rb_unlikely
#undef rb_unlikely
#endif
#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
# define __builtin_expect(x, expected_value) (x)
#endif
#define rb_likely(x) __builtin_expect(!!(x), 1)
#define rb_unlikely(x) __builtin_expect(!!(x), 0)
#else /* !__GNUC__ */
#define UNUSED(x) x
#ifdef rb_likely
#undef rb_likely
#endif
#ifdef rb_unlikely
#undef rb_unlikely
#endif
#define rb_likely(x) (x)
#define rb_unlikely(x) (x)
#endif
#ifdef _WIN32
#include <process.h>
#ifndef PATH_MAX
#define PATH_MAX 128
#endif
#ifdef strerror
#undef strerror
#endif
#define strerror(x) rb_strerror(x)
char *rb_strerror(int error);
#define ENOBUFS WSAENOBUFS
#define EINPROGRESS WSAEINPROGRESS
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EMSGSIZE WSAEMSGSIZE
#define EALREADY WSAEALREADY
#define EISCONN WSAEISCONN
#define EADDRINUSE WSAEADDRINUSE
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#define pipe(x) _pipe(x, 1024, O_BINARY)
#define ioctl(x,y,z) ioctlsocket(x,y, (u_long *)z)
#define WNOHANG 1
#ifndef SIGKILL
#define SIGKILL SIGTERM
#endif
#endif /* _WIN32 */
#ifndef HOSTIPLEN
#define HOSTIPLEN 53
#endif
#ifdef __GNUC__
#define slrb_assert(expr) do \
if(rb_unlikely(!(expr))) { \
rb_lib_log( \
"file: %s line: %d (%s): Assertion failed: (%s)", \
__FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \
} \
while(0)
#else
#define slrb_assert(expr) do \
if(rb_unlikely(!(expr))) { \
rb_lib_log( \
"file: %s line: %d: Assertion failed: (%s)", \
__FILE__, __LINE__, #expr); \
} \
while(0)
#endif
#ifdef SOFT_ASSERT
#define lrb_assert(expr) slrb_assert(expr)
#else
#define lrb_assert(expr) do { slrb_assert(expr); assert(expr); } while(0)
#endif
#ifdef RB_SOCKADDR_HAS_SA_LEN
#define ss_len sa_len
#endif
#define GET_SS_FAMILY(x) (((const struct sockaddr *)(x))->sa_family)
#define SET_SS_FAMILY(x, y) ((((struct sockaddr *)(x))->sa_family) = y)
#ifdef RB_SOCKADDR_HAS_SA_LEN
#define SET_SS_LEN(x, y) do { \
struct sockaddr *storage; \
storage = ((struct sockaddr *)(x));\
storage->sa_len = (y); \
} while (0)
#define GET_SS_LEN(x) (((struct sockaddr *)(x))->sa_len)
#else /* !RB_SOCKADDR_HAS_SA_LEN */
#define SET_SS_LEN(x, y) (((struct sockaddr *)(x))->sa_family = ((struct sockaddr *)(x))->sa_family)
#ifdef RB_IPV6
#define GET_SS_LEN(x) (((struct sockaddr *)(x))->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6))
#else
#define GET_SS_LEN(x) (((struct sockaddr *)(x))->sa_family == AF_INET ? sizeof(struct sockaddr_in) : 0)
#endif
#endif
#ifndef INADDRSZ
#define INADDRSZ 4
#endif
#ifndef IN6ADDRSZ
#define IN6ADDRSZ 16
#endif
#ifndef INT16SZ
#define INT16SZ 2
#endif
typedef void log_cb(const char *buffer);
typedef void restart_cb(const char *buffer);
typedef void die_cb(const char *buffer);
char *rb_ctime(const time_t, char *, size_t);
char *rb_date(const time_t, char *, size_t);
void rb_lib_log(const char *, ...);
void rb_lib_restart(const char *, ...) __attribute__((noreturn));
void rb_lib_die(const char *, ...);
void rb_set_time(void);
const char *rb_lib_version(void);
void rb_lib_init(log_cb * xilog, restart_cb * irestart, die_cb * idie, int closeall, int maxfds,
size_t dh_size, size_t fd_heap_size);
void rb_lib_loop(long delay) __attribute__((noreturn));
time_t rb_current_time(void);
const struct timeval *rb_current_time_tv(void);
pid_t rb_spawn_process(const char *, const char **);
char *rb_strtok_r(char *, const char *, char **);
int rb_gettimeofday(struct timeval *, void *);
void rb_sleep(unsigned int seconds, unsigned int useconds);
char *rb_crypt(const char *, const char *);
unsigned char *rb_base64_encode(const unsigned char *str, int length);
unsigned char *rb_base64_decode(const unsigned char *str, int length, int *ret);
int rb_kill(pid_t, int);
char *rb_strerror(int);
int rb_setenv(const char *, const char *, int);
pid_t rb_waitpid(pid_t pid, int *status, int options);
pid_t rb_getpid(void);
//unsigned int rb_geteuid(void);
#include <rb_tools.h>
#include <rb_memory.h>
#include <rb_commio.h>
#include <rb_balloc.h>
#include <rb_linebuf.h>
#include <rb_snprintf.h>
#include <rb_event.h>
#include <rb_helper.h>
#include <rb_rawbuf.h>
#include <rb_patricia.h>
#endif

View file

@ -0,0 +1,210 @@
/*
* ircd-ratbox: A slightly useful ircd.
* commio.h: A header for the network subsystem.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
* $Id: rb_commio.h 26092 2008-09-19 15:13:52Z androsyn $
*/
#ifndef RB_LIB_H
# error "Do not use commio.h directly"
#endif
#ifndef INCLUDED_commio_h
#define INCLUDED_commio_h
struct sockaddr;
struct _fde;
typedef struct _fde rb_fde_t;
/* Callback for completed IO events */
typedef void PF(rb_fde_t *, void *);
/* Callback for completed connections */
/* int fd, int status, void * */
typedef void CNCB(rb_fde_t *, int, void *);
/* callback for fd table dumps */
typedef void DUMPCB(int, const char *desc, void *);
/* callback for accept callbacks */
typedef void ACCB(rb_fde_t *, int status, struct sockaddr *addr, rb_socklen_t len, void *);
/* callback for pre-accept callback */
typedef int ACPRE(rb_fde_t *, struct sockaddr *addr, rb_socklen_t len, void *);
enum
{
RB_OK,
RB_ERR_BIND,
RB_ERR_DNS,
RB_ERR_TIMEOUT,
RB_ERR_CONNECT,
RB_ERROR,
RB_ERROR_SSL,
RB_ERR_MAX
};
#define RB_FD_NONE 0x01
#define RB_FD_FILE 0x02
#define RB_FD_SOCKET 0x04
#ifndef _WIN32
#define RB_FD_PIPE 0x08
#else
#define RB_FD_PIPE RB_FD_SOCKET
#endif
#define RB_FD_LISTEN 0x10
#define RB_FD_SSL 0x20
#define RB_FD_UNKNOWN 0x40
#define RB_RW_IO_ERROR -1 /* System call error */
#define RB_RW_SSL_ERROR -2 /* SSL Error */
#define RB_RW_SSL_NEED_READ -3 /* SSL Needs read */
#define RB_RW_SSL_NEED_WRITE -4 /* SSL Needs write */
struct rb_iovec
{
void *iov_base;
size_t iov_len;
};
void rb_fdlist_init(int closeall, int maxfds, size_t heapsize);
rb_fde_t *rb_open(int, uint8_t, const char *);
void rb_close(rb_fde_t *);
void rb_dump_fd(DUMPCB *, void *xdata);
void rb_note(rb_fde_t *, const char *);
/* Type of IO */
#define RB_SELECT_READ 0x1
#define RB_SELECT_WRITE 0x2
#define RB_SELECT_ACCEPT RB_SELECT_READ
#define RB_SELECT_CONNECT RB_SELECT_WRITE
#define RB_SSL_CERTFP_LEN 64
/* Methods for certfp */
/* Digest of full X.509 certificate */
#define RB_SSL_CERTFP_METH_CERT_SHA1 0x0000
#define RB_SSL_CERTFP_METH_CERT_SHA256 0x0001
#define RB_SSL_CERTFP_METH_CERT_SHA512 0x0002
/* Digest of SubjectPublicKeyInfo (RFC 5280), used by DANE (RFC 6698) */
#define RB_SSL_CERTFP_METH_SPKI_SHA256 0x1001
#define RB_SSL_CERTFP_METH_SPKI_SHA512 0x1002
/* Names for certfp */
#define CERTFP_NAME_CERT_SHA1 "sha1"
#define CERTFP_PREFIX_CERT_SHA1 ""
#define CERTFP_NAME_CERT_SHA256 "sha256"
#define CERTFP_PREFIX_CERT_SHA256 ""
#define CERTFP_NAME_CERT_SHA512 "sha512"
#define CERTFP_PREFIX_CERT_SHA512 ""
/* These prefixes are copied from RFC 7218 */
#define CERTFP_NAME_SPKI_SHA256 "spki_sha256"
#define CERTFP_PREFIX_SPKI_SHA256 "SPKI:SHA2-256:"
#define CERTFP_NAME_SPKI_SHA512 "spki_sha512"
#define CERTFP_PREFIX_SPKI_SHA512 "SPKI:SHA2-512:"
#define RB_SSL_CERTFP_LEN_SHA1 20
#define RB_SSL_CERTFP_LEN_SHA256 32
#define RB_SSL_CERTFP_LEN_SHA512 64
int rb_set_nb(rb_fde_t *);
int rb_set_buffers(rb_fde_t *, int);
int rb_get_sockerr(rb_fde_t *);
void rb_settimeout(rb_fde_t *, time_t, PF *, void *);
void rb_checktimeouts(void *);
void rb_connect_tcp(rb_fde_t *, struct sockaddr *, struct sockaddr *, int, CNCB *, void *, int);
void rb_connect_tcp_ssl(rb_fde_t *, struct sockaddr *, struct sockaddr *, int, CNCB *, void *, int);
int rb_connect_sockaddr(rb_fde_t *, struct sockaddr *addr, int len);
const char *rb_errstr(int status);
rb_fde_t *rb_socket(int family, int sock_type, int proto, const char *note);
int rb_socketpair(int family, int sock_type, int proto, rb_fde_t **F1, rb_fde_t **F2,
const char *note);
void rb_accept_tcp(rb_fde_t *, ACPRE * precb, ACCB * callback, void *data);
ssize_t rb_write(rb_fde_t *, const void *buf, int count);
ssize_t rb_writev(rb_fde_t *, struct rb_iovec *vector, int count);
ssize_t rb_read(rb_fde_t *, void *buf, int count);
int rb_pipe(rb_fde_t **, rb_fde_t **, const char *desc);
int rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list, const char *hostname);
int rb_ssl_listen(rb_fde_t *, int backlog, int defer_accept);
int rb_listen(rb_fde_t *, int backlog, int defer_accept);
int rb_remove_ssl_vserver(const char *hostname);
const char *rb_inet_ntop(int af, const void *src, char *dst, unsigned int size);
int rb_inet_pton(int af, const char *src, void *dst);
const char *rb_inet_ntop_sock(struct sockaddr *src, char *dst, unsigned int size);
int rb_inet_pton_sock(const char *src, struct sockaddr *dst);
int rb_getmaxconnect(void);
int rb_ignore_errno(int);
/* Generic wrappers */
void rb_setselect(rb_fde_t *, unsigned int type, PF * handler, void *client_data);
void rb_init_netio(void);
int rb_select(unsigned long);
int rb_fd_ssl(rb_fde_t *F);
int rb_get_fd(rb_fde_t *F);
const char *rb_get_ssl_strerror(rb_fde_t *F);
int rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method);
rb_fde_t *rb_get_fde(int fd);
int rb_send_fd_buf(rb_fde_t *xF, rb_fde_t **F, int count, void *data, size_t datasize, pid_t pid);
int rb_recv_fd_buf(rb_fde_t *F, void *data, size_t datasize, rb_fde_t **xF, int count);
void rb_set_type(rb_fde_t *F, uint8_t type);
uint8_t rb_get_type(rb_fde_t *F);
const char *rb_get_iotype(void);
typedef enum
{
RB_PRNG_FILE,
#ifdef _WIN32
RB_PRNGWIN32,
#endif
RB_PRNG_DEFAULT,
} prng_seed_t;
int rb_init_prng(const char *path, prng_seed_t seed_type);
int rb_get_random(void *buf, size_t len);
void rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout);
void rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout);
int rb_supports_ssl(void);
unsigned int rb_ssl_handshake_count(rb_fde_t *F);
void rb_ssl_clear_handshake_count(rb_fde_t *F);
int rb_pass_fd_to_process(rb_fde_t *, pid_t, rb_fde_t *);
rb_fde_t *rb_recv_fd(rb_fde_t *);
const char *rb_ssl_get_cipher(rb_fde_t *F);
#endif /* INCLUDED_commio_h */

View file

@ -0,0 +1,63 @@
/*
* ircd-ratbox: A slightly useful ircd
* helper.h: Starts and deals with ircd helpers
*
* Copyright (C) 2006 Aaron Sethman <androsyn@ratbox.org>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
* $Id: rb_helper.h 26092 2008-09-19 15:13:52Z androsyn $
*/
#ifndef RB_LIB_H
# error "Do not use helper.h directly"
#endif
#ifndef INCLUDED_helper_h
#define INCLUDED_helper_h
struct _rb_helper;
typedef struct _rb_helper rb_helper;
typedef void rb_helper_cb(rb_helper *);
rb_helper *rb_helper_start(const char *name, const char *fullpath, rb_helper_cb * read_cb,
rb_helper_cb * error_cb);
rb_helper *rb_helper_child(rb_helper_cb * read_cb, rb_helper_cb * error_cb,
log_cb * ilog, restart_cb * irestart, die_cb * idie,
size_t lb_heap_size, size_t dh_size, size_t fd_heap_size);
void rb_helper_restart(rb_helper *helper);
#ifdef __GNUC__
void
rb_helper_write(rb_helper *helper, const char *format, ...)
__attribute((format(printf, 2, 3)));
void rb_helper_write_queue(rb_helper *helper, const char *format, ...)
__attribute((format(printf, 2, 3)));
#else
void rb_helper_write(rb_helper *helper, const char *format, ...);
void rb_helper_write_queue(rb_helper *helper, const char *format, ...);
#endif
void rb_helper_write_flush(rb_helper *helper);
void rb_helper_run(rb_helper *helper);
void rb_helper_close(rb_helper *helper);
int rb_helper_read(rb_helper *helper, void *buf, size_t bufsize);
void rb_helper_loop(rb_helper *helper, long delay) __attribute__((noreturn));
#endif

View file

@ -0,0 +1,86 @@
/*
* ircd-ratbox: A slightly useful ircd.
* memory.h: A header for the memory functions.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
* $Id: rb_memory.h 26092 2008-09-19 15:13:52Z androsyn $
*/
#ifndef RB_LIB_H
#error "Do not use rb_memory.h directly"
#endif
#ifndef _RB_MEMORY_H
#define _RB_MEMORY_H
#include <stdlib.h>
void rb_outofmemory(void) __attribute__((noreturn));
static inline void *
rb_malloc(size_t size)
{
void *ret = calloc(1, size);
if(rb_unlikely(ret == NULL))
rb_outofmemory();
return (ret);
}
static inline void *
rb_realloc(void *x, size_t y)
{
void *ret = realloc(x, y);
if(rb_unlikely(ret == NULL))
rb_outofmemory();
return (ret);
}
static inline char *
rb_strndup(const char *x, size_t y)
{
char *ret = malloc(y);
if(rb_unlikely(ret == NULL))
rb_outofmemory();
rb_strlcpy(ret, x, y);
return (ret);
}
static inline char *
rb_strdup(const char *x)
{
char *ret = malloc(strlen(x) + 1);
if(rb_unlikely(ret == NULL))
rb_outofmemory();
strcpy(ret, x);
return (ret);
}
static inline void
rb_free(void *ptr)
{
if(rb_likely(ptr != NULL))
free(ptr);
}
#endif /* _I_MEMORY_H */

508
libratbox/install-sh Executable file
View file

@ -0,0 +1,508 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2014-09-12.12; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
tab=' '
nl='
'
IFS=" $tab$nl"
# Set DOITPROG to "echo" to test this script.
doit=${DOITPROG-}
doit_exec=${doit:-exec}
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_mkdir=
# Desired mode of installed file.
mode=0755
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
is_target_a_directory=possibly
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t)
is_target_a_directory=always
dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) is_target_a_directory=never;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.
if test -n "$dir_arg"; then
if test -n "$dst_arg"; then
echo "$0: target directory not allowed when installing a directory." >&2
exit 1
fi
fi
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
if test $# -gt 1 || test "$is_target_a_directory" = always; then
if test ! -d "$dst_arg"; then
echo "$0: $dst_arg: Is not a directory." >&2
exit 1
fi
fi
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
dstdir=`dirname "$dst"`
test -d "$dstdir"
dstdir_status=$?
fi
fi
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
# $RANDOM is not portable (e.g. dash); use it when possible to
# lower collision chance
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
# As "mkdir -p" follows symlinks and we work in /tmp possibly; so
# create the $tmpdir first (and fail if unsuccessful) to make sure
# that nobody tries to guess the $tmpdir name.
if (umask $mkdir_umask &&
$mkdirprog $mkdir_mode "$tmpdir" &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
test_tmpdir="$tmpdir/a"
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
oIFS=$IFS
IFS=/
set -f
set fnord $dstdir
shift
set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

11156
libratbox/ltmain.sh Normal file

File diff suppressed because it is too large Load diff

215
libratbox/missing Executable file
View file

@ -0,0 +1,215 @@
#! /bin/sh
# Common wrapper for a few potentially missing GNU programs.
scriptversion=2013-10-28.13; # UTC
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# 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, 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, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
case $1 in
--is-lightweight)
# Used by our autoconf macros to check whether the available missing
# script is modern enough.
exit 0
;;
--run)
# Back-compat with the calling convention used by older automake.
shift
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
to PROGRAM being missing or too old.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal autoconf autoheader autom4te automake makeinfo
bison yacc flex lex help2man
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
'g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: unknown '$1' option"
echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
# Run the given program, remember its exit status.
"$@"; st=$?
# If it succeeded, we are done.
test $st -eq 0 && exit 0
# Also exit now if we it failed (or wasn't found), and '--version' was
# passed; such an option is passed most likely to detect whether the
# program is present and works.
case $2 in --version|--help) exit $st;; esac
# Exit code 63 means version mismatch. This often happens when the user
# tries to use an ancient version of a tool on a file that requires a
# minimum version.
if test $st -eq 63; then
msg="probably too old"
elif test $st -eq 127; then
# Program was missing.
msg="missing on your system"
else
# Program was found and executed, but failed. Give up.
exit $st
fi
perl_URL=http://www.perl.org/
flex_URL=http://flex.sourceforge.net/
gnu_software_URL=http://www.gnu.org/software
program_details ()
{
case $1 in
aclocal|automake)
echo "The '$1' program is part of the GNU Automake package:"
echo "<$gnu_software_URL/automake>"
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/autoconf>"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
autoconf|autom4te|autoheader)
echo "The '$1' program is part of the GNU Autoconf package:"
echo "<$gnu_software_URL/autoconf/>"
echo "It also requires GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
esac
}
give_advice ()
{
# Normalize program name to check for.
normalized_program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
printf '%s\n' "'$1' is $msg."
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
case $normalized_program in
autoconf*)
echo "You should only need it if you modified 'configure.ac',"
echo "or m4 files included by it."
program_details 'autoconf'
;;
autoheader*)
echo "You should only need it if you modified 'acconfig.h' or"
echo "$configure_deps."
program_details 'autoheader'
;;
automake*)
echo "You should only need it if you modified 'Makefile.am' or"
echo "$configure_deps."
program_details 'automake'
;;
aclocal*)
echo "You should only need it if you modified 'acinclude.m4' or"
echo "$configure_deps."
program_details 'aclocal'
;;
autom4te*)
echo "You might have modified some maintainer files that require"
echo "the 'autom4te' program to be rebuilt."
program_details 'autom4te'
;;
bison*|yacc*)
echo "You should only need it if you modified a '.y' file."
echo "You may want to install the GNU Bison package:"
echo "<$gnu_software_URL/bison/>"
;;
lex*|flex*)
echo "You should only need it if you modified a '.l' file."
echo "You may want to install the Fast Lexical Analyzer package:"
echo "<$flex_URL>"
;;
help2man*)
echo "You should only need it if you modified a dependency" \
"of a man page."
echo "You may want to install the GNU Help2man package:"
echo "<$gnu_software_URL/help2man/>"
;;
makeinfo*)
echo "You should only need it if you modified a '.texi' file, or"
echo "any other file indirectly affecting the aspect of the manual."
echo "You might want to install the Texinfo package:"
echo "<$gnu_software_URL/texinfo/>"
echo "The spurious makeinfo call might also be the consequence of"
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
echo "want to install GNU make:"
echo "<$gnu_software_URL/make/>"
;;
*)
echo "You might have modified some files without having the proper"
echo "tools for further handling them. Check the 'README' file, it"
echo "often tells you about the needed prerequisites for installing"
echo "this package. You may also peek at any GNU archive site, in"
echo "case some other package contains this missing '$1' program."
;;
esac
}
give_advice "$1" | sed -e '1s/^/WARNING: /' \
-e '2,$s/^/ /' >&2
# Propagate the correct exit status (expected to be 127 for a program
# not found, 63 for a program that failed due to version mismatch).
exit $st
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

736
libratbox/src/Makefile.in Normal file
View file

@ -0,0 +1,736 @@
# Makefile.in generated by automake 1.15.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2017 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# $Id: Makefile.am 26046 2008-09-09 16:37:30Z androsyn $
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = src
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/libratbox_config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
test -z "$$files" \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
am__installdirs = "$(DESTDIR)$(libdir)"
LTLIBRARIES = $(lib_LTLIBRARIES)
libratbox_la_DEPENDENCIES =
am_libratbox_la_OBJECTS = unix.lo win32.lo crypt.lo balloc.lo \
commio.lo mbedtls.lo openssl.lo gnutls.lo nossl.lo event.lo \
ratbox_lib.lo rb_memory.lo linebuf.lo snprintf.lo tools.lo \
helper.lo devpoll.lo epoll.lo poll.lo ports.lo sigio.lo \
select.lo kqueue.lo rawbuf.lo patricia.lo arc4random.lo \
version.lo
libratbox_la_OBJECTS = $(am_libratbox_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
libratbox_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libratbox_la_LDFLAGS) $(LDFLAGS) -o $@
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(libratbox_la_SOURCES)
DIST_SOURCES = $(libratbox_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AS = @AS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CP = @CP@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
GNUTLS_LIBS = @GNUTLS_LIBS@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN = @LN@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@
MBEDTLS_LIBS = @MBEDTLS_LIBS@
MKDIR_P = @MKDIR_P@
MV = @MV@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PICFLAGS = @PICFLAGS@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
RANLIB = @RANLIB@
RB_PREFIX = @RB_PREFIX@
RM = @RM@
SED = @SED@
SEDOBJ = @SEDOBJ@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SSL_CFLAGS = @SSL_CFLAGS@
SSL_LIBS = @SSL_LIBS@
STRIP = @STRIP@
TOUCH = @TOUCH@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = foreign
INCLUDES = -I. -I../include @SSL_CFLAGS@ @GNUTLS_CFLAGS@ @MBEDTLS_CFLAGS@
BUILT_SOURCES = version.c
libratbox_la_SOURCES = \
unix.c \
win32.c \
crypt.c \
balloc.c \
commio.c \
mbedtls.c \
openssl.c \
gnutls.c \
nossl.c \
event.c \
ratbox_lib.c \
rb_memory.c \
linebuf.c \
snprintf.c \
tools.c \
helper.c \
devpoll.c \
epoll.c \
poll.c \
ports.c \
sigio.c \
select.c \
kqueue.c \
rawbuf.c \
patricia.c \
arc4random.c \
version.c
libratbox_la_LDFLAGS = @SSL_LIBS@ @GNUTLS_LIBS@ @MBEDTLS_LIBS@ -avoid-version -no-undefined -export-symbols export-syms.txt
libratbox_la_LIBADD = @SSL_LIBS@ @GNUTLS_LIBS@ @MBEDTLS_LIBS@
lib_LTLIBRARIES = libratbox.la
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign src/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
list2="$$list2 $$p"; \
else :; fi; \
done; \
test -z "$$list2" || { \
echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
$(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
}
uninstall-libLTLIBRARIES:
@$(NORMAL_UNINSTALL)
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
for p in $$list; do \
$(am__strip_dir) \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
done
clean-libLTLIBRARIES:
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
@list='$(lib_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
test -z "$$locs" || { \
echo rm -f $${locs}; \
rm -f $${locs}; \
}
libratbox.la: $(libratbox_la_OBJECTS) $(libratbox_la_DEPENDENCIES) $(EXTRA_libratbox_la_DEPENDENCIES)
$(AM_V_CCLD)$(libratbox_la_LINK) -rpath $(libdir) $(libratbox_la_OBJECTS) $(libratbox_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arc4random.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/balloc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/commio.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypt.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/devpoll.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epoll.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnutls.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helper.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kqueue.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linebuf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbedtls.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nossl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/patricia.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poll.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ports.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ratbox_lib.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rawbuf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rb_memory.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/select.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sigio.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snprintf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tools.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win32.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) check-am
all-am: Makefile $(LTLIBRARIES)
installdirs:
for dir in "$(DESTDIR)$(libdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
clean: clean-am
clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am: install-libLTLIBRARIES
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-libLTLIBRARIES
.MAKE: all check install install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \
ctags-am distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-libLTLIBRARIES install-man install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES
.PRECIOUS: Makefile
version.c: version.c.SH ../CREDITS
$(SHELL) ./version.c.SH
$(CP) version.c version.c.last
version.lo: version.c ../include/serno.h
$(LIBTOOL) --mode=compile $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

601
libratbox/src/balloc.c Normal file
View file

@ -0,0 +1,601 @@
/*
* ircd-ratbox: A slightly useful ircd.
* balloc.c: A block allocator.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2006 ircd-ratbox development team
*
* Below are the orignal headers from the old blalloc.c
*
* File: blalloc.c
* Owner: Wohali (Joan Touzet)
*
* Modified 2001/11/29 for mmap() support by Aaron Sethman <androsyn@ratbox.org>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
* $Id: balloc.c 26100 2008-09-20 01:27:19Z androsyn $
*/
/*
* About the block allocator
*
* Basically we have three ways of getting memory off of the operating
* system. Below are this list of methods and the order of preference.
*
* 1. mmap() anonymous pages with the MMAP_ANON flag.
* 2. mmap() via the /dev/zero trick.
* 3. HeapCreate/HeapAlloc (on win32)
* 4. malloc()
*
* The advantages of 1 and 2 are this. We can munmap() the pages which will
* return the pages back to the operating system, thus reducing the size
* of the process as the memory is unused. malloc() on many systems just keeps
* a heap of memory to itself, which never gets given back to the OS, except on
* exit. This of course is bad, if say we have an event that causes us to allocate
* say, 200MB of memory, while our normal memory consumption would be 15MB. In the
* malloc() case, the amount of memory allocated to our process never goes down, as
* malloc() has it locked up in its heap. With the mmap() method, we can munmap()
* the block and return it back to the OS, thus causing our memory consumption to go
* down after we no longer need it.
*
*
*
*/
#include <libratbox_config.h>
#include <ratbox_lib.h>
#ifndef NOBALLOC
#ifdef HAVE_MMAP /* We've got mmap() that is good */
#include <sys/mman.h>
/* HP-UX sucks */
#ifdef MAP_ANONYMOUS
#ifndef MAP_ANON
#define MAP_ANON MAP_ANONYMOUS
#endif
#endif
#endif
#endif
static uintptr_t offset_pad;
/* status information for an allocated block in heap */
struct rb_heap_block
{
size_t alloc_size;
rb_dlink_node node;
unsigned long free_count;
void *elems; /* Points to allocated memory */
};
typedef struct rb_heap_block rb_heap_block;
/* information for the root node of the heap */
struct rb_bh
{
rb_dlink_node hlist;
size_t elemSize; /* Size of each element to be stored */
unsigned long elemsPerBlock; /* Number of elements per block */
rb_dlink_list block_list;
rb_dlink_list free_list;
char *desc;
};
#ifndef NOBALLOC
static int newblock(rb_bh *bh);
static void rb_bh_gc_event(void *unused);
#endif /* !NOBALLOC */
static rb_dlink_list *heap_lists;
#if defined(WIN32)
static HANDLE block_heap;
#endif
#define rb_bh_fail(x) _rb_bh_fail(x, __FILE__, __LINE__)
static void __attribute__((noreturn))
_rb_bh_fail(const char *reason, const char *file, int line)
{
rb_lib_log("rb_heap_blockheap failure: %s (%s:%d)", reason, file, line);
abort();
}
#ifndef NOBALLOC
/*
* static inline void free_block(void *ptr, size_t size)
*
* Inputs: The block and its size
* Output: None
* Side Effects: Returns memory for the block back to the OS
*/
static inline void
free_block(void *ptr, size_t size)
{
#ifdef HAVE_MMAP
munmap(ptr, size);
#else
#ifdef _WIN32
HeapFree(block_heap, 0, ptr);
#else
free(ptr);
#endif
#endif
}
#endif /* !NOBALLOC */
/*
* void rb_init_bh(void)
*
* Inputs: None
* Outputs: None
* Side Effects: Initializes the block heap
*/
void
rb_init_bh(void)
{
heap_lists = rb_malloc(sizeof(rb_dlink_list));
offset_pad = sizeof(void *);
/* XXX if you get SIGBUS when trying to use a long long..here is where you need to
* fix your shit
*/
#ifdef __sparc__
if((offset_pad % __alignof__(long long)) != 0)
{
offset_pad += __alignof__(long long);
offset_pad &= ~(__alignof__(long long) - 1);
}
#endif
#ifndef NOBALLOC
#ifdef _WIN32
block_heap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
#endif
rb_event_addish("rb_bh_gc_event", rb_bh_gc_event, NULL, 300);
#endif /* !NOBALLOC */
}
#ifndef NOBALLOC
/*
* static inline void *get_block(size_t size)
*
* Input: Size of block to allocate
* Output: Pointer to new block
* Side Effects: None
*/
static inline void *
get_block(size_t size)
{
void *ptr;
#ifdef HAVE_MMAP
#ifdef MAP_ANON
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
#else
int zero_fd;
zero_fd = open("/dev/zero", O_RDWR);
if(zero_fd < 0)
rb_bh_fail("Failed opening /dev/zero");
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0);
close(zero_fd);
#endif /* MAP_ANON */
if(ptr == MAP_FAILED)
ptr = NULL;
#else
#ifdef _WIN32
ptr = HeapAlloc(block_heap, 0, size);
#else
ptr = malloc(size);
#endif
#endif
return (ptr);
}
static void
rb_bh_gc_event(void *unused)
{
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, heap_lists->head)
{
rb_bh_gc(ptr->data);
}
}
/* ************************************************************************ */
/* FUNCTION DOCUMENTATION: */
/* newblock */
/* Description: */
/* Allocates a new block for addition to a blockheap */
/* Parameters: */
/* bh (IN): Pointer to parent blockheap. */
/* Returns: */
/* 0 if successful, 1 if not */
/* ************************************************************************ */
static int
newblock(rb_bh *bh)
{
rb_heap_block *b;
unsigned long i;
uintptr_t offset;
rb_dlink_node *node;
/* Setup the initial data structure. */
b = rb_malloc(sizeof(rb_heap_block));
b->alloc_size = bh->elemsPerBlock * bh->elemSize;
b->elems = get_block(b->alloc_size);
if(rb_unlikely(b->elems == NULL))
{
rb_free(b);
return (1);
}
offset = (uintptr_t)b->elems;
/* Setup our blocks now */
for(i = 0; i < bh->elemsPerBlock; i++, offset += bh->elemSize)
{
*((void **)offset) = b;
node = (void *)(offset + offset_pad);
rb_dlinkAdd((void *)offset, node, &bh->free_list);
}
rb_dlinkAdd(b, &b->node, &bh->block_list);
b->free_count = bh->elemsPerBlock;
return (0);
}
#endif /* !NOBALLOC */
/* ************************************************************************ */
/* FUNCTION DOCUMENTATION: */
/* rb_bh_create */
/* Description: */
/* Creates a new blockheap from which smaller blocks can be allocated. */
/* Intended to be used instead of multiple calls to malloc() when */
/* performance is an issue. */
/* Parameters: */
/* elemsize (IN): Size of the basic element to be stored */
/* elemsperblock (IN): Number of elements to be stored in a single block */
/* of memory. When the blockheap runs out of free memory, it will */
/* allocate elemsize * elemsperblock more. */
/* Returns: */
/* Pointer to new rb_bh, or NULL if unsuccessful */
/* ************************************************************************ */
rb_bh *
rb_bh_create(size_t elemsize, int elemsperblock, const char *desc)
{
rb_bh *bh;
lrb_assert(elemsize > 0 && elemsperblock > 0);
lrb_assert(elemsize >= sizeof(rb_dlink_node));
/* Catch idiotic requests up front */
if((elemsize == 0) || (elemsperblock <= 0))
{
rb_bh_fail("Attempting to rb_bh_create idiotic sizes");
}
if(elemsize < sizeof(rb_dlink_node))
rb_bh_fail("Attempt to rb_bh_create smaller than sizeof(rb_dlink_node)");
/* Allocate our new rb_bh */
bh = rb_malloc(sizeof(rb_bh));
#ifndef NOBALLOC
elemsize += offset_pad;
if((elemsize % sizeof(void *)) != 0)
{
/* Pad to even pointer boundary */
elemsize += sizeof(void *);
elemsize &= ~(sizeof(void *) - 1);
}
#endif
bh->elemSize = elemsize;
bh->elemsPerBlock = elemsperblock;
if(desc != NULL)
bh->desc = rb_strdup(desc);
#ifndef NOBALLOC
/* Be sure our malloc was successful */
if(newblock(bh))
{
if(bh != NULL)
free(bh);
rb_lib_log("newblock() failed");
rb_outofmemory(); /* die.. out of memory */
}
#endif /* !NOBALLOC */
if(bh == NULL)
{
rb_bh_fail("bh == NULL when it shouldn't be");
}
rb_dlinkAdd(bh, &bh->hlist, heap_lists);
return (bh);
}
/* ************************************************************************ */
/* FUNCTION DOCUMENTATION: */
/* rb_bh_alloc */
/* Description: */
/* Returns a pointer to a struct within our rb_bh that's free for */
/* the taking. */
/* Parameters: */
/* bh (IN): Pointer to the Blockheap. */
/* Returns: */
/* Pointer to a structure (void *), or NULL if unsuccessful. */
/* ************************************************************************ */
void *
rb_bh_alloc(rb_bh *bh)
{
#ifndef NOBALLOC
rb_dlink_node *new_node;
rb_heap_block **block;
void *ptr;
#endif
lrb_assert(bh != NULL);
if(rb_unlikely(bh == NULL))
{
rb_bh_fail("Cannot allocate if bh == NULL");
}
#ifdef NOBALLOC
return (rb_malloc(bh->elemSize));
#else
if(bh->free_list.head == NULL)
{
/* Allocate new block and assign */
/* newblock returns 1 if unsuccessful, 0 if not */
if(rb_unlikely(newblock(bh)))
{
rb_lib_log("newblock() failed");
rb_outofmemory(); /* Well that didn't work either...bail */
}
if(bh->free_list.head == NULL)
{
rb_lib_log("out of memory after newblock()...");
rb_outofmemory();
}
}
new_node = bh->free_list.head;
block = (rb_heap_block **) new_node->data;
ptr = (void *)((uintptr_t)new_node->data + (uintptr_t)offset_pad);
rb_dlinkDelete(new_node, &bh->free_list);
(*block)->free_count--;
memset(ptr, 0, bh->elemSize - offset_pad);
return (ptr);
#endif
}
/* ************************************************************************ */
/* FUNCTION DOCUMENTATION: */
/* rb_bh_free */
/* Description: */
/* Returns an element to the free pool, does not free() */
/* Parameters: */
/* bh (IN): Pointer to rb_bh containing element */
/* ptr (in): Pointer to element to be "freed" */
/* Returns: */
/* 0 if successful, 1 if element not contained within rb_bh. */
/* ************************************************************************ */
int
rb_bh_free(rb_bh *bh, void *ptr)
{
#ifndef NOBALLOC
rb_heap_block *block;
void *data;
#endif
lrb_assert(bh != NULL);
lrb_assert(ptr != NULL);
if(rb_unlikely(bh == NULL))
{
rb_lib_log("balloc.c:rb_bhFree() bh == NULL");
return (1);
}
if(rb_unlikely(ptr == NULL))
{
rb_lib_log("balloc.rb_bhFree() ptr == NULL");
return (1);
}
#ifdef NOBALLOC
rb_free(ptr);
#else
data = (void *)((uintptr_t)ptr - (uintptr_t)offset_pad);
block = *(rb_heap_block **) data;
/* XXX */
if(rb_unlikely
(!((uintptr_t)ptr >= (uintptr_t)block->elems
&& (uintptr_t)ptr < (uintptr_t)block->elems + (uintptr_t)block->alloc_size)))
{
rb_bh_fail("rb_bh_free() bogus pointer");
}
block->free_count++;
rb_dlinkAdd(data, (rb_dlink_node *)ptr, &bh->free_list);
#endif /* !NOBALLOC */
return (0);
}
/* ************************************************************************ */
/* FUNCTION DOCUMENTATION: */
/* rb_bhDestroy */
/* Description: */
/* Completely free()s a rb_bh. Use for cleanup. */
/* Parameters: */
/* bh (IN): Pointer to the rb_bh to be destroyed. */
/* Returns: */
/* 0 if successful, 1 if bh == NULL */
/* ************************************************************************ */
int
rb_bh_destroy(rb_bh *bh)
{
#ifndef NOBALLOC
rb_dlink_node *ptr, *next;
rb_heap_block *b;
#endif
if(bh == NULL)
return (1);
#ifndef NOBALLOC
RB_DLINK_FOREACH_SAFE(ptr, next, bh->block_list.head)
{
b = ptr->data;
free_block(b->elems, b->alloc_size);
rb_free(b);
}
#endif /* !NOBALLOC */
rb_dlinkDelete(&bh->hlist, heap_lists);
rb_free(bh->desc);
rb_free(bh);
return (0);
}
void
rb_bh_usage(rb_bh *bh, size_t *bused, size_t *bfree, size_t *bmemusage, const char **desc)
{
#ifndef NOBALLOC
size_t used, freem, memusage;
if(bh == NULL)
{
return;
}
freem = rb_dlink_list_length(&bh->free_list);
used = (rb_dlink_list_length(&bh->block_list) * bh->elemsPerBlock) - freem;
memusage = used * bh->elemSize;
if(bused != NULL)
*bused = used;
if(bfree != NULL)
*bfree = freem;
if(bmemusage != NULL)
*bmemusage = memusage;
if(desc != NULL)
*desc = bh->desc;
#else
if(bused != NULL)
*bused = 0;
if(bfree != NULL)
*bfree = 0;
if(bmemusage != NULL)
*bmemusage = 0;
if(desc != NULL)
*desc = "no blockheap";
#endif
}
void
rb_bh_usage_all(rb_bh_usage_cb *cb, void *data)
{
rb_dlink_node *ptr;
rb_bh *bh;
size_t used, freem, memusage, heapalloc;
static const char *unnamed = "(unnamed_heap)";
const char *desc = unnamed;
if(cb == NULL)
return;
RB_DLINK_FOREACH(ptr, heap_lists->head)
{
bh = (rb_bh *)ptr->data;
freem = rb_dlink_list_length(&bh->free_list);
used = (rb_dlink_list_length(&bh->block_list) * bh->elemsPerBlock) - freem;
memusage = used * bh->elemSize;
heapalloc = (freem + used) * bh->elemSize;
if(bh->desc != NULL)
desc = bh->desc;
cb(used, freem, memusage, heapalloc, desc, data);
}
return;
}
void
rb_bh_total_usage(size_t *total_alloc, size_t *total_used)
{
rb_dlink_node *ptr;
size_t total_memory = 0, used_memory = 0, used, freem;
rb_bh *bh;
RB_DLINK_FOREACH(ptr, heap_lists->head)
{
bh = (rb_bh *)ptr->data;
freem = rb_dlink_list_length(&bh->free_list);
used = (rb_dlink_list_length(&bh->block_list) * bh->elemsPerBlock) - freem;
used_memory += used * bh->elemSize;
total_memory += (freem + used) * bh->elemSize;
}
if(total_alloc != NULL)
*total_alloc = total_memory;
if(total_used != NULL)
*total_used = used_memory;
}
#ifndef NOBALLOC
int
rb_bh_gc(rb_bh *bh)
{
rb_heap_block *b;
rb_dlink_node *ptr, *next;
unsigned long i;
uintptr_t offset;
if(bh == NULL)
{
/* somebody is smoking some craq..(probably lee, but don't tell him that) */
return (1);
}
if((rb_dlink_list_length(&bh->free_list) < bh->elemsPerBlock)
|| rb_dlink_list_length(&bh->block_list) == 1)
{
/* There couldn't possibly be an entire free block. Return. */
return (0);
}
RB_DLINK_FOREACH_SAFE(ptr, next, bh->block_list.head)
{
b = ptr->data;
if(rb_dlink_list_length(&bh->block_list) == 1)
return (0);
if(b->free_count == bh->elemsPerBlock)
{
/* i'm seriously going to hell for this.. */
offset = (uintptr_t)b->elems;
for(i = 0; i < bh->elemsPerBlock; i++, offset += (uintptr_t)bh->elemSize)
{
rb_dlinkDelete((rb_dlink_node *)(offset + offset_pad),
&bh->free_list);
}
rb_dlinkDelete(&b->node, &bh->block_list);
free_block(b->elems, b->alloc_size);
rb_free(b);
}
}
return (0);
}
#endif /* !NOBALLOC */

2279
libratbox/src/commio.c Normal file

File diff suppressed because it is too large Load diff

2313
libratbox/src/crypt.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,170 @@
rb_bh_alloc
rb_bh_create
rb_bh_destroy
rb_bh_free
rb_bh_gc
rb_bh_total_usage
rb_bh_usage
rb_bh_usage_all
rb_init_bh
rb_accept_tcp
rb_checktimeouts
rb_close
rb_connect_sockaddr
rb_connect_tcp
rb_connect_tcp_ssl
rb_dump_fd
rb_errstr
rb_fd_ssl
rb_fdlist_init
rb_get_fd
rb_get_fde
rb_get_iotype
rb_get_random
rb_get_sockerr
rb_get_ssl_certfp
rb_get_ssl_strerror
rb_get_type
rb_getmaxconnect
rb_ignore_errno
rb_inet_ntop
rb_inet_ntop_sock
rb_inet_pton
rb_inet_pton_sock
rb_init_netio
rb_init_prng
rb_listen
rb_note
rb_open
rb_pipe
rb_read
rb_recv_fd_buf
rb_select
rb_send_fd_buf
rb_set_buffers
rb_set_nb
rb_set_type
rb_setselect
rb_settimeout
rb_setup_fd
rb_setup_ssl_server
rb_setup_ssl_server_hostname
rb_remove_ssl_vserver
rb_socket
rb_socketpair
rb_ssl_listen
rb_ssl_start_accepted
rb_ssl_start_connected
rb_write
rb_writev
rb_crypt
rb_dump_events
rb_event_add
rb_event_addish
rb_event_addonce
rb_event_delete
rb_event_find_delete
rb_event_init
rb_event_next
rb_event_run
rb_event_update
rb_run_event
rb_helper_child
rb_helper_close
rb_helper_loop
rb_helper_read
rb_helper_restart
rb_helper_run
rb_helper_start
rb_helper_write
rb_helper_write_queue
rb_count_rb_linebuf_memory
rb_linebuf_attach
rb_linebuf_donebuf
rb_linebuf_flush
rb_linebuf_get
rb_linebuf_init
rb_linebuf_newbuf
rb_linebuf_parse
rb_linebuf_put
rb_linebuf_putbuf
rb_linebuf_putmsg
make_and_lookup
make_and_lookup_ip
rb_clear_patricia
rb_destroy_patricia
rb_init_patricia
rb_match_exact_string
rb_match_ip
rb_match_ip_exact
rb_match_string
rb_new_patricia
rb_patricia_lookup
rb_patricia_process
rb_patricia_remove
rb_patricia_search_best
rb_patricia_search_best2
rb_patricia_search_exact
rb_base64_decode
rb_base64_encode
rb_ctime
rb_current_time
rb_current_time_tv
rb_date
rb_lib_die
rb_lib_init
rb_lib_log
rb_lib_loop
rb_lib_restart
rb_lib_version
rb_set_time
rb_strtok_r
rb_free_rawbuffer
rb_init_rawbuffers
rb_new_rawbuffer
rb_rawbuf_append
rb_rawbuf_flush
rb_rawbuf_get
rb_rawbuf_length
rb_outofmemory
rb_snprintf
rb_snprintf_append
rb_sprintf
rb_sprintf_append
rb_vsnprintf
rb_vsnprintf_append
rb_vsprintf
rb_vsprintf_append
rb_free_rb_dlink_node
rb_init_rb_dlink_nodes
rb_make_rb_dlink_node
rb_string_to_array
rb_strlcat
rb_strlcpy
rb_strnlen
rb_gettimeofday
rb_sleep
rb_spawn_process
rb_supports_ssl
rb_ssl_handshake_count
rb_ssl_clear_handshake_count
rb_strerror
rb_kill
rb_setenv
rb_getpid
rb_waitpid
rb_basename
rb_dirname
rb_ssl_get_cipher
rb_zstring_alloc
rb_zstring_append_from_c
rb_zstring_append_from_zstring
rb_zstring_deserialize
rb_zstring_free
rb_zstring_from_c
rb_zstring_from_c_len
rb_zstring_len
rb_zstring_serialized
rb_zstring_to_c
rb_zstring_to_c_alloc
rb_zstring_to_ptr

917
libratbox/src/gnutls.c Normal file
View file

@ -0,0 +1,917 @@
/*
* libratbox: a library used by ircd-ratbox and other things
* gnutls.c: gnutls related code
*
* Copyright (C) 2007-2008 ircd-ratbox development team
* Copyright (C) 2007-2008 Aaron Sethman <androsyn@ratbox.org>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
*/
#include <libratbox_config.h>
#include <ratbox_lib.h>
#ifdef HAVE_GNUTLS
#include <commio-int.h>
#include <commio-ssl.h>
#include <gnutls/gnutls.h>
#include <gnutls/abstract.h>
#include <gnutls/x509.h>
#if (GNUTLS_VERSION_MAJOR < 3)
# include <gcrypt.h>
#else
# include <gnutls/crypto.h>
#endif
#include "gnutls_ratbox.h"
typedef enum
{
RB_FD_TLS_DIRECTION_IN = 0,
RB_FD_TLS_DIRECTION_OUT = 1
} rb_fd_tls_direction;
#define SSL_P(x) *((gnutls_session_t *) ((x)->ssl))
// Server side variables
static gnutls_certificate_credentials_t server_cert_key;
static gnutls_dh_params_t server_dhp;
// Client side variables
#define MAX_CERTS 6
static gnutls_x509_crt_t client_cert[MAX_CERTS];
static gnutls_x509_privkey_t client_key;
static unsigned int client_cert_count;
// Shared variables
static gnutls_priority_t default_priority;
struct ssl_connect
{
CNCB *callback;
void *data;
int timeout;
};
static const char *rb_ssl_strerror(int);
static void rb_ssl_connect_realcb(rb_fde_t *, int, struct ssl_connect *);
/*
* Internal GNUTLS-specific code
*/
/*
* We only have one certificate to authenticate with, as both a client and server.
*
* Unfortunately, GNUTLS tries to be clever, and as client, will attempt to use a certificate that the server will
* trust. We usually use self-signed certs, though, so the result of this search is always nothing. Therefore, it
* uses no certificate to authenticate as a client. This is undesirable, as it breaks fingerprint authentication;
* e.g. the connect::fingerprint on the remote ircd will not match.
*
* Thus, we use this callback to force GNUTLS to authenticate with our (server) certificate as a client.
*/
static int
rb_ssl_cert_auth_cb(gnutls_session_t session,
const gnutls_datum_t *const req_ca_rdn, const int req_ca_rdn_len,
const gnutls_pk_algorithm_t *const sign_algos, const int sign_algos_len,
#if (GNUTLS_VERSION_MAJOR < 3)
gnutls_retr_st *const st)
#else
gnutls_retr2_st *const st)
#endif
{
#if (GNUTLS_VERSION_MAJOR < 3)
st->type = GNUTLS_CRT_X509;
#else
st->cert_type = GNUTLS_CRT_X509;
st->key_type = GNUTLS_PRIVKEY_X509;
#endif
st->ncerts = client_cert_count;
st->cert.x509 = client_cert;
st->key.x509 = client_key;
st->deinit_all = 0;
return 0;
}
static ssize_t
rb_sock_net_recv(gnutls_transport_ptr_t context_ptr, void *const buf, const size_t count)
{
const int fd = rb_get_fd((rb_fde_t *)context_ptr);
return recv(fd, buf, count, 0);
}
static ssize_t
rb_sock_net_xmit(gnutls_transport_ptr_t context_ptr, const void *const buf, const size_t count)
{
const int fd = rb_get_fd((rb_fde_t *)context_ptr);
return send(fd, buf, count, 0);
}
static void
rb_ssl_init_fd(rb_fde_t *const F, const rb_fd_tls_direction dir)
{
F->ssl = rb_malloc(sizeof(gnutls_session_t));
if(F->ssl == NULL)
{
rb_lib_log("%s: rb_malloc: allocation failure", __func__);
rb_close(F);
return;
}
unsigned int init_flags = 0;
switch(dir)
{
case RB_FD_TLS_DIRECTION_IN:
init_flags |= GNUTLS_SERVER;
break;
case RB_FD_TLS_DIRECTION_OUT:
init_flags |= GNUTLS_CLIENT;
break;
}
gnutls_init((gnutls_session_t *) F->ssl, init_flags);
gnutls_credentials_set(SSL_P(F), GNUTLS_CRD_CERTIFICATE, server_cert_key);
gnutls_dh_set_prime_bits(SSL_P(F), 2048);
gnutls_transport_set_ptr(SSL_P(F), (gnutls_transport_ptr_t) F);
gnutls_transport_set_pull_function(SSL_P(F), rb_sock_net_recv);
gnutls_transport_set_push_function(SSL_P(F), rb_sock_net_xmit);
if (gnutls_priority_set(SSL_P(F), default_priority) != GNUTLS_E_SUCCESS)
gnutls_set_default_priority(SSL_P(F));
if(dir == RB_FD_TLS_DIRECTION_IN)
gnutls_certificate_server_set_request(SSL_P(F), GNUTLS_CERT_REQUEST);
}
static void
rb_ssl_accept_common(rb_fde_t *const F, void *const data)
{
lrb_assert(F != NULL);
lrb_assert(F->accept != NULL);
lrb_assert(F->accept->callback != NULL);
lrb_assert(F->ssl != NULL);
errno = 0;
const int ret = gnutls_handshake(SSL_P(F));
const int err = errno;
if(ret == GNUTLS_E_AGAIN || (ret == GNUTLS_E_INTERRUPTED && (err == 0 || rb_ignore_errno(err))))
{
unsigned int flags = (gnutls_record_get_direction(SSL_P(F)) == 0) ? RB_SELECT_READ : RB_SELECT_WRITE;
rb_setselect(F, flags, rb_ssl_accept_common, data);
return;
}
// These 2 calls may affect errno, which is why we save it above and restore it below
rb_settimeout(F, 0, NULL, NULL);
rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL);
struct acceptdata *const ad = F->accept;
F->accept = NULL;
if(ret == GNUTLS_E_SUCCESS)
{
F->handshake_count++;
ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data);
}
else if(ret == GNUTLS_E_INTERRUPTED && err != 0)
{
errno = err;
ad->callback(F, RB_ERROR, NULL, 0, ad->data);
}
else
{
errno = EIO;
F->ssl_errno = (unsigned long) -ret;
ad->callback(F, RB_ERROR_SSL, NULL, 0, ad->data);
}
rb_free(ad);
}
static void
rb_ssl_connect_common(rb_fde_t *const F, void *const data)
{
lrb_assert(F != NULL);
lrb_assert(F->ssl != NULL);
errno = 0;
const int ret = gnutls_handshake(SSL_P(F));
const int err = errno;
if(ret == GNUTLS_E_AGAIN || (ret == GNUTLS_E_INTERRUPTED && (err == 0 || rb_ignore_errno(err))))
{
unsigned int flags = (gnutls_record_get_direction(SSL_P(F)) == 0) ? RB_SELECT_READ : RB_SELECT_WRITE;
rb_setselect(F, flags, rb_ssl_connect_common, data);
return;
}
// These 2 calls may affect errno, which is why we save it above and restore it below
rb_settimeout(F, 0, NULL, NULL);
rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL);
struct ssl_connect *const sconn = data;
if(ret == GNUTLS_E_SUCCESS)
{
F->handshake_count++;
rb_ssl_connect_realcb(F, RB_OK, sconn);
}
else if(ret == GNUTLS_E_INTERRUPTED && err != 0)
{
errno = err;
rb_ssl_connect_realcb(F, RB_ERROR, sconn);
}
else
{
errno = EIO;
F->ssl_errno = (unsigned long) -ret;
rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
}
}
static const char *
rb_ssl_strerror(const int err)
{
return gnutls_strerror(err);
}
static ssize_t
rb_ssl_read_or_write(const int r_or_w, rb_fde_t *const F, void *const rbuf, const void *const wbuf, const size_t count)
{
ssize_t ret;
errno = 0;
if(r_or_w == 0)
ret = gnutls_record_recv(SSL_P(F), rbuf, count);
else
ret = gnutls_record_send(SSL_P(F), wbuf, count);
if(ret >= 0)
return ret;
if(ret == GNUTLS_E_AGAIN || (ret == GNUTLS_E_INTERRUPTED && (errno == 0 || rb_ignore_errno(errno))))
{
if(gnutls_record_get_direction(SSL_P(F)) == 0)
return RB_RW_SSL_NEED_READ;
else
return RB_RW_SSL_NEED_WRITE;
}
if(ret == GNUTLS_E_INTERRUPTED && errno != 0)
return RB_RW_IO_ERROR;
errno = EIO;
F->ssl_errno = (unsigned long) -ret;
return RB_RW_SSL_ERROR;
}
#if (GNUTLS_VERSION_MAJOR < 3)
static void
rb_gcry_random_seed(void *const unused)
{
gcry_fast_random_poll();
}
#endif
static void
rb_free_datum_t(gnutls_datum_t *const datum)
{
if(datum == NULL)
return;
rb_free(datum->data);
rb_free(datum);
}
static gnutls_datum_t *
rb_load_file_into_datum_t(const char *const file)
{
const int datum_fd = open(file, O_RDONLY);
if(datum_fd < 0)
return NULL;
struct stat fileinfo;
if(fstat(datum_fd, &fileinfo) != 0)
{
(void) close(datum_fd);
return NULL;
}
const size_t datum_size = (fileinfo.st_size < 131072) ? (size_t) fileinfo.st_size : 131072;
if(datum_size == 0)
{
(void) close(datum_fd);
return NULL;
}
gnutls_datum_t *datum;
if((datum = rb_malloc(sizeof *datum)) == NULL)
{
(void) close(datum_fd);
return NULL;
}
if((datum->data = rb_malloc(datum_size + 1)) == NULL)
{
rb_free(datum);
(void) close(datum_fd);
return NULL;
}
for(size_t data_read = 0; data_read < datum_size; )
{
ssize_t ret = read(datum_fd, ((unsigned char *)datum->data) + data_read, datum_size - data_read);
if(ret <= 0)
{
rb_free_datum_t(datum);
(void) close(datum_fd);
return NULL;
}
data_read += (size_t) ret;
}
(void) close(datum_fd);
datum->data[datum_size] = '\0';
datum->size = (unsigned int) datum_size;
return datum;
}
static int
make_certfp(gnutls_x509_crt_t cert, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method)
{
int ret;
int hashlen;
gnutls_digest_algorithm_t md_type;
int spki = 0;
switch(method)
{
case RB_SSL_CERTFP_METH_CERT_SHA1:
hashlen = RB_SSL_CERTFP_LEN_SHA1;
md_type = GNUTLS_DIG_SHA1;
break;
case RB_SSL_CERTFP_METH_SPKI_SHA256:
spki = 1;
case RB_SSL_CERTFP_METH_CERT_SHA256:
hashlen = RB_SSL_CERTFP_LEN_SHA256;
md_type = GNUTLS_DIG_SHA256;
break;
case RB_SSL_CERTFP_METH_SPKI_SHA512:
spki = 1;
case RB_SSL_CERTFP_METH_CERT_SHA512:
hashlen = RB_SSL_CERTFP_LEN_SHA512;
md_type = GNUTLS_DIG_SHA512;
break;
default:
rb_lib_log("%s: invalid method %d", __func__, method);
return 0;
}
if(! spki)
{
size_t digest_size = (size_t) hashlen;
if((ret = gnutls_x509_crt_get_fingerprint(cert, md_type, certfp, &digest_size)) != 0)
{
rb_lib_log("%s: gnutls_x509_crt_get_fingerprint: %d", __func__, ret);
return 0;
}
return hashlen;
}
gnutls_pubkey_t pubkey;
if((ret = gnutls_pubkey_init(&pubkey)) != 0)
{
rb_lib_log("%s: gnutls_pubkey_init: %d", __func__, ret);
return 0;
}
if((ret = gnutls_pubkey_import_x509(pubkey, cert, 0)) != 0)
{
rb_lib_log("%s: gnutls_pubkey_import_x509: %d", __func__, ret);
gnutls_pubkey_deinit(pubkey);
return 0;
}
unsigned char derkey[262144]; // Should be big enough to hold any SubjectPublicKeyInfo structure
size_t derkey_len = sizeof derkey;
if((ret = gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, derkey, &derkey_len)) != 0)
{
rb_lib_log("%s: gnutls_pubkey_export: %d", __func__, ret);
gnutls_pubkey_deinit(pubkey);
return 0;
}
gnutls_pubkey_deinit(pubkey);
if((ret = gnutls_hash_fast(md_type, derkey, derkey_len, certfp)) != 0)
{
rb_lib_log("%s: gnutls_hash_fast: %d", __func__, ret);
return 0;
}
return hashlen;
}
/*
* External GNUTLS-specific code
*/
void
rb_ssl_shutdown(rb_fde_t *const F)
{
if(F == NULL || F->ssl == NULL)
return;
for(int i = 0; i < 4; i++)
{
int ret = gnutls_bye(SSL_P(F), GNUTLS_SHUT_RDWR);
if(ret != GNUTLS_E_INTERRUPTED && ret != GNUTLS_E_AGAIN)
break;
}
gnutls_deinit(SSL_P(F));
rb_free(F->ssl);
F->ssl = NULL;
}
int
rb_init_ssl(void)
{
int ret;
if((ret = gnutls_global_init()) != GNUTLS_E_SUCCESS)
{
rb_lib_log("%s: gnutls_global_init: %s", __func__, rb_ssl_strerror(ret));
return 0;
}
#if (GNUTLS_VERSION_MAJOR < 3)
rb_event_addish("rb_gcry_random_seed", rb_gcry_random_seed, NULL, 300);
#endif
return 1;
}
int
rb_setup_ssl_server(const char *const certfile, const char *keyfile,
const char *const dhfile, const char *cipherlist, char *hostname)
{
if(certfile == NULL)
{
rb_lib_log("%s: no certificate file specified", __func__);
return 0;
}
if(keyfile == NULL)
keyfile = certfile;
if(cipherlist == NULL)
cipherlist = rb_gnutls_default_priority_str;
gnutls_datum_t *const d_cert = rb_load_file_into_datum_t(certfile);
if(d_cert == NULL)
{
rb_lib_log("%s: Error loading certificate: %s", __func__, strerror(errno));
return 0;
}
gnutls_datum_t *const d_key = rb_load_file_into_datum_t(keyfile);
if(d_key == NULL)
{
rb_lib_log("%s: Error loading key: %s", __func__, strerror(errno));
rb_free_datum_t(d_cert);
return 0;
}
int ret;
if((ret = gnutls_certificate_allocate_credentials(&server_cert_key)) != GNUTLS_E_SUCCESS)
{
rb_lib_log("%s: gnutls_certificate_allocate_credentials: %s", __func__, rb_ssl_strerror(ret));
rb_free_datum_t(d_cert);
rb_free_datum_t(d_key);
return 0;
}
#if (GNUTLS_VERSION_MAJOR < 3)
gnutls_certificate_client_set_retrieve_function(server_cert_key, rb_ssl_cert_auth_cb);
#else
gnutls_certificate_set_retrieve_function(server_cert_key, rb_ssl_cert_auth_cb);
#endif
if((ret = gnutls_certificate_set_x509_key_mem(server_cert_key, d_cert, d_key,
GNUTLS_X509_FMT_PEM)) != GNUTLS_E_SUCCESS)
{
rb_lib_log("%s: gnutls_certificate_set_x509_key_mem: %s", __func__, rb_ssl_strerror(ret));
gnutls_certificate_free_credentials(server_cert_key);
rb_free_datum_t(d_cert);
rb_free_datum_t(d_key);
return 0;
}
client_cert_count = MAX_CERTS;
if((ret = gnutls_x509_crt_list_import(client_cert, &client_cert_count, d_cert, GNUTLS_X509_FMT_PEM,
GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED)) < 1)
{
rb_lib_log("%s: gnutls_x509_crt_list_import: %s", __func__, rb_ssl_strerror(ret));
gnutls_certificate_free_credentials(server_cert_key);
rb_free_datum_t(d_cert);
rb_free_datum_t(d_key);
return 0;
}
client_cert_count = (unsigned int) ret;
if((ret = gnutls_x509_privkey_init(&client_key)) != GNUTLS_E_SUCCESS)
{
rb_lib_log("%s: gnutls_x509_privkey_init: %s", __func__, rb_ssl_strerror(ret));
gnutls_certificate_free_credentials(server_cert_key);
for(unsigned int i = 0; i < client_cert_count; i++)
gnutls_x509_crt_deinit(client_cert[i]);
rb_free_datum_t(d_cert);
rb_free_datum_t(d_key);
return 0;
}
if((ret = gnutls_x509_privkey_import(client_key, d_key, GNUTLS_X509_FMT_PEM)) != GNUTLS_E_SUCCESS)
{
rb_lib_log("%s: gnutls_x509_privkey_import: %s", __func__, rb_ssl_strerror(ret));
gnutls_certificate_free_credentials(server_cert_key);
for(unsigned int i = 0; i < client_cert_count; i++)
gnutls_x509_crt_deinit(client_cert[i]);
gnutls_x509_privkey_deinit(client_key);
rb_free_datum_t(d_cert);
rb_free_datum_t(d_key);
return 0;
}
rb_free_datum_t(d_cert);
rb_free_datum_t(d_key);
if(dhfile != NULL)
{
gnutls_datum_t *const d_dhp = rb_load_file_into_datum_t(dhfile);
if(d_dhp == NULL)
{
rb_lib_log("%s: Error parsing DH parameters: %s", __func__, strerror(errno));
gnutls_certificate_free_credentials(server_cert_key);
for(unsigned int i = 0; i < client_cert_count; i++)
gnutls_x509_crt_deinit(client_cert[i]);
gnutls_x509_privkey_deinit(client_key);
return 0;
}
if((ret = gnutls_dh_params_init(&server_dhp)) != GNUTLS_E_SUCCESS)
{
rb_lib_log("%s: Error parsing DH parameters: %s", __func__, rb_ssl_strerror(ret));
gnutls_certificate_free_credentials(server_cert_key);
for(unsigned int i = 0; i < client_cert_count; i++)
gnutls_x509_crt_deinit(client_cert[i]);
gnutls_x509_privkey_deinit(client_key);
rb_free_datum_t(d_dhp);
return 0;
}
if((ret = gnutls_dh_params_import_pkcs3(server_dhp, d_dhp, GNUTLS_X509_FMT_PEM)) != GNUTLS_E_SUCCESS)
{
rb_lib_log("%s: Error parsing DH parameters: %s", __func__, rb_ssl_strerror(ret));
gnutls_certificate_free_credentials(server_cert_key);
for(unsigned int i = 0; i < client_cert_count; i++)
gnutls_x509_crt_deinit(client_cert[i]);
gnutls_x509_privkey_deinit(client_key);
gnutls_dh_params_deinit(server_dhp);
rb_free_datum_t(d_dhp);
return 0;
}
gnutls_certificate_set_dh_params(server_cert_key, server_dhp);
rb_free_datum_t(d_dhp);
}
const char *err = NULL;
if((ret = gnutls_priority_init(&default_priority, cipherlist, &err)) != GNUTLS_E_SUCCESS)
{
rb_lib_log("%s: gnutls_priority_init: %s, error begins at '%s'? -- using defaults instead",
__func__, rb_ssl_strerror(ret), err ? err : "<unknown>");
(void) gnutls_priority_init(&default_priority, NULL, &err);
}
rb_lib_log("%s: TLS configuration successful", __func__);
return 1;
}
int
rb_init_prng(const char *const path, prng_seed_t seed_type)
{
#if (GNUTLS_VERSION_MAJOR < 3)
gcry_fast_random_poll();
rb_lib_log("%s: PRNG initialised", __func__);
#else
rb_lib_log("%s: Skipping PRNG initialisation; not required by GNUTLS v3+ backend", __func__);
#endif
return 1;
}
int
rb_get_random(void *const buf, const size_t length)
{
#if (GNUTLS_VERSION_MAJOR < 3)
gcry_randomize(buf, length, GCRY_STRONG_RANDOM);
#else
gnutls_rnd(GNUTLS_RND_KEY, buf, length);
#endif
return 1;
}
const char *
rb_get_ssl_strerror(rb_fde_t *const F)
{
const int err = (int) F->ssl_errno;
return rb_ssl_strerror(-err);
}
int
rb_get_ssl_certfp(rb_fde_t *const F, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method)
{
int ret;
if(F == NULL || F->ssl == NULL)
{
rb_lib_log("%s: no GNUTLS context", __func__);
return 0;
}
if(gnutls_certificate_type_get(SSL_P(F)) != GNUTLS_CRT_X509)
{
rb_lib_log("%s: not an X.509 certificate", __func__);
return 0;
}
unsigned int cert_list_size = 0;
const gnutls_datum_t *const cert_list = gnutls_certificate_get_peers(SSL_P(F), &cert_list_size);
if(cert_list == NULL || cert_list_size < 1)
{
rb_lib_log("%s: no peer certificate chain returned", __func__);
return 0;
}
gnutls_x509_crt_t peer_cert;
if((ret = gnutls_x509_crt_init(&peer_cert)) != 0)
{
rb_lib_log("%s: gnutls_x509_crt_init: %d", __func__, ret);
return 0;
}
if((ret = gnutls_x509_crt_import(peer_cert, &cert_list[0], GNUTLS_X509_FMT_DER)) < 0)
{
rb_lib_log("%s: gnutls_x509_crt_import: %d", __func__, ret);
gnutls_x509_crt_deinit(peer_cert);
return 0;
}
const int len = make_certfp(peer_cert, certfp, method);
gnutls_x509_crt_deinit(peer_cert);
return len;
}
void
rb_get_ssl_info(char *const buf, const size_t len)
{
(void) rb_snprintf(buf, len, "GNUTLS: compiled (v%s), library (v%s)",
LIBGNUTLS_VERSION, gnutls_check_version(NULL));
}
const char *
rb_ssl_get_cipher(rb_fde_t *const F)
{
if(F == NULL || F->ssl == NULL)
return NULL;
static char buf[512];
gnutls_protocol_t version_ptr = gnutls_protocol_get_version(SSL_P(F));
gnutls_cipher_algorithm_t cipher_ptr = gnutls_cipher_get(SSL_P(F));
const char *const version = gnutls_protocol_get_name(version_ptr);
const char *const cipher = gnutls_cipher_get_name(cipher_ptr);
(void) rb_snprintf(buf, sizeof buf, "%s, %s", version, cipher);
return buf;
}
ssize_t
rb_ssl_read(rb_fde_t *const F, void *const buf, const size_t count)
{
return rb_ssl_read_or_write(0, F, buf, NULL, count);
}
ssize_t
rb_ssl_write(rb_fde_t *const F, const void *const buf, const size_t count)
{
return rb_ssl_read_or_write(1, F, NULL, buf, count);
}
/*
* Internal library-agnostic code
*/
static void
rb_ssl_connect_realcb(rb_fde_t *const F, const int status, struct ssl_connect *const sconn)
{
lrb_assert(F != NULL);
lrb_assert(F->connect != NULL);
F->connect->callback = sconn->callback;
F->connect->data = sconn->data;
rb_connect_callback(F, status);
rb_free(sconn);
}
static void
rb_ssl_timeout_cb(rb_fde_t *const F, void *const data)
{
lrb_assert(F->accept != NULL);
lrb_assert(F->accept->callback != NULL);
F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data);
}
static void
rb_ssl_tryconn_timeout_cb(rb_fde_t *const F, void *const data)
{
rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data);
}
static void
rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data)
{
lrb_assert(F != NULL);
struct ssl_connect *const sconn = data;
if(status != RB_OK)
{
rb_ssl_connect_realcb(F, status, sconn);
return;
}
F->type |= RB_FD_SSL;
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT);
rb_ssl_connect_common(F, sconn);
}
/*
* External library-agnostic code
*/
int
rb_supports_ssl(void)
{
return 1;
}
unsigned int
rb_ssl_handshake_count(rb_fde_t *const F)
{
return F->handshake_count;
}
void
rb_ssl_clear_handshake_count(rb_fde_t *const F)
{
F->handshake_count = 0;
}
void
rb_ssl_start_accepted(rb_fde_t *const F, ACCB *const cb, void *const data, const int timeout)
{
F->type |= RB_FD_SSL;
F->accept = rb_malloc(sizeof(struct acceptdata));
F->accept->callback = cb;
F->accept->data = data;
F->accept->addrlen = 0;
(void) memset(&F->accept->S, 0x00, sizeof F->accept->S);
rb_settimeout(F, timeout, rb_ssl_timeout_cb, NULL);
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_IN);
rb_ssl_accept_common(F, NULL);
}
void
rb_ssl_accept_setup(rb_fde_t *const srv_F, rb_fde_t *const cli_F, struct sockaddr *const st, const int addrlen)
{
cli_F->type |= RB_FD_SSL;
cli_F->accept = rb_malloc(sizeof(struct acceptdata));
cli_F->accept->callback = srv_F->accept->callback;
cli_F->accept->data = srv_F->accept->data;
cli_F->accept->addrlen = (rb_socklen_t) addrlen;
(void) memset(&cli_F->accept->S, 0x00, sizeof cli_F->accept->S);
(void) memcpy(&cli_F->accept->S, st, (size_t) addrlen);
rb_settimeout(cli_F, 10, rb_ssl_timeout_cb, NULL);
rb_ssl_init_fd(cli_F, RB_FD_TLS_DIRECTION_IN);
rb_ssl_accept_common(cli_F, NULL);
}
int
rb_ssl_listen(rb_fde_t *const F, const int backlog, const int defer_accept)
{
int result = rb_listen(F, backlog, defer_accept);
F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL;
return result;
}
void
rb_connect_tcp_ssl(rb_fde_t *const F, struct sockaddr *const dest, struct sockaddr *const clocal,
const int socklen, CNCB *const callback, void *const data, const int timeout)
{
if(F == NULL)
return;
struct ssl_connect *const sconn = rb_malloc(sizeof *sconn);
sconn->data = data;
sconn->callback = callback;
sconn->timeout = timeout;
rb_connect_tcp(F, dest, clocal, socklen, rb_ssl_tryconn, sconn, timeout);
}
void
rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data, const int timeout)
{
if(F == NULL)
return;
struct ssl_connect *const sconn = rb_malloc(sizeof *sconn);
sconn->data = data;
sconn->callback = callback;
sconn->timeout = timeout;
F->connect = rb_malloc(sizeof(struct conndata));
F->connect->callback = callback;
F->connect->data = data;
F->type |= RB_FD_SSL;
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT);
rb_ssl_connect_common(F, sconn);
}
#endif /* HAVE_GNUTLS */

View file

@ -0,0 +1,37 @@
/*
* libratbox: a library used by ircd-ratbox and other things
* gnutls_ratbox.h: embedded data for GNUTLS backend
*
* Copyright (C) 2007-2008 ircd-ratbox development team
* Copyright (C) 2007-2008 Aaron Sethman <androsyn@ratbox.org>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
*/
static const char rb_gnutls_default_priority_str[] = ""
"+SECURE256:"
"+SECURE128:"
"!RSA:"
"+NORMAL:"
"!ARCFOUR-128:"
"!3DES-CBC:"
"!MD5:"
"+VERS-TLS1.2:"
"+VERS-TLS1.1:"
"!VERS-TLS1.0:"
"!VERS-SSL3.0:"
"%SAFE_RENEGOTIATION";

839
libratbox/src/linebuf.c Normal file
View file

@ -0,0 +1,839 @@
/*
* ircd-ratbox: A slightly useful ircd.
* linebuf.c: Maintains linebuffers.
*
* Copyright (C) 2001-2002 Adrian Chadd <adrian@creative.net.au>
* Copyright (C) 2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
* $Id: linebuf.c 26092 2008-09-19 15:13:52Z androsyn $
*/
#include <libratbox_config.h>
#include <ratbox_lib.h>
#include <commio-int.h>
static rb_bh *rb_linebuf_heap;
static int bufline_count = 0;
#ifndef LINEBUF_HEAP_SIZE
#define LINEBUF_HEAP_SIZE 2048
#endif
/*
* rb_linebuf_init
*
* Initialise the linebuf mechanism
*/
void
rb_linebuf_init(size_t heap_size)
{
rb_linebuf_heap = rb_bh_create(sizeof(buf_line_t), heap_size, "librb_linebuf_heap");
}
static buf_line_t *
rb_linebuf_allocate(void)
{
buf_line_t *t;
t = rb_bh_alloc(rb_linebuf_heap);
return (t);
}
static void
rb_linebuf_free(buf_line_t * p)
{
rb_bh_free(rb_linebuf_heap, p);
}
/*
* rb_linebuf_new_line
*
* Create a new line, and link it to the given linebuf.
* It will be initially empty.
*/
static buf_line_t *
rb_linebuf_new_line(buf_head_t * bufhead)
{
buf_line_t *bufline;
rb_dlink_node *node;
bufline = rb_linebuf_allocate();
if(bufline == NULL)
return NULL;
++bufline_count;
node = rb_make_rb_dlink_node();
/* Stick it at the end of the buf list */
rb_dlinkAddTail(bufline, node, &bufhead->list);
bufline->refcount++;
/* And finally, update the allocated size */
bufhead->alloclen++;
bufhead->numlines++;
return bufline;
}
/*
* rb_linebuf_done_line
*
* We've finished with the given line, so deallocate it
*/
static void
rb_linebuf_done_line(buf_head_t * bufhead, buf_line_t * bufline, rb_dlink_node *node)
{
/* Remove it from the linked list */
rb_dlinkDestroy(node, &bufhead->list);
/* Update the allocated size */
bufhead->alloclen--;
bufhead->len -= bufline->len;
lrb_assert(bufhead->len >= 0);
bufhead->numlines--;
bufline->refcount--;
lrb_assert(bufline->refcount >= 0);
if(bufline->refcount == 0)
{
/* and finally, deallocate the buf */
--bufline_count;
lrb_assert(bufline_count >= 0);
rb_linebuf_free(bufline);
}
}
/*
* skip to end of line or the crlfs, return the number of bytes ..
*/
static inline int
rb_linebuf_skip_crlf(char *ch, int len)
{
int orig_len = len;
/* First, skip until the first non-CRLF */
for(; len; len--, ch++)
{
if(*ch == '\r')
break;
else if(*ch == '\n')
break;
}
/* Then, skip until the last CRLF */
for(; len; len--, ch++)
{
if((*ch != '\r') && (*ch != '\n'))
break;
}
lrb_assert(orig_len > len);
return (orig_len - len);
}
/*
* rb_linebuf_newbuf
*
* Initialise the new buffer
*/
void
rb_linebuf_newbuf(buf_head_t * bufhead)
{
/* not much to do right now :) */
memset(bufhead, 0, sizeof(buf_head_t));
}
/*
* rb_linebuf_donebuf
*
* Flush all the lines associated with this buffer
*/
void
rb_linebuf_donebuf(buf_head_t * bufhead)
{
while(bufhead->list.head != NULL)
{
rb_linebuf_done_line(bufhead, (buf_line_t *) bufhead->list.head->data,
bufhead->list.head);
}
}
/*
* rb_linebuf_copy_line
*
* Okay..this functions comments made absolutely no sense.
*
* Basically what we do is this. Find the first chunk of text
* and then scan for a CRLF. If we didn't find it, but we didn't
* overflow our buffer..we wait for some more data.
* If we found a CRLF, we replace them with a \0 character.
* If we overflowed, we copy the most our buffer can handle, terminate
* it with a \0 and return.
*
* The return value is the amount of data we consumed. This could
* be different than the size of the linebuffer, as when we discard
* the overflow, we don't want to process it again.
*
* This still sucks in my opinion, but it seems to work.
*
* -Aaron
*/
static int
rb_linebuf_copy_line(buf_head_t * bufhead, buf_line_t * bufline, char *data, int len)
{
int cpylen = 0; /* how many bytes we've copied */
char *ch = data; /* Pointer to where we are in the read data */
char *bufch = bufline->buf + bufline->len;
int clen = 0; /* how many bytes we've processed,
and don't ever want to see again.. */
/* If its full or terminated, ignore it */
bufline->raw = 0;
lrb_assert(bufline->len < BUF_DATA_SIZE);
if(bufline->terminated == 1)
return 0;
clen = cpylen = rb_linebuf_skip_crlf(ch, len);
if(clen == -1)
return -1;
/* This is the ~overflow case..This doesn't happen often.. */
if(cpylen > (BUF_DATA_SIZE - bufline->len - 1))
{
cpylen = BUF_DATA_SIZE - bufline->len - 1;
memcpy(bufch, ch, cpylen);
bufline->buf[BUF_DATA_SIZE - 1] = '\0';
bufch = bufline->buf + BUF_DATA_SIZE - 2;
while(cpylen && (*bufch == '\r' || *bufch == '\n'))
{
*bufch = '\0';
cpylen--;
bufch--;
}
bufline->terminated = 1;
bufline->len = BUF_DATA_SIZE - 1;
bufhead->len += BUF_DATA_SIZE - 1;
return clen;
}
memcpy(bufch, ch, cpylen);
bufch += cpylen;
*bufch = '\0';
bufch--;
if(*bufch != '\r' && *bufch != '\n')
{
/* No linefeed, bail for the next time */
bufhead->len += cpylen;
bufline->len += cpylen;
bufline->terminated = 0;
return clen;
}
/* Yank the CRLF off this, replace with a \0 */
while(cpylen && (*bufch == '\r' || *bufch == '\n'))
{
*bufch = '\0';
cpylen--;
bufch--;
}
bufline->terminated = 1;
bufhead->len += cpylen;
bufline->len += cpylen;
return clen;
}
/*
* rb_linebuf_copy_raw
*
* Copy as much data as possible directly into a linebuf,
* splitting at \r\n, but without altering any data.
*
*/
static int
rb_linebuf_copy_raw(buf_head_t * bufhead, buf_line_t * bufline, char *data, int len)
{
int cpylen = 0; /* how many bytes we've copied */
char *ch = data; /* Pointer to where we are in the read data */
char *bufch = bufline->buf + bufline->len;
int clen = 0; /* how many bytes we've processed,
and don't ever want to see again.. */
/* If its full or terminated, ignore it */
bufline->raw = 1;
lrb_assert(bufline->len < BUF_DATA_SIZE);
if(bufline->terminated == 1)
return 0;
clen = cpylen = rb_linebuf_skip_crlf(ch, len);
if(clen == -1)
return -1;
/* This is the overflow case..This doesn't happen often.. */
if(cpylen > (BUF_DATA_SIZE - bufline->len - 1))
{
clen = BUF_DATA_SIZE - bufline->len - 1;
memcpy(bufch, ch, clen);
bufline->buf[BUF_DATA_SIZE - 1] = '\0';
bufline->terminated = 1;
bufline->len = BUF_DATA_SIZE - 1;
bufhead->len += BUF_DATA_SIZE - 1;
return clen;
}
memcpy(bufch, ch, cpylen);
bufch += cpylen;
*bufch = '\0';
bufch--;
if(*bufch != '\r' && *bufch != '\n')
{
/* No linefeed, bail for the next time */
bufhead->len += cpylen;
bufline->len += cpylen;
bufline->terminated = 0;
return clen;
}
bufline->terminated = 1;
bufhead->len += cpylen;
bufline->len += cpylen;
return clen;
}
/*
* rb_linebuf_parse
*
* Take a given buffer and break out as many buffers as we can.
* If we find a CRLF, we terminate that buffer and create a new one.
* If we don't find a CRLF whilst parsing a buffer, we don't mark it
* 'finished', so the next loop through we can continue appending ..
*
* A few notes here, which you'll need to understand before continuing.
*
* - right now I'm only dealing with single sized buffers. Later on,
* I might consider chaining buffers together to get longer "lines"
* but seriously, I don't see the advantage right now.
*
* - This *is* designed to turn into a reference-counter-protected setup
* to dodge copious copies.
*/
int
rb_linebuf_parse(buf_head_t * bufhead, char *data, int len, int raw)
{
buf_line_t *bufline;
int cpylen;
int linecnt = 0;
/* First, if we have a partial buffer, try to squeze data into it */
if(bufhead->list.tail != NULL)
{
/* Check we're doing the partial buffer thing */
bufline = bufhead->list.tail->data;
/* just try, the worst it could do is *reject* us .. */
if(!raw)
cpylen = rb_linebuf_copy_line(bufhead, bufline, data, len);
else
cpylen = rb_linebuf_copy_raw(bufhead, bufline, data, len);
if(cpylen == -1)
return -1;
linecnt++;
/* If we've copied the same as what we've got, quit now */
if(cpylen == len)
return linecnt; /* all the data done so soon? */
/* Skip the data and update len .. */
len -= cpylen;
lrb_assert(len >= 0);
data += cpylen;
}
/* Next, the loop */
while(len > 0)
{
/* We obviously need a new buffer, so .. */
bufline = rb_linebuf_new_line(bufhead);
/* And parse */
if(!raw)
cpylen = rb_linebuf_copy_line(bufhead, bufline, data, len);
else
cpylen = rb_linebuf_copy_raw(bufhead, bufline, data, len);
if(cpylen == -1)
return -1;
len -= cpylen;
lrb_assert(len >= 0);
data += cpylen;
linecnt++;
}
return linecnt;
}
/*
* rb_linebuf_get
*
* get the next buffer from our line. For the time being it will copy
* data into the given buffer and free the underlying linebuf.
*/
int
rb_linebuf_get(buf_head_t * bufhead, char *buf, int buflen, int partial, int raw)
{
buf_line_t *bufline;
int cpylen;
char *start, *ch;
/* make sure we have a line */
if(bufhead->list.head == NULL)
return 0; /* Obviously not.. hrm. */
bufline = bufhead->list.head->data;
/* make sure that the buffer was actually *terminated */
if(!(partial || bufline->terminated))
return 0; /* Wait for more data! */
if(buflen < bufline->len)
cpylen = buflen - 1;
else
cpylen = bufline->len;
/* Copy it */
start = bufline->buf;
/* if we left extraneous '\r\n' characters in the string,
* and we don't want to read the raw data, clean up the string.
*/
if(bufline->raw && !raw)
{
/* skip leading EOL characters */
while(cpylen && (*start == '\r' || *start == '\n'))
{
start++;
cpylen--;
}
/* skip trailing EOL characters */
ch = &start[cpylen - 1];
while(cpylen && (*ch == '\r' || *ch == '\n'))
{
ch--;
cpylen--;
}
}
memcpy(buf, start, cpylen);
/* convert CR/LF to NULL */
if(!raw)
buf[cpylen] = '\0';
lrb_assert(cpylen >= 0);
/* Deallocate the line */
rb_linebuf_done_line(bufhead, bufline, bufhead->list.head);
/* return how much we copied */
return cpylen;
}
/*
* rb_linebuf_attach
*
* attach the lines in a buf_head_t to another buf_head_t
* without copying the data (using refcounts).
*/
void
rb_linebuf_attach(buf_head_t * bufhead, buf_head_t * new)
{
rb_dlink_node *ptr;
buf_line_t *line;
RB_DLINK_FOREACH(ptr, new->list.head)
{
line = ptr->data;
rb_dlinkAddTailAlloc(line, &bufhead->list);
/* Update the allocated size */
bufhead->alloclen++;
bufhead->len += line->len;
bufhead->numlines++;
line->refcount++;
}
}
/*
* rb_linebuf_putmsg
*
* Similar to rb_linebuf_put, but designed for use by send.c.
*
* prefixfmt is used as a format for the varargs, and is inserted first.
* Then format/va_args is appended to the buffer.
*/
void
rb_linebuf_putmsg(buf_head_t * bufhead, const char *format, va_list * va_args,
const char *prefixfmt, ...)
{
buf_line_t *bufline;
int len = 0;
va_list prefix_args;
/* make sure the previous line is terminated */
#ifndef NDEBUG
if(bufhead->list.tail)
{
bufline = bufhead->list.tail->data;
lrb_assert(bufline->terminated);
}
#endif
/* Create a new line */
bufline = rb_linebuf_new_line(bufhead);
if(prefixfmt != NULL)
{
va_start(prefix_args, prefixfmt);
len = rb_vsnprintf(bufline->buf, BUF_DATA_SIZE, prefixfmt, prefix_args);
va_end(prefix_args);
}
if(va_args != NULL)
{
len += rb_vsnprintf((bufline->buf + len), (BUF_DATA_SIZE - len), format, *va_args);
}
bufline->terminated = 1;
/* Truncate the data if required */
if(rb_unlikely(len > 510))
{
len = 510;
bufline->buf[len++] = '\r';
bufline->buf[len++] = '\n';
}
else if(rb_unlikely(len == 0))
{
bufline->buf[len++] = '\r';
bufline->buf[len++] = '\n';
bufline->buf[len] = '\0';
}
else
{
/* Chop trailing CRLF's .. */
while((bufline->buf[len] == '\r') || (bufline->buf[len] == '\n')
|| (bufline->buf[len] == '\0'))
{
len--;
}
bufline->buf[++len] = '\r';
bufline->buf[++len] = '\n';
bufline->buf[++len] = '\0';
}
bufline->len = len;
bufhead->len += len;
}
void
rb_linebuf_putbuf(buf_head_t * bufhead, const char *buffer)
{
buf_line_t *bufline;
int len = 0;
/* make sure the previous line is terminated */
#ifndef NDEBUG
if(bufhead->list.tail)
{
bufline = bufhead->list.tail->data;
lrb_assert(bufline->terminated);
}
#endif
/* Create a new line */
bufline = rb_linebuf_new_line(bufhead);
if(rb_unlikely(buffer != NULL))
len = rb_strlcpy(bufline->buf, buffer, BUF_DATA_SIZE);
bufline->terminated = 1;
/* Truncate the data if required */
if(rb_unlikely(len > 510))
{
len = 510;
bufline->buf[len++] = '\r';
bufline->buf[len++] = '\n';
}
else if(rb_unlikely(len == 0))
{
bufline->buf[len++] = '\r';
bufline->buf[len++] = '\n';
bufline->buf[len] = '\0';
}
else
{
/* Chop trailing CRLF's .. */
while((bufline->buf[len] == '\r') || (bufline->buf[len] == '\n')
|| (bufline->buf[len] == '\0'))
{
len--;
}
bufline->buf[++len] = '\r';
bufline->buf[++len] = '\n';
bufline->buf[++len] = '\0';
}
bufline->len = len;
bufhead->len += len;
}
void
rb_linebuf_put(buf_head_t * bufhead, const char *format, ...)
{
buf_line_t *bufline;
int len = 0;
va_list args;
/* make sure the previous line is terminated */
#ifndef NDEBUG
if(bufhead->list.tail)
{
bufline = bufhead->list.tail->data;
lrb_assert(bufline->terminated);
}
#endif
/* Create a new line */
bufline = rb_linebuf_new_line(bufhead);
if(rb_unlikely(format != NULL))
{
va_start(args, format);
len = rb_vsnprintf(bufline->buf, BUF_DATA_SIZE, format, args);
va_end(args);
}
bufline->terminated = 1;
/* Truncate the data if required */
if(rb_unlikely(len > 510))
{
len = 510;
bufline->buf[len++] = '\r';
bufline->buf[len++] = '\n';
}
else if(rb_unlikely(len == 0))
{
bufline->buf[len++] = '\r';
bufline->buf[len++] = '\n';
bufline->buf[len] = '\0';
}
else
{
/* Chop trailing CRLF's .. */
while((bufline->buf[len] == '\r') || (bufline->buf[len] == '\n')
|| (bufline->buf[len] == '\0'))
{
len--;
}
bufline->buf[++len] = '\r';
bufline->buf[++len] = '\n';
bufline->buf[++len] = '\0';
}
bufline->len = len;
bufhead->len += len;
}
/*
* rb_linebuf_flush
*
* Flush data to the buffer. It tries to write as much data as possible
* to the given socket. Any return values are passed straight through.
* If there is no data in the socket, EWOULDBLOCK is set as an errno
* rather than returning 0 (which would map to an EOF..)
*
* Notes: XXX We *should* have a clue here when a non-full buffer is arrived.
* and tag it so that we don't re-schedule another write until
* we have a CRLF.
*/
int
rb_linebuf_flush(rb_fde_t *F, buf_head_t * bufhead)
{
buf_line_t *bufline;
int retval;
/*
* autoconf checks for this..but really just want to use it if we have a
* native version even if libircd provides a fake version...
*/
#ifdef HAVE_WRITEV
if(!rb_fd_ssl(F))
{
rb_dlink_node *ptr;
int x = 0, y;
int xret;
static struct rb_iovec vec[RB_UIO_MAXIOV];
memset(vec, 0, sizeof(vec));
/* Check we actually have a first buffer */
if(bufhead->list.head == NULL)
{
/* nope, so we return none .. */
errno = EWOULDBLOCK;
return -1;
}
ptr = bufhead->list.head;
bufline = ptr->data;
if(!bufline->terminated)
{
errno = EWOULDBLOCK;
return -1;
}
vec[x].iov_base = bufline->buf + bufhead->writeofs;
vec[x++].iov_len = bufline->len - bufhead->writeofs;
ptr = ptr->next;
do
{
if(ptr == NULL)
break;
bufline = ptr->data;
if(!bufline->terminated)
break;
vec[x].iov_base = bufline->buf;
vec[x].iov_len = bufline->len;
ptr = ptr->next;
}
while(++x < RB_UIO_MAXIOV);
if(x == 0)
{
errno = EWOULDBLOCK;
return -1;
}
xret = retval = rb_writev(F, vec, x);
if(retval <= 0)
return retval;
ptr = bufhead->list.head;
for(y = 0; y < x; y++)
{
bufline = ptr->data;
if(xret >= bufline->len - bufhead->writeofs)
{
xret -= bufline->len - bufhead->writeofs;
ptr = ptr->next;
rb_linebuf_done_line(bufhead, bufline, bufhead->list.head);
bufhead->writeofs = 0;
}
else
{
bufhead->writeofs += xret;
break;
}
}
return retval;
}
#endif
/* this is the non-writev case */
/* Check we actually have a first buffer */
if(bufhead->list.head == NULL)
{
/* nope, so we return none .. */
errno = EWOULDBLOCK;
return -1;
}
bufline = bufhead->list.head->data;
/* And that its actually full .. */
if(!bufline->terminated)
{
errno = EWOULDBLOCK;
return -1;
}
/* Now, try writing data */
retval = rb_write(F, bufline->buf + bufhead->writeofs, bufline->len - bufhead->writeofs);
if(retval <= 0)
return retval;
/* we've got data, so update the write offset */
bufhead->writeofs += retval;
/* if we've written everything *and* the CRLF, deallocate and update
bufhead */
if(bufhead->writeofs == bufline->len)
{
bufhead->writeofs = 0;
lrb_assert(bufhead->len >= 0);
rb_linebuf_done_line(bufhead, bufline, bufhead->list.head);
}
/* Return line length */
return retval;
}
/*
* count linebufs for stats z
*/
void
rb_count_rb_linebuf_memory(size_t *count, size_t *rb_linebuf_memory_used)
{
rb_bh_usage(rb_linebuf_heap, count, NULL, rb_linebuf_memory_used, NULL);
}

896
libratbox/src/mbedtls.c Normal file
View file

@ -0,0 +1,896 @@
/*
* libratbox: a library used by ircd-ratbox and other things
* mbedtls.c: ARM MbedTLS backend
*
* Copyright (C) 2007-2008 ircd-ratbox development team
* Copyright (C) 2007-2008 Aaron Sethman <androsyn@ratbox.org>
* Copyright (C) 2015 William Pitcock <nenolod@dereferenced.org>
* Copyright (C) 2016 Aaron Jones <aaronmdjones@gmail.com>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
*/
#include <libratbox_config.h>
#include <ratbox_lib.h>
#ifdef HAVE_MBEDTLS
#include <commio-int.h>
#include <commio-ssl.h>
#include "mbedtls_ratbox.h"
typedef enum
{
RB_FD_TLS_DIRECTION_IN = 0,
RB_FD_TLS_DIRECTION_OUT = 1
} rb_fd_tls_direction;
#define RB_MAX_CIPHERSUITES 512
typedef struct
{
mbedtls_x509_crt crt;
mbedtls_pk_context key;
mbedtls_dhm_context dhp;
mbedtls_ssl_config server_cfg;
mbedtls_ssl_config client_cfg;
size_t refcount;
int suites[RB_MAX_CIPHERSUITES + 1];
} rb_mbedtls_cfg_context;
typedef struct
{
rb_mbedtls_cfg_context *cfg;
mbedtls_ssl_context ssl;
} rb_mbedtls_ssl_context;
#define SSL_C(x) ((rb_mbedtls_ssl_context *) (x)->ssl)->cfg
#define SSL_P(x) &((rb_mbedtls_ssl_context *) (x)->ssl)->ssl
static mbedtls_ctr_drbg_context ctr_drbg_ctx;
static mbedtls_entropy_context entropy_ctx;
static rb_mbedtls_cfg_context *rb_mbedtls_cfg = NULL;
#if (MBEDTLS_VERSION_NUMBER < 0x02050100)
static mbedtls_x509_crt dummy_ca_ctx;
#endif
struct ssl_connect
{
CNCB *callback;
void *data;
int timeout;
};
static const char *rb_ssl_strerror(int);
static void rb_ssl_connect_realcb(rb_fde_t *, int, struct ssl_connect *);
/*
* Internal MbedTLS-specific code
*/
static void
rb_mbedtls_cfg_incref(rb_mbedtls_cfg_context *const cfg)
{
lrb_assert(cfg->refcount > 0);
cfg->refcount++;
}
static void
rb_mbedtls_cfg_decref(rb_mbedtls_cfg_context *const cfg)
{
if(cfg == NULL)
return;
lrb_assert(cfg->refcount > 0);
if((--cfg->refcount) > 0)
return;
mbedtls_ssl_config_free(&cfg->client_cfg);
mbedtls_ssl_config_free(&cfg->server_cfg);
mbedtls_dhm_free(&cfg->dhp);
mbedtls_pk_free(&cfg->key);
mbedtls_x509_crt_free(&cfg->crt);
rb_free(cfg);
}
static int
rb_sock_net_recv(void *const context_ptr, unsigned char *const buf, const size_t count)
{
const int fd = rb_get_fd((rb_fde_t *)context_ptr);
const int ret = (int) read(fd, buf, count);
if(ret < 0 && rb_ignore_errno(errno))
return MBEDTLS_ERR_SSL_WANT_READ;
return ret;
}
static int
rb_sock_net_xmit(void *const context_ptr, const unsigned char *const buf, const size_t count)
{
const int fd = rb_get_fd((rb_fde_t *)context_ptr);
const int ret = (int) write(fd, buf, count);
if(ret < 0 && rb_ignore_errno(errno))
return MBEDTLS_ERR_SSL_WANT_WRITE;
return ret;
}
static void
rb_ssl_init_fd(rb_fde_t *const F, const rb_fd_tls_direction dir)
{
rb_mbedtls_ssl_context *const mbed_ssl_ctx = rb_malloc(sizeof *mbed_ssl_ctx);
if(mbed_ssl_ctx == NULL)
{
rb_lib_log("%s: rb_malloc: allocation failure", __func__);
rb_close(F);
return;
}
mbedtls_ssl_config *mbed_config = NULL;
switch(dir)
{
case RB_FD_TLS_DIRECTION_IN:
mbed_config = &rb_mbedtls_cfg->server_cfg;
break;
case RB_FD_TLS_DIRECTION_OUT:
mbed_config = &rb_mbedtls_cfg->client_cfg;
break;
}
mbedtls_ssl_init(&mbed_ssl_ctx->ssl);
int ret;
if((ret = mbedtls_ssl_setup(&mbed_ssl_ctx->ssl, mbed_config)) != 0)
{
rb_lib_log("%s: ssl_setup: %s", __func__, rb_ssl_strerror(ret));
mbedtls_ssl_free(&mbed_ssl_ctx->ssl);
rb_free(mbed_ssl_ctx);
rb_close(F);
return;
}
mbedtls_ssl_set_bio(&mbed_ssl_ctx->ssl, F, rb_sock_net_xmit, rb_sock_net_recv, NULL);
rb_mbedtls_cfg_incref(rb_mbedtls_cfg);
mbed_ssl_ctx->cfg = rb_mbedtls_cfg;
F->ssl = mbed_ssl_ctx;
}
static rb_mbedtls_cfg_context *
rb_mbedtls_cfg_new(void)
{
rb_mbedtls_cfg_context *const cfg = rb_malloc(sizeof *cfg);
if(cfg == NULL)
return NULL;
mbedtls_x509_crt_init(&cfg->crt);
mbedtls_pk_init(&cfg->key);
mbedtls_dhm_init(&cfg->dhp);
mbedtls_ssl_config_init(&cfg->server_cfg);
mbedtls_ssl_config_init(&cfg->client_cfg);
(void) memset(cfg->suites, 0x00, sizeof cfg->suites);
cfg->refcount = 1;
int ret;
if((ret = mbedtls_ssl_config_defaults(&cfg->server_cfg,
MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
{
rb_lib_log("%s: ssl_config_defaults (server): %s", __func__, rb_ssl_strerror(ret));
rb_mbedtls_cfg_decref(cfg);
return NULL;
}
if((ret = mbedtls_ssl_config_defaults(&cfg->client_cfg,
MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
{
rb_lib_log("%s: ssl_config_defaults (client): %s", __func__, rb_ssl_strerror(ret));
rb_mbedtls_cfg_decref(cfg);
return NULL;
}
mbedtls_ssl_conf_rng(&cfg->server_cfg, mbedtls_ctr_drbg_random, &ctr_drbg_ctx);
mbedtls_ssl_conf_rng(&cfg->client_cfg, mbedtls_ctr_drbg_random, &ctr_drbg_ctx);
#if (MBEDTLS_VERSION_NUMBER < 0x02050100)
mbedtls_ssl_conf_ca_chain(&cfg->server_cfg, &dummy_ca_ctx, NULL);
mbedtls_ssl_conf_ca_chain(&cfg->client_cfg, &dummy_ca_ctx, NULL);
#endif
mbedtls_ssl_conf_authmode(&cfg->server_cfg, MBEDTLS_SSL_VERIFY_OPTIONAL);
mbedtls_ssl_conf_authmode(&cfg->client_cfg, MBEDTLS_SSL_VERIFY_NONE);
mbedtls_ssl_conf_min_version(&cfg->server_cfg, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_2);
mbedtls_ssl_conf_min_version(&cfg->client_cfg, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_2);
#ifdef MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE
mbedtls_ssl_conf_legacy_renegotiation(&cfg->client_cfg, MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE);
#endif
#ifdef MBEDTLS_SSL_SESSION_TICKETS_DISABLED
mbedtls_ssl_conf_session_tickets(&cfg->client_cfg, MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
#endif
return cfg;
}
static void
rb_ssl_accept_common(rb_fde_t *const F, void *const data)
{
lrb_assert(F != NULL);
lrb_assert(F->accept != NULL);
lrb_assert(F->accept->callback != NULL);
lrb_assert(F->ssl != NULL);
(void) data;
const int ret = mbedtls_ssl_handshake(SSL_P(F));
switch(ret)
{
case 0:
F->handshake_count++;
break;
case MBEDTLS_ERR_SSL_WANT_READ:
rb_setselect(F, RB_SELECT_READ, rb_ssl_accept_common, NULL);
return;
case MBEDTLS_ERR_SSL_WANT_WRITE:
rb_setselect(F, RB_SELECT_WRITE, rb_ssl_accept_common, NULL);
return;
default:
errno = EIO;
F->ssl_errno = (unsigned long) -ret;
F->accept->callback(F, RB_ERROR_SSL, NULL, 0, F->accept->data);
return;
}
rb_settimeout(F, 0, NULL, NULL);
rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL);
struct acceptdata *const ad = F->accept;
F->accept = NULL;
ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data);
rb_free(ad);
}
static void
rb_ssl_connect_common(rb_fde_t *const F, void *const data)
{
lrb_assert(F != NULL);
lrb_assert(F->ssl != NULL);
const int ret = mbedtls_ssl_handshake(SSL_P(F));
switch(ret)
{
case 0:
F->handshake_count++;
break;
case MBEDTLS_ERR_SSL_WANT_READ:
rb_setselect(F, RB_SELECT_READ, rb_ssl_connect_common, data);
return;
case MBEDTLS_ERR_SSL_WANT_WRITE:
rb_setselect(F, RB_SELECT_WRITE, rb_ssl_connect_common, data);
return;
default:
errno = EIO;
F->ssl_errno = (unsigned long) -ret;
rb_ssl_connect_realcb(F, RB_ERROR_SSL, data);
return;
}
rb_ssl_connect_realcb(F, RB_OK, data);
}
static const char *
rb_ssl_strerror(int err)
{
static char errbuf[512];
if (err < 0)
err = -err;
#ifdef MBEDTLS_ERROR_C
char mbed_errbuf[512];
mbedtls_strerror(err, mbed_errbuf, sizeof mbed_errbuf);
(void) rb_snprintf(errbuf, sizeof errbuf, "-0x%X: %s", (unsigned int) err, mbed_errbuf);
#else
(void) rb_snprintf(errbuf, sizeof errbuf, "-0x%X", (unsigned int) err);
#endif
return errbuf;
}
static int
rb_make_certfp(const mbedtls_x509_crt *const peer_cert, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method)
{
size_t hashlen = 0;
mbedtls_md_type_t md_type;
int spki = 0;
switch(method)
{
case RB_SSL_CERTFP_METH_CERT_SHA1:
md_type = MBEDTLS_MD_SHA1;
hashlen = RB_SSL_CERTFP_LEN_SHA1;
break;
case RB_SSL_CERTFP_METH_SPKI_SHA256:
spki = 1;
case RB_SSL_CERTFP_METH_CERT_SHA256:
md_type = MBEDTLS_MD_SHA256;
hashlen = RB_SSL_CERTFP_LEN_SHA256;
break;
case RB_SSL_CERTFP_METH_SPKI_SHA512:
spki = 1;
case RB_SSL_CERTFP_METH_CERT_SHA512:
md_type = MBEDTLS_MD_SHA512;
hashlen = RB_SSL_CERTFP_LEN_SHA512;
break;
default:
return 0;
}
const mbedtls_md_info_t *const md_info = mbedtls_md_info_from_type(md_type);
if(md_info == NULL)
return 0;
int ret;
void* data = peer_cert->raw.p;
size_t datalen = peer_cert->raw.len;
if(spki)
{
// Compiler may complain about dropping const qualifier on the cast below
// See <https://github.com/ARMmbed/mbedtls/issues/396> -- this is okay
unsigned char der_pubkey[8192];
if((ret = mbedtls_pk_write_pubkey_der((mbedtls_pk_context *)&peer_cert->pk,
der_pubkey, sizeof der_pubkey)) < 0)
{
rb_lib_log("%s: pk_write_pubkey_der: %s", __func__, rb_ssl_strerror(ret));
return 0;
}
data = der_pubkey + (sizeof(der_pubkey) - (size_t)ret);
datalen = (size_t)ret;
}
if((ret = mbedtls_md(md_info, data, datalen, certfp)) != 0)
{
rb_lib_log("%s: mbedtls_md: %s", __func__, rb_ssl_strerror(ret));
return 0;
}
return (int) hashlen;
}
/*
* External MbedTLS-specific code
*/
void
rb_ssl_shutdown(rb_fde_t *const F)
{
if(F == NULL || F->ssl == NULL)
return;
for(int i = 0; i < 4; i++)
{
int ret = mbedtls_ssl_close_notify(SSL_P(F));
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
break;
}
mbedtls_ssl_free(SSL_P(F));
rb_mbedtls_cfg_decref(SSL_C(F));
rb_free(F->ssl);
F->ssl = NULL;
}
int
rb_init_ssl(void)
{
mbedtls_ctr_drbg_init(&ctr_drbg_ctx);
mbedtls_entropy_init(&entropy_ctx);
int ret;
if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg_ctx, mbedtls_entropy_func, &entropy_ctx,
(const unsigned char *)rb_mbedtls_personal_str, sizeof(rb_mbedtls_personal_str))) != 0)
{
rb_lib_log("%s: ctr_drbg_seed: %s", __func__, rb_ssl_strerror(ret));
return 0;
}
#if (MBEDTLS_VERSION_NUMBER < 0x02050100)
if((ret = mbedtls_x509_crt_parse_der(&dummy_ca_ctx, rb_mbedtls_dummy_ca_certificate,
sizeof(rb_mbedtls_dummy_ca_certificate))) != 0)
{
rb_lib_log("%s: x509_crt_parse_der (Dummy CA): %s", __func__, rb_ssl_strerror(ret));
return 0;
}
#endif
rb_lib_log("%s: MbedTLS backend initialised", __func__);
return 1;
}
int
rb_setup_ssl_server(const char *const certfile, const char *keyfile,
const char *const dhfile, const char *const cipherlist, const char *hostname)
{
if(certfile == NULL)
{
rb_lib_log("%s: no certificate file specified", __func__);
return 0;
}
if(keyfile == NULL)
keyfile = certfile;
rb_mbedtls_cfg_context *const newcfg = rb_mbedtls_cfg_new();
if(newcfg == NULL)
{
rb_lib_log("%s: rb_mbedtls_cfg_new: allocation failed", __func__);
return 0;
}
int ret;
if((ret = mbedtls_x509_crt_parse_file(&newcfg->crt, certfile)) != 0)
{
rb_lib_log("%s: x509_crt_parse_file ('%s'): %s", __func__, certfile, rb_ssl_strerror(ret));
rb_mbedtls_cfg_decref(newcfg);
return 0;
}
if((ret = mbedtls_pk_parse_keyfile(&newcfg->key, keyfile, NULL)) != 0)
{
rb_lib_log("%s: pk_parse_keyfile ('%s'): %s", __func__, keyfile, rb_ssl_strerror(ret));
rb_mbedtls_cfg_decref(newcfg);
return 0;
}
if((ret = mbedtls_pk_check_pair(&newcfg->crt.pk, &newcfg->key)) != 0)
{
rb_lib_log("%s: pk_check_pair: public/private key mismatch", __func__);
rb_mbedtls_cfg_decref(newcfg);
return 0;
}
if((ret = mbedtls_ssl_conf_own_cert(&newcfg->server_cfg, &newcfg->crt, &newcfg->key)) != 0)
{
rb_lib_log("%s: ssl_conf_own_cert (server): %s", __func__, rb_ssl_strerror(ret));
rb_mbedtls_cfg_decref(newcfg);
return 0;
}
if((ret = mbedtls_ssl_conf_own_cert(&newcfg->client_cfg, &newcfg->crt, &newcfg->key)) != 0)
{
rb_lib_log("%s: ssl_conf_own_cert (client): %s", __func__, rb_ssl_strerror(ret));
rb_mbedtls_cfg_decref(newcfg);
return 0;
}
/* Absense of DH parameters does not matter with mbedTLS, as it comes with its own defaults
Thus, clients can still use DHE- ciphersuites, just over a weaker, common DH group
So, we do not consider failure to parse DH parameters as fatal */
if(dhfile == NULL)
{
rb_lib_log("%s: no DH parameters file specified", __func__);
}
else
{
if((ret = mbedtls_dhm_parse_dhmfile(&newcfg->dhp, dhfile)) != 0)
{
rb_lib_log("%s: dhm_parse_dhmfile ('%s'): %s", __func__, dhfile, rb_ssl_strerror(ret));
}
else if((ret = mbedtls_ssl_conf_dh_param_ctx(&newcfg->server_cfg, &newcfg->dhp)) != 0)
{
rb_lib_log("%s: ssl_conf_dh_param_ctx: %s", __func__, rb_ssl_strerror(ret));
}
}
const int *rb_ciphersuites = newcfg->suites;
size_t suites_count = 0;
if(cipherlist != NULL)
{
// The cipherlist is (const char *) -- we should not modify it
char *const cipherlist_dup = strdup(cipherlist);
if(cipherlist_dup != NULL)
{
char *cipher_str = cipherlist_dup;
char *cipher_idx;
do
{
// Arbitrary, but the same separator as OpenSSL uses
cipher_idx = strchr(cipher_str, ':');
// This could legitimately be NULL (last ciphersuite in the list)
if(cipher_idx != NULL)
*cipher_idx = '\0';
size_t cipher_len = strlen(cipher_str);
int cipher_idn = 0;
// All MbedTLS ciphersuite names begin with these 4 characters
if(cipher_len > 4 && strncmp(cipher_str, "TLS-", 4) == 0)
cipher_idn = mbedtls_ssl_get_ciphersuite_id(cipher_str);
// Prevent the same ciphersuite being added multiple times
for(size_t x = 0; cipher_idn != 0 && newcfg->suites[x] != 0; x++)
if(newcfg->suites[x] == cipher_idn)
cipher_idn = 0;
// Add the suite to the list
if(cipher_idn != 0)
newcfg->suites[suites_count++] = cipher_idn;
// Advance the string to the next entry
if(cipher_idx)
cipher_str = cipher_idx + 1;
} while(cipher_idx && suites_count < RB_MAX_CIPHERSUITES);
if(suites_count == 0)
rb_lib_log("%s: Ciphersuites provided, but could not parse any", __func__);
free(cipherlist_dup);
}
else
{
rb_lib_log("%s: strdup: %s", __func__, strerror(errno));
}
}
else
{
rb_lib_log("%s: No ciphersuite list provided", __func__);
}
if(suites_count == 0)
{
rb_lib_log("%s: Using default ciphersuites", __func__);
rb_ciphersuites = rb_mbedtls_ciphersuites;
suites_count = (sizeof(rb_mbedtls_ciphersuites) / sizeof(rb_mbedtls_ciphersuites[0])) - 1;
}
mbedtls_ssl_conf_ciphersuites(&newcfg->server_cfg, rb_ciphersuites);
mbedtls_ssl_conf_ciphersuites(&newcfg->client_cfg, rb_ciphersuites);
rb_lib_log("%s: Configured %zu ciphersuites", __func__, suites_count);
rb_mbedtls_cfg_decref(rb_mbedtls_cfg);
rb_mbedtls_cfg = newcfg;
rb_lib_log("%s: TLS configuration successful", __func__);
return 1;
}
int
rb_init_prng(const char *const path, prng_seed_t seed_type)
{
(void) path;
(void) seed_type;
rb_lib_log("%s: Skipping PRNG initialisation; not required by MbedTLS backend", __func__);
return 1;
}
int
rb_get_random(void *const buf, const size_t length)
{
int ret;
if((ret = mbedtls_ctr_drbg_random(&ctr_drbg_ctx, buf, length)) != 0)
{
rb_lib_log("%s: ctr_drbg_random: %s", __func__, rb_ssl_strerror(ret));
return 0;
}
return 1;
}
const char *
rb_get_ssl_strerror(rb_fde_t *const F)
{
const int err = (int) F->ssl_errno;
return rb_ssl_strerror(err);
}
int
rb_get_ssl_certfp(rb_fde_t *const F, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method)
{
if(F == NULL || F->ssl == NULL)
return 0;
const mbedtls_x509_crt *const peer_cert = mbedtls_ssl_get_peer_cert(SSL_P(F));
if(peer_cert == NULL)
return 0;
return rb_make_certfp(peer_cert, certfp, method);
}
void
rb_get_ssl_info(char *const buf, const size_t len)
{
char version_str[512];
mbedtls_version_get_string(version_str);
(void) rb_snprintf(buf, len, "ARM mbedTLS: compiled (v%s), library (v%s)",
MBEDTLS_VERSION_STRING, version_str);
}
const char *
rb_ssl_get_cipher(rb_fde_t *const F)
{
if(F == NULL || F->ssl == NULL)
return NULL;
static char buf[512];
const char *const version = mbedtls_ssl_get_version(SSL_P(F));
const char *const cipher = mbedtls_ssl_get_ciphersuite(SSL_P(F));
(void) rb_snprintf(buf, sizeof buf, "%s, %s", version, cipher);
return buf;
}
ssize_t
rb_ssl_read(rb_fde_t *const F, void *const buf, const size_t count)
{
lrb_assert(F != NULL);
lrb_assert(F->ssl != NULL);
const int ret = mbedtls_ssl_read(SSL_P(F), buf, count);
if(ret >= 0)
return (ssize_t) ret;
switch(ret)
{
case MBEDTLS_ERR_SSL_WANT_READ:
errno = EAGAIN;
return RB_RW_SSL_NEED_READ;
case MBEDTLS_ERR_SSL_WANT_WRITE:
errno = EAGAIN;
return RB_RW_SSL_NEED_WRITE;
default:
errno = EIO;
F->ssl_errno = (unsigned long) -ret;
return RB_RW_SSL_ERROR;
}
}
ssize_t
rb_ssl_write(rb_fde_t *const F, const void *const buf, const size_t count)
{
lrb_assert(F != NULL);
lrb_assert(F->ssl != NULL);
const int ret = mbedtls_ssl_write(SSL_P(F), buf, count);
if(ret >= 0)
return (ssize_t) ret;
switch(ret)
{
case MBEDTLS_ERR_SSL_WANT_READ:
errno = EAGAIN;
return RB_RW_SSL_NEED_READ;
case MBEDTLS_ERR_SSL_WANT_WRITE:
errno = EAGAIN;
return RB_RW_SSL_NEED_WRITE;
default:
errno = EIO;
F->ssl_errno = (unsigned long) -ret;
return RB_RW_SSL_ERROR;
}
}
/*
* Internal library-agnostic code
*/
static void
rb_ssl_connect_realcb(rb_fde_t *const F, const int status, struct ssl_connect *const sconn)
{
lrb_assert(F != NULL);
lrb_assert(F->connect != NULL);
F->connect->callback = sconn->callback;
F->connect->data = sconn->data;
rb_connect_callback(F, status);
rb_free(sconn);
}
static void
rb_ssl_timeout_cb(rb_fde_t *const F, void *const data)
{
(void) data;
lrb_assert(F->accept != NULL);
lrb_assert(F->accept->callback != NULL);
F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data);
}
static void
rb_ssl_tryconn_timeout_cb(rb_fde_t *const F, void *const data)
{
rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data);
}
static void
rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data)
{
lrb_assert(F != NULL);
struct ssl_connect *const sconn = data;
if(status != RB_OK)
{
rb_ssl_connect_realcb(F, status, sconn);
return;
}
F->type |= RB_FD_SSL;
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT);
rb_ssl_connect_common(F, sconn);
}
/*
* External library-agnostic code
*/
int
rb_supports_ssl(void)
{
return 1;
}
unsigned int
rb_ssl_handshake_count(rb_fde_t *const F)
{
return F->handshake_count;
}
void
rb_ssl_clear_handshake_count(rb_fde_t *const F)
{
F->handshake_count = 0;
}
void
rb_ssl_start_accepted(rb_fde_t *const F, ACCB *const cb, void *const data, const int timeout)
{
F->type |= RB_FD_SSL;
F->accept = rb_malloc(sizeof(struct acceptdata));
F->accept->callback = cb;
F->accept->data = data;
F->accept->addrlen = 0;
(void) memset(&F->accept->S, 0x00, sizeof F->accept->S);
rb_settimeout(F, timeout, rb_ssl_timeout_cb, NULL);
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_IN);
rb_ssl_accept_common(F, NULL);
}
void
rb_ssl_accept_setup(rb_fde_t *const srv_F, rb_fde_t *const cli_F, struct sockaddr *const st, const int addrlen)
{
cli_F->type |= RB_FD_SSL;
cli_F->accept = rb_malloc(sizeof(struct acceptdata));
cli_F->accept->callback = srv_F->accept->callback;
cli_F->accept->data = srv_F->accept->data;
cli_F->accept->addrlen = (rb_socklen_t) addrlen;
(void) memset(&cli_F->accept->S, 0x00, sizeof cli_F->accept->S);
(void) memcpy(&cli_F->accept->S, st, (size_t) addrlen);
rb_settimeout(cli_F, 10, rb_ssl_timeout_cb, NULL);
rb_ssl_init_fd(cli_F, RB_FD_TLS_DIRECTION_IN);
rb_ssl_accept_common(cli_F, NULL);
}
int
rb_ssl_listen(rb_fde_t *const F, const int backlog, const int defer_accept)
{
int result = rb_listen(F, backlog, defer_accept);
F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL;
return result;
}
void
rb_connect_tcp_ssl(rb_fde_t *const F, struct sockaddr *const dest, struct sockaddr *const clocal,
const int socklen, CNCB *const callback, void *const data, const int timeout)
{
if(F == NULL)
return;
struct ssl_connect *const sconn = rb_malloc(sizeof *sconn);
sconn->data = data;
sconn->callback = callback;
sconn->timeout = timeout;
rb_connect_tcp(F, dest, clocal, socklen, rb_ssl_tryconn, sconn, timeout);
}
void
rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data, const int timeout)
{
if(F == NULL)
return;
struct ssl_connect *const sconn = rb_malloc(sizeof *sconn);
sconn->data = data;
sconn->callback = callback;
sconn->timeout = timeout;
F->connect = rb_malloc(sizeof(struct conndata));
F->connect->callback = callback;
F->connect->data = data;
F->type |= RB_FD_SSL;
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT);
rb_ssl_connect_common(F, sconn);
}
#endif /* HAVE_MBEDTLS */

View file

@ -0,0 +1,237 @@
/*
* libratbox: a library used by ircd-ratbox and other things
* mbedtls_ratbox.h: embedded data for ARM MbedTLS backend
*
* Copyright (C) 2016 Aaron Jones <aaronmdjones@gmail.com>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
* $Id$
*/
#ifndef RB_MBEDTLS_EMBEDDED_DATA_H
#define RB_MBEDTLS_EMBEDDED_DATA_H
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/certs.h"
#include "mbedtls/x509.h"
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_ciphersuites.h"
#include "mbedtls/error.h"
#include "mbedtls/debug.h"
#include "mbedtls/dhm.h"
#include "mbedtls/version.h"
/*
* Personalization string for CTR-DRBG initialization
*/
static const char rb_mbedtls_personal_str[] = "charybdis/librb personalization string";
/*
* Default list of supported ciphersuites
* The user can override this with the ssl_cipher_list option in ircd.conf
*
* The format for this option is the same as the macro names below, but
* with underscores replaced with hyphens, and without the initial MBEDTLS_
*
* For example;
* ssl_cipher_list = "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384"
*
* Multiple ciphersuites can be separated by colons (:)
*
* ************************************************************************
*
* The ordering of the following list should be intuitive. Within the list;
*
* * All AEAD forward-secret ciphersuites are located first [1]
* * All SHA2 forward-secret ciphersuites are located second
* * All remaining forward-secret ciphersuites are located third
* * All non-forward-secret ciphersuites are located last, in the same order
*
* [1] Because in practice, they are the only secure ciphersuites available;
* the ETM extension for CBC ciphersuites has not seen wide adoption.
*
* In practice, all clients SHOULD support an AEAD forward-secret cipher,
* which the server will then negotiate as they are preferred.
*
* This choice can be revisited in future; please consult me first. -- amdj
*/
static const int rb_mbedtls_ciphersuites[] = {
// AEAD forward-secret ciphersuites
#ifdef MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
#endif
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM,
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM,
// SHA2 forward-secret ciphersuites
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
// Remaining forward-secret ciphersuites
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
// Non-forward-secret ciphersuites
MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384,
MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
MBEDTLS_TLS_RSA_WITH_AES_256_CCM,
MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,
MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
MBEDTLS_TLS_RSA_WITH_AES_128_CCM,
MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256,
MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA,
MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,
MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
// The end of list sentinel
0
};
/*
* YES, this is a hardcoded CA certificate.
*
* BEFORE YOU THROW YOUR ARMS UP IN A PANIC ABOUT A BACKDOOR, READ THIS TEXT!
*
* ARM mbedTLS required a CA certificate to be set in its configuration before it will
* process a client certificate from peers. Since we want to do that, and not all
* installations will have a CA certificate to hand, we have this.
*
* Its key was securely destroyed after being generated, but even if it wasn't, that
* doesn't matter; the IRCd will accept ALL certificates, whether signed by this CA
* certificate or not!
*
* After all, it only cares about certificates in as far as to generate a fingerprint
* for them.
*
* Yes, this is a massive hack, but there is no alternative for older versions.
*
* This issue was fixed in commit 39ae8cd2077d on the MbedTLS 2.5 development branch,
* released in version 2.5.1 on 19 June 2017. This certificate will not be used if
* that version (or greater) is installed.
*/
#if (MBEDTLS_VERSION_NUMBER < 0x02050100)
static const unsigned char rb_mbedtls_dummy_ca_certificate[825] = {
0x30, 0x82, 0x03, 0x35, 0x30, 0x82, 0x02, 0x1D, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00,
0x86, 0xC5, 0x1F, 0x62, 0xBE, 0xFC, 0x0B, 0xA8, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x31, 0x31, 0x2F, 0x30, 0x2D, 0x06, 0x03, 0x55,
0x04, 0x03, 0x0C, 0x26, 0x43, 0x68, 0x61, 0x72, 0x79, 0x62, 0x64, 0x69, 0x73, 0x20, 0x6D, 0x62,
0x65, 0x64, 0x54, 0x4C, 0x53, 0x20, 0x44, 0x75, 0x6D, 0x6D, 0x79, 0x20, 0x43, 0x41, 0x20, 0x43,
0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x36,
0x30, 0x35, 0x30, 0x34, 0x30, 0x38, 0x35, 0x32, 0x35, 0x33, 0x5A, 0x17, 0x0D, 0x34, 0x33, 0x30,
0x39, 0x32, 0x30, 0x30, 0x38, 0x35, 0x32, 0x35, 0x33, 0x5A, 0x30, 0x31, 0x31, 0x2F, 0x30, 0x2D,
0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x26, 0x43, 0x68, 0x61, 0x72, 0x79, 0x62, 0x64, 0x69, 0x73,
0x20, 0x6D, 0x62, 0x65, 0x64, 0x54, 0x4C, 0x53, 0x20, 0x44, 0x75, 0x6D, 0x6D, 0x79, 0x20, 0x43,
0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x82, 0x01,
0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00,
0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xCA, 0x4B,
0xA6, 0xA1, 0x82, 0x5B, 0x06, 0xC6, 0x82, 0x76, 0x8E, 0xB2, 0x22, 0x37, 0x83, 0x91, 0x4B, 0xD0,
0xAE, 0x2F, 0xEE, 0x8E, 0x60, 0x04, 0xBA, 0x77, 0x8C, 0xD0, 0xCF, 0x5E, 0xA4, 0xFD, 0x80, 0xA1,
0x2E, 0xDC, 0x1F, 0xD9, 0x72, 0x2C, 0x28, 0x03, 0x27, 0x48, 0x23, 0x6E, 0x41, 0x49, 0x62, 0x09,
0x2D, 0xCF, 0x87, 0xA1, 0x45, 0x9D, 0x2B, 0x43, 0x6F, 0xBB, 0xDB, 0x23, 0xD8, 0xD9, 0x6D, 0x36,
0x4E, 0xA3, 0x85, 0x40, 0x4D, 0x72, 0xEC, 0x7B, 0xEF, 0x2B, 0x13, 0xE4, 0x6F, 0xDA, 0x23, 0x4F,
0x1C, 0xE7, 0xEA, 0xD9, 0x17, 0x2B, 0xD6, 0x67, 0x79, 0x42, 0xC3, 0x81, 0x9A, 0x77, 0x64, 0xC7,
0xC5, 0x44, 0xE1, 0xA4, 0xA3, 0x50, 0x8C, 0x1F, 0xCA, 0xD3, 0x6F, 0xC7, 0xFF, 0x2C, 0xBA, 0x7B,
0x21, 0x0C, 0xF3, 0xA9, 0x6A, 0x89, 0x74, 0x33, 0x60, 0xA1, 0xF8, 0x9F, 0xAA, 0x39, 0xA9, 0x45,
0x7E, 0x3D, 0x41, 0x67, 0x04, 0xF5, 0x9F, 0x47, 0x62, 0xAC, 0x65, 0xE0, 0x8D, 0x46, 0x9E, 0xD9,
0xE5, 0x77, 0xD5, 0x8C, 0x47, 0xA2, 0xFB, 0x7D, 0x94, 0x27, 0xC9, 0xB9, 0x3F, 0x4D, 0xF4, 0xFD,
0x19, 0x3C, 0xF6, 0x24, 0xAE, 0x70, 0xD7, 0x23, 0xE4, 0x64, 0x0A, 0xFC, 0x63, 0x89, 0x8A, 0xFE,
0xD0, 0x8E, 0x48, 0x1A, 0xD8, 0xC3, 0xA9, 0xEC, 0x9D, 0x0F, 0xC7, 0xC5, 0x22, 0xBC, 0x45, 0x4A,
0x2F, 0x4D, 0xF5, 0x0E, 0x4F, 0xFF, 0xAC, 0xE0, 0x55, 0xF4, 0x86, 0x04, 0x1B, 0x60, 0xDF, 0x4C,
0x25, 0xB9, 0xEC, 0x10, 0x0C, 0x54, 0x16, 0xDF, 0x42, 0xF0, 0x07, 0x00, 0x28, 0x81, 0x7C, 0x95,
0xAA, 0xC1, 0x01, 0xA3, 0xB8, 0xDF, 0x68, 0xCB, 0x55, 0xA7, 0x80, 0xCC, 0xE5, 0x3D, 0xE1, 0x68,
0x10, 0x27, 0x56, 0x94, 0x67, 0xEC, 0x82, 0x66, 0x3D, 0x96, 0x76, 0xC3, 0xEE, 0x23, 0x02, 0x03,
0x01, 0x00, 0x01, 0xA3, 0x50, 0x30, 0x4E, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16,
0x04, 0x14, 0xFF, 0xC8, 0xBA, 0x56, 0x74, 0xB1, 0x03, 0xA9, 0x79, 0x55, 0xFA, 0x58, 0x86, 0x13,
0xDE, 0xC0, 0xFA, 0xF2, 0x94, 0x62, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30,
0x16, 0x80, 0x14, 0xFF, 0xC8, 0xBA, 0x56, 0x74, 0xB1, 0x03, 0xA9, 0x79, 0x55, 0xFA, 0x58, 0x86,
0x13, 0xDE, 0xC0, 0xFA, 0xF2, 0x94, 0x62, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05,
0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x3D, 0x35, 0x69, 0x87, 0xEB, 0x41, 0xA9,
0x2A, 0x51, 0xF3, 0x28, 0x71, 0xB4, 0x06, 0x7F, 0x15, 0x5A, 0x6D, 0x88, 0x5B, 0xC8, 0x4C, 0xE1,
0x6C, 0xC7, 0xCB, 0x93, 0x63, 0x69, 0xFB, 0xA6, 0x6D, 0xC7, 0x44, 0x6B, 0xD6, 0x39, 0x46, 0x34,
0xFC, 0x45, 0x23, 0xD2, 0x29, 0x1B, 0xCC, 0x1C, 0x13, 0xD7, 0x63, 0x10, 0x81, 0xF5, 0x82, 0x45,
0xEC, 0xDC, 0x20, 0x5F, 0xBB, 0xC3, 0xE6, 0x4A, 0x07, 0xA7, 0xBD, 0x9E, 0xFC, 0x5D, 0xFE, 0xC5,
0x43, 0x3A, 0xC6, 0xA4, 0x6C, 0x5B, 0xF9, 0x63, 0x8F, 0xF9, 0xEB, 0xC2, 0xF4, 0xA7, 0xE4, 0x1B,
0x23, 0xFA, 0xE1, 0x5A, 0x79, 0xC5, 0x1D, 0x1D, 0xFC, 0xAA, 0x81, 0xF7, 0x21, 0x52, 0xC9, 0x46,
0x17, 0x1B, 0x24, 0x4B, 0x14, 0x5C, 0xF9, 0xB5, 0x86, 0x04, 0x80, 0x51, 0x95, 0xCF, 0x4E, 0x47,
0x32, 0x8A, 0x1E, 0x52, 0x2E, 0xBF, 0x08, 0x8E, 0x9E, 0xE3, 0x88, 0x45, 0xC3, 0x75, 0xD7, 0xAE,
0xC3, 0x7E, 0x7E, 0xE9, 0xC9, 0x5B, 0xD8, 0x58, 0x3B, 0x25, 0x53, 0x0C, 0x00, 0x21, 0x1A, 0x71,
0x12, 0x23, 0xA0, 0x35, 0x6E, 0xC9, 0x7D, 0x83, 0x5C, 0x19, 0xE4, 0x05, 0x84, 0x46, 0x4E, 0x50,
0xE2, 0x9E, 0x70, 0x2E, 0x74, 0x05, 0xEA, 0x31, 0x04, 0x55, 0xA7, 0xF4, 0x67, 0x95, 0xDC, 0x86,
0x1F, 0x9D, 0xA0, 0x5D, 0x7F, 0x29, 0x48, 0x84, 0xEF, 0x13, 0xB8, 0xB3, 0xBF, 0x65, 0xD4, 0x52,
0x98, 0x06, 0xE6, 0x8A, 0xB1, 0x36, 0xEA, 0x39, 0xB3, 0x04, 0x2B, 0x6E, 0x64, 0x6E, 0xF3, 0x20,
0x74, 0xB6, 0x6E, 0x21, 0x3B, 0x99, 0xFE, 0x6E, 0x70, 0x48, 0x78, 0xEA, 0x31, 0x95, 0xB3, 0xB0,
0x0E, 0x48, 0x83, 0x35, 0xA9, 0x74, 0xBF, 0x45, 0x07, 0xC8, 0x5A, 0x12, 0xA2, 0x4D, 0x16, 0xDB,
0xB3, 0x1F, 0x72, 0xDE, 0x2A, 0x28, 0xFE, 0x7C, 0x2D
};
#endif /* MBEDTLS_VERSION_NUMBER */
#endif /* RB_MBEDTLS_EMBEDDED_DATA_H */

185
libratbox/src/nossl.c Normal file
View file

@ -0,0 +1,185 @@
/*
* libratbox: a library used by ircd-ratbox and other things
* nossl.c: ssl stub code
*
* Copyright (C) 2007-2008 ircd-ratbox development team
* Copyright (C) 2007-2008 Aaron Sethman <androsyn@ratbox.org>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
* $Id: commio.c 24808 2008-01-02 08:17:05Z androsyn $
*/
#include <libratbox_config.h>
#include <ratbox_lib.h>
#if !defined(HAVE_OPENSSL) && !defined(HAVE_GNUTLS) && !defined(HAVE_MBEDTLS)
#include "arc4random.h"
#include <commio-int.h>
#include <commio-ssl.h>
int
rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list, const char *hostname)
{
errno = ENOSYS;
return 0;
}
int
rb_init_ssl(void)
{
errno = ENOSYS;
return -1;
}
int
rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept)
{
errno = ENOSYS;
return -1;
}
static void
rb_stir_arc4random(void *unused)
{
arc4random_stir();
}
int
rb_init_prng(const char *path, prng_seed_t seed_type)
{
/* xxx this ignores the parameters above */
arc4random_stir();
rb_event_addish("rb_stir_arc4random", rb_stir_arc4random, NULL, 300);
return 1;
}
int
rb_get_random(void *buf, size_t length)
{
uint32_t rnd = 0, i;
uint8_t *xbuf = buf;
for(i = 0; i < length; i++)
{
if(i % 4 == 0)
rnd = arc4random();
xbuf[i] = rnd;
rnd >>= 8;
}
return 1;
}
const char *
rb_get_ssl_strerror(rb_fde_t *F)
{
static const char *nosupport = "SSL/TLS not supported";
return nosupport;
}
int
rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
{
return 0;
}
void
rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout)
{
return;
}
void
rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout)
{
return;
}
void
rb_connect_tcp_ssl(rb_fde_t *F, struct sockaddr *dest,
struct sockaddr *clocal, int socklen, CNCB * callback, void *data, int timeout)
{
return;
}
int
rb_supports_ssl(void)
{
return 0;
}
void
rb_ssl_shutdown(rb_fde_t *F)
{
return;
}
void
rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, int addrlen)
{
return;
}
ssize_t
rb_ssl_read(rb_fde_t *F, void *buf, size_t count)
{
errno = ENOSYS;
return -1;
}
ssize_t
rb_ssl_write(rb_fde_t *F, const void *buf, size_t count)
{
errno = ENOSYS;
return -1;
}
unsigned int
rb_ssl_handshake_count(rb_fde_t *F)
{
return 0;
}
void
rb_ssl_clear_handshake_count(rb_fde_t *F)
{
return;
}
void
rb_get_ssl_info(char *buf, size_t len)
{
rb_snprintf(buf, len, "Not compiled with SSL support");
}
int
rb_ssl_get_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN])
{
errno = ENOSYS;
return -1;
}
const char *
rb_ssl_get_cipher(rb_fde_t *F)
{
errno = ENOSYS;
return NULL;
}
#endif /* !HAVE_OPENSSL */

850
libratbox/src/openssl.c Normal file
View file

@ -0,0 +1,850 @@
/*
* libratbox: a library used by ircd-ratbox and other things
* openssl.c: OpenSSL backend
*
* Copyright (C) 2007-2008 ircd-ratbox development team
* Copyright (C) 2007-2008 Aaron Sethman <androsyn@ratbox.org>
* Copyright (C) 2015-2016 Aaron Jones <aaronmdjones@gmail.com>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
*/
#include <libratbox_config.h>
#include <ratbox_lib.h>
#ifdef HAVE_OPENSSL
#include <commio-int.h>
#include <commio-ssl.h>
#include "openssl_ratbox.h"
typedef enum
{
RB_FD_TLS_DIRECTION_IN = 0,
RB_FD_TLS_DIRECTION_OUT = 1
} rb_fd_tls_direction;
#define SSL_P(x) ((SSL *)((x)->ssl))
typedef struct ssl_vhost_s
{
char *hostname;
SSL_CTX *ctx;
rb_dlink_node node;
} ssl_vhost;
static SSL_CTX *ssl_ctx = NULL;
rb_dlink_list ssl_vhosts;
rb_dlink_node *
find_ssl_vhost(const char *hostname)
{
ssl_vhost *vhost_p;
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, ssl_vhosts.head)
{
vhost_p = ptr->data;
if(!strcmp(hostname,vhost_p->hostname))
return ptr;
}
return NULL;
}
struct ssl_connect
{
CNCB *callback;
void *data;
int timeout;
};
static const char *rb_ssl_strerror(unsigned long);
static void rb_ssl_connect_realcb(rb_fde_t *, int, struct ssl_connect *);
/*
* Internal OpenSSL-specific code
*/
static unsigned long
rb_ssl_last_err(void)
{
unsigned long err_saved, err = 0;
while((err_saved = ERR_get_error()) != 0)
err = err_saved;
return err;
}
static void
rb_ssl_init_fd(rb_fde_t *const F, const rb_fd_tls_direction dir)
{
(void) rb_ssl_last_err();
F->ssl = SSL_new(ssl_ctx);
if(F->ssl == NULL)
{
rb_lib_log("%s: SSL_new: %s", __func__, rb_ssl_strerror(rb_ssl_last_err()));
rb_close(F);
return;
}
switch(dir)
{
case RB_FD_TLS_DIRECTION_IN:
SSL_set_accept_state(SSL_P(F));
break;
case RB_FD_TLS_DIRECTION_OUT:
SSL_set_connect_state(SSL_P(F));
break;
}
SSL_set_fd(SSL_P(F), rb_get_fd(F));
}
static void
rb_ssl_accept_common(rb_fde_t *const F, void *const data)
{
lrb_assert(F != NULL);
lrb_assert(F->accept != NULL);
lrb_assert(F->accept->callback != NULL);
lrb_assert(F->ssl != NULL);
(void) rb_ssl_last_err();
int ret = SSL_do_handshake(SSL_P(F));
int err = SSL_get_error(SSL_P(F), ret);
if(ret == 1)
{
F->handshake_count++;
rb_settimeout(F, 0, NULL, NULL);
rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL);
struct acceptdata *const ad = F->accept;
F->accept = NULL;
ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data);
rb_free(ad);
return;
}
if(ret == -1 && err == SSL_ERROR_WANT_READ)
{
rb_setselect(F, RB_SELECT_READ, rb_ssl_accept_common, NULL);
return;
}
if(ret == -1 && err == SSL_ERROR_WANT_WRITE)
{
rb_setselect(F, RB_SELECT_WRITE, rb_ssl_accept_common, NULL);
return;
}
errno = EIO;
F->ssl_errno = (unsigned long) err;
F->accept->callback(F, RB_ERROR_SSL, NULL, 0, F->accept->data);
}
static void
rb_ssl_connect_common(rb_fde_t *const F, void *const data)
{
lrb_assert(F != NULL);
lrb_assert(F->ssl != NULL);
(void) rb_ssl_last_err();
int ret = SSL_do_handshake(SSL_P(F));
int err = SSL_get_error(SSL_P(F), ret);
if(ret == 1)
{
F->handshake_count++;
rb_settimeout(F, 0, NULL, NULL);
rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL);
rb_ssl_connect_realcb(F, RB_OK, data);
return;
}
if(ret == -1 && err == SSL_ERROR_WANT_READ)
{
rb_setselect(F, RB_SELECT_READ, rb_ssl_connect_common, data);
return;
}
if(ret == -1 && err == SSL_ERROR_WANT_WRITE)
{
rb_setselect(F, RB_SELECT_WRITE, rb_ssl_connect_common, data);
return;
}
errno = EIO;
F->ssl_errno = (unsigned long) err;
rb_ssl_connect_realcb(F, RB_ERROR_SSL, data);
}
static const char *
rb_ssl_strerror(const unsigned long err)
{
static char errbuf[512];
ERR_error_string_n(err, errbuf, sizeof errbuf);
return errbuf;
}
static int
verify_accept_all_cb(const int preverify_ok, X509_STORE_CTX *const x509_ctx)
{
return 1;
}
static ssize_t
rb_ssl_read_or_write(const int r_or_w, rb_fde_t *const F, void *const rbuf, const void *const wbuf, const size_t count)
{
ssize_t ret;
unsigned long err;
(void) rb_ssl_last_err();
if(r_or_w == 0)
ret = (ssize_t) SSL_read(SSL_P(F), rbuf, (int)count);
else
ret = (ssize_t) SSL_write(SSL_P(F), wbuf, (int)count);
if(ret < 0)
{
switch(SSL_get_error(SSL_P(F), ret))
{
case SSL_ERROR_WANT_READ:
errno = EAGAIN;
return RB_RW_SSL_NEED_READ;
case SSL_ERROR_WANT_WRITE:
errno = EAGAIN;
return RB_RW_SSL_NEED_WRITE;
case SSL_ERROR_ZERO_RETURN:
return 0;
case SSL_ERROR_SYSCALL:
err = rb_ssl_last_err();
if(err == 0)
{
F->ssl_errno = 0;
return RB_RW_IO_ERROR;
}
break;
default:
err = rb_ssl_last_err();
break;
}
F->ssl_errno = err;
if(err > 0)
{
errno = EIO; /* not great but... */
return RB_RW_SSL_ERROR;
}
return RB_RW_IO_ERROR;
}
return ret;
}
static int
make_certfp(X509 *const cert, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method)
{
unsigned int hashlen = 0;
const EVP_MD *md_type = NULL;
const ASN1_ITEM *item = NULL;
void *data = NULL;
switch(method)
{
case RB_SSL_CERTFP_METH_CERT_SHA1:
hashlen = RB_SSL_CERTFP_LEN_SHA1;
md_type = EVP_sha1();
item = ASN1_ITEM_rptr(X509);
data = cert;
break;
case RB_SSL_CERTFP_METH_CERT_SHA256:
hashlen = RB_SSL_CERTFP_LEN_SHA256;
md_type = EVP_sha256();
item = ASN1_ITEM_rptr(X509);
data = cert;
break;
case RB_SSL_CERTFP_METH_CERT_SHA512:
hashlen = RB_SSL_CERTFP_LEN_SHA512;
md_type = EVP_sha512();
item = ASN1_ITEM_rptr(X509);
data = cert;
break;
case RB_SSL_CERTFP_METH_SPKI_SHA256:
hashlen = RB_SSL_CERTFP_LEN_SHA256;
md_type = EVP_sha256();
item = ASN1_ITEM_rptr(X509_PUBKEY);
data = X509_get_X509_PUBKEY(cert);
break;
case RB_SSL_CERTFP_METH_SPKI_SHA512:
hashlen = RB_SSL_CERTFP_LEN_SHA512;
md_type = EVP_sha512();
item = ASN1_ITEM_rptr(X509_PUBKEY);
data = X509_get_X509_PUBKEY(cert);
break;
default:
return 0;
}
if(ASN1_item_digest(item, md_type, data, certfp, &hashlen) != 1)
{
rb_lib_log("%s: ASN1_item_digest: %s", __func__, rb_ssl_strerror(rb_ssl_last_err()));
return 0;
}
return (int) hashlen;
}
/*
* External OpenSSL-specific code
*/
void
rb_ssl_shutdown(rb_fde_t *const F)
{
if(F == NULL || F->ssl == NULL)
return;
(void) rb_ssl_last_err();
for(int i = 0; i < 4; i++)
{
int ret = SSL_shutdown(SSL_P(F));
int err = SSL_get_error(SSL_P(F), ret);
if(ret >= 0 || (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE))
break;
}
SSL_free(SSL_P(F));
F->ssl = NULL;
}
int
rb_init_ssl(void)
{
#ifndef LRB_SSL_NO_EXPLICIT_INIT
(void) SSL_library_init();
SSL_load_error_strings();
#endif
rb_lib_log("%s: OpenSSL backend initialised", __func__);
return 1;
}
static int rb_ssl_servername_cb(SSL *s, int *ad, void *arg)
{
ssl_vhost *vhost_p;
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
const char * servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
rb_lib_log("Hostname in TLS extension?");
if (servername)
{
rb_lib_log("Hostname in TLS extension %s", servername);
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, ssl_vhosts.head)
{
vhost_p = ptr->data;
if (strcmp(servername, vhost_p->hostname) != 0)
continue;
if (vhost_p->ctx)
{
rb_lib_log("Switching server context %s", servername);
SSL_set_SSL_CTX(s,vhost_p->ctx);
}
}
}
return SSL_TLSEXT_ERR_OK;
}
void
free_ssl_vhost(ssl_vhost *vhost_p)
{
if(vhost_p == NULL)
return;
rb_free(vhost_p->hostname);
SSL_CTX_free(vhost_p->ctx);
rb_free(vhost_p);
}
int
rb_remove_ssl_vserver(const char *hostname)
{
rb_dlink_node *ptr = find_ssl_vhost(hostname);
if(ptr != NULL && ptr) {
rb_dlinkDelete(ptr, &ssl_vhosts);
free_ssl_vhost(ptr->data);
return 1;
}
return 0;
}
int
rb_setup_ssl_server(const char *const certfile, const char *keyfile,
const char *const dhfile, const char *cipherlist,
const char *hostname)
{
if(certfile == NULL)
{
rb_lib_log("%s: no certificate file specified", __func__);
return 0;
}
if(keyfile == NULL)
keyfile = certfile;
if(cipherlist == NULL)
cipherlist = rb_default_ciphers;
(void) rb_ssl_last_err();
#ifdef LRB_HAVE_TLS_METHOD_API
SSL_CTX *const ssl_ctx_new = SSL_CTX_new(TLS_method());
#else
SSL_CTX *const ssl_ctx_new = SSL_CTX_new(SSLv23_method());
#endif
if(ssl_ctx_new == NULL)
{
rb_lib_log("%s: SSL_CTX_new: %s", __func__, rb_ssl_strerror(rb_ssl_last_err()));
return 0;
}
if(SSL_CTX_use_certificate_chain_file(ssl_ctx_new, certfile) != 1)
{
rb_lib_log("%s: SSL_CTX_use_certificate_chain_file ('%s'): %s", __func__, certfile,
rb_ssl_strerror(rb_ssl_last_err()));
SSL_CTX_free(ssl_ctx_new);
return 0;
}
if(SSL_CTX_use_PrivateKey_file(ssl_ctx_new, keyfile, SSL_FILETYPE_PEM) != 1)
{
rb_lib_log("%s: SSL_CTX_use_PrivateKey_file ('%s'): %s", __func__, keyfile,
rb_ssl_strerror(rb_ssl_last_err()));
SSL_CTX_free(ssl_ctx_new);
return 0;
}
if(dhfile == NULL)
{
rb_lib_log("%s: no DH parameters file specified", __func__);
}
else
{
FILE *const dhf = fopen(dhfile, "r");
DH *dhp = NULL;
if(dhf == NULL)
{
rb_lib_log("%s: fopen ('%s'): %s", __func__, dhfile, strerror(errno));
}
else if(PEM_read_DHparams(dhf, &dhp, NULL, NULL) == NULL)
{
rb_lib_log("%s: PEM_read_DHparams ('%s'): %s", __func__, dhfile,
rb_ssl_strerror(rb_ssl_last_err()));
fclose(dhf);
}
else
{
SSL_CTX_set_tmp_dh(ssl_ctx_new, dhp);
DH_free(dhp);
fclose(dhf);
}
}
if(SSL_CTX_set_cipher_list(ssl_ctx_new, cipherlist) != 1)
{
rb_lib_log("%s: SSL_CTX_set_cipher_list: could not configure any ciphers", __func__);
SSL_CTX_free(ssl_ctx_new);
return 0;
}
SSL_CTX_set_tlsext_servername_callback(ssl_ctx_new, rb_ssl_servername_cb);
SSL_CTX_set_session_cache_mode(ssl_ctx_new, SSL_SESS_CACHE_OFF);
SSL_CTX_set_verify(ssl_ctx_new, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb);
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
(void) SSL_CTX_clear_options(ssl_ctx_new, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
#endif
#ifndef LRB_HAVE_TLS_METHOD_API
(void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
#endif
#ifdef SSL_OP_NO_TLSv1
(void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_NO_TLSv1);
#endif
#ifdef SSL_OP_NO_TICKET
(void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_NO_TICKET);
#endif
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
(void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_CIPHER_SERVER_PREFERENCE);
#endif
#ifdef SSL_OP_SINGLE_DH_USE
(void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_SINGLE_DH_USE);
#endif
#ifdef SSL_OP_SINGLE_ECDH_USE
(void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_SINGLE_ECDH_USE);
#endif
#ifdef LRB_HAVE_TLS_ECDH_AUTO
(void) SSL_CTX_set_ecdh_auto(ssl_ctx_new, 1);
#endif
#ifdef LRB_HAVE_TLS_SET_CURVES
(void) SSL_CTX_set1_curves_list(ssl_ctx_new, rb_default_curves);
#else
# if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && !defined(OPENSSL_NO_ECDH) && defined(NID_secp384r1)
EC_KEY *const ec_key = EC_KEY_new_by_curve_name(NID_secp384r1);
if(ec_key != NULL)
{
SSL_CTX_set_tmp_ecdh(ssl_ctx_new, ec_key);
EC_KEY_free(ec_key);
}
else
rb_lib_log("%s: EC_KEY_new_by_curve_name failed; will not enable ECDHE- ciphers", __func__);
# else
rb_lib_log("%s: OpenSSL built without ECDH support; will not enable ECDHE- ciphers", __func__);
# endif
#endif
rb_lib_log("%s: TLS configuration successful", __func__);
if(hostname == NULL) {
if(ssl_ctx)
SSL_CTX_free(ssl_ctx);
ssl_ctx = ssl_ctx_new;
} else {
ssl_vhost *vhost_p = NULL;
rb_lib_log("rb_setup_ssl_server: SETUP [%s]", hostname);
rb_dlink_node *ptr = find_ssl_vhost(hostname);
if(ptr != NULL && ptr)
vhost_p = ptr->data;
if(vhost_p == NULL) {
vhost_p = rb_malloc(sizeof(ssl_vhost));
vhost_p->hostname = rb_strdup(hostname);
rb_dlinkAdd(vhost_p, &vhost_p->node, &ssl_vhosts);
}
if(vhost_p->ctx)
SSL_CTX_free(vhost_p->ctx);
vhost_p->ctx = ssl_ctx_new;
}
return 1;
}
int
rb_init_prng(const char *const path, prng_seed_t seed_type)
{
(void) rb_ssl_last_err();
if(seed_type == RB_PRNG_FILE && RAND_load_file(path, -1) < 0)
rb_lib_log("%s: RAND_load_file: %s", __func__, rb_ssl_strerror(rb_ssl_last_err()));
if(RAND_status() != 1)
{
rb_lib_log("%s: RAND_status: %s", __func__, rb_ssl_strerror(rb_ssl_last_err()));
return 0;
}
rb_lib_log("%s: PRNG initialised", __func__);
return 1;
}
int
rb_get_random(void *const buf, const size_t length)
{
(void) rb_ssl_last_err();
if(RAND_bytes(buf, (int) length) != 1)
{
rb_lib_log("%s: RAND_bytes: %s", __func__, rb_ssl_strerror(rb_ssl_last_err()));
return 0;
}
return 1;
}
const char *
rb_get_ssl_strerror(rb_fde_t *const F)
{
return rb_ssl_strerror(F->ssl_errno);
}
int
rb_get_ssl_certfp(rb_fde_t *const F, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method)
{
if(F == NULL || F->ssl == NULL)
return 0;
X509 *const peer_cert = SSL_get_peer_certificate(SSL_P(F));
if(peer_cert == NULL)
return 0;
int len = 0;
switch(SSL_get_verify_result(SSL_P(F)))
{
case X509_V_OK:
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
case X509_V_ERR_CERT_UNTRUSTED:
len = make_certfp(peer_cert, certfp, method);
default:
X509_free(peer_cert);
return len;
}
}
void
rb_get_ssl_info(char *const buf, const size_t len)
{
#ifdef LRB_SSL_FULL_VERSION_INFO
if(LRB_SSL_VNUM_RUNTIME == LRB_SSL_VNUM_COMPILETIME)
(void) rb_snprintf(buf, len, "OpenSSL: compiled 0x%lx, library %s",
LRB_SSL_VNUM_COMPILETIME, LRB_SSL_VTEXT_COMPILETIME);
else
(void) rb_snprintf(buf, len, "OpenSSL: compiled (0x%lx, %s), library (0x%lx, %s)",
LRB_SSL_VNUM_COMPILETIME, LRB_SSL_VTEXT_COMPILETIME,
LRB_SSL_VNUM_RUNTIME, LRB_SSL_VTEXT_RUNTIME);
#else
(void) rb_snprintf(buf, len, "OpenSSL: compiled 0x%lx, library %s",
LRB_SSL_VNUM_COMPILETIME, LRB_SSL_VTEXT_RUNTIME);
#endif
}
const char *
rb_ssl_get_cipher(rb_fde_t *const F)
{
if(F == NULL || F->ssl == NULL)
return NULL;
static char buf[512];
const char *const version = SSL_get_version(SSL_P(F));
const char *const cipher = SSL_get_cipher_name(SSL_P(F));
(void) rb_snprintf(buf, sizeof buf, "%s, %s", version, cipher);
return buf;
}
ssize_t
rb_ssl_read(rb_fde_t *const F, void *const buf, const size_t count)
{
return rb_ssl_read_or_write(0, F, buf, NULL, count);
}
ssize_t
rb_ssl_write(rb_fde_t *const F, const void *const buf, const size_t count)
{
return rb_ssl_read_or_write(1, F, NULL, buf, count);
}
/*
* Internal library-agnostic code
*/
static void
rb_ssl_connect_realcb(rb_fde_t *const F, const int status, struct ssl_connect *const sconn)
{
lrb_assert(F->connect != NULL);
F->connect->callback = sconn->callback;
F->connect->data = sconn->data;
rb_connect_callback(F, status);
rb_free(sconn);
}
static void
rb_ssl_timeout_cb(rb_fde_t *const F, void *const data)
{
lrb_assert(F->accept != NULL);
lrb_assert(F->accept->callback != NULL);
F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data);
}
static void
rb_ssl_tryconn_timeout_cb(rb_fde_t *const F, void *const data)
{
rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data);
}
static void
rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data)
{
lrb_assert(F != NULL);
struct ssl_connect *const sconn = data;
if(status != RB_OK)
{
rb_ssl_connect_realcb(F, status, sconn);
return;
}
F->type |= RB_FD_SSL;
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT);
rb_ssl_connect_common(F, sconn);
}
/*
* External library-agnostic code
*/
int
rb_supports_ssl(void)
{
return 1;
}
unsigned int
rb_ssl_handshake_count(rb_fde_t *const F)
{
return F->handshake_count;
}
void
rb_ssl_clear_handshake_count(rb_fde_t *const F)
{
F->handshake_count = 0;
}
void
rb_ssl_start_accepted(rb_fde_t *const F, ACCB *const cb, void *const data, const int timeout)
{
F->type |= RB_FD_SSL;
F->accept = rb_malloc(sizeof(struct acceptdata));
F->accept->callback = cb;
F->accept->data = data;
F->accept->addrlen = 0;
(void) memset(&F->accept->S, 0x00, sizeof F->accept->S);
rb_settimeout(F, timeout, rb_ssl_timeout_cb, NULL);
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_IN);
rb_ssl_accept_common(F, NULL);
}
void
rb_ssl_accept_setup(rb_fde_t *const srv_F, rb_fde_t *const cli_F, struct sockaddr *const st, const int addrlen)
{
cli_F->type |= RB_FD_SSL;
cli_F->accept = rb_malloc(sizeof(struct acceptdata));
cli_F->accept->callback = srv_F->accept->callback;
cli_F->accept->data = srv_F->accept->data;
cli_F->accept->addrlen = (rb_socklen_t) addrlen;
(void) memset(&cli_F->accept->S, 0x00, sizeof cli_F->accept->S);
(void) memcpy(&cli_F->accept->S, st, (size_t) addrlen);
rb_settimeout(cli_F, 10, rb_ssl_timeout_cb, NULL);
rb_ssl_init_fd(cli_F, RB_FD_TLS_DIRECTION_IN);
rb_ssl_accept_common(cli_F, NULL);
}
int
rb_ssl_listen(rb_fde_t *const F, const int backlog, const int defer_accept)
{
int result = rb_listen(F, backlog, defer_accept);
F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL;
return result;
}
void
rb_connect_tcp_ssl(rb_fde_t *const F, struct sockaddr *const dest, struct sockaddr *const clocal,
const int socklen, CNCB *const callback, void *const data, const int timeout)
{
if(F == NULL)
return;
struct ssl_connect *const sconn = rb_malloc(sizeof *sconn);
sconn->data = data;
sconn->callback = callback;
sconn->timeout = timeout;
rb_connect_tcp(F, dest, clocal, socklen, rb_ssl_tryconn, sconn, timeout);
}
void
rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data, const int timeout)
{
if(F == NULL)
return;
struct ssl_connect *const sconn = rb_malloc(sizeof *sconn);
sconn->data = data;
sconn->callback = callback;
sconn->timeout = timeout;
F->connect = rb_malloc(sizeof(struct conndata));
F->connect->callback = callback;
F->connect->data = data;
F->type |= RB_FD_SSL;
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT);
rb_ssl_connect_common(F, sconn);
}
#endif /* HAVE_OPENSSL */

View file

@ -0,0 +1,141 @@
/*
* libratbox: a library used by ircd-ratbox and other things
* openssl_ratbox.h: OpenSSL backend data
*
* Copyright (C) 2015-2016 Aaron Jones <aaronmdjones@gmail.com>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
*/
#ifndef LRB_OPENSSL_H_INC
#define LRB_OPENSSL_H_INC 1
#include <openssl/dh.h>
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <openssl/opensslv.h>
/*
* A long time ago, in a world far away, OpenSSL had a well-established mechanism for ensuring compatibility with
* regards to added, changed, and removed functions, by having an SSLEAY_VERSION_NUMBER macro. This was then
* renamed to OPENSSL_VERSION_NUMBER, but the old macro was kept around for compatibility until OpenSSL version
* 1.1.0.
*
* Then the OpenBSD developers decided that having OpenSSL in their codebase was a bad idea. They forked it to
* create LibreSSL, gutted all of the functionality they didn't want or need, and generally improved the library
* a lot. Then, as the OpenBSD developers are want to do, they packaged up LibreSSL for release to other
* operating systems, as LibreSSL Portable. Think along the lines of OpenSSH where they have also done this.
*
* The fun part of this story ends there. LibreSSL has an OPENSSL_VERSION_NUMBER macro, but they have set it to a
* stupidly high value, version 2.0. OpenSSL version 2.0 does not exist, and LibreSSL 2.2 does not implement
* everything OpenSSL 1.0.2 or 1.1.0 do. This completely breaks the entire purpose of the macro.
*
* The ifdef soup below is for LibreSSL compatibility. Please find whoever thought setting OPENSSL_VERSION_NUMBER
* to a version that does not exist was a good idea. Encourage them to realise that it is not. -- amdj
*/
#if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L)
# define LRB_SSL_NO_EXPLICIT_INIT 1
#endif
#if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10002000L)
# define LRB_HAVE_TLS_SET_CURVES 1
# if (OPENSSL_VERSION_NUMBER < 0x10100000L)
# define LRB_HAVE_TLS_ECDH_AUTO 1
# endif
#endif
#if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x20020002L)
# define LRB_HAVE_TLS_METHOD_API 1
#else
# if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L)
# define LRB_HAVE_TLS_METHOD_API 1
# endif
#endif
#if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L)
# define LRB_SSL_VTEXT_COMPILETIME OPENSSL_VERSION_TEXT
# define LRB_SSL_VTEXT_RUNTIME OpenSSL_version(OPENSSL_VERSION)
# define LRB_SSL_VNUM_COMPILETIME OPENSSL_VERSION_NUMBER
# define LRB_SSL_VNUM_RUNTIME OpenSSL_version_num()
# define LRB_SSL_FULL_VERSION_INFO 1
#else
# if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x20200000L)
# define LRB_SSL_VTEXT_RUNTIME SSLeay_version(SSLEAY_VERSION)
# define LRB_SSL_VNUM_COMPILETIME LIBRESSL_VERSION_NUMBER
# else
# define LRB_SSL_VTEXT_RUNTIME SSLeay_version(SSLEAY_VERSION)
# define LRB_SSL_VNUM_COMPILETIME SSLEAY_VERSION_NUMBER
# endif
#endif
#if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER > 0x10101000L)
# define LRB_HAVE_TLS_ECDH_X25519 1
#else
# if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER > 0x2050100fL)
# define LRB_HAVE_TLS_ECDH_X25519 1
# endif
#endif
/*
* Default supported ciphersuites (if the user does not provide any) and
* curves (OpenSSL 1.0.2+). Hardcoded secp384r1 (NIST P-384) is used on
* OpenSSL 1.0.0 and 1.0.1 (if available).
*
* We prefer AEAD ciphersuites first in order of strength, then SHA2
* ciphersuites, then remaining suites.
*/
static const char rb_default_ciphers[] = ""
"aECDSA+kEECDH+CHACHA20:"
"aRSA+kEECDH+CHACHA20:"
"aRSA+kEDH+CHACHA20:"
"aECDSA+kEECDH+AESGCM:"
"aRSA+kEECDH+AESGCM:"
"aRSA+kEDH+AESGCM:"
"aECDSA+kEECDH+AESCCM:"
"aRSA+kEECDH+AESCCM:"
"aRSA+kEDH+AESCCM:"
"@STRENGTH:"
"aECDSA+kEECDH+HIGH+SHA384:"
"aRSA+kEECDH+HIGH+SHA384:"
"aRSA+kEDH+HIGH+SHA384:"
"aECDSA+kEECDH+HIGH+SHA256:"
"aRSA+kEECDH+HIGH+SHA256:"
"aRSA+kEDH+HIGH+SHA256:"
"aECDSA+kEECDH+HIGH:"
"aRSA+kEECDH+HIGH:"
"aRSA+kEDH+HIGH:"
"HIGH:"
"!3DES:"
"!aNULL";
#ifdef LRB_HAVE_TLS_SET_CURVES
# ifdef LRB_HAVE_TLS_ECDH_X25519
static char rb_default_curves[] = "X25519:P-521:P-384:P-256";
# else
static char rb_default_curves[] = "P-521:P-384:P-256";
# endif
#endif
#endif /* LRB_OPENSSL_H_INC */

424
libratbox/src/ratbox_lib.c Normal file
View file

@ -0,0 +1,424 @@
/*
* ircd-ratbox: A slightly useful ircd.
* ratbox_lib.c: libircd initialization functions at the like
*
* Copyright (C) 2005,2006 ircd-ratbox development team
* Copyright (C) 2005,2006 Aaron Sethman <androsyn@ratbox.org>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
* $Id: ratbox_lib.c 26282 2008-12-10 20:33:21Z androsyn $
*/
#include <libratbox_config.h>
#include <ratbox_lib.h>
#include <commio-int.h>
#include <commio-ssl.h>
static log_cb *rb_log;
static restart_cb *rb_restart;
static die_cb *rb_die;
static struct timeval rb_time;
static char errbuf[512];
/* this doesn't do locales...oh well i guess */
static const char *months[] = {
"January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December"
};
static const char *weekdays[] = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
};
static const char *s_month[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
"Aug", "Sep", "Oct", "Nov", "Dec"
};
static const char *s_weekdays[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
char *
rb_ctime(const time_t t, char *buf, size_t len)
{
char *p;
struct tm *tp;
static char timex[128];
size_t tlen;
#if defined(HAVE_GMTIME_R)
struct tm tmr;
tp = gmtime_r(&t, &tmr);
#else
tp = gmtime(&t);
#endif
if(buf == NULL)
{
p = timex;
tlen = sizeof(timex);
}
else
{
p = buf;
tlen = len;
}
if(rb_unlikely(tp == NULL))
{
rb_strlcpy(p, "", tlen);
return (p);
}
rb_snprintf(p, tlen, "%s %s %d %02u:%02u:%02u %d",
s_weekdays[tp->tm_wday], s_month[tp->tm_mon],
tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec, tp->tm_year + 1900);
return (p);
}
/* I hate this..but its sort of ircd standard now.. */
char *
rb_date(const time_t t, char *buf, size_t len)
{
struct tm *gm;
#if defined(HAVE_GMTIME_R)
struct tm gmbuf;
gm = gmtime_r(&t, &gmbuf);
#else
gm = gmtime(&t);
#endif
if(rb_unlikely(gm == NULL))
{
rb_strlcpy(buf, "", len);
return (buf);
}
rb_snprintf(buf, len, "%s %s %d %d -- %02u:%02u:%02u +00:00",
weekdays[gm->tm_wday], months[gm->tm_mon], gm->tm_mday,
gm->tm_year + 1900, gm->tm_hour, gm->tm_min, gm->tm_sec);
return (buf);
}
time_t
rb_current_time(void)
{
return rb_time.tv_sec;
}
const struct timeval *
rb_current_time_tv(void)
{
return &rb_time;
}
void
rb_lib_log(const char *format, ...)
{
va_list args;
if(rb_log == NULL)
return;
va_start(args, format);
rb_vsnprintf(errbuf, sizeof(errbuf), format, args);
va_end(args);
rb_log(errbuf);
}
void
rb_lib_die(const char *format, ...)
{
va_list args;
if(rb_die == NULL)
abort();
va_start(args, format);
rb_vsnprintf(errbuf, sizeof(errbuf), format, args);
va_end(args);
rb_die(errbuf);
}
void
rb_lib_restart(const char *format, ...)
{
va_list args;
if(rb_restart == NULL)
abort();
va_start(args, format);
rb_vsnprintf(errbuf, sizeof(errbuf), format, args);
va_end(args);
rb_restart(errbuf);
abort();
}
void
rb_set_time(void)
{
struct timeval newtime;
if(rb_unlikely(rb_gettimeofday(&newtime, NULL) == -1))
{
rb_lib_log("Clock Failure (%s)", strerror(errno));
rb_lib_restart("Clock Failure");
}
if(newtime.tv_sec < rb_time.tv_sec)
rb_set_back_events(rb_time.tv_sec - newtime.tv_sec);
memcpy(&rb_time, &newtime, sizeof(struct timeval));
}
extern const char *libratbox_serno;
const char *
rb_lib_version(void)
{
static char version_info[512];
char ssl_info[512];
rb_get_ssl_info(ssl_info, sizeof(ssl_info));
rb_snprintf(version_info, sizeof(version_info), "libratbox version: %s - %s", libratbox_serno, ssl_info);
return version_info;
}
void
rb_lib_init(log_cb * ilog, restart_cb * irestart, die_cb * idie, int closeall, int maxcon,
size_t dh_size, size_t fd_heap_size)
{
rb_set_time();
rb_log = ilog;
rb_restart = irestart;
rb_die = idie;
rb_event_init();
rb_init_bh();
rb_fdlist_init(closeall, maxcon, fd_heap_size);
rb_init_netio();
rb_init_rb_dlink_nodes(dh_size);
if(rb_io_supports_event())
{
rb_io_init_event();
}
}
void
rb_lib_loop(long delay)
{
time_t next;
rb_set_time();
if(rb_io_supports_event())
{
while(1)
rb_select(-1);
}
while(1)
{
if(delay == 0)
{
if((next = rb_event_next()) > 0)
{
next -= rb_current_time();
if(next <= 0)
next = 1000;
else
next *= 1000;
}
else
next = -1;
rb_select(next);
}
else
rb_select(delay);
rb_event_run();
}
}
#ifndef HAVE_STRTOK_R
char *
rb_strtok_r(char *s, const char *delim, char **save)
{
char *token;
if(s == NULL)
s = *save;
/* Scan leading delimiters. */
s += strspn(s, delim);
if(*s == '\0')
{
*save = s;
return NULL;
}
token = s;
s = strpbrk(token, delim);
if(s == NULL)
*save = (token + strlen(token));
else
{
*s = '\0';
*save = s + 1;
}
return token;
}
#else
char *
rb_strtok_r(char *s, const char *delim, char **save)
{
return strtok_r(s, delim, save);
}
#endif
static const char base64_table[] =
{ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
};
static const char base64_pad = '=';
static const short base64_reverse_table[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
unsigned char *
rb_base64_encode(const unsigned char *str, int length)
{
const unsigned char *current = str;
unsigned char *p;
unsigned char *result;
if((length + 2) < 0 || ((length + 2) / 3) >= (1 << (sizeof(int) * 8 - 2)))
{
return NULL;
}
result = rb_malloc(((length + 2) / 3) * 5);
p = result;
while(length > 2)
{
*p++ = base64_table[current[0] >> 2];
*p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
*p++ = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
*p++ = base64_table[current[2] & 0x3f];
current += 3;
length -= 3;
}
if(length != 0)
{
*p++ = base64_table[current[0] >> 2];
if(length > 1)
{
*p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
*p++ = base64_table[(current[1] & 0x0f) << 2];
*p++ = base64_pad;
}
else
{
*p++ = base64_table[(current[0] & 0x03) << 4];
*p++ = base64_pad;
*p++ = base64_pad;
}
}
*p = '\0';
return result;
}
unsigned char *
rb_base64_decode(const unsigned char *str, int length, int *ret)
{
const unsigned char *current = str;
int ch, i = 0, j = 0, k;
unsigned char *result;
result = rb_malloc(length + 1);
while((ch = *current++) != '\0' && length-- > 0)
{
if(ch == base64_pad)
break;
ch = base64_reverse_table[ch];
if(ch < 0)
continue;
switch (i % 4)
{
case 0:
result[j] = ch << 2;
break;
case 1:
result[j++] |= ch >> 4;
result[j] = (ch & 0x0f) << 4;
break;
case 2:
result[j++] |= ch >> 2;
result[j] = (ch & 0x03) << 6;
break;
case 3:
result[j++] |= ch;
break;
}
i++;
}
k = j;
if(ch == base64_pad)
{
switch (i % 4)
{
case 1:
free(result);
return NULL;
case 2:
k++;
/* FALLTHROUGH */
case 3:
result[k++] = 0;
}
}
result[j] = '\0';
*ret = j;
return result;
}

View file

@ -105,4 +105,8 @@ do_die(struct Client *source_p, const char *servername)
}
ircd_shutdown(get_client_name(source_p, HIDE_IP));
<<<<<<< .merge_file_0nztsK
/* UNREACHABLE */
=======
>>>>>>> .merge_file_F0prEH
}

View file

@ -424,7 +424,7 @@ ms_join(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
if(parv[2][0] == '&')
return;
mbuf = modebuf;
char *mbuf = modebuf;
mode.key[0] = mode.forward[0] = '\0';
mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
@ -539,8 +539,11 @@ ms_sjoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
int i, joinc = 0, timeslice = 0;
static char empty[] = "";
rb_dlink_node *ptr, *next_ptr;
<<<<<<< .merge_file_gR6TZa
=======
char *mbuf;
int pargs;
>>>>>>> .merge_file_qhnxdu
const char *para[MAXMODEPARAMS];
if(parc < 5)
@ -554,7 +557,7 @@ ms_sjoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
return;
modebuf[0] = parabuf[0] = mode.key[0] = mode.forward[0] = '\0';
pargs = mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
/* Hide connecting server on netburst -- jilles */
if (ConfigServerHide.flatten_links && !HasSentEob(source_p))
@ -562,7 +565,7 @@ ms_sjoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
else
fakesource_p = source_p;
mbuf = modebuf;
char *mbuf = modebuf;
newts = atol(parv[1]);
s = parv[3];
@ -769,9 +772,10 @@ ms_sjoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
mbuf = modebuf;
para[0] = para[1] = para[2] = para[3] = empty;
pargs = 0;
len_uid = 0;
int pargs = 0;
/* if theres a space, theres going to be more than one nick, change the
* first space to \0, so s is just the first nick, and point p to the
* second nick
@ -1171,8 +1175,12 @@ set_final_mode(char *mbuf, char *parabuf, struct Mode *mode, struct Mode *oldmod
len = sprintf(pbuf, "%s ", mode->forward);
pbuf += len;
}
*mbuf = '\0';
*mbuf = '\0';
<<<<<<< .merge_file_gR6TZa
=======
>>>>>>> .merge_file_qhnxdu
return mbuf;
}
@ -1194,6 +1202,10 @@ remove_our_modes(struct Channel *chptr, struct Client *source_p)
int i;
char *mbuf = lmodebuf;
<<<<<<< .merge_file_gR6TZa
char *mbuf = lmodebuf;
=======
>>>>>>> .merge_file_qhnxdu
*mbuf++ = '-';
for(i = 0; i < MAXMODEPARAMS; i++)
@ -1296,8 +1308,13 @@ remove_ban_list(struct Channel *chptr, struct Client *source_p,
pbuf = lparabuf;
<<<<<<< .merge_file_gR6TZa
cur_len = mlen = rb_sprintf(lmodebuf, ":%s MODE %s -", source_p->name, chptr->chname);
char *mbuf = lmodebuf + mlen;
=======
cur_len = mlen = sprintf(lmodebuf, ":%s MODE %s -", source_p->name, chptr->chname);
mbuf = lmodebuf + mlen;
>>>>>>> .merge_file_qhnxdu
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
{

View file

@ -370,7 +370,10 @@ do_bmask(bool extended, struct MsgBuf *msgbuf_p, struct Client *client_p, struct
{
*forward++ = '\0';
if(*forward == '\0')
tlen--, forward = NULL;
{
tlen--;
forward = NULL;
}
else
possibly_remove_lower_forward(fakesource_p,
mems, chptr, banlist,

View file

@ -133,9 +133,13 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
}
exit_client(client_p, client_p, client_p, "Invalid servername.");
<<<<<<< .merge_file_pjgqgl
return 0;
=======
return;
/* NOT REACHED */
break;
>>>>>>> .merge_file_QmFPuY
case -2:
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
@ -148,9 +152,13 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
log_client_name(client_p, SHOW_IP));
exit_client(client_p, client_p, client_p, "Invalid credentials.");
<<<<<<< .merge_file_pjgqgl
return 0;
=======
return;
/* NOT REACHED */
break;
>>>>>>> .merge_file_QmFPuY
case -3:
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
@ -163,9 +171,13 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
log_client_name(client_p, SHOW_IP));
exit_client(client_p, client_p, client_p, "Invalid host.");
<<<<<<< .merge_file_pjgqgl
return 0;
=======
return;
/* NOT REACHED */
break;
>>>>>>> .merge_file_QmFPuY
/* servername is > HOSTLEN */
case -4:
@ -176,9 +188,14 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
log_client_name(client_p, SHOW_IP));
exit_client(client_p, client_p, client_p, "Invalid servername.");
<<<<<<< .merge_file_pjgqgl
return 0;
=======
return;
/* NOT REACHED */
break;
>>>>>>> .merge_file_QmFPuY
case -5:
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Connection from servername %s requires SSL/TLS but is plaintext",
@ -187,11 +204,20 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
log_client_name(client_p, SHOW_IP));
exit_client(client_p, client_p, client_p, "Access denied, requires SSL/TLS but is plaintext");
<<<<<<< .merge_file_pjgqgl
return 0;
case -6:
if (client_p->certfp)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
=======
return;
case -6:
if (client_p->certfp)
{
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
>>>>>>> .merge_file_QmFPuY
"Connection from servername %s has invalid certificate fingerprint %s",
name, client_p->certfp);
ilog(L_SERVER, "Access denied, invalid certificate fingerprint %s from %s",
@ -200,7 +226,11 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
}
else
{
<<<<<<< .merge_file_pjgqgl
sendto_realops_snomask(SNO_GENERAL, L_ALL,
=======
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
>>>>>>> .merge_file_QmFPuY
"Connection from servername %s failed certificate validation",
name);
ilog(L_SERVER, "Access denied; certificate validation failed for certificate from %s",
@ -208,6 +238,12 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
exit_client(client_p, client_p, client_p, "Invalid certificate.");
}
<<<<<<< .merge_file_pjgqgl
return 0;
default:
sendto_realops_snomask(SNO_GENERAL, L_ALL,
=======
return;
case -7:
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
@ -220,6 +256,7 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
return;
default:
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
>>>>>>> .merge_file_QmFPuY
"Connection from servername %s rejected, unknown error %d",
name, ret);
ilog(L_SERVER, "Access denied, unknown error %d for server %s%s", ret,
@ -227,7 +264,11 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
log_client_name(client_p, SHOW_IP));
exit_client(client_p, client_p, client_p, "Unknown error.");
<<<<<<< .merge_file_pjgqgl
return 0;
=======
return;
>>>>>>> .merge_file_QmFPuY
}
/* require TS6 for direct links */
@ -298,7 +339,11 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
if (client_p->preClient && !EmptyString(client_p->preClient->id)) {
if ((target_p = find_id(client_p->preClient->id)) != NULL) {
<<<<<<< .merge_file_pjgqgl
sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) ? L_NETWIDE : L_ALL,
=======
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
>>>>>>> .merge_file_QmFPuY
"Attempt to re-introduce SID %s from %s%s (already in use by %s)",
client_p->preClient->id,
EmptyString(client_p->name) ? name : "",
@ -311,7 +356,11 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
sendto_one(client_p, "ERROR :SID already exists.");
exit_client(client_p, client_p, client_p, "SID Exists");
<<<<<<< .merge_file_pjgqgl
return 0;
=======
return;
>>>>>>> .merge_file_QmFPuY
} else {
rb_strlcpy(client_p->id, client_p->preClient->id, sizeof(client_p->id));
}

View file

@ -152,6 +152,16 @@ clicap_find(const char *data, int *negate, int *finished)
static void
clicap_generate(struct Client *source_p, const char *subcmd, int flags)
{
<<<<<<< .merge_file_FIhLV9
char buf[BUFSIZE] = { 0 };
char capbuf[BUFSIZE] = { 0 };
char *p;
int buflen = 0;
int curlen, mlen;
size_t i;
mlen = rb_sprintf(buf, ":%s CAP %s %s",
=======
const char *str_cont = "* :";
const char *str_final = ":";
struct CapabilityEntry *entry;
@ -160,6 +170,7 @@ clicap_generate(struct Client *source_p, const char *subcmd, int flags)
enum multiline_item_result multiline_item_ret;
multiline_ret = send_multiline_init(source_p, " ", ":%s CAP %s %s %s",
>>>>>>> .merge_file_J3fUTs
me.name,
EmptyString(source_p->name) ? "*" : source_p->name,
subcmd,
@ -207,10 +218,30 @@ clicap_generate(struct Client *source_p, const char *subcmd, int flags)
if (!flags && clicap != NULL && clicap->data != NULL)
data = clicap->data(source_p);
<<<<<<< .merge_file_FIhLV9
/* \r\n\0, possible "-~=", space, " *" */
if(buflen + clicap_list[i].namelen >= BUFSIZE - 10)
{
/* remove our trailing space -- if buflen == mlen
* here, we didnt even succeed in adding one.
*/
if(buflen != mlen)
*(p - 1) = '\0';
else
*p = '\0';
sendto_one(source_p, "%s * :%s", buf, capbuf);
p = capbuf;
buflen = mlen;
memset(capbuf, 0, sizeof(capbuf));
}
=======
multiline_item_ret = send_multiline_item(source_p, "%s%s%s",
entry->cap,
data != NULL ? "=" : "",
data != NULL ? data : "");
>>>>>>> .merge_file_J3fUTs
if (multiline_item_ret == MULTILINE_FAILURE)
return;

View file

@ -416,6 +416,12 @@ static struct InfoStruct info_table[] = {
"Minimum delay between less intensive commands",
INFO_DECIMAL(&ConfigFileEntry.pace_wait_simple),
},
{
"listfake_wait",
OUTPUT_DECIMAL,
&ConfigFileEntry.listfake_wait,
"Time until real list command can be used"
},
{
"ping_cookie",
"Require ping cookies to connect",

View file

@ -156,7 +156,37 @@ m_list(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
last_used = rb_current_time();
}
<<<<<<< .merge_file_PyqEuU
/* Disable LIST for a configured timespan after connect and send configured fake
* channels instead.
* Exempts: Opers, identifed users and users with spambot_exempt flag
*/
if (((source_p->localClient->firsttime + ConfigFileEntry.listfake_wait) > rb_current_time())
&& !IsOper(source_p) && !IsExemptSpambot(source_p) &&
!(source_p->user != NULL && !EmptyString(source_p->user->suser)))
{
struct fakechannel_entry *fakechannel;
struct DictionaryIter iter;
sendto_one(source_p, form_str(RPL_LISTSTART), me.name, source_p->name);
DICTIONARY_FOREACH(fakechannel, &iter, fakechannel_dict)
{
sendto_one(source_p, form_str(RPL_LIST), me.name, source_p->name,
"",
fakechannel->name,
(rand() % fakechannel->users_max + fakechannel->users_min),
fakechannel->topic);
}
sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
return 0;
}
return mo_list(client_p, source_p, parc, parv);
=======
mo_list(msgbuf_p, client_p, source_p, parc, parv);
>>>>>>> .merge_file_yv6CiZ
}
/* mo_list()

View file

@ -40,11 +40,15 @@
#include "reject.h"
#include "hash.h"
#include "cache.h"
<<<<<<< .merge_file_Kl8bB5
#include "sslproc.h"
=======
#include "rb_radixtree.h"
#include "sslproc.h"
static const char rehash_desc[] =
"Provides the REHASH command to reload configuration and other files";
>>>>>>> .merge_file_4WlQOU
static void mo_rehash(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
static void me_rehash(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
@ -102,6 +106,22 @@ rehash_ssld(struct Client *source_p)
restart_ssld();
}
static void
rehash_ssld(struct Client *source_p)
{
if (!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
me.name, source_p->name, "admin");
return;
}
sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s is restarting ssld",
get_oper_name(source_p));
restart_ssld();
}
static void
rehash_motd(struct Client *source_p)
{
@ -350,7 +370,12 @@ do_rehash(struct Client *source_p, const char *type)
remote_rehash_oper_p = source_p;
ilog(L_MAIN, "REHASH From %s[%s]", get_oper_name(source_p),
source_p->sockhost);
<<<<<<< .merge_file_Kl8bB5
rehash(0);
rehash_ulimit();
=======
rehash(false);
>>>>>>> .merge_file_4WlQOU
remote_rehash_oper_p = NULL;
}
}
@ -374,13 +399,25 @@ mo_rehash(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
}
if (parc > 2)
type = parv[1], target_server = parv[2];
{
type = parv[1];
target_server = parv[2];
}
else if (parc > 1 && (strchr(parv[1], '.') || strchr(parv[1], '?') || strchr(parv[1], '*')))
type = NULL, target_server = parv[1];
{
type = NULL;
target_server = parv[1];
}
else if (parc > 1)
type = parv[1], target_server = NULL;
{
type = parv[1];
target_server = NULL;
}
else
type = NULL, target_server = NULL;
{
type = NULL;
target_server = NULL;
}
if (target_server != NULL)
{

View file

@ -127,4 +127,8 @@ do_restart(struct Client *source_p, const char *servername)
sprintf(buf, "Server RESTART by %s", get_client_name(source_p, HIDE_IP));
restart(buf);
<<<<<<< .merge_file_Q6Imwg
/* UNREACHABLE */
=======
>>>>>>> .merge_file_lKBA0a
}

View file

@ -52,8 +52,17 @@ static void me_mechlist(struct MsgBuf *, struct Client *, struct Client *, int,
static void abort_sasl(void *);
static void abort_sasl_exit(void *);
<<<<<<< .merge_file_j0yiRK
static void advertise_sasl_cap(int);
static void advertise_sasl_new(struct Client *);
static void advertise_sasl_exit(void *);
static void advertise_sasl_config(void *);
static int sasl_agent_present = 0;
=======
static unsigned int CLICAP_SASL = 0;
static char mechlist_buf[BUFSIZE];
>>>>>>> .merge_file_hyMtKJ
struct Message authenticate_msgtab = {
"AUTHENTICATE", 0, 0, 0, 0,
@ -72,6 +81,42 @@ mapi_clist_av1 sasl_clist[] = {
&authenticate_msgtab, &sasl_msgtab, &mechlist_msgtab, NULL
};
mapi_hfn_list_av1 sasl_hfnlist[] = {
<<<<<<< .merge_file_j0yiRK
{ "new_local_user", (hookfn) abort_sasl },
{ "client_exit", (hookfn) abort_sasl_exit },
{ "new_remote_user", (hookfn) advertise_sasl_new },
{ "after_client_exit", (hookfn) advertise_sasl_exit },
{ "conf_read_end", (hookfn) advertise_sasl_config },
{ NULL, NULL }
};
static int
sasl_visible(void)
{
struct Client *agent_p = NULL;
if (ConfigFileEntry.sasl_service)
agent_p = find_named_client(ConfigFileEntry.sasl_service);
return agent_p != NULL && IsService(agent_p);
}
static int
_modinit(void)
{
sasl_agent_present = 0;
advertise_sasl_config(NULL);
return 0;
}
static void
_moddeinit(void)
{
advertise_sasl_cap(0);
}
DECLARE_MODULE_AV1(sasl, _modinit, _moddeinit, sasl_clist, NULL, sasl_hfnlist, "$Revision: 1409 $");
=======
{ "client_exit", abort_sasl_exit },
{ NULL, NULL }
};
@ -91,6 +136,7 @@ mapi_cap_list_av2 sasl_cap_list[] = {
{ MAPI_CAP_CLIENT, "sasl", &capdata_sasl, &CLICAP_SASL },
{ 0, NULL, NULL, NULL },
};
>>>>>>> .merge_file_hyMtKJ
static int
_modinit(void)
@ -130,6 +176,12 @@ m_authenticate(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *
return;
}
if (*parv[1] == ':' || strchr(parv[1], ' '))
{
exit_client(client_p, client_p, client_p, "Malformed AUTHENTICATE");
return 0;
}
saslserv_p = find_named_client(ConfigFileEntry.sasl_service);
if(saslserv_p == NULL || !IsService(saslserv_p))
{
@ -165,13 +217,21 @@ m_authenticate(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *
{
sendto_one(source_p, form_str(ERR_SASLABORTED), me.name, EmptyString(source_p->name) ? "*" : source_p->name);
source_p->localClient->sasl_out = 0;
<<<<<<< .merge_file_j0yiRK
return 0;
=======
return;
>>>>>>> .merge_file_hyMtKJ
}
sendto_one(saslserv_p, ":%s ENCAP %s SASL %s %s H %s %s %c",
me.id, saslserv_p->servptr->name, source_p->id, saslserv_p->id,
source_p->host, source_p->sockhost,
<<<<<<< .merge_file_j0yiRK
IsSSL(source_p) ? 'S' : 'P');
=======
IsSecure(source_p) ? 'S' : 'P');
>>>>>>> .merge_file_hyMtKJ
if (source_p->certfp != NULL)
sendto_one(saslserv_p, ":%s ENCAP %s SASL %s %s S %s %s",
@ -191,13 +251,22 @@ m_authenticate(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *
sendto_one(source_p, form_str(ERR_SASLABORTED), me.name, EmptyString(source_p->name) ? "*" : source_p->name);
sendto_one(agent_p, ":%s ENCAP %s SASL %s %s D A", me.id, agent_p->servptr->name, source_p->id, agent_p->id);
source_p->localClient->sasl_out = 0;
<<<<<<< .merge_file_j0yiRK
return 0;
=======
return;
>>>>>>> .merge_file_hyMtKJ
}
sendto_one(agent_p, ":%s ENCAP %s SASL %s %s C %s",
me.id, agent_p->servptr->name, source_p->id, agent_p->id,
parv[1]);
}
<<<<<<< .merge_file_j0yiRK
source_p->localClient->sasl_out++;
=======
>>>>>>> .merge_file_hyMtKJ
source_p->localClient->sasl_out++;
}
@ -233,6 +302,10 @@ me_sasl(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
/* If SASL has been aborted, we only want to track authentication failures. */
in_progress = target_p->localClient->sasl_out != 0;
/* If SASL has been aborted, do nothing. */
if (target_p->localClient->sasl_out == 0)
return 0;
/* Reject if someone has already answered. */
if(*target_p->localClient->sasl_agent && strncmp(parv[1], target_p->localClient->sasl_agent, IDLEN))
return;
@ -334,3 +407,48 @@ abort_sasl_exit(void *data_)
if (data->target->localClient)
abort_sasl(data->target);
}
<<<<<<< .merge_file_j0yiRK
static void
advertise_sasl_cap(int available)
{
if (sasl_agent_present != available) {
if (available) {
sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * NEW :sasl", me.name);
} else {
sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * DEL :sasl", me.name);
}
sasl_agent_present = available;
}
}
static void
advertise_sasl_new(struct Client *client_p)
{
if (!ConfigFileEntry.sasl_service)
return;
if (irccmp(client_p->name, ConfigFileEntry.sasl_service))
return;
advertise_sasl_cap(IsService(client_p));
}
static void
advertise_sasl_exit(void *ignored)
{
if (!ConfigFileEntry.sasl_service)
return;
if (sasl_agent_present) {
advertise_sasl_cap(sasl_visible());
}
}
static void
advertise_sasl_config(void *ignored)
{
advertise_sasl_cap(sasl_visible());
}
=======
>>>>>>> .merge_file_hyMtKJ

View file

@ -99,9 +99,13 @@ mr_starttls(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sou
sendto_one_numeric(client_p, RPL_STARTTLS, form_str(RPL_STARTTLS));
send_queued(client_p);
<<<<<<< .merge_file_2ab79i
ctl = start_ssld_accept(client_p->localClient->F, F[1], client_p->localClient->connid);
=======
/* TODO: set localClient->ssl_callback and handle success/failure */
ctl = start_ssld_accept(client_p->localClient->F, F[1], connid_get(client_p));
>>>>>>> .merge_file_h35QVt
if (ctl != NULL)
{
client_p->localClient->F = F[0];
@ -109,4 +113,11 @@ mr_starttls(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sou
SetSSL(client_p);
SetSecure(client_p);
}
<<<<<<< .merge_file_2ab79i
else
return 1;
return 0;
=======
>>>>>>> .merge_file_h35QVt
}

View file

@ -44,12 +44,19 @@
#include "hash.h"
#include "reject.h"
#include "whowas.h"
<<<<<<< .merge_file_voAp55
#include "sslproc.h"
#define Lformat "%s %u %u %u %u %u :%ld %ld %s"
#define Sformat ":%s %d %s %s %u %u %u %u %u :%ld %ld %s"
=======
#include "rb_radixtree.h"
#include "sslproc.h"
#include "s_assert.h"
static const char stats_desc[] =
"Provides the STATS command to inspect various server/network information";
>>>>>>> .merge_file_gExsVy
static void m_stats (struct MsgBuf *, struct Client *, struct Client *, int, const char **);
@ -72,10 +79,15 @@ mapi_hlist_av1 stats_hlist[] = {
DECLARE_MODULE_AV2(stats, NULL, NULL, stats_clist, stats_hlist, NULL, NULL, NULL, stats_desc);
<<<<<<< .merge_file_voAp55
static void stats_l_list(struct Client *s, const char *, int, int, rb_dlink_list *, char,
int (*check_fn)(struct Client *target_p));
=======
const char *Lformat = "%s %u %u %u %u %u :%u %u %s";
static void stats_l_list(struct Client *s, const char *, bool, bool, rb_dlink_list *, char,
bool (*check_fn)(struct Client *source_p, struct Client *target_p));
>>>>>>> .merge_file_gExsVy
static void stats_l_client(struct Client *source_p, struct Client *target_p,
char statchar);
@ -117,7 +129,10 @@ static void stats_operedup(struct Client *);
static void stats_ports(struct Client *);
static void stats_tresv(struct Client *);
static void stats_resv(struct Client *);
<<<<<<< .merge_file_voAp55
=======
static void stats_secure(struct Client *);
>>>>>>> .merge_file_gExsVy
static void stats_ssld(struct Client *);
static void stats_usage(struct Client *);
static void stats_tstats(struct Client *);
@ -144,6 +159,58 @@ static void stats_capability(struct Client *);
* C initalisers so we don't have to iterate anymore
* --Elizafox
*/
<<<<<<< .merge_file_voAp55
static struct StatsStruct stats_cmd_table[] = {
/* letter function need_oper need_admin */
{'a', stats_dns_servers, 1, 1, },
{'A', stats_dns_servers, 1, 1, },
{'b', stats_delay, 1, 1, },
{'B', stats_hash, 1, 1, },
{'c', stats_connect, 0, 0, },
{'C', stats_capability, 1, 0, },
{'d', stats_tdeny, 1, 0, },
{'D', stats_deny, 1, 0, },
{'e', stats_exempt, 1, 0, },
{'E', stats_events, 1, 1, },
{'f', stats_comm, 1, 1, },
{'F', stats_comm, 1, 1, },
{'g', stats_prop_klines, 1, 0, },
{'h', stats_hubleaf, 0, 0, },
{'H', stats_hubleaf, 0, 0, },
{'i', stats_auth, 0, 0, },
{'I', stats_auth, 0, 0, },
{'k', stats_tklines, 0, 0, },
{'K', stats_klines, 0, 0, },
{'l', NULL /* special */, 0, 0, },
{'L', NULL /* special */, 0, 0, },
{'m', stats_messages, 0, 0, },
{'M', stats_messages, 0, 0, },
{'n', stats_dnsbl, 0, 0, },
{'o', stats_oper, 0, 0, },
{'O', stats_privset, 1, 0, },
{'p', stats_operedup, 0, 0, },
{'P', stats_ports, 0, 0, },
{'q', stats_tresv, 1, 0, },
{'Q', stats_resv, 1, 0, },
{'r', stats_usage, 1, 0, },
{'R', stats_usage, 1, 0, },
{'s', stats_ssld, 1, 1, },
{'S', stats_ssld, 1, 1, },
{'t', stats_tstats, 1, 0, },
{'T', stats_tstats, 1, 0, },
{'u', stats_uptime, 0, 0, },
{'U', stats_shared, 1, 0, },
{'v', stats_servers, 0, 0, },
{'V', stats_servers, 0, 0, },
{'x', stats_tgecos, 1, 0, },
{'X', stats_gecos, 1, 0, },
{'y', stats_class, 0, 0, },
{'Y', stats_class, 0, 0, },
{'z', stats_memory, 1, 0, },
{'Z', stats_ziplinks, 1, 0, },
{'?', stats_servlinks, 0, 0, },
{(char) 0, (void (*)(struct Client *)) 0, 0, 0, }
=======
static struct stats_cmd stats_cmd_table[256] = {
/* letter handler admin priv */
['a'] = HANDLER_NORM(stats_dns_servers, true, NULL),
@ -189,6 +256,7 @@ static struct stats_cmd stats_cmd_table[256] = {
['Y'] = HANDLER_NORM(stats_class, false, NULL),
['z'] = HANDLER_NORM(stats_memory, false, "oper:general"),
['?'] = HANDLER_NORM(stats_servlinks, false, NULL),
>>>>>>> .merge_file_gExsVy
};
/*
@ -921,6 +989,24 @@ stats_ssld(struct Client *source_p)
ssld_foreach_info(stats_ssld_foreach, source_p);
}
static void
stats_ssld_foreach(void *data, pid_t pid, int cli_count, enum ssld_status status)
{
struct Client *source_p = data;
sendto_one_numeric(source_p, RPL_STATSDEBUG,
"S :%u %c %u",
pid,
status == SSLD_DEAD ? 'D' : (status == SSLD_SHUTDOWN ? 'S' : 'A'),
cli_count);
}
static void
stats_ssld(struct Client *source_p)
{
ssld_foreach_info(stats_ssld_foreach, source_p);
}
static void
stats_usage (struct Client *source_p)
{
@ -1399,7 +1485,6 @@ stats_memory (struct Client *source_p)
static void
stats_servlinks (struct Client *source_p)
{
static char Sformat[] = ":%s %d %s %s %u %u %u %u %u :%u %u %s";
long uptime, sendK, receiveK;
struct Client *target_p;
rb_dlink_node *ptr;
@ -1434,8 +1519,13 @@ stats_servlinks (struct Client *source_p)
(int) target_p->localClient->receiveK,
rb_current_time() - target_p->localClient->firsttime,
(rb_current_time() > target_p->localClient->lasttime) ?
<<<<<<< .merge_file_voAp55
(rb_current_time() - target_p->localClient->lasttime) : (long) 0,
IsOper (source_p) ? show_capabilities (target_p) : "TS");
=======
(rb_current_time() - target_p->localClient->lasttime) : 0,
IsOperGeneral (source_p) ? show_capabilities (target_p) : "TS");
>>>>>>> .merge_file_gExsVy
}
sendto_one_numeric(source_p, RPL_STATSDEBUG,
@ -1615,8 +1705,13 @@ stats_l_client(struct Client *source_p, struct Client *target_p,
(int) target_p->localClient->receiveK,
rb_current_time() - target_p->localClient->firsttime,
(rb_current_time() > target_p->localClient->lasttime) ?
<<<<<<< .merge_file_voAp55
(rb_current_time() - target_p->localClient->lasttime) : (long) 0,
IsOper(source_p) ? show_capabilities(target_p) : "-");
=======
(rb_current_time() - target_p->localClient->lasttime) : 0,
IsOperGeneral(source_p) ? show_capabilities(target_p) : "-");
>>>>>>> .merge_file_gExsVy
}
else
@ -1641,8 +1736,13 @@ stats_l_client(struct Client *source_p, struct Client *target_p,
hdata_showidle.approved ? (int) target_p->localClient->receiveM : 0,
hdata_showidle.approved ? (int) target_p->localClient->receiveK : 0,
rb_current_time() - target_p->localClient->firsttime,
<<<<<<< .merge_file_voAp55
(rb_current_time() > target_p->localClient->lasttime) ?
(rb_current_time() - target_p->localClient->lasttime) : (long) 0,
=======
(rb_current_time() > target_p->localClient->lasttime) && hdata_showidle.approved ?
(rb_current_time() - target_p->localClient->lasttime) : 0,
>>>>>>> .merge_file_gExsVy
"-");
}
}

View file

@ -300,6 +300,16 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy)
{
s = ConfigFileEntry.servicestring;
}
<<<<<<< .merge_file_zYZ429
if(MyClient(target_p) && !EmptyString(target_p->localClient->opername) && IsOper(target_p) && IsOper(source_p))
{
char obuf[512];
rb_snprintf(obuf, sizeof(obuf), "is opered as %s, privset %s",
target_p->localClient->opername, target_p->localClient->privset->name);
sendto_one_numeric(source_p, RPL_WHOISSPECIAL, form_str(RPL_WHOISSPECIAL),
target_p->name, obuf);
=======
if (!EmptyString(target_p->user->opername) && IsOper(target_p))
{
if (target_p == source_p || HasPrivilege(source_p, "oper:privs"))
@ -325,6 +335,7 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy)
{
sendto_one_numeric(source_p, RPL_WHOISOPERATOR, form_str(RPL_WHOISOPERATOR),
target_p->name, s);
>>>>>>> .merge_file_AQS60w
}
if(IsSecureClient(target_p))

106
modules/static_modules.c.SH Normal file
View file

@ -0,0 +1,106 @@
#!/bin/sh
# static_modules.c.SH: Generates our static module list
# $Id: static_modules.c.SH 6 2005-09-10 01:02:21Z nenolod $
#
SYMS=`for x in $*; do basename $x .o|sed -es/^m_//; done`
cat > static_modules.c <<EOF
/*
* This file is automatically generated: do not modify
* ircd-ratbox: A slightly useful ircd
*
* Copyright (C) 2003 Aaron Sethman <androsyn@ratbox.org>
* Copyright (C) 2003-2005 ircd-ratbox development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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 "hash.h"
#include "logger.h"
EOF
for x in $SYMS; do
echo extern struct mapi_header_av1 "$x"_mheader\;
done >> static_modules.c
echo static const struct mapi_header_av1 *mapi_headers[] = { >> static_modules.c
for x in $SYMS; do
echo \&"$x"_mheader,
done >> static_modules.c
echo NULL }\; >> static_modules.c
cat >> static_modules.c <<EOF
void load_static_modules(void)
{
int x;
int *mapi_version;
for(x = 0; mapi_headers[x] != NULL; x++)
{
mapi_version = (int *)mapi_headers[x];
if(MAPI_MAGIC(*mapi_version) != MAPI_MAGIC_HDR)
{
ilog(L_MAIN, "Error: linked in module without a MAPI header..giving up");
exit(70);
}
switch(MAPI_VERSION(*mapi_version))
{
case 1:
{
struct mapi_mheader_av1 *mheader = (struct mapi_mheader_av1*)mapi_version;
if (mheader->mapi_register && (mheader->mapi_register() == -1))
{
ilog(L_MAIN, "Error: linked in module failed loading..giving up");
exit(70);
}
if(mheader->mapi_command_list)
{
struct Message **m;
for(m = mheader->mapi_command_list; *m; ++m)
mod_add_cmd(*m);
}
if(mheader->mapi_hook_list)
{
mapi_hlist_av1 *m;
for(m = mheader->mapi_hook_list; m->hapi_name; ++m)
*m->hapi_id = register_hook(m->hapi_name);
}
if(mheader->mapi_hfn_list)
{
mapi_hfn_list_av1 *m;
for(m = mheader->mapi_hfn_list; m->hapi_name; ++m)
add_hook(m->hapi_name, m->fn);
}
break;
}
default:
{
ilog(L_MAIN, "Error: Unknown MAPI version in linked in module..giving up");
exit(70);
}
}
}
}
EOF

View file

@ -0,0 +1,12 @@
diff --git a/src/bandbi.c b/src/bandbi.c
index 96f65b4..0a85a92 100644
--- a/src/bandbi.c
+++ b/src/bandbi.c
@@ -82,7 +82,6 @@ start_bandb(void)
const char *suffix = "";
#endif
- rb_setenv("BANDB_DBPATH", PKGLOCALSTATEDIR "/ban.db", 1);
if(bandb_path == NULL)
{
rb_snprintf(fullpath, sizeof(fullpath), "%s/bandb%s", PKGLIBEXECDIR, suffix);

454
src/bandbi.c Normal file
View file

@ -0,0 +1,454 @@
/* src/bandbi.c
* An interface to the ban db.
*
* Copyright (C) 2006 Lee Hardy <lee -at- leeh.co.uk>
* Copyright (C) 2006 ircd-ratbox 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.
*
* $Id$
*/
#include "stdinc.h"
#include "ratbox_lib.h"
#include "client.h"
#include "s_conf.h"
#include "logger.h"
#include "match.h"
#include "bandbi.h"
#include "parse.h"
#include "channel.h"
#include "hostmask.h"
#include "hash.h"
#include "s_newconf.h"
#include "reject.h"
#include "send.h"
#include "ircd.h"
#include "msg.h" /* XXX: MAXPARA */
#include "operhash.h"
static char bandb_add_letter[LAST_BANDB_TYPE] = {
'K', 'D', 'X', 'R'
};
rb_dlink_list bandb_pending;
static rb_helper *bandb_helper;
static int start_bandb(void);
static void bandb_parse(rb_helper *);
static void bandb_restart_cb(rb_helper *);
static char *bandb_path;
void
init_bandb(void)
{
if(start_bandb())
{
ilog(L_MAIN, "Unable to start bandb helper: %s", strerror(errno));
exit(0);
}
}
static int
start_bandb(void)
{
char fullpath[PATH_MAX + 1];
#ifdef _WIN32
const char *suffix = ".exe";
#else
const char *suffix = "";
#endif
rb_setenv("BANDB_DBPATH", PKGLOCALSTATEDIR "/ban.db", 1);
if(bandb_path == NULL)
{
rb_snprintf(fullpath, sizeof(fullpath), "%s/bandb%s", PKGLIBEXECDIR, suffix);
if(access(fullpath, X_OK) == -1)
{
rb_snprintf(fullpath, sizeof(fullpath), "%s/bin/bandb%s",
ConfigFileEntry.dpath, suffix);
if(access(fullpath, X_OK) == -1)
{
ilog(L_MAIN,
"Unable to execute bandb%s in %s or %s/bin",
suffix, PKGLIBEXECDIR, ConfigFileEntry.dpath);
return 0;
}
}
bandb_path = rb_strdup(fullpath);
}
bandb_helper = rb_helper_start("bandb", bandb_path, bandb_parse, bandb_restart_cb);
if(bandb_helper == NULL)
{
ilog(L_MAIN, "Unable to start bandb: %s", strerror(errno));
sendto_realops_snomask(SNO_GENERAL, L_ALL, "Unable to start bandb: %s",
strerror(errno));
return 1;
}
rb_helper_run(bandb_helper);
return 0;
}
void
bandb_add(bandb_type type, struct Client *source_p, const char *mask1,
const char *mask2, const char *reason, const char *oper_reason, int perm)
{
if(bandb_helper == NULL)
return;
static char buf[BUFSIZE];
rb_snprintf(buf, sizeof(buf), "%c %s ", bandb_add_letter[type], mask1);
if(!EmptyString(mask2))
rb_snprintf_append(buf, sizeof(buf), "%s ", mask2);
rb_snprintf_append(buf, sizeof(buf), "%s %ld %d :%s",
get_oper_name(source_p), (long int)rb_current_time(), perm, reason);
if(!EmptyString(oper_reason))
rb_snprintf_append(buf, sizeof(buf), "|%s", oper_reason);
rb_helper_write(bandb_helper, "%s", buf);
}
static char bandb_del_letter[LAST_BANDB_TYPE] = {
'k', 'd', 'x', 'r'
};
void
bandb_del(bandb_type type, const char *mask1, const char *mask2)
{
if(bandb_helper == NULL)
return;
static char buf[BUFSIZE];
buf[0] = '\0';
rb_snprintf_append(buf, sizeof(buf), "%c %s", bandb_del_letter[type], mask1);
if(!EmptyString(mask2))
rb_snprintf_append(buf, sizeof(buf), " %s", mask2);
rb_helper_write(bandb_helper, "%s", buf);
}
static void
bandb_handle_ban(char *parv[], int parc)
{
struct ConfItem *aconf;
char *p;
int para = 1;
aconf = make_conf();
aconf->port = 0;
if(parv[0][0] == 'K')
aconf->user = rb_strdup(parv[para++]);
aconf->host = rb_strdup(parv[para++]);
aconf->info.oper = operhash_add(parv[para++]);
switch (parv[0][0])
{
case 'K':
aconf->status = CONF_KILL;
break;
case 'D':
aconf->status = CONF_DLINE;
break;
case 'X':
aconf->status = CONF_XLINE;
break;
case 'R':
if(IsChannelName(aconf->host))
aconf->status = CONF_RESV_CHANNEL;
else
aconf->status = CONF_RESV_NICK;
break;
}
if((p = strchr(parv[para], '|')))
{
*p++ = '\0';
aconf->spasswd = rb_strdup(p);
}
aconf->passwd = rb_strdup(parv[para]);
rb_dlinkAddAlloc(aconf, &bandb_pending);
}
static int
bandb_check_kline(struct ConfItem *aconf)
{
struct rb_sockaddr_storage daddr;
struct ConfItem *kconf = NULL;
int aftype;
const char *p;
aftype = parse_netmask(aconf->host, &daddr, NULL);
if(aftype != HM_HOST)
{
#ifdef RB_IPV6
if(aftype == HM_IPV6)
aftype = AF_INET6;
else
#endif
aftype = AF_INET;
kconf = find_conf_by_address(aconf->host, NULL, NULL, (struct sockaddr *)&daddr,
CONF_KILL, aftype, aconf->user, NULL);
}
else
kconf = find_conf_by_address(aconf->host, NULL, NULL, NULL, CONF_KILL, 0, aconf->user, NULL);
if(kconf && ((kconf->flags & CONF_FLAGS_TEMPORARY) == 0))
return 0;
for(p = aconf->user; *p; p++)
{
if(!IsUserChar(*p) && !IsKWildChar(*p))
return 0;
}
for(p = aconf->host; *p; p++)
{
if(!IsHostChar(*p) && !IsKWildChar(*p))
return 0;
}
return 1;
}
static int
bandb_check_dline(struct ConfItem *aconf)
{
struct rb_sockaddr_storage daddr;
int bits;
if(!parse_netmask(aconf->host, &daddr, &bits))
return 0;
return 1;
}
static int
bandb_check_xline(struct ConfItem *aconf)
{
struct ConfItem *xconf;
/* XXX perhaps convert spaces to \s? -- jilles */
xconf = find_xline_mask(aconf->host);
if(xconf != NULL && !(xconf->flags & CONF_FLAGS_TEMPORARY))
return 0;
return 1;
}
static int
bandb_check_resv_channel(struct ConfItem *aconf)
{
const char *p;
if(hash_find_resv(aconf->host) || strlen(aconf->host) > CHANNELLEN)
return 0;
for(p = aconf->host; *p; p++)
{
if(!IsChanChar(*p))
return 0;
}
return 1;
}
static int
bandb_check_resv_nick(struct ConfItem *aconf)
{
if(!clean_resv_nick(aconf->host))
return 0;
if(find_nick_resv(aconf->host))
return 0;
return 1;
}
static void
bandb_handle_clear(void)
{
rb_dlink_node *ptr, *next_ptr;
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
{
free_conf(ptr->data);
rb_dlinkDestroy(ptr, &bandb_pending);
}
}
static void
bandb_handle_finish(void)
{
struct ConfItem *aconf;
rb_dlink_node *ptr, *next_ptr;
clear_out_address_conf_bans();
clear_s_newconf_bans();
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
{
aconf = ptr->data;
rb_dlinkDestroy(ptr, &bandb_pending);
switch (aconf->status)
{
case CONF_KILL:
if(bandb_check_kline(aconf))
add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
else
free_conf(aconf);
break;
case CONF_DLINE:
if(bandb_check_dline(aconf))
add_conf_by_address(aconf->host, CONF_DLINE, aconf->user, NULL, aconf);
else
free_conf(aconf);
break;
case CONF_XLINE:
if(bandb_check_xline(aconf))
rb_dlinkAddAlloc(aconf, &xline_conf_list);
else
free_conf(aconf);
break;
case CONF_RESV_CHANNEL:
if(bandb_check_resv_channel(aconf))
add_to_resv_hash(aconf->host, aconf);
else
free_conf(aconf);
break;
case CONF_RESV_NICK:
if(bandb_check_resv_nick(aconf))
rb_dlinkAddAlloc(aconf, &resv_conf_list);
else
free_conf(aconf);
break;
}
}
check_banned_lines();
}
static void __attribute__((noreturn))
bandb_handle_failure(rb_helper *helper, char **parv, int parc)
{
if(server_state_foreground)
fprintf(stderr, "bandb - bandb failure: %s\n", parv[1]);
ilog(L_MAIN, "bandb - bandb failure: %s", parv[1]);
sendto_realops_snomask(SNO_GENERAL, L_ALL, "bandb - bandb failure: %s", parv[1]);
exit(1);
}
static void
bandb_parse(rb_helper *helper)
{
static char buf[READBUF_SIZE];
char *parv[MAXPARA + 1];
int len, parc;
while((len = rb_helper_read(helper, buf, sizeof(buf))))
{
parc = rb_string_to_array(buf, parv, MAXPARA);
if(parc < 1)
continue;
switch (parv[0][0])
{
case '!':
bandb_handle_failure(helper, parv, parc);
/* UNREACHABLE */
case 'K':
case 'D':
case 'X':
case 'R':
bandb_handle_ban(parv, parc);
break;
case 'C':
bandb_handle_clear();
break;
case 'F':
bandb_handle_finish();
break;
}
}
}
void
bandb_rehash_bans(void)
{
if(bandb_helper != NULL)
rb_helper_write(bandb_helper, "L");
}
static void
bandb_restart_cb(rb_helper *helper)
{
ilog(L_MAIN, "bandb - bandb_restart_cb called, bandb helper died?");
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"bandb - bandb_restart_cb called, bandb helper died?");
if(helper != NULL)
{
rb_helper_close(helper);
bandb_helper = NULL;
}
start_bandb();
return;
}

396
src/cache.c Normal file
View file

@ -0,0 +1,396 @@
/*
* ircd-ratbox: an advanced Internet Relay Chat Daemon(ircd).
* cache.c - code for caching files
*
* Copyright (C) 2003 Lee Hardy <lee@leeh.co.uk>
* Copyright (C) 2003-2005 ircd-ratbox 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.
*
* $Id: cache.c 25119 2008-03-13 16:57:05Z androsyn $
*/
#include "stdinc.h"
#include "ircd_defs.h"
#include "common.h"
#include "s_conf.h"
#include "client.h"
#include "hash.h"
#include "cache.h"
#include "irc_dictionary.h"
#include "numeric.h"
#include "send.h"
struct cachefile *user_motd = NULL;
struct cachefile *oper_motd = NULL;
struct cacheline *emptyline = NULL;
rb_dlink_list links_cache_list;
char user_motd_changed[MAX_DATE_STRING];
struct Dictionary *help_dict_oper = NULL;
struct Dictionary *help_dict_user = NULL;
/* init_cache()
*
* inputs -
* outputs -
* side effects - inits the file/line cache blockheaps, loads motds
*/
void
init_cache(void)
{
/* allocate the emptyline */
emptyline = rb_malloc(sizeof(struct cacheline));
emptyline->data = rb_strdup(" ");
user_motd_changed[0] = '\0';
user_motd = cache_file(MPATH, "ircd.motd", 0);
oper_motd = cache_file(OPATH, "opers.motd", 0);
memset(&links_cache_list, 0, sizeof(links_cache_list));
help_dict_oper = irc_dictionary_create(strcasecmp);
help_dict_user = irc_dictionary_create(strcasecmp);
}
/*
* removes tabs from src, replaces with 8 spaces, and returns the length
* of the new string. if the new string would be greater than destlen,
* it is truncated to destlen - 1
*/
static size_t
untabify(char *dest, const char *src, size_t destlen)
{
size_t x = 0, i;
const char *s = src;
char *d = dest;
while(*s != '\0' && x < destlen - 1)
{
if(*s == '\t')
{
for(i = 0; i < 8 && x < destlen - 1; i++, x++, d++)
*d = ' ';
s++;
} else
{
*d++ = *s++;
x++;
}
}
*d = '\0';
return x;
}
/* cache_file()
*
* inputs - file to cache, files "shortname", flags to set
* outputs - pointer to file cached, else NULL
* side effects -
*/
struct cachefile *
cache_file(const char *filename, const char *shortname, int flags)
{
FILE *in;
struct cachefile *cacheptr;
struct cacheline *lineptr;
char line[BUFSIZE];
char *p;
if((in = fopen(filename, "r")) == NULL)
return NULL;
cacheptr = rb_malloc(sizeof(struct cachefile));
rb_strlcpy(cacheptr->name, shortname, sizeof(cacheptr->name));
cacheptr->flags = flags;
/* cache the file... */
while(fgets(line, sizeof(line), in) != NULL)
{
if((p = strpbrk(line, "\r\n")) != NULL)
*p = '\0';
if(!EmptyString(line))
{
char untabline[BUFSIZE];
lineptr = rb_malloc(sizeof(struct cacheline));
untabify(untabline, line, sizeof(untabline));
lineptr->data = rb_strdup(untabline);
rb_dlinkAddTail(lineptr, &lineptr->linenode, &cacheptr->contents);
}
else
rb_dlinkAddTailAlloc(emptyline, &cacheptr->contents);
}
if (0 == rb_dlink_list_length(&cacheptr->contents))
{
/* No contents. Don't cache it after all. */
rb_free(cacheptr);
cacheptr = NULL;
}
fclose(in);
return cacheptr;
}
void
cache_links(void *unused)
{
struct Client *target_p;
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
char *links_line;
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, links_cache_list.head)
{
rb_free(ptr->data);
rb_free_rb_dlink_node(ptr);
}
links_cache_list.head = links_cache_list.tail = NULL;
links_cache_list.length = 0;
RB_DLINK_FOREACH(ptr, global_serv_list.head)
{
target_p = ptr->data;
/* skip ourselves (done in /links) and hidden servers */
if(IsMe(target_p) ||
(IsHidden(target_p) && !ConfigServerHide.disable_hidden))
continue;
/* if the below is ever modified, change LINKSLINELEN */
links_line = rb_malloc(LINKSLINELEN);
rb_snprintf(links_line, LINKSLINELEN, "%s %s :1 %s",
target_p->name, me.name,
target_p->info[0] ? target_p->info :
"(Unknown Location)");
rb_dlinkAddTailAlloc(links_line, &links_cache_list);
}
}
/* free_cachefile()
*
* inputs - cachefile to free
* outputs -
* side effects - cachefile and its data is free'd
*/
void
free_cachefile(struct cachefile *cacheptr)
{
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
if(cacheptr == NULL)
return;
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, cacheptr->contents.head)
{
if(ptr->data != emptyline)
{
struct cacheline *line = ptr->data;
rb_free(line->data);
rb_free(line);
}
else
{
rb_free_rb_dlink_node(ptr);
}
}
rb_free(cacheptr);
}
/* load_help()
*
* inputs -
* outputs -
* side effects - old help cache deleted
* - contents of help directories are loaded.
*/
void
load_help(void)
{
DIR *helpfile_dir = NULL;
struct dirent *ldirent= NULL;
char filename[PATH_MAX];
struct cachefile *cacheptr;
struct DictionaryIter iter;
#if defined(S_ISLNK) && defined(HAVE_LSTAT)
struct stat sb;
#endif
DICTIONARY_FOREACH(cacheptr, &iter, help_dict_oper)
{
irc_dictionary_delete(help_dict_oper, cacheptr->name);
free_cachefile(cacheptr);
}
DICTIONARY_FOREACH(cacheptr, &iter, help_dict_user)
{
irc_dictionary_delete(help_dict_user, cacheptr->name);
free_cachefile(cacheptr);
}
helpfile_dir = opendir(HPATH);
if(helpfile_dir == NULL)
return;
while((ldirent = readdir(helpfile_dir)) != NULL)
{
if(ldirent->d_name[0] == '.')
continue;
rb_snprintf(filename, sizeof(filename), "%s/%s", HPATH, ldirent->d_name);
cacheptr = cache_file(filename, ldirent->d_name, HELP_OPER);
irc_dictionary_add(help_dict_oper, cacheptr->name, cacheptr);
}
closedir(helpfile_dir);
helpfile_dir = opendir(UHPATH);
if(helpfile_dir == NULL)
return;
while((ldirent = readdir(helpfile_dir)) != NULL)
{
if(ldirent->d_name[0] == '.')
continue;
rb_snprintf(filename, sizeof(filename), "%s/%s", UHPATH, ldirent->d_name);
#if defined(S_ISLNK) && defined(HAVE_LSTAT)
if(lstat(filename, &sb) < 0)
continue;
/* ok, if its a symlink, we work on the presumption if an
* oper help exists of that name, its a symlink to that --fl
*/
if(S_ISLNK(sb.st_mode))
{
cacheptr = irc_dictionary_retrieve(help_dict_oper, ldirent->d_name);
if(cacheptr != NULL)
{
cacheptr->flags |= HELP_USER;
continue;
}
}
#endif
cacheptr = cache_file(filename, ldirent->d_name, HELP_USER);
irc_dictionary_add(help_dict_user, cacheptr->name, cacheptr);
}
closedir(helpfile_dir);
}
/* send_user_motd()
*
* inputs - client to send motd to
* outputs - client is sent motd if exists, else ERR_NOMOTD
* side effects -
*/
void
send_user_motd(struct Client *source_p)
{
struct cacheline *lineptr;
rb_dlink_node *ptr;
const char *myname = get_id(&me, source_p);
const char *nick = get_id(source_p, source_p);
if(user_motd == NULL || rb_dlink_list_length(&user_motd->contents) == 0)
{
sendto_one(source_p, form_str(ERR_NOMOTD), myname, nick);
return;
}
sendto_one(source_p, form_str(RPL_MOTDSTART), myname, nick, me.name);
RB_DLINK_FOREACH(ptr, user_motd->contents.head)
{
lineptr = ptr->data;
sendto_one(source_p, form_str(RPL_MOTD), myname, nick, lineptr->data);
}
sendto_one(source_p, form_str(RPL_ENDOFMOTD), myname, nick);
}
void
cache_user_motd(void)
{
struct stat sb;
struct tm *local_tm;
if(stat(MPATH, &sb) == 0)
{
local_tm = localtime(&sb.st_mtime);
if(local_tm != NULL)
{
rb_snprintf(user_motd_changed, sizeof(user_motd_changed),
"%d/%d/%d %d:%d",
local_tm->tm_mday, local_tm->tm_mon + 1,
1900 + local_tm->tm_year, local_tm->tm_hour,
local_tm->tm_min);
}
}
free_cachefile(user_motd);
user_motd = cache_file(MPATH, "ircd.motd", 0);
}
/* send_oper_motd()
*
* inputs - client to send motd to
* outputs - client is sent oper motd if exists
* side effects -
*/
void
send_oper_motd(struct Client *source_p)
{
struct cacheline *lineptr;
rb_dlink_node *ptr;
if(oper_motd == NULL || rb_dlink_list_length(&oper_motd->contents) == 0)
return;
sendto_one(source_p, form_str(RPL_OMOTDSTART),
me.name, source_p->name);
RB_DLINK_FOREACH(ptr, oper_motd->contents.head)
{
lineptr = ptr->data;
sendto_one(source_p, form_str(RPL_OMOTD),
me.name, source_p->name, lineptr->data);
}
sendto_one(source_p, form_str(RPL_ENDOFOMOTD),
me.name, source_p->name);
}

1406
src/channel.c Normal file

File diff suppressed because it is too large Load diff

1830
src/chmode.c Normal file

File diff suppressed because it is too large Load diff

2030
src/client.c Normal file

File diff suppressed because it is too large Load diff

142
src/getopt.c Normal file
View file

@ -0,0 +1,142 @@
/*
* ircd-ratbox: A slightly useful ircd.
* getopt.c: Uses getopt to fetch the command line options.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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
*
* $Id: getopt.c 6 2005-09-10 01:02:21Z nenolod $
*/
#include "stdinc.h"
#include "ircd_getopt.h"
# define OPTCHAR '-'
static void usage(char *name) __attribute__((noreturn));
void
parseargs(int *argc, char ***argv, struct lgetopt *opts)
{
int i;
char *progname = (*argv)[0];
/* loop through each argument */
for (;;)
{
int found = 0;
(*argc)--;
(*argv)++;
if(*argc < 1)
{
return;
}
/* check if it *is* an arg.. */
if((*argv)[0][0] != OPTCHAR)
{
return;
}
(*argv)[0]++;
/* search through our argument list, and see if it matches */
for (i = 0; opts[i].opt; i++)
{
if(!strcmp(opts[i].opt, (*argv)[0]))
{
/* found our argument */
found = 1;
switch (opts[i].argtype)
{
case YESNO:
*((int *) opts[i].argloc) = 1;
break;
case INTEGER:
if(*argc < 2)
{
fprintf(stderr,
"Error: option '%c%s' requires an argument\n",
OPTCHAR, opts[i].opt);
usage((*argv)[0]);
}
*((int *) opts[i].argloc) = atoi((*argv)[1]);
(*argc)--;
(*argv)++;
break;
case STRING:
if(*argc < 2)
{
fprintf(stderr,
"error: option '%c%s' requires an argument\n",
OPTCHAR, opts[i].opt);
usage(progname);
}
*((char **) opts[i].argloc) =
malloc(strlen((*argv)[1]) + 1);
strcpy(*((char **) opts[i].argloc), (*argv)[1]);
(*argc)--;
(*argv)++;
break;
case USAGE:
usage(progname);
/*NOTREACHED*/ default:
fprintf(stderr,
"Error: internal error in parseargs() at %s:%d\n",
__FILE__, __LINE__);
exit(EXIT_FAILURE);
}
}
}
if(!found)
{
fprintf(stderr, "error: unknown argument '%c%s'\n", OPTCHAR, (*argv)[0]);
usage(progname);
}
}
}
static void
usage(char *name)
{
int i = 0;
fprintf(stderr, "Usage: %s [options]\n", name);
fprintf(stderr, "Where valid options are:\n");
for (i = 0; myopts[i].opt; i++)
{
fprintf(stderr, "\t%c%-10s %-20s%s\n", OPTCHAR,
myopts[i].opt, (myopts[i].argtype == YESNO
|| myopts[i].argtype ==
USAGE) ? "" : myopts[i].argtype ==
INTEGER ? "<number>" : "<string>", myopts[i].desc);
}
exit(EXIT_FAILURE);
}

805
src/hash.c Normal file
View file

@ -0,0 +1,805 @@
/*
* ircd-ratbox: A slightly useful ircd.
* hash.c: Maintains hashtables.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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
*
* $Id: hash.c 3177 2007-02-01 00:19:14Z jilles $
*/
#include "stdinc.h"
#include "ircd_defs.h"
#include "s_conf.h"
#include "channel.h"
#include "client.h"
#include "common.h"
#include "hash.h"
#include "match.h"
#include "ircd.h"
#include "numeric.h"
#include "send.h"
#include "msg.h"
#include "cache.h"
#include "s_newconf.h"
#include "s_assert.h"
#define ZCONNID_MAX 64 /* i doubt we'll have this many ziplinks ;) */
#define hash_cli_connid(x) (x % CLI_CONNID_MAX)
#define hash_zconnid(x) (x % ZCONNID_MAX)
static rb_dlink_list clientbyconnidTable[CLI_CONNID_MAX];
static rb_dlink_list clientbyzconnidTable[ZCONNID_MAX];
rb_dlink_list *clientTable;
rb_dlink_list *channelTable;
rb_dlink_list *idTable;
rb_dlink_list *resvTable;
rb_dlink_list *hostTable;
/*
* look in whowas.c for the missing ...[WW_MAX]; entry
*/
/*
* Hashing.
*
* The server uses a chained hash table to provide quick and efficient
* hash table maintenance (providing the hash function works evenly over
* the input range). The hash table is thus not susceptible to problems
* of filling all the buckets or the need to rehash.
* It is expected that the hash table would look something like this
* during use:
* +-----+ +-----+ +-----+ +-----+
* ---| 224 |----| 225 |----| 226 |---| 227 |---
* +-----+ +-----+ +-----+ +-----+
* | | |
* +-----+ +-----+ +-----+
* | A | | C | | D |
* +-----+ +-----+ +-----+
* |
* +-----+
* | B |
* +-----+
*
* A - GOPbot, B - chang, C - hanuaway, D - *.mu.OZ.AU
*
* The order shown above is just one instant of the server.
*
*
* The hash functions currently used are based Fowler/Noll/Vo hashes
* which work amazingly well and have a extremely low collision rate
* For more info see http://www.isthe.com/chongo/tech/comp/fnv/index.html
*
*
*/
/* init_hash()
*
* clears the various hashtables
*/
void
init_hash(void)
{
clientTable = rb_malloc(sizeof(rb_dlink_list) * U_MAX);
idTable = rb_malloc(sizeof(rb_dlink_list) * U_MAX);
channelTable = rb_malloc(sizeof(rb_dlink_list) * CH_MAX);
hostTable = rb_malloc(sizeof(rb_dlink_list) * HOST_MAX);
resvTable = rb_malloc(sizeof(rb_dlink_list) * R_MAX);
}
#ifndef RICER_HASHING
u_int32_t
fnv_hash_upper(const unsigned char *s, int bits)
{
u_int32_t h = FNV1_32_INIT;
while (*s)
{
h ^= ToUpper(*s++);
h += (h<<1) + (h<<4) + (h<<7) + (h << 8) + (h << 24);
}
if (bits < 32)
h = ((h >> bits) ^ h) & ((1<<bits)-1);
return h;
}
u_int32_t
fnv_hash(const unsigned char *s, int bits)
{
u_int32_t h = FNV1_32_INIT;
while (*s)
{
h ^= *s++;
h += (h<<1) + (h<<4) + (h<<7) + (h << 8) + (h << 24);
}
if (bits < 32)
h = ((h >> bits) ^ h) & ((1<<bits)-1);
return h;
}
u_int32_t
fnv_hash_len(const unsigned char *s, int bits, int len)
{
u_int32_t h = FNV1_32_INIT;
const unsigned char *x = s + len;
while (*s && s < x)
{
h ^= *s++;
h += (h<<1) + (h<<4) + (h<<7) + (h << 8) + (h << 24);
}
if (bits < 32)
h = ((h >> bits) ^ h) & ((1<<bits)-1);
return h;
}
u_int32_t
fnv_hash_upper_len(const unsigned char *s, int bits, int len)
{
u_int32_t h = FNV1_32_INIT;
const unsigned char *x = s + len;
while (*s && s < x)
{
h ^= ToUpper(*s++);
h += (h<<1) + (h<<4) + (h<<7) + (h << 8) + (h << 24);
}
if (bits < 32)
h = ((h >> bits) ^ h) & ((1<<bits)-1);
return h;
}
#endif
/* hash_nick()
*
* hashes a nickname, first converting to lowercase
*/
static u_int32_t
hash_nick(const char *name)
{
return fnv_hash_upper((const unsigned char *) name, U_MAX_BITS);
}
/* hash_id()
*
* hashes an id, case is kept
*/
static u_int32_t
hash_id(const char *name)
{
return fnv_hash((const unsigned char *) name, U_MAX_BITS);
}
/* hash_channel()
*
* hashes a channel name, based on first 30 chars only for efficiency
*/
static u_int32_t
hash_channel(const char *name)
{
return fnv_hash_upper_len((const unsigned char *) name, CH_MAX_BITS, 30);
}
/* hash_hostname()
*
* hashes a hostname, based on first 30 chars only, as thats likely to
* be more dynamic than rest.
*/
static u_int32_t
hash_hostname(const char *name)
{
return fnv_hash_upper_len((const unsigned char *) name, HOST_MAX_BITS, 30);
}
/* hash_resv()
*
* hashes a resv channel name, based on first 30 chars only
*/
static u_int32_t
hash_resv(const char *name)
{
return fnv_hash_upper_len((const unsigned char *) name, R_MAX_BITS, 30);
}
/* add_to_id_hash()
*
* adds an entry to the id hash table
*/
void
add_to_id_hash(const char *name, struct Client *client_p)
{
unsigned int hashv;
if(EmptyString(name) || (client_p == NULL))
return;
hashv = hash_id(name);
rb_dlinkAddAlloc(client_p, &idTable[hashv]);
}
/* add_to_client_hash()
*
* adds an entry (client/server) to the client hash table
*/
void
add_to_client_hash(const char *name, struct Client *client_p)
{
unsigned int hashv;
s_assert(name != NULL);
s_assert(client_p != NULL);
if(EmptyString(name) || (client_p == NULL))
return;
hashv = hash_nick(name);
rb_dlinkAddAlloc(client_p, &clientTable[hashv]);
}
/* add_to_hostname_hash()
*
* adds a client entry to the hostname hash table
*/
void
add_to_hostname_hash(const char *hostname, struct Client *client_p)
{
unsigned int hashv;
s_assert(hostname != NULL);
s_assert(client_p != NULL);
if(EmptyString(hostname) || (client_p == NULL))
return;
hashv = hash_hostname(hostname);
rb_dlinkAddAlloc(client_p, &hostTable[hashv]);
}
/* add_to_resv_hash()
*
* adds a resv channel entry to the resv hash table
*/
void
add_to_resv_hash(const char *name, struct ConfItem *aconf)
{
unsigned int hashv;
s_assert(!EmptyString(name));
s_assert(aconf != NULL);
if(EmptyString(name) || aconf == NULL)
return;
hashv = hash_resv(name);
rb_dlinkAddAlloc(aconf, &resvTable[hashv]);
}
/* del_from_id_hash()
*
* removes an id from the id hash table
*/
void
del_from_id_hash(const char *id, struct Client *client_p)
{
unsigned int hashv;
s_assert(id != NULL);
s_assert(client_p != NULL);
if(EmptyString(id) || client_p == NULL)
return;
hashv = hash_id(id);
rb_dlinkFindDestroy(client_p, &idTable[hashv]);
}
/* del_from_client_hash()
*
* removes a client/server from the client hash table
*/
void
del_from_client_hash(const char *name, struct Client *client_p)
{
unsigned int hashv;
/* no s_asserts, this can happen when removing a client that
* is unregistered.
*/
if(EmptyString(name) || client_p == NULL)
return;
hashv = hash_nick(name);
rb_dlinkFindDestroy(client_p, &clientTable[hashv]);
}
/* del_from_channel_hash()
*
* removes a channel from the channel hash table
*/
void
del_from_channel_hash(const char *name, struct Channel *chptr)
{
unsigned int hashv;
s_assert(name != NULL);
s_assert(chptr != NULL);
if(EmptyString(name) || chptr == NULL)
return;
hashv = hash_channel(name);
rb_dlinkFindDestroy(chptr, &channelTable[hashv]);
}
/* del_from_hostname_hash()
*
* removes a client entry from the hostname hash table
*/
void
del_from_hostname_hash(const char *hostname, struct Client *client_p)
{
unsigned int hashv;
if(hostname == NULL || client_p == NULL)
return;
hashv = hash_hostname(hostname);
rb_dlinkFindDestroy(client_p, &hostTable[hashv]);
}
/* del_from_resv_hash()
*
* removes a resv entry from the resv hash table
*/
void
del_from_resv_hash(const char *name, struct ConfItem *aconf)
{
unsigned int hashv;
s_assert(name != NULL);
s_assert(aconf != NULL);
if(EmptyString(name) || aconf == NULL)
return;
hashv = hash_resv(name);
rb_dlinkFindDestroy(aconf, &resvTable[hashv]);
}
/* find_id()
*
* finds a client entry from the id hash table
*/
struct Client *
find_id(const char *name)
{
struct Client *target_p;
rb_dlink_node *ptr;
unsigned int hashv;
if(EmptyString(name))
return NULL;
hashv = hash_id(name);
RB_DLINK_FOREACH(ptr, idTable[hashv].head)
{
target_p = ptr->data;
if(strcmp(name, target_p->id) == 0)
return target_p;
}
return NULL;
}
/* find_client()
*
* finds a client/server entry from the client hash table
*/
struct Client *
find_client(const char *name)
{
struct Client *target_p;
rb_dlink_node *ptr;
unsigned int hashv;
s_assert(name != NULL);
if(EmptyString(name))
return NULL;
/* hunting for an id, not a nick */
if(IsDigit(*name))
return (find_id(name));
hashv = hash_nick(name);
RB_DLINK_FOREACH(ptr, clientTable[hashv].head)
{
target_p = ptr->data;
if(irccmp(name, target_p->name) == 0)
return target_p;
}
return NULL;
}
/* find_named_client()
*
* finds a client/server entry from the client hash table
*/
struct Client *
find_named_client(const char *name)
{
struct Client *target_p;
rb_dlink_node *ptr;
unsigned int hashv;
s_assert(name != NULL);
if(EmptyString(name))
return NULL;
hashv = hash_nick(name);
RB_DLINK_FOREACH(ptr, clientTable[hashv].head)
{
target_p = ptr->data;
if(irccmp(name, target_p->name) == 0)
return target_p;
}
return NULL;
}
/* find_server()
*
* finds a server from the client hash table
*/
struct Client *
find_server(struct Client *source_p, const char *name)
{
struct Client *target_p;
rb_dlink_node *ptr;
unsigned int hashv;
if(EmptyString(name))
return NULL;
if((source_p == NULL || !MyClient(source_p)) &&
IsDigit(*name) && strlen(name) == 3)
{
target_p = find_id(name);
return(target_p);
}
hashv = hash_nick(name);
RB_DLINK_FOREACH(ptr, clientTable[hashv].head)
{
target_p = ptr->data;
if((IsServer(target_p) || IsMe(target_p)) &&
irccmp(name, target_p->name) == 0)
return target_p;
}
return NULL;
}
/* find_hostname()
*
* finds a hostname rb_dlink list from the hostname hash table.
* we return the full rb_dlink list, because you can have multiple
* entries with the same hostname
*/
rb_dlink_node *
find_hostname(const char *hostname)
{
unsigned int hashv;
if(EmptyString(hostname))
return NULL;
hashv = hash_hostname(hostname);
return hostTable[hashv].head;
}
/* find_channel()
*
* finds a channel from the channel hash table
*/
struct Channel *
find_channel(const char *name)
{
struct Channel *chptr;
rb_dlink_node *ptr;
unsigned int hashv;
s_assert(name != NULL);
if(EmptyString(name))
return NULL;
hashv = hash_channel(name);
RB_DLINK_FOREACH(ptr, channelTable[hashv].head)
{
chptr = ptr->data;
if(irccmp(name, chptr->chname) == 0)
return chptr;
}
return NULL;
}
/*
* get_or_create_channel
* inputs - client pointer
* - channel name
* - pointer to int flag whether channel was newly created or not
* output - returns channel block or NULL if illegal name
* - also modifies *isnew
*
* Get Channel block for chname (and allocate a new channel
* block, if it didn't exist before).
*/
struct Channel *
get_or_create_channel(struct Client *client_p, const char *chname, int *isnew)
{
struct Channel *chptr;
rb_dlink_node *ptr;
unsigned int hashv;
int len;
const char *s = chname;
if(EmptyString(s))
return NULL;
len = strlen(s);
if(len > CHANNELLEN)
{
char *t;
if(IsServer(client_p))
{
sendto_realops_snomask(SNO_DEBUG, L_ALL,
"*** Long channel name from %s (%d > %d): %s",
client_p->name, len, CHANNELLEN, s);
}
len = CHANNELLEN;
t = LOCAL_COPY(s);
*(t + CHANNELLEN) = '\0';
s = t;
}
hashv = hash_channel(s);
RB_DLINK_FOREACH(ptr, channelTable[hashv].head)
{
chptr = ptr->data;
if(irccmp(s, chptr->chname) == 0)
{
if(isnew != NULL)
*isnew = 0;
return chptr;
}
}
if(isnew != NULL)
*isnew = 1;
chptr = allocate_channel(s);
rb_dlinkAdd(chptr, &chptr->node, &global_channel_list);
chptr->channelts = rb_current_time(); /* doesn't hurt to set it here */
rb_dlinkAddAlloc(chptr, &channelTable[hashv]);
return chptr;
}
/* hash_find_resv()
*
* hunts for a resv entry in the resv hash table
*/
struct ConfItem *
hash_find_resv(const char *name)
{
struct ConfItem *aconf;
rb_dlink_node *ptr;
unsigned int hashv;
s_assert(name != NULL);
if(EmptyString(name))
return NULL;
hashv = hash_resv(name);
RB_DLINK_FOREACH(ptr, resvTable[hashv].head)
{
aconf = ptr->data;
if(!irccmp(name, aconf->host))
{
aconf->port++;
return aconf;
}
}
return NULL;
}
void
clear_resv_hash(void)
{
struct ConfItem *aconf;
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
int i;
HASH_WALK_SAFE(i, R_MAX, ptr, next_ptr, resvTable)
{
aconf = ptr->data;
/* skip temp resvs */
if(aconf->hold)
continue;
free_conf(ptr->data);
rb_dlinkDestroy(ptr, &resvTable[i]);
}
HASH_WALK_END
}
void
add_to_zconnid_hash(struct Client *client_p)
{
unsigned int hashv;
hashv = hash_zconnid(client_p->localClient->zconnid);
rb_dlinkAddAlloc(client_p, &clientbyzconnidTable[hashv]);
}
void
del_from_zconnid_hash(struct Client *client_p)
{
unsigned int hashv;
hashv = hash_zconnid(client_p->localClient->zconnid);
rb_dlinkFindDestroy(client_p, &clientbyzconnidTable[hashv]);
}
void
add_to_cli_connid_hash(struct Client *client_p)
{
unsigned int hashv;
hashv = hash_cli_connid(client_p->localClient->connid);
rb_dlinkAddAlloc(client_p, &clientbyconnidTable[hashv]);
}
void
del_from_cli_connid_hash(struct Client *client_p)
{
unsigned int hashv;
hashv = hash_cli_connid(client_p->localClient->connid);
rb_dlinkFindDestroy(client_p, &clientbyconnidTable[hashv]);
}
struct Client *
find_cli_connid_hash(int connid)
{
struct Client *target_p;
rb_dlink_node *ptr;
unsigned int hashv;
hashv = hash_cli_connid(connid);
RB_DLINK_FOREACH(ptr, clientbyconnidTable[hashv].head)
{
target_p = ptr->data;
if(target_p->localClient->connid == (uint32_t)connid)
return target_p;
}
hashv = hash_zconnid(connid);
RB_DLINK_FOREACH(ptr, clientbyzconnidTable[hashv].head)
{
target_p = ptr->data;
if(target_p->localClient->zconnid == (uint32_t)connid)
return target_p;
}
return NULL;
}
static void
output_hash(struct Client *source_p, const char *name, int length, int *counts, unsigned long deepest)
{
unsigned long total = 0;
int i;
char buf[128];
sendto_one_numeric(source_p, RPL_STATSDEBUG,
"B :%s Hash Statistics", name);
snprintf(buf, sizeof buf, "%.3f%%",
(float) ((counts[0]*100) / (float) length));
sendto_one_numeric(source_p, RPL_STATSDEBUG,
"B :Size: %d Empty: %d (%s)",
length, counts[0], buf);
for(i = 1; i < 11; i++)
{
total += (counts[i] * i);
}
/* dont want to divide by 0! --fl */
if(counts[0] != length)
{
snprintf(buf, sizeof buf, "%.3f/%.3f",
(float) (total / (length - counts[0])),
(float) (total / length));
sendto_one_numeric(source_p, RPL_STATSDEBUG,
"B :Average depth: %s Highest depth: %lu",
buf, deepest);
}
for(i = 0; i < 11; i++)
{
sendto_one_numeric(source_p, RPL_STATSDEBUG,
"B :Nodes with %d entries: %d",
i, counts[i]);
}
}
static void
count_hash(struct Client *source_p, rb_dlink_list *table, int length, const char *name)
{
int counts[11];
unsigned long deepest = 0;
int i;
memset(counts, 0, sizeof(counts));
for(i = 0; i < length; i++)
{
if(rb_dlink_list_length(&table[i]) >= 10)
counts[10]++;
else
counts[rb_dlink_list_length(&table[i])]++;
if(rb_dlink_list_length(&table[i]) > deepest)
deepest = rb_dlink_list_length(&table[i]);
}
output_hash(source_p, name, length, counts, deepest);
}
void
hash_stats(struct Client *source_p)
{
count_hash(source_p, channelTable, CH_MAX, "Channel");
sendto_one_numeric(source_p, RPL_STATSDEBUG, "B :--");
count_hash(source_p, clientTable, U_MAX, "Client");
sendto_one_numeric(source_p, RPL_STATSDEBUG, "B :--");
count_hash(source_p, idTable, U_MAX, "ID");
sendto_one_numeric(source_p, RPL_STATSDEBUG, "B :--");
count_hash(source_p, hostTable, HOST_MAX, "Hostname");
sendto_one_numeric(source_p, RPL_STATSDEBUG, "B :--");
count_hash(source_p, clientbyconnidTable, CLI_CONNID_MAX, "Client by connection id");
}

225
src/hook.c Normal file
View file

@ -0,0 +1,225 @@
/*
* ircd-ratbox: an advanced Internet Relay Chat Daemon(ircd).
* hook.c - code for dealing with the hook system
*
* This code is basically a slow leaking array. Events are simply just a
* position in this array. When hooks are added, events will be created if
* they dont exist - this means modules with hooks can be loaded in any
* order, and events are preserved through module reloads.
*
* Copyright (C) 2004-2005 Lee Hardy <lee -at- leeh.co.uk>
* Copyright (C) 2004-2005 ircd-ratbox 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.
*
* $Id: hook.c 712 2006-02-06 04:42:14Z gxti $
*/
#include "stdinc.h"
#include "hook.h"
#include "match.h"
hook *hooks;
#define HOOK_INCREMENT 1000
int num_hooks = 0;
int last_hook = 0;
int max_hooks = HOOK_INCREMENT;
#ifdef USE_IODEBUG_HOOKS
int h_iosend_id;
int h_iorecv_id;
int h_iorecvctrl_id;
#endif
int h_burst_client;
int h_burst_channel;
int h_burst_finished;
int h_server_introduced;
int h_server_eob;
int h_client_exit;
int h_after_client_exit;
int h_umode_changed;
int h_new_local_user;
int h_new_remote_user;
int h_introduce_client;
int h_can_kick;
int h_privmsg_user;
int h_privmsg_channel;
int h_conf_read_start;
int h_conf_read_end;
void
init_hook(void)
{
hooks = rb_malloc(sizeof(hook) * HOOK_INCREMENT);
#ifdef USE_IODEBUG_HOOKS
h_iosend_id = register_hook("iosend");
h_iorecv_id = register_hook("iorecv");
h_iorecvctrl_id = register_hook("iorecvctrl");
#endif
h_burst_client = register_hook("burst_client");
h_burst_channel = register_hook("burst_channel");
h_burst_finished = register_hook("burst_finished");
h_server_introduced = register_hook("server_introduced");
h_server_eob = register_hook("server_eob");
h_client_exit = register_hook("client_exit");
h_after_client_exit = register_hook("after_client_exit");
h_umode_changed = register_hook("umode_changed");
h_new_local_user = register_hook("new_local_user");
h_new_remote_user = register_hook("new_remote_user");
h_introduce_client = register_hook("introduce_client");
h_can_kick = register_hook("can_kick");
h_privmsg_user = register_hook("privmsg_user");
h_privmsg_channel = register_hook("privmsg_channel");
h_conf_read_start = register_hook("conf_read_start");
h_conf_read_end = register_hook("conf_read_end");
}
/* grow_hooktable()
* Enlarges the hook table by HOOK_INCREMENT
*/
static void
grow_hooktable(void)
{
hook *newhooks;
newhooks = rb_malloc(sizeof(hook) * (max_hooks + HOOK_INCREMENT));
memcpy(newhooks, hooks, sizeof(hook) * num_hooks);
rb_free(hooks);
hooks = newhooks;
max_hooks += HOOK_INCREMENT;
}
/* find_freehookslot()
* Finds the next free slot in the hook table, given by an entry with
* h->name being NULL.
*/
static int
find_freehookslot(void)
{
int i;
if((num_hooks + 1) > max_hooks)
grow_hooktable();
for(i = 0; i < max_hooks; i++)
{
if(!hooks[i].name)
return i;
}
/* shouldnt ever get here */
return(max_hooks - 1);
}
/* find_hook()
* Finds an event in the hook table.
*/
static int
find_hook(const char *name)
{
int i;
for(i = 0; i < max_hooks; i++)
{
if(!hooks[i].name)
continue;
if(!irccmp(hooks[i].name, name))
return i;
}
return -1;
}
/* register_hook()
* Finds an events position in the hook table, creating it if it doesnt
* exist.
*/
int
register_hook(const char *name)
{
int i;
if((i = find_hook(name)) < 0)
{
i = find_freehookslot();
hooks[i].name = rb_strdup(name);
num_hooks++;
}
return i;
}
/* add_hook()
* Adds a hook to an event in the hook table, creating event first if
* needed.
*/
void
add_hook(const char *name, hookfn fn)
{
int i;
i = register_hook(name);
rb_dlinkAddAlloc(fn, &hooks[i].hooks);
}
/* remove_hook()
* Removes a hook from an event in the hook table.
*/
void
remove_hook(const char *name, hookfn fn)
{
int i;
if((i = find_hook(name)) < 0)
return;
rb_dlinkFindDestroy(fn, &hooks[i].hooks);
}
/* call_hook()
* Calls functions from a given event in the hook table.
*/
void
call_hook(int id, void *arg)
{
hookfn fn;
rb_dlink_node *ptr;
/* The ID we were passed is the position in the hook table of this
* hook
*/
RB_DLINK_FOREACH(ptr, hooks[id].hooks.head)
{
fn = ptr->data;
fn(arg);
}
}

774
src/hostmask.c Normal file
View file

@ -0,0 +1,774 @@
/*
* charybdis: an advanced internet relay chat daemon (ircd).
* hostmask.c: Code to efficiently find IP & hostmask based configs.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
* Copyright (C) 2005-2008 charybdis development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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
*
* $Id: hostmask.c 2757 2006-11-10 22:58:15Z jilles $
*/
#include "stdinc.h"
#include "ircd_defs.h"
#include "s_conf.h"
#include "hostmask.h"
#include "numeric.h"
#include "send.h"
#include "match.h"
#include "ipv4_from_ipv6.h"
#ifdef RB_IPV6
static unsigned long hash_ipv6(struct sockaddr *, int);
#endif
static unsigned long hash_ipv4(struct sockaddr *, int);
/* int parse_netmask(const char *, struct rb_sockaddr_storage *, int *);
* Input: A hostmask, or an IPV4/6 address.
* Output: An integer describing whether it is an IPV4, IPV6 address or a
* hostmask, an address(if it is an IP mask),
* a bitlength(if it is IP mask).
* Side effects: None
*/
int
parse_netmask(const char *text, struct rb_sockaddr_storage *naddr, int *nb)
{
char *ip = LOCAL_COPY(text);
char *ptr;
struct rb_sockaddr_storage *addr, xaddr;
int *b, xb;
if(nb == NULL)
b = &xb;
else
b = nb;
if(naddr == NULL)
addr = &xaddr;
else
addr = naddr;
if(strpbrk(ip, "*?") != NULL)
{
return HM_HOST;
}
#ifdef RB_IPV6
if(strchr(ip, ':'))
{
if((ptr = strchr(ip, '/')))
{
*ptr = '\0';
ptr++;
*b = atoi(ptr);
if(*b > 128)
*b = 128;
else if(*b < 0)
return HM_HOST;
} else
*b = 128;
if(rb_inet_pton_sock(ip, (struct sockaddr *)addr) > 0)
return HM_IPV6;
else
return HM_HOST;
} else
#endif
if(strchr(text, '.'))
{
if((ptr = strchr(ip, '/')))
{
*ptr = '\0';
ptr++;
*b = atoi(ptr);
if(*b > 32)
*b = 32;
else if(*b < 0)
return HM_HOST;
} else
*b = 32;
if(rb_inet_pton_sock(ip, (struct sockaddr *)addr) > 0)
return HM_IPV4;
else
return HM_HOST;
}
return HM_HOST;
}
/* Hashtable stuff...now external as its used in m_stats.c */
struct AddressRec *atable[ATABLE_SIZE];
void
init_host_hash(void)
{
memset(&atable, 0, sizeof(atable));
}
/* unsigned long hash_ipv4(struct rb_sockaddr_storage*)
* Input: An IP address.
* Output: A hash value of the IP address.
* Side effects: None
*/
static unsigned long
hash_ipv4(struct sockaddr *saddr, int bits)
{
struct sockaddr_in *addr = (struct sockaddr_in *)(void *)saddr;
if(bits != 0)
{
unsigned long av = ntohl(addr->sin_addr.s_addr) & ~((1 << (32 - bits)) - 1);
return (av ^ (av >> 12) ^ (av >> 24)) & (ATABLE_SIZE - 1);
}
return 0;
}
/* unsigned long hash_ipv6(struct rb_sockaddr_storage*)
* Input: An IP address.
* Output: A hash value of the IP address.
* Side effects: None
*/
#ifdef RB_IPV6
static unsigned long
hash_ipv6(struct sockaddr *saddr, int bits)
{
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)(void *)saddr;
unsigned long v = 0, n;
for (n = 0; n < 16; n++)
{
if(bits >= 8)
{
v ^= addr->sin6_addr.s6_addr[n];
bits -= 8;
}
else if(bits)
{
v ^= addr->sin6_addr.s6_addr[n] & ~((1 << (8 - bits)) - 1);
return v & (ATABLE_SIZE - 1);
}
else
return v & (ATABLE_SIZE - 1);
}
return v & (ATABLE_SIZE - 1);
}
#endif
/* int hash_text(const char *start)
* Input: The start of the text to hash.
* Output: The hash of the string between 1 and (TH_MAX-1)
* Side-effects: None.
*/
static int
hash_text(const char *start)
{
const char *p = start;
unsigned long h = 0;
while(*p)
{
h = (h << 4) - (h + (unsigned char) ToLower(*p++));
}
return (h & (ATABLE_SIZE - 1));
}
/* unsigned long get_hash_mask(const char *)
* Input: The text to hash.
* Output: The hash of the string right of the first '.' past the last
* wildcard in the string.
* Side-effects: None.
*/
static unsigned long
get_mask_hash(const char *text)
{
const char *hp = "", *p;
for (p = text + strlen(text) - 1; p >= text; p--)
if(*p == '*' || *p == '?')
return hash_text(hp);
else if(*p == '.')
hp = p + 1;
return hash_text(text);
}
/* struct ConfItem* find_conf_by_address(const char*, struct rb_sockaddr_storage*,
* int type, int fam, const char *username)
* Input: The hostname, the address, the type of mask to find, the address
* family, the username.
* Output: The matching value with the highest precedence.
* Side-effects: None
* Note: Setting bit 0 of the type means that the username is ignored.
*/
struct ConfItem *
find_conf_by_address(const char *name, const char *sockhost,
const char *orighost,
struct sockaddr *addr, int type, int fam,
const char *username, const char *auth_user)
{
unsigned long hprecv = 0;
struct ConfItem *hprec = NULL;
struct AddressRec *arec;
int b;
if(username == NULL)
username = "";
if(addr)
{
/* Check for IPV6 matches... */
#ifdef RB_IPV6
if(fam == AF_INET6)
{
for (b = 128; b >= 0; b -= 16)
{
for (arec = atable[hash_ipv6(addr, b)]; arec; arec = arec->next)
if(arec->type == (type & ~0x1) &&
arec->masktype == HM_IPV6 &&
comp_with_mask_sock(addr, (struct sockaddr *)&arec->Mask.ipa.addr,
arec->Mask.ipa.bits) &&
(type & 0x1 || match(arec-> username, username)) &&
(type != CONF_CLIENT || !arec->auth_user ||
(auth_user && match(arec->auth_user, auth_user))) &&
arec->precedence > hprecv)
{
hprecv = arec->precedence;
hprec = arec->aconf;
}
}
}
else
#endif
if(fam == AF_INET)
{
for (b = 32; b >= 0; b -= 8)
{
for (arec = atable[hash_ipv4(addr, b)]; arec; arec = arec->next)
if(arec->type == (type & ~0x1) &&
arec->masktype == HM_IPV4 &&
comp_with_mask_sock(addr, (struct sockaddr *)&arec->Mask.ipa.addr,
arec->Mask.ipa.bits) &&
(type & 0x1 || match(arec->username, username)) &&
(type != CONF_CLIENT || !arec->auth_user ||
(auth_user && match(arec->auth_user, auth_user))) &&
arec->precedence > hprecv)
{
hprecv = arec->precedence;
hprec = arec->aconf;
}
}
}
}
if(orighost != NULL)
{
const char *p;
for (p = orighost; p != NULL;)
{
for (arec = atable[hash_text(p)]; arec; arec = arec->next)
if((arec->type == (type & ~0x1)) &&
(arec->masktype == HM_HOST) &&
arec->precedence > hprecv &&
match(arec->Mask.hostname, orighost) &&
(type != CONF_CLIENT || !arec->auth_user ||
(auth_user && match(arec->auth_user, auth_user))) &&
(type & 0x1 || match(arec->username, username)))
{
hprecv = arec->precedence;
hprec = arec->aconf;
}
p = strchr(p, '.');
if(p != NULL)
p++;
else
break;
}
for (arec = atable[0]; arec; arec = arec->next)
{
if(arec->type == (type & ~0x1) &&
arec->masktype == HM_HOST &&
arec->precedence > hprecv &&
(match(arec->Mask.hostname, orighost) ||
(sockhost && match(arec->Mask.hostname, sockhost))) &&
(type != CONF_CLIENT || !arec->auth_user ||
(auth_user && match(arec->auth_user, auth_user))) &&
(type & 0x1 || match(arec->username, username)))
{
hprecv = arec->precedence;
hprec = arec->aconf;
}
}
}
if(name != NULL)
{
const char *p;
/* And yes - we have to check p after strchr and p after increment for
* NULL -kre */
for (p = name; p != NULL;)
{
for (arec = atable[hash_text(p)]; arec; arec = arec->next)
if((arec->type == (type & ~0x1)) &&
(arec->masktype == HM_HOST) &&
arec->precedence > hprecv &&
match(arec->Mask.hostname, name) &&
(type != CONF_CLIENT || !arec->auth_user ||
(auth_user && match(arec->auth_user, auth_user))) &&
(type & 0x1 || match(arec->username, username)))
{
hprecv = arec->precedence;
hprec = arec->aconf;
}
p = strchr(p, '.');
if(p != NULL)
p++;
else
break;
}
for (arec = atable[0]; arec; arec = arec->next)
{
if(arec->type == (type & ~0x1) &&
arec->masktype == HM_HOST &&
arec->precedence > hprecv &&
(match(arec->Mask.hostname, name) ||
(sockhost && match(arec->Mask.hostname, sockhost))) &&
(type != CONF_CLIENT || !arec->auth_user ||
(auth_user && match(arec->auth_user, auth_user))) &&
(type & 0x1 || match(arec->username, username)))
{
hprecv = arec->precedence;
hprec = arec->aconf;
}
}
}
return hprec;
}
/* struct ConfItem* find_address_conf(const char*, const char*,
* struct rb_sockaddr_storage*, int);
* Input: The hostname, username, address, address family.
* Output: The applicable ConfItem.
* Side-effects: None
*/
struct ConfItem *
find_address_conf(const char *host, const char *sockhost, const char *user,
const char *notildeuser, struct sockaddr *ip, int aftype, char *auth_user)
{
struct ConfItem *iconf, *kconf;
const char *vuser;
#ifdef RB_IPV6
struct sockaddr_in ip4;
#endif
/* Find the best I-line... If none, return NULL -A1kmm */
if(!(iconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_CLIENT, aftype, user, auth_user)))
return NULL;
/* Find what their visible username will be.
* Note that the username without tilde may contain one char more.
* -- jilles */
vuser = IsNoTilde(iconf) ? notildeuser : user;
/* If they are exempt from K-lines, return the best I-line. -A1kmm */
if(IsConfExemptKline(iconf))
return iconf;
/* Find the best K-line... -A1kmm */
kconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_KILL, aftype, user, NULL);
/* If they are K-lined, return the K-line */
if(kconf)
return kconf;
/* if theres a spoof, check it against klines.. */
if(IsConfDoSpoofIp(iconf))
{
char *p = strchr(iconf->info.name, '@');
/* note, we dont need to pass sockhost here, as its
* guaranteed to not match by whats above.. --anfl
*/
if(p)
{
*p = '\0';
kconf = find_conf_by_address(p+1, NULL, NULL, ip, CONF_KILL, aftype, iconf->info.name, NULL);
*p = '@';
}
else
kconf = find_conf_by_address(iconf->info.name, NULL, NULL, ip, CONF_KILL, aftype, vuser, NULL);
if(kconf)
return kconf;
}
/* if no_tilde, check the username without tilde against klines too
* -- jilles */
if(user != vuser)
{
kconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_KILL, aftype, vuser, NULL);
if(kconf)
return kconf;
}
#ifdef RB_IPV6
if(ip != NULL && ip->sa_family == AF_INET6 &&
ipv4_from_ipv6((const struct sockaddr_in6 *)(const void *)ip, &ip4))
{
kconf = find_conf_by_address(NULL, NULL, NULL, (struct sockaddr *)&ip4, CONF_KILL, AF_INET, vuser, NULL);
if(kconf)
return kconf;
}
#endif /* RB_IPV6 */
return iconf;
}
/* struct ConfItem* find_dline(struct rb_sockaddr_storage*, int)
* Input: An address, an address family.
* Output: The best matching D-line or exempt line.
* Side effects: None.
*/
struct ConfItem *
find_dline(struct sockaddr *addr, int aftype)
{
struct ConfItem *aconf;
#ifdef RB_IPV6
struct sockaddr_in addr2;
#endif
aconf = find_conf_by_address(NULL, NULL, NULL, addr, CONF_EXEMPTDLINE | 1, aftype, NULL, NULL);
if(aconf)
return aconf;
aconf = find_conf_by_address(NULL, NULL, NULL, addr, CONF_DLINE | 1, aftype, NULL, NULL);
if(aconf)
return aconf;
#ifdef RB_IPV6
if(addr->sa_family == AF_INET6 &&
ipv4_from_ipv6((const struct sockaddr_in6 *)(const void *)addr, &addr2))
{
aconf = find_conf_by_address(NULL, NULL, NULL, (struct sockaddr *)&addr2, CONF_DLINE | 1, AF_INET, NULL, NULL);
if(aconf)
return aconf;
}
#endif
return NULL;
}
/* void find_exact_conf_by_address(const char*, int, const char *)
* Input:
* Output: ConfItem if found
* Side-effects: None
*/
struct ConfItem *
find_exact_conf_by_address(const char *address, int type, const char *username)
{
int masktype, bits;
unsigned long hv;
struct AddressRec *arec;
struct rb_sockaddr_storage addr;
if(address == NULL)
address = "/NOMATCH!/";
masktype = parse_netmask(address, &addr, &bits);
#ifdef RB_IPV6
if(masktype == HM_IPV6)
{
/* We have to do this, since we do not re-hash for every bit -A1kmm. */
hv = hash_ipv6((struct sockaddr *)&addr, bits - bits % 16);
}
else
#endif
if(masktype == HM_IPV4)
{
/* We have to do this, since we do not re-hash for every bit -A1kmm. */
hv = hash_ipv4((struct sockaddr *)&addr, bits - bits % 8);
}
else
{
hv = get_mask_hash(address);
}
for (arec = atable[hv]; arec; arec = arec->next)
{
if (arec->type == type &&
arec->masktype == masktype &&
(arec->username == NULL || username == NULL ? arec->username == username : !irccmp(arec->username, username)))
{
if (masktype == HM_HOST)
{
if (!irccmp(arec->Mask.hostname, address))
return arec->aconf;
}
else
{
if (arec->Mask.ipa.bits == bits &&
comp_with_mask_sock((struct sockaddr *)&arec->Mask.ipa.addr, (struct sockaddr *)&addr, bits))
return arec->aconf;
}
}
}
return NULL;
}
/* void add_conf_by_address(const char*, int, const char *,
* struct ConfItem *aconf)
* Input:
* Output: None
* Side-effects: Adds this entry to the hash table.
*/
void
add_conf_by_address(const char *address, int type, const char *username, const char *auth_user, struct ConfItem *aconf)
{
static unsigned long prec_value = 0xFFFFFFFF;
int bits;
unsigned long hv;
struct AddressRec *arec;
if(address == NULL)
address = "/NOMATCH!/";
arec = rb_malloc(sizeof(struct AddressRec));
arec->masktype = parse_netmask(address, &arec->Mask.ipa.addr, &bits);
#ifdef RB_IPV6
if(arec->masktype == HM_IPV6)
{
arec->Mask.ipa.bits = bits;
/* We have to do this, since we do not re-hash for every bit -A1kmm. */
bits -= bits % 16;
arec->next = atable[(hv = hash_ipv6((struct sockaddr *)&arec->Mask.ipa.addr, bits))];
atable[hv] = arec;
}
else
#endif
if(arec->masktype == HM_IPV4)
{
arec->Mask.ipa.bits = bits;
/* We have to do this, since we do not re-hash for every bit -A1kmm. */
bits -= bits % 8;
arec->next = atable[(hv = hash_ipv4((struct sockaddr *)&arec->Mask.ipa.addr, bits))];
atable[hv] = arec;
}
else
{
arec->Mask.hostname = address;
arec->next = atable[(hv = get_mask_hash(address))];
atable[hv] = arec;
}
arec->username = username;
arec->auth_user = auth_user;
arec->aconf = aconf;
arec->precedence = prec_value--;
arec->type = type;
}
/* void delete_one_address(const char*, struct ConfItem*)
* Input: An address string, the associated ConfItem.
* Output: None
* Side effects: Deletes an address record. Frees the ConfItem if there
* is nothing referencing it, sets it as illegal otherwise.
*/
void
delete_one_address_conf(const char *address, struct ConfItem *aconf)
{
int masktype, bits;
unsigned long hv;
struct AddressRec *arec, *arecl = NULL;
struct rb_sockaddr_storage addr;
masktype = parse_netmask(address, &addr, &bits);
#ifdef RB_IPV6
if(masktype == HM_IPV6)
{
/* We have to do this, since we do not re-hash for every bit -A1kmm. */
bits -= bits % 16;
hv = hash_ipv6((struct sockaddr *)&addr, bits);
}
else
#endif
if(masktype == HM_IPV4)
{
/* We have to do this, since we do not re-hash for every bit -A1kmm. */
bits -= bits % 8;
hv = hash_ipv4((struct sockaddr *)&addr, bits);
}
else
hv = get_mask_hash(address);
for (arec = atable[hv]; arec; arec = arec->next)
{
if(arec->aconf == aconf)
{
if(arecl)
arecl->next = arec->next;
else
atable[hv] = arec->next;
aconf->status |= CONF_ILLEGAL;
if(!aconf->clients)
free_conf(aconf);
rb_free(arec);
return;
}
arecl = arec;
}
}
/* void clear_out_address_conf(void)
* Input: None
* Output: None
* Side effects: Clears out all address records in the hash table,
* frees them, and frees the ConfItems if nothing references
* them, otherwise sets them as illegal.
*/
void
clear_out_address_conf(void)
{
int i;
struct AddressRec **store_next;
struct AddressRec *arec, *arecn;
for (i = 0; i < ATABLE_SIZE; i++)
{
store_next = &atable[i];
for (arec = atable[i]; arec; arec = arecn)
{
arecn = arec->next;
/* We keep the temporary K-lines and destroy the
* permanent ones, just to be confusing :) -A1kmm */
if(arec->aconf->flags & CONF_FLAGS_TEMPORARY ||
(arec->type != CONF_CLIENT && arec->type != CONF_EXEMPTDLINE))
{
*store_next = arec;
store_next = &arec->next;
}
else
{
arec->aconf->status |= CONF_ILLEGAL;
if(!arec->aconf->clients)
free_conf(arec->aconf);
rb_free(arec);
}
}
*store_next = NULL;
}
}
void
clear_out_address_conf_bans(void)
{
int i;
struct AddressRec **store_next;
struct AddressRec *arec, *arecn;
for (i = 0; i < ATABLE_SIZE; i++)
{
store_next = &atable[i];
for (arec = atable[i]; arec; arec = arecn)
{
arecn = arec->next;
/* We keep the temporary K-lines and destroy the
* permanent ones, just to be confusing :) -A1kmm */
if(arec->aconf->flags & CONF_FLAGS_TEMPORARY ||
(arec->type == CONF_CLIENT || arec->type == CONF_EXEMPTDLINE))
{
*store_next = arec;
store_next = &arec->next;
}
else
{
arec->aconf->status |= CONF_ILLEGAL;
if(!arec->aconf->clients)
free_conf(arec->aconf);
rb_free(arec);
}
}
*store_next = NULL;
}
}
/*
* show_iline_prefix()
*
* inputs - pointer to struct Client requesting output
* - pointer to struct ConfItem
* - name to which iline prefix will be prefixed to
* output - pointer to static string with prefixes listed in ascii form
* side effects - NONE
*/
char *
show_iline_prefix(struct Client *sptr, struct ConfItem *aconf, char *name)
{
static char prefix_of_host[USERLEN + 15];
char *prefix_ptr;
prefix_ptr = prefix_of_host;
if(IsNoTilde(aconf))
*prefix_ptr++ = '-';
if(IsNeedIdentd(aconf))
*prefix_ptr++ = '+';
if(IsConfDoSpoofIp(aconf))
*prefix_ptr++ = '=';
if(IsOper(sptr) && IsConfExemptFlood(aconf))
*prefix_ptr++ = '|';
if(IsOper(sptr) && IsConfExemptDNSBL(aconf) && !IsConfExemptKline(aconf))
*prefix_ptr++ = '$';
if(IsOper(sptr) && IsConfExemptKline(aconf))
*prefix_ptr++ = '^';
if(IsOper(sptr) && IsConfExemptLimits(aconf))
*prefix_ptr++ = '>';
*prefix_ptr = '\0';
strncpy(prefix_ptr, name, USERLEN);
return (prefix_of_host);
}
/* report_auth()
*
* Inputs: pointer to client to report to
* Output: None
* Side effects: Reports configured auth{} blocks to client_p
*/
void
report_auth(struct Client *client_p)
{
char *name, *host, *user, *classname;
const char *pass;
struct AddressRec *arec;
struct ConfItem *aconf;
int i, port;
for (i = 0; i < ATABLE_SIZE; i++)
for (arec = atable[i]; arec; arec = arec->next)
if(arec->type == CONF_CLIENT)
{
aconf = arec->aconf;
if(!IsOper(client_p) && IsConfDoSpoofIp(aconf))
continue;
get_printable_conf(aconf, &name, &host, &pass, &user, &port,
&classname);
if(!EmptyString(aconf->spasswd))
pass = aconf->spasswd;
sendto_one_numeric(client_p, RPL_STATSILINE,
form_str(RPL_STATSILINE),
name, pass, show_iline_prefix(client_p, aconf, user),
show_ip_conf(aconf, client_p) ? host : "255.255.255.255",
port, classname);
}
}

785
src/ircd.c Normal file
View file

@ -0,0 +1,785 @@
/*
* charybdis: A slightly useful ircd.
* ircd.c: Starts up and runs the ircd.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2008 ircd-ratbox development team
* Copyright (C) 2005-2013 charybdis development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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
*
* $Id$
*/
#include "ratbox_lib.h"
#include "stdinc.h"
#include "setup.h"
#include "config.h"
#include "ircd.h"
#include "channel.h"
#include "class.h"
#include "client.h"
#include "common.h"
#include "hash.h"
#include "match.h"
#include "ircd_signal.h"
#include "msg.h" /* msgtab */
#include "hostmask.h"
#include "numeric.h"
#include "parse.h"
#include "res.h"
#include "restart.h"
#include "s_auth.h"
#include "s_conf.h"
#include "logger.h"
#include "s_serv.h" /* try_connections */
#include "s_user.h"
#include "s_stats.h"
#include "scache.h"
#include "send.h"
#include "supported.h"
#include "whowas.h"
#include "modules.h"
#include "hook.h"
#include "ircd_getopt.h"
#include "newconf.h"
#include "reject.h"
#include "s_conf.h"
#include "s_newconf.h"
#include "cache.h"
#include "monitor.h"
#include "patchlevel.h"
#include "serno.h"
#include "sslproc.h"
#include "chmode.h"
#include "privilege.h"
#include "bandbi.h"
/* /quote set variables */
struct SetOptions GlobalSetOptions;
/* configuration set from ircd.conf */
struct config_file_entry ConfigFileEntry;
/* server info set from ircd.conf */
struct server_info ServerInfo;
/* admin info set from ircd.conf */
struct admin_info AdminInfo;
struct Counter Count;
struct ServerStatistics ServerStats;
int maxconnections;
struct Client me; /* That's me */
struct LocalUser meLocalUser; /* That's also part of me */
rb_dlink_list global_client_list;
/* unknown/client pointer lists */
rb_dlink_list unknown_list; /* unknown clients ON this server only */
rb_dlink_list lclient_list; /* local clients only ON this server */
rb_dlink_list serv_list; /* local servers to this server ONLY */
rb_dlink_list global_serv_list; /* global servers on the network */
rb_dlink_list local_oper_list; /* our opers, duplicated in lclient_list */
rb_dlink_list oper_list; /* network opers */
const char *logFileName = LPATH;
const char *pidFileName = PPATH;
char **myargv;
int dorehash = 0;
int dorehashbans = 0;
int doremotd = 0;
int kline_queued = 0;
int server_state_foreground = 0;
int opers_see_all_users = 0;
int ircd_ssl_ok = 0;
int ircd_zlib_ok = 1;
int testing_conf = 0;
time_t startup_time;
int default_server_capabs;
int splitmode;
int splitchecking;
int split_users;
int split_servers;
int eob_count;
void
ircd_shutdown(const char *reason)
{
struct Client *target_p;
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, lclient_list.head)
{
target_p = ptr->data;
sendto_one(target_p, ":%s NOTICE %s :Server Terminating. %s",
me.name, target_p->name, reason);
}
RB_DLINK_FOREACH(ptr, serv_list.head)
{
target_p = ptr->data;
sendto_one(target_p, ":%s ERROR :Terminated by %s",
me.name, reason);
}
ilog(L_MAIN, "Server Terminating. %s", reason);
close_logfiles();
unlink(pidFileName);
exit(0);
}
/*
* init_sys
*
* inputs - boot_daemon flag
* output - none
* side effects - if boot_daemon flag is not set, don't daemonize
*/
static void
init_sys(void)
{
#if defined(RLIMIT_NOFILE) && defined(HAVE_SYS_RESOURCE_H)
struct rlimit limit;
if(!getrlimit(RLIMIT_NOFILE, &limit))
{
maxconnections = limit.rlim_cur;
if(maxconnections <= MAX_BUFFER)
{
fprintf(stderr, "ERROR: Shell FD limits are too low.\n");
fprintf(stderr, "ERROR: charybdis reserves %d FDs, shell limits must be above this\n", MAX_BUFFER);
exit(EXIT_FAILURE);
}
return;
}
#endif /* RLIMIT_FD_MAX */
maxconnections = MAXCONNECTIONS;
}
void rehash_ulimit(void)
{
#if defined(RLIMIT_NOFILE) && defined(HAVE_SYS_RESOURCE_H)
struct rlimit limit;
if(!getrlimit(RLIMIT_NOFILE, &limit) && limit.rlim_cur != maxconnections)
{
if(limit.rlim_cur <= MAX_BUFFER)
{
fprintf(stderr, "ERROR: Shell FD limits are too low.\n");
fprintf(stderr, "ERROR: charybdis reserves %d FDs, shell limits must be above this\n", MAX_BUFFER);
fprintf(stderr, "ERROR: keeping old limits\n");
return;
} else if(limit.rlim_cur < maxconnections)
{
fprintf(stderr, "ERROR: ulimit decreased\n");
fprintf(stderr, "ERROR: keeping old limits\n");
return;
}
maxconnections = limit.rlim_cur;
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Setting maxconnections to %d", maxconnections);
return;
}
#endif /* RLIMIT_FD_MAX */
}
static int
make_daemon(void)
{
int pid, nullfd, fdx;
/* The below is approximately what daemon(1, 0) does, but
we need control over the parent after forking to print
the startup message -- Aaron */
if((nullfd = open("/dev/null", O_RDWR)) < 0)
{
perror("open /dev/null");
exit(EXIT_FAILURE);
}
if((pid = fork()) < 0)
{
perror("fork");
exit(EXIT_FAILURE);
}
else if(pid > 0)
{
inotice("now running in background mode from %s as pid %d ...",
ConfigFileEntry.dpath, pid);
exit(EXIT_SUCCESS);
}
for(fdx = 0; fdx <= 2; fdx++)
if (fdx != nullfd)
(void) dup2(nullfd, fdx);
if(nullfd > 2)
(void) close(nullfd);
(void) setsid();
return 0;
}
static int printVersion = 0;
struct lgetopt myopts[] = {
{"configfile", &ConfigFileEntry.configfile,
STRING, "File to use for ircd.conf"},
{"logfile", &logFileName,
STRING, "File to use for ircd.log"},
{"pidfile", &pidFileName,
STRING, "File to use for process ID"},
{"foreground", &server_state_foreground,
YESNO, "Run in foreground (don't detach)"},
{"version", &printVersion,
YESNO, "Print version and exit"},
{"conftest", &testing_conf,
YESNO, "Test the configuration files and exit"},
{"help", NULL, USAGE, "Print this text"},
{NULL, NULL, STRING, NULL},
};
static void
check_rehash(void *unused)
{
/*
* Check to see whether we have to rehash the configuration ..
*/
if(dorehash)
{
rehash(1);
rehash_ulimit();
dorehash = 0;
}
if(dorehashbans)
{
rehash_bans(1);
dorehashbans = 0;
}
if(doremotd)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Got signal SIGUSR1, reloading ircd motd file");
cache_user_motd();
doremotd = 0;
}
}
/*
* initalialize_global_set_options
*
* inputs - none
* output - none
* side effects - This sets all global set options needed
*/
static void
initialize_global_set_options(void)
{
memset(&GlobalSetOptions, 0, sizeof(GlobalSetOptions));
/* memset( &ConfigFileEntry, 0, sizeof(ConfigFileEntry)); */
GlobalSetOptions.maxclients = ServerInfo.default_max_clients;
if(GlobalSetOptions.maxclients > (maxconnections - MAX_BUFFER) || (GlobalSetOptions.maxclients <= 0))
GlobalSetOptions.maxclients = maxconnections - MAX_BUFFER;
GlobalSetOptions.autoconn = 1;
GlobalSetOptions.spam_time = MIN_JOIN_LEAVE_TIME;
GlobalSetOptions.spam_num = MAX_JOIN_LEAVE_COUNT;
GlobalSetOptions.floodcount = ConfigFileEntry.default_floodcount;
split_servers = ConfigChannel.default_split_server_count;
split_users = ConfigChannel.default_split_user_count;
if(split_users && split_servers
&& (ConfigChannel.no_create_on_split || ConfigChannel.no_join_on_split))
{
splitmode = 1;
splitchecking = 1;
}
GlobalSetOptions.ident_timeout = ConfigFileEntry.default_ident_timeout;
rb_strlcpy(GlobalSetOptions.operstring,
ConfigFileEntry.default_operstring,
sizeof(GlobalSetOptions.operstring));
rb_strlcpy(GlobalSetOptions.adminstring,
ConfigFileEntry.default_adminstring,
sizeof(GlobalSetOptions.adminstring));
/* memset( &ConfigChannel, 0, sizeof(ConfigChannel)); */
/* End of global set options */
}
/*
* initialize_server_capabs
*
* inputs - none
* output - none
*/
static void
initialize_server_capabs(void)
{
default_server_capabs &= ~CAP_ZIP;
}
/*
* write_pidfile
*
* inputs - filename+path of pid file
* output - none
* side effects - write the pid of the ircd to filename
*/
static void
write_pidfile(const char *filename)
{
FILE *fb;
char buff[32];
if((fb = fopen(filename, "w")))
{
unsigned int pid = (unsigned int) getpid();
rb_snprintf(buff, sizeof(buff), "%u\n", pid);
if((fputs(buff, fb) == -1))
{
ilog(L_MAIN, "Error writing %u to pid file %s (%s)",
pid, filename, strerror(errno));
}
fclose(fb);
return;
}
else
{
ilog(L_MAIN, "Error opening pid file %s", filename);
}
}
/*
* check_pidfile
*
* inputs - filename+path of pid file
* output - none
* side effects - reads pid from pidfile and checks if ircd is in process
* list. if it is, gracefully exits
* -kre
*/
static void
check_pidfile(const char *filename)
{
FILE *fb;
char buff[32];
pid_t pidfromfile;
/* Don't do logging here, since we don't have log() initialised */
if((fb = fopen(filename, "r")))
{
if(fgets(buff, 20, fb) != NULL)
{
pidfromfile = atoi(buff);
if(!kill(pidfromfile, 0))
{
printf("ircd: daemon is already running\n");
exit(-1);
}
}
fclose(fb);
}
}
/*
* setup_corefile
*
* inputs - nothing
* output - nothing
* side effects - setups corefile to system limits.
* -kre
*/
static void
setup_corefile(void)
{
#ifdef HAVE_SYS_RESOURCE_H
struct rlimit rlim; /* resource limits */
/* Set corefilesize to maximum */
if(!getrlimit(RLIMIT_CORE, &rlim))
{
rlim.rlim_cur = rlim.rlim_max;
setrlimit(RLIMIT_CORE, &rlim);
}
#endif
}
static void
ircd_log_cb(const char *str)
{
ilog(L_MAIN, "libratbox reports: %s", str);
}
static void __attribute__((noreturn))
ircd_restart_cb(const char *str)
{
inotice("libratbox has called the restart callback: %s", str);
restart(str);
}
/*
* Why EXIT_FAILURE here?
* Because if ircd_die_cb() is called it's because of a fatal
* error inside libcharybdis, and we don't know how to handle the
* exception, so it is logical to return a FAILURE exit code here.
* --nenolod
*/
static void __attribute__((noreturn))
ircd_die_cb(const char *str)
{
if(str != NULL)
{
/* Try to get the message out to currently logged in operators. */
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "libratbox has called the die callback..aborting: %s", str);
inotice("libratbox has called the die callback..aborting: %s", str);
}
else
inotice("libratbox has called the die callback..aborting");
unlink(pidFileName);
exit(EXIT_FAILURE);
}
struct ev_entry *check_splitmode_ev = NULL;
static int
seed_with_urandom(void)
{
unsigned int seed;
int fd;
fd = open("/dev/urandom", O_RDONLY);
if(fd >= 0)
{
if(read(fd, &seed, sizeof(seed)) == sizeof(seed))
{
close(fd);
srand(seed);
return 1;
}
close(fd);
}
return 0;
}
static void
seed_with_clock(void)
{
const struct timeval *tv;
rb_set_time();
tv = rb_current_time_tv();
srand(tv->tv_sec ^ (tv->tv_usec | (getpid() << 20)));
}
static void
seed_random(void *unused)
{
unsigned int seed;
if(rb_get_random(&seed, sizeof(seed)) == -1)
{
if(!seed_with_urandom())
seed_with_clock();
return;
}
srand(seed);
}
/*
* main
*
* Initializes the IRCd.
*
* Inputs - number of commandline args, args themselves
* Outputs - none
* Side Effects - this is where the ircd gets going right now
*/
int
main(int argc, char *argv[])
{
int fd;
struct vhost_conf *vhost_p;
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
/* Check to see if the user is running us as root, which is a nono */
if(geteuid() == 0)
{
fprintf(stderr, "Don't run ircd as root!!!\n");
return -1;
}
init_sys();
ConfigFileEntry.dpath = DPATH;
ConfigFileEntry.configfile = CPATH; /* Server configuration file */
ConfigFileEntry.connect_timeout = 30; /* Default to 30 */
umask(077); /* better safe than sorry --SRB */
myargv = argv;
parseargs(&argc, &argv, myopts);
if(chdir(ConfigFileEntry.dpath))
{
fprintf(stderr, "Unable to chdir to %s: %s\n", ConfigFileEntry.dpath, strerror(errno));
exit(EXIT_FAILURE);
}
rb_set_time();
/*
* Setup corefile size immediately after boot -kre
*/
setup_corefile();
memset(&me, 0, sizeof(me));
memset(&meLocalUser, 0, sizeof(meLocalUser));
me.localClient = &meLocalUser;
/* Make sure all lists are zeroed */
memset(&unknown_list, 0, sizeof(unknown_list));
memset(&lclient_list, 0, sizeof(lclient_list));
memset(&serv_list, 0, sizeof(serv_list));
memset(&global_serv_list, 0, sizeof(global_serv_list));
memset(&local_oper_list, 0, sizeof(local_oper_list));
memset(&oper_list, 0, sizeof(oper_list));
rb_dlinkAddTail(&me, &me.node, &global_client_list);
memset(&Count, 0, sizeof(Count));
memset(&ServerInfo, 0, sizeof(ServerInfo));
memset(&AdminInfo, 0, sizeof(AdminInfo));
memset(&ServerStats, 0, sizeof(struct ServerStatistics));
if(printVersion)
{
printf("ircd: version %s(%s)\n", ircd_version, serno);
#ifdef CUSTOM_BRANDING
printf("ircd: based on %s-%s\n", PACKAGE_NAME, PACKAGE_VERSION);
#endif
printf("ircd: %s\n", rb_lib_version());
exit(EXIT_SUCCESS);
}
setup_signals();
if (testing_conf)
server_state_foreground = 1;
/* Make sure fd 0, 1 and 2 are in use -- jilles */
do
{
fd = open("/dev/null", O_RDWR);
} while (fd < 2 && fd != -1);
if (fd > 2)
close(fd);
else if (fd == -1)
exit(1);
/* Check if there is pidfile and daemon already running */
if(!testing_conf)
{
check_pidfile(pidFileName);
inotice("starting %s ...", ircd_version);
inotice("%s", rb_lib_version());
if(!server_state_foreground)
make_daemon();
}
/* Init the event subsystem */
rb_lib_init(ircd_log_cb, ircd_restart_cb, ircd_die_cb, !server_state_foreground, maxconnections, DNODE_HEAP_SIZE, FD_HEAP_SIZE);
rb_linebuf_init(LINEBUF_HEAP_SIZE);
rb_init_prng(NULL, RB_PRNG_DEFAULT);
seed_random(NULL);
init_builtin_capabs();
default_server_capabs = CAP_MASK;
init_main_logfile();
newconf_init();
init_s_conf();
init_s_newconf();
init_hash();
clear_scache_hash_table(); /* server cache name table */
init_host_hash();
clear_hash_parse();
init_client();
init_hook();
init_channels();
initclass();
initwhowas();
init_reject();
init_cache();
init_monitor();
construct_cflags_strings();
load_all_modules(1);
#ifndef STATIC_MODULES
load_core_modules(1);
#endif
init_auth(); /* Initialise the auth code */
init_resolver(); /* Needs to be setup before the io loop */
privilegeset_set_new("default", "", 0);
if (testing_conf)
fprintf(stderr, "\nBeginning config test\n");
read_conf_files(YES); /* cold start init conf files */
#ifndef STATIC_MODULES
mod_add_path(MODULE_DIR);
mod_add_path(MODULE_DIR "/autoload");
#endif
init_isupport();
init_bandb();
init_ssld();
rehash_bans(0);
initialize_server_capabs(); /* Set up default_server_capabs */
initialize_global_set_options();
if(ServerInfo.name == NULL)
{
ierror("no server name specified in serverinfo block.");
return -1;
}
rb_strlcpy(me.name, ServerInfo.name, sizeof(me.name));
if(ServerInfo.sid[0] == '\0')
{
ierror("no server sid specified in serverinfo block.");
return -2;
}
strcpy(me.id, ServerInfo.sid);
init_uid();
/* serverinfo{} description must exist. If not, error out. */
if(ServerInfo.description == NULL)
{
ierror("no server description specified in serverinfo block.");
return -3;
}
rb_strlcpy(me.info, ServerInfo.description, sizeof(me.info));
if(ServerInfo.ssl_cert != NULL && ServerInfo.ssl_private_key != NULL)
{
if(ServerInfo.ssl_cipher_list == NULL)
{
ierror("no ssl cipher list specified in serverinfo block.");
return -4;
}
/* just do the rb_setup_ssl_server to validate the config */
if(!rb_setup_ssl_server(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list, NULL))
{
ilog(L_MAIN, "WARNING: Unable to setup SSL.");
ircd_ssl_ok = 0;
}
else
ircd_ssl_ok = 1;
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, vhost_conf_list.head)
{
vhost_p = ptr->data;
ilog(L_MAIN, "WARNING: h:%s c:%s k:%s d:%s ci:%s", vhost_p->hostname, vhost_p->ssl_cert, vhost_p->ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list);
if(rb_setup_ssl_server(vhost_p->ssl_cert, vhost_p->ssl_private_key,
vhost_p->ssl_dh_params ? vhost_p->ssl_dh_params : ServerInfo.ssl_dh_params,
vhost_p->ssl_cipher_list ? vhost_p->ssl_cipher_list : ServerInfo.ssl_cipher_list, vhost_p->hostname))
{
ircd_ssl_ok = 1;
}
}
}
if (testing_conf)
{
fprintf(stderr, "\nConfig testing complete.\n");
fflush(stderr);
return 0; /* Why? We want the launcher to exit out. */
}
me.from = &me;
me.servptr = &me;
SetMe(&me);
make_server(&me);
startup_time = rb_current_time();
add_to_client_hash(me.name, &me);
add_to_id_hash(me.id, &me);
me.serv->nameinfo = scache_connect(me.name, me.info, 0);
rb_dlinkAddAlloc(&me, &global_serv_list);
construct_umodebuf();
check_class();
write_pidfile(pidFileName);
load_help();
open_logfiles();
ilog(L_MAIN, "Server Ready");
/* We want try_connections to be called as soon as possible now! -- adrian */
/* No, 'cause after a restart it would cause all sorts of nick collides */
/* um. by waiting even longer, that just means we have even *more*
* nick collisions. what a stupid idea. set an event for the IO loop --fl
*/
rb_event_addish("try_connections", try_connections, NULL, STARTUP_CONNECTIONS_TIME);
rb_event_addonce("try_connections_startup", try_connections, NULL, 2);
rb_event_add("check_rehash", check_rehash, NULL, 3);
rb_event_addish("reseed_srand", seed_random, NULL, 300); /* reseed every 10 minutes */
if(splitmode)
check_splitmode_ev = rb_event_add("check_splitmode", check_splitmode, NULL, 5);
if(server_state_foreground)
inotice("now running in foreground mode from %s as pid %d ...",
ConfigFileEntry.dpath, getpid());
rb_lib_loop(0);
/* UNREACHABLE */
}

260
src/ircd_lexer.l Normal file
View file

@ -0,0 +1,260 @@
/* src/ircd_lexer.l
*
* 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
*
* $Id: ircd_lexer.l 3540 2007-07-30 17:26:00Z jilles $
*/
%option case-insensitive
%option noyywrap
%option nounput
%{
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#define WE_ARE_MEMORY_C
#include "stdinc.h"
#include "ircd_defs.h"
#include "common.h"
#include "config.h"
#include "logger.h"
#include "s_conf.h"
#include "newconf.h"
#include "y.tab.h"
int yylex(void);
#define MAX_INCLUDE_DEPTH 10
YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
int include_stack_ptr=0;
int lineno = 1;
void ccomment(void);
void cinclude(void);
void hashcomment(void);
int ieof(void);
int lineno_stack[MAX_INCLUDE_DEPTH];
char conffile_stack[MAX_INCLUDE_DEPTH][IRCD_BUFSIZE];
char conffilebuf[IRCD_BUFSIZE+1];
char *current_file = conffilebuf;
FILE *inc_fbfile_in[MAX_INCLUDE_DEPTH];
char yy_linebuf[16384];
#undef YY_INPUT
#define YY_FATAL_ERROR(msg) conf_yy_fatal_error(msg)
#define YY_INPUT(buf,result,max_size) \
if (!(result = conf_fgets(buf, max_size, conf_fbfile_in))) \
YY_FATAL_ERROR("input in flex scanner failed");
%}
ws [ \t]*
digit [0-9]
comment #.*
qstring \"[^\"\n]*[\"\n]
string [a-zA-Z_\~\:][a-zA-Z0-9_\:]*
include \.include{ws}(\<.*\>|\".*\")
%%
{include} { cinclude(); }
"/*" { ccomment(); }
\n.* { rb_strlcpy(yy_linebuf, yytext+1, sizeof(yy_linebuf)); lineno++; yyless(1); }
{ws} ;
{comment} { hashcomment(); }
{digit}+ { yylval.number = atoi(yytext); return NUMBER; }
{qstring} {
if(yytext[yyleng-2] == '\\')
{
yyless(yyleng-1); /* return last quote */
yymore(); /* append next string */
}
else
{
rb_strlcpy(yylval.string, yytext + 1, 1024);
if(yylval.string[yyleng-2] != '"')
ilog(L_MAIN, "Unterminated character string");
else
{
int i,j;
yylval.string[yyleng-2] = '\0'; /* remove close
* quote
*/
for (j=i=0 ;yylval.string[i] != '\0'; i++,j++)
{
if (yylval.string[i] != '\\')
{
yylval.string[j] = yylval.string[i];
}
else
{
i++;
if (yylval.string[i] == '\0') /* XXX
* should not
* happen
*/
{
ilog(L_MAIN,
"Unterminated character string");
break;
}
yylval.string[j] = yylval.string[i];
}
}
yylval.string[j] = '\0';
return QSTRING;
}
}
}
loadmodule { return LOADMODULE; }
{string} {
rb_strlcpy(yylval.string, yytext, 1024);
yylval.string[yyleng] = '\0';
return STRING;
}
\.\. { return TWODOTS; }
. { return yytext[0]; }
<<EOF>> { if (ieof()) yyterminate(); }
%%
/* C-comment ignoring routine -kre*/
void ccomment()
{
int c;
/* log(L_NOTICE, "got comment"); */
while (1)
{
while ((c = input()) != '*' && c != EOF)
if (c == '\n') ++lineno;
if (c == '*')
{
while ((c = input()) == '*');
if (c == '/')
break;
if (c == '\n') ++lineno;
}
if (c == EOF)
{
YY_FATAL_ERROR("EOF in comment");
/* XXX hack alert this disables
* the stupid unused function warning
* gcc generates
*/
yy_fatal_error("EOF in comment");
break;
}
}
}
void cinclude(void)
{
char *c;
if ((c = strchr(yytext, '<')) == NULL)
*strchr(c = strchr(yytext, '"') + 1, '"') = 0;
else
*strchr(++c, '>') = 0;
/* do stacking and co. */
if (include_stack_ptr >= MAX_INCLUDE_DEPTH)
conf_report_error("Includes nested too deep (max is %d)", MAX_INCLUDE_DEPTH);
else
{
FILE *tmp_fbfile_in;
tmp_fbfile_in = fopen(c, "r");
if (tmp_fbfile_in == NULL)
{
/* if its not found in PREFIX, look in ETCPATH */
char fnamebuf[IRCD_BUFSIZE];
snprintf(fnamebuf, sizeof(fnamebuf), "%s/%s", ETCPATH, c);
tmp_fbfile_in = fopen(fnamebuf, "r");
/* wasnt found there either.. error. */
if(tmp_fbfile_in == NULL)
{
conf_report_error("Include %s: %s.", c, strerror(errno));
return;
}
}
lineno_stack[include_stack_ptr] = lineno;
lineno = 1;
inc_fbfile_in[include_stack_ptr] = conf_fbfile_in;
strcpy(conffile_stack[include_stack_ptr], c);
current_file = conffile_stack[include_stack_ptr];
include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
conf_fbfile_in = tmp_fbfile_in;
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
}
}
int ieof(void)
{
if (include_stack_ptr)
fclose(conf_fbfile_in);
if (--include_stack_ptr < 0)
{
/* We will now exit the lexer - restore init values if we get /rehash
* later and reenter lexer -kre */
include_stack_ptr = 0;
lineno = 1;
return 1;
}
/* switch buffer */
yy_delete_buffer(YY_CURRENT_BUFFER);
lineno = lineno_stack[include_stack_ptr];
conf_fbfile_in = inc_fbfile_in[include_stack_ptr];
if(include_stack_ptr)
current_file = conffile_stack[include_stack_ptr];
else
current_file = conffilebuf;
yy_switch_to_buffer(include_stack[include_stack_ptr]);
return 0;
}
/* #-comment style, look for #include */
#define INCLUDE "#include"
void hashcomment(void)
{
if (strlen(yytext) < sizeof(INCLUDE) - 1)
return;
if (!strncasecmp(yytext, INCLUDE, sizeof(INCLUDE) - 1))
yyerror("You probably meant '.include', skipping");
}

333
src/ircd_parser.y Normal file
View file

@ -0,0 +1,333 @@
/* This code is in the public domain.
* $Nightmare: nightmare/src/main/parser.y,v 1.2.2.1.2.1 2002/07/02 03:42:10 ejb Exp $
* $Id: ircd_parser.y 871 2006-02-18 21:56:00Z nenolod $
*/
%{
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#define WE_ARE_MEMORY_C
#include "stdinc.h"
#include "setup.h"
#include "common.h"
#include "ircd_defs.h"
#include "config.h"
#include "client.h"
#include "modules.h"
#include "newconf.h"
#define YY_NO_UNPUT
int yyparse(void);
void yyerror(const char *);
int yylex(void);
static time_t conf_find_time(char*);
static struct {
const char * name;
const char * plural;
time_t val;
} ircd_times[] = {
{"second", "seconds", 1},
{"minute", "minutes", 60},
{"hour", "hours", 60 * 60},
{"day", "days", 60 * 60 * 24},
{"week", "weeks", 60 * 60 * 24 * 7},
{"fortnight", "fortnights", 60 * 60 * 24 * 14},
{"month", "months", 60 * 60 * 24 * 7 * 4},
{"year", "years", 60 * 60 * 24 * 365},
/* ok-- we now do sizes here too. they aren't times, but
it's close enough */
{"byte", "bytes", 1},
{"kb", NULL, 1024},
{"kbyte", "kbytes", 1024},
{"kilobyte", "kilebytes", 1024},
{"mb", NULL, 1024 * 1024},
{"mbyte", "mbytes", 1024 * 1024},
{"megabyte", "megabytes", 1024 * 1024},
{NULL, NULL, 0},
};
time_t conf_find_time(char *name)
{
int i;
for (i = 0; ircd_times[i].name; i++)
{
if (strcasecmp(ircd_times[i].name, name) == 0 ||
(ircd_times[i].plural && strcasecmp(ircd_times[i].plural, name) == 0))
return ircd_times[i].val;
}
return 0;
}
static struct
{
const char *word;
int yesno;
} yesno[] = {
{"yes", 1},
{"no", 0},
{"true", 1},
{"false", 0},
{"on", 1},
{"off", 0},
{NULL, 0}
};
static int conf_get_yesno_value(char *str)
{
int i;
for (i = 0; yesno[i].word; i++)
{
if (strcasecmp(str, yesno[i].word) == 0)
{
return yesno[i].yesno;
}
}
return -1;
}
static void free_cur_list(conf_parm_t* list)
{
if (list->type == CF_STRING || list->type == CF_QSTRING) {
rb_free(list->v.string);
} else if (list->type == CF_FLIST) {
/* Even though CF_FLIST is a flag, comparing with == is valid
* because conf_parm_t.type must be either a type or one flag.
*/
free_cur_list(list->v.list);
}
if (list->next) {
free_cur_list(list->next);
}
rb_free(list);
}
conf_parm_t * cur_list = NULL;
static void add_cur_list_cpt(conf_parm_t *new)
{
if (cur_list == NULL)
{
cur_list = rb_malloc(sizeof(conf_parm_t));
cur_list->type = CF_FLIST;
cur_list->v.list = new;
}
else
{
new->next = cur_list->v.list;
cur_list->v.list = new;
}
}
static void add_cur_list(int type, char *str, int number)
{
conf_parm_t *new;
new = rb_malloc(sizeof(conf_parm_t));
new->next = NULL;
new->type = type;
switch(type)
{
case CF_INT:
case CF_TIME:
case CF_YESNO:
new->v.number = number;
break;
case CF_STRING:
case CF_QSTRING:
new->v.string = rb_strdup(str);
break;
}
add_cur_list_cpt(new);
}
%}
%union {
int number;
char string[1024];
conf_parm_t * conf_parm;
}
%token LOADMODULE TWODOTS
%token <string> QSTRING STRING
%token <number> NUMBER
%type <string> qstring string
%type <number> number timespec
%type <conf_parm> oneitem single itemlist
%start conf
%%
conf:
| conf conf_item
| error
;
conf_item: block
| loadmodule
;
block: string
{
conf_start_block($1, NULL);
}
'{' block_items '}' ';'
{
if (conf_cur_block)
conf_end_block(conf_cur_block);
}
| string qstring
{
conf_start_block($1, $2);
}
'{' block_items '}' ';'
{
if (conf_cur_block)
conf_end_block(conf_cur_block);
}
;
block_items: block_items block_item
| block_item
;
block_item: string '=' itemlist ';'
{
conf_call_set(conf_cur_block, $1, cur_list);
free_cur_list(cur_list);
cur_list = NULL;
}
;
itemlist: itemlist ',' single
| single
;
single: oneitem
{
add_cur_list_cpt($1);
}
| oneitem TWODOTS oneitem
{
/* "1 .. 5" meaning 1,2,3,4,5 - only valid for integers */
if ($1->type != CF_INT || $3->type != CF_INT)
{
conf_report_error("Both arguments in '..' notation must be integers.");
break;
}
else
{
int i;
for (i = $1->v.number; i <= $3->v.number; i++)
{
add_cur_list(CF_INT, 0, i);
}
}
}
;
oneitem: qstring
{
$$ = rb_malloc(sizeof(conf_parm_t));
$$->type = CF_QSTRING;
$$->v.string = rb_strdup($1);
}
| timespec
{
$$ = rb_malloc(sizeof(conf_parm_t));
$$->type = CF_TIME;
$$->v.number = $1;
}
| number
{
$$ = rb_malloc(sizeof(conf_parm_t));
$$->type = CF_INT;
$$->v.number = $1;
}
| string
{
/* a 'string' could also be a yes/no value ..
so pass it as that, if so */
int val = conf_get_yesno_value($1);
$$ = rb_malloc(sizeof(conf_parm_t));
if (val != -1)
{
$$->type = CF_YESNO;
$$->v.number = val;
}
else
{
$$->type = CF_STRING;
$$->v.string = rb_strdup($1);
}
}
;
loadmodule:
LOADMODULE QSTRING
{
#ifndef STATIC_MODULES
char *m_bn;
m_bn = rb_basename((char *) $2);
if (findmodule_byname(m_bn) == -1)
load_one_module($2, 0);
rb_free(m_bn);
#endif
}
';'
;
qstring: QSTRING { strcpy($$, $1); } ;
string: STRING { strcpy($$, $1); } ;
number: NUMBER { $$ = $1; } ;
timespec: number string
{
time_t t;
if ((t = conf_find_time($2)) == 0)
{
conf_report_error("Unrecognised time type/size '%s'", $2);
t = 1;
}
$$ = $1 * t;
}
| timespec timespec
{
$$ = $1 + $2;
}
| timespec number
{
$$ = $1 + $2;
}
;

175
src/ircd_signal.c Normal file
View file

@ -0,0 +1,175 @@
/************************************************************************
* IRC - Internet Relay Chat, src/ircd_signal.c
* Copyright (C) 1990 Jarkko Oikarinen and
* University of Oulu, Computing Center
*
* 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: ircd_signal.c 6 2005-09-10 01:02:21Z nenolod $
*/
#include "stdinc.h"
#include "ircd_signal.h"
#include "ircd.h" /* dorehash */
#include "restart.h" /* server_reboot */
#include "logger.h"
#include "s_conf.h"
#include "client.h"
#include "send.h"
/*
* dummy_handler - don't know if this is really needed but if alarm is still
* being used we probably will
*/
static void
dummy_handler(int sig)
{
/* Empty */
}
static void
sigchld_handler(int sig)
{
int status, olderrno;
olderrno = errno;
while (waitpid(-1, &status, WNOHANG) > 0)
;
errno = olderrno;
}
/*
* sigterm_handler - exit the server
*/
static void __attribute__((noreturn))
sigterm_handler(int sig)
{
ircd_shutdown("Received SIGTERM");
}
/*
* sighup_handler - reread the server configuration
*/
static void
sighup_handler(int sig)
{
dorehash = 1;
}
/*
* sigusr1_handler - reread the motd file
*/
static void
sigusr1_handler(int sig)
{
doremotd = 1;
}
static void
sigusr2_handler(int sig)
{
dorehashbans = 1;
}
/*
* sigint_handler - restart the server
*/
static void
sigint_handler(int sig)
{
static int restarting = 0;
if(server_state_foreground)
{
ilog(L_MAIN, "Server exiting on SIGINT");
exit(0);
}
else
{
ilog(L_MAIN, "Server Restarting on SIGINT");
if(restarting == 0)
{
restarting = 1;
server_reboot();
}
}
}
/*
* setup_signals - initialize signal handlers for server
*/
void
setup_signals()
{
sigset_t sigs;
struct sigaction act;
sigemptyset(&sigs);
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);
sigaddset(&sigs, SIGALRM);
act.sa_handler = sighup_handler;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGHUP);
sigaction(SIGHUP, &act, 0);
sigaddset(&sigs, SIGHUP);
act.sa_handler = sigint_handler;
sigaddset(&act.sa_mask, SIGINT);
sigaction(SIGINT, &act, 0);
sigaddset(&sigs, SIGINT);
act.sa_handler = sigterm_handler;
sigaddset(&act.sa_mask, SIGTERM);
sigaction(SIGTERM, &act, 0);
sigaddset(&sigs, SIGTERM);
act.sa_handler = sigusr1_handler;
sigaddset(&act.sa_mask, SIGUSR1);
sigaction(SIGUSR1, &act, 0);
sigaddset(&sigs, SIGUSR1);
act.sa_handler = sigusr2_handler;
sigaddset(&act.sa_mask, SIGUSR2);
sigaction(SIGUSR2, &act, 0);
sigaddset(&sigs, SIGUSR2);
act.sa_handler = sigchld_handler;
sigaddset(&act.sa_mask, SIGCHLD);
sigaction(SIGCHLD, &act, 0);
sigaddset(&sigs, SIGCHLD);
sigprocmask(SIG_UNBLOCK, &sigs, NULL);
}

613
src/listener.c Normal file
View file

@ -0,0 +1,613 @@
/*
* ircd-ratbox: A slightly useful ircd.
* listener.c: Listens on a port.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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
*
* $Id: listener.c 3460 2007-05-18 20:31:33Z jilles $
*/
#include "stdinc.h"
#include "setup.h"
#include "listener.h"
#include "client.h"
#include "match.h"
#include "ircd.h"
#include "ircd_defs.h"
#include "numeric.h"
#include "s_conf.h"
#include "s_newconf.h"
#include "s_stats.h"
#include "send.h"
#include "s_auth.h"
#include "reject.h"
#include "s_conf.h"
#include "hostmask.h"
#include "sslproc.h"
#include "hash.h"
#include "s_assert.h"
#include "logger.h"
#ifndef INADDR_NONE
#define INADDR_NONE ((unsigned int) 0xffffffff)
#endif
#if defined(NO_IN6ADDR_ANY) && defined(RB_IPV6)
static const struct in6_addr in6addr_any =
{ { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
#endif
static struct Listener *ListenerPollList = NULL;
static int accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, void *data);
static void accept_callback(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t addrlen, void *data);
static struct Listener *
make_listener(struct rb_sockaddr_storage *addr)
{
struct Listener *listener = (struct Listener *) rb_malloc(sizeof(struct Listener));
s_assert(0 != listener);
listener->name = me.name;
listener->F = NULL;
memcpy(&listener->addr, addr, sizeof(struct rb_sockaddr_storage));
listener->next = NULL;
return listener;
}
void
free_listener(struct Listener *listener)
{
s_assert(NULL != listener);
if(listener == NULL)
return;
/*
* remove from listener list
*/
if(listener == ListenerPollList)
ListenerPollList = listener->next;
else
{
struct Listener *prev = ListenerPollList;
for (; prev; prev = prev->next)
{
if(listener == prev->next)
{
prev->next = listener->next;
break;
}
}
}
/* free */
rb_free(listener);
}
#define PORTNAMELEN 6 /* ":31337" */
/*
* get_listener_port - return displayable listener port
*/
static uint16_t
get_listener_port(const struct Listener *listener)
{
#ifdef RB_IPV6
if(listener->addr.ss_family == AF_INET6)
return ntohs(((const struct sockaddr_in6 *)&listener->addr)->sin6_port);
else
#endif
return ntohs(((const struct sockaddr_in *)&listener->addr)->sin_port);
}
/*
* get_listener_name - return displayable listener name and port
* returns "host.foo.org:6667" for a given listener
*/
const char *
get_listener_name(const struct Listener *listener)
{
static char buf[HOSTLEN + HOSTLEN + PORTNAMELEN + 4];
s_assert(NULL != listener);
if(listener == NULL)
return NULL;
rb_snprintf(buf, sizeof(buf), "%s[%s/%u]",
me.name, listener->name, get_listener_port(listener));
return buf;
}
/*
* show_ports - send port listing to a client
* inputs - pointer to client to show ports to
* output - none
* side effects - show ports
*/
void
show_ports(struct Client *source_p)
{
struct Listener *listener = 0;
for (listener = ListenerPollList; listener; listener = listener->next)
{
sendto_one_numeric(source_p, RPL_STATSPLINE,
form_str(RPL_STATSPLINE), 'P',
get_listener_port(listener),
IsOperAdmin(source_p) ? listener->name : me.name,
listener->ref_count, (listener->active) ? "active" : "disabled",
listener->ssl ? " ssl" : "");
}
}
/*
* inetport - create a listener socket in the AF_INET or AF_INET6 domain,
* bind it to the port given in 'port' and listen to it
* returns true (1) if successful false (0) on error.
*
* If the operating system has a define for SOMAXCONN, use it, otherwise
* use RATBOX_SOMAXCONN
*/
#ifdef SOMAXCONN
#undef RATBOX_SOMAXCONN
#define RATBOX_SOMAXCONN SOMAXCONN
#endif
static int
inetport(struct Listener *listener)
{
rb_fde_t *F;
int opt = 1;
const char *errstr;
/*
* At first, open a new socket
*/
F = rb_socket(GET_SS_FAMILY(&listener->addr), SOCK_STREAM, 0, "Listener socket");
#ifdef RB_IPV6
if(listener->addr.ss_family == AF_INET6)
{
struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&listener->addr;
if(!IN6_ARE_ADDR_EQUAL(&in6->sin6_addr, &in6addr_any))
{
rb_inet_ntop(AF_INET6, &in6->sin6_addr, listener->vhost, sizeof(listener->vhost));
listener->name = listener->vhost;
}
} else
#endif
{
struct sockaddr_in *in = (struct sockaddr_in *)&listener->addr;
if(in->sin_addr.s_addr != INADDR_ANY)
{
rb_inet_ntop(AF_INET, &in->sin_addr, listener->vhost, sizeof(listener->vhost));
listener->name = listener->vhost;
}
}
if(F == NULL)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Cannot open socket for listener on port %d",
get_listener_port(listener));
ilog(L_MAIN, "Cannot open socket for listener %s",
get_listener_name(listener));
return 0;
}
else if((maxconnections - 10) < rb_get_fd(F)) /* XXX this is kinda bogus*/
{
ilog_error("no more connections left for listener");
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"No more connections left for listener on port %d",
get_listener_port(listener));
ilog(L_MAIN, "No more connections left for listener %s",
get_listener_name(listener));
rb_close(F);
return 0;
}
/*
* XXX - we don't want to do all this crap for a listener
* set_sock_opts(listener);
*/
if(setsockopt(rb_get_fd(F), SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)))
{
errstr = strerror(rb_get_sockerr(F));
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Cannot set SO_REUSEADDR for listener on port %d: %s",
get_listener_port(listener), errstr);
ilog(L_MAIN, "Cannot set SO_REUSEADDR for listener %s: %s",
get_listener_name(listener), errstr);
rb_close(F);
return 0;
}
/*
* Bind a port to listen for new connections if port is non-null,
* else assume it is already open and try get something from it.
*/
if(bind(rb_get_fd(F), (struct sockaddr *) &listener->addr, GET_SS_LEN(&listener->addr)))
{
errstr = strerror(rb_get_sockerr(F));
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Cannot bind for listener on port %d: %s",
get_listener_port(listener), errstr);
ilog(L_MAIN, "Cannot bind for listener %s: %s",
get_listener_name(listener), errstr);
rb_close(F);
return 0;
}
if(rb_listen(F, RATBOX_SOMAXCONN, listener->defer_accept))
{
errstr = strerror(rb_get_sockerr(F));
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Cannot listen() for listener on port %d: %s",
get_listener_port(listener), errstr);
ilog(L_MAIN, "Cannot listen() for listener %s: %s",
get_listener_name(listener), errstr);
rb_close(F);
return 0;
}
listener->F = F;
rb_accept_tcp(listener->F, accept_precallback, accept_callback, listener);
return 1;
}
static struct Listener *
find_listener(struct rb_sockaddr_storage *addr)
{
struct Listener *listener = NULL;
struct Listener *last_closed = NULL;
for (listener = ListenerPollList; listener; listener = listener->next)
{
if(addr->ss_family != listener->addr.ss_family)
continue;
switch(addr->ss_family)
{
case AF_INET:
{
struct sockaddr_in *in4 = (struct sockaddr_in *)addr;
struct sockaddr_in *lin4 = (struct sockaddr_in *)&listener->addr;
if(in4->sin_addr.s_addr == lin4->sin_addr.s_addr &&
in4->sin_port == lin4->sin_port )
{
if(listener->F == NULL)
last_closed = listener;
else
return(listener);
}
break;
}
#ifdef RB_IPV6
case AF_INET6:
{
struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr;
struct sockaddr_in6 *lin6 =(struct sockaddr_in6 *)&listener->addr;
if(IN6_ARE_ADDR_EQUAL(&in6->sin6_addr, &lin6->sin6_addr) &&
in6->sin6_port == lin6->sin6_port)
{
if(listener->F == NULL)
last_closed = listener;
else
return(listener);
}
break;
}
#endif
default:
break;
}
}
return last_closed;
}
/*
* add_listener- create a new listener
* port - the port number to listen on
* vhost_ip - if non-null must contain a valid IP address string in
* the format "255.255.255.255"
*/
void
add_listener(int port, const char *vhost_ip, int family, int ssl, int defer_accept)
{
struct Listener *listener;
struct rb_sockaddr_storage vaddr;
/*
* if no port in conf line, don't bother
*/
if(port == 0)
return;
memset(&vaddr, 0, sizeof(vaddr));
vaddr.ss_family = family;
if(vhost_ip != NULL)
{
if(family == AF_INET)
{
if(rb_inet_pton(family, vhost_ip, &((struct sockaddr_in *)&vaddr)->sin_addr) <= 0)
return;
}
#ifdef RB_IPV6
else
{
if(rb_inet_pton(family, vhost_ip, &((struct sockaddr_in6 *)&vaddr)->sin6_addr) <= 0)
return;
}
#endif
} else
{
switch(family)
{
case AF_INET:
((struct sockaddr_in *)&vaddr)->sin_addr.s_addr = INADDR_ANY;
break;
#ifdef RB_IPV6
case AF_INET6:
memcpy(&((struct sockaddr_in6 *)&vaddr)->sin6_addr, &in6addr_any, sizeof(struct in6_addr));
break;
default:
return;
#endif
}
}
switch(family)
{
case AF_INET:
SET_SS_LEN(&vaddr, sizeof(struct sockaddr_in));
((struct sockaddr_in *)&vaddr)->sin_port = htons(port);
break;
#ifdef RB_IPV6
case AF_INET6:
SET_SS_LEN(&vaddr, sizeof(struct sockaddr_in6));
((struct sockaddr_in6 *)&vaddr)->sin6_port = htons(port);
break;
#endif
default:
break;
}
if((listener = find_listener(&vaddr)))
{
if(listener->F != NULL)
return;
}
else
{
listener = make_listener(&vaddr);
listener->next = ListenerPollList;
ListenerPollList = listener;
}
listener->F = NULL;
listener->ssl = ssl;
listener->defer_accept = defer_accept;
if(inetport(listener))
listener->active = 1;
else
close_listener(listener);
}
/*
* close_listener - close a single listener
*/
void
close_listener(struct Listener *listener)
{
s_assert(listener != NULL);
if(listener == NULL)
return;
if(listener->F != NULL)
{
rb_close(listener->F);
listener->F = NULL;
}
listener->active = 0;
if(listener->ref_count)
return;
free_listener(listener);
}
/*
* close_listeners - close and free all listeners that are not being used
*/
void
close_listeners()
{
struct Listener *listener;
struct Listener *listener_next = 0;
/*
* close all 'extra' listening ports we have
*/
for (listener = ListenerPollList; listener; listener = listener_next)
{
listener_next = listener->next;
close_listener(listener);
}
}
#define DLINE_WARNING "ERROR :You have been D-lined.\r\n"
/*
* add_connection - creates a client which has just connected to us on
* the given fd. The sockhost field is initialized with the ip# of the host.
* The client is sent to the auth module for verification, and not put in
* any client list yet.
*/
static void
add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, struct sockaddr *lai)
{
struct Client *new_client;
s_assert(NULL != listener);
/*
* get the client socket name from the socket
* the client has already been checked out in accept_connection
*/
new_client = make_client(NULL);
new_client->localClient->F = F;
memcpy(&new_client->localClient->ip, sai, sizeof(struct rb_sockaddr_storage));
memcpy(&new_client->preClient->lip, lai, sizeof(struct rb_sockaddr_storage));
/*
* copy address to 'sockhost' as a string, copy it to host too
* so we have something valid to put into error messages...
*/
rb_inet_ntop_sock((struct sockaddr *)&new_client->localClient->ip, new_client->sockhost,
sizeof(new_client->sockhost));
rb_strlcpy(new_client->host, new_client->sockhost, sizeof(new_client->host));
if (listener->ssl)
{
rb_fde_t *xF[2];
if(rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF[0], &xF[1], "Incoming ssld Connection") == -1)
{
SetIOError(new_client);
exit_client(new_client, new_client, new_client, "Fatal Error");
return;
}
new_client->localClient->ssl_ctl = start_ssld_accept(F, xF[1], new_client->localClient->connid); /* this will close F for us */
if(new_client->localClient->ssl_ctl == NULL)
{
SetIOError(new_client);
exit_client(new_client, new_client, new_client, "Service Unavailable");
return;
}
F = xF[0];
new_client->localClient->F = F;
SetSSL(new_client);
}
new_client->localClient->listener = listener;
++listener->ref_count;
start_auth(new_client);
}
static const char *toofast = "ERROR :Reconnecting too fast, throttled.\r\n";
static int
accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, void *data)
{
struct Listener *listener = (struct Listener *)data;
char buf[BUFSIZE];
struct ConfItem *aconf;
static time_t last_oper_notice = 0;
int len;
if(listener->ssl && (!ircd_ssl_ok || !get_ssld_count()))
{
rb_close(F);
return 0;
}
if((maxconnections - 10) < rb_get_fd(F)) /* XXX this is kinda bogus */
{
++ServerStats.is_ref;
/*
* slow down the whining to opers bit
*/
if((last_oper_notice + 20) <= rb_current_time())
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"All connections in use. (%s)",
get_listener_name(listener));
last_oper_notice = rb_current_time();
}
rb_write(F, "ERROR :All connections in use\r\n", 31);
rb_close(F);
return 0;
}
aconf = find_dline(addr, addr->sa_family);
if(aconf != NULL && (aconf->status & CONF_EXEMPTDLINE))
return 1;
/* Do an initial check we aren't connecting too fast or with too many
* from this IP... */
if(aconf != NULL)
{
ServerStats.is_ref++;
if(ConfigFileEntry.dline_with_reason)
{
len = rb_snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", get_user_ban_reason(aconf));
if (len >= (int)(sizeof(buf)-1))
{
buf[sizeof(buf) - 3] = '\r';
buf[sizeof(buf) - 2] = '\n';
buf[sizeof(buf) - 1] = '\0';
}
}
else
strcpy(buf, "ERROR :You have been D-lined.\r\n");
rb_write(F, buf, strlen(buf));
rb_close(F);
return 0;
}
if(check_reject(F, addr))
return 0;
if(throttle_add(addr))
{
rb_write(F, toofast, strlen(toofast));
rb_close(F);
return 0;
}
return 1;
}
static void
accept_callback(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t addrlen, void *data)
{
struct Listener *listener = data;
struct rb_sockaddr_storage lip;
unsigned int locallen = sizeof(struct rb_sockaddr_storage);
ServerStats.is_ac++;
if(getsockname(rb_get_fd(F), (struct sockaddr *) &lip, &locallen) < 0)
{
/* this can fail if the connection disappeared in the meantime */
rb_close(F);
return;
}
add_connection(listener, F, addr, (struct sockaddr *)&lip);
}

930
src/modules.c Normal file
View file

@ -0,0 +1,930 @@
/*
* ircd-ratbox: A slightly useful ircd.
* modules.c: A module loader.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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
*
* $Id: modules.c 3161 2007-01-25 07:23:01Z nenolod $
*/
#include "stdinc.h"
#include "modules.h"
#include "logger.h"
#include "ircd.h"
#include "client.h"
#include "send.h"
#include "s_conf.h"
#include "s_newconf.h"
#include "numeric.h"
#include "parse.h"
#include "ircd_defs.h"
#include "match.h"
#ifndef STATIC_MODULES
struct module **modlist = NULL;
static const char *core_module_table[] = {
"m_ban",
"m_die",
"m_error",
"m_join",
"m_kick",
"m_kill",
"m_message",
"m_mode",
"m_nick",
"m_part",
"m_quit",
"m_server",
"m_squit",
NULL
};
#define MODS_INCREMENT 10
int num_mods = 0;
int max_mods = MODS_INCREMENT;
static rb_dlink_list mod_paths;
static int mo_modload(struct Client *, struct Client *, int, const char **);
static int mo_modlist(struct Client *, struct Client *, int, const char **);
static int mo_modreload(struct Client *, struct Client *, int, const char **);
static int mo_modunload(struct Client *, struct Client *, int, const char **);
static int mo_modrestart(struct Client *, struct Client *, int, const char **);
struct Message modload_msgtab = {
"MODLOAD", 0, 0, 0, MFLG_SLOW,
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modload, 2}}
};
struct Message modunload_msgtab = {
"MODUNLOAD", 0, 0, 0, MFLG_SLOW,
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modunload, 2}}
};
struct Message modreload_msgtab = {
"MODRELOAD", 0, 0, 0, MFLG_SLOW,
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modreload, 2}}
};
struct Message modlist_msgtab = {
"MODLIST", 0, 0, 0, MFLG_SLOW,
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modlist, 0}}
};
struct Message modrestart_msgtab = {
"MODRESTART", 0, 0, 0, MFLG_SLOW,
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modrestart, 0}}
};
void
modules_init(void)
{
mod_add_cmd(&modload_msgtab);
mod_add_cmd(&modunload_msgtab);
mod_add_cmd(&modreload_msgtab);
mod_add_cmd(&modlist_msgtab);
mod_add_cmd(&modrestart_msgtab);
/* Add the default paths we look in to the module system --nenolod */
mod_add_path(MODPATH);
mod_add_path(AUTOMODPATH);
}
/* mod_find_path()
*
* input - path
* output - none
* side effects - returns a module path from path
*/
static char *
mod_find_path(const char *path)
{
rb_dlink_node *ptr;
char *mpath;
RB_DLINK_FOREACH(ptr, mod_paths.head)
{
mpath = ptr->data;
if(!strcmp(path, mpath))
return mpath;
}
return NULL;
}
/* mod_add_path
*
* input - path
* ouput -
* side effects - adds path to list
*/
void
mod_add_path(const char *path)
{
char *pathst;
if(mod_find_path(path))
return;
pathst = rb_strdup(path);
rb_dlinkAddAlloc(pathst, &mod_paths);
}
/* mod_clear_paths()
*
* input -
* output -
* side effects - clear the lists of paths
*/
void
mod_clear_paths(void)
{
rb_dlink_node *ptr, *next_ptr;
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, mod_paths.head)
{
rb_free(ptr->data);
rb_free_rb_dlink_node(ptr);
}
mod_paths.head = mod_paths.tail = NULL;
mod_paths.length = 0;
}
/* findmodule_byname
*
* input -
* output -
* side effects -
*/
int
findmodule_byname(const char *name)
{
int i;
for (i = 0; i < num_mods; i++)
{
if(!irccmp(modlist[i]->name, name))
return i;
}
return -1;
}
/* load_all_modules()
*
* input -
* output -
* side effects -
*/
void
load_all_modules(int warn)
{
DIR *system_module_dir = NULL;
struct dirent *ldirent = NULL;
char module_fq_name[PATH_MAX + 1];
int len;
modules_init();
modlist = (struct module **) rb_malloc(sizeof(struct module *) * (MODS_INCREMENT));
max_mods = MODS_INCREMENT;
system_module_dir = opendir(AUTOMODPATH);
if(system_module_dir == NULL)
{
ilog(L_MAIN, "Could not load modules from %s: %s", AUTOMODPATH, strerror(errno));
return;
}
while ((ldirent = readdir(system_module_dir)) != NULL)
{
len = strlen(ldirent->d_name);
if((len > 3) && !strcmp(ldirent->d_name+len-3, SHARED_SUFFIX))
{
(void) rb_snprintf(module_fq_name, sizeof(module_fq_name), "%s/%s", AUTOMODPATH, ldirent->d_name);
(void) load_a_module(module_fq_name, warn, 0);
}
}
(void) closedir(system_module_dir);
}
/* load_core_modules()
*
* input -
* output -
* side effects - core modules are loaded, if any fail, kill ircd
*/
void
load_core_modules(int warn)
{
char module_name[PATH_MAX];
int i;
for (i = 0; core_module_table[i]; i++)
{
rb_snprintf(module_name, sizeof(module_name), "%s/%s%s", MODPATH,
core_module_table[i], SHARED_SUFFIX);
if(load_a_module(module_name, warn, 1) == -1)
{
ilog(L_MAIN,
"Error loading core module %s%s: terminating ircd",
core_module_table[i], SHARED_SUFFIX);
exit(0);
}
}
}
/* load_one_module()
*
* input -
* output -
* side effects -
*/
int
load_one_module(const char *path, int coremodule)
{
char modpath[PATH_MAX];
rb_dlink_node *pathst;
const char *mpath;
struct stat statbuf;
if (server_state_foreground == 1)
inotice("loading module %s ...", path);
RB_DLINK_FOREACH(pathst, mod_paths.head)
{
mpath = pathst->data;
rb_snprintf(modpath, sizeof(modpath), "%s/%s", mpath, path);
if((strstr(modpath, "../") == NULL) && (strstr(modpath, "/..") == NULL))
{
if(stat(modpath, &statbuf) == 0)
{
if(S_ISREG(statbuf.st_mode))
{
/* Regular files only please */
if(coremodule)
return load_a_module(modpath, 1, 1);
else
return load_a_module(modpath, 1, 0);
}
}
}
}
sendto_realops_snomask(SNO_GENERAL, L_ALL, "Cannot locate module %s", path);
return -1;
}
/* load a module .. */
static int
mo_modload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
char *m_bn;
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
me.name, source_p->name, "admin");
return 0;
}
m_bn = rb_basename(parv[1]);
if(findmodule_byname(m_bn) != -1)
{
sendto_one_notice(source_p, ":Module %s is already loaded", m_bn);
rb_free(m_bn);
return 0;
}
load_one_module(parv[1], 0);
rb_free(m_bn);
return 0;
}
/* unload a module .. */
static int
mo_modunload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
char *m_bn;
int modindex;
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
me.name, source_p->name, "admin");
return 0;
}
m_bn = rb_basename(parv[1]);
if((modindex = findmodule_byname(m_bn)) == -1)
{
sendto_one_notice(source_p, ":Module %s is not loaded", m_bn);
rb_free(m_bn);
return 0;
}
if(modlist[modindex]->core == 1)
{
sendto_one_notice(source_p, ":Module %s is a core module and may not be unloaded", m_bn);
rb_free(m_bn);
return 0;
}
if(unload_one_module(m_bn, 1) == -1)
{
sendto_one_notice(source_p, ":Module %s is not loaded", m_bn);
}
rb_free(m_bn);
return 0;
}
/* unload and load in one! */
static int
mo_modreload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
char *m_bn;
int modindex;
int check_core;
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
me.name, source_p->name, "admin");
return 0;
}
m_bn = rb_basename(parv[1]);
if((modindex = findmodule_byname(m_bn)) == -1)
{
sendto_one_notice(source_p, ":Module %s is not loaded", m_bn);
rb_free(m_bn);
return 0;
}
check_core = modlist[modindex]->core;
if(unload_one_module(m_bn, 1) == -1)
{
sendto_one_notice(source_p, ":Module %s is not loaded", m_bn);
rb_free(m_bn);
return 0;
}
if((load_one_module(m_bn, check_core) == -1) && check_core)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Error reloading core module: %s: terminating ircd", m_bn);
ilog(L_MAIN, "Error loading core module %s: terminating ircd", m_bn);
exit(0);
}
rb_free(m_bn);
return 0;
}
/* list modules .. */
static int
mo_modlist(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
int i;
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
me.name, source_p->name, "admin");
return 0;
}
for (i = 0; i < num_mods; i++)
{
if(parc > 1)
{
if(match(parv[1], modlist[i]->name))
{
sendto_one(source_p, form_str(RPL_MODLIST),
me.name, source_p->name,
modlist[i]->name,
(unsigned long)(uintptr_t)modlist[i]->address,
modlist[i]->version, modlist[i]->core ? "(core)" : "");
}
}
else
{
sendto_one(source_p, form_str(RPL_MODLIST),
me.name, source_p->name, modlist[i]->name,
(unsigned long)(uintptr_t)modlist[i]->address,
modlist[i]->version,
modlist[i]->core ? "(core)" : "");
}
}
sendto_one(source_p, form_str(RPL_ENDOFMODLIST), me.name, source_p->name);
return 0;
}
/* unload and reload all modules */
static void
modules_do_restart(void *unused)
{
int modnum = num_mods;
while (num_mods)
unload_one_module(modlist[0]->name, 0);
load_all_modules(0);
load_core_modules(0);
rehash(0);
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Module Restart: %d modules unloaded, %d modules loaded",
modnum, num_mods);
ilog(L_MAIN, "Module Restart: %d modules unloaded, %d modules loaded", modnum, num_mods);
}
static int
mo_modrestart(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
me.name, source_p->name, "admin");
return 0;
}
sendto_one_notice(source_p, ":Reloading all modules");
/*
* If a remote MODRESTART is received, m_encap.so will be reloaded,
* but ms_encap is in the call stack (it indirectly calls this
* function). This will go horribly wrong if m_encap is reloaded to
* a different address.
*
* So, defer the restart to the event loop (above) and return now.
*/
rb_event_addonce("modules_do_restart", modules_do_restart, NULL, 1);
return 0;
}
#ifndef RTLD_NOW
#define RTLD_NOW RTLD_LAZY /* openbsd deficiency */
#endif
#ifndef RTLD_LOCAL
#define RTLD_LOCAL 0
#endif
#ifdef CHARYBDIS_PROFILE
# ifndef RTLD_PROFILE
# warning libdl may not support profiling, sucks. :(
# define RTLD_PROFILE 0
# endif
#endif
static void increase_modlist(void);
#define MODS_INCREMENT 10
static char unknown_ver[] = "<unknown>";
/* This file contains the core functions to use dynamic libraries.
* -TimeMr14C
*/
#ifdef HAVE_MACH_O_DYLD_H
/*
** jmallett's dl*(3) shims for NSModule(3) systems.
*/
#include <mach-o/dyld.h>
#ifndef HAVE_DLOPEN
#ifndef RTLD_LAZY
#define RTLD_LAZY 2185 /* built-in dl*(3) don't care */
#endif
void undefinedErrorHandler(const char *);
NSModule multipleErrorHandler(NSSymbol, NSModule, NSModule);
void linkEditErrorHandler(NSLinkEditErrors, int, const char *, const char *);
char *dlerror(void);
void *dlopen(char *, int);
int dlclose(void *);
void *dlsym(void *, char *);
static int firstLoad = TRUE;
static int myDlError;
static char *myErrorTable[] = { "Loading file as object failed\n",
"Loading file as object succeeded\n",
"Not a valid shared object\n",
"Architecture of object invalid on this architecture\n",
"Invalid or corrupt image\n",
"Could not access object\n",
"NSCreateObjectFileImageFromFile failed\n",
NULL
};
void
undefinedErrorHandler(const char *symbolName)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL, "Undefined symbol: %s", symbolName);
ilog(L_MAIN, "Undefined symbol: %s", symbolName);
return;
}
NSModule
multipleErrorHandler(NSSymbol s, NSModule old, NSModule new)
{
/* XXX
** This results in substantial leaking of memory... Should free one
** module, maybe?
*/
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Symbol `%s' found in `%s' and `%s'",
NSNameOfSymbol(s), NSNameOfModule(old), NSNameOfModule(new));
ilog(L_MAIN, "Symbol `%s' found in `%s' and `%s'",
NSNameOfSymbol(s), NSNameOfModule(old), NSNameOfModule(new));
/* We return which module should be considered valid, I believe */
return new;
}
void
linkEditErrorHandler(NSLinkEditErrors errorClass, int errnum,
const char *fileName, const char *errorString)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Link editor error: %s for %s", errorString, fileName);
ilog(L_MAIN, "Link editor error: %s for %s", errorString, fileName);
return;
}
char *
dlerror(void)
{
return myDlError == NSObjectFileImageSuccess ? NULL : myErrorTable[myDlError % 7];
}
void *
dlopen(char *filename, int unused)
{
NSObjectFileImage myImage;
NSModule myModule;
if(firstLoad)
{
/*
** If we are loading our first symbol (huzzah!) we should go ahead
** and install link editor error handling!
*/
NSLinkEditErrorHandlers linkEditorErrorHandlers;
linkEditorErrorHandlers.undefined = undefinedErrorHandler;
linkEditorErrorHandlers.multiple = multipleErrorHandler;
linkEditorErrorHandlers.linkEdit = linkEditErrorHandler;
NSInstallLinkEditErrorHandlers(&linkEditorErrorHandlers);
firstLoad = FALSE;
}
myDlError = NSCreateObjectFileImageFromFile(filename, &myImage);
if(myDlError != NSObjectFileImageSuccess)
{
return NULL;
}
myModule = NSLinkModule(myImage, filename, NSLINKMODULE_OPTION_PRIVATE);
return (void *) myModule;
}
int
dlclose(void *myModule)
{
NSUnLinkModule(myModule, FALSE);
return 0;
}
void *
dlsym(void *myModule, char *mySymbolName)
{
NSSymbol mySymbol;
mySymbol = NSLookupSymbolInModule((NSModule) myModule, mySymbolName);
return NSAddressOfSymbol(mySymbol);
}
#endif
#endif
/*
* HPUX dl compat functions
*/
#if defined(HAVE_SHL_LOAD) && !defined(HAVE_DLOPEN)
#define RTLD_LAZY BIND_DEFERRED
#define RTLD_GLOBAL DYNAMIC_PATH
#define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
#define dlclose(handle) shl_unload((shl_t)(handle))
#define dlsym(handle,name) hpux_dlsym(handle,name)
#define dlerror() strerror(errno)
static void *
hpux_dlsym(void *handle, char *name)
{
void *sym_addr;
if(!shl_findsym((shl_t *) & handle, name, TYPE_UNDEFINED, &sym_addr))
return sym_addr;
return NULL;
}
#endif
/* unload_one_module()
*
* inputs - name of module to unload
* - 1 to say modules unloaded, 0 to not
* output - 0 if successful, -1 if error
* side effects - module is unloaded
*/
int
unload_one_module(const char *name, int warn)
{
int modindex;
if((modindex = findmodule_byname(name)) == -1)
return -1;
/*
** XXX - The type system in C does not allow direct conversion between
** data and function pointers, but as it happens, most C compilers will
** safely do this, however it is a theoretical overlow to cast as we
** must do here. I have library functions to take care of this, but
** despite being more "correct" for the C language, this is more
** practical. Removing the abuse of the ability to cast ANY pointer
** to and from an integer value here will break some compilers.
** -jmallett
*/
/* Left the comment in but the code isn't here any more -larne */
switch (modlist[modindex]->mapi_version)
{
case 1:
{
struct mapi_mheader_av1 *mheader = modlist[modindex]->mapi_header;
if(mheader->mapi_command_list)
{
struct Message **m;
for (m = mheader->mapi_command_list; *m; ++m)
mod_del_cmd(*m);
}
/* hook events are never removed, we simply lose the
* ability to call them --fl
*/
if(mheader->mapi_hfn_list)
{
mapi_hfn_list_av1 *m;
for (m = mheader->mapi_hfn_list; m->hapi_name; ++m)
remove_hook(m->hapi_name, m->fn);
}
if(mheader->mapi_unregister)
mheader->mapi_unregister();
break;
}
default:
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Unknown/unsupported MAPI version %d when unloading %s!",
modlist[modindex]->mapi_version, modlist[modindex]->name);
ilog(L_MAIN, "Unknown/unsupported MAPI version %d when unloading %s!",
modlist[modindex]->mapi_version, modlist[modindex]->name);
break;
}
dlclose(modlist[modindex]->address);
rb_free(modlist[modindex]->name);
memmove(&modlist[modindex], &modlist[modindex + 1],
sizeof(struct module *) * ((num_mods - 1) - modindex));
if(num_mods != 0)
num_mods--;
if(warn == 1)
{
ilog(L_MAIN, "Module %s unloaded", name);
sendto_realops_snomask(SNO_GENERAL, L_ALL, "Module %s unloaded", name);
}
return 0;
}
/*
* load_a_module()
*
* inputs - path name of module, int to notice, int of core
* output - -1 if error 0 if success
* side effects - loads a module if successful
*/
int
load_a_module(const char *path, int warn, int core)
{
void *tmpptr = NULL;
char *mod_basename;
const char *ver;
int *mapi_version;
mod_basename = rb_basename(path);
#ifdef CHARYBDIS_PROFILE
tmpptr = dlopen(path, RTLD_NOW | RTLD_LOCAL | RTLD_PROFILE);
#else
tmpptr = dlopen(path, RTLD_NOW | RTLD_LOCAL);
#endif
if(tmpptr == NULL)
{
const char *err = dlerror();
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Error loading module %s: %s", mod_basename, err);
ilog(L_MAIN, "Error loading module %s: %s", mod_basename, err);
rb_free(mod_basename);
return -1;
}
/*
* _mheader is actually a struct mapi_mheader_*, but mapi_version
* is always the first member of this structure, so we treate it
* as a single int in order to determine the API version.
* -larne.
*/
mapi_version = (int *) dlsym(tmpptr, "_mheader");
if((mapi_version == NULL
&& (mapi_version = (int *) dlsym(tmpptr, "__mheader")) == NULL)
|| MAPI_MAGIC(*mapi_version) != MAPI_MAGIC_HDR)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Data format error: module %s has no MAPI header.",
mod_basename);
ilog(L_MAIN, "Data format error: module %s has no MAPI header.", mod_basename);
(void) dlclose(tmpptr);
rb_free(mod_basename);
return -1;
}
switch (MAPI_VERSION(*mapi_version))
{
case 1:
{
struct mapi_mheader_av1 *mheader = (struct mapi_mheader_av1 *)(void *)mapi_version; /* see above */
if(mheader->mapi_register && (mheader->mapi_register() == -1))
{
ilog(L_MAIN, "Module %s indicated failure during load.",
mod_basename);
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Module %s indicated failure during load.",
mod_basename);
dlclose(tmpptr);
rb_free(mod_basename);
return -1;
}
if(mheader->mapi_command_list)
{
struct Message **m;
for (m = mheader->mapi_command_list; *m; ++m)
mod_add_cmd(*m);
}
if(mheader->mapi_hook_list)
{
mapi_hlist_av1 *m;
for (m = mheader->mapi_hook_list; m->hapi_name; ++m)
*m->hapi_id = register_hook(m->hapi_name);
}
if(mheader->mapi_hfn_list)
{
mapi_hfn_list_av1 *m;
for (m = mheader->mapi_hfn_list; m->hapi_name; ++m)
add_hook(m->hapi_name, m->fn);
}
ver = mheader->mapi_module_version;
break;
}
default:
ilog(L_MAIN, "Module %s has unknown/unsupported MAPI version %d.",
mod_basename, MAPI_VERSION(*mapi_version));
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Module %s has unknown/unsupported MAPI version %d.",
mod_basename, *mapi_version);
dlclose(tmpptr);
rb_free(mod_basename);
return -1;
}
if(ver == NULL)
ver = unknown_ver;
increase_modlist();
modlist[num_mods] = rb_malloc(sizeof(struct module));
modlist[num_mods]->address = tmpptr;
modlist[num_mods]->version = ver;
modlist[num_mods]->core = core;
modlist[num_mods]->name = rb_strdup(mod_basename);
modlist[num_mods]->mapi_header = mapi_version;
modlist[num_mods]->mapi_version = MAPI_VERSION(*mapi_version);
num_mods++;
if(warn == 1)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Module %s [version: %s; MAPI version: %d] loaded at 0x%lx",
mod_basename, ver, MAPI_VERSION(*mapi_version),
(unsigned long) tmpptr);
ilog(L_MAIN, "Module %s [version: %s; MAPI version: %d] loaded at 0x%lx",
mod_basename, ver, MAPI_VERSION(*mapi_version), (unsigned long) tmpptr);
}
rb_free(mod_basename);
return 0;
}
/*
* increase_modlist
*
* inputs - NONE
* output - NONE
* side effects - expand the size of modlist if necessary
*/
static void
increase_modlist(void)
{
struct module **new_modlist = NULL;
if((num_mods + 1) < max_mods)
return;
new_modlist = (struct module **) rb_malloc(sizeof(struct module *) *
(max_mods + MODS_INCREMENT));
memcpy((void *) new_modlist, (void *) modlist, sizeof(struct module *) * num_mods);
rb_free(modlist);
modlist = new_modlist;
max_mods += MODS_INCREMENT;
}
#else /* STATIC_MODULES */
/* load_all_modules()
*
* input -
* output -
* side effects - all the msgtabs are added for static modules
*/
void
load_all_modules(int warn)
{
load_static_modules();
}
#endif /* STATIC_MODULES */

2721
src/newconf.c Normal file

File diff suppressed because it is too large Load diff

755
src/parse.c Normal file
View file

@ -0,0 +1,755 @@
/*
* charybdis: an advanced ircd.
* parse.c: The message parser.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
* Copyright (C) 2007 William Pitcock
*
* 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
*
* $Id: parse.c 3177 2007-02-01 00:19:14Z jilles $
*/
#include "stdinc.h"
#include "parse.h"
#include "client.h"
#include "channel.h"
#include "common.h"
#include "hash.h"
#include "match.h"
#include "ircd.h"
#include "numeric.h"
#include "logger.h"
#include "s_stats.h"
#include "send.h"
#include "msg.h"
#include "s_conf.h"
#include "s_serv.h"
#include "packet.h"
#include "s_assert.h"
static struct Dictionary *cmd_dict = NULL;
struct Dictionary *alias_dict = NULL;
struct Dictionary *fakechannel_dict = NULL;
/* parv[0] is not used, and parv[LAST] == NULL */
static char *para[MAXPARA + 2];
static void cancel_clients(struct Client *, struct Client *);
static void remove_unknown(struct Client *, char *, char *);
static void do_numeric(char[], struct Client *, struct Client *, int, char **);
static void do_alias(struct alias_entry *, struct Client *, char *);
static int handle_command(struct Message *, struct Client *, struct Client *, int, const char**);
static char buffer[1024];
/* turn a string into a parc/parv pair */
static inline int
string_to_array(char *string, char **parv)
{
char *p, *buf = string;
int x = 1;
parv[x] = NULL;
while (*buf == ' ') /* skip leading spaces */
buf++;
if(*buf == '\0') /* ignore all-space args */
return x;
do
{
if(*buf == ':') /* Last parameter */
{
buf++;
parv[x++] = buf;
parv[x] = NULL;
return x;
}
else
{
parv[x++] = buf;
parv[x] = NULL;
if((p = strchr(buf, ' ')) != NULL)
{
*p++ = '\0';
buf = p;
}
else
return x;
}
while (*buf == ' ')
buf++;
if(*buf == '\0')
return x;
}
/* we can go upto parv[MAXPARA], as parv[0] is skipped */
while (x < MAXPARA);
if(*p == ':')
p++;
parv[x++] = p;
parv[x] = NULL;
return x;
}
/* parse()
*
* given a raw buffer, parses it and generates parv and parc
*/
void
parse(struct Client *client_p, char *pbuffer, char *bufend)
{
struct Client *from = client_p;
char *sender;
char *ch;
char *s;
char *end;
int i = 1;
char *numeric = 0;
struct Message *mptr;
s_assert(MyConnect(client_p));
s_assert(client_p->localClient->F != NULL);
if(IsAnyDead(client_p))
return;
for (ch = pbuffer; *ch == ' '; ch++) /* skip spaces */
/* null statement */ ;
para[0] = from->name;
if(*ch == ':')
{
ch++;
/* point sender to the sender param */
sender = ch;
if((s = strchr(ch, ' ')))
{
*s = '\0';
s++;
ch = s;
}
if(*sender && IsServer(client_p))
{
from = find_client(sender);
/* didnt find any matching client, issue a kill */
if(from == NULL)
{
ServerStats.is_unpf++;
remove_unknown(client_p, sender, pbuffer);
return;
}
para[0] = from->name;
/* fake direction, hmm. */
if(from->from != client_p)
{
ServerStats.is_wrdi++;
cancel_clients(client_p, from);
return;
}
}
while (*ch == ' ')
ch++;
}
if(*ch == '\0')
{
ServerStats.is_empt++;
return;
}
/* at this point there must be some sort of command parameter */
/*
* Extract the command code from the packet. Point s to the end
* of the command code and calculate the length using pointer
* arithmetic. Note: only need length for numerics and *all*
* numerics must have parameters and thus a space after the command
* code. -avalon
*/
/* EOB is 3 chars long but is not a numeric */
if(*(ch + 3) == ' ' && /* ok, lets see if its a possible numeric.. */
IsDigit(*ch) && IsDigit(*(ch + 1)) && IsDigit(*(ch + 2)))
{
mptr = NULL;
numeric = ch;
ServerStats.is_num++;
s = ch + 3; /* I know this is ' ' from above if */
*s++ = '\0'; /* blow away the ' ', and point s to next part */
}
else
{
int ii = 0;
if((s = strchr(ch, ' ')))
*s++ = '\0';
mptr = irc_dictionary_retrieve(cmd_dict, ch);
/* no command or its encap only, error */
if(!mptr || !mptr->cmd)
{
/*
* Note: Give error message *only* to recognized
* persons. It's a nightmare situation to have
* two programs sending "Unknown command"'s or
* equivalent to each other at full blast....
* If it has got to person state, it at least
* seems to be well behaving. Perhaps this message
* should never be generated, though... --msa
* Hm, when is the buffer empty -- if a command
* code has been found ?? -Armin
*/
if(pbuffer[0] != '\0')
{
if (IsPerson(client_p))
{
struct alias_entry *aptr = irc_dictionary_retrieve(alias_dict, ch);
if (aptr != NULL)
{
do_alias(aptr, client_p, s);
return;
}
}
if(IsPerson(from))
{
sendto_one(from, form_str(ERR_UNKNOWNCOMMAND),
me.name, from->name, ch);
}
}
ServerStats.is_unco++;
return;
}
ii = bufend - ((s) ? s : ch);
mptr->bytes += ii;
}
end = bufend - 1;
/* XXX this should be done before parse() is called */
if(*end == '\n')
*end-- = '\0';
if(*end == '\r')
*end = '\0';
if(s != NULL)
i = string_to_array(s, para);
if(mptr == NULL)
{
do_numeric(numeric, client_p, from, i, para);
return;
}
if(handle_command(mptr, client_p, from, i, /* XXX discards const!!! */ (const char **)(void *)para) < -1)
{
char *p;
for (p = pbuffer; p <= end; p += 8)
{
/* HACK HACK */
/* Its expected this nasty code can be removed
* or rewritten later if still needed.
*/
if((unsigned long) (p + 8) > (unsigned long) end)
{
for (; p <= end; p++)
{
ilog(L_MAIN, "%02x |%c", p[0], p[0]);
}
}
else
ilog(L_MAIN,
"%02x %02x %02x %02x %02x %02x %02x %02x |%c%c%c%c%c%c%c%c",
p[0], p[1], p[2], p[3], p[4], p[5],
p[6], p[7], p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
}
}
}
/*
* handle_command
*
* inputs - pointer to message block
* - pointer to client
* - pointer to client message is from
* - count of number of args
* - pointer to argv[] array
* output - -1 if error from server
* side effects -
*/
static int
handle_command(struct Message *mptr, struct Client *client_p,
struct Client *from, int i, const char** hpara)
{
struct MessageEntry ehandler;
MessageHandler handler = 0;
char squitreason[80];
if(IsAnyDead(client_p))
return -1;
if(IsServer(client_p))
mptr->rcount++;
mptr->count++;
/* New patch to avoid server flooding from unregistered connects
- Pie-Man 07/27/2000 */
if(!IsRegistered(client_p))
{
/* if its from a possible server connection
* ignore it.. more than likely its a header thats sneaked through
*/
if(IsAnyServer(client_p) && !(mptr->flags & MFLG_UNREG))
return (1);
}
ehandler = mptr->handlers[from->handler];
handler = ehandler.handler;
/* check right amount of params is passed... --is */
if(i < ehandler.min_para ||
(ehandler.min_para && EmptyString(hpara[ehandler.min_para - 1])))
{
if(!IsServer(client_p))
{
sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS),
me.name,
EmptyString(client_p->name) ? "*" : client_p->name,
mptr->cmd);
if(MyClient(client_p))
return (1);
else
return (-1);
}
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Dropping server %s due to (invalid) command '%s'"
" with only %d arguments (expecting %d).",
client_p->name, mptr->cmd, i, ehandler.min_para);
ilog(L_SERVER,
"Insufficient parameters (%d < %d) for command '%s' from %s.",
i, ehandler.min_para, mptr->cmd, client_p->name);
rb_snprintf(squitreason, sizeof squitreason,
"Insufficient parameters (%d < %d) for command '%s'",
i, ehandler.min_para, mptr->cmd);
exit_client(client_p, client_p, client_p, squitreason);
return (-1);
}
(*handler) (client_p, from, i, hpara);
return (1);
}
void
handle_encap(struct Client *client_p, struct Client *source_p,
const char *command, int parc, const char *parv[])
{
struct Message *mptr;
struct MessageEntry ehandler;
MessageHandler handler = 0;
mptr = irc_dictionary_retrieve(cmd_dict, command);
if(mptr == NULL || mptr->cmd == NULL)
return;
ehandler = mptr->handlers[ENCAP_HANDLER];
handler = ehandler.handler;
if(parc < ehandler.min_para ||
(ehandler.min_para && EmptyString(parv[ehandler.min_para - 1])))
return;
(*handler) (client_p, source_p, parc, parv);
}
/*
* clear_hash_parse()
*
* inputs -
* output - NONE
* side effects - MUST MUST be called at startup ONCE before
* any other keyword hash routine is used.
*
*/
void
clear_hash_parse()
{
cmd_dict = irc_dictionary_create(strcasecmp);
}
/* mod_add_cmd
*
* inputs - command name
* - pointer to struct Message
* output - none
* side effects - load this one command name
* msg->count msg->bytes is modified in place, in
* modules address space. Might not want to do that...
*/
void
mod_add_cmd(struct Message *msg)
{
s_assert(msg != NULL);
if(msg == NULL)
return;
if (irc_dictionary_find(cmd_dict, msg->cmd) != NULL)
return;
msg->count = 0;
msg->rcount = 0;
msg->bytes = 0;
irc_dictionary_add(cmd_dict, msg->cmd, msg);
}
/* mod_del_cmd
*
* inputs - command name
* output - none
* side effects - unload this one command name
*/
void
mod_del_cmd(struct Message *msg)
{
s_assert(msg != NULL);
if(msg == NULL)
return;
irc_dictionary_delete(cmd_dict, msg->cmd);
}
/*
* report_messages
*
* inputs - pointer to client to report to
* output - NONE
* side effects - NONE
*/
void
report_messages(struct Client *source_p)
{
struct DictionaryIter iter;
struct Message *msg;
struct alias_entry *amsg;
DICTIONARY_FOREACH(msg, &iter, cmd_dict)
{
s_assert(msg->cmd != NULL);
sendto_one_numeric(source_p, RPL_STATSCOMMANDS,
form_str(RPL_STATSCOMMANDS),
msg->cmd, msg->count,
msg->bytes, msg->rcount);
}
DICTIONARY_FOREACH(amsg, &iter, alias_dict)
{
s_assert(amsg->name != NULL);
sendto_one_numeric(source_p, RPL_STATSCOMMANDS,
form_str(RPL_STATSCOMMANDS),
amsg->name, amsg->hits, 0L, 0);
}
}
/* cancel_clients()
*
* inputs - client who sent us the message, client with fake
* direction
* outputs - a given warning about the fake direction
* side effects -
*/
static void
cancel_clients(struct Client *client_p, struct Client *source_p)
{
/* ok, fake prefix happens naturally during a burst on a nick
* collision with TS5, we cant kill them because one client has to
* survive, so we just send an error.
*/
if(IsServer(source_p) || IsMe(source_p))
{
sendto_realops_snomask(SNO_DEBUG, L_ALL,
"Message for %s[%s] from %s",
source_p->name, source_p->from->name,
client_p->name);
}
else
{
sendto_realops_snomask(SNO_DEBUG, L_ALL,
"Message for %s[%s@%s!%s] from %s (TS, ignored)",
source_p->name,
source_p->username,
source_p->host,
source_p->from->name,
client_p->name);
}
}
/* remove_unknown()
*
* inputs - client who gave us message, supposed sender, buffer
* output -
* side effects - kills issued for clients, squits for servers
*/
static void
remove_unknown(struct Client *client_p, char *lsender, char *lbuffer)
{
int slen = strlen(lsender);
char sid[4];
struct Client *server;
/* meepfoo is a nickname (ignore)
* #XXXXXXXX is a UID (KILL)
* #XX is a SID (SQUIT)
* meep.foo is a server (SQUIT)
*/
if((IsDigit(lsender[0]) && slen == 3) ||
(strchr(lsender, '.') != NULL))
{
sendto_realops_snomask(SNO_DEBUG, L_ALL,
"Unknown prefix (%s) from %s, Squitting %s",
lbuffer, client_p->name, lsender);
sendto_one(client_p,
":%s SQUIT %s :(Unknown prefix (%s) from %s)",
get_id(&me, client_p), lsender,
lbuffer, client_p->name);
}
else if(!IsDigit(lsender[0]))
;
else if(slen != 9)
sendto_realops_snomask(SNO_DEBUG, L_ALL,
"Invalid prefix (%s) from %s",
lbuffer, client_p->name);
else
{
memcpy(sid, lsender, 3);
sid[3] = '\0';
server = find_server(NULL, sid);
if (server != NULL && server->from == client_p)
sendto_one(client_p, ":%s KILL %s :%s (Unknown Client)",
get_id(&me, client_p), lsender, me.name);
}
}
/*
*
* parc number of arguments ('sender' counted as one!)
* parv[1]..parv[parc-1]
* pointers to additional parameters, this is a NULL
* terminated list (parv[parc] == NULL).
*
* *WARNING*
* Numerics are mostly error reports. If there is something
* wrong with the message, just *DROP* it! Don't even think of
* sending back a neat error message -- big danger of creating
* a ping pong error message...
*/
static void
do_numeric(char numeric[], struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
struct Client *target_p;
struct Channel *chptr;
if(parc < 2 || !IsServer(source_p))
return;
/* Remap low number numerics. */
if(numeric[0] == '0')
numeric[0] = '1';
/*
* Prepare the parameter portion of the message into 'buffer'.
* (Because the buffer is twice as large as the message buffer
* for the socket, no overflow can occur here... ...on current
* assumptions--bets are off, if these are changed --msa)
* Note: if buffer is non-empty, it will begin with SPACE.
*/
if(parc > 1)
{
char *t = buffer; /* Current position within the buffer */
int i;
int tl; /* current length of presently being built string in t */
for (i = 2; i < (parc - 1); i++)
{
tl = rb_sprintf(t, " %s", parv[i]);
t += tl;
}
rb_sprintf(t, " :%s", parv[parc - 1]);
}
if((target_p = find_client(parv[1])) != NULL)
{
if(IsMe(target_p))
{
/*
* We shouldn't get numerics sent to us,
* any numerics we do get indicate a bug somewhere..
*/
/* ugh. this is here because of nick collisions. when two servers
* relink, they burst each other their nicks, then perform collides.
* if there is a nick collision, BOTH servers will kill their own
* nicks, and BOTH will kill the other servers nick, which wont exist,
* because it will have been already killed by the local server.
*
* unfortunately, as we cant guarantee other servers will do the
* "right thing" on a nick collision, we have to keep both kills.
* ergo we need to ignore ERR_NOSUCHNICK. --fl_
*/
/* quick comment. This _was_ tried. i.e. assume the other servers
* will do the "right thing" and kill a nick that is colliding.
* unfortunately, it did not work. --Dianora
*/
/* note, now we send PING on server connect, we can
* also get ERR_NOSUCHSERVER..
*/
if(atoi(numeric) != ERR_NOSUCHNICK &&
atoi(numeric) != ERR_NOSUCHSERVER)
sendto_realops_snomask(SNO_GENERAL, L_ADMIN,
"*** %s(via %s) sent a %s numeric to me: %s",
source_p->name,
client_p->name, numeric, buffer);
return;
}
else if(target_p->from == client_p)
{
/* This message changed direction (nick collision?)
* ignore it.
*/
return;
}
/* csircd will send out unknown umode flag for +a (admin), drop it here. */
if((atoi(numeric) == ERR_UMODEUNKNOWNFLAG) && MyClient(target_p))
return;
/* Fake it for server hiding, if its our client */
sendto_one(target_p, ":%s %s %s%s",
get_id(source_p, target_p), numeric,
get_id(target_p, target_p), buffer);
return;
}
else if((chptr = find_channel(parv[1])) != NULL)
sendto_channel_flags(client_p, ALL_MEMBERS, source_p, chptr,
"%s %s%s",
numeric, chptr->chname, buffer);
}
static void do_alias(struct alias_entry *aptr, struct Client *source_p, char *text)
{
char *p;
struct Client *target_p;
if (!IsFloodDone(source_p) && source_p->localClient->receiveM > 20)
flood_endgrace(source_p);
p = strchr(aptr->target, '@');
if (p != NULL)
{
/* user@server */
target_p = find_server(NULL, p + 1);
if (target_p != NULL && IsMe(target_p))
target_p = NULL;
}
else
{
/* nick, must be +S */
target_p = find_named_person(aptr->target);
if (target_p != NULL && !IsService(target_p))
target_p = NULL;
}
if (target_p == NULL)
{
sendto_one_numeric(source_p, ERR_SERVICESDOWN, form_str(ERR_SERVICESDOWN), aptr->target);
return;
}
if (text != NULL && *text == ':')
text++;
if (text == NULL || *text == '\0')
{
sendto_one(source_p, form_str(ERR_NOTEXTTOSEND), me.name, source_p->name);
return;
}
/* increment the hitcounter on this alias */
aptr->hits++;
sendto_one(target_p, ":%s PRIVMSG %s :%s",
get_id(source_p, target_p),
p != NULL ? aptr->target : get_id(target_p, target_p),
text);
}
int
m_not_oper(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
sendto_one_numeric(source_p, ERR_NOPRIVILEGES, form_str(ERR_NOPRIVILEGES));
return 0;
}
int
m_unregistered(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
/* bit of a hack.
* I don't =really= want to waste a bit in a flag
* number_of_nick_changes is only really valid after the client
* is fully registered..
*/
if(client_p->localClient->number_of_nick_changes == 0)
{
sendto_one(client_p, form_str(ERR_NOTREGISTERED), me.name);
client_p->localClient->number_of_nick_changes++;
}
return 0;
}
int
m_registered(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
sendto_one(client_p, form_str(ERR_ALREADYREGISTRED), me.name, source_p->name);
return 0;
}
int
m_ignore(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
return 0;
}

934
src/res.c Normal file
View file

@ -0,0 +1,934 @@
/*
* 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.
*
* $Id: res.c 3301 2007-03-28 15:04:06Z jilles $
* from Hybrid Id: res.c 459 2006-02-12 22:21:37Z db $
*
* 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
*/
#include "stdinc.h"
#include "ircd_defs.h"
#include "common.h"
#include "ircd.h"
#include "res.h"
#include "reslib.h"
#include "match.h"
#include "numeric.h"
#include "client.h" /* SNO_* */
#include "s_assert.h"
#include "logger.h"
#include "send.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 RES_MAXALIASES 35 /* maximum aliases allowed */
#define RES_MAXADDRS 35 /* maximum addresses allowed */
#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 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);
/*
* 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)
{
#ifdef RB_IPV6
const struct sockaddr_in6 *v6;
const struct sockaddr_in6 *v6in = (const struct sockaddr_in6 *)inp;
#endif
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];
if (srv->ss_family != inp->ss_family)
continue;
#ifdef RB_IPV6
v6 = (const struct sockaddr_in6 *)srv;
#endif
v4 = (const struct sockaddr_in *)srv;
/* could probably just memcmp(srv, inp, srv.ss_len) here
* but we'll err on the side of caution - stu
*/
switch (srv->ss_family)
{
#ifdef RB_IPV6
case AF_INET6:
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 ns;
}
break;
#endif
case AF_INET:
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 ns;
}
break;
default:
break;
}
}
return -1;
}
/*
* 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(irc_nsaddr_list[0].ss_family, 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)
*/
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.
*/
#ifdef HAVE_LRAND48
do
{
request->id = (request->id + lrand48()) & 0xffff;
} while (find_id(request->id));
#else
int k = 0;
struct timeval tv;
gettimeofday(&tv, NULL);
do
{
request->id = (request->id + k + tv.tv_usec) & 0xffff;
k++;
} while (find_id(request->id));
#endif /* HAVE_LRAND48 */
rb_dlinkAdd(request, &request->node, &request_list);
return request;
}
/*
* delete_resolver_queries - cleanup outstanding queries
* for which there no longer exist clients or conf lines.
*/
void delete_resolver_queries(const struct DNSQuery *query)
{
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
struct reslist *request;
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, request_list.head)
{
if ((request = ptr->data) != NULL)
{
if (query == request->query)
rem_request(request);
}
}
}
/*
* retryfreq - determine how many queries to wait before resending
* if there have been that many consecutive timeouts
*/
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);
}
/*
* 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);
}
/*
* 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)
{
const unsigned char *cp;
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);
}
if (addr->ss_family == AF_INET)
{
const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
cp = (const unsigned char *)&v4->sin_addr.s_addr;
rb_sprintf(request->queryname, "%u.%u.%u.%u.in-addr.arpa", (unsigned int)(cp[3]),
(unsigned int)(cp[2]), (unsigned int)(cp[1]), (unsigned int)(cp[0]));
}
#ifdef RB_IPV6
else if (addr->ss_family == AF_INET6)
{
const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
cp = (const unsigned char *)&v6->sin6_addr.s6_addr;
(void)sprintf(request->queryname, "%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.ip6.arpa",
(unsigned int)(cp[15] & 0xf), (unsigned int)(cp[15] >> 4),
(unsigned int)(cp[14] & 0xf), (unsigned int)(cp[14] >> 4),
(unsigned int)(cp[13] & 0xf), (unsigned int)(cp[13] >> 4),
(unsigned int)(cp[12] & 0xf), (unsigned int)(cp[12] >> 4),
(unsigned int)(cp[11] & 0xf), (unsigned int)(cp[11] >> 4),
(unsigned int)(cp[10] & 0xf), (unsigned int)(cp[10] >> 4),
(unsigned int)(cp[9] & 0xf), (unsigned int)(cp[9] >> 4),
(unsigned int)(cp[8] & 0xf), (unsigned int)(cp[8] >> 4),
(unsigned int)(cp[7] & 0xf), (unsigned int)(cp[7] >> 4),
(unsigned int)(cp[6] & 0xf), (unsigned int)(cp[6] >> 4),
(unsigned int)(cp[5] & 0xf), (unsigned int)(cp[5] >> 4),
(unsigned int)(cp[4] & 0xf), (unsigned int)(cp[4] >> 4),
(unsigned int)(cp[3] & 0xf), (unsigned int)(cp[3] >> 4),
(unsigned int)(cp[2] & 0xf), (unsigned int)(cp[2] >> 4),
(unsigned int)(cp[1] & 0xf), (unsigned int)(cp[1] >> 4),
(unsigned int)(cp[0] & 0xf), (unsigned int)(cp[0] >> 4));
}
#endif
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:
#ifdef RB_IPV6
case T_AAAA:
#endif
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 (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 */
#ifdef RB_IPV6
struct sockaddr_in6 *v6;
#endif
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);
#ifdef RB_IPV6
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);
#endif
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);
case T_CNAME:
/* real answer will follow */
current += rd_length;
break;
default:
/* XXX I'd rather just throw away the entire bogus thing
* but its possible its just a broken nameserver with still
* valid answers. But lets do some rudimentary logging for now...
*/
ilog(L_MAIN, "irc_res.c bogus type %d", type);
break;
}
}
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#.
*/
#ifdef RB_IPV6
if (request->addr.ss_family == AF_INET6)
gethost_byname_type_fqdn(request->name, request->query, T_AAAA);
else
#endif
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;
s_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);
}
void report_dns_servers(struct Client *source_p)
{
int i;
char ipaddr[128];
for (i = 0; i < irc_nscount; i++)
{
if (!rb_inet_ntop_sock((struct sockaddr *)&(irc_nsaddr_list[i]),
ipaddr, sizeof ipaddr))
rb_strlcpy(ipaddr, "?", sizeof ipaddr);
sendto_one_numeric(source_p, RPL_STATSDEBUG,
"A %s %d", ipaddr, ns_failure_count[i]);
}
}

646
src/s_auth.c Normal file
View file

@ -0,0 +1,646 @@
/*
* ircd-ratbox: A slightly useful ircd.
* s_auth.c: Functions for querying a users ident.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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
*
* $Id: s_auth.c 3354 2007-04-03 09:21:31Z nenolod $ */
/*
* Changes:
* July 6, 1999 - Rewrote most of the code here. When a client connects
* to the server and passes initial socket validation checks, it
* is owned by this module (auth) which returns it to the rest of the
* server when dns and auth queries are finished. Until the client is
* released, the server does not know it exists and does not process
* any messages from it.
* --Bleep Thomas Helvey <tomh@inxpress.net>
*/
#include "stdinc.h"
#include "config.h"
#include "s_auth.h"
#include "s_conf.h"
#include "client.h"
#include "common.h"
#include "match.h"
#include "ircd.h"
#include "numeric.h"
#include "packet.h"
#include "res.h"
#include "logger.h"
#include "s_stats.h"
#include "send.h"
#include "hook.h"
#include "blacklist.h"
#include "s_assert.h"
struct AuthRequest
{
rb_dlink_node node;
struct Client *client; /* pointer to client struct for request */
struct DNSQuery dns_query; /* DNS Query */
unsigned int flags; /* current state of request */
rb_fde_t *F; /* file descriptor for auth queries */
time_t timeout; /* time when query expires */
uint16_t lport;
uint16_t rport;
};
/*
* flag values for AuthRequest
* NAMESPACE: AM_xxx - Authentication Module
*/
#define AM_AUTH_CONNECTING (1 << 0)
#define AM_AUTH_PENDING (1 << 1)
#define AM_DNS_PENDING (1 << 2)
#define SetDNSPending(x) ((x)->flags |= AM_DNS_PENDING)
#define ClearDNSPending(x) ((x)->flags &= ~AM_DNS_PENDING)
#define IsDNSPending(x) ((x)->flags & AM_DNS_PENDING)
#define SetAuthConnect(x) ((x)->flags |= AM_AUTH_CONNECTING)
#define ClearAuthConnect(x) ((x)->flags &= ~AM_AUTH_CONNECTING)
#define IsAuthConnect(x) ((x)->flags & AM_AUTH_CONNECTING)
#define SetAuthPending(x) ((x)->flags |= AM_AUTH_PENDING)
#define ClearAuthPending(x) ((x)->flags &= AM_AUTH_PENDING)
#define IsAuthPending(x) ((x)->flags & AM_AUTH_PENDING)
#define ClearAuth(x) ((x)->flags &= ~(AM_AUTH_PENDING | AM_AUTH_CONNECTING))
#define IsDoingAuth(x) ((x)->flags & (AM_AUTH_PENDING | AM_AUTH_CONNECTING))
/*
* a bit different approach
* this replaces the original sendheader macros
*/
static const char *HeaderMessages[] =
{
":*** Looking up your hostname...",
":*** Found your hostname",
":*** Couldn't look up your hostname",
":*** Checking Ident",
":*** Got Ident response",
":*** No Ident response",
":*** Your hostname is too long, ignoring hostname",
":*** Your forward and reverse DNS do not match, ignoring hostname",
":*** Cannot verify hostname validity, ignoring hostname",
};
typedef enum
{
REPORT_DO_DNS,
REPORT_FIN_DNS,
REPORT_FAIL_DNS,
REPORT_DO_ID,
REPORT_FIN_ID,
REPORT_FAIL_ID,
REPORT_HOST_TOOLONG,
REPORT_HOST_MISMATCH,
REPORT_HOST_UNKNOWN
}
ReportType;
#define sendheader(c, r) sendto_one_notice(c, "%s", HeaderMessages[(r)])
static rb_dlink_list auth_poll_list;
static rb_bh *auth_heap;
static EVH timeout_auth_queries_event;
static PF read_auth_reply;
static CNCB auth_connect_callback;
/*
* init_auth()
*
* Initialise the auth code
*/
void
init_auth(void)
{
/* This hook takes a struct Client for its argument */
memset(&auth_poll_list, 0, sizeof(auth_poll_list));
rb_event_addish("timeout_auth_queries_event", timeout_auth_queries_event, NULL, 1);
auth_heap = rb_bh_create(sizeof(struct AuthRequest), LCLIENT_HEAP_SIZE, "auth_heap");
}
/*
* make_auth_request - allocate a new auth request
*/
static struct AuthRequest *
make_auth_request(struct Client *client)
{
struct AuthRequest *request = rb_bh_alloc(auth_heap);
client->localClient->auth_request = request;
request->F = NULL;
request->client = client;
request->timeout = rb_current_time() + ConfigFileEntry.connect_timeout;
return request;
}
/*
* free_auth_request - cleanup auth request allocations
*/
static void
free_auth_request(struct AuthRequest *request)
{
rb_bh_free(auth_heap, request);
}
/*
* release_auth_client - release auth client from auth system
* this adds the client into the local client lists so it can be read by
* the main io processing loop
*/
static void
release_auth_client(struct AuthRequest *auth)
{
struct Client *client = auth->client;
if(IsDNSPending(auth) || IsDoingAuth(auth))
return;
client->localClient->auth_request = NULL;
rb_dlinkDelete(&auth->node, &auth_poll_list);
free_auth_request(auth);
/*
* When a client has auth'ed, we want to start reading what it sends
* us. This is what read_packet() does.
* -- adrian
*/
rb_dlinkAddTail(client, &client->node, &global_client_list);
read_packet(client->localClient->F, client);
}
/*
* auth_dns_callback - called when resolver query finishes
* if the query resulted in a successful search, hp will contain
* a non-null pointer, otherwise hp will be null.
* set the client on it's way to a connection completion, regardless
* of success of failure
*/
static void
auth_dns_callback(void *vptr, struct DNSReply *reply)
{
struct AuthRequest *auth = (struct AuthRequest *) vptr;
ClearDNSPending(auth);
/* XXX: this shouldn't happen, but it does. -nenolod */
if(auth->client->localClient == NULL)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"auth_dns_callback(): auth->client->localClient (%s) is NULL", get_client_name(auth->client, HIDE_IP));
rb_dlinkDelete(&auth->node, &auth_poll_list);
free_auth_request(auth);
/* and they will silently drop through and all will hopefully be ok... -nenolod */
return;
}
if(reply)
{
int good = 1;
if(auth->client->localClient->ip.ss_family == AF_INET)
{
struct sockaddr_in *ip, *ip_fwd;
ip = (struct sockaddr_in *) &auth->client->localClient->ip;
ip_fwd = (struct sockaddr_in *) &reply->addr;
if(ip->sin_addr.s_addr != ip_fwd->sin_addr.s_addr)
{
sendheader(auth->client, REPORT_HOST_MISMATCH);
good = 0;
}
}
#ifdef RB_IPV6
else if(auth->client->localClient->ip.ss_family == AF_INET6)
{
struct sockaddr_in6 *ip, *ip_fwd;
ip = (struct sockaddr_in6 *) &auth->client->localClient->ip;
ip_fwd = (struct sockaddr_in6 *) &reply->addr;
if(memcmp(&ip->sin6_addr, &ip_fwd->sin6_addr, sizeof(struct in6_addr)) != 0)
{
sendheader(auth->client, REPORT_HOST_MISMATCH);
good = 0;
}
}
#endif
else /* can't verify it, don't know how. reject it. */
{
sendheader(auth->client, REPORT_HOST_UNKNOWN);
good = 0;
}
if(good && strlen(reply->h_name) <= HOSTLEN)
{
rb_strlcpy(auth->client->host, reply->h_name, sizeof(auth->client->host));
sendheader(auth->client, REPORT_FIN_DNS);
}
else if (strlen(reply->h_name) > HOSTLEN)
sendheader(auth->client, REPORT_HOST_TOOLONG);
}
else
sendheader(auth->client, REPORT_FAIL_DNS);
release_auth_client(auth);
}
/*
* authsenderr - handle auth send errors
*/
static void
auth_error(struct AuthRequest *auth)
{
++ServerStats.is_abad;
rb_close(auth->F);
auth->F = NULL;
ClearAuth(auth);
sendheader(auth->client, REPORT_FAIL_ID);
release_auth_client(auth);
}
/*
* start_auth_query - Flag the client to show that an attempt to
* contact the ident server on
* the client's host. The connect and subsequently the socket are all put
* into 'non-blocking' mode. Should the connect or any later phase of the
* identifing process fail, it is aborted and the user is given a username
* of "unknown".
*/
static int
start_auth_query(struct AuthRequest *auth)
{
struct rb_sockaddr_storage localaddr, destaddr;
rb_fde_t *F;
int family;
if(IsAnyDead(auth->client))
return 0;
family = auth->client->localClient->ip.ss_family;
if((F = rb_socket(family, SOCK_STREAM, 0, "ident")) == NULL)
{
ilog_error("creating auth stream socket");
++ServerStats.is_abad;
return 0;
}
/*
* TBD: this is a pointless arbitrary limit .. we either have a socket or not. -nenolod
*/
if((maxconnections - 10) < rb_get_fd(F))
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Can't allocate fd for auth on %s",
get_client_name(auth->client, SHOW_IP));
rb_close(F);
return 0;
}
sendheader(auth->client, REPORT_DO_ID);
/*
* get the local address of the client and bind to that to
* make the auth request. This used to be done only for
* ifdef VIRTUAL_HOST, but needs to be done for all clients
* since the ident request must originate from that same address--
* and machines with multiple IP addresses are common now
*/
localaddr = auth->client->preClient->lip;
/* XXX mangle_mapped_sockaddr((struct sockaddr *)&localaddr); */
#ifdef RB_IPV6
if(localaddr.ss_family == AF_INET6)
{
auth->lport = ntohs(((struct sockaddr_in6 *)&localaddr)->sin6_port);
((struct sockaddr_in6 *)&localaddr)->sin6_port = 0;
}
else
#endif
{
auth->lport = ntohs(((struct sockaddr_in *)&localaddr)->sin_port);
((struct sockaddr_in *)&localaddr)->sin_port = 0;
}
destaddr = auth->client->localClient->ip;
#ifdef RB_IPV6
if(localaddr.ss_family == AF_INET6)
{
auth->rport = ntohs(((struct sockaddr_in6 *)&destaddr)->sin6_port);
((struct sockaddr_in6 *)&destaddr)->sin6_port = htons(113);
}
else
#endif
{
auth->rport = ntohs(((struct sockaddr_in *)&destaddr)->sin_port);
((struct sockaddr_in *)&destaddr)->sin_port = htons(113);
}
auth->F = F;
SetAuthConnect(auth);
rb_connect_tcp(F, (struct sockaddr *)&destaddr,
(struct sockaddr *) &localaddr, GET_SS_LEN(&localaddr),
auth_connect_callback, auth,
GlobalSetOptions.ident_timeout);
return 1; /* We suceed here for now */
}
/*
* GetValidIdent - parse ident query reply from identd server
*
* Inputs - pointer to ident buf
* Output - NULL if no valid ident found, otherwise pointer to name
* Side effects -
*/
static char *
GetValidIdent(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 0;
*colon1Ptr = '\0';
colon1Ptr++;
colon2Ptr = strchr(colon1Ptr, ':');
if(!colon2Ptr)
return 0;
*colon2Ptr = '\0';
colon2Ptr++;
commaPtr = strchr(remotePortString, ',');
if(!commaPtr)
return 0;
*commaPtr = '\0';
commaPtr++;
remp = atoi(remotePortString);
if(!remp)
return 0;
locp = atoi(commaPtr);
if(!locp)
return 0;
/* look for USERID bordered by first pair of colons */
if(!strstr(colon1Ptr, "USERID"))
return 0;
colon3Ptr = strchr(colon2Ptr, ':');
if(!colon3Ptr)
return 0;
*colon3Ptr = '\0';
colon3Ptr++;
return (colon3Ptr);
}
/*
* start_auth - starts auth (identd) and dns queries for a client
*/
void
start_auth(struct Client *client)
{
struct AuthRequest *auth = 0;
s_assert(0 != client);
if(client == NULL)
return;
auth = make_auth_request(client);
auth->dns_query.ptr = auth;
auth->dns_query.callback = auth_dns_callback;
sendheader(client, REPORT_DO_DNS);
/* No DNS cache now, remember? -- adrian */
gethost_byaddr(&client->localClient->ip, &auth->dns_query);
SetDNSPending(auth);
if(ConfigFileEntry.disable_auth == 0)
start_auth_query(auth);
rb_dlinkAdd(auth, &auth->node, &auth_poll_list);
}
/*
* timeout_auth_queries - timeout resolver and identd requests
* allow clients through if requests failed
*/
static void
timeout_auth_queries_event(void *notused)
{
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
struct AuthRequest *auth;
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, auth_poll_list.head)
{
auth = ptr->data;
if(auth->timeout < rb_current_time())
{
if(auth->F != NULL)
rb_close(auth->F);
if(IsDoingAuth(auth))
{
ClearAuth(auth);
++ServerStats.is_abad;
sendheader(auth->client, REPORT_FAIL_ID);
auth->client->localClient->auth_request = NULL;
}
if(IsDNSPending(auth))
{
ClearDNSPending(auth);
delete_resolver_queries(&auth->dns_query);
sendheader(auth->client, REPORT_FAIL_DNS);
}
auth->client->localClient->lasttime = rb_current_time();
release_auth_client(auth);
}
}
}
/*
* auth_connect_callback() - 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
auth_connect_callback(rb_fde_t *F, int error, void *data)
{
struct AuthRequest *auth = data;
char authbuf[32];
int authlen;
/* Check the error */
if(error != RB_OK)
{
/* We had an error during connection :( */
auth_error(auth);
return;
}
rb_snprintf(authbuf, sizeof(authbuf), "%u , %u\r\n",
auth->rport, auth->lport);
authlen = strlen(authbuf);
if(rb_write(auth->F, authbuf, authlen) != authlen)
{
auth_error(auth);
return;
}
ClearAuthConnect(auth);
SetAuthPending(auth);
read_auth_reply(auth->F, auth);
}
/*
* read_auth_reply - read the reply (if any) from the ident server
* we connected to.
* We only give it one shot, if the reply isn't good the first time
* fail the authentication entirely. --Bleep
*/
#define AUTH_BUFSIZ 128
static void
read_auth_reply(rb_fde_t *F, void *data)
{
struct AuthRequest *auth = data;
char *s = NULL;
char *t = NULL;
int len;
int count;
char buf[AUTH_BUFSIZ + 1] = { 0 }; /* buffer to read auth reply into */
len = rb_read(F, buf, AUTH_BUFSIZ);
if(len < 0 && rb_ignore_errno(errno))
{
rb_setselect(F, RB_SELECT_READ, read_auth_reply, auth);
return;
}
if(len > 0)
{
buf[len] = '\0';
if((s = GetValidIdent(buf)))
{
t = auth->client->username;
while (*s == '~' || *s == '^')
s++;
for (count = USERLEN; *s && count; s++)
{
if(*s == '@')
{
break;
}
if(!IsSpace(*s) && *s != ':' && *s != '[')
{
*t++ = *s;
count--;
}
}
*t = '\0';
}
}
rb_close(auth->F);
auth->F = NULL;
ClearAuth(auth);
if(s == NULL)
{
++ServerStats.is_abad;
strcpy(auth->client->username, "unknown");
sendheader(auth->client, REPORT_FAIL_ID);
}
else
{
sendheader(auth->client, REPORT_FIN_ID);
++ServerStats.is_asuc;
SetGotId(auth->client);
}
release_auth_client(auth);
}
/*
* delete_auth_queries()
*
*/
void
delete_auth_queries(struct Client *target_p)
{
struct AuthRequest *auth;
if(target_p == NULL || target_p->localClient == NULL ||
target_p->localClient->auth_request == NULL)
return;
auth = target_p->localClient->auth_request;
target_p->localClient->auth_request = NULL;
if(IsDNSPending(auth))
delete_resolver_queries(&auth->dns_query);
if(auth->F != NULL)
rb_close(auth->F);
rb_dlinkDelete(&auth->node, &auth_poll_list);
free_auth_request(auth);
}

1721
src/s_conf.c Normal file

File diff suppressed because it is too large Load diff

847
src/s_newconf.c Normal file
View file

@ -0,0 +1,847 @@
/*
* ircd-ratbox: an advanced Internet Relay Chat Daemon(ircd).
* s_newconf.c - code for dealing with conf stuff
*
* Copyright (C) 2004 Lee Hardy <lee@leeh.co.uk>
* Copyright (C) 2004-2005 ircd-ratbox 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.
*
* $Id: s_newconf.c 3508 2007-06-04 16:04:49Z jilles $
*/
#include "stdinc.h"
#include "ircd_defs.h"
#include "common.h"
#include "s_conf.h"
#include "s_newconf.h"
#include "client.h"
#include "s_serv.h"
#include "send.h"
#include "hostmask.h"
#include "newconf.h"
#include "hash.h"
#include "irc_dictionary.h"
#include "s_assert.h"
#include "logger.h"
rb_dlink_list shared_conf_list;
rb_dlink_list cluster_conf_list;
rb_dlink_list oper_conf_list;
rb_dlink_list hubleaf_conf_list;
rb_dlink_list server_conf_list;
rb_dlink_list xline_conf_list;
rb_dlink_list resv_conf_list; /* nicks only! */
rb_dlink_list nd_list; /* nick delay */
rb_dlink_list tgchange_list;
rb_dlink_list vhost_conf_list;
rb_patricia_tree_t *tgchange_tree;
static rb_bh *nd_heap = NULL;
static void expire_temp_rxlines(void *unused);
static void expire_nd_entries(void *unused);
struct ev_entry *expire_nd_entries_ev = NULL;
struct ev_entry *expire_temp_rxlines_ev = NULL;
void
init_s_newconf(void)
{
tgchange_tree = rb_new_patricia(PATRICIA_BITS);
nd_heap = rb_bh_create(sizeof(struct nd_entry), ND_HEAP_SIZE, "nd_heap");
expire_nd_entries_ev = rb_event_addish("expire_nd_entries", expire_nd_entries, NULL, 30);
expire_temp_rxlines_ev = rb_event_addish("expire_temp_rxlines", expire_temp_rxlines, NULL, 60);
}
void
clear_s_newconf(void)
{
struct server_conf *server_p;
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, shared_conf_list.head)
{
/* ptr here is ptr->data->node */
rb_dlinkDelete(ptr, &shared_conf_list);
free_remote_conf(ptr->data);
}
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, cluster_conf_list.head)
{
rb_dlinkDelete(ptr, &cluster_conf_list);
free_remote_conf(ptr->data);
}
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, hubleaf_conf_list.head)
{
rb_dlinkDelete(ptr, &hubleaf_conf_list);
free_remote_conf(ptr->data);
}
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, oper_conf_list.head)
{
free_oper_conf(ptr->data);
rb_dlinkDestroy(ptr, &oper_conf_list);
}
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, server_conf_list.head)
{
server_p = ptr->data;
if(!server_p->servers)
{
rb_dlinkDelete(ptr, &server_conf_list);
free_server_conf(ptr->data);
}
else
server_p->flags |= SERVER_ILLEGAL;
}
}
void
clear_s_newconf_bans(void)
{
struct ConfItem *aconf;
rb_dlink_node *ptr, *next_ptr;
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, xline_conf_list.head)
{
aconf = ptr->data;
if(aconf->hold)
continue;
free_conf(aconf);
rb_dlinkDestroy(ptr, &xline_conf_list);
}
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, resv_conf_list.head)
{
aconf = ptr->data;
/* temporary resv */
if(aconf->hold)
continue;
free_conf(aconf);
rb_dlinkDestroy(ptr, &resv_conf_list);
}
clear_resv_hash();
}
struct remote_conf *
make_remote_conf(void)
{
struct remote_conf *remote_p = rb_malloc(sizeof(struct remote_conf));
return remote_p;
}
void
free_remote_conf(struct remote_conf *remote_p)
{
s_assert(remote_p != NULL);
if(remote_p == NULL)
return;
rb_free(remote_p->username);
rb_free(remote_p->host);
rb_free(remote_p->server);
rb_free(remote_p);
}
int
find_shared_conf(const char *username, const char *host,
const char *server, int flags)
{
struct remote_conf *shared_p;
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, shared_conf_list.head)
{
shared_p = ptr->data;
if(match(shared_p->username, username) &&
match(shared_p->host, host) &&
match(shared_p->server, server))
{
if(shared_p->flags & flags)
return YES;
else
return NO;
}
}
return NO;
}
void
propagate_generic(struct Client *source_p, const char *command,
const char *target, int cap, const char *format, ...)
{
char buffer[BUFSIZE];
va_list args;
va_start(args, format);
rb_vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
sendto_match_servs(source_p, target, cap, NOCAPS,
"%s %s %s",
command, target, buffer);
sendto_match_servs(source_p, target, CAP_ENCAP, cap,
"ENCAP %s %s %s",
target, command, buffer);
}
void
cluster_generic(struct Client *source_p, const char *command,
int cltype, int cap, const char *format, ...)
{
char buffer[BUFSIZE];
struct remote_conf *shared_p;
va_list args;
rb_dlink_node *ptr;
va_start(args, format);
rb_vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
RB_DLINK_FOREACH(ptr, cluster_conf_list.head)
{
shared_p = ptr->data;
if(!(shared_p->flags & cltype))
continue;
sendto_match_servs(source_p, shared_p->server, cap, NOCAPS,
"%s %s %s",
command, shared_p->server, buffer);
sendto_match_servs(source_p, shared_p->server, CAP_ENCAP, cap,
"ENCAP %s %s %s",
shared_p->server, command, buffer);
}
}
struct oper_conf *
make_oper_conf(void)
{
struct oper_conf *oper_p = rb_malloc(sizeof(struct oper_conf));
return oper_p;
}
void
free_oper_conf(struct oper_conf *oper_p)
{
s_assert(oper_p != NULL);
if(oper_p == NULL)
return;
rb_free(oper_p->username);
rb_free(oper_p->host);
rb_free(oper_p->name);
rb_free(oper_p->certfp);
if(oper_p->passwd)
{
memset(oper_p->passwd, 0, strlen(oper_p->passwd));
rb_free(oper_p->passwd);
}
#ifdef HAVE_LIBCRYPTO
rb_free(oper_p->rsa_pubkey_file);
if(oper_p->rsa_pubkey)
RSA_free(oper_p->rsa_pubkey);
#endif
rb_free(oper_p);
}
struct oper_conf *
find_oper_conf(const char *username, const char *host, const char *locip, const char *name)
{
struct oper_conf *oper_p;
struct rb_sockaddr_storage ip, cip;
char addr[HOSTLEN+1];
int bits, cbits;
rb_dlink_node *ptr;
parse_netmask(locip, &cip, &cbits);
RB_DLINK_FOREACH(ptr, oper_conf_list.head)
{
oper_p = ptr->data;
/* name/username doesnt match.. */
if(irccmp(oper_p->name, name) || !match(oper_p->username, username))
continue;
rb_strlcpy(addr, oper_p->host, sizeof(addr));
if(parse_netmask(addr, &ip, &bits) != HM_HOST)
{
if(ip.ss_family == cip.ss_family &&
comp_with_mask_sock((struct sockaddr *)&ip, (struct sockaddr *)&cip, bits))
return oper_p;
}
/* we have to compare against the host as well, because its
* valid to set a spoof to an IP, which if we only compare
* in ip form to sockhost will not necessarily match --anfl
*/
if(match(oper_p->host, host))
return oper_p;
}
return NULL;
}
struct server_conf *
make_server_conf(void)
{
struct server_conf *server_p = rb_malloc(sizeof(struct server_conf));
server_p->aftype = AF_INET;
return server_p;
}
void
free_server_conf(struct server_conf *server_p)
{
s_assert(server_p != NULL);
if(server_p == NULL)
return;
if(!EmptyString(server_p->passwd))
{
memset(server_p->passwd, 0, strlen(server_p->passwd));
rb_free(server_p->passwd);
}
if(!EmptyString(server_p->spasswd))
{
memset(server_p->spasswd, 0, strlen(server_p->spasswd));
rb_free(server_p->spasswd);
}
rb_free(server_p->name);
rb_free(server_p->host);
rb_free(server_p->class_name);
rb_free(server_p->certfp);
rb_free(server_p);
}
void
add_server_conf(struct server_conf *server_p)
{
if(EmptyString(server_p->class_name))
{
server_p->class_name = rb_strdup("default");
server_p->class = default_class;
return;
}
server_p->class = find_class(server_p->class_name);
if(server_p->class == default_class)
{
conf_report_error("Warning connect::class invalid for %s",
server_p->name);
rb_free(server_p->class_name);
server_p->class_name = rb_strdup("default");
}
if(strchr(server_p->host, '*') || strchr(server_p->host, '?'))
return;
}
struct server_conf *
find_server_conf(const char *name)
{
struct server_conf *server_p;
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, server_conf_list.head)
{
server_p = ptr->data;
if(ServerConfIllegal(server_p))
continue;
if(match(name, server_p->name))
return server_p;
}
return NULL;
}
void
attach_server_conf(struct Client *client_p, struct server_conf *server_p)
{
/* already have an attached conf */
if(client_p->localClient->att_sconf)
{
/* short circuit this special case :) */
if(client_p->localClient->att_sconf == server_p)
return;
detach_server_conf(client_p);
}
CurrUsers(server_p->class)++;
client_p->localClient->att_sconf = server_p;
server_p->servers++;
}
void
detach_server_conf(struct Client *client_p)
{
struct server_conf *server_p = client_p->localClient->att_sconf;
if(server_p == NULL)
return;
client_p->localClient->att_sconf = NULL;
server_p->servers--;
CurrUsers(server_p->class)--;
if(ServerConfIllegal(server_p) && !server_p->servers)
{
/* the class this one is using may need destroying too */
if(MaxUsers(server_p->class) < 0 && CurrUsers(server_p->class) <= 0)
free_class(server_p->class);
rb_dlinkDelete(&server_p->node, &server_conf_list);
free_server_conf(server_p);
}
}
void
set_server_conf_autoconn(struct Client *source_p, const char *name, int newval)
{
struct server_conf *server_p;
if((server_p = find_server_conf(name)) != NULL)
{
if(newval)
server_p->flags |= SERVER_AUTOCONN;
else
server_p->flags &= ~SERVER_AUTOCONN;
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"%s has changed AUTOCONN for %s to %i",
get_oper_name(source_p), name, newval);
}
else
sendto_one_notice(source_p, ":Can't find %s", name);
}
void
disable_server_conf_autoconn(const char *name)
{
struct server_conf *server_p;
server_p = find_server_conf(name);
if(server_p != NULL && server_p->flags & SERVER_AUTOCONN)
{
server_p->flags &= ~SERVER_AUTOCONN;
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Disabling AUTOCONN for %s because of error",
name);
ilog(L_SERVER, "Disabling AUTOCONN for %s because of error",
name);
}
}
struct ConfItem *
find_xline(const char *gecos, int counter)
{
struct ConfItem *aconf;
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, xline_conf_list.head)
{
aconf = ptr->data;
if(match_esc(aconf->host, gecos))
{
if(counter)
aconf->port++;
return aconf;
}
}
return NULL;
}
struct ConfItem *
find_xline_mask(const char *gecos)
{
struct ConfItem *aconf;
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, xline_conf_list.head)
{
aconf = ptr->data;
if(!irccmp(aconf->host, gecos))
return aconf;
}
return NULL;
}
struct ConfItem *
find_nick_resv(const char *name)
{
struct ConfItem *aconf;
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, resv_conf_list.head)
{
aconf = ptr->data;
if(match_esc(aconf->host, name))
{
aconf->port++;
return aconf;
}
}
return NULL;
}
struct ConfItem *
find_nick_resv_mask(const char *name)
{
struct ConfItem *aconf;
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, resv_conf_list.head)
{
aconf = ptr->data;
if(!irccmp(aconf->host, name))
return aconf;
}
return NULL;
}
/* clean_resv_nick()
*
* inputs - nick
* outputs - 1 if nick is vaild resv, 0 otherwise
* side effects -
*/
int
clean_resv_nick(const char *nick)
{
char tmpch;
int as = 0;
int q = 0;
int ch = 0;
if(*nick == '-' || IsDigit(*nick))
return 0;
while ((tmpch = *nick++))
{
if(tmpch == '?' || tmpch == '@' || tmpch == '#')
q++;
else if(tmpch == '*')
as++;
else if(IsNickChar(tmpch))
ch++;
else
return 0;
}
if(!ch && as)
return 0;
return 1;
}
/* valid_wild_card_simple()
*
* inputs - "thing" to test
* outputs - 1 if enough wildcards, else 0
* side effects -
*/
int
valid_wild_card_simple(const char *data)
{
const char *p;
char tmpch;
int nonwild = 0;
int wild = 0;
/* check the string for minimum number of nonwildcard chars */
p = data;
while((tmpch = *p++))
{
/* found an escape, p points to the char after it, so skip
* that and move on.
*/
if(tmpch == '\\' && *p)
{
p++;
if(++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
return 1;
}
else if(!IsMWildChar(tmpch))
{
/* if we have enough nonwildchars, return */
if(++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
return 1;
}
else
wild++;
}
/* strings without wilds are also ok */
return wild == 0;
}
time_t
valid_temp_time(const char *p)
{
time_t result = 0;
while(*p)
{
if(IsDigit(*p))
{
result *= 10;
result += ((*p) & 0xF);
p++;
}
else
return -1;
}
if(result > (60 * 24 * 7 * 52))
result = (60 * 24 * 7 * 52);
return(result * 60);
}
/* Propagated bans are expired elsewhere. */
static void
expire_temp_rxlines(void *unused)
{
struct ConfItem *aconf;
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
int i;
HASH_WALK_SAFE(i, R_MAX, ptr, next_ptr, resvTable)
{
aconf = ptr->data;
if(aconf->lifetime != 0)
continue;
if(aconf->hold && aconf->hold <= rb_current_time())
{
if(ConfigFileEntry.tkline_expire_notices)
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Temporary RESV for [%s] expired",
aconf->host);
free_conf(aconf);
rb_dlinkDestroy(ptr, &resvTable[i]);
}
}
HASH_WALK_END
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, resv_conf_list.head)
{
aconf = ptr->data;
if(aconf->lifetime != 0)
continue;
if(aconf->hold && aconf->hold <= rb_current_time())
{
if(ConfigFileEntry.tkline_expire_notices)
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Temporary RESV for [%s] expired",
aconf->host);
free_conf(aconf);
rb_dlinkDestroy(ptr, &resv_conf_list);
}
}
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, xline_conf_list.head)
{
aconf = ptr->data;
if(aconf->lifetime != 0)
continue;
if(aconf->hold && aconf->hold <= rb_current_time())
{
if(ConfigFileEntry.tkline_expire_notices)
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Temporary X-line for [%s] expired",
aconf->host);
free_conf(aconf);
rb_dlinkDestroy(ptr, &xline_conf_list);
}
}
}
unsigned long
get_nd_count(void)
{
return(rb_dlink_list_length(&nd_list));
}
void
add_nd_entry(const char *name)
{
struct nd_entry *nd;
if(irc_dictionary_find(nd_dict, name) != NULL)
return;
nd = rb_bh_alloc(nd_heap);
rb_strlcpy(nd->name, name, sizeof(nd->name));
nd->expire = rb_current_time() + ConfigFileEntry.nick_delay;
/* this list is ordered */
rb_dlinkAddTail(nd, &nd->lnode, &nd_list);
irc_dictionary_add(nd_dict, nd->name, nd);
}
void
free_nd_entry(struct nd_entry *nd)
{
irc_dictionary_delete(nd_dict, nd->name);
rb_dlinkDelete(&nd->lnode, &nd_list);
rb_bh_free(nd_heap, nd);
}
void
expire_nd_entries(void *unused)
{
struct nd_entry *nd;
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, nd_list.head)
{
nd = ptr->data;
/* this list is ordered - we can stop when we hit the first
* entry that doesnt expire..
*/
if(nd->expire > rb_current_time())
return;
free_nd_entry(nd);
}
}
void
add_tgchange(const char *host)
{
tgchange *target;
rb_patricia_node_t *pnode;
if(find_tgchange(host))
return;
target = rb_malloc(sizeof(tgchange));
pnode = make_and_lookup(tgchange_tree, host);
pnode->data = target;
target->pnode = pnode;
target->ip = rb_strdup(host);
target->expiry = rb_current_time() + (60*60*12);
rb_dlinkAdd(target, &target->node, &tgchange_list);
}
tgchange *
find_tgchange(const char *host)
{
rb_patricia_node_t *pnode;
if((pnode = rb_match_exact_string(tgchange_tree, host)))
return pnode->data;
return NULL;
}
struct vhost_conf *
find_ssl_vhost(const char *hostname)
{
struct vhost_conf *vhost_p;
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, vhost_conf_list.head)
{
vhost_p = ptr->data;
if(!strcmp(hostname,vhost_p->hostname))
return vhost_p;
}
return NULL;
}
struct vhost_conf *
make_vhost_conf(void)
{
struct vhost_conf *vhost_p = rb_malloc(sizeof(struct vhost_conf));
return vhost_p;
}
void
free_vhost_conf(struct vhost_conf *vhost_p)
{
s_assert(vhost_p != NULL);
if(vhost_p == NULL)
return;
rb_free(vhost_p->hostname);
rb_free(vhost_p->ssl_private_key);
rb_free(vhost_p->ssl_cert);
rb_free(vhost_p->ssl_dh_params);
rb_free(vhost_p->ssl_cipher_list);
rb_free(vhost_p);
}
// TODO: Free vhost_conf_list

1400
src/s_serv.c Normal file

File diff suppressed because it is too large Load diff

1517
src/s_user.c Normal file

File diff suppressed because it is too large Load diff

1023
src/sslproc.c Normal file

File diff suppressed because it is too large Load diff

348
src/supported.c Normal file
View file

@ -0,0 +1,348 @@
/*
* charybdis: A slightly useful ircd.
* supported.c: isupport (005) numeric
*
* Copyright (C) 2006 Jilles Tjoelker
*
* 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.
*
* $Id: supported.c 3568 2007-09-09 18:59:08Z jilles $
*/
/* From the old supported.h which is
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2004 ircd-ratbox development team
*/
/*
* - from mirc's versions.txt
*
* mIRC now supports the numeric 005 tokens: CHANTYPES=# and
* PREFIX=(ohv)@%+ and can handle a dynamic set of channel and
* nick prefixes.
*
* mIRC assumes that @ is supported on all networks, any mode
* left of @ is assumed to have at least equal power to @, and
* any mode right of @ has less power.
*
* mIRC has internal support for @%+ modes.
*
* $nick() can now handle all mode letters listed in PREFIX.
*
* Also added support for CHANMODES=A,B,C,D token (not currently
* supported by any servers), which lists all modes supported
* by a channel, where:
*
* A = modes that take a parameter, and add or remove nicks
* or addresses to a list, such as +bIe for the ban,
* invite, and exception lists.
*
* B = modes that change channel settings, but which take
* a parameter when they are set and unset, such as
* +k key, and -k key.
*
* C = modes that change channel settings, but which take
* a parameter only when they are set, such as +l N,
* and -l.
*
* D = modes that change channel settings, such as +imnpst
* and take no parameters.
*
* All unknown/unlisted modes are treated as type D.
*/
#include "stdinc.h"
#include "client.h"
#include "common.h"
#include "numeric.h"
#include "ircd.h"
#include "s_conf.h"
#include "s_user.h"
#include "supported.h"
#include "chmode.h"
#include "send.h"
rb_dlink_list isupportlist;
struct isupportitem
{
const char *name;
const char *(*func)(const void *);
const void *param;
rb_dlink_node node;
};
void
add_isupport(const char *name, const char *(*func)(const void *), const void *param)
{
struct isupportitem *item;
item = rb_malloc(sizeof(struct isupportitem));
item->name = name;
item->func = func;
item->param = param;
rb_dlinkAddTail(item, &item->node, &isupportlist);
}
const void *
change_isupport(const char *name, const char *(*func)(const void *), const void *param)
{
rb_dlink_node *ptr;
struct isupportitem *item;
const void *oldvalue = NULL;
RB_DLINK_FOREACH(ptr, isupportlist.head)
{
item = ptr->data;
if (!strcmp(item->name, name))
{
oldvalue = item->param;
// item->name = name;
item->func = func;
item->param = param;
break;
}
}
return oldvalue;
}
void
delete_isupport(const char *name)
{
rb_dlink_node *ptr, *next_ptr;
struct isupportitem *item;
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, isupportlist.head)
{
item = ptr->data;
if (!strcmp(item->name, name))
{
rb_dlinkDelete(ptr, &isupportlist);
rb_free(item);
}
}
}
/* XXX caching? */
void
show_isupport(struct Client *client_p)
{
rb_dlink_node *ptr;
struct isupportitem *item;
const char *value;
char buf[512];
int extra_space;
unsigned int nchars, nparams;
int l;
extra_space = strlen(client_p->name);
/* UID */
if (!MyClient(client_p) && extra_space < 9)
extra_space = 9;
/* :<me.name> 005 <nick> <params> :are supported by this server */
/* form_str(RPL_ISUPPORT) is %s :are supported by this server */
extra_space += strlen(me.name) + 1 + strlen(form_str(RPL_ISUPPORT));
nchars = extra_space;
nparams = 0;
buf[0] = '\0';
RB_DLINK_FOREACH(ptr, isupportlist.head)
{
item = ptr->data;
value = (*item->func)(item->param);
if (value == NULL)
continue;
l = strlen(item->name) + (EmptyString(value) ? 0 : 1 + strlen(value));
if (nchars + l + (nparams > 0) >= sizeof buf || nparams + 1 > 12)
{
sendto_one_numeric(client_p, RPL_ISUPPORT, form_str(RPL_ISUPPORT), buf);
nchars = extra_space;
nparams = 0;
buf[0] = '\0';
}
if (nparams > 0)
{
rb_strlcat(buf, " ", sizeof buf);
nchars++;
}
rb_strlcat(buf, item->name, sizeof buf);
if (!EmptyString(value))
{
rb_strlcat(buf, "=", sizeof buf);
rb_strlcat(buf, value, sizeof buf);
}
nchars += l;
nparams++;
}
if (nparams > 0)
sendto_one_numeric(client_p, RPL_ISUPPORT, form_str(RPL_ISUPPORT), buf);
}
const char *
isupport_intptr(const void *ptr)
{
static char buf[15];
rb_snprintf(buf, sizeof buf, "%d", *(const int *)ptr);
return buf;
}
const char *
isupport_boolean(const void *ptr)
{
return *(const int *)ptr ? "" : NULL;
}
const char *
isupport_string(const void *ptr)
{
return (const char *)ptr;
}
const char *
isupport_stringptr(const void *ptr)
{
return *(char * const *)ptr;
}
static const char *
isupport_umode(const void *ptr)
{
const char *str;
str = ptr;
return ConfigFileEntry.oper_only_umodes &
user_modes[(unsigned char)*str] ? NULL : str;
}
static const char *
isupport_chanmodes(const void *ptr)
{
static char result[80];
rb_snprintf(result, sizeof result, "%s%sbq,k,%slj,%s",
ConfigChannel.use_except ? "e" : "",
ConfigChannel.use_invex ? "I" : "",
ConfigChannel.use_forward ? "f" : "",
cflagsbuf);
return result;
}
static const char *
isupport_chantypes(const void *ptr)
{
return ConfigChannel.disable_local_channels ? "#" : "&#";
}
static const char *
isupport_chanlimit(const void *ptr)
{
static char result[30];
rb_snprintf(result, sizeof result, "%s:%i",
ConfigChannel.disable_local_channels ? "#" : "&#", ConfigChannel.max_chans_per_user);
return result;
}
static const char *
isupport_maxlist(const void *ptr)
{
static char result[30];
rb_snprintf(result, sizeof result, "bq%s%s:%i",
ConfigChannel.use_except ? "e" : "",
ConfigChannel.use_invex ? "I" : "",
ConfigChannel.max_bans);
return result;
}
static const char *
isupport_targmax(const void *ptr)
{
static char result[200];
rb_snprintf(result, sizeof result, "NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:%d,NOTICE:%d,ACCEPT:,MONITOR:",
ConfigFileEntry.max_targets,
ConfigFileEntry.max_targets);
return result;
}
static const char *
isupport_extban(const void *ptr)
{
const char *p;
static char result[200];
p = get_extban_string();
if (EmptyString(p))
return NULL;
rb_snprintf(result, sizeof result, "$,%s", p);
return result;
}
static const char *
isupport_nicklen(const void *ptr)
{
static char result[200];
rb_snprintf(result, sizeof result, "%u", ConfigFileEntry.nicklen - 1);
return result;
}
void
init_isupport(void)
{
static int maxmodes = MAXMODEPARAMS;
static int channellen = LOC_CHANNELLEN;
static int topiclen = TOPICLEN;
static int maxnicklen = NICKLEN - 1;
add_isupport("CHANTYPES", isupport_chantypes, NULL);
add_isupport("EXCEPTS", isupport_boolean, &ConfigChannel.use_except);
add_isupport("INVEX", isupport_boolean, &ConfigChannel.use_invex);
add_isupport("CHANMODES", isupport_chanmodes, NULL);
add_isupport("CHANLIMIT", isupport_chanlimit, NULL);
add_isupport("PREFIX", isupport_string, "(ov)@+");
add_isupport("MAXLIST", isupport_maxlist, NULL);
add_isupport("MODES", isupport_intptr, &maxmodes);
add_isupport("NETWORK", isupport_stringptr, &ServerInfo.network_name);
add_isupport("STATUSMSG", isupport_string, "@+");
add_isupport("CALLERID", isupport_umode, "g");
add_isupport("CASEMAPPING", isupport_string, "rfc1459");
add_isupport("NICKLEN", isupport_nicklen, NULL);
add_isupport("MAXNICKLEN", isupport_intptr, &maxnicklen);
add_isupport("CHANNELLEN", isupport_intptr, &channellen);
add_isupport("TOPICLEN", isupport_intptr, &topiclen);
add_isupport("DEAF", isupport_umode, "D");
add_isupport("TARGMAX", isupport_targmax, NULL);
add_isupport("EXTBAN", isupport_extban, NULL);
add_isupport("CLIENTVER", isupport_string, "3.0");
}

View file

@ -133,8 +133,19 @@ static void conn_plain_read_cb(rb_fde_t *fd, void *data);
static void conn_plain_read_shutdown_cb(rb_fde_t *fd, void *data);
static void mod_cmd_write_queue(mod_ctl_t * ctl, const void *data, size_t len);
static const char *remote_closed = "Remote host closed the connection";
<<<<<<< .merge_file_7dGMbH
static int ssld_ssl_ok;
static int certfp_method = RB_SSL_CERTFP_METH_CERT_SHA1;
#ifdef HAVE_LIBZ
static int ssld_zlib_ok = 1;
#else
static int ssld_zlib_ok = 0;
#endif
=======
static bool ssld_ssl_ok;
static int certfp_method = RB_SSL_CERTFP_METH_CERT_SHA1;
>>>>>>> .merge_file_Ch5lvI
static conn_t *
@ -164,6 +175,18 @@ free_conn(conn_t * conn)
{
rb_free_rawbuffer(conn->modbuf_out);
rb_free_rawbuffer(conn->plainbuf_out);
<<<<<<< .merge_file_7dGMbH
#ifdef HAVE_LIBZ
if(IsZip(conn))
{
zlib_stream_t *stream = conn->stream;
inflateEnd(&stream->instream);
deflateEnd(&stream->outstream);
rb_free(stream);
}
#endif
=======
>>>>>>> .merge_file_Ch5lvI
rb_free(conn);
}
@ -565,6 +588,8 @@ ssl_send_certfp(conn_t *conn)
uint32_to_buf(&buf[5], certfp_method);
uint32_to_buf(&buf[9], len);
mod_cmd_write_queue(conn->ctl, buf, 13 + len);
<<<<<<< .merge_file_7dGMbH
=======
}
static void
@ -575,6 +600,7 @@ ssl_send_open(conn_t *conn)
buf[0] = 'O';
uint32_to_buf(&buf[1], conn->id);
mod_cmd_write_queue(conn->ctl, buf, 5);
>>>>>>> .merge_file_Ch5lvI
}
static void
@ -586,7 +612,10 @@ ssl_process_accept_cb(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen
{
ssl_send_cipher(conn);
ssl_send_certfp(conn);
<<<<<<< .merge_file_7dGMbH
=======
ssl_send_open(conn);
>>>>>>> .merge_file_Ch5lvI
conn_mod_read_cb(conn->mod_fd, conn);
conn_plain_read_cb(conn->plain_fd, conn);
return;
@ -605,7 +634,10 @@ ssl_process_connect_cb(rb_fde_t *F, int status, void *data)
{
ssl_send_cipher(conn);
ssl_send_certfp(conn);
<<<<<<< .merge_file_7dGMbH
=======
ssl_send_open(conn);
>>>>>>> .merge_file_Ch5lvI
conn_mod_read_cb(conn->mod_fd, conn);
conn_plain_read_cb(conn->plain_fd, conn);
}
@ -692,11 +724,17 @@ process_stats(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
if(conn == NULL)
return;
<<<<<<< .merge_file_7dGMbH
rb_snprintf(outstat, sizeof(outstat), "S %s %llu %llu %llu %llu", odata,
(unsigned long long) conn->plain_out, (unsigned long long) conn->mod_in,
(unsigned long long) conn->plain_in, (unsigned long long) conn->mod_out);
=======
snprintf(outstat, sizeof(outstat), "S %s %llu %llu %llu %llu", odata,
(unsigned long long)conn->plain_out,
(unsigned long long)conn->mod_in,
(unsigned long long)conn->plain_in,
(unsigned long long)conn->mod_out);
>>>>>>> .merge_file_Ch5lvI
conn->plain_out = 0;
conn->plain_in = 0;
conn->mod_in = 0;
@ -705,10 +743,109 @@ process_stats(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
}
static void
<<<<<<< .merge_file_7dGMbH
change_connid(mod_ctl_t *ctl, mod_ctl_buf_t *ctlb)
{
uint32_t id = buf_to_uint32(&ctlb->buf[1]);
uint32_t newid = buf_to_uint32(&ctlb->buf[5]);
conn_t *conn = conn_find_by_id(id);
lrb_assert(conn != NULL);
if(conn == NULL)
{
uint8_t buf[256];
int len;
buf[0] = 'D';
uint32_to_buf(&buf[1], newid);
sprintf((char *) &buf[5], "connid %d does not exist", id);
len = (strlen((char *) &buf[5]) + 1) + 5;
mod_cmd_write_queue(ctl, buf, len);
return;
}
rb_dlinkDelete(&conn->node, connid_hash(conn->id));
SetZipSSL(conn);
conn->id = newid;
}
#ifdef HAVE_LIBZ
static void
zlib_process(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
{
uint8_t level;
size_t recvqlen;
size_t hdr = (sizeof(uint8_t) * 2) + sizeof(uint32_t);
void *recvq_start;
z_stream *instream, *outstream;
conn_t *conn;
uint32_t id;
conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
if(rb_get_type(conn->mod_fd) == RB_FD_UNKNOWN)
rb_set_type(conn->mod_fd, RB_FD_SOCKET);
if(rb_get_type(conn->plain_fd) == RB_FD_UNKNOWN)
rb_set_type(conn->plain_fd, RB_FD_SOCKET);
id = buf_to_uint32(&ctlb->buf[1]);
conn_add_id_hash(conn, id);
level = (uint8_t)ctlb->buf[5];
recvqlen = ctlb->buflen - hdr;
recvq_start = &ctlb->buf[6];
SetZip(conn);
conn->stream = rb_malloc(sizeof(zlib_stream_t));
instream = &((zlib_stream_t *) conn->stream)->instream;
outstream = &((zlib_stream_t *) conn->stream)->outstream;
instream->total_in = 0;
instream->total_out = 0;
instream->zalloc = (alloc_func) ssld_alloc;
instream->zfree = (free_func) ssld_free;
instream->data_type = Z_ASCII;
inflateInit(&((zlib_stream_t *) conn->stream)->instream);
outstream->total_in = 0;
outstream->total_out = 0;
outstream->zalloc = (alloc_func) ssld_alloc;
outstream->zfree = (free_func) ssld_free;
outstream->data_type = Z_ASCII;
if(level > 9)
level = (uint8_t) Z_DEFAULT_COMPRESSION;
deflateInit(&((zlib_stream_t *) conn->stream)->outstream, level);
if(recvqlen > 0)
common_zlib_inflate(conn, recvq_start, recvqlen);
conn_mod_read_cb(conn->mod_fd, conn);
conn_plain_read_cb(conn->plain_fd, conn);
return;
}
#endif
static void
init_prng(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
{
char *path;
prng_seed_t seed_type;
seed_type = (prng_seed_t) ctl_buf->buf[1];
path = (char *) &ctl_buf->buf[2];
rb_init_prng(path, seed_type);
}
static void
=======
>>>>>>> .merge_file_Ch5lvI
ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
{
char *buf;
char *cert, *key, *dhparam, *cipher_list;
char *cert, *key, *dhparam, *cipher_list, *hostname;
buf = (char *) &ctl_buf->buf[2];
cert = buf;
@ -718,6 +855,11 @@ ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
dhparam = buf;
buf += strlen(dhparam) + 1;
cipher_list = buf;
<<<<<<< .merge_file_7dGMbH
buf += strlen(cipher_list) + 1;
hostname = buf;
=======
>>>>>>> .merge_file_Ch5lvI
if(strlen(key) == 0)
key = cert;
if(strlen(dhparam) == 0)
@ -725,7 +867,15 @@ ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
if(strlen(cipher_list) == 0)
cipher_list = NULL;
if(!rb_setup_ssl_server(cert, key, dhparam, cipher_list))
int ret;
if(strlen(hostname) == 0) {
ret = rb_setup_ssl_server(cert, key, dhparam, cipher_list, NULL);
} else {
ret = rb_setup_ssl_server(cert, key, dhparam, cipher_list, hostname);
return;
}
if(!ret)
{
const char *invalid = "I";
mod_cmd_write_queue(ctl, invalid, strlen(invalid));
@ -733,6 +883,24 @@ ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
}
}
static void
ssl_remove_ssl_vhost(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
{
char *buf;
char *hostname;
buf = (char *) &ctl_buf->buf[2];
hostname = buf;
if(!rb_remove_ssl_vserver(hostname))
{
const char *invalid = "I";
mod_cmd_write_queue(ctl, invalid, strlen(invalid));
return;
}
}
static void
send_nossl_support(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
{
@ -845,6 +1013,22 @@ mod_process_cmd_recv(mod_ctl_t * ctl)
ssl_new_keys(ctl, ctl_buf);
break;
}
<<<<<<< .merge_file_7dGMbH
case 'D':
{
if(!ssld_ssl_ok)
{
send_nossl_support(ctl, ctl_buf);
break;
}
ssl_remove_ssl_vhost(ctl, ctl_buf);
break;
}
case 'I':
init_prng(ctl, ctl_buf);
break;
=======
>>>>>>> .merge_file_Ch5lvI
case 'S':
{
process_stats(ctl, ctl_buf);
@ -956,7 +1140,11 @@ int
main(int argc, char **argv)
{
const char *s_ctlfd, *s_pipe, *s_pid;
<<<<<<< .merge_file_7dGMbH
int ctlfd, pipefd, maxfd;
=======
int ctlfd, pipefd, maxfd, x;
>>>>>>> .merge_file_Ch5lvI
maxfd = maxconn();
s_ctlfd = getenv("CTL_FD");
@ -976,6 +1164,12 @@ main(int argc, char **argv)
pipefd = atoi(s_pipe);
ppid = atoi(s_pid);
<<<<<<< .merge_file_7dGMbH
#ifndef _WIN32
int x;
=======
>>>>>>> .merge_file_Ch5lvI
for(x = 3; x < maxfd; x++)
{
if(x != ctlfd && x != pipefd)
@ -995,11 +1189,18 @@ main(int argc, char **argv)
if(x > 2)
close(x);
}
<<<<<<< .merge_file_7dGMbH
#endif
=======
>>>>>>> .merge_file_Ch5lvI
setup_signals();
rb_lib_init(NULL, NULL, NULL, 0, maxfd, 1024, 4096);
rb_init_rawbuffers(1024);
<<<<<<< .merge_file_7dGMbH
=======
rb_init_prng(NULL, RB_PRNG_DEFAULT);
>>>>>>> .merge_file_Ch5lvI
ssld_ssl_ok = rb_supports_ssl();
mod_ctl = rb_malloc(sizeof(mod_ctl_t));
mod_ctl->F = rb_open(ctlfd, RB_FD_SOCKET, "ircd control socket");
@ -1010,8 +1211,12 @@ main(int argc, char **argv)
rb_event_add("check_handshake_flood", check_handshake_flood, NULL, 10);
read_pipe_ctl(mod_ctl->F_pipe, NULL);
mod_read_ctl(mod_ctl->F, mod_ctl);
<<<<<<< .merge_file_7dGMbH
if(!ssld_zlib_ok && !ssld_ssl_ok)
=======
send_version(mod_ctl);
if(!ssld_ssl_ok)
>>>>>>> .merge_file_Ch5lvI
{
/* this is really useless... */
send_i_am_useless(mod_ctl);
@ -1020,11 +1225,16 @@ main(int argc, char **argv)
exit(1);
}
<<<<<<< .merge_file_7dGMbH
if(!ssld_zlib_ok)
send_nozlib_support(mod_ctl, NULL);
=======
send_nozlib_support(mod_ctl, NULL);
>>>>>>> .merge_file_Ch5lvI
if(!ssld_ssl_ok)
send_nossl_support(mod_ctl, NULL);
rb_lib_loop(0);
return 0;
/* UNREACHABLE */
}

View file

@ -96,11 +96,9 @@ main(int argc, char *argv[])
case 'h':
full_usage();
/* NOT REACHED */
break;
case '?':
brief_usage();
/* NOT REACHED */
break;
default:
printf("Invalid Option: -%c\n", c);
break;
@ -371,7 +369,7 @@ generate_random_salt(char *salt, int length)
return (salt);
}
void
static void
full_usage()
{
printf("mkpasswd [-m|-b|-x|-y] [-l saltlength] [-r rounds] [-s salt] [-p plaintext]\n");
@ -389,7 +387,7 @@ full_usage()
exit(0);
}
void
static void
brief_usage()
{
printf("mkpasswd - password hash generator\n");